예제 #1
0
 function getFilePath($file)
 {
     $role = \PEAR2\Pyrus\Installer\Role::factory($this->packagefile->getPackageType(), $this->packagefile->packagingcontents[$file]['attribs']['role']);
     list(, $path) = $role->getRelativeLocation($this->packagefile, new \PEAR2\Pyrus\PackageFile\v2Iterator\FileTag($this->packagefile->packagingcontents[$file], '', $this->packagefile), true);
     $dir = \PEAR2\Pyrus\Config::singleton($this->registry->getPath())->{$role->getLocationConfig()};
     return $dir . DIRECTORY_SEPARATOR . $path;
 }
예제 #2
0
 /**
  * Construct simple channel server
  *
  * @param PEAR2_SimpleChannelServer_Channel $channel   channel object
  * @param string $webpath   full path to web files eg: /var/www/pear/
  * @param string $pyruspath Path to the pyrus controlled PEAR installation
  */
 function __construct(\PEAR2\Pyrus\Channel $channel, $webpath, $pyruspath = null)
 {
     if (!realpath($webpath) || !is_writable($webpath)) {
         throw new PEAR2_SimpleChannelServer_Exception('Path to channel web files ' .
             $webpath .
             ' must exist and be writable');
     } else {
         $this->webpath = $webpath;
     }
     if (!$pyruspath) {
     	$pyruspath = __DIR__;
     }
     $rest = $channel->protocols->rest;
     foreach ($rest as $restpath) {
         $restpath = str_replace('http://'.$channel->name.'/', '', $restpath);
         break;
     }
     if (dirname($restpath . 'a') . '/' !== $restpath) {
         $restpath .= '/';
     }
     $this->uri     = 'http://' . $channel->name . '/';
     $this->channel = $channel;
     $this->rest    = new PEAR2_SimpleChannelServer_REST_Manager($webpath.'/'.$restpath, $channel->name,
         $restpath);
     $this->get     = new PEAR2_SimpleChannelServer_Get($webpath.'/get', $pyruspath);
     try {
         $a = \PEAR2\Pyrus\Config::singleton($pyruspath);
     } catch (Exception $e) {
         throw new PEAR2_SimpleChannelServer_Exception('Cannot initialize Pyrus Config',
             $e);
     }
 }
예제 #3
0
 function __construct($coverage, $recursive)
 {
     $this->ini_overwrites[] = 'error_reporting=' . E_ALL;
     if ($coverage) {
         $this->_options['coverage'] = true;
     }
     if ($recursive) {
         $this->_options['recur'] = true;
     }
     $this->windows = substr(PHP_OS, 0, 3) == 'WIN';
     $this->_php = \PEAR2\Pyrus\Config::current()->php_bin;
     $this->xdebug_loaded = extension_loaded('xdebug');
 }
예제 #4
0
 function isUpgradeable()
 {
     if (!isset(\PEAR2\Pyrus\Main::$options['upgrade'])) {
         // we don't attempt to upgrade a dep unless we're upgrading
         return false;
     }
     $reg = \PEAR2\Pyrus\Config::current()->registry;
     $version = $reg->info($this->name, $this->channel, 'version');
     if (version_compare($this->version['release'], $version, '<=')) {
         return !isset(\PEAR2\Pyrus\Main::$options['force']);
     }
     return true;
 }
 /**
  * Install a PEAR package.
  *
  * @param string $package Name of the package to install. PEAR2_Templates_Savant
  *
  * @return void
  */
 static function installPackage($package)
 {
     $config = \PEAR2\Pyrus\Config::singleton(self::$autoload_registry);
     $config->preferred_state = 'alpha';
     $p = new \PEAR2\Pyrus\Package($package);
     try {
         \PEAR2\Pyrus\Installer::begin();
         \PEAR2\Pyrus\Installer::prepare($p);
         \PEAR2\Pyrus\Installer::commit();
     } catch (Exception $e) {
         \PEAR2\Pyrus\Installer::rollback();
         echo $e;
     }
 }
예제 #6
0
    function getRelativeLocation(\PEAR2\Pyrus\PackageFileInterface $pkg, \PEAR2\Pyrus\PackageFile\v2Iterator\FileTag $file,
                                 $retDir = false)
    {
        if ($this->md5 === null) {
            return parent::getRelativeLocation($pkg, $file, $retDir);
        }

        $info = parent::getRelativeLocation($pkg, $file, $retDir);
        $path = \PEAR2\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'];
                \PEAR2\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;
    }
예제 #7
0
    function __construct($__DIR__)
    {
        set_include_path($__DIR__);
        $c = \PEAR2\Pyrus\Config::singleton(dirname($__DIR__), dirname($__DIR__) . '/pearconfig.xml');
        $c->bin_dir = $__DIR__ . '/bin';
        restore_include_path();
        $c->saveConfig();

        $chan = new PEAR2\SimpleChannelServer\Channel('pear2.php.net', 'unit test channel');
        $scs = new PEAR2\SimpleChannelServer\Main($chan, $__DIR__, dirname($__DIR__) . '/PEAR2');

        $scs->saveChannel();
        $this->chan = $chan;
        $this->scs = $scs;
        $this->__DIR__ = $__DIR__;
    }
예제 #8
0
 function cloneRegistry(Base $registry)
 {
     try {
         $packageiterator = $registry->package;
         foreach (\PEAR2\Pyrus\Config::current()->channelregistry->listChannels() as $channel) {
             $packageiterator->setIteratorChannel($channel);
             foreach ($packageiterator as $package) {
                 if ($this->exists($package->name, $package->channel)) {
                     $old = $this->toPackageFile($package->name, $package->channel);
                     if ($old->date == $package->date && $old->time == $package->time) {
                         continue;
                     }
                 }
                 $this->replace($package);
             }
         }
     } catch (\Exception $e) {
         throw new Exception('Cannot clone registry', $e);
     }
 }
예제 #9
0
 /**
  * Get/Create a transaction.
  *
  * @param string|PEAR2\Pyrus\Installer\Role\Common $path The directory path.
  * @return Transaction A PEAR2\Pyrus\AtomicFileTransaction\Transaction instance
  */
 public function getTransaction($path)
 {
     if ($path instanceof \PEAR2\Pyrus\Installer\Role\Common) {
         $path = \PEAR2\Pyrus\Config::current()->{$path->getLocationConfig()};
     }
     $path = FS::path((string) $path);
     if (isset($this->transactions[$path])) {
         return $this->transactions[$path];
     }
     // Create new transaction object
     $class = $this->getTransactionClass();
     try {
         $this->transactions[$path] = new $class($path, $this);
         return $this->transactions[$path];
     } catch (\Exception $e) {
         $errs = new MultiErrors();
         $errs->E_ERROR[] = $e;
         $errs->merge($this->rollbackTransactions());
         throw new MultiException('Unable to begin transaction', $errs);
     }
 }
예제 #10
0
 /**
  * Do a package.xml 1.0 replacement, with additional package-info fields available
  *
  * See validateXml() source for the complete list of allowed fields
  * @param \PEAR2\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 = \PEAR2\Pyrus\Config::current()->{$a['to']};
             if (is_null($to)) {
                 \PEAR2\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 {
                 \PEAR2\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 {
                 \PEAR2\Pyrus\Logger::log(0, "{$dest}: invalid package-info replacement: {$a['to']}");
                 return false;
             }
         }
         if (!is_null($to)) {
             $subst_from[] = $a['from'];
             $subst_to[] = $to;
         }
     }
     \PEAR2\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;
 }
예제 #11
0
    /**
     * Check to see if any packages in the list of packages to be installed
     * satisfy this dependency, and return one if found, otherwise
     * instantiate a new dependency package object
     * @return \PEAR2\Pyrus\PackageInterface|NULL
     */
    function retrieve(\PEAR2\Pyrus\PackageFile\v2\Dependencies\Package $info)
    {
        if (isset(self::$localPackages[$info->channel . '/' . $info->name])
                || $this->childProcessed($info->channel . '/' . $info->name)) {
            // we can safely ignore this dependency, an explicit local
            // package is being installed, and we will use it
            // or the dependency has been previously processed, and we will
            // simply result in a duplicate
            return;
        }

        $reg = Config::current()->registry;
        // first check to see if the dependency is installed
        $canupgrade = false;
        if (isset($reg->package[$info->channel . '/' . $info->name])) {
            if (!isset(\PEAR2\Pyrus\Main::$options['upgrade'])) {
                // we don't attempt to upgrade a dep unless we're upgrading
                return;
            }

            $version   = $reg->info($info->name, $info->channel, 'version');
            $stability = $reg->info($info->name, $info->channel, 'state');
            if ($this->node->isRemote() && $this->node->getExplicitState()) {
                $installedstability = \PEAR2\Pyrus\Installer::betterStates($stability);
                $parentstability = \PEAR2\Pyrus\Installer::betterStates($this->node->getExplicitState());
                if (count($parentstability) > count($installedstability)) {
                    $stability = $this->node->getExplicitState();
                }
            } else {
                $installedstability = \PEAR2\Pyrus\Installer::betterStates($stability);
                $prefstability = \PEAR2\Pyrus\Installer::betterStates(Config::current()->preferred_state);
                if (count($prefstability) > count($installedstability)) {
                    $stability = Config::current()->preferred_state;
                }
            }

            // see if there are new versions in our stability or better
            if (isset($info->uri)) {
                return;
            }

            $remote = new \PEAR2\Pyrus\Channel\RemotePackage(Config::current()
                                                            ->channelregistry[$info->channel], $stability);
            $found = false;
            foreach ($remote[$info->name] as $remoteversion => $rinfo) {
                if (version_compare($remoteversion, $version, '<=')) {
                    continue;
                }

                if (version_compare($rinfo['minimumphp'], static::getPHPversion(), '>')) {
                    continue;
                }

                // found one, so upgrade is possible if dependencies pass
                $found = true;
                break;
            }

            // the installed package version satisfies this dependency, don't do anything
            if (!$found) {
                return;
            }

            $canupgrade = true;
        }

        if (isset($info->uri)) {
            $ret = new \PEAR2\Pyrus\Package\Remote($info->uri);
            // set up the basics
            $ret->name = $info->name;
            $ret->uri = $info->uri;
            $this->addChild($ret);
            return;
        }

        if ($this->node->isRemote() && $this->node->getExplicitState()) {
            // pass the same explicit state to the child dependency
            $ret = new \PEAR2\Pyrus\Package\Remote($info->channel . '/' . $info->name . '-' .
                                                  $this->node->getExplicitState());
            if ($canupgrade) {
                $ret->setUpgradeable();
            }

            $this->addChild($ret);
            return;
        }

        $ret = new \PEAR2\Pyrus\Package\Remote($info->channel . '/' . $info->name);
        if ($canupgrade) {
            $ret->setUpgradeable();
        }

        $this->addChild($ret);
        return;
    }
예제 #12
0
 function log($level, $message)
 {
     static $data = array();
     if (\PEAR2\Pyrus\Config::initializing()) {
         // we can't check verbose until initializing is complete, so save
         // the message, and only display the log after config is initialized
         $data[] = array($level, $message);
         return;
     }
     if (count($data)) {
         $save = $data;
         $data = array();
         foreach ($save as $info) {
             $this->log($info[0], $info[1]);
         }
     }
     if ($level <= $this->verbose) {
         if (strlen($message) && $message[strlen($message) - 1] !== "\r") {
             echo $message . "\n";
         } else {
             echo $message;
         }
     }
 }
예제 #13
0
}
$cert = explode(PATH_SEPARATOR, $_ENV['CERT']);
if (count($cert) != 2 || !file_exists($cert[0])) {
    die('set the CERT environment variable to the /path/to/cert' . PATH_SEPARATOR . 'password');
}

$certinfo = array();
$pkcs = openssl_pkcs12_read(file_get_contents($cert[0]), $certinfo, $cert[1]);
if (!$pkcs) {
    die('Invalid certificate: ' . $cert[0] . ', or invalid password');
}

require __DIR__ . '/../../../../../autoload.php';

set_include_path(__DIR__);
$c = \PEAR2\Pyrus\Config::singleton(dirname(__DIR__), dirname(__DIR__) . '/pearconfig.xml');
$c->bin_dir = __DIR__ . '/bin';
restore_include_path();
$c->saveConfig();

$chan = new PEAR2\SimpleChannelServer\Channel('pear2.php.net', 'unit test channel');
$scs = new PEAR2\SimpleChannelServer\Main($chan, __DIR__, dirname(__DIR__) . '/PEAR2');

$scs->saveChannel();

$pf = new \PEAR2\Pyrus\PackageFile\v2;

for ($i = 1; $i <= 1; $i++) {
    file_put_contents(__DIR__ . "/glooby$i", 'hi');
}
예제 #14
0
 public function info($package, $channel, $field)
 {
     if (!$this->exists($package, $channel)) {
         throw new Exception('Unknown package ' . $channel . '/' . $package);
     }
     $pf = $this->toPackageFile($package, $channel);
     if ($field === null) {
         return $pf;
     }
     if ($field == 'version') {
         $field = 'release-version';
     }
     if ($field != 'installedfiles' && $field != 'dirtree') {
         return $pf->{$field};
     }
     $packagefile = $this->_namePath($channel, $package) . '.reg';
     if (!$packagefile || !isset($packagefile[0])) {
         throw new Exception('Cannot find registry for package ' . $channel . '/' . $package);
     }
     $packagecontents = file_get_contents($packagefile);
     $data = @unserialize($packagecontents);
     if ($data === false) {
         throw new Exception('Cannot retrieve package file object for package ' . $channel . '/' . $package . ', PEAR 1.x registry file might be corrupt!');
     }
     if ($field == 'dirtree') {
         $ret = $data['filelist']['dirtree'];
         usort($ret, 'strnatcasecmp');
         return array_reverse($ret);
     }
     $configpaths = $roles = array();
     $config = \PEAR2\Pyrus\Config::current();
     foreach (Role::getValidRoles($pf->getPackageType()) as $role) {
         // set up a list of file role => configuration variable
         // for storing in the registry
         $roles[$role] = Role::factory($pf->getPackageType(), $role);
         $configpaths[$role] = $config->{$roles[$role]->getLocationConfig()};
     }
     $ret = array();
     foreach ($data['filelist'] as $file) {
         if (!isset($file['installed_as']) || !isset($configpaths[$file['role']])) {
             continue;
         }
         if (0 !== strpos($file['installed_as'], $configpaths[$file['role']])) {
             // this was installed with a different configuration, so don't guess
             $file['relativepath'] = basename($file['installed_as']);
             $file['configpath'] = dirname($file['installed_as']);
         } else {
             $file['relativepath'] = substr($file['installed_as'], strlen($configpaths[$file['role']]) + 1);
             $file['configpath'] = $configpaths[$file['role']];
         }
         $ret[$file['installed_as']] = $file;
     }
     return $ret;
 }
예제 #15
0
    function getDependenciesOn($info)
    {
        $name = $info->name;
        $channel = $info->channel;
        $packages = \PEAR2\Pyrus\Config::current()->registry
                            ->getDependentPackages($info->getPackageFileObject());

        $ret = array();
        foreach ($packages as $package) {
            $deps = $package->dependencies;
            foreach (array('package', 'subpackage') as $type) {
                foreach (array('required', 'optional') as $required) {
                    foreach ($deps[$required]->$type as $dep) {
                        if ($dep->channel != $channel || $dep->name != $name) {
                            continue;
                        }

                        $ret[] = $dep;
                    }
                }
            }
        }

        return $ret;
    }
예제 #16
0
 /**
  * Retrieves a value from the Pyrus configuration.
  *
  * @param  string $name The variable name
  * @return mixed        The configuration value
  */
 public function getConfig($name)
 {
     $this->config = \PEAR2\Pyrus\Config::current();
     return $this->config->__get($name);
 }
예제 #17
0
    static function registerCustomRole($info)
    {
        self::$_roles[$info['name']] = $info;
        $roles = self::$_roles;
        ksort($roles);
        self::$_roles = $roles;
        self::getBaseinstallRoles(true);
        self::getInstallableRoles(true);
        self::getValidRoles('****', true);
        if (isset($info['configvar'])) {
            if (!isset($info['configvar'][0])) {
                $info['configvar'] = array($info['configvar']);
            }

            foreach ($info['configvar'] as $configvar) {
                $default = $configvar['default'];
                if (false !== strpos($default, '<?php')) {
                    $tmp = Config::current()->temp_dir . DIRECTORY_SEPARATOR . '.configdefault.php';
                    if (!file_exists(dirname($tmp))) {
                        mkdir(dirname($tmp), 0755, true);
                    }

                    file_put_contents($tmp, $default);
                    $getDefault = function() use ($tmp) {
                        include $tmp;
                        return $default;
                    };

                    $default = $getDefault();
                }

                Config::addConfigValue($configvar['name'], $default, $configvar['configtype']);
            }
        }
    }
예제 #18
0
    /**
     * Unlike other tasks, the installed file name is passed in instead of the file contents,
     * because this task is handled post-installation
     * @param \PEAR2\Pyrus\PackageInterface
     * @param string path to the post-install script
     * @return bool false to skip this file
     */
    function setupPostInstall()
    {
        $files = \PEAR2\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;
    }
예제 #19
0
 static function registerCustomRole($info)
 {
     if (!isset(self::$_roles)) {
         self::registerRoles();
     }
     self::$_roles[$info['name']] = $info;
     $roles = self::$_roles;
     ksort($roles);
     self::$_roles = $roles;
     self::getBaseinstallRoles(true);
     self::getInstallableRoles(true);
     self::getValidRoles('****', true);
     if (isset($info['configvar'])) {
         if (!isset($info['configvar'][0])) {
             $info['configvar'] = array($info['configvar']);
         }
         foreach ($info['configvar'] as $configvar) {
             if ($configvar['configtype'] == 'system' && in_array($configvar['name'], Config::current()->customsystemvars) || $configvar['configtype'] == 'user' && in_array($configvar['name'], Config::current()->customuservars) || $configvar['configtype'] == 'channel' && in_array($configvar['name'], Config::current()->customchannelvars)) {
                 continue;
             }
             $default = $configvar['default'];
             if (false !== strpos($default, '<?php')) {
                 $tmp = Config::current()->temp_dir . DIRECTORY_SEPARATOR . '.configdefault.php';
                 if (!file_exists(dirname($tmp))) {
                     mkdir(dirname($tmp), 0755, true);
                 }
                 if (file_put_contents($tmp, $default) === false) {
                     throw new Role\Exception("Cannot create custom role configuration file {$tmp}");
                 }
                 $getDefault = function () use($tmp) {
                     include $tmp;
                     return $default;
                 };
                 $default = $getDefault();
             }
             Config::addConfigValue($configvar['name'], $default, $configvar['configtype']);
         }
     }
 }
예제 #20
0
 function warning($msg)
 {
     $package = Config::parsedPackageNameToString($this->_currentPackage, true);
     $this->errs->E_WARNING[] = new Exception(sprintf($msg, $package));
     return true;
 }
예제 #21
0
    /**
     * @param string|Installer\Role\Common $rolepath
     * @return AtomicFileTransaction
     */
    static function getTransactionObject($rolepath)
    {
        if ($rolepath instanceof Installer\Role\Common) {
            $rolepath = Config::current()->{$rolepath->getLocationConfig()};
        }
        $rolepath =str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $rolepath);

        if (isset(static::$allTransactObjects[$rolepath])) {
            return static::$allTransactObjects[$rolepath];
        }

        $ret = static::$allTransactObjects[$rolepath] = new AtomicFileTransaction($rolepath);
        if (static::$intransaction) {
            // start the transaction process for this atomic transaction object
            $errs =  new \PEAR2\MultiErrors;
            try {
                $ret->beginTransaction();
            } catch (\Exception $e) {
                $errs->E_ERROR[] = $e;
                foreach (static::$allTransactObjects as $path2 => $transact) {
                    try {
                        $transact->removeJournalPath();
                    } catch (\Exception $e2) {
                        $errs->E_WARNING[] = $e2;
                    }
                }

                throw new AtomicFileTransaction\Exception(
                    'Unable to begin transaction for ' . $rolepath, $errs
                );
            }
        }

        return $ret;
    }
예제 #22
0
 /**
  * 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, \PEAR2\Pyrus\Config will attempt to guess at the config file location as
  * documented in the class docblock {@link \PEAR2\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';
         }
     }
     \PEAR2\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);
     }
 }
예제 #23
0
    /**
     * Detect any files already installed that would be overwritten by
     * files inside the package represented by $package
     */
    public function detectFileConflicts(\PEAR2\Pyrus\PackageFileInterface $package)
    {
        if (!static::existsRegistry($this->_path)) {
            throw new \PEAR2\Pyrus\ChannelRegistry\Exception('Error: no existing SQLite3 channel registry for ' . $this->_path);
        }
        $database = static::getRegistry($this->_path);

        $ret = array();
        $sql = 'SELECT
                    packages_channel, packages_name
                FROM files
                WHERE
                    packagepath = :path
                ORDER BY packages_channel, packages_name';
        $stmt = $database->prepare($sql);
        // now iterate over each file in the package, and note all the conflicts
        $roles = array();
        foreach (Role::getValidRoles($package->getPackageType()) as $role) {
            // set up a list of file role => configuration variable
            // for storing in the registry
            $roles[$role] = Role::factory($package->getPackageType(), $role);
        }

        $ret = array();
        $config = Config::current();
        foreach ($package->installcontents as $file) {
            $stmt->reset();
            $relativepath = $roles[$file->role]->getRelativeLocation($package, $file);
            if (!$relativepath) {
                continue;
            }

            $testpath = $config->{$roles[$file->role]->getLocationConfig()} .
                    DIRECTORY_SEPARATOR . $relativepath;
            $stmt->bindValue(':path', $testpath, SQLITE3_TEXT);
            $result = $stmt->execute();

            while ($res = $result->fetchArray(SQLITE3_ASSOC)) {
                $pn = $this->info($res['packages_name'], $res['packages_channel'], 'name');
                $ret[] = array($relativepath => $res['packages_channel'] . '/' . $pn);
            }
        }

        return $ret;
    }
예제 #24
0
 function offsetUnset($offset)
 {
     $info = Config::current()->channelregistry->parseName($offset);
     $this->reg->uninstall($info['package'], $info['channel']);
 }
예제 #25
0
 /**
  * Render packages from the creators passed into the constructor.
  *
  * This will take any package source and an array mapping internal
  * path => file name and create new packages in the formats requested.
  *
  * All files in package.xml will have the string @PACKAGE_VERSION@
  * automatically replaced with the current package's version
  * @param \PEAR2\Pyrus\Package $package
  * @param array $extrafiles
  */
 function render(\PEAR2\Pyrus\Package $package, array $extrafiles = array())
 {
     foreach ($this->_creators as $creator) {
         $creator->init();
     }
     $this->prepend = $prepend = $package->name . '-' . $package->version['release'];
     if ($package->isNewPackage()) {
         $packagexml = $prepend . '/.xmlregistry/packages/' . str_replace('/', '!', $package->channel) . '/' . $package->name . '/' . $package->version['release'] . '-info.xml';
     } else {
         if ($package->isOldAndCrustyCompatible()) {
             $packagexml = 'package2.xml';
             $old = file_get_contents('package.xml');
         } else {
             $packagexml = 'package.xml';
         }
     }
     if (self::VERSION === '@' . 'PACKAGE_VERSION@') {
         // we're running straight from SVN, so pretend to be 2.0.0
         $package->packagerversion = '2.0.0';
     } else {
         $package->packagerversion = self::VERSION;
     }
     // get packaging package.xml
     $packageingstr = (string) new \PEAR2\Pyrus\XMLWriter($package->toArray(true));
     foreach ($this->_creators as $creator) {
         $creator->addFile($packagexml, $packageingstr);
     }
     if ($package->isOldAndCrustyCompatible()) {
         foreach ($this->_creators as $creator) {
             $creator->addFile('package.xml', $old);
         }
     }
     if ($package->getInternalPackage() instanceof Xml) {
         // check for package_compatible.xml
         if ($package->isNewPackage() && file_exists($package->getFilePath('package_compatible.xml'))) {
             foreach ($this->_creators as $creator) {
                 $creator->addFile('package.xml', file_get_contents($package->getFilePath('package_compatible.xml')));
             }
         }
     }
     $packagingloc = \PEAR2\Pyrus\Config::current()->temp_dir . DIRECTORY_SEPARATOR . 'pyrpackage';
     if (file_exists($packagingloc)) {
         \PEAR2\Pyrus\Filesystem::rmrf($packagingloc, false, false);
     }
     mkdir($packagingloc, 0777, true);
     // $packageat is the relative path within the archive
     // $info is an array of format:
     // array('attribs' => array('name' => ...)[, 'tasks:blah' ...])
     $alreadyPackaged = array();
     $globalreplace = array('attribs' => array('from' => '@' . 'PACKAGE_VERSION@', 'to' => 'version', 'type' => 'package-info'));
     foreach ($package->packagingcontents as $packageat => $info) {
         $role = \PEAR2\Pyrus\Installer\Role::factory($package->getPackageType(), $info['attribs']['role']);
         try {
             $role->packageTimeValidate($package, $info);
         } catch (\Exception $e) {
             throw new Creator\Exception('Invalid file ' . $packageat . ': ' . $e->getMessage(), $e);
         }
         $packageat = str_replace('\\', '/', $packageat);
         $packageat = str_replace('//', '/', $packageat);
         if ($packageat[0] === '/' || strlen($packageat) > 2 && ($packageat[1] === ':' && $packageat[2] == '/')) {
             throw new Creator\Exception('Invalid path, cannot save a root path ' . $packageat);
         }
         if (preg_match('@^\\.\\.?/|/\\.\\.?\\z|/\\.\\./@', $packageat)) {
             throw new Creator\Exception('Invalid path, cannot use directory ' . 'reference . or .. ' . $packageat);
         }
         $alreadyPackaged[$packageat] = true;
         $packageat = $prepend . '/' . $packageat;
         $contents = $package->getFileContents($info['attribs']['name'], true);
         if (!file_exists(dirname($packagingloc . DIRECTORY_SEPARATOR . $packageat))) {
             mkdir(dirname($packagingloc . DIRECTORY_SEPARATOR . $packageat), 0777, true);
         }
         $fp = fopen($packagingloc . DIRECTORY_SEPARATOR . $packageat, 'wb+');
         ftruncate($fp, 0);
         stream_copy_to_stream($contents, $fp);
         fclose($contents);
         rewind($fp);
         if ($package->isNewPackage() && $info['attribs']['role'] == 'php') {
             if (isset($info['tasks:replace'])) {
                 if (isset($info['tasks:replace'][0])) {
                     $info['tasks:replace'][] = $globalreplace;
                 } else {
                     $info['tasks:replace'] = array($info['tasks:replace'], $globalreplace);
                 }
             } else {
                 $info['tasks:replace'] = $globalreplace;
             }
         }
         if (isset(\PEAR2\Pyrus\Config::current()->registry->package[$package->channel . '/' . $package->name])) {
             $version = \PEAR2\Pyrus\Config::current()->registry->info($package->name, $package->channel, 'version');
         } else {
             $version = null;
         }
         foreach (new Creator\TaskIterator($info, $package, \PEAR2\Pyrus\Task\Common::PACKAGE, $version) as $task) {
             // do pre-processing of file contents
             try {
                 $task->startSession($fp, $packageat);
             } catch (\Exception $e) {
                 // TODO: handle exceptions
             }
         }
         fclose($fp);
     }
     foreach ($this->_creators as $creator) {
         $creator->addDir($packagingloc);
     }
     if ($package->isNewPackage()) {
         $this->addPEAR2Stuff($alreadyPackaged);
     }
     $this->addExtraFiles($extrafiles);
     foreach ($this->_creators as $creator) {
         $creator->close();
     }
     \PEAR2\Pyrus\Filesystem::rmrf($packagingloc, false, false);
 }
예제 #26
0
    /**
     * @param array output of {@link parsePackageName()}
     * @return \PEAR2\Pyrus\Channel\RemotePackage
     * @access private
     */
    function getRemotePackage($parr)
    {
        // getDownloadURL returns an array.  On error, it only contains information
        // on the latest release as array(version, info).  On success it contains
        // array(version, info, download url string)
        $state = isset($parr['state']) ? $parr['state'] :  Config::current()->preferred_state;
        if (!isset(Config::current()->channelregistry[$parr['channel']])) {
            throw new Exception('Unknown remote channel: ' . $parr['channel']);
        }

        try {
            $chan = Config::current()->channelregistry[$parr['channel']];
        } catch (\Exception $e) {
            throw new Exception('Cannot retrieve download information ' .
                'for remote abstract package ' . $parr['channel'] . '/' . $parr['package'], $e);
        }

        $p_mirror = Config::current()->preferred_mirror;
        $mirror   = isset($chan->mirrors[$p_mirror]) ? $chan->mirrors[$p_mirror] : $chan;
        return $mirror->remotepackage[$parr['package']];
    }
예제 #27
0
 /**
  * Detect any files already installed that would be overwritten by
  * files inside the package represented by $package
  */
 public function detectFileConflicts(\PEAR2\Pyrus\PackageFileInterface $package)
 {
     // construct list of all installed files
     $filesByPackage = $allfiles = array();
     $config = \PEAR2\Pyrus\Config::current();
     foreach ($config->channelregistry as $channel) {
         foreach ($this->listPackages($channel->name) as $packagename) {
             $files = $this->info($packagename, $channel->name, 'installedfiles');
             $newfiles = array();
             foreach ($files as $file) {
                 $newfiles[$file['installed_as']] = $file;
             }
             $filesByPackage[$channel->name . '/' . $packagename] = $newfiles;
             $allfiles = array_merge($allfiles, $newfiles);
         }
     }
     // now iterate over each file in the package, and note all the conflicts
     $roles = array();
     foreach (Role::getValidRoles($package->getPackageType()) as $role) {
         // set up a list of file role => configuration variable
         // for storing in the registry
         $roles[$role] = Role::factory($package->getPackageType(), $role);
     }
     $ret = array();
     foreach ($package->installcontents as $file) {
         $relativepath = $roles[$file->role]->getRelativeLocation($package, $file);
         if (!$relativepath) {
             continue;
         }
         $testpath = $config->{$roles[$file->role]->getLocationConfig()} . DIRECTORY_SEPARATOR . $relativepath;
         if (isset($allfiles[$testpath])) {
             foreach ($filesByPackage as $pname => $files) {
                 if (isset($files[$testpath])) {
                     $ret[] = array($relativepath => $pname);
                     break;
                 }
             }
         }
     }
     return $ret;
 }
예제 #28
0
 /**
  * @param \PEAR2\Pyrus\PackageFile\v2
  * @param int
  */
 function validate(\PEAR2\Pyrus\PackageInterface $pf, $state = \PEAR2\Pyrus\Validate::NORMAL)
 {
     $this->errors = new \PEAR2\MultiErrors;
     if (!$pf->schemaOK) {
         // this package.xml was created from scratch, not loaded from an existing
         // package.xml
         $dom = new \DOMDocument;
         libxml_use_internal_errors(true);
         libxml_clear_errors();
         $dom->loadXML($pf);
         $a = $pf->toArray();
         if ($a['package']['attribs']['version'] == '2.1') {
             $schema = \PEAR2\Pyrus\Main::getDataPath() . '/package-2.1.xsd';
             // for running out of cvs
             if (!file_exists($schema)) {
                 $schema = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/package-2.1.xsd';
             }
         } else {
             $schema = \PEAR2\Pyrus\Main::getDataPath() . '/package-2.0.xsd';
             // for running out of cvs
             if (!file_exists($schema)) {
                 $schema = dirname(dirname(dirname(dirname(__DIR__)))) . '/data/package-2.0.xsd';
             }
         }
         $dom->schemaValidate($schema);
         $causes = array();
         foreach (libxml_get_errors() as $error) {
             $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception("Line " .
                  $error->line . ': ' . $error->message);
         }
         if (count($this->errors)) {
             throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml, does' .
                 ' not validate against schema', $this->errors);
         }
     }
     $this->_pf = $pf;
     $this->_curState = $state;
     $this->_packageInfo = $this->_pf->toArray();
     $this->_packageInfo = $this->_packageInfo['package'];
     if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
         return false;
     }
     $myversion = self::VERSION;
     if ($myversion === '@PACKAGE_VERSION@') {
         // we're running from CVS, assume we're 2.0.0
         $myversion = '2.0.0';
     }
     $test = $this->_packageInfo;
     if (isset($test['dependencies']) &&
           isset($test['dependencies']['required']) &&
           isset($test['dependencies']['required']['pearinstaller']) &&
           isset($test['dependencies']['required']['pearinstaller']['min']) &&
           version_compare($myversion,
             $test['dependencies']['required']['pearinstaller']['min'], '<')) {
         $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception(
             'This package.xml requires PEAR version ' .
             $test['dependencies']['required']['pearinstaller']['min'] .
             ' to parse properly, we are version ' . $myversion);
     }
     $fail = false;
     foreach ($pf->contents as $file) {
         // leverage the hidden iterators to do our validation
         $name = $file->dir . $file->name;
         if ($name[0] == '.' && $name[1] == '/') {
             // name is something like "./doc/whatever.txt"
             $this->errors->E_ERROR[] = new \PEAR2\Pyrus\Package\Exception(
                 'File "' . $name . '" cannot begin with "."');
             continue;
         }
         if (!$this->_validateRole($file->role)) {
             if (isset($this->_packageInfo['usesrole'])) {
                 $roles = $this->_packageInfo['usesrole'];
                 if (!isset($roles[0])) {
                     $roles = array($roles);
                 }
                 foreach ($roles as $role) {
                     if ($role['role'] = $file->role) {
                         if (isset($role['uri'])) {
                             $package = $role['uri'];
                         } else {
                             $package = \PEAR2\Pyrus\Config::
                                 parsedPackageNameToString(array('package' =>
                                     $role['package'], 'channel' => $role['channel']),
                                     true);
                         }
                         $msg = 'This package contains role "' . $file->role .
                             '" and requires package "' . $package
                              . '" to be used';
                         $this->errors->E_WARNING[] =
                             new \PEAR2\Pyrus\PackageFile\Exception($msg);
                     }
                 }
             }
             $this->errors->E_ERROR[] =
                 new \PEAR2\Pyrus\PackageFile\Exception(
                 'File "' . $name . '" has invalid role "' .
                 $file->role . '", should be one of ' . implode(', ',
                 \PEAR2\Pyrus\Installer\Role::getValidRoles($this->_pf->getPackageType())));
         }
         if (count($file->tasks) && $this->_curState != \PEAR2\Pyrus\Validate::DOWNLOADING) { // has tasks
             $save = $file->getArrayCopy();
             foreach ($file->tasks as $task => $value) {
                 if ($tagClass = \PEAR2\Pyrus\Task\Common::getTask($task)) {
                     if (!is_array($value) || !isset($value[0])) {
                         $value = array($value);
                     }
                     foreach ($value as $v) {
                         try {
                             $ret = $tagClass::validateXml($this->_pf, $v, $save['attribs'], $file->name);
                         } catch (\PEAR2\Pyrus\Task\Exception $e) {
                             $this->errors->E_ERROR[] =
                                 new \PEAR2\Pyrus\PackageFile\Exception('Invalid task $task', $e);
                         }
                     }
                 } else {
                     if (isset($this->_packageInfo['usestask'])) {
                         $roles = $this->_packageInfo['usestask'];
                         if (!isset($roles[0])) {
                             $roles = array($roles);
                         }
                         foreach ($roles as $role) {
                             if ($role['task'] = $task) {
                                 if (isset($role['uri'])) {
                                     $package = $role['uri'];
                                 } else {
                                     $package = \PEAR2\Pyrus\Config::
                                         parsedPackageNameToString(array('package' =>
                                             $role['package'], 'channel' => $role['channel']),
                                             true);
                                 }
                                 $msg = 'This package contains task "' .
                                     str_replace($this->_pf->getTasksNs() . ':', '', $task) .
                                     '" and requires package "' . $package
                                      . '" to be used';
                                 $this->errors->E_WARNING[] =
                                     new \PEAR2\Pyrus\PackageFile\Exception($msg);
                             }
                         }
                     }
                     $this->errors->E_ERROR[] =
                         new \PEAR2\Pyrus\PackageFile\Exception(
                         'Unknown task "' . $task . '" passed in file <file name="' .
                         $name . '">');
                 }
             }
         }
     }
     $this->_validateRelease();
     if (count($this->errors->E_ERROR)) {
         throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml', $this->errors);
     }
     try {
         $validator = \PEAR2\Pyrus\Config::current()
             ->channelregistry[$this->_pf->channel]
             ->getValidationObject($this->_pf->name);
     } catch (\PEAR2\Pyrus\Config\Exception $e) {
         throw new \PEAR2\Pyrus\PackageFile\Exception(
             'Unable to process channel-specific configuration for channel ' .
             $this->_pf->getChannel(), $e);
     } catch (\Exception $e) {
         $valpack = \PEAR2\Pyrus\Config::current()
             ->channelregistry[$this->_pf->channel]->getValidationPackage();
         $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception(
             'Unknown channel ' . $this->_pf->channel);
         $this->errors->E_ERROR[] = new \PEAR2\Pyrus\PackageFile\Exception(
             'package "' . $this->_pf->channel . '/' . $this->_pf->name .
             '" cannot be properly validated without validation package "' .
             $this->_pf->channel . '/' . $valpack['name'] . '-' . $valpack['version'] . '"');
     }
     try {
         $validator->setPackageFile($this->_pf);
         $validator->setChannel(\PEAR2\Pyrus\Config::current()
             ->channelregistry[$this->_pf->channel]);
         $validator->validate($state);
         // merge in errors from channel-specific validation
         $this->errors[] = $validator->getFailures();
     } catch (\Exception $e) {
         $this->errors->E_ERROR[] = $e;
     }
     if (count($this->errors->E_ERROR)) {
         throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml',
             $this->errors);
     }
     if ($state == \PEAR2\Pyrus\Validate::PACKAGING) {
         if ($this->_pf->type == 'bundle') {
             if (!$this->_analyzeBundledPackages()) {
                 throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml',
                     $this->errors);
             }
         } else {
             if (!$this->_analyzePhpFiles()) {
                 throw new \PEAR2\Pyrus\PackageFile\Exception('Invalid package.xml',
                     $this->errors);
             }
         }
     }
     return $state;
 }
예제 #29
0
/*
$channel = new PEAR2\SimpleChannelServer('pear2.php.net','/Library/WebServer/Documents/pearserver', null, '/Users/bbieber/pyrus', array('saltybeagle','cellog'));
if (!@unserialize(file_get_contents('/tmp/categories.inf'))) {
      $cat = PEAR2_SimpleChannelServer_Categories::create('Name1',
          'Description 1', 'Alias1')->
          create('Name2', 'Description 2')->
          create('Name3', 'Description 3', 'Alias3')->
          create('Name4', 'Description 4');
      file_put_contents('/tmp/categories.inf', serialize($cat));
}

$categories = PEAR2_SimpleChannelServer_Categories::getCategories();
$categories = $channel->listCategories();
foreach($categories as $category) {
    var_dump($category);
}
*/
$channel = new PEAR2\SimpleChannelServer\Channel('pear2.php.net','Brett Bieber\'s PEAR Channel','salty');

//$scs = new PEAR2\SimpleChannelServer($channel,'/Library/WebServer/Documents/pearserver','/home/bbieber/pyrus/php');
$scs = new PEAR2\SimpleChannelServer($channel,'/home/cellog/testapache/htdocs',\PEAR2\Pyrus\Config::current()->path);
$categories = PEAR2\SimpleChannelServer\Categories::create('Default', 'This is the default category');
$scs->saveChannel();
$scs->saveRelease(new \PEAR2\Pyrus\Package(dirname(__FILE__) . '/../package.xml'), 'cellog');
echo 'did it'.PHP_EOL;
/*
$manager = new PEAR2\SimpleChannelServer\REST\Manager('/Library/WebServer/Documents/pearserver','pear2.php.net','rest/',array('cellog'));
var_dump($manager->saveRelease(new \PEAR2\Pyrus\Package(dirname(__FILE__) . '/../package.xml'),'cellog'));
*/
?>
예제 #30
0
    /**
     * Rebuild the dependency DB by reading registry entries.
     */
    function rebuildDB()
    {
        $depdb = array('_version' => $this->_version);
        if (!$this->hasWriteAccess()) {
            // allow startup for read-only with older Registry
            return $depdb;
        }
        $reg = \PEAR2\Pyrus\Config::current()->registry;

        foreach (\PEAR2\Pyrus\Config::current()->channelregistry as $channel) {
            foreach ($reg->listPackages($channel->name) as $package) {
                $package = $reg->package[$channel->name . '/' . $package];
                $depdb = $this->_setPackageDeps($depdb, $package);
            }
        }

        $this->_writeDepDB($depdb);
    }