[ PHPXref.com ] [ Generated: Sun Jul 20 19:16:47 2008 ] [ P4A 1.0.0 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/p4a/libraries/pear/PEAR/ -> Downloader.php (source)

   1  <?php
   2  /**

   3   * PEAR_Downloader, the PEAR Installer's download utility class

   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   * @author     Stig Bakken <ssb@php.net>

  17   * @author     Tomas V. V. Cox <cox@idecnet.com>

  18   * @author     Martin Jansen <mj@php.net>

  19   * @copyright  1997-2006 The PHP Group

  20   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0

  21   * @version    CVS: $Id: Downloader.php,v 1.99 2006/03/02 18:14:13 cellog Exp $

  22   * @link       http://pear.php.net/package/PEAR

  23   * @since      File available since Release 1.3.0

  24   */
  25  
  26  /**

  27   * Needed for constants, extending

  28   */
  29  require_once 'PEAR/Common.php';
  30  
  31  define('PEAR_INSTALLER_OK',       1);
  32  define('PEAR_INSTALLER_FAILED',   0);
  33  define('PEAR_INSTALLER_SKIPPED', -1);
  34  define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
  35  
  36  /**

  37   * Administration class used to download anything from the internet (PEAR Packages,

  38   * static URLs, xml files)

  39   *

  40   * @category   pear

  41   * @package    PEAR

  42   * @author     Greg Beaver <cellog@php.net>

  43   * @author     Stig Bakken <ssb@php.net>

  44   * @author     Tomas V. V. Cox <cox@idecnet.com>

  45   * @author     Martin Jansen <mj@php.net>

  46   * @copyright  1997-2006 The PHP Group

  47   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0

  48   * @version    Release: 1.4.9

  49   * @link       http://pear.php.net/package/PEAR

  50   * @since      Class available since Release 1.3.0

  51   */
  52  class PEAR_Downloader extends PEAR_Common
  53  {
  54      /**

  55       * @var PEAR_Registry

  56       * @access private

  57       */
  58      var $_registry;
  59  
  60      /**

  61       * @var PEAR_Remote

  62       * @access private

  63       */
  64      var $_remote;
  65  
  66      /**

  67       * Preferred Installation State (snapshot, devel, alpha, beta, stable)

  68       * @var string|null

  69       * @access private

  70       */
  71      var $_preferredState;
  72  
  73      /**

  74       * Options from command-line passed to Install.

  75       *

  76       * Recognized options:<br />

  77       *  - onlyreqdeps   : install all required dependencies as well

  78       *  - alldeps       : install all dependencies, including optional

  79       *  - installroot   : base relative path to install files in

  80       *  - force         : force a download even if warnings would prevent it

  81       *  - nocompress    : download uncompressed tarballs

  82       * @see PEAR_Command_Install

  83       * @access private

  84       * @var array

  85       */
  86      var $_options;
  87  
  88      /**

  89       * Downloaded Packages after a call to download().

  90       *

  91       * Format of each entry:

  92       *

  93       * <code>

  94       * array('pkg' => 'package_name', 'file' => '/path/to/local/file',

  95       *    'info' => array() // parsed package.xml

  96       * );

  97       * </code>

  98       * @access private

  99       * @var array

 100       */
 101      var $_downloadedPackages = array();
 102  
 103      /**

 104       * Packages slated for download.

 105       *

 106       * This is used to prevent downloading a package more than once should it be a dependency

 107       * for two packages to be installed.

 108       * Format of each entry:

 109       *

 110       * <pre>

 111       * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,

 112       * );

 113       * </pre>

 114       * @access private

 115       * @var array

 116       */
 117      var $_toDownload = array();
 118  
 119      /**

 120       * Array of every package installed, with names lower-cased.

 121       *

 122       * Format:

 123       * <code>

 124       * array('package1' => 0, 'package2' => 1, );

 125       * </code>

 126       * @var array

 127       */
 128      var $_installed = array();
 129  
 130      /**

 131       * @var array

 132       * @access private

 133       */
 134      var $_errorStack = array();
 135      
 136      /**

 137       * @var boolean

 138       * @access private

 139       */
 140      var $_internalDownload = false;
 141  
 142      /**

 143       * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}

 144       * @var array

 145       * @access private

 146       */
 147      var $_packageSortTree;
 148  
 149      /**

 150       * Temporary directory, or configuration value where downloads will occur

 151       * @var string

 152       */
 153      var $_downloadDir;
 154      // {{{ PEAR_Downloader()

 155  
 156      /**

 157       * @param PEAR_Frontend_*

 158       * @param array

 159       * @param PEAR_Config

 160       */
 161      function PEAR_Downloader(&$ui, $options, &$config)
 162      {
 163          parent::PEAR_Common();
 164          $this->_options = $options;
 165          $this->config = &$config;
 166          $this->_preferredState = $this->config->get('preferred_state');
 167          $this->ui = &$ui;
 168          if (!$this->_preferredState) {
 169              // don't inadvertantly use a non-set preferred_state

 170              $this->_preferredState = null;
 171          }
 172  
 173          if (isset($this->_options['installroot'])) {
 174              $this->config->setInstallRoot($this->_options['installroot']);
 175          }
 176          $this->_registry = &$config->getRegistry();
 177          $this->_remote = &$config->getRemote();
 178  
 179          if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
 180              $this->_installed = $this->_registry->listAllPackages();
 181              foreach ($this->_installed as $key => $unused) {
 182                  if (!count($unused)) {
 183                      continue;
 184                  }
 185                  @array_walk($this->_installed[$key], 'strtolower');
 186              }
 187          }
 188      }
 189  
 190      /**

 191       * Attempt to discover a channel's remote capabilities from

 192       * its server name

 193       * @param string

 194       * @return boolean

 195       */
 196      function discover($channel)
 197      {
 198          $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
 199          PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
 200          $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
 201          if (!class_exists('System')) {
 202              require_once 'System.php';
 203          }
 204          $a = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui,
 205              System::mktemp(array('-d')), $callback, false);
 206          PEAR::popErrorHandling();
 207          if (PEAR::isError($a)) {
 208              return false;
 209          }
 210          list($a, $lastmodified) = $a;
 211          if (!class_exists('PEAR/ChannelFile.php')) {
 212              require_once 'PEAR/ChannelFile.php';
 213          }
 214          $b = new PEAR_ChannelFile;
 215          if ($b->fromXmlFile($a)) {
 216              @unlink($a);
 217              if ($this->config->get('auto_discover')) {
 218                  $this->_registry->addChannel($b, $lastmodified);
 219                  $alias = $b->getName();
 220                  if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
 221                      $alias = $b->getAlias();
 222                  }
 223                  $this->log(1, 'Auto-discovered channel "' . $channel .
 224                      '", alias "' . $alias . '", adding to registry');
 225              }
 226              return true;
 227          }
 228          @unlink($a);
 229          return false;
 230      }
 231  
 232      /**

 233       * For simpler unit-testing

 234       * @param PEAR_Downloader

 235       * @return PEAR_Downloader_Package

 236       */
 237      function &newDownloaderPackage(&$t)
 238      {
 239          if (!class_exists('PEAR_Downloader_Package')) {
 240              require_once 'PEAR/Downloader/Package.php';
 241          }
 242          $a = &new PEAR_Downloader_Package($t);
 243          return $a;
 244      }
 245  
 246      /**

 247       * For simpler unit-testing

 248       * @param PEAR_Config

 249       * @param array

 250       * @param array

 251       * @param int

 252       */
 253      function &getDependency2Object(&$c, $i, $p, $s)
 254      {
 255          if (!class_exists('PEAR/Dependency2.php')) {
 256              require_once 'PEAR/Dependency2.php';
 257          }
 258          $z = &new PEAR_Dependency2($c, $i, $p, $s);
 259          return $z;
 260      }
 261  
 262      function &download($params)
 263      {
 264          if (!count($params)) {
 265              $a = array();
 266              return $a;
 267          }
 268          if (!isset($this->_registry)) {
 269              $this->_registry = &$this->config->getRegistry();
 270          }
 271          if (!isset($this->_remote)) {
 272              $this->_remote = &$this->config->getRemote();
 273          }
 274          $channelschecked = array();
 275          // convert all parameters into PEAR_Downloader_Package objects

 276          foreach ($params as $i => $param) {
 277              $params[$i] = &$this->newDownloaderPackage($this);
 278              PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
 279              $err = $params[$i]->initialize($param);
 280              PEAR::staticPopErrorHandling();
 281              if (!$err) {
 282                  // skip parameters that were missed by preferred_state

 283                  continue;
 284              }
 285              if (PEAR::isError($err)) {
 286                  if (!isset($this->_options['soft'])) {
 287                      $this->log(0, $err->getMessage());
 288                  }
 289                  $params[$i] = false;
 290                  if (is_object($param)) {
 291                      $param = $param->getChannel() . '/' . $param->getPackage();
 292                  }
 293                  $this->pushError('Package "' . $param . '" is not valid',
 294                      PEAR_INSTALLER_SKIPPED);
 295              } else {
 296                  if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
 297                        !isset($this->_options['offline'])) {
 298                      $channelschecked[$params[$i]->getChannel()] = true;
 299                      PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
 300                      if (!class_exists('System')) {
 301                          require_once 'System.php';
 302                      }
 303                      $curchannel = &$this->_registry->getChannel($params[$i]->getChannel());
 304                      if (PEAR::isError($curchannel)) {
 305                          PEAR::staticPopErrorHandling();
 306                          return $this->raiseError($curchannel);
 307                      }
 308                      $a = $this->downloadHttp('http://' . $params[$i]->getChannel() .
 309                          '/channel.xml', $this->ui,
 310                          System::mktemp(array('-d')), null, $curchannel->lastModified());
 311                      PEAR::staticPopErrorHandling();
 312                      if (PEAR::isError($a) || !$a) {
 313                          continue;
 314                      }
 315                      $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
 316                          'updated its protocols, use "channel-update ' . $params[$i]->getChannel() .
 317                          '" to update');
 318                  }
 319                  if ($params[$i] && !isset($this->_options['downloadonly'])) {
 320                      if (isset($this->_options['packagingroot'])) {
 321                          $checkdir = $this->_prependPath(
 322                              $this->config->get('php_dir', null, $params[$i]->getChannel()),
 323                              $this->_options['packagingroot']);
 324                      } else {
 325                          $checkdir = $this->config->get('php_dir',
 326                              null, $params[$i]->getChannel());
 327                      }
 328                      while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
 329                          $checkdir = dirname($checkdir);
 330                      }
 331                      if ($checkdir == '.') {
 332                          $checkdir = '/';
 333                      }
 334                      if (!@is_writeable($checkdir)) {
 335                          return PEAR::raiseError('Cannot install, php_dir for channel "' .
 336                              $params[$i]->getChannel() . '" is not writeable by the current user');
 337                      }
 338                  }
 339              }
 340          }
 341          unset($channelschecked);
 342          PEAR_Downloader_Package::removeDuplicates($params);
 343          if (!count($params)) {
 344              $a = array();
 345              return $a;
 346          }
 347          if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
 348              $reverify = true;
 349              while ($reverify) {
 350                  $reverify = false;
 351                  foreach ($params as $i => $param) {
 352                      $ret = $params[$i]->detectDependencies($params);
 353                      if (PEAR::isError($ret)) {
 354                          $reverify = true;
 355                          $params[$i] = false;
 356                          PEAR_Downloader_Package::removeDuplicates($params);
 357                          if (!isset($this->_options['soft'])) {
 358                              $this->log(0, $ret->getMessage());
 359                          }
 360                          continue 2;
 361                      }
 362                  }
 363              }
 364          }
 365          if (isset($this->_options['offline'])) {
 366              $this->log(3, 'Skipping dependency download check, --offline specified');
 367          }
 368          if (!count($params)) {
 369              $a = array();
 370              return $a;
 371          }
 372          while (PEAR_Downloader_Package::mergeDependencies($params));
 373          PEAR_Downloader_Package::removeInstalled($params);
 374          if (!count($params)) {
 375              $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
 376              $a = array();
 377              return $a;
 378          }
 379          PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
 380          $err = $this->analyzeDependencies($params);
 381          PEAR::popErrorHandling();
 382          if (!count($params)) {
 383              $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
 384              $a = array();
 385              return $a;
 386          }
 387          $ret = array();
 388          $newparams = array();
 389          if (isset($this->_options['pretend'])) {
 390              return $params;
 391          }
 392          foreach ($params as $i => $package) {
 393              PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
 394              $pf = &$params[$i]->download();
 395              PEAR::staticPopErrorHandling();
 396              if (PEAR::isError($pf)) {
 397                  if (!isset($this->_options['soft'])) {
 398                      $this->log(1, $pf->getMessage());
 399                      $this->log(0, 'Error: cannot download "' .
 400                          $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
 401                              true) .
 402                          '"');
 403                  }
 404                  continue;
 405              }
 406              $newparams[] = &$params[$i];
 407              $ret[] = array('file' => $pf->getArchiveFile(),
 408                                     'info' => &$pf,
 409                                     'pkg' => $pf->getPackage());
 410          }
 411          $this->_downloadedPackages = $ret;
 412          return $newparams;
 413      }
 414  
 415      /**

 416       * @param array all packages to be installed

 417       */
 418      function analyzeDependencies(&$params)
 419      {
 420          $hasfailed = $failed = false;
 421          if (isset($this->_options['downloadonly'])) {
 422              return;
 423          }
 424          PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
 425          $redo = true;
 426          $reset = false;
 427          while ($redo) {
 428              $redo = false;
 429              foreach ($params as $i => $param) {
 430                  $deps = $param->getDeps();
 431                  if (!$deps) {
 432                      $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
 433                          $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
 434                      if ($param->getType() == 'xmlrpc') {
 435                          $send = $param->getDownloadURL();
 436                      } else {
 437                          $send = $param->getPackageFile();
 438                      }
 439                      $installcheck = $depchecker->validatePackage($send, $this, $params);
 440                      if (PEAR::isError($installcheck)) {
 441                          if (!isset($this->_options['soft'])) {
 442                              $this->log(0, $installcheck->getMessage());
 443                          }
 444                          $hasfailed = true;
 445                          $params[$i] = false;
 446                          $reset = true;
 447                          $redo = true;
 448                          $failed = false;
 449                          PEAR_Downloader_Package::removeDuplicates($params);
 450                          continue 2;
 451                      }
 452                      continue;
 453                  }
 454                  if (!$reset && $param->alreadyValidated()) {
 455                      continue;
 456                  }
 457                  if (count($deps)) {
 458                      $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
 459                          $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
 460                      if ($param->getType() == 'xmlrpc') {
 461                          $send = $param->getDownloadURL();
 462                      } else {
 463                          $send = $param->getPackageFile();
 464                      }
 465                      $installcheck = $depchecker->