PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file Package.php

Documentation is available at Package.php

  1. <?php
  2. /**
  3.  * PEAR_Downloader_Package
  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.  * @version    CVS: $Id: Package.php 313023 2011-07-06 19:17:11Z dufuz $
  13.  * @link       http://pear.php.net/package/PEAR
  14.  * @since      File available since Release 1.4.0a1
  15.  */
  16.  
  17. /**
  18.  * Error code when parameter initialization fails because no releases
  19.  * exist within preferred_state, but releases do exist
  20.  */
  21. define('PEAR_DOWNLOADER_PACKAGE_STATE'-1003);
  22. /**
  23.  * Error code when parameter initialization fails because no releases
  24.  * exist that will work with the existing PHP version
  25.  */
  26. define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION'-1004);
  27.  
  28. /**
  29.  * Coordinates download parameters and manages their dependencies
  30.  * prior to downloading them.
  31.  *
  32.  * Input can come from three sources:
  33.  *
  34.  * - local files (archives or package.xml)
  35.  * - remote files (downloadable urls)
  36.  * - abstract package names
  37.  *
  38.  * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
  39.  * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
  40.  * format returned of dependencies is slightly different from that used in package.xml.
  41.  *
  42.  * This class hides the differences between these elements, and makes automatic
  43.  * dependency resolution a piece of cake.  It also manages conflicts when
  44.  * two classes depend on incompatible dependencies, or differing versions of the same
  45.  * package dependency.  In addition, download will not be attempted if the php version is
  46.  * not supported, PEAR installer version is not supported, or non-PECL extensions are not
  47.  * installed.
  48.  * @category   pear
  49.  * @package    PEAR
  50.  * @author     Greg Beaver <cellog@php.net>
  51.  * @copyright  1997-2009 The Authors
  52.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  53.  * @version    Release: 1.9.4
  54.  * @link       http://pear.php.net/package/PEAR
  55.  * @since      Class available since Release 1.4.0a1
  56.  */
  57. {
  58.     /**
  59.      * @var PEAR_Downloader 
  60.      */
  61.     var $_downloader;
  62.     /**
  63.      * @var PEAR_Config 
  64.      */
  65.     var $_config;
  66.     /**
  67.      * @var PEAR_Registry 
  68.      */
  69.     var $_registry;
  70.     /**
  71.      * Used to implement packagingroot properly
  72.      * @var PEAR_Registry 
  73.      */
  74.     var $_installRegistry;
  75.     /**
  76.      * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
  77.      */
  78.     var $_packagefile;
  79.     /**
  80.      * @var array 
  81.      */
  82.     var $_parsedname;
  83.     /**
  84.      * @var array 
  85.      */
  86.     var $_downloadURL;
  87.     /**
  88.      * @var array 
  89.      */
  90.     var $_downloadDeps = array();
  91.     /**
  92.      * @var boolean 
  93.      */
  94.     var $_valid = false;
  95.     /**
  96.      * @var boolean 
  97.      */
  98.     var $_analyzed = false;
  99.     /**
  100.      * if this or a parent package was invoked with Package-state, this is set to the
  101.      * state variable.
  102.      *
  103.      * This allows temporary reassignment of preferred_state for a parent package and all of
  104.      * its dependencies.
  105.      * @var string|false
  106.      */
  107.     var $_explicitState = false;
  108.     /**
  109.      * If this package is invoked with Package#group, this variable will be true
  110.      */
  111.     var $_explicitGroup = false;
  112.     /**
  113.      * Package type local|url
  114.      * @var string 
  115.      */
  116.     var $_type;
  117.     /**
  118.      * Contents of package.xml, if downloaded from a remote channel
  119.      * @var string|false
  120.      * @access private
  121.      */
  122.     var $_rawpackagefile;
  123.     /**
  124.      * @var boolean 
  125.      * @access private
  126.      */
  127.     var $_validated = false;
  128.  
  129.     /**
  130.      * @param PEAR_Downloader 
  131.      */
  132.     function PEAR_Downloader_Package(&$downloader)
  133.     {
  134.         $this->_downloader &$downloader;
  135.         $this->_config &$this->_downloader->config;
  136.         $this->_registry &$this->_config->getRegistry();
  137.         $options $downloader->getOptions();
  138.         if (isset($options['packagingroot'])) {
  139.             $this->_config->setInstallRoot($options['packagingroot']);
  140.             $this->_installRegistry &$this->_config->getRegistry();
  141.             $this->_config->setInstallRoot(false);
  142.         else {
  143.             $this->_installRegistry &$this->_registry;
  144.         }
  145.         $this->_valid $this->_analyzed = false;
  146.     }
  147.  
  148.     /**
  149.      * Parse the input and determine whether this is a local file, a remote uri, or an
  150.      * abstract package name.
  151.      *
  152.      * This is the heart of the PEAR_Downloader_Package(), and is used in
  153.      * {@link PEAR_Downloader::download()}
  154.      * @param string 
  155.      * @return bool|PEAR_Error
  156.      */
  157.     function initialize($param)
  158.     {
  159.         $origErr $this->_fromFile($param);
  160.         if ($this->_valid{
  161.             return true;
  162.         }
  163.  
  164.         $options $this->_downloader->getOptions();
  165.         if (isset($options['offline'])) {
  166.             if (PEAR::isError($origErr&& !isset($options['soft'])) {
  167.                 foreach ($origErr->getUserInfo(as $userInfo{
  168.                     if (isset($userInfo['message'])) {
  169.                         $this->_downloader->log(0$userInfo['message']);
  170.                     }
  171.                 }
  172.  
  173.                 $this->_downloader->log(0$origErr->getMessage());
  174.             }
  175.  
  176.             return PEAR::raiseError('Cannot download non-local package "' $param '"');
  177.         }
  178.  
  179.         $err $this->_fromUrl($param);
  180.         if (PEAR::isError($err|| !$this->_valid{
  181.             if ($this->_type == 'url'{
  182.                 if (PEAR::isError($err&& !isset($options['soft'])) {
  183.                     $this->_downloader->log(0$err->getMessage());
  184.                 }
  185.  
  186.                 return PEAR::raiseError("Invalid or missing remote package file");
  187.             }
  188.  
  189.             $err $this->_fromString($param);
  190.             if (PEAR::isError($err|| !$this->_valid{
  191.                 if (PEAR::isError($err&& $err->getCode(== PEAR_DOWNLOADER_PACKAGE_STATE{
  192.                     return false; // instruct the downloader to silently skip
  193.                 }
  194.  
  195.                 if (isset($this->_type&& $this->_type == 'local' && PEAR::isError($origErr)) {
  196.                     if (is_array($origErr->getUserInfo())) {
  197.                         foreach ($origErr->getUserInfo(as $err{
  198.                             if (is_array($err)) {
  199.                                 $err $err['message'];
  200.                             }
  201.  
  202.                             if (!isset($options['soft'])) {
  203.                                 $this->_downloader->log(0$err);
  204.                             }
  205.                         }
  206.                     }
  207.  
  208.                     if (!isset($options['soft'])) {
  209.                         $this->_downloader->log(0$origErr->getMessage());
  210.                     }
  211.  
  212.                     if (is_array($param)) {
  213.                         $param $this->_registry->parsedPackageNameToString($paramtrue);
  214.                     }
  215.  
  216.                     if (!isset($options['soft'])) {
  217.                         $this->_downloader->log(2"Cannot initialize '$param', invalid or missing package file");
  218.                     }
  219.  
  220.                     // Passing no message back - already logged above
  221.                     return PEAR::raiseError();
  222.                 }
  223.  
  224.                 if (PEAR::isError($err&& !isset($options['soft'])) {
  225.                     $this->_downloader->log(0$err->getMessage());
  226.                 }
  227.  
  228.                 if (is_array($param)) {
  229.                     $param $this->_registry->parsedPackageNameToString($paramtrue);
  230.                 }
  231.  
  232.                 if (!isset($options['soft'])) {
  233.                     $this->_downloader->log(2"Cannot initialize '$param', invalid or missing package file");
  234.                 }
  235.  
  236.                 // Passing no message back - already logged above
  237.                 return PEAR::raiseError();
  238.             }
  239.         }
  240.  
  241.         return true;
  242.     }
  243.  
  244.     /**
  245.      * Retrieve any non-local packages
  246.      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
  247.      */
  248.     function &download()
  249.     {
  250.         if (isset($this->_packagefile)) {
  251.             return $this->_packagefile;
  252.         }
  253.  
  254.         if (isset($this->_downloadURL['url'])) {
  255.             $this->_isvalid = false;
  256.             $info $this->getParsedPackage();
  257.             foreach ($info as $i => $p{
  258.                 $info[$istrtolower($p);
  259.             }
  260.  
  261.             $err $this->_fromUrl($this->_downloadURL['url'],
  262.                 $this->_registry->parsedPackageNameToString($this->_parsednametrue));
  263.             $newinfo $this->getParsedPackage();
  264.             foreach ($newinfo as $i => $p{
  265.                 $newinfo[$istrtolower($p);
  266.             }
  267.  
  268.             if ($info != $newinfo{
  269.                 do {
  270.                     if ($info['channel'== 'pecl.php.net' && $newinfo['channel'== 'pear.php.net'{
  271.                         $info['channel''pear.php.net';
  272.                         if ($info == $newinfo{
  273.                             // skip the channel check if a pecl package says it's a PEAR package
  274.                             break;
  275.                         }
  276.                     }
  277.                     if ($info['channel'== 'pear.php.net' && $newinfo['channel'== 'pecl.php.net'{
  278.                         $info['channel''pecl.php.net';
  279.                         if ($info == $newinfo{
  280.                             // skip the channel check if a pecl package says it's a PEAR package
  281.                             break;
  282.                         }
  283.                     }
  284.  
  285.                     return PEAR::raiseError('CRITICAL ERROR: We are ' .
  286.                         $this->_registry->parsedPackageNameToString($info', but the file ' .
  287.                         'downloaded claims to be ' .
  288.                         $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
  289.                 while (false);
  290.             }
  291.  
  292.             if (PEAR::isError($err|| !$this->_valid{
  293.                 return $err;
  294.             }
  295.         }
  296.  
  297.         $this->_type 'local';
  298.         return $this->_packagefile;
  299.     }
  300.  
  301.     function &getPackageFile()
  302.     {
  303.         return $this->_packagefile;
  304.     }
  305.  
  306.     function &getDownloader()
  307.     {
  308.         return $this->_downloader;
  309.     }
  310.  
  311.     function getType()
  312.     {
  313.         return $this->_type;
  314.     }
  315.  
  316.     /**
  317.      * Like {@link initialize()}, but operates on a dependency
  318.      */
  319.     function fromDepURL($dep)
  320.     {
  321.         $this->_downloadURL $dep;
  322.         if (isset($dep['uri'])) {
  323.             $options $this->_downloader->getOptions();
  324.             if (!extension_loaded("zlib"|| isset($options['nocompress'])) {
  325.                 $ext '.tar';
  326.             else {
  327.                 $ext '.tgz';
  328.             }
  329.  
  330.             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  331.             $err $this->_fromUrl($dep['uri'$ext);
  332.             PEAR::popErrorHandling();
  333.             if (PEAR::isError($err)) {
  334.                 if (!isset($options['soft'])) {
  335.                     $this->_downloader->log(0$err->getMessage());
  336.                 }
  337.  
  338.                 return PEAR::raiseError('Invalid uri dependency "' $dep['uri'$ext '", ' .
  339.                     'cannot download');
  340.             }
  341.         else {
  342.             $this->_parsedname =
  343.                 array(
  344.                     'package' => $dep['info']->getPackage(),
  345.                     'channel' => $dep['info']->getChannel(),
  346.                     'version' => $dep['version']
  347.                 );
  348.             if (!isset($dep['nodefault'])) {
  349.                 $this->_parsedname['group''default'// download the default dependency group
  350.                 $this->_explicitGroup = false;
  351.             }
  352.  
  353.             $this->_rawpackagefile $dep['raw'];
  354.         }
  355.     }
  356.  
  357.     function detectDependencies($params)
  358.     {
  359.         $options $this->_downloader->getOptions();
  360.         if (isset($options['downloadonly'])) {
  361.             return;
  362.         }
  363.  
  364.         if (isset($options['offline'])) {
  365.             $this->_downloader->log(3'Skipping dependency download check, --offline specified');
  366.             return;
  367.         }
  368.  
  369.         $pname $this->getParsedPackage();
  370.         if (!$pname{
  371.             return;
  372.         }
  373.  
  374.         $deps $this->getDeps();
  375.         if (!$deps{
  376.             return;
  377.         }
  378.  
  379.         if (isset($deps['required'])) // package.xml 2.0
  380.             return $this->_detect2($deps$pname$options$params);
  381.         }
  382.  
  383.         return $this->_detect1($deps$pname$options$params);
  384.     }
  385.  
  386.     function setValidated()
  387.     {
  388.         $this->_validated = true;
  389.     }
  390.  
  391.     function alreadyValidated()
  392.     {
  393.         return $this->_validated;
  394.     }
  395.  
  396.     /**
  397.      * Remove packages to be downloaded that are already installed
  398.      * @param array of PEAR_Downloader_Package objects
  399.      * @static
  400.      */
  401.     function removeInstalled(&$params)
  402.     {
  403.         if (!isset($params[0])) {
  404.             return;
  405.         }
  406.  
  407.         $options $params[0]->_downloader->getOptions();
  408.         if (!isset($options['downloadonly'])) {
  409.             foreach ($params as $i => $param{
  410.                 $package $param->getPackage();
  411.                 $channel $param->getChannel();
  412.                 // remove self if already installed with this version
  413.                 // this does not need any pecl magic - we only remove exact matches
  414.                 if ($param->_installRegistry->packageExists($package$channel)) {
  415.                     $packageVersion $param->_installRegistry->packageInfo($package'version'$channel);
  416.                     if (version_compare($packageVersion$param->getVersion()'==')) {
  417.                         if (!isset($options['force'])) {
  418.                             $info $param->getParsedPackage();
  419.                             unset($info['version']);
  420.                             unset($info['state']);
  421.                             if (!isset($options['soft'])) {
  422.                                 $param->_downloader->log(1'Skipping package "' .
  423.                                     $param->getShortName(.
  424.                                     '", already installed as version ' $packageVersion);
  425.                             }
  426.                             $params[$i= false;
  427.                         }
  428.                     elseif (!isset($options['force']&& !isset($options['upgrade']&&
  429.                           !isset($options['soft'])) {
  430.                         $info $param->getParsedPackage();
  431.                         $param->_downloader->log(1'Skipping package "' .
  432.                             $param->getShortName(.
  433.                             '", already installed as version ' $packageVersion);
  434.                         $params[$i= false;
  435.                     }
  436.                 }
  437.             }
  438.         }
  439.  
  440.         PEAR_Downloader_Package::removeDuplicates($params);
  441.     }
  442.  
  443.     function _detect2($deps$pname$options$params)
  444.     {
  445.         $this->_downloadDeps = array();
  446.         $groupnotfound = false;
  447.         foreach (array('package''subpackage'as $packagetype{
  448.             // get required dependency group
  449.             if (isset($deps['required'][$packagetype])) {
  450.                 if (isset($deps['required'][$packagetype][0])) {
  451.                     foreach ($deps['required'][$packagetypeas $dep{
  452.                         if (isset($dep['conflicts'])) {
  453.                             // skip any package that this package conflicts with
  454.                             continue;
  455.                         }
  456.                         $ret $this->_detect2Dep($dep$pname'required'$params);
  457.                         if (is_array($ret)) {
  458.                             $this->_downloadDeps[$ret;
  459.                         elseif (PEAR::isError($ret&& !isset($options['soft'])) {
  460.                             $this->_downloader->log(0$ret->getMessage());
  461.                         }
  462.                     }
  463.                 else {
  464.                     $dep $deps['required'][$packagetype];
  465.                     if (!isset($dep['conflicts'])) {
  466.                         // skip any package that this package conflicts with
  467.                         $ret $this->_detect2Dep($dep$pname'required'$params);
  468.                         if (is_array($ret)) {
  469.                             $this->_downloadDeps[$ret;
  470.                         elseif (PEAR::isError($ret&& !isset($options['soft'])) {
  471.                             $this->_downloader->log(0$ret->getMessage());
  472.                         }
  473.                     }
  474.                 }
  475.             }
  476.  
  477.             // get optional dependency group, if any
  478.             if (isset($deps['optional'][$packagetype])) {
  479.                 $skipnames = array();
  480.                 if (!isset($deps['optional'][$packagetype][0])) {
  481.                     $deps['optional'][$packagetype= array($deps['optional'][$packagetype]);
  482.                 }
  483.  
  484.                 foreach ($deps['optional'][$packagetypeas $dep{
  485.                     $skip = false;
  486.                     if (!isset($options['alldeps'])) {
  487.                         $dep['package'$dep['name'];
  488.                         if (!isset($options['soft'])) {
  489.                             $this->_downloader->log(3'Notice: package "' .
  490.                               $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
  491.                                     true'" optional dependency "' .
  492.                                 $this->_registry->parsedPackageNameToString(array('package' =>
  493.                                     $dep['name']'channel' => 'pear.php.net')true.
  494.                                 '" will not be automatically downloaded');
  495.                         }
  496.                         $skipnames[$this->_registry->parsedPackageNameToString($deptrue);
  497.                         $skip = true;
  498.                         unset($dep['package']);
  499.                     }
  500.  
  501.                     $ret $this->_detect2Dep($dep$pname'optional'$params);
  502.                     if (PEAR::isError($ret&& !isset($options['soft'])) {
  503.                         $this->_downloader->log(0$ret->getMessage());
  504.                     }
  505.  
  506.                     if (!$ret{
  507.                         $dep['package'$dep['name'];
  508.                         $skip count($skipnames?
  509.                             $skipnames[count($skipnames- 1'';
  510.                         if ($skip ==
  511.                               $this->_registry->parsedPackageNameToString($deptrue)) {
  512.                             array_pop($skipnames);
  513.                         }
  514.                     }
  515.  
  516.                     if (!$skip && is_array($ret)) {
  517.                         $this->_downloadDeps[$ret;
  518.                     }
  519.                 }
  520.  
  521.                 if (count($skipnames)) {
  522.                     if (!isset($options['soft'])) {
  523.                         $this->_downloader->log(1'Did not download optional dependencies: ' .
  524.                             implode(', '$skipnames.
  525.                             ', use --alldeps to download automatically');
  526.                     }
  527.                 }
  528.             }
  529.  
  530.             // get requested dependency group, if any
  531.             $groupname $this->getGroup();
  532.             $explicit  $this->_explicitGroup;
  533.             if (!$groupname{
  534.                 if (!$this->canDefault()) {
  535.                     continue;
  536.                 }
  537.  
  538.                 $groupname 'default'// try the default dependency group
  539.             }
  540.  
  541.             if ($groupnotfound{
  542.                 continue;
  543.             }
  544.  
  545.             if (isset($deps['group'])) {
  546.                 if (isset($deps['group']['attribs'])) {
  547.                     if (strtolower($deps['group']['attribs']['name']== strtolower($groupname)) {
  548.                         $group $deps['group'];
  549.                     elseif ($explicit{
  550.                         if (!isset($options['soft'])) {
  551.                             $this->_downloader->log(0'Warning: package "' .
  552.                                 $this->_registry->parsedPackageNameToString($pnametrue.
  553.                                 '" has no dependency ' 'group named "' $groupname '"');
  554.                         }
  555.  
  556.                         $groupnotfound = true;
  557.                         continue;
  558.                     }
  559.                 else {
  560.                     $found = false;
  561.                     foreach ($deps['group'as $group{
  562.                         if (strtolower($group['attribs']['name']== strtolower($groupname)) {
  563.                             $found = true;
  564.                             break;
  565.                         }
  566.                     }
  567.  
  568.                     if (!$found{
  569.                         if ($explicit{
  570.                             if (!isset($options['soft'])) {
  571.                                 $this->_downloader->log(0'Warning: package "' .
  572.                                     $this->_registry->parsedPackageNameToString($pnametrue.
  573.                                     '" has no dependency ' 'group named "' $groupname '"');
  574.                             }
  575.                         }
  576.  
  577.                         $groupnotfound = true;
  578.                         continue;
  579.                     }
  580.                 }
  581.             }
  582.  
  583.             if (isset($group&& isset($group[$packagetype])) {
  584.                 if (isset($group[$packagetype][0])) {
  585.                     foreach ($group[$packagetypeas $dep{
  586.                         $ret $this->_detect2Dep($dep$pname'dependency group "' .
  587.                             $group['attribs']['name''"'$params);
  588.                         if (is_array($ret)) {
  589.                             $this->_downloadDeps[$ret;
  590.                         elseif (PEAR::isError($ret&& !isset($options['soft'])) {
  591.                             $this->_downloader->log(0$ret->getMessage());
  592.                         }
  593.                     }
  594.                 else {
  595.                     $ret $this->_detect2Dep($group[$packagetype]$pname,
  596.                         'dependency group "' .
  597.                         $group['attribs']['name''"'$params);
  598.                     if (is_array($ret)) {
  599.                         $this->_downloadDeps[$ret;
  600.                     elseif (PEAR::isError($ret&& !isset($options['soft'])) {
  601.                         $this->_downloader->log(0$ret->getMessage());
  602.                     }
  603.                 }
  604.             }
  605.         }
  606.     }
  607.  
  608.     function _detect2Dep($dep$pname$group$params)
  609.     {
  610.         if (isset($dep['conflicts'])) {
  611.             return true;
  612.         }
  613.  
  614.         $options $this->_downloader->getOptions();
  615.         if (isset($dep['uri'])) {
  616.             return array('uri' => $dep['uri']'dep' => $dep);;
  617.         }
  618.  
  619.         $testdep $dep;
  620.         $testdep['package'$dep['name'];
  621.         if (PEAR_Downloader_Package::willDownload($testdep$params)) {
  622.             $dep['package'$dep['name'];
  623.             if (!isset($options['soft'])) {
  624.                 $this->_downloader->log(2$this->getShortName(': Skipping ' $group .
  625.                     ' dependency "' .
  626.                     $this->_registry->parsedPackageNameToString($deptrue.
  627.                     '", will be installed');
  628.             }
  629.             return false;
  630.         }
  631.  
  632.         $options $this->_downloader->getOptions();
  633.         if ($this->_explicitState{
  634.             $pname['state'$this->_explicitState;
  635.         }
  636.  
  637.         $url $this->_downloader->_getDepPackageDownloadUrl($dep$pname);
  638.         if (PEAR::isError($url)) {
  639.             PEAR::popErrorHandling();
  640.             return $url;
  641.         }
  642.  
  643.         $dep['package'$dep['name'];
  644.         $ret $this->_analyzeDownloadURL($url'dependency'$dep$params$group == 'optional' &&
  645.             !isset($options['alldeps'])true);
  646.         PEAR::popErrorHandling();
  647.         if (PEAR::isError($ret)) {
  648.             if (!isset($options['soft'])) {
  649.                 $this->_downloader->log(0$ret->getMessage());
  650.             }
  651.  
  652.             return false;
  653.         }
  654.  
  655.         // check to see if a dep is already installed and is the same or newer
  656.         if (!isset($dep['min']&& !isset($dep['max']&& !isset($dep['recommended'])) {
  657.             $oper 'has';
  658.         else {
  659.             $oper 'gt';
  660.         }
  661.  
  662.         // do not try to move this before getDepPackageDownloadURL
  663.         // we can't determine whether upgrade is necessary until we know what
  664.         // version would be downloaded
  665.         if (!isset($options['force']&& $this->isInstalled($ret$oper)) {
  666.             $version $this->_installRegistry->packageInfo($dep['name']'version'$dep['channel']);
  667.             $dep['package'$dep['name'];
  668.             if (!isset($options['soft'])) {
  669.                 $this->_downloader->log(3$this->getShortName(': Skipping ' $group .
  670.                     ' dependency "' .
  671.                 $this->_registry->parsedPackageNameToString($deptrue.
  672.                     '" version ' $url['version'', already installed as version ' .
  673.                     $version);
  674.             }
  675.  
  676.             return false;
  677.         }
  678.  
  679.         if (isset($dep['nodefault'])) {
  680.             $ret['nodefault'= true;
  681.         }
  682.  
  683.         return $ret;
  684.     }
  685.  
  686.     function _detect1($deps$pname$options$params)
  687.     {
  688.         $this->_downloadDeps = array();
  689.         $skipnames = array();
  690.         foreach ($deps as $dep{
  691.             $nodownload = false;
  692.             if (isset ($dep['type']&& $dep['type'=== 'pkg'{
  693.                 $dep['channel''pear.php.net';
  694.                 $dep['package'$dep['name'];
  695.                 switch ($dep['rel']{
  696.                     case 'not' :
  697.                         continue 2;
  698.                     case 'ge' :
  699.                     case 'eq' :
  700.                     case 'gt' :
  701.                     case 'has' :
  702.                         $group (!isset($dep['optional']|| $dep['optional'== 'no'?
  703.                             'required' :
  704.                             'optional';
  705.                         if (PEAR_Downloader_Package::willDownload($dep$params)) {
  706.                             $this->_downloader->log(2$this->getShortName(': Skipping ' $group
  707.                                 . ' dependency "' .
  708.                                 $this->_registry->parsedPackageNameToString($deptrue.
  709.                                 '", will be installed');
  710.                             continue 2;
  711.                         }
  712.                         $fakedp = new PEAR_PackageFile_v1;
  713.                         $fakedp->setPackage($dep['name']);
  714.                         // skip internet check if we are not upgrading (bug #5810)
  715.                         if (!isset($options['upgrade']&& $this->isInstalled(
  716.                               $fakedp$dep['rel'])) {
  717.                             $this->_downloader->log(2$this->getShortName(': Skipping ' $group
  718.                                 . ' dependency "' .
  719.                                 $this->_registry->parsedPackageNameToString($deptrue.
  720.                                 '", is already installed');
  721.                             continue 2;
  722.                         }
  723.                 }
  724.  
  725.                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  726.                 if ($this->_explicitState{
  727.                     $pname['state'$this->_explicitState;
  728.                 }
  729.  
  730.                 $url $this->_downloader->_getDepPackageDownloadUrl($dep$pname);
  731.                 $chan 'pear.php.net';
  732.                 if (PEAR::isError($url)) {
  733.                     // check to see if this is a pecl package that has jumped
  734.                     // from pear.php.net to pecl.php.net channel
  735.                     if (!class_exists('PEAR_Dependency2')) {
  736.                         require_once 'PEAR/Dependency2.php';
  737.                     }
  738.  
  739.                     $newdep PEAR_Dependency2::normalizeDep($dep);
  740.                     $newdep $newdep[0];
  741.                     $newdep['channel''pecl.php.net';
  742.                     $chan 'pecl.php.net';
  743.                     $url $this->_downloader->_getDepPackageDownloadUrl($newdep$pname);
  744.                     $obj &$this->_installRegistry->getPackage($dep['name']);
  745.                     if (PEAR::isError($url)) {
  746.                         PEAR::popErrorHandling();
  747.                         if ($obj !== null && $this->isInstalled($obj$dep['rel'])) {
  748.                             $group (!isset($dep['optional']|| $dep['optional'== 'no'?
  749.                                 'required' :
  750.                                 'optional';
  751.                             $dep['package'$dep['name'];
  752.                             if (!isset($options['soft'])) {
  753.                                 $this->_downloader->log(3$this->getShortName(.
  754.                                     ': Skipping ' $group ' dependency "' .
  755.                                     $this->_registry->parsedPackageNameToString($deptrue.
  756.                                     '", already installed as version ' $obj->getVersion());
  757.                             }
  758.                             $skip count($skipnames?
  759.                                 $skipnames[count($skipnames- 1'';
  760.                             if ($skip ==
  761.                                   $this->_registry->parsedPackageNameToString($deptrue)) {
  762.                                 array_pop($skipnames);
  763.                             }
  764.                             continue;
  765.                         else {
  766.                             if (isset($dep['optional']&& $dep['optional'== 'yes'{
  767.                                 $this->_downloader->log(2$this->getShortName(.
  768.                                     ': Skipping optional dependency "' .
  769.                                     $this->_registry->parsedPackageNameToString($deptrue.
  770.                                     '", no releases exist');
  771.                                 continue;
  772.                             else {
  773.                                 return $url;
  774.                             }
  775.                         }
  776.                     }
  777.                 }
  778.  
  779.                 PEAR::popErrorHandling();
  780.                 if (!isset($options['alldeps'])) {
  781.                     if (isset($dep['optional']&& $dep['optional'== 'yes'{
  782.                         if (!isset($options['soft'])) {
  783.                             $this->_downloader->log(3'Notice: package "' .
  784.                                 $this->getShortName(.
  785.                                 '" optional dependency "' .
  786.                                 $this->_registry->parsedPackageNameToString(
  787.                                     array('channel' => $chan'package' =>
  788.                                     $dep['name'])true.
  789.                                 '" will not be automatically downloaded');
  790.                         }
  791.                         $skipnames[$this->_registry->parsedPackageNameToString(
  792.                                 array('channel' => $chan'package' =>
  793.                                 $dep['name'])true);
  794.                         $nodownload = true;
  795.                     }
  796.                 }
  797.  
  798.                 if (!isset($options['alldeps']&& !isset($options['onlyreqdeps'])) {
  799.                     if (!isset($dep['optional']|| $dep['optional'== 'no'{
  800.                         if (!isset($options['soft'])) {
  801.                             $this->_downloader->log(3'Notice: package "' .
  802.                                 $this->getShortName(.
  803.                                 '" required dependency "' .
  804.                                 $this->_registry->parsedPackageNameToString(
  805.                                     array('channel' => $chan'package' =>
  806.                                     $dep['name'])true.
  807.                                 '" will not be automatically downloaded');
  808.                         }
  809.                         $skipnames[$this->_registry->parsedPackageNameToString(
  810.                                 array('channel' => $chan'package' =>
  811.                                 $dep['name'])true);
  812.                         $nodownload = true;
  813.                     }
  814.                 }
  815.  
  816.                 // check to see if a dep is already installed
  817.                 // do not try to move this before getDepPackageDownloadURL
  818.                 // we can't determine whether upgrade is necessary until we know what
  819.                 // version would be downloaded
  820.                 if (!isset($options['force']&& $this->isInstalled(
  821.                         $url$dep['rel'])) {
  822.                     $group (!isset($dep['optional']|| $dep['optional'== 'no'?
  823.                         'required' :
  824.                         'optional';
  825.                     $dep['package'$dep['name'];
  826.                     if (isset($newdep)) {
  827.                         $version $this->_installRegistry->packageInfo($newdep['name']'version'$newdep['channel']);
  828.                     else {
  829.                         $version $this->_installRegistry->packageInfo($dep['name']'version');
  830.                     }
  831.  
  832.                     $dep['version'$url['version'];
  833.                     if (!isset($options['soft'])) {
  834.                         $this->_downloader->log(3$this->getShortName(': Skipping ' $group .
  835.                             ' dependency "' .
  836.                             $this->_registry->parsedPackageNameToString($deptrue.
  837.                             '", already installed as version ' $version);
  838.                     }
  839.  
  840.                     $skip count($skipnames?
  841.                         $skipnames[count($skipnames- 1'';
  842.                     if ($skip ==
  843.                           $this->_registry->parsedPackageNameToString($deptrue)) {
  844.                         array_pop($skipnames);
  845.                     }
  846.  
  847.                     continue;
  848.                 }
  849.  
  850.                 if ($nodownload{
  851.                     continue;
  852.                 }
  853.  
  854.                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  855.                 if (isset($newdep)) {
  856.                     $dep $newdep;
  857.                 }
  858.  
  859.                 $dep['package'$dep['name'];
  860.                 $ret $this->_analyzeDownloadURL($url'dependency'$dep$params,
  861.                     isset($dep['optional']&& $dep['optional'== 'yes' &&
  862.                     !isset($options['alldeps'])true);
  863.                 PEAR::popErrorHandling();
  864.                 if (PEAR::isError($ret)) {
  865.                     if (!isset($options['soft'])) {
  866.                         $this->_downloader->log(0$ret->getMessage());
  867.                     }
  868.                     continue;
  869.                 }
  870.  
  871.                 $this->_downloadDeps[$ret;
  872.             }
  873.         }
  874.  
  875.         if (count($skipnames)) {
  876.             if (!isset($options['soft'])) {
  877.                 $this->_downloader->log(1'Did not download dependencies: ' .
  878.                     implode(', '$skipnames.
  879.                     ', use --alldeps or --onlyreqdeps to download automatically');
  880.             }
  881.         }
  882.     }
  883.  
  884.     function setDownloadURL($pkg)
  885.     {
  886.         $this->_downloadURL $pkg;
  887.     }
  888.  
  889.     /**
  890.      * Set the package.xml object for this downloaded package
  891.      *
  892.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2$pkg 
  893.      */
  894.     function setPackageFile(&$pkg)
  895.     {
  896.         $this->_packagefile &$pkg;
  897.     }
  898.  
  899.     function getShortName()
  900.     {
  901.         return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
  902.             'package' => $this->getPackage())true);
  903.     }
  904.  
  905.     function getParsedPackage()
  906.     {
  907.         if (isset($this->_packagefile|| isset($this->_parsedname)) {
  908.             return array('channel' => $this->getChannel(),
  909.                 'package' => $this->getPackage(),
  910.                 'version' => $this->getVersion());
  911.         }
  912.  
  913.         return false;
  914.     }
  915.  
  916.     function getDownloadURL()
  917.     {
  918.         return $this->_downloadURL;
  919.     }
  920.  
  921.     function canDefault()
  922.     {
  923.         if (isset($this->_downloadURL&& isset($this->_downloadURL['nodefault'])) {
  924.             return false;
  925.         }
  926.  
  927.         return true;
  928.     }
  929.  
  930.     function getPackage()
  931.     {
  932.         if (isset($this->_packagefile)) {
  933.             return $this->_packagefile->getPackage();
  934.         elseif (isset($this->_downloadURL['info'])) {
  935.             return $this->_downloadURL['info']->getPackage();
  936.         }
  937.  
  938.         return false;
  939.     }
  940.  
  941.     /**
  942.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  943.      */
  944.     function isSubpackage(&$pf)
  945.     {
  946.         if (isset($this->_packagefile)) {
  947.             return $this->_packagefile->isSubpackage($pf);
  948.         elseif (isset($this->_downloadURL['info'])) {
  949.             return $this->_downloadURL['info']->isSubpackage($pf);
  950.         }
  951.  
  952.         return false;
  953.     }
  954.  
  955.     function getPackageType()
  956.     {
  957.         if (isset($this->_packagefile)) {
  958.             return $this->_packagefile->getPackageType();
  959.         elseif (isset($this->_downloadURL['info'])) {
  960.             return $this->_downloadURL['info']->getPackageType();
  961.         }
  962.  
  963.         return false;
  964.     }
  965.  
  966.     function isBundle()
  967.     {
  968.         if (isset($this->_packagefile)) {
  969.             return $this->_packagefile->getPackageType(== 'bundle';
  970.         }
  971.  
  972.         return false;
  973.     }
  974.  
  975.     function getPackageXmlVersion()
  976.     {
  977.         if (isset($this->_packagefile)) {
  978.             return $this->_packagefile->getPackagexmlVersion();
  979.         elseif (isset($this->_downloadURL['info'])) {
  980.             return $this->_downloadURL['info']->getPackagexmlVersion();
  981.         }
  982.  
  983.         return '1.0';
  984.     }
  985.  
  986.     function getChannel()
  987.     {
  988.         if (isset($this->_packagefile)) {
  989.             return $this->_packagefile->getChannel();
  990.         elseif (isset($this->_downloadURL['info'])) {
  991.             return $this->_downloadURL['info']->getChannel();
  992.         }
  993.  
  994.         return false;
  995.     }
  996.  
  997.     function getURI()
  998.     {
  999.         if (isset($this->_packagefile)) {
  1000.             return $this->_packagefile->getURI();
  1001.         elseif (isset($this->_downloadURL['info'])) {
  1002.             return $this->_downloadURL['info']->getURI();
  1003.         }
  1004.  
  1005.         return false;
  1006.     }
  1007.  
  1008.     function getVersion()
  1009.     {
  1010.         if (isset($this->_packagefile)) {
  1011.             return $this->_packagefile->getVersion();
  1012.         elseif (isset($this->_downloadURL['version'])) {
  1013.             return $this->_downloadURL['version'];
  1014.         }
  1015.  
  1016.         return false;
  1017.     }
  1018.  
  1019.     function isCompatible($pf)
  1020.     {
  1021.         if (isset($this->_packagefile)) {
  1022.             return $this->_packagefile->isCompatible($pf);
  1023.         elseif (isset($this->_downloadURL['info'])) {
  1024.             return $this->_downloadURL['info']->isCompatible($pf);
  1025.         }
  1026.  
  1027.         return true;
  1028.     }
  1029.  
  1030.     function setGroup($group)
  1031.     {
  1032.         $this->_parsedname['group'$group;
  1033.     }
  1034.  
  1035.     function getGroup()
  1036.     {
  1037.         if (isset($this->_parsedname['group'])) {
  1038.             return $this->_parsedname['group'];
  1039.         }
  1040.  
  1041.         return '';
  1042.     }
  1043.  
  1044.     function isExtension($name)
  1045.     {
  1046.         if (isset($this->_packagefile)) {
  1047.             return $this->_packagefile->isExtension($name);
  1048.         elseif (isset($this->_downloadURL['info'])) {
  1049.             if ($this->_downloadURL['info']->getPackagexmlVersion(== '2.0'{
  1050.                 return $this->_downloadURL['info']->getProvidesExtension(== $name;
  1051.             }
  1052.  
  1053.             return false;
  1054.         }
  1055.  
  1056.         return false;
  1057.     }
  1058.  
  1059.     function getDeps()
  1060.     {
  1061.         if (isset($this->_packagefile)) {
  1062.             $ver $this->_packagefile->getPackagexmlVersion();
  1063.             if (version_compare($ver'2.0''>=')) {
  1064.                 return $this->_packagefile->getDeps(true);
  1065.             }
  1066.  
  1067.             return $this->_packagefile->getDeps();
  1068.         elseif (isset($this->_downloadURL['info'])) {
  1069.             $ver $this->_downloadURL['info']->getPackagexmlVersion();
  1070.             if (version_compare($ver'2.0''>=')) {
  1071.                 return $this->_downloadURL['info']->getDeps(true);
  1072.             }
  1073.  
  1074.             return $this->_downloadURL['info']->getDeps();
  1075.         }
  1076.  
  1077.         return array();
  1078.     }
  1079.  
  1080.     /**
  1081.      * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
  1082.      *                      returned from getDepDownloadURL()
  1083.      */
  1084.     function isEqual($param)
  1085.     {
  1086.         if (is_object($param)) {
  1087.             $channel $param->getChannel();
  1088.             $package $param->getPackage();
  1089.             if ($param->getURI()) {
  1090.                 $param = array(
  1091.                     'channel' => $param->getChannel(),
  1092.                     'package' => $param->getPackage(),
  1093.                     'version' => $param->getVersion(),
  1094.                     'uri' => $param->getURI(),
  1095.                 );
  1096.             else {
  1097.                 $param = array(
  1098.                     'channel' => $param->getChannel(),
  1099.                     'package' => $param->getPackage(),
  1100.                     'version' => $param->getVersion(),
  1101.                 );
  1102.             }
  1103.         else {
  1104.             if (isset($param['uri'])) {
  1105.                 if ($this->getChannel(!= '__uri'{
  1106.                     return false;
  1107.                 }
  1108.                 return $param['uri'== $this->getURI();
  1109.             }
  1110.  
  1111.             $package = isset($param['package']$param['package'$param['info']->getPackage();
  1112.             $channel = isset($param['channel']$param['channel'$param['info']->getChannel();
  1113.             if (isset($param['rel'])) {
  1114.                 if (!class_exists('PEAR_Dependency2')) {
  1115.                     require_once 'PEAR/Dependency2.php';
  1116.                 }
  1117.  
  1118.                 $newdep PEAR_Dependency2::normalizeDep($param);
  1119.                 $newdep $newdep[0];
  1120.             elseif (isset($param['min'])) {
  1121.                 $newdep $param;
  1122.             }
  1123.         }
  1124.  
  1125.         if (isset($newdep)) {
  1126.             if (!isset($newdep['min'])) {
  1127.                 $newdep['min''0';
  1128.             }
  1129.  
  1130.             if (!isset($newdep['max'])) {
  1131.                 $newdep['max''100000000000000000000';
  1132.             }
  1133.  
  1134.             // use magic to support pecl packages suddenly jumping to the pecl channel
  1135.             // we need to support both dependency possibilities
  1136.             if ($channel == 'pear.php.net' && $this->getChannel(== 'pecl.php.net'{
  1137.                 if ($package == $this->getPackage()) {
  1138.                     $channel 'pecl.php.net';
  1139.                 }
  1140.             }
  1141.             if ($channel == 'pecl.php.net' && $this->getChannel(== 'pear.php.net'{
  1142.                 if ($package == $this->getPackage()) {
  1143.                     $channel 'pear.php.net';
  1144.                 }
  1145.             }
  1146.  
  1147.             return (strtolower($package== strtolower($this->getPackage()) &&
  1148.                 $channel == $this->getChannel(&&
  1149.                 version_compare($newdep['min']$this->getVersion()'<='&&
  1150.                 version_compare($newdep['max']$this->getVersion()'>='));
  1151.         }
  1152.  
  1153.         // use magic to support pecl packages suddenly jumping to the pecl channel
  1154.         if ($channel == 'pecl.php.net' && $this->getChannel(== 'pear.php.net'{
  1155.             if (strtolower($package== strtolower($this->getPackage())) {
  1156.                 $channel 'pear.php.net';
  1157.             }
  1158.         }
  1159.  
  1160.         if (isset($param['version'])) {
  1161.             return (strtolower($package== strtolower($this->getPackage()) &&
  1162.                 $channel == $this->getChannel(&&
  1163.                 $param['version'== $this->getVersion());
  1164.         }
  1165.  
  1166.         return strtolower($package== strtolower($this->getPackage()) &&
  1167.             $channel == $this->getChannel();
  1168.     }
  1169.  
  1170.     function isInstalled($dep$oper '==')
  1171.     {
  1172.         if (!$dep{
  1173.             return false;
  1174.         }
  1175.  
  1176.         if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '=='{
  1177.             return false;
  1178.         }
  1179.  
  1180.         if (is_object($dep)) {
  1181.             $package $dep->getPackage();
  1182.             $channel $dep->getChannel();
  1183.             if ($dep->getURI()) {
  1184.                 $dep = array(
  1185.                     'uri' => $dep->getURI(),
  1186.                     'version' => $dep->getVersion(),
  1187.                 );
  1188.             else {
  1189.                 $dep = array(
  1190.                     'version' => $dep->getVersion(),
  1191.                 );
  1192.             }
  1193.         else {
  1194.             if (isset($dep['uri'])) {
  1195.                 $channel '__uri';
  1196.                 $package $dep['dep']['name'];
  1197.             else {
  1198.                 $channel $dep['info']->getChannel();
  1199.                 $package $dep['info']->getPackage();
  1200.             }
  1201.         }
  1202.  
  1203.         $options $this->_downloader->getOptions();
  1204.         $test    $this->_installRegistry->packageExists($package$channel);
  1205.         if (!$test && $channel == 'pecl.php.net'{
  1206.             // do magic to allow upgrading from old pecl packages to new ones
  1207.             $test $this->_installRegistry->packageExists($package'pear.php.net');
  1208.             $channel 'pear.php.net';
  1209.         }
  1210.  
  1211.         if ($test{
  1212.             if (isset($dep['uri'])) {
  1213.                 if ($this->_installRegistry->packageInfo($package'uri''__uri'== $dep['uri']{
  1214.                     return true;
  1215.                 }
  1216.             }
  1217.  
  1218.             if (isset($options['upgrade'])) {
  1219.                 $packageVersion $this->_installRegistry->packageInfo($package'version'$channel);
  1220.                 if (version_compare($packageVersion$dep['version']'>=')) {
  1221.                     return true;
  1222.                 }
  1223.  
  1224.                 return false;
  1225.             }
  1226.  
  1227.             return true;
  1228.         }
  1229.  
  1230.         return false;
  1231.     }
  1232.  
  1233.     /**
  1234.      * Detect duplicate package names with differing versions
  1235.      *
  1236.      * If a user requests to install Date 1.4.6 and Date 1.4.7,
  1237.      * for instance, this is a logic error.  This method
  1238.      * detects this situation.
  1239.      *
  1240.      * @param array $params array of PEAR_Downloader_Package objects
  1241.      * @param array $errorparams empty array
  1242.      * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
  1243.      */
  1244.     function detectStupidDuplicates($params&$errorparams)
  1245.     {
  1246.         $existing = array();
  1247.         foreach ($params as $i => $param{
  1248.             $package $param->getPackage();
  1249.             $channel $param->getChannel();
  1250.             $group   $param->getGroup();
  1251.             if (!isset($existing[$channel '/' $package])) {
  1252.                 $existing[$channel '/' $package= array();
  1253.             }
  1254.  
  1255.             if (!isset($existing[$channel '/' $package][$group])) {
  1256.                 $existing[$channel '/' $package][$group= array();
  1257.             }
  1258.  
  1259.             $existing[$channel '/' $package][$group][$i;
  1260.         }
  1261.  
  1262.         $indices = array();
  1263.         foreach ($existing as $package => $groups{
  1264.             foreach ($groups as $group => $dupes{
  1265.                 if (count($dupes> 1{
  1266.                     $indices $indices $dupes;
  1267.                 }
  1268.             }
  1269.         }
  1270.  
  1271.         $indices array_unique($indices);
  1272.         foreach ($indices as $index{
  1273.             $errorparams[$params[$index];
  1274.         }
  1275.  
  1276.         return count($errorparams);
  1277.     }
  1278.  
  1279.     /**
  1280.      * @param array 
  1281.      * @param bool ignore install groups - for final removal of dupe packages
  1282.      * @static
  1283.      */
  1284.     function removeDuplicates(&$params$ignoreGroups = false)
  1285.     {
  1286.         $pnames = array();
  1287.         foreach ($params as $i => $param{
  1288.             if (!$param{
  1289.                 continue;
  1290.             }
  1291.  
  1292.             if ($param->getPackage()) {
  1293.                 $group $ignoreGroups '' $param->getGroup();
  1294.                 $pnames[$i$param->getChannel('/' .
  1295.                     $param->getPackage('-' $param->getVersion('#' $group;
  1296.             }
  1297.         }
  1298.  
  1299.         $pnames array_unique($pnames);
  1300.         $unset  array_diff(array_keys($params)array_keys($pnames));
  1301.         $testp  array_flip($pnames);
  1302.         foreach ($params as $i => $param{
  1303.             if (!$param{
  1304.                 $unset[$i;
  1305.                 continue;
  1306.             }
  1307.  
  1308.             if (!is_a($param'PEAR_Downloader_Package')) {
  1309.                 $unset[$i;
  1310.                 continue;
  1311.             }
  1312.  
  1313.             $group $ignoreGroups '' $param->getGroup();
  1314.             if (!isset($testp[$param->getChannel('/' $param->getPackage('-' .
  1315.                   $param->getVersion('#' $group])) {
  1316.                 $unset[$i;
  1317.             }
  1318.         }
  1319.  
  1320.         foreach ($unset as $i{
  1321.             unset($params[$i]);
  1322.         }
  1323.  
  1324.         $ret = array();
  1325.         foreach ($params as $i => $param{
  1326.             $ret[&$params[$i];
  1327.         }
  1328.  
  1329.         $params = array();
  1330.         foreach ($ret as $i => $param{
  1331.             $params[&$ret[$i];
  1332.         }
  1333.     }
  1334.  
  1335.     function explicitState()
  1336.     {
  1337.         return $this->_explicitState;
  1338.     }
  1339.  
  1340.     function setExplicitState($s)
  1341.     {
  1342.         $this->_explicitState $s;
  1343.     }
  1344.  
  1345.     /**
  1346.      * @static
  1347.      */
  1348.     function mergeDependencies(&$params)
  1349.     {
  1350.         $bundles $newparams = array();
  1351.         foreach ($params as $i => $param{
  1352.             if (!$param->isBundle()) {
  1353.                 continue;
  1354.             }
  1355.  
  1356.             $bundles[$i;
  1357.             $pf &$param->getPackageFile();
  1358.             $newdeps = array();
  1359.             $contents $pf->getBundledPackages();
  1360.             if (!is_array($contents)) {
  1361.                 $contents = array($contents);
  1362.             }
  1363.  
  1364.             foreach ($contents as $file{
  1365.                 $filecontents $pf->getFileContents($file);
  1366.                 $dl &$param->getDownloader();
  1367.                 $options $dl->getOptions();
  1368.                 if (PEAR::isError($dir $dl->getDownloadDir())) {
  1369.                     return $dir;
  1370.                 }
  1371.  
  1372.                 $fp @fopen($dir . DIRECTORY_SEPARATOR . $file'wb');
  1373.                 if (!$fp{
  1374.                     continue;
  1375.                 }
  1376.  
  1377.                 // FIXME do symlink check
  1378.  
  1379.                 fwrite($fp$filecontentsstrlen($filecontents));
  1380.                 fclose($fp);
  1381.                 if ($s $params[$i]->explicitState()) {
  1382.                     $obj->setExplicitState($s);
  1383.                 }
  1384.  
  1385.                 $obj &new PEAR_Downloader_Package($params[$i]->getDownloader());
  1386.                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1387.                 if (PEAR::isError($dir $dl->getDownloadDir())) {
  1388.                     PEAR::popErrorHandling();
  1389.                     return $dir;
  1390.                 }
  1391.  
  1392.                 $e $obj->_fromFile($a $dir . DIRECTORY_SEPARATOR . $file);
  1393.                 PEAR::popErrorHandling();
  1394.                 if (PEAR::isError($e)) {
  1395.                     if (!isset($options['soft'])) {
  1396.                         $dl->log(0$e->getMessage());
  1397.                     }
  1398.                     continue;
  1399.                 }
  1400.  
  1401.                 $j &$obj;
  1402.                 if (!PEAR_Downloader_Package::willDownload($j,
  1403.                       array_merge($params$newparams)) && !$param->isInstalled($j)) {
  1404.                     $newparams[&$j;
  1405.                 }
  1406.             }
  1407.         }
  1408.  
  1409.         foreach ($bundles as $i{
  1410.             unset($params[$i])// remove bundles - only their contents matter for installation
  1411.         }
  1412.  
  1413.         PEAR_Downloader_Package::removeDuplicates($params)// strip any unset indices
  1414.         if (count($newparams)) // add in bundled packages for install
  1415.             foreach ($newparams as $i => $unused{
  1416.                 $params[&$newparams[$i];
  1417.             }
  1418.             $newparams = array();
  1419.         }
  1420.  
  1421.         foreach ($params as $i => $param{
  1422.             $newdeps = array();
  1423.             foreach ($param->_downloadDeps as $dep{
  1424.                 $merge array_merge($params$newparams);
  1425.                 if (!PEAR_Downloader_Package::willDownload($dep$merge)
  1426.                     && !$param->isInstalled($dep)
  1427.                 {
  1428.                     $newdeps[$dep;
  1429.                 else {
  1430.                     //var_dump($dep);
  1431.                     // detect versioning conflicts here
  1432.                 }
  1433.             }
  1434.  
  1435.             // convert the dependencies into PEAR_Downloader_Package objects for the next time around
  1436.             $params[$i]->_downloadDeps = array();
  1437.             foreach ($newdeps as $dep{
  1438.                 $obj &new PEAR_Downloader_Package($params[$i]->getDownloader());
  1439.                 if ($s $params[$i]->explicitState()) {
  1440.                     $obj->setExplicitState($s);
  1441.                 }
  1442.  
  1443.                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1444.                 $e $obj->fromDepURL($dep);
  1445.                 PEAR::popErrorHandling();
  1446.                 if (PEAR::isError($e)) {
  1447.                     if (!isset($options['soft'])) {
  1448.                         $obj->_downloader->log(0$e->getMessage());
  1449.                     }
  1450.                     continue;
  1451.                 }
  1452.  
  1453.                 $e $obj->detectDependencies($params);
  1454.                 if (PEAR::isError($e)) {
  1455.                     if (!isset($options['soft'])) {
  1456.                         $obj->_downloader->log(0$e->getMessage());
  1457.                     }
  1458.                 }
  1459.  
  1460.                 $j &$obj;
  1461.                 $newparams[&$j;
  1462.             }
  1463.         }
  1464.  
  1465.         if (count($newparams)) {
  1466.             foreach ($newparams as $i => $unused{
  1467.                 $params[&$newparams[$i];
  1468.             }
  1469.             return true;
  1470.         }
  1471.  
  1472.         return false;
  1473.     }
  1474.  
  1475.  
  1476.     /**
  1477.      * @static
  1478.      */
  1479.     function willDownload($param$params)
  1480.     {
  1481.         if (!is_array($params)) {
  1482.             return false;
  1483.         }
  1484.  
  1485.         foreach ($params as $obj{
  1486.             if ($obj->isEqual($param)) {
  1487.                 return true;
  1488.             }
  1489.         }
  1490.  
  1491.         return false;
  1492.     }
  1493.  
  1494.     /**
  1495.      * For simpler unit-testing
  1496.      * @param PEAR_Config 
  1497.      * @param int 
  1498.      * @param string 
  1499.      */
  1500.     function &getPackagefileObject(&$c$d)
  1501.     {
  1502.         $a &new PEAR_PackageFile($c$d);
  1503.         return $a;
  1504.     }
  1505.  
  1506.     /**
  1507.      * This will retrieve from a local file if possible, and parse out
  1508.      * a group name as well.  The original parameter will be modified to reflect this.
  1509.      * @param string|arraycan be a parsed package name as well
  1510.      * @access private
  1511.      */
  1512.     function _fromFile(&$param)
  1513.     {
  1514.         $saveparam $param;
  1515.         if (is_string($param)) {
  1516.             if (!@file_exists($param)) {
  1517.                 $test explode('#'$param);
  1518.                 $group array_pop($test);
  1519.                 if (@file_exists(implode('#'$test))) {
  1520.                     $this->setGroup($group);
  1521.                     $param implode('#'$test);
  1522.                     $this->_explicitGroup = true;
  1523.                 }
  1524.             }
  1525.  
  1526.             if (@is_file($param)) {
  1527.                 $this->_type 'local';
  1528.                 $options $this->_downloader->getOptions();
  1529.                 $pkg &$this->getPackagefileObject($this->_config$this->_downloader->_debug);
  1530.                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1531.                 $pf &$pkg->fromAnyFile($paramPEAR_VALIDATE_INSTALLING);
  1532.                 PEAR::popErrorHandling();
  1533.                 if (PEAR::isError($pf)) {
  1534.                     $this->_valid = false;
  1535.                     $param $saveparam;
  1536.                     return $pf;
  1537.                 }
  1538.                 $this->_packagefile &$pf;
  1539.                 if (!$this->getGroup()) {
  1540.                     $this->setGroup('default')// install the default dependency group
  1541.                 }
  1542.                 return $this->_valid = true;
  1543.             }
  1544.         }
  1545.         $param $saveparam;
  1546.         return $this->_valid = false;
  1547.     }
  1548.  
  1549.     function _fromUrl($param$saveparam '')
  1550.     {
  1551.         if (!is_array($param&& (preg_match('#^(http|https|ftp)://#'$param))) {
  1552.             $options $this->_downloader->getOptions();
  1553.             $this->_type 'url';
  1554.             $callback $this->_downloader->ui ?
  1555.                 array(&$this->_downloader'_downloadCallback': null;
  1556.             $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
  1557.             if (PEAR::isError($dir $this->_downloader->getDownloadDir())) {
  1558.                 $this->_downloader->popErrorHandling();
  1559.                 return $dir;
  1560.             }
  1561.  
  1562.             $this->_downloader->log(3'Downloading "' $param '"');
  1563.             $file $this->_downloader->downloadHttp($param$this->_downloader->ui,
  1564.                 $dir$callbacknullfalse$this->getChannel());
  1565.             $this->_downloader->popErrorHandling();
  1566.             if (PEAR::isError($file)) {
  1567.                 if (!empty($saveparam)) {
  1568.                     $saveparam = ", cannot download \"$saveparam\"";
  1569.                 }
  1570.                 $err PEAR::raiseError('Could not download from "' $param .
  1571.                     '"' $saveparam ' (' $file->getMessage(')');
  1572.                     return $err;
  1573.             }
  1574.  
  1575.             if ($this->_rawpackagefile{
  1576.                 require_once 'Archive/Tar.php';
  1577.                 $tar &new Archive_Tar($file);
  1578.                 $packagexml $tar->extractInString('package2.xml');
  1579.                 if (!$packagexml{
  1580.                     $packagexml $tar->extractInString('package.xml');
  1581.                 }
  1582.  
  1583.                 if (str_replace(array("\n""\r")array('','')$packagexml!=
  1584.                       str_replace(array("\n""\r")array('','')$this->_rawpackagefile)) {
  1585.                     if ($this->getChannel(!= 'pear.php.net'{
  1586.                         return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
  1587.                             'not match value returned from xml-rpc');
  1588.                     }
  1589.  
  1590.                     // be more lax for the existing PEAR packages that have not-ok
  1591.                     // characters in their package.xml
  1592.                     $this->_downloader->log(0'CRITICAL WARNING: The "' .
  1593.                         $this->getPackage('" package has invalid characters in its ' .
  1594.                         'package.xml.  The next version of PEAR may not be able to install ' .
  1595.                         'this package for security reasons.  Please open a bug report at ' .
  1596.                         'http://pear.php.net/package/' $this->getPackage('/bugs');
  1597.                 }
  1598.             }
  1599.  
  1600.             // whew, download worked!
  1601.             $pkg &$this->getPackagefileObject($this->_config$this->_downloader->debug);
  1602.  
  1603.             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1604.             $pf &$pkg->fromAnyFile($filePEAR_VALIDATE_INSTALLING);
  1605.             PEAR::popErrorHandling();
  1606.             if (PEAR::isError($pf)) {
  1607.                 if (is_array($pf->getUserInfo())) {
  1608.                     foreach ($pf->getUserInfo(as $err{
  1609.                         if (is_array($err)) {
  1610.                             $err $err['message'];
  1611.                         }
  1612.  
  1613.                         if (!isset($options['soft'])) {
  1614.                             $this->_downloader->log(0"Validation Error: $err");
  1615.                         }
  1616.                     }
  1617.                 }
  1618.  
  1619.                 if (!isset($options['soft'])) {
  1620.                     $this->_downloader->log(0$pf->getMessage());
  1621.                 }
  1622.  
  1623.                 ///FIXME need to pass back some error code that we can use to match with to cancel all further operations
  1624.                 /// At least stop all deps of this package from being installed
  1625.                 $out $saveparam $saveparam $param;
  1626.                 $err PEAR::raiseError('Download of "' $out '" succeeded, but it is not a valid package archive');
  1627.                 $this->_valid = false;
  1628.                 return $err;
  1629.             }
  1630.  
  1631.             $this->_packagefile &$pf;
  1632.             $this->setGroup('default')// install the default dependency group
  1633.             return $this->_valid = true;
  1634.         }
  1635.  
  1636.         return $this->_valid = false;
  1637.     }
  1638.  
  1639.     /**
  1640.      *
  1641.      * @param string|arraypass in an array of format
  1642.      *                      array(
  1643.      *                       'package' => 'pname',
  1644.      *                      ['channel' => 'channame',]
  1645.      *                      ['version' => 'version',]
  1646.      *                      ['state' => 'state',])
  1647.      *                      or a string of format [channame/]pname[-version|-state]
  1648.      */
  1649.     function _fromString($param)
  1650.     {
  1651.         $options $this->_downloader->getOptions();
  1652.         $channel $this->_config->get('default_channel');
  1653.         $pname $this->_registry->parsePackageName($param$channel);
  1654.         PEAR::popErrorHandling();
  1655.         if (PEAR::isError($pname)) {
  1656.             if ($pname->getCode(== 'invalid'{
  1657.                 $this->_valid = false;
  1658.                 return false;
  1659.             }
  1660.  
  1661.             if ($pname->getCode(== 'channel'{
  1662.                 $parsed $pname->getUserInfo();
  1663.                 if ($this->_downloader->discover($parsed['channel'])) {
  1664.                     if ($this->_config->get('auto_discover')) {
  1665.                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1666.                         $pname $this->_registry->parsePackageName($param$channel);
  1667.                         PEAR::popErrorHandling();
  1668.                     else {
  1669.                         if (!isset($options['soft'])) {
  1670.                             $this->_downloader->log(0'Channel "' $parsed['channel'.
  1671.                                 '" is not initialized, use ' .
  1672.                                 '"pear channel-discover ' $parsed['channel''" to initialize' .
  1673.                                 'or pear config-set auto_discover 1');
  1674.                         }
  1675.                     }
  1676.                 }
  1677.  
  1678.                 if (PEAR::isError($pname)) {
  1679.                     if (!isset($options['soft'])) {
  1680.                         $this->_downloader->log(0$pname->getMessage());
  1681.                     }
  1682.  
  1683.                     if (is_array($param)) {
  1684.                         $param $this->_registry->parsedPackageNameToString($param);
  1685.                     }
  1686.  
  1687.                     $err PEAR::raiseError('invalid package name/package file "' $param '"');
  1688.                     $this->_valid = false;
  1689.                     return $err;
  1690.                 }
  1691.             else {
  1692.                 if (!isset($options['soft'])) {
  1693.                     $this->_downloader->log(0$pname->getMessage());
  1694.                 }
  1695.  
  1696.                 $err PEAR::raiseError('invalid package name/package file "' $param '"');
  1697.                 $this->_valid = false;
  1698.                 return $err;
  1699.             }
  1700.         }
  1701.  
  1702.         if (!isset($this->_type)) {
  1703.             $this->_type 'rest';
  1704.         }
  1705.  
  1706.         $this->_parsedname    $pname;
  1707.         $this->_explicitState = isset($pname['state']$pname['state': false;
  1708.         $this->_explicitGroup = isset($pname['group']? true : false;
  1709.  
  1710.         $info $this->_downloader->_getPackageDownloadUrl($pname);
  1711.         if (PEAR::isError($info)) {
  1712.             if ($info->getCode(!= -976 && $pname['channel'== 'pear.php.net'{
  1713.                 // try pecl
  1714.                 $pname['channel''pecl.php.net';
  1715.                 if ($test $this->_downloader->_getPackageDownloadUrl($pname)) {
  1716.                     if (!PEAR::isError($test)) {
  1717.                         $info PEAR::raiseError($info->getMessage(' - package ' .
  1718.                             $this->_registry->parsedPackageNameToString($pnametrue.
  1719.                             ' can be installed with "pecl install ' $pname['package'.
  1720.                             '"');
  1721.                     else {
  1722.                         $pname['channel''pear.php.net';
  1723.                     }
  1724.                 else {
  1725.                     $pname['channel''pear.php.net';
  1726.                 }
  1727.             }
  1728.  
  1729.             return $info;
  1730.         }
  1731.  
  1732.         $this->_rawpackagefile $info['raw'];
  1733.         $ret $this->_analyzeDownloadURL($info$param$pname);
  1734.         if (PEAR::isError($ret)) {
  1735.             return $ret;
  1736.         }
  1737.  
  1738.         if ($ret{
  1739.             $this->_downloadURL $ret;
  1740.             return $this->_valid = (bool) $ret;
  1741.         }
  1742.     }
  1743.  
  1744.     /**
  1745.      * @param array output of package.getDownloadURL
  1746.      * @param string|array|object information  for detecting packages to be downloaded, and
  1747.      *                             for errors
  1748.      * @param array name information of the package
  1749.      * @param array|nullpackages to be downloaded
  1750.      * @param bool is this an optional dependency?
  1751.      * @param bool is this any kind of dependency?
  1752.      * @access private
  1753.      */
  1754.     function _analyzeDownloadURL($info$param$pname$params = null$optional = false,
  1755.                                  $isdependency = false)
  1756.     {
  1757.         if (!is_string($param&& PEAR_Downloader_Package::willDownload($param$params)) {
  1758.             return false;
  1759.         }
  1760.  
  1761.         if ($info === false{
  1762.             $saveparam !is_string($param? ", cannot download \"$param\"" : '';
  1763.  
  1764.             // no releases exist
  1765.             return PEAR::raiseError('No releases for package "' .
  1766.                 $this->_registry->parsedPackageNameToString($pnametrue'" exist' $saveparam);
  1767.         }
  1768.  
  1769.         if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
  1770.             $err = false;
  1771.             if ($pname['channel'== 'pecl.php.net'{
  1772.                 if ($info['info']->getChannel(!= 'pear.php.net'{
  1773.                     $err = true;
  1774.                 }
  1775.             elseif ($info['info']->getChannel(== 'pecl.php.net'{
  1776.                 if ($pname['channel'!= 'pear.php.net'{
  1777.                     $err = true;
  1778.                 }
  1779.             else {
  1780.                 $err = true;
  1781.             }
  1782.  
  1783.             if ($err{
  1784.                 return PEAR::raiseError('SECURITY ERROR: package in channel "' $pname['channel'.
  1785.                     '" retrieved another channel\'s name for download! ("' .
  1786.                     $info['info']->getChannel('")');
  1787.             }
  1788.         }
  1789.  
  1790.         $preferred_state $this->_config->get('preferred_state');
  1791.         if (!isset($info['url'])) {
  1792.             $package_version $this->_registry->packageInfo($info['info']->getPackage(),
  1793.             'version'$info['info']->getChannel());
  1794.             if ($this->isInstalled($info)) {
  1795.                 if ($isdependency && version_compare($info['version']$package_version'<=')) {
  1796.                     // ignore bogus errors of "failed to download dependency"
  1797.                     // if it is already installed and the one that would be
  1798.                     // downloaded is older or the same version (Bug #7219)
  1799.                     return false;
  1800.                 }
  1801.             }
  1802.  
  1803.             if ($info['version'=== $package_version{
  1804.                 if (!isset($options['soft'])) {
  1805.                     $this->_downloader->log(1'WARNING: failed to download ' $pname['channel'.
  1806.                         '/' $pname['package''-' $package_version', additionally the suggested version' .
  1807.                         ' (' $package_version ') is the same as the locally installed one.');
  1808.                 }
  1809.  
  1810.                 return false;
  1811.             }
  1812.  
  1813.             if (version_compare($info['version']$package_version'<=')) {
  1814.                 if (!isset($options['soft'])) {
  1815.                     $this->_downloader->log(1'WARNING: failed to download ' $pname['channel'.
  1816.                         '/' $pname['package''-' $package_version ', additionally the suggested version' .
  1817.                         ' (' $info['version'') is a lower version than the locally installed one (' $package_version ').');
  1818.                 }
  1819.  
  1820.                 return false;
  1821.             }
  1822.  
  1823.             $instead =  ', will instead download version ' $info['version'.
  1824.                         ', stability "' $info['info']->getState('"';
  1825.             // releases exist, but we failed to get any
  1826.             if (isset($this->_downloader->_options['force'])) {
  1827.                 if (isset($pname['version'])) {
  1828.                     $vs ', version "' $pname['version''"';
  1829.                 elseif (isset($pname['state'])) {
  1830.                     $vs ', stability "' $pname['state''"';
  1831.                 elseif ($param == 'dependency'{
  1832.                     if (!class_exists('PEAR_Common')) {
  1833.                         require_once 'PEAR/Common.php';
  1834.                     }
  1835.  
  1836.                     if (!in_array($info['info']->getState(),
  1837.                           PEAR_Common::betterStates($preferred_statetrue))) {
  1838.                         if ($optional{
  1839.                             // don't spit out confusing error message
  1840.                             return $this->_downloader->_getPackageDownloadUrl(
  1841.                                 array('package' => $pname['package'],
  1842.                                       'channel' => $pname['channel'],
  1843.                                       'version' => $info['version']));
  1844.                         }
  1845.                         $vs ' within preferred state "' $preferred_state .
  1846.                             '"';
  1847.                     else {
  1848.                         if (!class_exists('PEAR_Dependency2')) {
  1849.                             require_once 'PEAR/Dependency2.php';
  1850.                         }
  1851.  
  1852.                         if ($optional{
  1853.                             // don't spit out confusing error message
  1854.                             return $this->_downloader->_getPackageDownloadUrl(
  1855.                                 array('package' => $pname['package'],
  1856.                                       'channel' => $pname['channel'],
  1857.                                       'version' => $info['version']));
  1858.                         }
  1859.                         $vs PEAR_Dependency2::_getExtraString($pname);
  1860.                         $instead '';
  1861.                     }
  1862.                 else {
  1863.                     $vs ' within preferred state "' $preferred_state '"';
  1864.                 }
  1865.  
  1866.                 if (!isset($options['soft'])) {
  1867.                     $this->_downloader->log(1'WARNING: failed to download ' $pname['channel'.
  1868.                         '/' $pname['package'$vs $instead);
  1869.                 }
  1870.  
  1871.                 // download the latest release
  1872.                 return $this->_downloader->_getPackageDownloadUrl(
  1873.                     array('package' => $pname['package'],
  1874.                           'channel' => $pname['channel'],
  1875.                           'version' => $info['version']));
  1876.             else {
  1877.                 if (isset($info['php']&& $info['php']{
  1878.                     $err PEAR::raiseError('Failed to download ' .
  1879.                         $this->_registry->parsedPackageNameToString(
  1880.                             array('channel' => $pname['channel'],
  1881.                                   'package' => $pname['package']),
  1882.                                 true.
  1883.                         ', latest release is version ' $info['php']['v'.
  1884.                         ', but it requires PHP version "' .
  1885.                         $info['php']['m''", use "' .
  1886.                         $this->_registry->parsedPackageNameToString(
  1887.                             array('channel' => $pname['channel']'package' => $pname['package'],
  1888.                             'version' => $info['php']['v'])) '" to install',
  1889.                             PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
  1890.                     return $err;
  1891.                 }
  1892.  
  1893.                 // construct helpful error message
  1894.                 if (isset($pname['version'])) {
  1895.                     $vs ', version "' $pname['version''"';
  1896.                 elseif (isset($pname['state'])) {
  1897.                     $vs ', stability "' $pname['state''"';
  1898.                 elseif ($param == 'dependency'{
  1899.                     if (!class_exists('PEAR_Common')) {
  1900.                         require_once 'PEAR/Common.php';
  1901.                     }
  1902.  
  1903.                     if (!in_array($info['info']->getState(),
  1904.                           PEAR_Common::betterStates($preferred_statetrue))) {
  1905.                         if ($optional{
  1906.                             // don't spit out confusing error message, and don't die on
  1907.                             // optional dep failure!
  1908.                             return $this->_downloader->_getPackageDownloadUrl(
  1909.                                 array('package' => $pname['package'],
  1910.                                       'channel' => $pname['channel'],
  1911.                                       'version' => $info['version']));
  1912.                         }
  1913.                         $vs ' within preferred state "' $preferred_state '"';
  1914.                     else {
  1915.                         if (!class_exists('PEAR_Dependency2')) {
  1916.                             require_once 'PEAR/Dependency2.php';
  1917.                         }
  1918.  
  1919.                         if ($optional{
  1920.                             // don't spit out confusing error message, and don't die on
  1921.                             // optional dep failure!
  1922.                             return $this->_downloader->_getPackageDownloadUrl(
  1923.                                 array('package' => $pname['package'],
  1924.                                       'channel' => $pname['channel'],
  1925.                                       'version' => $info['version']));
  1926.                         }
  1927.                         $vs PEAR_Dependency2::_getExtraString($pname);
  1928.                     }
  1929.                 else {
  1930.                     $vs ' within preferred state "' $this->_downloader->config->get('preferred_state''"';
  1931.                 }
  1932.  
  1933.                 $options $this->_downloader->getOptions();
  1934.                 // this is only set by the "download-all" command
  1935.                 if (isset($options['ignorepreferred_state'])) {
  1936.                     $err PEAR::raiseError(
  1937.                         'Failed to download ' $this->_registry->parsedPackageNameToString(
  1938.                             array('channel' => $pname['channel']'package' => $pname['package']),
  1939.                                 true)
  1940.                          . $vs .
  1941.                         ', latest release is version ' $info['version'.
  1942.                         ', stability "' $info['info']->getState('", use "' .
  1943.                         $this->_registry->parsedPackageNameToString(
  1944.                             array('channel' => $pname['channel']'package' => $pname['package'],
  1945.                             'version' => $info['version'])) '" to install',
  1946.                             PEAR_DOWNLOADER_PACKAGE_STATE);
  1947.                     return $err;
  1948.                 }
  1949.  
  1950.                 // Checks if the user has a package installed already and checks the release against
  1951.                 // the state against the installed package, this allows upgrades for packages
  1952.                 // with lower stability than the preferred_state
  1953.                 $stability $this->_registry->packageInfo($pname['package']'stability'$pname['channel']);
  1954.                 if (!$this->isInstalled($info)
  1955.                     || !in_array($info['info']->getState()PEAR_Common::betterStates($stability['release']true))
  1956.                 {
  1957.                     $err PEAR::raiseError(
  1958.                         'Failed to download ' $this->_registry->parsedPackageNameToString(
  1959.                             array('channel' => $pname['channel']'package' => $pname['package']),
  1960.                                 true)
  1961.                          . $vs .
  1962.                         ', latest release is version ' $info['version'.
  1963.                         ', stability "' $info['info']->getState('", use "' .
  1964.                         $this->_registry->parsedPackageNameToString(
  1965.                             array('channel' => $pname['channel']'package' => $pname['package'],
  1966.                             'version' => $info['version'])) '" to install');
  1967.                     return $err;
  1968.                 }
  1969.             }
  1970.         }
  1971.  
  1972.         if (isset($info['deprecated']&& $info['deprecated']{
  1973.             $this->_downloader->log(0,
  1974.                 'WARNING: "' .
  1975.                     $this->_registry->parsedPackageNameToString(
  1976.                             array('channel' => $info['info']->getChannel(),
  1977.                                   'package' => $info['info']->getPackage())true.
  1978.                 '" is deprecated in favor of "' .
  1979.                     $this->_registry->parsedPackageNameToString($info['deprecated']true.
  1980.                 '"');
  1981.         }
  1982.  
  1983.         return $info;
  1984.     }
  1985. }

Documentation generated on Wed, 06 Jul 2011 23:31:02 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.