"Fossies" - the Fresh Open Source Software Archive

Member "tiki-21.2/vendor_bundled/vendor/pear/pear/PEAR/REST/10.php" (19 Apr 2020, 32667 Bytes) of package /linux/www/tiki-21.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "10.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 /**
    3  * PEAR_REST_10
    4  *
    5  * PHP versions 4 and 5
    6  *
    7  * @category   pear
    8  * @package    PEAR
    9  * @author     Greg Beaver <cellog@php.net>
   10  * @copyright  1997-2009 The Authors
   11  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
   12  * @link       http://pear.php.net/package/PEAR
   13  * @since      File available since Release 1.4.0a12
   14  */
   15 
   16 /**
   17  * For downloading REST xml/txt files
   18  */
   19 require_once 'PEAR/REST.php';
   20 
   21 /**
   22  * Implement REST 1.0
   23  *
   24  * @category   pear
   25  * @package    PEAR
   26  * @author     Greg Beaver <cellog@php.net>
   27  * @copyright  1997-2009 The Authors
   28  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
   29  * @version    Release: @package_version@
   30  * @link       http://pear.php.net/package/PEAR
   31  * @since      Class available since Release 1.4.0a12
   32  */
   33 class PEAR_REST_10
   34 {
   35     /**
   36      * @var PEAR_REST
   37      */
   38     var $_rest;
   39     function __construct($config, $options = array())
   40     {
   41         $this->_rest = new PEAR_REST($config, $options);
   42     }
   43 
   44     /**
   45      * Retrieve information about a remote package to be downloaded from a REST server
   46      *
   47      * @param string $base The uri to prepend to all REST calls
   48      * @param array $packageinfo an array of format:
   49      * <pre>
   50      *  array(
   51      *   'package' => 'packagename',
   52      *   'channel' => 'channelname',
   53      *  ['state' => 'alpha' (or valid state),]
   54      *  -or-
   55      *  ['version' => '1.whatever']
   56      * </pre>
   57      * @param string $prefstate Current preferred_state config variable value
   58      * @param bool $installed the installed version of this package to compare against
   59      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
   60      */
   61     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
   62     {
   63         $states = $this->betterStates($prefstate, true);
   64         if (!$states) {
   65             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
   66         }
   67 
   68         $channel  = $packageinfo['channel'];
   69         $package  = $packageinfo['package'];
   70         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
   71         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
   72         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
   73 
   74         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
   75         if (PEAR::isError($info)) {
   76             return PEAR::raiseError('No releases available for package "' .
   77                 $channel . '/' . $package . '"');
   78         }
   79 
   80         if (!isset($info['r'])) {
   81             return false;
   82         }
   83 
   84         $release = $found = false;
   85         if (!is_array($info['r']) || !isset($info['r'][0])) {
   86             $info['r'] = array($info['r']);
   87         }
   88 
   89         foreach ($info['r'] as $release) {
   90             if (!isset($this->_rest->_options['force']) && ($installed &&
   91                   version_compare($release['v'], $installed, '<'))) {
   92                 continue;
   93             }
   94 
   95             if (isset($state)) {
   96                 // try our preferred state first
   97                 if ($release['s'] == $state) {
   98                     $found = true;
   99                     break;
  100                 }
  101                 // see if there is something newer and more stable
  102                 // bug #7221
  103                 if (in_array($release['s'], $this->betterStates($state), true)) {
  104                     $found = true;
  105                     break;
  106                 }
  107             } elseif (isset($version)) {
  108                 if ($release['v'] == $version) {
  109                     $found = true;
  110                     break;
  111                 }
  112             } else {
  113                 if (in_array($release['s'], $states)) {
  114                     $found = true;
  115                     break;
  116                 }
  117             }
  118         }
  119 
  120         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
  121     }
  122 
  123     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
  124                                $prefstate = 'stable', $installed = false, $channel = false)
  125     {
  126         $states = $this->betterStates($prefstate, true);
  127         if (!$states) {
  128             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
  129         }
  130 
  131         $channel  = $dependency['channel'];
  132         $package  = $dependency['name'];
  133         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
  134         $version  = isset($dependency['version']) ? $dependency['version'] : null;
  135         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
  136 
  137         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
  138         if (PEAR::isError($info)) {
  139             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
  140                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
  141         }
  142 
  143         if (!is_array($info) || !isset($info['r'])) {
  144             return false;
  145         }
  146 
  147         $exclude = array();
  148         $min = $max = $recommended = false;
  149         if ($xsdversion == '1.0') {
  150             switch ($dependency['rel']) {
  151                 case 'ge' :
  152                     $min = $dependency['version'];
  153                 break;
  154                 case 'gt' :
  155                     $min = $dependency['version'];
  156                     $exclude = array($dependency['version']);
  157                 break;
  158                 case 'eq' :
  159                     $recommended = $dependency['version'];
  160                 break;
  161                 case 'lt' :
  162                     $max = $dependency['version'];
  163                     $exclude = array($dependency['version']);
  164                 break;
  165                 case 'le' :
  166                     $max = $dependency['version'];
  167                 break;
  168                 case 'ne' :
  169                     $exclude = array($dependency['version']);
  170                 break;
  171             }
  172         } else {
  173             $min = isset($dependency['min']) ? $dependency['min'] : false;
  174             $max = isset($dependency['max']) ? $dependency['max'] : false;
  175             $recommended = isset($dependency['recommended']) ?
  176                 $dependency['recommended'] : false;
  177             if (isset($dependency['exclude'])) {
  178                 if (!isset($dependency['exclude'][0])) {
  179                     $exclude = array($dependency['exclude']);
  180                 }
  181             }
  182         }
  183         $release = $found = false;
  184         if (!is_array($info['r']) || !isset($info['r'][0])) {
  185             $info['r'] = array($info['r']);
  186         }
  187         foreach ($info['r'] as $release) {
  188             if (!isset($this->_rest->_options['force']) && ($installed &&
  189                   version_compare($release['v'], $installed, '<'))) {
  190                 continue;
  191             }
  192             if (in_array($release['v'], $exclude)) { // skip excluded versions
  193                 continue;
  194             }
  195             // allow newer releases to say "I'm OK with the dependent package"
  196             if ($xsdversion == '2.0' && isset($release['co'])) {
  197                 if (!is_array($release['co']) || !isset($release['co'][0])) {
  198                     $release['co'] = array($release['co']);
  199                 }
  200                 foreach ($release['co'] as $entry) {
  201                     if (isset($entry['x']) && !is_array($entry['x'])) {
  202                         $entry['x'] = array($entry['x']);
  203                     } elseif (!isset($entry['x'])) {
  204                         $entry['x'] = array();
  205                     }
  206                     if ($entry['c'] == $deppackage['channel'] &&
  207                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
  208                           version_compare($deppackage['version'], $entry['min'], '>=') &&
  209                           version_compare($deppackage['version'], $entry['max'], '<=') &&
  210                           !in_array($release['v'], $entry['x'])) {
  211                         $recommended = $release['v'];
  212                         break;
  213                     }
  214                 }
  215             }
  216             if ($recommended) {
  217                 if ($release['v'] != $recommended) { // if we want a specific
  218                     // version, then skip all others
  219                     continue;
  220                 } else {
  221                     if (!in_array($release['s'], $states)) {
  222                         // the stability is too low, but we must return the
  223                         // recommended version if possible
  224                         return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
  225                     }
  226                 }
  227             }
  228             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
  229                 continue;
  230             }
  231             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
  232                 continue;
  233             }
  234             if ($installed && version_compare($release['v'], $installed, '<')) {
  235                 continue;
  236             }
  237             if (in_array($release['s'], $states)) { // if in the preferred state...
  238                 $found = true; // ... then use it
  239                 break;
  240             }
  241         }
  242         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
  243     }
  244 
  245     /**
  246      * Take raw data and return the array needed for processing a download URL
  247      *
  248      * @param string $base REST base uri
  249      * @param string $package Package name
  250      * @param array $release an array of format array('v' => version, 's' => state)
  251      *                       describing the release to download
  252      * @param array $info list of all releases as defined by allreleases.xml
  253      * @param bool|null $found determines whether the release was found or this is the next
  254      *                    best alternative.  If null, then versions were skipped because
  255      *                    of PHP dependency
  256      * @return array|PEAR_Error
  257      * @access private
  258      */
  259     function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
  260     {
  261         if (!$found) {
  262             $release = $info['r'][0];
  263         }
  264 
  265         $packageLower = strtolower($package);
  266         $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
  267             'info.xml', false, false, $channel);
  268         if (PEAR::isError($pinfo)) {
  269             return PEAR::raiseError('Package "' . $package .
  270                 '" does not have REST info xml available');
  271         }
  272 
  273         $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
  274             $release['v'] . '.xml', false, false, $channel);
  275         if (PEAR::isError($releaseinfo)) {
  276             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
  277                 '" does not have REST xml available');
  278         }
  279 
  280         $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
  281             'deps.' . $release['v'] . '.txt', false, true, $channel);
  282         if (PEAR::isError($packagexml)) {
  283             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
  284                 '" does not have REST dependency information available');
  285         }
  286 
  287         $packagexml = unserialize($packagexml);
  288         if (!$packagexml) {
  289             $packagexml = array();
  290         }
  291 
  292         $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
  293             '/allreleases.xml', false, false, $channel);
  294         if (PEAR::isError($allinfo)) {
  295             return $allinfo;
  296         }
  297 
  298         if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
  299             $allinfo['r'] = array($allinfo['r']);
  300         }
  301 
  302         $compatible = false;
  303         foreach ($allinfo['r'] as $release) {
  304             if ($release['v'] != $releaseinfo['v']) {
  305                 continue;
  306             }
  307 
  308             if (!isset($release['co'])) {
  309                 break;
  310             }
  311 
  312             $compatible = array();
  313             if (!is_array($release['co']) || !isset($release['co'][0])) {
  314                 $release['co'] = array($release['co']);
  315             }
  316 
  317             foreach ($release['co'] as $entry) {
  318                 $comp = array();
  319                 $comp['name']    = $entry['p'];
  320                 $comp['channel'] = $entry['c'];
  321                 $comp['min']     = $entry['min'];
  322                 $comp['max']     = $entry['max'];
  323                 if (isset($entry['x']) && !is_array($entry['x'])) {
  324                     $comp['exclude'] = $entry['x'];
  325                 }
  326 
  327                 $compatible[] = $comp;
  328             }
  329 
  330             if (count($compatible) == 1) {
  331                 $compatible = $compatible[0];
  332             }
  333 
  334             break;
  335         }
  336 
  337         $deprecated = false;
  338         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
  339             if (is_array($pinfo['dp'])) {
  340                 $deprecated = array('channel' => (string) $pinfo['dc'],
  341                                     'package' => trim($pinfo['dp']['_content']));
  342             } else {
  343                 $deprecated = array('channel' => (string) $pinfo['dc'],
  344                                     'package' => trim($pinfo['dp']));
  345             }
  346         }
  347 
  348         $return = array(
  349             'version'    => $releaseinfo['v'],
  350             'info'       => $packagexml,
  351             'package'    => $releaseinfo['p']['_content'],
  352             'stability'  => $releaseinfo['st'],
  353             'compatible' => $compatible,
  354             'deprecated' => $deprecated,
  355         );
  356 
  357         if ($found) {
  358             $return['url'] = $releaseinfo['g'];
  359             return $return;
  360         }
  361 
  362         $return['php'] = $phpversion;
  363         return $return;
  364     }
  365 
  366     function listPackages($base, $channel = false)
  367     {
  368         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
  369         if (PEAR::isError($packagelist)) {
  370             return $packagelist;
  371         }
  372 
  373         if (!is_array($packagelist) || !isset($packagelist['p'])) {
  374             return array();
  375         }
  376 
  377         if (!is_array($packagelist['p'])) {
  378             $packagelist['p'] = array($packagelist['p']);
  379         }
  380 
  381         return $packagelist['p'];
  382     }
  383 
  384     /**
  385      * List all categories of a REST server
  386      *
  387      * @param string $base base URL of the server
  388      * @return array of categorynames
  389      */
  390     function listCategories($base, $channel = false)
  391     {
  392         $categories = array();
  393 
  394         // c/categories.xml does not exist;
  395         // check for every package its category manually
  396         // This is SLOOOWWWW : ///
  397         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
  398         if (PEAR::isError($packagelist)) {
  399             return $packagelist;
  400         }
  401 
  402         if (!is_array($packagelist) || !isset($packagelist['p'])) {
  403             $ret = array();
  404             return $ret;
  405         }
  406 
  407         if (!is_array($packagelist['p'])) {
  408             $packagelist['p'] = array($packagelist['p']);
  409         }
  410 
  411         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  412         foreach ($packagelist['p'] as $package) {
  413                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
  414                 if (PEAR::isError($inf)) {
  415                     PEAR::popErrorHandling();
  416                     return $inf;
  417                 }
  418                 $cat = $inf['ca']['_content'];
  419                 if (!isset($categories[$cat])) {
  420                     $categories[$cat] = $inf['ca'];
  421                 }
  422         }
  423 
  424         return array_values($categories);
  425     }
  426 
  427     /**
  428      * List a category of a REST server
  429      *
  430      * @param string $base base URL of the server
  431      * @param string $category name of the category
  432      * @param boolean $info also download full package info
  433      * @return array of packagenames
  434      */
  435     function listCategory($base, $category, $info = false, $channel = false)
  436     {
  437         // gives '404 Not Found' error when category doesn't exist
  438         $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
  439         if (PEAR::isError($packagelist)) {
  440             return $packagelist;
  441         }
  442 
  443         if (!is_array($packagelist) || !isset($packagelist['p'])) {
  444             return array();
  445         }
  446 
  447         if (!is_array($packagelist['p']) ||
  448             !isset($packagelist['p'][0])) { // only 1 pkg
  449             $packagelist = array($packagelist['p']);
  450         } else {
  451             $packagelist = $packagelist['p'];
  452         }
  453 
  454         if ($info == true) {
  455             // get individual package info
  456             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  457             foreach ($packagelist as $i => $packageitem) {
  458                 $url = sprintf('%s'.'r/%s/latest.txt',
  459                         $base,
  460                         strtolower($packageitem['_content']));
  461                 $version = $this->_rest->retrieveData($url, false, false, $channel);
  462                 if (PEAR::isError($version)) {
  463                     break; // skipit
  464                 }
  465                 $url = sprintf('%s'.'r/%s/%s.xml',
  466                         $base,
  467                         strtolower($packageitem['_content']),
  468                         $version);
  469                 $info = $this->_rest->retrieveData($url, false, false, $channel);
  470                 if (PEAR::isError($info)) {
  471                     break; // skipit
  472                 }
  473                 $packagelist[$i]['info'] = $info;
  474             }
  475             PEAR::popErrorHandling();
  476         }
  477 
  478         return $packagelist;
  479     }
  480 
  481 
  482     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
  483     {
  484         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
  485         if (PEAR::isError($packagelist)) {
  486             return $packagelist;
  487         }
  488         if ($this->_rest->config->get('verbose') > 0) {
  489             $ui = &PEAR_Frontend::singleton();
  490             $ui->log('Retrieving data...0%', true);
  491         }
  492         $ret = array();
  493         if (!is_array($packagelist) || !isset($packagelist['p'])) {
  494             return $ret;
  495         }
  496         if (!is_array($packagelist['p'])) {
  497             $packagelist['p'] = array($packagelist['p']);
  498         }
  499 
  500         // only search-packagename = quicksearch !
  501         if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
  502             $newpackagelist = array();
  503             foreach ($packagelist['p'] as $package) {
  504                 if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
  505                     $newpackagelist[] = $package;
  506                 }
  507             }
  508             $packagelist['p'] = $newpackagelist;
  509         }
  510         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  511         $next = .1;
  512         foreach ($packagelist['p'] as $progress => $package) {
  513             if ($this->_rest->config->get('verbose') > 0) {
  514                 if ($progress / count($packagelist['p']) >= $next) {
  515                     if ($next == .5) {
  516                         $ui->log('50%', false);
  517                     } else {
  518                         $ui->log('.', false);
  519                     }
  520                     $next += .1;
  521                 }
  522             }
  523 
  524             if ($basic) { // remote-list command
  525                 if ($dostable) {
  526                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
  527                         '/stable.txt', false, false, $channel);
  528                 } else {
  529                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
  530                         '/latest.txt', false, false, $channel);
  531                 }
  532                 if (PEAR::isError($latest)) {
  533                     $latest = false;
  534                 }
  535                 $info = array('stable' => $latest);
  536             } else { // list-all command
  537                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
  538                 if (PEAR::isError($inf)) {
  539                     PEAR::popErrorHandling();
  540                     return $inf;
  541                 }
  542                 if ($searchpackage) {
  543                     $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
  544                     if (!$found && !(isset($searchsummary) && !empty($searchsummary)
  545                         && (stristr($inf['s'], $searchsummary) !== false
  546                             || stristr($inf['d'], $searchsummary) !== false)))
  547                     {
  548                         continue;
  549                     };
  550                 }
  551                 $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
  552                     '/allreleases.xml', false, false, $channel);
  553                 if (PEAR::isError($releases)) {
  554                     continue;
  555                 }
  556                 if (!isset($releases['r'][0])) {
  557                     $releases['r'] = array($releases['r']);
  558                 }
  559                 unset($latest);
  560                 unset($unstable);
  561                 unset($stable);
  562                 unset($state);
  563                 foreach ($releases['r'] as $release) {
  564                     if (!isset($latest)) {
  565                         if ($dostable && $release['s'] == 'stable') {
  566                             $latest = $release['v'];
  567                             $state = 'stable';
  568                         }
  569                         if (!$dostable) {
  570                             $latest = $release['v'];
  571                             $state = $release['s'];
  572                         }
  573                     }
  574                     if (!isset($stable) && $release['s'] == 'stable') {
  575                         $stable = $release['v'];
  576                         if (!isset($unstable)) {
  577                             $unstable = $stable;
  578                         }
  579                     }
  580                     if (!isset($unstable) && $release['s'] != 'stable') {
  581                         $latest = $unstable = $release['v'];
  582                         $state = $release['s'];
  583                     }
  584                     if (isset($latest) && !isset($state)) {
  585                         $state = $release['s'];
  586                     }
  587                     if (isset($latest) && isset($stable) && isset($unstable)) {
  588                         break;
  589                     }
  590                 }
  591                 $deps = array();
  592                 if (!isset($unstable)) {
  593                     $unstable = false;
  594                     $state = 'stable';
  595                     if (isset($stable)) {
  596                         $latest = $unstable = $stable;
  597                     }
  598                 } else {
  599                     $latest = $unstable;
  600                 }
  601                 if (!isset($latest)) {
  602                     $latest = false;
  603                 }
  604                 if ($latest) {
  605                     $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
  606                         $latest . '.txt', false, false, $channel);
  607                     if (!PEAR::isError($d)) {
  608                         $d = unserialize($d);
  609                         if ($d) {
  610                             if (isset($d['required'])) {
  611                                 if (!class_exists('PEAR_PackageFile_v2')) {
  612                                     require_once 'PEAR/PackageFile/v2.php';
  613                                 }
  614                                 if (!isset($pf)) {
  615                                     $pf = new PEAR_PackageFile_v2;
  616                                 }
  617                                 $pf->setDeps($d);
  618                                 $tdeps = $pf->getDeps();
  619                             } else {
  620                                 $tdeps = $d;
  621                             }
  622                             foreach ($tdeps as $dep) {
  623                                 if ($dep['type'] !== 'pkg') {
  624                                     continue;
  625                                 }
  626                                 $deps[] = $dep;
  627                             }
  628                         }
  629                     }
  630                 }
  631                 if (!isset($stable)) {
  632                     $stable = '-n/a-';
  633                 }
  634                 if (!$searchpackage) {
  635                     $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
  636                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
  637                         'unstable' => $unstable, 'state' => $state);
  638                 } else {
  639                     $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
  640                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
  641                         'unstable' => $unstable, 'state' => $state);
  642                 }
  643             }
  644             $ret[$package] = $info;
  645         }
  646         PEAR::popErrorHandling();
  647         return $ret;
  648     }
  649 
  650     function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
  651     {
  652         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
  653         if (PEAR::isError($packagelist)) {
  654             return $packagelist;
  655         }
  656 
  657         $ret = array();
  658         if (!is_array($packagelist) || !isset($packagelist['p'])) {
  659             return $ret;
  660         }
  661 
  662         if (!is_array($packagelist['p'])) {
  663             $packagelist['p'] = array($packagelist['p']);
  664         }
  665 
  666         foreach ($packagelist['p'] as $package) {
  667             if (!isset($installed[strtolower($package)])) {
  668                 continue;
  669             }
  670 
  671             $inst_version = $reg->packageInfo($package, 'version', $channel);
  672             $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
  673             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  674             $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
  675                 '/allreleases.xml', false, false, $channel);
  676             PEAR::popErrorHandling();
  677             if (PEAR::isError($info)) {
  678                 continue; // no remote releases
  679             }
  680 
  681             if (!isset($info['r'])) {
  682                 continue;
  683             }
  684 
  685             $release = $found = false;
  686             if (!is_array($info['r']) || !isset($info['r'][0])) {
  687                 $info['r'] = array($info['r']);
  688             }
  689 
  690             // $info['r'] is sorted by version number
  691             usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
  692             foreach ($info['r'] as $release) {
  693                 if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
  694                     // not newer than the one installed
  695                     break;
  696                 }
  697 
  698                 // new version > installed version
  699                 if (!$pref_state) {
  700                     // every state is a good state
  701                     $found = true;
  702                     break;
  703                 } else {
  704                     $new_state = $release['s'];
  705                     // if new state >= installed state: go
  706                     if (in_array($new_state, $this->betterStates($inst_state, true))) {
  707                         $found = true;
  708                         break;
  709                     } else {
  710                         // only allow to lower the state of package,
  711                         // if new state >= preferred state: go
  712                         if (in_array($new_state, $this->betterStates($pref_state, true))) {
  713                             $found = true;
  714                             break;
  715                         }
  716                     }
  717                 }
  718             }
  719 
  720             if (!$found) {
  721                 continue;
  722             }
  723 
  724             $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
  725                 $release['v'] . '.xml', false, false, $channel);
  726             if (PEAR::isError($relinfo)) {
  727                 return $relinfo;
  728             }
  729 
  730             $ret[$package] = array(
  731                 'version'  => $release['v'],
  732                 'state'    => $release['s'],
  733                 'filesize' => $relinfo['f'],
  734             );
  735         }
  736 
  737         return $ret;
  738     }
  739 
  740     function packageInfo($base, $package, $channel = false)
  741     {
  742         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  743         $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
  744         if (PEAR::isError($pinfo)) {
  745             PEAR::popErrorHandling();
  746             return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
  747                 $pinfo->getMessage());
  748         }
  749 
  750         $releases = array();
  751         $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
  752             '/allreleases.xml', false, false, $channel);
  753         if (!PEAR::isError($allreleases)) {
  754             if (!class_exists('PEAR_PackageFile_v2')) {
  755                 require_once 'PEAR/PackageFile/v2.php';
  756             }
  757 
  758             if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
  759                 $allreleases['r'] = array($allreleases['r']);
  760             }
  761 
  762             $pf = new PEAR_PackageFile_v2;
  763             foreach ($allreleases['r'] as $release) {
  764                 $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
  765                     $release['v'] . '.txt', false, false, $channel);
  766                 if (PEAR::isError($ds)) {
  767                     continue;
  768                 }
  769 
  770                 if (!isset($latest)) {
  771                     $latest = $release['v'];
  772                 }
  773 
  774                 $pf->setDeps(unserialize($ds));
  775                 $ds = $pf->getDeps();
  776                 $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
  777                     . '/' . $release['v'] . '.xml', false, false, $channel);
  778 
  779                 if (PEAR::isError($info)) {
  780                     continue;
  781                 }
  782 
  783                 $releases[$release['v']] = array(
  784                     'doneby' => $info['m'],
  785                     'license' => $info['l'],
  786                     'summary' => $info['s'],
  787                     'description' => $info['d'],
  788                     'releasedate' => $info['da'],
  789                     'releasenotes' => $info['n'],
  790                     'state' => $release['s'],
  791                     'deps' => $ds ? $ds : array(),
  792                 );
  793             }
  794         } else {
  795             $latest = '';
  796         }
  797 
  798         PEAR::popErrorHandling();
  799         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
  800             if (is_array($pinfo['dp'])) {
  801                 $deprecated = array('channel' => (string) $pinfo['dc'],
  802                                     'package' => trim($pinfo['dp']['_content']));
  803             } else {
  804                 $deprecated = array('channel' => (string) $pinfo['dc'],
  805                                     'package' => trim($pinfo['dp']));
  806             }
  807         } else {
  808             $deprecated = false;
  809         }
  810 
  811         if (!isset($latest)) {
  812             $latest = '';
  813         }
  814 
  815         return array(
  816             'name' => $pinfo['n'],
  817             'channel' => $pinfo['c'],
  818             'category' => $pinfo['ca']['_content'],
  819             'stable' => $latest,
  820             'license' => $pinfo['l'],
  821             'summary' => $pinfo['s'],
  822             'description' => $pinfo['d'],
  823             'releases' => $releases,
  824             'deprecated' => $deprecated,
  825             );
  826     }
  827 
  828     /**
  829      * Return an array containing all of the states that are more stable than
  830      * or equal to the passed in state
  831      *
  832      * @param string Release state
  833      * @param boolean Determines whether to include $state in the list
  834      * @return false|array False if $state is not a valid release state
  835      */
  836     function betterStates($state, $include = false)
  837     {
  838         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
  839         $i = array_search($state, $states);
  840         if ($i === false) {
  841             return false;
  842         }
  843 
  844         if ($include) {
  845             $i--;
  846         }
  847 
  848         return array_slice($states, $i + 1);
  849     }
  850 
  851     /**
  852      * Sort releases by version number
  853      *
  854      * @access private
  855      */
  856     function _sortReleasesByVersionNumber($a, $b)
  857     {
  858         if (version_compare($a['v'], $b['v'], '=')) {
  859             return 0;
  860         }
  861 
  862         if (version_compare($a['v'], $b['v'], '>')) {
  863             return -1;
  864         }
  865 
  866         if (version_compare($a['v'], $b['v'], '<')) {
  867             return 1;
  868         }
  869     }
  870 }