/** * Replace all line endings with line endings customized for the current OS * * See validateXml() source for the complete list of allowed fields * @param \Pyrus\PackageInterface * @param resource open file pointer, set to the beginning of the file * @param string the eventual final file location (informational only) * @return string */ function startSession($fp, $dest) { $contents = stream_get_contents($fp); \Pyrus\Logger::log(3, "replacing all line endings with \\n in {$dest}"); $contents = preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents); rewind($fp); ftruncate($fp, 0); fwrite($fp, $contents); return true; }
function __construct($debugging = false) { if (!$debugging) { set_exception_handler(array($this, 'exceptionHandler')); } \Pyrus\Logger::attach($this); if (!isset(static::$commandParser)) { $schemapath = \Pyrus\Main::getDataPath() . '/customcommand-2.0.xsd'; $defaultcommands = \Pyrus\Main::getDataPath() . '/built-in-commands.xml'; // Check for a local-developer-commands.xml file $localcommands = false; if (file_exists(\Pyrus\Main::getDataPath() . '/local-developer-commands.xml')) { $localcommands = realpath(\Pyrus\Main::getDataPath() . '/local-developer-commands.xml'); } $parser = new \Pyrus\XMLParser(); $commands = $parser->parse($defaultcommands, $schemapath); $commands = $commands['commands']['command']; if ($localcommands) { // Add in local commands $localcommands = $parser->parse($localcommands, $schemapath); $commands = array_merge($commands, $localcommands['commands']['command']); } if ('@PACKAGE_VERSION@' == '@' . 'PACKAGE_VERSION@') { $version = '2.0.0a4'; // running from git } else { $version = '@PACKAGE_VERSION@'; } static::$commandParser = new \Pyrus\ScriptFrontend(array('version' => $version, 'description' => 'Pyrus, the PHP manager', 'name' => 'php ' . basename($_SERVER['argv'][0]))); // set up our custom renderer for help options static::$commandParser->accept(new \Pyrus\ScriptFrontend\Renderer(static::$commandParser)); // set up command-less options and argument static::$commandParser->addOption('verbose', array('short_name' => '-v', 'long_name' => '--verbose', 'action' => 'Counter', 'description' => 'increase verbosity')); static::$commandParser->addOption('paranoid', array('short_name' => '-p', 'long_name' => '--paranoid', 'action' => 'Counter', 'description' => 'set or increase paranoia level')); \Pyrus\PluginRegistry::registerFrontend($this); \Pyrus\PluginRegistry::addCommand($commands); } $term = getenv('TERM'); if (function_exists('posix_isatty') && !posix_isatty(1)) { // output is being redirected to a file or through a pipe } elseif ($term) { if (preg_match('/^(xterm|vt220|linux)/', $term)) { $this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109); $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109); } elseif (preg_match('/^vt100/', $term)) { $this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0); } } }
function getRelativeLocation(\Pyrus\PackageFileInterface $pkg, \Pyrus\PackageFile\v2Iterator\FileTag $file, $retDir = false) { if ($this->md5 === null) { return parent::getRelativeLocation($pkg, $file, $retDir); } $info = parent::getRelativeLocation($pkg, $file, $retDir); $path = \Pyrus\Config::current()->cfg_dir . DIRECTORY_SEPARATOR; if ($retDir) { $filepath = $info[1]; } else { $filepath = $info; } if (@file_exists($path . $filepath)) { // configuration has already been installed, check for modifications // made by the user $md5 = md5_file($path . $filepath); $newmd5 = $pkg->files[$file->packagedname]['attribs']; if (!isset($newmd5['md5sum'])) { $newmd5 = md5_file($pkg->getFilePath($file->packagedname)); } else { $newmd5 = $newmd5['md5sum']; } // first check to see if the user modified the file // next check to see if the config file changed from the last installed version // if both tests are satisfied, install the new file under another name and display a warning if ($md5 !== $this->md5 && $md5 !== $newmd5) { // configuration has been modified, so save our version as // configfile.new-version $old = $filepath; $filepath .= '.new-' . $pkg->version['release']; \Pyrus\Logger::log(0, "WARNING: configuration file {$old} is being installed as {$filepath}, " . "you should manually merge in changes to the existing configuration file"); } } if ($retDir) { $info[1] = $filepath; } else { $info = $filepath; } return $info; }
/** * Extract configuration from system + user configuration files * * Configuration is stored in XML format, in two locations. * * The system configuration contains all of the important directory * configuration variables like data_dir, and the location of php.ini and * the php executable php.exe or php. This configuration is tightly bound * to the repository, and cannot be moved. As such, php_dir is auto-defined * as dirname(/path/to/pear/.config), or /path/to/pear. * * Only 1 user configuration file is allowed, and contains user-specific * settings, including the locations where to download package releases * and where to cache files downloaded from the internet. If false is passed * in, \Pyrus\Config will attempt to guess at the config file location as * documented in the class docblock {@link \Pyrus\Config}. * @param string $pearDirectory * @param string|false $userfile */ protected function loadConfigFile($pearDirectory, $snapshot = null) { if (!file_exists($pearDirectory . DIRECTORY_SEPARATOR . '.configsnapshots')) { // no configurations - this may be an extracted-from-disk install. // in this case, we use the defaults, as this is intended return; } $snapshotdir = $pearDirectory . DIRECTORY_SEPARATOR . '.configsnapshots'; $snapshotfile = $snapshotdir . DIRECTORY_SEPARATOR . $snapshot; if (!file_exists($snapshotfile)) { if (preg_match('/^\\d{4}\\-\\d{2}\\-\\d{2} \\d{2}[-:]\\d{2}[-:]\\d{2}$/', $snapshot)) { // passed a date, locate a matching snapshot if (!strpos($snapshot, ':')) { // change YYYY-MM-DD HH-MM-SS to YYYY-MM-DD HH:MM:SS $snapshot = explode(' ', $snapshot); $snapshot[1] = str_replace('-', ':', $snapshot[1]); $snapshot = implode(' ', $snapshot); } $us = new \DateTime($snapshot); $dir = new \RegexIterator(new \RecursiveDirectoryIterator($snapshotdir), '/configsnapshot\\-\\d{4}\\-\\d{2}\\-\\d{2} \\d{2}\\-\\d{2}\\-\\d{2}.xml/', \RegexIterator::MATCH, \RegexIterator::USE_KEY); foreach ($dir as $match) { $matches[] = $match; } usort($matches, array($this, 'datediff')); unset($match); $found = false; foreach ($matches as $match) { $match = substr($match->getFileName(), strlen('configsnapshot-')); $match = str_replace('.xml', '', $match); $match = explode(' ', $match); $match[1] = str_replace('-', ':', $match[1]); $match = implode(' ', $match); $testdate = new \DateTime($match); if ($testdate > $us) { continue; } if ($testdate == $us) { // found a snapshot match $found = true; break; } if ($us > $testdate) { // we fall between these two snapshots, so use this one $found = true; break; } } if (!$found) { // no config snapshots return parent::loadConfigFile($pearDirectory); } $snapshotfile = $snapshotdir . DIRECTORY_SEPARATOR . 'configsnapshot-' . str_replace(':', '-', $match) . '.xml'; } } \Pyrus\Logger::log(5, 'Loading configuration snapshot ' . $snapshotfile . ' for ' . $pearDirectory); try { $this->helperLoadConfigFile($pearDirectory, $snapshotfile, 'snapshot'); } catch (\Exception $e) { // no config snapshots found, so simply load the existing config return parent::loadConfigFile($pearDirectory); } }
/** * * @param string|array pass in an array of format * array( * 'package' => 'pname', * ['channel' => 'channame',] * ['version' => 'version',] * ['state' => 'state',]) * or a string of format [channame/]pname[-version|-state] */ protected function fromString($param) { try { $pname = Config::parsePackageName($param, true); } catch (\Pyrus\ChannelRegistry\ParseException $e) { if ($e->why !== 'channel') { throw new Exception('invalid package name/package file "' . $param . '"', $e); } if (Config::current()->auto_discover) { try { try { $chan = new \Pyrus\Channel(new \Pyrus\ChannelFile('https://' . $e->params['channel'] . '/channel.xml')); } catch (\Exception $e) { $chan = new \Pyrus\Channel(new \Pyrus\ChannelFile('http://' . $e->params['channel'] . '/channel.xml')); } } catch (\Exception $e) { throw new Exception('Cannot auto-discover channel ' . $e->params['channel'], $e); } Config::current()->channelregistry[] = $chan; try { Config::parsePackageName($param, Config::current()->default_channel); } catch (\Exception $e) { throw new Exception('invalid package name/package file "' . $param . '"', $e); } } else { \Pyrus\Logger::log(0, 'Channel "' . $param['channel'] . '" is not initialized, use ' . '"pyrus channel-discover ' . $param['channel'] . '" to initialize' . 'or pyrus set auto_discover 1'); } } $this->parsedname = $pname; $this->explicitVersion = isset($pname['version']) ? $pname['version'] : false; $this->explicitState = isset($pname['state']) ? $pname['state'] : false; $this->explicitGroup = isset($pname['group']) ? true : false; $reg = Config::current()->registry; $version = $reg->info($pname['package'], $pname['channel'], 'version'); $stability = $reg->info($pname['package'], $pname['channel'], 'state'); if (!isset(\Pyrus\Main::$options['force']) && !isset(\Pyrus\Main::$options['downloadonly']) && $version && $this->explicitVersion && !isset($pname['group'])) { if (version_compare($version, $pname['version'], '>=')) { throw new InstalledException(Config::parsedPackageNameToString($pname, true) . ' is already installed and is newer than detected ' . 'release version ' . $pname['version']); } } if (!$this->explicitVersion && $stability) { // if installed, use stability of the installed package, // but only if it is less restrictive than preferred_state. // This allows automatic upgrade to a newer beta for 1 package // even if preferred_state is stable, for instance. $states = \Pyrus\Installer::betterStates(Config::current()->preferred_state); $newstates = \Pyrus\Installer::betterStates($stability); if (count($newstates) > count($states)) { $this->explicitState = $stability; } } $this->type = 'abstract'; $ret = $this->getRemotePackage($pname); if ($this->explicitVersion) { $ret->setExplicitVersion($this->explicitVersion); $ret->version['release'] = $this->explicitVersion; } if ($this->explicitState) { $ret->setExplicitState($this->explicitState); } return $ret; }
/** * validate a downloaded package against installed packages * * @param $pkg downloaded package package.xml object * @param array $params full list of packages to install * @return bool */ function validateDownloadedPackage(\Pyrus\PackageFileInterface $pkg, $params = array()) { $me = $pkg->channel . '/' . $pkg->name; $reg = Config::current()->registry; $deppackages = $reg->getDependentPackages($pkg); $fail = false; if ($deppackages) { $actual = array(); // first, remove packages that will be installed foreach ($deppackages as $package) { foreach ($params as $packd) { if (strtolower($packd->name) == strtolower($package->name) && $packd->channel == $package->channel) { \Pyrus\Logger::log(3, 'skipping installed package check of "' . Config::parsedPackageNameToString(array('channel' => $package->channel, 'package' => $package->name), true) . '", version "' . $packd->version['release'] . '" will be ' . 'downloaded and installed'); continue 2; } } $actual[] = $package; } foreach ($actual as $package) { $checker = new \Pyrus\Dependency\Validator(array('channel' => $package->channel, 'package' => $package->name), $this->_state, $this->errs); foreach ($params as $packd) { $deps = $package->dependencies['required']->package; if (isset($deps[$me])) { $ret = $checker->_validatePackageDownload($deps[$me], array($pkg, $package)); } $deps = $package->dependencies['required']->subpackage; if (isset($deps[$me])) { $ret = $checker->_validatePackageDownload($deps[$me], array($pkg)); } $deps = $package->dependencies['optional']->package; if (isset($deps[$me])) { $ret = $checker->_validatePackageDownload($deps[$me], array($pkg, $package)); } $deps = $package->dependencies['optional']->subpackage; if (isset($deps[$me])) { $ret = $checker->_validatePackageDownload($deps[$me], array($pkg)); } } } } if (count($this->errs->E_ERROR)) { return $this->raiseError('%s cannot be installed, conflicts with installed packages'); } return true; }
function _analyzeBundledPackages() { if (!$this->_pf->type == 'bundle') { return false; } if (!$this->_pf->packagefile) { return false; } $dir_prefix = $this->_pf->filepath; foreach ($this->_pf->bundledpackage as $package) { if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) { $this->errors->E_ERROR[] = new \Pyrus\PackageFile\Exception('File "' . $dir_prefix . DIRECTORY_SEPARATOR . $package . '" in package.xml does not exist'); continue; } \Pyrus\Logger::log(1, "Analyzing bundled package {$package}"); try { $ret = new \Pyrus\Package\Tar($dir_prefix . DIRECTORY_SEPARATOR . $package); } catch (\Exception $e) { $this->errors->E_ERROR[] = new \Pyrus\PackageFile\Exception('File "' . $dir_prefix . DIRECTORY_SEPARATOR . $package . '" in package.xml is not valid', $e); continue; } } return true; }
/** * Figure out which version is best, and use this, or error out if none work * @param \Pyrus\PackageFile\v2\Dependencies\Package $compositeDep * the composite of all dependencies on this package, as calculated * by {@link \Pyrus\Package\Dependency::getCompositeDependency()} */ function figureOutBestVersion(\Pyrus\PackageFile\v2\Dependencies\Package $compositeDep, $versions = null, \Pyrus\PackageFile\v2\Dependencies\Package $compositeConflictingDep = null) { // set up release list if not done yet $this->rewind(); $ok = \Pyrus\Installer::betterStates($this->minimumStability, true); $v = $this->explicitVersion; $n = $this->channel . '/' . $this->name; $failIfExplicit = function ($versioninfo) use($v, $n) { if ($v && $versioninfo['v'] == $v) { throw new Exception($n . ' Cannot be installed, it does not satisfy ' . 'all dependencies'); } }; foreach ($this->releaseList as $versioninfo) { if (isset(\Pyrus\Main::$options['force'])) { // found one if ($this->versionSet && $versioninfo['v'] != $this->version['release']) { // inform the installer we need to reset dependencies $this->version['release'] = $versioninfo['v']; return true; } $this->version['release'] = $versioninfo['v']; return; } if ($versions && !in_array($versioninfo['v'], $versions)) { continue; } if (!isset(\Pyrus\Main::$options['force']) && isset($versioninfo['m'])) { // minimum PHP version required if (version_compare($versioninfo['m'], $this->getPHPVersion(), '>')) { $failIfExplicit($versioninfo); continue; } } if (!in_array($versioninfo['s'], $ok) && !isset(\Pyrus\Main::$options['force'])) { // release is not stable enough continue; } if ($this->explicitVersion && $versioninfo['v'] != $this->explicitVersion) { continue; } if (!$compositeDep->satisfied($versioninfo['v'])) { $failIfExplicit($versioninfo); continue; } if ($compositeConflictingDep && !$compositeConflictingDep->satisfied($versioninfo['v'])) { $failIfExplicit($versioninfo); continue; } $paranoia = \Pyrus\Main::getParanoiaLevel(); if (!$this->explicitVersion && $paranoia > 1) { // first, we check to see if we are upgrading if (isset(\Pyrus\Main::$options['upgrade'])) { // now we check to see if we are installed if (isset(Config::current()->registry->package[$n])) { $installed = Config::current()->registry->info($this->name, $this->channel, 'apiversion'); $installed = explode('.', $installed); if (count($installed) == 2) { $installed[] = '0'; } if (count($installed) == 1) { $installed[] = '0'; $installed[] = '0'; } if (isset($this->parent->protocols->rest['REST1.3'])) { $api = $this->rest->retrieveCacheFirst($this->parent->protocols->rest['REST1.3']->baseurl . 'r/' . strtolower($this->name) . '/v2.' . $versioninfo['v'] . '.xml', false, false, 'text/xml'); } else { throw new Exception('Channel ' . $this->channel . ' does not support ' . 'a paranoia greater than 1'); } $api = explode('.', $api['a']); if (count($api) == 2) { $api[] = '0'; } if (count($api) == 1) { $api[] = '0'; $api[] = '0'; } if ($paranoia > 4) { $paranoia = 4; } switch ($paranoia) { case 4: if ($installed != $api) { Logger::log(0, 'Skipping ' . $this->channel . '/' . $this->name . ' version ' . $versioninfo['v'] . ', API has changed'); continue 2; } break; case 3: if ($installed[0] == $api[0] && $installed[1] != $api[1]) { Logger::log(0, 'Skipping ' . $this->channel . '/' . $this->name . ' version ' . $versioninfo['v'] . ', API has added' . ' new features'); continue 2; } // break intentionally omitted // break intentionally omitted case 2: if ($installed[0] != $api[0]) { Logger::log(0, 'Skipping ' . $this->channel . '/' . $this->name . ' version ' . $versioninfo['v'] . ', API breaks' . ' backwards compatibility'); continue 2; } break; } } } } // found one if ($this->versionSet && $versioninfo['v'] != $this->version['release']) { // inform the installer we need to reset dependencies $this->version['release'] = $versioninfo['v']; return true; } $this->version['release'] = $versioninfo['v']; return; } throw new Exception('Unable to locate a package release for ' . $this->channel . '/' . $this->name . ' that can satisfy all dependencies'); }
function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings) { $info = ''; $warn = false; if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) { $this->save_text($temp_skipif, $section_text['SKIPIF']); $output = $this->system_with_timeout("{$this->_php}{$ini_settings} -f \"{$temp_skipif}\""); $output = $output[1]; $loutput = ltrim($output); unlink($temp_skipif); if (!strncasecmp('skip', $loutput, 4)) { $skipreason = "SKIP {$tested}"; if (preg_match('/^\\s*skip\\s*(.+)\\s*/i', $output, $m)) { $skipreason .= '(reason: ' . $m[1] . ')'; } if (!isset($this->_options['quiet'])) { \Pyrus\Logger::log(0, $skipreason); } if (isset($this->_options['tapoutput'])) { return array('ok', ' # skip ' . $reason); } return 'SKIPPED'; } if (!strncasecmp('info', $loutput, 4) && preg_match('/^\\s*info\\s*(.+)\\s*/i', $output, $m)) { $info = " (info: {$m['1']})"; } if (!strncasecmp('warn', $loutput, 4) && preg_match('/^\\s*warn\\s*(.+)\\s*/i', $output, $m)) { $warn = true; /* only if there is a reason */ $info = " (warn: {$m['1']})"; } } return array('warn' => $warn, 'info' => $info); }
public function listPackages($channel) { $dir = $this->_namePath($channel, ''); if (!@file_exists($dir)) { return array(); } $ret = array(); try { $parser = new \Pyrus\XMLParser(); foreach (new \DirectoryIterator($dir) as $file) { if ($file->isDot()) { continue; } try { foreach (new \DirectoryIterator($file->getPathName()) as $registries) { if ($registries->isDir()) { continue; } $a = $parser->parse($registries->getPathName()); $ret[] = $a['package']['name']; } } catch (\Exception $e) { \Pyrus\Logger::log(0, 'Warning: corrupted XML registry entry: ' . $file->getPathName() . ': ' . $e); } } } catch (\Exception $e) { throw new Exception('Could not open channel directory for ' . 'channel ' . $channel, $e); } return $ret; }
final function packageTimeValidate(\Pyrus\Package $package, array $fileXml) { if (!isset($this->info['validationmethod'])) { return true; } if (!method_exists($this, $this->info['validationmethod'])) { \Pyrus\Logger::log(0, 'WARNING: custom role ' . $this->info['name'] . ' specifies non-existing validation method ' . $this->info['validationmethod']); return true; } return $this->{$this->info['validationmethod']}($package, $fileXml); }
/** * Unlike other tasks, the installed file name is passed in instead of the file contents, * because this task is handled post-installation * @param \Pyrus\PackageInterface * @param string path to the post-install script * @return bool false to skip this file */ function setupPostInstall() { $files = \Pyrus\Config::current()->registry->info($this->pkg->name, $this->pkg->channel, 'installedfiles'); foreach ($files as $path => $info) { if ($info['name'] == $this->_filename) { break; } } Logger::log(0, 'Including external post-installation script "' . $path . '" - any errors are in this script'); include $path; if (class_exists($this->scriptClass) === false) { throw new Exception('init of post-install script class "' . $this->scriptClass . '" failed'); } Logger::log(0, 'Inclusion succeeded'); $this->obj = new $this->scriptClass(); Logger::log(1, 'running post-install script "' . $this->scriptClass . '->init()"'); try { $this->obj->init2($this->pkg, $this->lastVersion); } catch (\Exception $e) { throw new Exception('init of post-install script "' . $this->scriptClass . '->init()" failed', $e); } Logger::log(0, 'init succeeded'); return true; }
function _install($info, $replace) { $database = static::getRegistry($this->_path); if (!$replace) { $info = $info->toRaw(); // this avoids potential exception on setting date/time // which can happen if $info is a registry package that // has been uninstalled $info->date = date('Y-m-d'); $info->time = date('H:i:s'); } $licloc = $info->license; $licuri = $info->license['uri']; $licpath = $info->license['path']; $sql = ' INSERT INTO packages (lcname, name, channel, version, apiversion, summary, packagetype, description, stability, apistability, releasedate, releasetime, license, licenseuri, licensepath, releasenotes, lastinstalledversion, installedwithpear, installtimeconfig) VALUES(:lcname, :name, :channel, :versionrelease, :versionapi, :summary, :packagetype, :description, :stabilityrelease, :stabilityapi, :date, :time, :license, :licenseuri, :licensepath, :notes, :lastinstalledv, :lastinstalledp, :lastinstalltime )'; $stmt = $database->prepare($sql); $n = $info->name; $c = $info->channel; $stmt->bindValue(':lcname', strtolower($n)); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':versionrelease', $info->version['release']); $stmt->bindValue(':versionapi', $info->version['api']); $stmt->bindValue(':summary', $info->summary); $stmt->bindValue(':description', $info->description); $stmt->bindValue(':packagetype', $info->type); $stmt->bindValue(':stabilityrelease', $info->stability['release']); $stmt->bindValue(':stabilityapi', $info->stability['api']); $stmt->bindValue(':date', $info->date); $stmt->bindValue(':time', $info->time); $stmt->bindValue(':license', $info->license['name']); $stmt->bindValue(':licenseuri', $licuri, $licuri === null ? SQLITE3_NULL : SQLITE3_TEXT); $stmt->bindValue(':licensepath', $licpath, $licpath === null ? SQLITE3_NULL : SQLITE3_TEXT); $stmt->bindValue(':notes', $info->notes); $stmt->bindValue(':lastinstalledv', null, SQLITE3_NULL); if ('@PACKAGE_VERSION@' == '@' . 'PACKAGE_VERSION@') { $v = '2.0.0a1'; } else { $v = '@PACKAGE_VERSION@'; } $stmt->bindValue(':lastinstalledp', $v); $stmt->bindValue(':lastinstalltime', Config::configSnapshot()); $stmt->execute(); $stmt->close(); $n = strtolower($n); $sql = ' INSERT INTO maintainers (packages_name, packages_channel, role, name, user, email, active) VALUES (:name, :channel, :role, :m_name, :m_user, :m_email, :m_active)'; $stmt = $database->prepare($sql); foreach ($info->allmaintainers as $role => $maintainers) { foreach ($maintainers as $maintainer) { $stmt->clear(); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':role', $role); $stmt->bindValue(':m_name', $maintainer->name); $stmt->bindValue(':m_user', $maintainer->user); $stmt->bindValue(':m_email', $maintainer->email); $stmt->bindValue(':m_active', $maintainer->active); @$stmt->execute(); } } $stmt->close(); $curconfig = Config::current(); $roles = array(); $sql = ' INSERT INTO configureoptions (packages_name, packages_channel, name, prompt, defaultValue) VALUES(:name, :channel, :oname, :prompt, :default)'; \Pyrus\Logger::log(4, 'Preparing SQL: ' . $sql); $stmt = $database->prepare($sql); $stmt->bindValue(':name', $n); \Pyrus\Logger::log(4, 'Binding SQL parameter :name: ' . var_export($n, true)); $stmt->bindValue(':channel', $c); \Pyrus\Logger::log(4, 'Binding SQL parameter :channel: ' . var_export($c, true)); foreach ($info->installrelease->configureoption as $option) { $stmt->bindValue(':oname', $option->name); \Pyrus\Logger::log(4, 'Binding SQL parameter :oname: ' . var_export($option->name, true)); $stmt->bindValue(':prompt', $option->prompt); \Pyrus\Logger::log(4, 'Binding SQL parameter :prompt: ' . var_export($option->prompt, true)); if ($option->default === null) { $stmt->bindValue(':default', null, SQLITE3_NULL); \Pyrus\Logger::log(4, 'Binding SQL parameter :default: NULL'); } else { $stmt->bindValue(':default', $option->default); \Pyrus\Logger::log(4, 'Binding SQL parameter :default: ' . var_export($option->default, true)); } $stmt->execute(); } $sql = ' INSERT INTO files (packages_name, packages_channel, packagepath, configpath, role, relativepath, origpath, baseinstalldir, tasks, md5sum) VALUES(:name, :channel, :path, :configpath, :role, :relativepath, :origpath, :baseinstall, :tasks, :md5)'; $stmt = $database->prepare($sql); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); foreach (Role::getValidRoles($info->getPackageType()) as $role) { // set up a list of file role => configuration variable // for storing in the registry $roles[$role] = Role::factory($info->getPackageType(), $role); } foreach ($info->installcontents as $file) { $relativepath = $roles[$file->role]->getRelativeLocation($info, $file); if (!$relativepath) { continue; } $p = $curconfig->{$roles[$file->role]->getLocationConfig()}; $stmt->bindValue(':relativepath', $relativepath); $stmt->bindValue(':configpath', $p); $stmt->bindValue(':path', $p . DIRECTORY_SEPARATOR . $relativepath); $stmt->bindValue(':origpath', $file->packagedname); $stmt->bindValue(':role', $file->role); $stmt->bindValue(':baseinstall', $file->baseinstalldir); $stmt->bindValue(':tasks', serialize($file->tasks)); if ($file->md5sum) { $stmt->bindValue(':md5', $file->md5sum); } else { // clearly the person installing doesn't care about this, so // use a dummy value $stmt->bindValue(':md5', md5('')); } $stmt->execute(); } $stmt->close(); $sql = ' INSERT INTO baseinstalldirs (packages_name, packages_channel, dirname, baseinstall) VALUES(:name, :channel, :dirname, :baseinstall)'; $stmt = $database->prepare($sql); foreach ($info->getBaseInstallDirs() as $dir => $base) { $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':dirname', $dir); $stmt->bindValue(':baseinstall', $base); $stmt->execute(); } $stmt->close(); if (count($info->compatible)) { $sql = ' INSERT INTO compatible_releases (packages_name, packages_channel, compat_package, compat_channel, min, max) VALUES (:name, :channel, :cname, :cchannel, :min, :max)'; $stmt = $database->prepare($sql); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $sql2 = ' INSERT INTO compatible_releases_exclude (packages_name, packages_channel, compat_package, compat_channel, exclude) VALUES (:name, :channel, :cname, :cchannel, :exclude)'; $stmt2 = $database->prepare($sql2); $stmt2->bindValue(':name', $n); $stmt2->bindValue(':channel', $c); foreach ($info->compatible as $compatible) { $stmt->bindValue(':cname', $compatible->name); $stmt->bindValue(':cchannel', $compatible->channel); $stmt->bindValue(':min', $compatible->min); $stmt->bindValue(':max', $compatible->max); $stmt->execute(); if (isset($compatible->exclude)) { $stmt2->bindValue(':cname', $compatible->name); $stmt2->bindValue(':cchannel', $compatible->channel); foreach ($compatible->exclude as $exclude) { $stmt2->bindValue(':exclude', $exclude); $stmt2->execute(); } } } } $sql = ' INSERT INTO extension_dependencies (required, packages_name, packages_channel, extension, conflicts, min, max, recommended) VALUES (:required, :name, :channel, :extension, :conflicts, :min, :max, :recommended)'; $stmt = $database->prepare($sql); foreach (array('required', 'optional') as $required) { foreach ($info->dependencies[$required]->extension as $d) { // $d is a \Pyrus\PackageFile\v2\Dependencies\Package object $req = $required == 'required' ? 1 : 0; $stmt->bindValue(':required', $req, SQLITE3_INTEGER); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':extension', $d->name); $stmt->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt->bindValue(':min', $d->min); $stmt->bindValue(':max', $d->max); $stmt->bindValue(':recommended', $d->recommended); $stmt->execute(); if (isset($d->exclude)) { $sql = ' INSERT INTO extension_dependencies_exclude (required, packages_name, packages_channel, extension, exclude, conflicts) VALUES(:required, :name, :channel, :extension, :exclude, :conflicts)'; $stmt1 = $database->prepare($sql); foreach ($d->exclude as $exclude) { $stmt1->clear(); $req = $required == 'required' ? 1 : 0; $stmt1->bindValue(':required', $req, SQLITE3_INTEGER); $stmt1->bindValue(':name', $n); $stmt1->bindValue(':channel', $c); $stmt1->bindValue(':extension', $d->name); $stmt1->bindValue(':exclude', $exclude); $stmt1->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt1->execute(); } $stmt1->close(); } } } $stmt->close(); $sql = ' INSERT INTO package_dependencies (required, packages_name, packages_channel, deppackage, depchannel, conflicts, min, max, recommended, is_subpackage, providesextension) VALUES (:required, :name, :channel, :dep_package, :dep_channel, :conflicts, :min, :max, :recommended, :sub, :ext)'; $stmt = $database->prepare($sql); $first = true; foreach (array('required', 'optional') as $required) { foreach (array('package', 'subpackage') as $package) { foreach ($info->dependencies[$required]->{$package} as $d) { // $d is a \Pyrus\PackageFile\v2\Dependencies\Package object $sub = $package == 'subpackage'; if (!$first) { $stmt->clear(); $first = false; } $req = $required == 'required' ? 1 : 0; $stmt->bindValue(':required', $req, SQLITE3_INTEGER); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':dep_package', $d->name); $stmt->bindValue(':dep_channel', $d->channel); $con = $d->conflicts; $stmt->bindValue(':conflicts', $con, SQLITE3_INTEGER); $stmt->bindValue(':min', $d->min); $stmt->bindValue(':max', $d->max); $stmt->bindValue(':recommended', $d->recommended); $stmt->bindValue(':sub', $sub); if ($d->providesextension) { $stmt->bindValue(':ext', $d->providesextension); } else { $stmt->bindValue(':ext', null, SQLITE3_NULL); } $stmt->execute(); if (isset($d->exclude)) { $sql = ' INSERT INTO package_dependencies_exclude (required, packages_name, packages_channel, deppackage, depchannel, exclude, conflicts, is_subpackage) VALUES(:required, :name, :channel, :dep_package, :dep_channel, :exclude, :conflicts, :sub)'; $stmt1 = $database->prepare($sql); foreach ($d->exclude as $exclude) { $stmt1->clear(); $req = $required == 'required' ? 1 : 0; $stmt1->bindValue(':required', $req, SQLITE3_INTEGER); $stmt1->bindValue(':name', $n); $stmt1->bindValue(':channel', $c); $stmt1->bindValue(':dep_package', $d->name); $stmt1->bindValue(':dep_channel', $d->channel); $stmt1->bindValue(':exclude', $exclude); $stmt1->bindValue(':sub', $sub); $con = $d->conflicts; $stmt1->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt1->execute(); } $stmt1->close(); } } } } $stmt->close(); $sql = ' INSERT INTO php_dependencies (packages_name, packages_channel, min, max) VALUES (:name, :channel, :min, :max)'; $max = $info->dependencies['required']->php->max; $stmt = $database->prepare($sql); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':min', $info->dependencies['required']->php->min); if ($max === null) { $stmt->bindValue(':max', $max, SQLITE3_NULL); } else { $stmt->bindValue(':max', $max); } $stmt->execute(); $stmt->close(); $sql = ' INSERT INTO php_dependencies_exclude (packages_name, packages_channel, exclude) VALUES (:name, :channel, :exclude)'; $stmt = $database->prepare($sql); if ($info->dependencies['required']->php->exclude) { foreach ($info->dependencies['required']->php->exclude as $exclude) { $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':exclude', $exclude); $stmt->execute(); } } $stmt->close(); $sql = ' INSERT INTO pearinstaller_dependencies (packages_name, packages_channel, min, max) VALUES (:name, :channel, :min, :max)'; $max = $info->dependencies['required']->pearinstaller->max; $stmt = $database->prepare($sql); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':min', $info->dependencies['required']->pearinstaller->min); if ($max === null) { $stmt->bindValue(':max', $max, SQLITE3_NULL); } else { $stmt->bindValue(':max', $max); } $stmt->execute(); $stmt->close(); $sql = ' INSERT INTO pearinstaller_dependencies_exclude (packages_name, packages_channel, exclude) VALUES (:name, :channel, :exclude)'; $stmt = $database->prepare($sql); if ($info->dependencies['required']->pearinstaller->exclude) { foreach ($info->dependencies['required']->pearinstaller->exclude as $exclude) { $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':exclude', $exclude); $stmt->execute(); } } $stmt->close(); if (isset($info->dependencies['required']->os)) { $sql = ' INSERT INTO os_dependencies (packages_name, packages_channel, osname, conflicts) VALUES (:name, :channel, :os, :conflicts)'; $stmt = $database->prepare($sql); foreach ($info->dependencies['required']->os as $dep) { $stmt->clear(); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':os', $dep->name); $stmt->bindValue(':conflicts', $dep->conflicts, SQLITE3_INTEGER); $stmt->execute(); } $stmt->close(); } if (isset($info->dependencies['required']->arch)) { $sql = ' INSERT INTO arch_dependencies (packages_name, packages_channel, pattern, conflicts) VALUES (:name, :channel, :arch, :conflicts)'; $stmt = $database->prepare($sql); foreach ($info->dependencies['required']->arch as $dep) { $stmt->clear(); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':arch', $dep->pattern); $stmt->bindValue(':conflicts', $dep->conflicts, SQLITE3_INTEGER); $stmt->execute(); } $stmt->close(); } foreach ($info->dependencies['group'] as $group) { $sql = ' INSERT INTO dep_groups (packages_name, packages_channel, groupname, grouphint) VALUES (:name, :channel, :groupname, :grouphint)'; $stmt = $database->prepare($sql); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':groupname', $group->name); $stmt->bindValue(':grouphint', $group->hint); $stmt->execute(); $stmt->close(); $sql = ' INSERT INTO extension_dependencies (required, packages_name, packages_channel, extension, conflicts, min, max, recommended, groupname) VALUES (0, :name, :channel, :extension, :conflicts, :min, :max, :recommended, :groupname)'; $stmt = $database->prepare($sql); foreach ($group->extension as $d) { // $d is a \Pyrus\PackageFile\v2\Dependencies\Package object $stmt->clear(); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':extension', $d->name); $stmt->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt->bindValue(':min', $d->min); $stmt->bindValue(':max', $d->max); $stmt->bindValue(':recommended', $d->recommended); $stmt->bindValue(':groupname', $group->name); $stmt->execute(); if (isset($d->exclude)) { $sql = ' INSERT INTO extension_dependencies_exclude (required, packages_name, packages_channel, extension, exclude, conflicts, groupname) VALUES(0, :name, :channel, :extension, :exclude, :conflicts, :groupname)'; $stmt1 = $database->prepare($sql); foreach ($d->exclude as $exclude) { $stmt1->clear(); $stmt1->bindValue(':name', $n); $stmt1->bindValue(':channel', $c); $stmt1->bindValue(':extension', $d->name); $stmt1->bindValue(':exclude', $exclude); $stmt1->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt1->bindValue(':groupname', $group->name); $stmt1->execute(); } $stmt1->close(); } } $stmt->close(); $sql = ' INSERT INTO package_dependencies (required, packages_name, packages_channel, deppackage, depchannel, conflicts, min, max, recommended, is_subpackage, groupname, providesextension) VALUES (0, :name, :channel, :dep_package, :dep_channel, :conflicts, :min, :max, :recommended, :sub, :group, :ext)'; $stmt = $database->prepare($sql); foreach (array('package', 'subpackage') as $package) { foreach ($group->{$package} as $d) { // $d is a \Pyrus\PackageFile\v2\Dependencies\Package object $sub = $package == 'subpackage'; $ext = $d->providesextension; $stmt->clear(); $stmt->bindValue(':name', $n); $stmt->bindValue(':channel', $c); $stmt->bindValue(':dep_package', $d->name); $stmt->bindValue(':dep_channel', $d->channel); $stmt->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt->bindValue(':min', $d->min); $stmt->bindValue(':max', $d->max); $stmt->bindValue(':recommended', $d->recommended); $stmt->bindValue(':sub', $sub); $stmt->bindValue(':group', $group->name); if ($ext) { $stmt->bindValue(':ext', $ext); } else { $stmt->bindValue(':ext', $ext, SQLITE3_NULL); } $stmt->execute(); if (isset($d->exclude)) { $sql = ' INSERT INTO package_dependencies_exclude (required, packages_name, packages_channel, deppackage, depchannel, exclude, conflicts, is_subpackage, groupname) VALUES(0, :name, :channel, :dep_package, :dep_channel, :exclude, :conflicts, :sub, :group)'; $stmt1 = $database->prepare($sql); foreach ($d->exclude as $exclude) { $stmt1->clear(); $req = 0; $stmt1->bindValue(':required', $req, SQLITE3_INTEGER); $stmt1->bindValue(':name', $n); $stmt1->bindValue(':channel', $c); $stmt1->bindValue(':dep_package', $d->name); $stmt1->bindValue(':dep_channel', $d->channel); $stmt1->bindValue(':exclude', $exclude); $stmt1->bindValue(':sub', $sub); $stmt1->bindValue(':group', $group->name); $stmt1->bindValue(':conflicts', $d->conflicts, SQLITE3_INTEGER); $stmt1->execute(); } $stmt1->close(); } } } } $stmt->close(); }
/** * Do a package.xml 1.0 replacement, with additional package-info fields available * * See validateXml() source for the complete list of allowed fields * @param \Pyrus\PackageInterface * @param resource open file pointer, set to the beginning of the file * @param string the eventual final file location (informational only) * @return string|false */ function startSession($fp, $dest) { $contents = stream_get_contents($fp); $subst_from = $subst_to = array(); foreach ($this->_replacements as $a) { $a = $a['attribs']; $to = ''; if ($a['type'] == 'pear-config') { if ($this->installphase == Common::PACKAGE) { return false; } $to = \Pyrus\Config::current()->{$a['to']}; if (is_null($to)) { \Pyrus\Logger::log(0, "{$dest}: invalid pear-config replacement: {$a['to']}"); return false; } } elseif ($a['type'] == 'php-const') { if ($this->installphase == Common::PACKAGE) { return false; } if (defined($a['to'])) { $to = constant($a['to']); } else { \Pyrus\Logger::log(0, "{$dest}: invalid php-const replacement: {$a['to']}"); return false; } } else { if ($t = $this->pkg->{$a['to']}) { if ($a['to'] == 'version') { $t = $t['release']; } $to = $t; } else { \Pyrus\Logger::log(0, "{$dest}: invalid package-info replacement: {$a['to']}"); return false; } } if (!is_null($to)) { $subst_from[] = $a['from']; $subst_to[] = $to; } } \Pyrus\Logger::log(3, "doing " . sizeof($subst_from) . " substitution(s) for {$dest}"); if (sizeof($subst_from)) { $contents = str_replace($subst_from, $subst_to, $contents); } rewind($fp); ftruncate($fp, 0); fwrite($fp, $contents); return true; }
public function listPackages($channel) { $dir = $this->_namePath($channel, ''); if (!@file_exists($dir)) { return array(); } $ret = array(); try { foreach (new \DirectoryIterator($dir) as $file) { if ($file->isDot() || !$file->isFile()) { continue; } $a = @unserialize(file_get_contents($file->getPathName())); // $a['name'] is not set on v1 regs if ($a !== false && isset($a['name'])) { $ret[] = $a['name']; } elseif ($a !== false && isset($a['package'])) { $ret[] = $a['package']; } else { \Pyrus\Logger::log(0, 'Warning: corrupted REG registry entry: ' . $file->getPathName()); } } } catch (\Exception $e) { throw new Exception('Could not open channel directory for channel ' . $channel, $e); } return $ret; }