[ Index ]
 

Code source de GeekLog 1.4.1

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/system/pear/PEAR/Downloader/ -> Package.php (source)

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


Généré le : Wed Nov 21 12:27:40 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics