[ Index ]
 

Code source de PHP PEAR 1.4.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/PEAR/ -> Registry.php (source)

   1  <?php
   2  /**
   3   * PEAR_Registry
   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     Stig Bakken <ssb@php.net>
  16   * @author     Tomas V. V. Cox <cox@idecnet.com>
  17   * @author     Greg Beaver <cellog@php.net>
  18   * @copyright  1997-2006 The PHP Group
  19   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  20   * @version    CVS: $Id: Registry.php,v 1.159 2006/12/20 19:34:03 cellog Exp $
  21   * @link       http://pear.php.net/package/PEAR
  22   * @since      File available since Release 0.1
  23   */
  24  
  25  /**
  26   * for PEAR_Error
  27   */
  28  require_once  'PEAR.php';
  29  require_once  'PEAR/DependencyDB.php';
  30  
  31  define('PEAR_REGISTRY_ERROR_LOCK',   -2);
  32  define('PEAR_REGISTRY_ERROR_FORMAT', -3);
  33  define('PEAR_REGISTRY_ERROR_FILE',   -4);
  34  define('PEAR_REGISTRY_ERROR_CONFLICT', -5);
  35  define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
  36  
  37  /**
  38   * Administration class used to maintain the installed package database.
  39   * @category   pear
  40   * @package    PEAR
  41   * @author     Stig Bakken <ssb@php.net>
  42   * @author     Tomas V. V. Cox <cox@idecnet.com>
  43   * @author     Greg Beaver <cellog@php.net>
  44   * @copyright  1997-2006 The PHP Group
  45   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  46   * @version    Release: 1.5.0
  47   * @link       http://pear.php.net/package/PEAR
  48   * @since      Class available since Release 1.4.0a1
  49   */
  50  class PEAR_Registry extends PEAR
  51  {
  52      // {{{ properties
  53  
  54      /**
  55       * File containing all channel information.
  56       * @var string
  57       */
  58      var $channels = '';
  59  
  60      /** Directory where registry files are stored.
  61       * @var string
  62       */
  63      var $statedir = '';
  64  
  65      /** File where the file map is stored
  66       * @var string
  67       */
  68      var $filemap = '';
  69  
  70      /** Directory where registry files for channels are stored.
  71       * @var string
  72       */
  73      var $channelsdir = '';
  74  
  75      /** Name of file used for locking the registry
  76       * @var string
  77       */
  78      var $lockfile = '';
  79  
  80      /** File descriptor used during locking
  81       * @var resource
  82       */
  83      var $lock_fp = null;
  84  
  85      /** Mode used during locking
  86       * @var int
  87       */
  88      var $lock_mode = 0; // XXX UNUSED
  89  
  90      /** Cache of package information.  Structure:
  91       * array(
  92       *   'package' => array('id' => ... ),
  93       *   ... )
  94       * @var array
  95       */
  96      var $pkginfo_cache = array();
  97  
  98      /** Cache of file map.  Structure:
  99       * array( '/path/to/file' => 'package', ... )
 100       * @var array
 101       */
 102      var $filemap_cache = array();
 103  
 104      /**
 105       * @var false|PEAR_ChannelFile
 106       */
 107      var $_pearChannel;
 108  
 109      /**
 110       * @var false|PEAR_ChannelFile
 111       */
 112      var $_peclChannel;
 113  
 114      /**
 115       * @var PEAR_DependencyDB
 116       */
 117      var $_dependencyDB;
 118  
 119      /**
 120       * @var PEAR_Config
 121       */
 122      var $_config;
 123      // }}}
 124  
 125      // {{{ constructor
 126  
 127      /**
 128       * PEAR_Registry constructor.
 129       *
 130       * @param string (optional) PEAR install directory (for .php files)
 131       * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
 132       *        default values are not desired.  Only used the very first time a PEAR
 133       *        repository is initialized
 134       * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
 135       *        default values are not desired.  Only used the very first time a PEAR
 136       *        repository is initialized
 137       *
 138       * @access public
 139       */
 140      function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
 141                             $pecl_channel = false)
 142      {
 143          parent::PEAR();
 144          $ds = DIRECTORY_SEPARATOR;
 145          $this->install_dir = $pear_install_dir;
 146          $this->channelsdir = $pear_install_dir.$ds.'.channels';
 147          $this->statedir = $pear_install_dir.$ds.'.registry';
 148          $this->filemap  = $pear_install_dir.$ds.'.filemap';
 149          $this->lockfile = $pear_install_dir.$ds.'.lock';
 150          $this->_pearChannel = $pear_channel;
 151          $this->_peclChannel = $pecl_channel;
 152          $this->_config = false;
 153      }
 154  
 155      function hasWriteAccess()
 156      {
 157          if (!file_exists($this->install_dir)) {
 158              $dir = $this->install_dir;
 159              while ($dir && $dir != '.') {
 160                  $dir = dirname($dir); // cd ..
 161                  if ($dir != '.' && file_exists($dir)) {
 162                      if (is_writeable($dir)) {
 163                          return true;
 164                      } else {
 165                          return false;
 166                      }
 167                  }
 168              }
 169              return false;
 170          }
 171          return is_writeable($this->install_dir);
 172      }
 173  
 174      function setConfig(&$config)
 175      {
 176          $this->_config = &$config;
 177      }
 178  
 179      function _initializeChannelDirs()
 180      {
 181          static $running = false;
 182          if (!$running) {
 183              $running = true;
 184              $ds = DIRECTORY_SEPARATOR;
 185              if (!is_dir($this->channelsdir) ||
 186                    !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
 187                    !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
 188                    !file_exists($this->channelsdir . $ds . '__uri.reg')) {
 189                  if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
 190                      $pear_channel = $this->_pearChannel;
 191                      if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
 192                          if (!class_exists('PEAR_ChannelFile')) {
 193                              require_once  'PEAR/ChannelFile.php';
 194                          }
 195                          $pear_channel = new PEAR_ChannelFile;
 196                          $pear_channel->setName('pear.php.net');
 197                          $pear_channel->setAlias('pear');
 198                          $pear_channel->setServer('pear.php.net');
 199                          $pear_channel->setSummary('PHP Extension and Application Repository');
 200                          $pear_channel->setDefaultPEARProtocols();
 201                          $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
 202                          $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
 203                      } else {
 204                          $pear_channel->setName('pear.php.net');
 205                          $pear_channel->setAlias('pear');
 206                      }
 207                      $pear_channel->validate();
 208                      $this->_addChannel($pear_channel);
 209                  }
 210                  if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
 211                      $pecl_channel = $this->_peclChannel;
 212                      if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
 213                          if (!class_exists('PEAR_ChannelFile')) {
 214                              require_once  'PEAR/ChannelFile.php';
 215                          }
 216                          $pecl_channel = new PEAR_ChannelFile;
 217                          $pecl_channel->setName('pecl.php.net');
 218                          $pecl_channel->setAlias('pecl');
 219                          $pecl_channel->setServer('pecl.php.net');
 220                          $pecl_channel->setSummary('PHP Extension Community Library');
 221                          $pecl_channel->setDefaultPEARProtocols();
 222                          $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
 223                          $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
 224                          $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
 225                      } else {
 226                          $pecl_channel->setName('pecl.php.net');
 227                          $pecl_channel->setAlias('pecl');
 228                      }
 229                      $pecl_channel->validate();
 230                      $this->_addChannel($pecl_channel);
 231                  }
 232                  if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
 233                      if (!class_exists('PEAR_ChannelFile')) {
 234                          require_once  'PEAR/ChannelFile.php';
 235                      }
 236                      $private = new PEAR_ChannelFile;
 237                      $private->setName('__uri');
 238                      $private->addFunction('xmlrpc', '1.0', '****');
 239                      $private->setSummary('Pseudo-channel for static packages');
 240                      $this->_addChannel($private);
 241                  }
 242                  $this->_rebuildFileMap();
 243              }
 244              $running = false;
 245          }
 246      }
 247  
 248      function _initializeDirs()
 249      {
 250          $ds = DIRECTORY_SEPARATOR;
 251          // XXX Compatibility code should be removed in the future
 252          // rename all registry files if any to lowercase
 253          if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
 254                $handle = opendir($this->statedir)) {
 255              $dest = $this->statedir . $ds;
 256              while (false !== ($file = readdir($handle))) {
 257                  if (preg_match('/^.*[A-Z].*\.reg$/', $file)) {
 258                      rename($dest . $file, $dest . strtolower($file));
 259                  }
 260              }
 261              closedir($handle);
 262          }
 263          $this->_initializeChannelDirs();
 264          if (!file_exists($this->filemap)) {
 265              $this->_rebuildFileMap();
 266          }
 267          $this->_initializeDepDB();
 268      }
 269  
 270      function _initializeDepDB()
 271      {
 272          if (!isset($this->_dependencyDB)) {
 273              static $initializing = false;
 274              if (!$initializing) {
 275                  $initializing = true;
 276                  if (!$this->_config) { // never used?
 277                      if (OS_WINDOWS) {
 278                          $file = 'pear.ini';
 279                      } else {
 280                          $file = '.pearrc';
 281                      }
 282                      $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
 283                          $file);
 284                      $this->_config->setRegistry($this);
 285                      $this->_config->set('php_dir', $this->install_dir);
 286                  }
 287                  $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
 288                  if (PEAR::isError($this->_dependencyDB)) {
 289                      // attempt to recover by removing the dep db
 290                      if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') .
 291                          DIRECTORY_SEPARATOR . '.depdb')) {
 292                          @unlink($this->_config->get('php_dir', null, 'pear.php.net') .
 293                              DIRECTORY_SEPARATOR . '.depdb');
 294                      }
 295                      $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
 296                      if (PEAR::isError($this->_dependencyDB)) {
 297                          echo $this->_dependencyDB->getMessage();
 298                          echo 'Unrecoverable error';
 299                          exit(1);
 300                      }
 301                  }
 302                  $initializing = false;
 303              }
 304          }
 305      }
 306      // }}}
 307      // {{{ destructor
 308  
 309      /**
 310       * PEAR_Registry destructor.  Makes sure no locks are forgotten.
 311       *
 312       * @access private
 313       */
 314      function _PEAR_Registry()
 315      {
 316          parent::_PEAR();
 317          if (is_resource($this->lock_fp)) {
 318              $this->_unlock();
 319          }
 320      }
 321  
 322      // }}}
 323  
 324      // {{{ _assertStateDir()
 325  
 326      /**
 327       * Make sure the directory where we keep registry files exists.
 328       *
 329       * @return bool TRUE if directory exists, FALSE if it could not be
 330       * created
 331       *
 332       * @access private
 333       */
 334      function _assertStateDir($channel = false)
 335      {
 336          if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
 337              return $this->_assertChannelStateDir($channel);
 338          }
 339          static $init = false;
 340          if (!file_exists($this->statedir)) {
 341              if (!$this->hasWriteAccess()) {
 342                  return false;
 343              }
 344              require_once  'System.php';
 345              if (!System::mkdir(array('-p', $this->statedir))) {
 346                  return $this->raiseError("could not create directory '{$this->statedir}'");
 347              }
 348              $init = true;
 349          } elseif (!is_dir($this->statedir)) {
 350              return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
 351                  'it already exists and is not a directory');
 352          }
 353          $ds = DIRECTORY_SEPARATOR;
 354          if (!file_exists($this->channelsdir)) {
 355              if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
 356                    !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
 357                    !file_exists($this->channelsdir . $ds . '__uri.reg')) {
 358                  $init = true;
 359              }
 360          } elseif (!is_dir($this->channelsdir)) {
 361              return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
 362                  'it already exists and is not a directory');
 363          }
 364          if ($init) {
 365              static $running = false;
 366              if (!$running) {
 367                  $running = true;
 368                  $this->_initializeDirs();
 369                  $running = false;
 370                  $init = false;
 371              }
 372          } else {
 373              $this->_initializeDepDB();
 374          }
 375          return true;
 376      }
 377  
 378      // }}}
 379      // {{{ _assertChannelStateDir()
 380  
 381      /**
 382       * Make sure the directory where we keep registry files exists for a non-standard channel.
 383       *
 384       * @param string channel name
 385       * @return bool TRUE if directory exists, FALSE if it could not be
 386       * created
 387       *
 388       * @access private
 389       */
 390      function _assertChannelStateDir($channel)
 391      {
 392          $ds = DIRECTORY_SEPARATOR;
 393          if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
 394              if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
 395                  $this->_initializeChannelDirs();
 396              }
 397              return $this->_assertStateDir($channel);
 398          }
 399          $channelDir = $this->_channelDirectoryName($channel);
 400          if (!is_dir($this->channelsdir) ||
 401                !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
 402              $this->_initializeChannelDirs();
 403          }
 404          if (!file_exists($channelDir)) {
 405              if (!$this->hasWriteAccess()) {
 406                  return false;
 407              }
 408              require_once  'System.php';
 409              if (!System::mkdir(array('-p', $channelDir))) {
 410                  return $this->raiseError("could not create directory '" . $channelDir .
 411                      "'");
 412              }
 413          } elseif (!is_dir($channelDir)) {
 414              return $this->raiseError("could not create directory '" . $channelDir .
 415                  "', already exists and is not a directory");
 416          }
 417          return true;
 418      }
 419  
 420      // }}}
 421      // {{{ _assertChannelDir()
 422  
 423      /**
 424       * Make sure the directory where we keep registry files for channels exists
 425       *
 426       * @return bool TRUE if directory exists, FALSE if it could not be
 427       * created
 428       *
 429       * @access private
 430       */
 431      function _assertChannelDir()
 432      {
 433          if (!file_exists($this->channelsdir)) {
 434              if (!$this->hasWriteAccess()) {
 435                  return false;
 436              }
 437              require_once  'System.php';
 438              if (!System::mkdir(array('-p', $this->channelsdir))) {
 439                  return $this->raiseError("could not create directory '{$this->channelsdir}'");
 440              }
 441          } elseif (!is_dir($this->channelsdir)) {
 442              return $this->raiseError("could not create directory '{$this->channelsdir}" .
 443                  "', it already exists and is not a directory");
 444              
 445          }
 446          if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
 447              if (!$this->hasWriteAccess()) {
 448                  return false;
 449              }
 450              require_once  'System.php';
 451              if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
 452                  return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
 453              }
 454          } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
 455              return $this->raiseError("could not create directory '{$this->channelsdir}" .
 456                  "/.alias', it already exists and is not a directory");
 457              
 458          }
 459          return true;
 460      }
 461  
 462      // }}}
 463      // {{{ _packageFileName()
 464  
 465      /**
 466       * Get the name of the file where data for a given package is stored.
 467       *
 468       * @param string channel name, or false if this is a PEAR package
 469       * @param string package name
 470       *
 471       * @return string registry file name
 472       *
 473       * @access public
 474       */
 475      function _packageFileName($package, $channel = false)
 476      {
 477          if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
 478              return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
 479                  strtolower($package) . '.reg';
 480          }
 481          return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
 482      }
 483  
 484      // }}}
 485      // {{{ _channelFileName()
 486  
 487      /**
 488       * Get the name of the file where data for a given channel is stored.
 489       * @param string channel name
 490       * @return string registry file name
 491       */
 492      function _channelFileName($channel, $noaliases = false)
 493      {
 494          if (!$noaliases) {
 495              if (file_exists($this->_getChannelAliasFileName($channel))) {
 496                  $channel = implode('', file($this->_getChannelAliasFileName($channel)));
 497              }
 498          }
 499          return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
 500              strtolower($channel)) . '.reg';
 501      }
 502  
 503      // }}}
 504      // {{{ getChannelAliasFileName()
 505  
 506      /**
 507       * @param string
 508       * @return string
 509       */
 510      function _getChannelAliasFileName($alias)
 511      {
 512          return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
 513                DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
 514      }
 515  
 516      // }}}
 517      // {{{ _getChannelFromAlias()
 518  
 519      /**
 520       * Get the name of a channel from its alias
 521       */
 522      function _getChannelFromAlias($channel)
 523      {
 524          if (!$this->_channelExists($channel)) {
 525              if ($channel == 'pear.php.net') {
 526                  return 'pear.php.net';
 527              }
 528              if ($channel == 'pecl.php.net') {
 529                  return 'pecl.php.net';
 530              }
 531              if ($channel == '__uri') {
 532                  return '__uri';
 533              }
 534              return false;
 535          }
 536          $channel = strtolower($channel);
 537          if (file_exists($this->_getChannelAliasFileName($channel))) {
 538              // translate an alias to an actual channel
 539              return implode('', file($this->_getChannelAliasFileName($channel)));
 540          } else {
 541              return $channel;
 542          }
 543      }    
 544      // }}}
 545      // {{{ _getChannelFromAlias()
 546  
 547      /**
 548       * Get the alias of a channel from its alias or its name
 549       */
 550      function _getAlias($channel)
 551      {
 552          if (!$this->_channelExists($channel)) {
 553              if ($channel == 'pear.php.net') {
 554                  return 'pear';
 555              }
 556              if ($channel == 'pecl.php.net') {
 557                  return 'pecl';
 558              }
 559              return false;
 560          }
 561          $channel = $this->_getChannel($channel);
 562          if (PEAR::isError($channel)) {
 563              return $channel;
 564          }
 565          return $channel->getAlias();
 566      }    
 567      // }}}
 568      // {{{ _channelDirectoryName()
 569  
 570      /**
 571       * Get the name of the file where data for a given package is stored.
 572       *
 573       * @param string channel name, or false if this is a PEAR package
 574       * @param string package name
 575       *
 576       * @return string registry file name
 577       *
 578       * @access public
 579       */
 580      function _channelDirectoryName($channel)
 581      {
 582          if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
 583              return $this->statedir;
 584          } else {
 585              $ch = $this->_getChannelFromAlias($channel);
 586              if (!$ch) {
 587                  $ch = $channel;
 588              }
 589              return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
 590                  str_replace('/', '_', $ch));
 591          }
 592      }
 593  
 594      // }}}
 595      // {{{ _openPackageFile()
 596  
 597      function _openPackageFile($package, $mode, $channel = false)
 598      {
 599          if (!$this->_assertStateDir($channel)) {
 600              return null;
 601          }
 602          if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
 603              return null;
 604          }
 605          $file = $this->_packageFileName($package, $channel);
 606          if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
 607              return null;
 608          }
 609          $fp = @fopen($file, $mode);
 610          if (!$fp) {
 611              return null;
 612          }
 613          return $fp;
 614      }
 615  
 616      // }}}
 617      // {{{ _closePackageFile()
 618  
 619      function _closePackageFile($fp)
 620      {
 621          fclose($fp);
 622      }
 623  
 624      // }}}
 625      // {{{ _openChannelFile()
 626  
 627      function _openChannelFile($channel, $mode)
 628      {
 629          if (!$this->_assertChannelDir()) {
 630              return null;
 631          }
 632          if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
 633              return null;
 634          }
 635          $file = $this->_channelFileName($channel);
 636          if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
 637              return null;
 638          }
 639          $fp = @fopen($file, $mode);
 640          if (!$fp) {
 641              return null;
 642          }
 643          return $fp;
 644      }
 645  
 646      // }}}
 647      // {{{ _closePackageFile()
 648  
 649      function _closeChannelFile($fp)
 650      {
 651          fclose($fp);
 652      }
 653  
 654      // }}}
 655      // {{{ _rebuildFileMap()
 656  
 657      function _rebuildFileMap()
 658      {
 659          if (!class_exists('PEAR_Installer_Role')) {
 660              require_once  'PEAR/Installer/Role.php';
 661          }
 662          $channels = $this->_listAllPackages();
 663          $files = array();
 664          foreach ($channels as $channel => $packages) {
 665              foreach ($packages as $package) {
 666                  $version = $this->_packageInfo($package, 'version', $channel);
 667                  $filelist = $this->_packageInfo($package, 'filelist', $channel);
 668                  if (!is_array($filelist)) {
 669                      continue;
 670                  }
 671                  foreach ($filelist as $name => $attrs) {
 672                      if (isset($attrs['attribs'])) {
 673                          $attrs = $attrs['attribs'];
 674                      }
 675                      // it is possible for conflicting packages in different channels to
 676                      // conflict with data files/doc files
 677                      if ($name == 'dirtree') {
 678                          continue;
 679                      }
 680                      if (isset($attrs['role']) && !in_array($attrs['role'],
 681                            PEAR_Installer_Role::getInstallableRoles())) {
 682                          // these are not installed
 683                          continue;
 684                      }
 685                      if (isset($attrs['role']) && !in_array($attrs['role'],
 686                            PEAR_Installer_Role::getBaseinstallRoles())) {
 687                          $attrs['baseinstalldir'] = $package;
 688                      }
 689                      if (isset($attrs['baseinstalldir'])) {
 690                          $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
 691                      } else {
 692                          $file = $name;
 693                      }
 694                      $file = preg_replace(',^/+,', '', $file);
 695                      if ($channel != 'pear.php.net') {
 696                          $files[$attrs['role']][$file] = array(strtolower($channel),
 697                              strtolower($package));
 698                      } else {
 699                          if (!is_array($files)) {
 700                              $file = array();
 701                          }
 702                          if (!isset($files[$attrs['role']])) {
 703                              $files[$attrs['role']] = array();
 704                          }
 705                          $files[$attrs['role']][$file] = strtolower($package);
 706                      }
 707                  }
 708              }
 709          }
 710          $this->_assertStateDir();
 711          if (!$this->hasWriteAccess()) {
 712              return false;
 713          }
 714          $fp = @fopen($this->filemap, 'wb');
 715          if (!$fp) {
 716              return false;
 717          }
 718          $this->filemap_cache = $files;
 719          fwrite($fp, serialize($files));
 720          fclose($fp);
 721          return true;
 722      }
 723  
 724      // }}}
 725      // {{{ _readFileMap()
 726  
 727      function _readFileMap()
 728      {
 729          if (!file_exists($this->filemap)) {
 730              return array();
 731          }
 732          $fp = @fopen($this->filemap, 'r');
 733          if (!$fp) {
 734              return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
 735          }
 736          clearstatcache();
 737          $rt = get_magic_quotes_runtime();
 738          set_magic_quotes_runtime(0);
 739          $fsize = filesize($this->filemap);
 740          fclose($fp);
 741          $data = file_get_contents($this->filemap);
 742          set_magic_quotes_runtime($rt);
 743          $tmp = unserialize($data);
 744          if (!$tmp && $fsize > 7) {
 745              return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
 746          }
 747          $this->filemap_cache = $tmp;
 748          return true;
 749      }
 750  
 751      // }}}
 752      // {{{ _lock()
 753  
 754      /**
 755       * Lock the registry.
 756       *
 757       * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
 758       *                See flock manual for more information.
 759       *
 760       * @return bool TRUE on success, FALSE if locking failed, or a
 761       *              PEAR error if some other error occurs (such as the
 762       *              lock file not being writable).
 763       *
 764       * @access private
 765       */
 766      function _lock($mode = LOCK_EX)
 767      {
 768          if (!eregi('Windows 9', php_uname())) {
 769              if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
 770                  // XXX does not check type of lock (LOCK_SH/LOCK_EX)
 771                  return true;
 772              }
 773              if (!$this->_assertStateDir()) {
 774                  if ($mode == LOCK_EX) {
 775                      return $this->raiseError('Registry directory is not writeable by the current user');
 776                  } else {
 777                      return true;
 778                  }
 779              }
 780              $open_mode = 'w';
 781              // XXX People reported problems with LOCK_SH and 'w'
 782              if ($mode === LOCK_SH || $mode === LOCK_UN) {
 783                  if (!file_exists($this->lockfile)) {
 784                      touch($this->lockfile);
 785                  }
 786                  $open_mode = 'r';
 787              }
 788  
 789              if (!is_resource($this->lock_fp)) {
 790                  $this->lock_fp = @fopen($this->lockfile, $open_mode);
 791              }
 792  
 793              if (!is_resource($this->lock_fp)) {
 794                  return $this->raiseError("could not create lock file" .
 795                                           (isset($php_errormsg) ? ": " . $php_errormsg : ""));
 796              }
 797              if (!(int)flock($this->lock_fp, $mode)) {
 798                  switch ($mode) {
 799                      case LOCK_SH: $str = 'shared';    break;
 800                      case LOCK_EX: $str = 'exclusive'; break;
 801                      case LOCK_UN: $str = 'unlock';    break;
 802                      default:      $str = 'unknown';   break;
 803                  }
 804                  return $this->raiseError("could not acquire $str lock ($this->lockfile)",
 805                                           PEAR_REGISTRY_ERROR_LOCK);
 806              }
 807          }
 808          return true;
 809      }
 810  
 811      // }}}
 812      // {{{ _unlock()
 813  
 814      function _unlock()
 815      {
 816          $ret = $this->_lock(LOCK_UN);
 817          if (is_resource($this->lock_fp)) {
 818              fclose($this->lock_fp);
 819          }
 820          $this->lock_fp = null;
 821          return $ret;
 822      }
 823  
 824      // }}}
 825      // {{{ _packageExists()
 826  
 827      function _packageExists($package, $channel = false)
 828      {
 829          return file_exists($this->_packageFileName($package, $channel));
 830      }
 831  
 832      // }}}
 833      // {{{ _channelExists()
 834  
 835      /**
 836       * Determine whether a channel exists in the registry
 837       * @param string Channel name
 838       * @param bool if true, then aliases will be ignored
 839       * @return boolean
 840       */
 841      function _channelExists($channel, $noaliases = false)
 842      {
 843          $a = file_exists($this->_channelFileName($channel, $noaliases));
 844          if (!$a && $channel == 'pear.php.net') {
 845              return true;
 846          }
 847          if (!$a && $channel == 'pecl.php.net') {
 848              return true;
 849          }
 850          return $a;
 851      }
 852  
 853      // }}}
 854      // {{{ _addChannel()
 855  
 856      /**
 857       * @param PEAR_ChannelFile Channel object
 858       * @param donotuse
 859       * @param string Last-Modified HTTP tag from remote request
 860       * @return boolean|PEAR_Error True on creation, false if it already exists
 861       */
 862      function _addChannel($channel, $update = false, $lastmodified = false)
 863      {
 864          if (!is_a($channel, 'PEAR_ChannelFile')) {
 865              return false;
 866          }
 867          if (!$channel->validate()) {
 868              return false;
 869          }
 870          if (file_exists($this->_channelFileName($channel->getName()))) {
 871              if (!$update) {
 872                  return false;
 873              }
 874              $checker = $this->_getChannel($channel->getName());
 875              if (PEAR::isError($checker)) {
 876                  return $checker;
 877              }
 878              if ($channel->getAlias() != $checker->getAlias()) {
 879                  if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
 880                      @unlink($this->_getChannelAliasFileName($checker->getAlias()));
 881                  }
 882              }
 883          } else {
 884              if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net'))) {
 885                  return false;
 886              }
 887          }
 888          $ret = $this->_assertChannelDir();
 889          if (PEAR::isError($ret)) {
 890              return $ret;
 891          }
 892          $ret = $this->_assertChannelStateDir($channel->getName());
 893          if (PEAR::isError($ret)) {
 894              return $ret;
 895          }
 896          if ($channel->getAlias() != $channel->getName()) {
 897              if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
 898                    $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
 899                  $channel->setAlias($channel->getName());
 900              }
 901              if (!$this->hasWriteAccess()) {
 902                  return false;
 903              }
 904              $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
 905              if (!$fp) {
 906                  return false;
 907              }
 908              fwrite($fp, $channel->getName());
 909              fclose($fp);
 910          }
 911          if (!$this->hasWriteAccess()) {
 912              return false;
 913          }
 914          $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
 915          if (!$fp) {
 916              return false;
 917          }
 918          $info = $channel->toArray();
 919          if ($lastmodified) {
 920              $info['_lastmodified'] = $lastmodified;
 921          } else {
 922              $info['_lastmodified'] = date('r');
 923          }
 924          fwrite($fp, serialize($info));
 925          fclose($fp);
 926          return true;
 927      }
 928  
 929      // }}}
 930      // {{{ _deleteChannel()
 931  
 932      /**
 933       * Deletion fails if there are any packages installed from the channel
 934       * @param string|PEAR_ChannelFile channel name
 935       * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
 936       */
 937      function _deleteChannel($channel)
 938      {
 939          if (!is_string($channel)) {
 940              if (is_a($channel, 'PEAR_ChannelFile')) {
 941                  if (!$channel->validate()) {
 942                      return false;
 943                  }
 944                  $channel = $channel->getName();
 945              } else {
 946                  return false;
 947              }
 948          }
 949          if ($this->_getChannelFromAlias($channel) == '__uri') {
 950              return false;
 951          }
 952          if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
 953              return false;
 954          }
 955          if (!$this->_channelExists($channel)) {
 956              return false;
 957          }
 958          if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
 959              return false;
 960          }
 961          $channel = $this->_getChannelFromAlias($channel);
 962          if ($channel == 'pear.php.net') {
 963              return false;
 964          }
 965          $test = $this->_listChannelPackages($channel);
 966          if (count($test)) {
 967              return false;
 968          }
 969          $test = @rmdir($this->_channelDirectoryName($channel));
 970          if (!$test) {
 971              return false;
 972          }
 973          $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
 974          if (file_exists($file)) {
 975              $test = @unlink($file);
 976              if (!$test) {
 977                  return false;
 978              }
 979          }
 980          $file = $this->_channelFileName($channel);
 981          $ret = true;
 982          if (file_exists($file)) {
 983              $ret = @unlink($file);
 984          }
 985          return $ret;
 986      }
 987  
 988      // }}}
 989      // {{{ _isChannelAlias()
 990  
 991      /**
 992       * Determine whether a channel exists in the registry
 993       * @param string Channel Alias
 994       * @return boolean
 995       */
 996      function _isChannelAlias($alias)
 997      {
 998          return file_exists($this->_getChannelAliasFileName($alias));
 999      }
1000  
1001      // }}}
1002      // {{{ _packageInfo()
1003  
1004      /**
1005       * @param string|null
1006       * @param string|null
1007       * @param string|null
1008       * @return array|null
1009       * @access private
1010       */
1011      function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
1012      {
1013          if ($package === null) {
1014              if ($channel === null) {
1015                  $channels = $this->_listChannels();
1016                  $ret = array();
1017                  foreach ($channels as $channel) {
1018                      $channel = strtolower($channel);
1019                      $ret[$channel] = array();
1020                      $packages = $this->_listPackages($channel);
1021                      foreach ($packages as $package) {
1022                          $ret[$channel][] = $this->_packageInfo($package, null, $channel);
1023                      }
1024                  }
1025                  return $ret;
1026              }
1027              $ps = $this->_listPackages($channel);
1028              if (!count($ps)) {
1029                  return array();
1030              }
1031              return array_map(array(&$this, '_packageInfo'),
1032                               $ps, array_fill(0, count($ps), null),
1033                               array_fill(0, count($ps), $channel));
1034          }
1035          $fp = $this->_openPackageFile($package, 'r', $channel);
1036          if ($fp === null) {
1037              return null;
1038          }
1039          $rt = get_magic_quotes_runtime();
1040          set_magic_quotes_runtime(0);
1041          clearstatcache();
1042          $this->_closePackageFile($fp);
1043          $data = file_get_contents($this->_packageFileName($package, $channel));
1044          set_magic_quotes_runtime($rt);
1045          $data = unserialize($data);
1046          if ($key === null) {
1047              return $data;
1048          }
1049          // compatibility for package.xml version 2.0
1050          if (isset($data['old'][$key])) {
1051              return $data['old'][$key];
1052          }
1053          if (isset($data[$key])) {
1054              return $data[$key];
1055          }
1056          return null;
1057      }
1058  
1059      // }}}
1060      // {{{ _channelInfo()
1061  
1062      /**
1063       * @param string Channel name
1064       * @param bool whether to strictly retrieve info of channels, not just aliases
1065       * @return array|null
1066       */
1067      function _channelInfo($channel, $noaliases = false)
1068      {
1069          if (!$this->_channelExists($channel, $noaliases)) {
1070              return null;
1071          }
1072          $fp = $this->_openChannelFile($channel, 'r');
1073          if ($fp === null) {
1074              return null;
1075          }
1076          $rt = get_magic_quotes_runtime();
1077          set_magic_quotes_runtime(0);
1078          clearstatcache();
1079          $this->_closeChannelFile($fp);
1080          $data = file_get_contents($this->_channelFileName($channel));
1081          set_magic_quotes_runtime($rt);
1082          $data = unserialize($data);
1083          return $data;
1084      }
1085  
1086      // }}}
1087      // {{{ _listChannels()
1088  
1089      function _listChannels()
1090      {
1091          $channellist = array();
1092          if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
1093              return array('pear.php.net', 'pecl.php.net', '__uri');
1094          }
1095          $dp = opendir($this->channelsdir);
1096          while ($ent = readdir($dp)) {
1097              if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
1098                  continue;
1099              }
1100              if ($ent == '__uri.reg') {
1101                  $channellist[] = '__uri';
1102                  continue;
1103              }
1104              $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
1105          }
1106          closedir($dp);
1107          if (!in_array('pear.php.net', $channellist)) {
1108              $channellist[] = 'pear.php.net';
1109          }
1110          if (!in_array('pecl.php.net', $channellist)) {
1111              $channellist[] = 'pecl.php.net';
1112          }
1113          if (!in_array('__uri', $channellist)) {
1114              $channellist[] = '__uri';
1115          }
1116          return $channellist;
1117      }
1118  
1119      // }}}
1120      // {{{ _listPackages()
1121  
1122      function _listPackages($channel = false)
1123      {
1124          if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
1125              return $this->_listChannelPackages($channel);
1126          }
1127          if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
1128              return array();
1129          }
1130          $pkglist = array();
1131          $dp = opendir($this->statedir);
1132          if (!$dp) {
1133              return $pkglist;
1134          }
1135          while ($ent = readdir($dp)) {
1136              if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
1137                  continue;
1138              }
1139              $pkglist[] = substr($ent, 0, -4);
1140          }
1141          closedir($dp);
1142          return $pkglist;
1143      }
1144  
1145      // }}}
1146      // {{{ _listChannelPackages()
1147  
1148      function _listChannelPackages($channel)
1149      {
1150          $pkglist = array();
1151          if (!file_exists($this->_channelDirectoryName($channel)) ||
1152                !is_dir($this->_channelDirectoryName($channel))) {
1153              return array();
1154          }
1155          $dp = opendir($this->_channelDirectoryName($channel));
1156          if (!$dp) {
1157              return $pkglist;
1158          }
1159          while ($ent = readdir($dp)) {
1160              if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
1161                  continue;
1162              }
1163              $pkglist[] = substr($ent, 0, -4);
1164          }
1165          closedir($dp);
1166          return $pkglist;
1167      }
1168  
1169      // }}}
1170      
1171      function _listAllPackages()
1172      {
1173          $ret = array();
1174          foreach ($this->_listChannels() as $channel) {
1175              $ret[$channel] = $this->_listPackages($channel);
1176          }
1177          return $ret;
1178      }
1179  
1180      /**
1181       * Add an installed package to the registry
1182       * @param string package name
1183       * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
1184       * @return bool success of saving
1185       * @access private
1186       */
1187      function _addPackage($package, $info)
1188      {
1189          if ($this->_packageExists($package)) {
1190              return false;
1191          }
1192          $fp = $this->_openPackageFile($package, 'wb');
1193          if ($fp === null) {
1194              return false;
1195          }
1196          $info['_lastmodified'] = time();
1197          fwrite($fp, serialize($info));
1198          $this->_closePackageFile($fp);
1199          if (isset($info['filelist'])) {
1200              $this->_rebuildFileMap();
1201          }
1202          return true;
1203      }
1204  
1205      /**
1206       * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
1207       * @return bool
1208       * @access private
1209       */
1210      function _addPackage2($info)
1211      {
1212          if (!$info->validate()) {
1213              if (class_exists('PEAR_Common')) {
1214                  $ui = PEAR_Frontend::singleton();
1215                  if ($ui) {
1216                      foreach ($info->getValidationWarnings() as $err) {
1217                          $ui->log($err['message'], true);
1218                      }
1219                  }
1220              }
1221              return false;
1222          }
1223          $channel = $info->getChannel();
1224          $package = $info->getPackage();
1225          $save = $info;
1226          if ($this->_packageExists($package, $channel)) {
1227              return false;
1228          }
1229          if (!$this->_channelExists($channel, true)) {
1230              return false;
1231          }
1232          $info = $info->toArray(true);
1233          if (!$info) {
1234              return false;
1235          }
1236          $fp = $this->_openPackageFile($package, 'wb', $channel);
1237          if ($fp === null) {
1238              return false;
1239          }
1240          $info['_lastmodified'] = time();
1241          fwrite($fp, serialize($info));
1242          $this->_closePackageFile($fp);
1243          $this->_rebuildFileMap();
1244          return true;
1245      }
1246  
1247      /**
1248       * @param string Package name
1249       * @param array parsed package.xml 1.0
1250       * @param bool this parameter is only here for BC.  Don't use it.
1251       * @access private
1252       */
1253      function _updatePackage($package, $info, $merge = true)
1254      {
1255          $oldinfo = $this->_packageInfo($package);
1256          if (empty($oldinfo)) {
1257              return false;
1258          }
1259          $fp = $this->_openPackageFile($package, 'w');
1260          if ($fp === null) {
1261              return false;
1262          }
1263          if (is_object($info)) {
1264              $info = $info->toArray();
1265          }
1266          $info['_lastmodified'] = time();
1267          $newinfo = $info;
1268          if ($merge) {
1269              $info = array_merge($oldinfo, $info);
1270          } else {
1271              $diff = $info;
1272          }
1273          fwrite($fp, serialize($info));
1274          $this->_closePackageFile($fp);
1275          if (isset($newinfo['filelist'])) {
1276              $this->_rebuildFileMap();
1277          }
1278          return true;
1279      }
1280  
1281      /**
1282       * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
1283       * @return bool
1284       * @access private
1285       */
1286      function _updatePackage2($info)
1287      {
1288          if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
1289              return false;
1290          }
1291          $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
1292          if ($fp === null) {
1293              return false;
1294          }
1295          $save = $info;
1296          $info = $save->getArray(true);
1297          $info['_lastmodified'] = time();
1298          fwrite($fp, serialize($info));
1299          $this->_closePackageFile($fp);
1300          $this->_rebuildFileMap();
1301          return true;
1302      }
1303  
1304      /**
1305       * @param string Package name
1306       * @param string Channel name
1307       * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
1308       * @access private
1309       */
1310      function &_getPackage($package, $channel = 'pear.php.net')
1311      {
1312          $info = $this->_packageInfo($package, null, $channel);
1313          if ($info === null) {
1314              return $info;
1315          }
1316          $a = $this->_config;
1317          if (!$a) {
1318              $this->_config = &new PEAR_Config;
1319              $this->_config->set('php_dir', $this->statedir);
1320          }
1321          if (!class_exists('PEAR_PackageFile')) {
1322              require_once  'PEAR/PackageFile.php';
1323          }
1324          $pkg = &new PEAR_PackageFile($this->_config);
1325          $pf = &$pkg->fromArray($info);
1326          return $pf;
1327      }
1328  
1329      /**
1330       * @param string channel name
1331       * @param bool whether to strictly retrieve channel names
1332       * @return PEAR_ChannelFile|PEAR_Error
1333       * @access private
1334       */
1335      function &_getChannel($channel, $noaliases = false)
1336      {
1337          $ch = false;
1338          if ($this->_channelExists($channel, $noaliases)) {
1339              $chinfo = $this->_channelInfo($channel, $noaliases);
1340              if ($chinfo) {
1341                  if (!class_exists('PEAR_ChannelFile')) {
1342                      require_once  'PEAR/ChannelFile.php';
1343                  }
1344                  $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
1345              }
1346          }
1347          if ($ch) {
1348              if ($ch->validate()) {
1349                  return $ch;
1350              }
1351              foreach ($ch->getErrors(true) as $err) {
1352                  $message = $err['message'] . "\n";
1353              }
1354              $ch = PEAR::raiseError($message);
1355              return $ch;
1356          }
1357          if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
1358              // the registry is not properly set up, so use defaults
1359              if (!class_exists('PEAR_ChannelFile')) {
1360                  require_once  'PEAR/ChannelFile.php';
1361              }
1362              $pear_channel = new PEAR_ChannelFile;
1363              $pear_channel->setName('pear.php.net');
1364              $pear_channel->setAlias('pear');
1365              $pear_channel->setSummary('PHP Extension and Application Repository');
1366              $pear_channel->setDefaultPEARProtocols();
1367              $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
1368              $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
1369              return $pear_channel;
1370          }
1371          if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
1372              // the registry is not properly set up, so use defaults
1373              if (!class_exists('PEAR_ChannelFile')) {
1374                  require_once  'PEAR/ChannelFile.php';
1375              }
1376              $pear_channel = new PEAR_ChannelFile;
1377              $pear_channel->setName('pecl.php.net');
1378              $pear_channel->setAlias('pecl');
1379              $pear_channel->setSummary('PHP Extension Community Library');
1380              $pear_channel->setDefaultPEARProtocols();
1381              $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
1382              $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
1383              $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
1384              return $pear_channel;
1385          }
1386          if ($this->_getChannelFromAlias($channel) == '__uri') {
1387              // the registry is not properly set up, so use defaults
1388              if (!class_exists('PEAR_ChannelFile')) {
1389                  require_once  'PEAR/ChannelFile.php';
1390              }
1391              $private = new PEAR_ChannelFile;
1392              $private->setName('__uri');
1393              $private->addFunction('xmlrpc', '1.0', '****');
1394              $private->setSummary('Pseudo-channel for static packages');
1395              return $private;
1396          }
1397          return $ch;
1398      }
1399  
1400      // {{{ packageExists()
1401  
1402      /**
1403       * @param string Package name
1404       * @param string Channel name
1405       * @return bool
1406       */
1407      function packageExists($package, $channel = 'pear.php.net')
1408      {
1409          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1410              return $e;
1411          }
1412          $ret = $this->_packageExists($package, $channel);
1413          $this->_unlock();
1414          return $ret;
1415      }
1416  
1417      // }}}
1418  
1419      // {{{ channelExists()
1420  
1421      /**
1422       * @param string channel name
1423       * @param bool if true, then aliases will be ignored
1424       * @return bool
1425       */
1426      function channelExists($channel, $noaliases = false)
1427      {
1428          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1429              return $e;
1430          }
1431          $ret = $this->_channelExists($channel, $noaliases);
1432          $this->_unlock();
1433          return $ret;
1434      }
1435  
1436      // }}}
1437  
1438      // {{{ isAlias()
1439  
1440      /**
1441       * Determines whether the parameter is an alias of a channel
1442       * @param string
1443       * @return bool
1444       */
1445      function isAlias($alias)
1446      {
1447          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1448              return $e;
1449          }
1450          $ret = $this->_isChannelAlias($alias);
1451          $this->_unlock();
1452          return $ret;
1453      }
1454  
1455      // }}}
1456      // {{{ packageInfo()
1457  
1458      /**
1459       * @param string|null
1460       * @param string|null
1461       * @param string
1462       * @return array|null
1463       */
1464      function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
1465      {
1466          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1467              return $e;
1468          }
1469          $ret = $this->_packageInfo($package, $key, $channel);
1470          $this->_unlock();
1471          return $ret;
1472      }
1473  
1474      // }}}
1475      // {{{ channelInfo()
1476  
1477      /**
1478       * Retrieve a raw array of channel data.
1479       *
1480       * Do not use this, instead use {@link getChannel()} for normal
1481       * operations.  Array structure is undefined in this method
1482       * @param string channel name
1483       * @param bool whether to strictly retrieve information only on non-aliases
1484       * @return array|null|PEAR_Error
1485       */
1486      function channelInfo($channel = null, $noaliases = false)
1487      {
1488          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1489              return $e;
1490          }
1491          $ret = $this->_channelInfo($channel, $noaliases);
1492          $this->_unlock();
1493          return $ret;
1494      }
1495  
1496      // }}}
1497  
1498      /**
1499       * @param string
1500       */
1501      function channelName($channel)
1502      {
1503          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1504              return $e;
1505          }
1506          $ret = $this->_getChannelFromAlias($channel);
1507          $this->_unlock();
1508          return $ret;
1509      }
1510  
1511      /**
1512       * @param string
1513       */
1514      function channelAlias($channel)
1515      {
1516          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1517              return $e;
1518          }
1519          $ret = $this->_getAlias($channel);
1520          $this->_unlock();
1521          return $ret;
1522      }
1523      // {{{ listPackages()
1524  
1525      function listPackages($channel = false)
1526      {
1527          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1528              return $e;
1529          }
1530          $ret = $this->_listPackages($channel);
1531          $this->_unlock();
1532          return $ret;
1533      }
1534  
1535      // }}}
1536      // {{{ listAllPackages()
1537  
1538      function listAllPackages()
1539      {
1540          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1541              return $e;
1542          }
1543          $ret = $this->_listAllPackages();
1544          $this->_unlock();
1545          return $ret;
1546      }
1547  
1548      // }}}
1549      // {{{ listChannel()
1550  
1551      function listChannels()
1552      {
1553          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1554              return $e;
1555          }
1556          $ret = $this->_listChannels();
1557          $this->_unlock();
1558          return $ret;
1559      }
1560  
1561      // }}}
1562      // {{{ addPackage()
1563  
1564      /**
1565       * Add an installed package to the registry
1566       * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
1567       *               that will be passed to {@link addPackage2()}
1568       * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
1569       * @return bool success of saving
1570       */
1571      function addPackage($package, $info)
1572      {
1573          if (is_object($info)) {
1574              return $this->addPackage2($info);
1575          }
1576          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1577              return $e;
1578          }
1579          $ret = $this->_addPackage($package, $info);
1580          $this->_unlock();
1581          if ($ret) {
1582              if (!class_exists('PEAR_PackageFile_v1')) {
1583                  require_once  'PEAR/PackageFile/v1.php';
1584              }
1585              $pf = new PEAR_PackageFile_v1;
1586              $pf->setConfig($this->_config);
1587              $pf->fromArray($info);
1588              $this->_dependencyDB->uninstallPackage($pf);
1589              $this->_dependencyDB->installPackage($pf);
1590          }
1591          return $ret;
1592      }
1593  
1594      // }}}
1595      // {{{ addPackage2()
1596  
1597      function addPackage2($info)
1598      {
1599          if (!is_object($info)) {
1600              return $this->addPackage($info['package'], $info);
1601          }
1602          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1603              return $e;
1604          }
1605          $ret = $this->_addPackage2($info);
1606          $this->_unlock();
1607          if ($ret) {
1608              $this->_dependencyDB->uninstallPackage($info);
1609              $this->_dependencyDB->installPackage($info);
1610          }
1611          return $ret;
1612      }
1613  
1614      // }}}
1615      // {{{ updateChannel()
1616  
1617      /**
1618       * For future expandibility purposes, separate this
1619       * @param PEAR_ChannelFile
1620       */
1621      function updateChannel($channel, $lastmodified = null)
1622      {
1623          if ($channel->getName() == '__uri') {
1624              return false;
1625          }
1626          return $this->addChannel($channel, $lastmodified, true);
1627      }
1628  
1629      // }}}
1630      // {{{ deleteChannel()
1631  
1632      /**
1633       * Deletion fails if there are any packages installed from the channel
1634       * @param string|PEAR_ChannelFile channel name
1635       * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
1636       */
1637      function deleteChannel($channel)
1638      {
1639          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1640              return $e;
1641          }
1642          $ret = $this->_deleteChannel($channel);
1643          $this->_unlock();
1644          if ($ret && is_a($this->_config, 'PEAR_Config')) {
1645              $this->_config->setChannels($this->listChannels());
1646          }
1647          return $ret;
1648      }
1649  
1650      // }}}
1651      // {{{ addChannel()
1652  
1653      /**
1654       * @param PEAR_ChannelFile Channel object
1655       * @param string Last-Modified header from HTTP for caching
1656       * @return boolean|PEAR_Error True on creation, false if it already exists
1657       */
1658      function addChannel($channel, $lastmodified = false, $update = false)
1659      {
1660          if (!is_a($channel, 'PEAR_ChannelFile')) {
1661              return false;
1662          }
1663          if (!$channel->validate()) {
1664              return false;
1665          }
1666          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1667              return $e;
1668          }
1669          $ret = $this->_addChannel($channel, $update, $lastmodified);
1670          $this->_unlock();
1671          if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
1672              $this->_config->setChannels($this->listChannels());
1673          }
1674          return $ret;
1675      }
1676  
1677      // }}}
1678      // {{{ deletePackage()
1679  
1680      function deletePackage($package, $channel = 'pear.php.net')
1681      {
1682          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1683              return $e;
1684          }
1685          $file = $this->_packageFileName($package, $channel);
1686          if (file_exists($file)) {
1687              $ret = @unlink($file);
1688          } else {
1689              $ret = false;
1690          }
1691          $this->_rebuildFileMap();
1692          $this->_unlock();
1693          $p = array('channel' => $channel, 'package' => $package);
1694          $this->_dependencyDB->uninstallPackage($p);
1695          return $ret;
1696      }
1697  
1698      // }}}
1699      // {{{ updatePackage()
1700  
1701      function updatePackage($package, $info, $merge = true)
1702      {
1703          if (is_object($info)) {
1704              return $this->updatePackage2($info, $merge);
1705          }
1706          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1707              return $e;
1708          }
1709          $ret = $this->_updatePackage($package, $info, $merge);
1710          $this->_unlock();
1711          if ($ret) {
1712              if (!class_exists('PEAR_PackageFile_v1')) {
1713                  require_once  'PEAR/PackageFile/v1.php';
1714              }
1715              $pf = new PEAR_PackageFile_v1;
1716              $pf->setConfig($this->_config);
1717              $pf->fromArray($this->packageInfo($package));
1718              $this->_dependencyDB->uninstallPackage($pf);
1719              $this->_dependencyDB->installPackage($pf);
1720          }
1721          return $ret;
1722      }
1723  
1724      // }}}
1725      // {{{ updatePackage2()
1726  
1727      function updatePackage2($info)
1728      {
1729          if (!is_object($info)) {
1730              return $this->updatePackage($info['package'], $info, $merge);
1731          }
1732          if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
1733              return false;
1734          }
1735          if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
1736              return $e;
1737          }
1738          $ret = $this->_updatePackage2($info);
1739          $this->_unlock();
1740          if ($ret) {
1741              $this->_dependencyDB->uninstallPackage($info);
1742              $this->_dependencyDB->installPackage($info);
1743          }
1744          return $ret;
1745      }
1746  
1747      // }}}
1748      // {{{ getChannel()
1749      /**
1750       * @param string channel name
1751       * @param bool whether to strictly return raw channels (no aliases)
1752       * @return PEAR_ChannelFile|PEAR_Error
1753       */
1754      function &getChannel($channel, $noaliases = false)
1755      {
1756          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1757              return $e;
1758          }
1759          $ret = &$this->_getChannel($channel, $noaliases);
1760          if (!$ret) {
1761              return PEAR::raiseError('Unknown channel: ' . $channel);
1762          }
1763          $this->_unlock();
1764          return $ret;
1765      }
1766  
1767      // }}}
1768      // {{{ getPackage()
1769      /**
1770       * @param string package name
1771       * @param string channel name
1772       * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
1773       */
1774      function &getPackage($package, $channel = 'pear.php.net')
1775      {
1776          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1777              return $e;
1778          }
1779          $pf = &$this->_getPackage($package, $channel);
1780          $this->_unlock();
1781          return $pf;
1782      }
1783  
1784      // }}}
1785  
1786      /**
1787       * Get PEAR_PackageFile_v[1/2] objects representing the contents of
1788       * a dependency group that are installed.
1789       *
1790       * This is used at uninstall-time
1791       * @param array
1792       * @return array|false
1793       */
1794      function getInstalledGroup($group)
1795      {
1796          $ret = array();
1797          if (isset($group['package'])) {
1798              if (!isset($group['package'][0])) {
1799                  $group['package'] = array($group['package']);
1800              }
1801              foreach ($group['package'] as $package) {
1802                  $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
1803                  $p = &$this->getPackage($package['name'], $depchannel);
1804                  if ($p) {
1805                      $save = &$p;
1806                      $ret[] = &$save;
1807                  }
1808              }
1809          }
1810          if (isset($group['subpackage'])) {
1811              if (!isset($group['subpackage'][0])) {
1812                  $group['subpackage'] = array($group['subpackage']);
1813              }
1814              foreach ($group['subpackage'] as $package) {
1815                  $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
1816                  $p = &$this->getPackage($package['name'], $depchannel);
1817                  if ($p) {
1818                      $save = &$p;
1819                      $ret[] = &$save;
1820                  }
1821              }
1822          }
1823          if (!count($ret)) {
1824              return false;
1825          }
1826          return $ret;
1827      }
1828  
1829      // {{{ getChannelValidator()
1830      /**
1831       * @param string channel name
1832       * @return PEAR_Validate|false
1833       */
1834      function &getChannelValidator($channel)
1835      {
1836          $chan = $this->getChannel($channel);
1837          if (PEAR::isError($chan)) {
1838              return $chan;
1839          }
1840          $val = $chan->getValidationObject();
1841          return $val;
1842      }
1843      // }}}
1844      // {{{ getChannels()
1845      /**
1846       * @param string channel name
1847       * @return array an array of PEAR_ChannelFile objects representing every installed channel
1848       */
1849      function &getChannels()
1850      {
1851          $ret = array();
1852          if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1853              return $e;
1854          }
1855          foreach ($this->_listChannels() as $channel) {
1856              $e = &$this->_getChannel($channel);
1857              if (!$e || PEAR::isError($e)) {
1858                  continue;
1859              }
1860              $ret[] = $e;
1861          }
1862          $this->_unlock();
1863          return $ret;
1864      }
1865  
1866      // }}}
1867      // {{{ checkFileMap()
1868  
1869      /**
1870       * Test whether a file or set of files belongs to a package.
1871       *
1872       * If an array is passed in
1873       * @param string|array file path, absolute or relative to the pear
1874       *                     install dir
1875       * @param string|array name of PEAR package or array('package' => name, 'channel' =>
1876       *                     channel) of a package that will be ignored
1877       * @param string API version - 1.1 will exclude any files belonging to a package
1878       * @param array private recursion variable
1879       * @return array|false which package and channel the file belongs to, or an empty
1880       *                     string if the file does not belong to an installed package,
1881       *                     or belongs to the second parameter's package
1882       */
1883      function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
1884      {
1885          if (is_array($path)) {
1886              static $notempty;
1887              if (empty($notempty)) {
1888                  if (!class_exists('PEAR_Installer_Role')) {
1889                      require_once  'PEAR/Installer/Role.php';
1890                  }
1891                  $notempty = create_function('$a','return !empty($a);');
1892              }
1893              $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
1894                  : strtolower($package);
1895              $pkgs = array();
1896              foreach ($path as $name => $attrs) {
1897                  if (is_array($attrs)) {
1898                      if (isset($attrs['install-as'])) {
1899                          $name = $attrs['install-as'];
1900                      }
1901                      if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
1902                          // these are not installed
1903                          continue;
1904                      }
1905                      if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
1906                          $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
1907                      }
1908                      if (isset($attrs['baseinstalldir'])) {
1909                          $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
1910                      }
1911                  }
1912                  $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
1913                  if (PEAR::isError($pkgs[$name])) {
1914                      return $pkgs[$name];
1915                  }
1916              }
1917              return array_filter($pkgs, $notempty);
1918          }
1919          if (empty($this->filemap_cache)) {
1920              if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
1921                  return $e;
1922              }
1923              $err = $this->_readFileMap();
1924              $this->_unlock();
1925              if (PEAR::isError($err)) {
1926                  return $err;
1927              }
1928          }
1929          if (!$attrs) {
1930              $attrs = array('role' => 'php'); // any old call would be for PHP role only
1931          }
1932          if (isset($this->filemap_cache[$attrs['role']][$path])) {
1933              if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
1934                  return false;
1935              }
1936              return $this->filemap_cache[$attrs['role']][$path];
1937          }
1938          $l = strlen($this->install_dir);
1939          if (substr($path, 0, $l) == $this->install_dir) {
1940              $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
1941          }
1942          if (isset($this->filemap_cache[$attrs['role']][$path])) {
1943              if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
1944                  return false;
1945              }
1946              return $this->filemap_cache[$attrs['role']][$path];
1947          }
1948          return false;
1949      }
1950  
1951      // }}}
1952      // {{{ flush()
1953      /**
1954       * Force a reload of the filemap
1955       * @since 1.5.0RC3
1956       */
1957      function flushFileMap()
1958      {
1959          $this->filemap_cache = null;
1960          clearstatcache(); // ensure that the next read gets the full, current filemap
1961      }
1962  
1963      // }}}
1964      // {{{ apiVersion()
1965      /**
1966       * Get the expected API version.  Channels API is version 1.1, as it is backwards
1967       * compatible with 1.0
1968       * @return string
1969       */
1970      function apiVersion()
1971      {
1972          return '1.1';
1973      }
1974      // }}}
1975  
1976  
1977      /**
1978       * Parse a package name, or validate a parsed package name array
1979       * @param string|array pass in an array of format
1980       *                     array(
1981       *                      'package' => 'pname',
1982       *                     ['channel' => 'channame',]
1983       *                     ['version' => 'version',]
1984       *                     ['state' => 'state',]
1985       *                     ['group' => 'groupname'])
1986       *                     or a string of format
1987       *                     [channel://][channame/]pname[-version|-state][/group=groupname]
1988       * @return array|PEAR_Error
1989       */
1990      function parsePackageName($param, $defaultchannel = 'pear.php.net')
1991      {
1992          $saveparam = $param;
1993          if (is_array($param)) {
1994              // convert to string for error messages
1995              $saveparam = $this->parsedPackageNameToString($param);
1996              // process the array
1997              if (!isset($param['package'])) {
1998                  return PEAR::raiseError('parsePackageName(): array $param ' .
1999                      'must contain a valid package name in index "param"',
2000                      'package', null, null, $param);
2001              }
2002              if (!isset($param['uri'])) {
2003                  if (!isset($param['channel'])) {
2004                      $param['channel'] = $defaultchannel;
2005                  }
2006              } else {
2007                  $param['channel'] = '__uri';
2008              }
2009          } else {
2010              $components = @parse_url((string) $param);
2011              if (isset($components['scheme'])) {
2012                  if ($components['scheme'] == 'http') {
2013                      // uri package
2014                      $param = array('uri' => $param, 'channel' => '__uri');
2015                  } elseif($components['scheme'] != 'channel') {
2016                      return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
2017                          'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
2018                  }
2019              }
2020              if (!isset($components['path'])) {
2021                  return PEAR::raiseError('parsePackageName(): array $param ' .
2022                      'must contain a valid package name in "' . $param . '"',
2023                      'package', null, null, $param);
2024              }
2025              if (isset($components['host'])) {
2026                  // remove the leading "/"
2027                  $components['path'] = substr($components['path'], 1);
2028              }
2029              if (!isset($components['scheme'])) {
2030                  if (strpos($components['path'], '/') !== false) {
2031                      if ($components['path']{0} == '/') {
2032                          return PEAR::raiseError('parsePackageName(): this is not ' .
2033                              'a package name, it begins with "/" in "' . $param . '"',
2034                              'invalid', null, null, $param);
2035                      }
2036                      $parts = explode('/', $components['path']);
2037                      $components['host'] = array_shift($parts);
2038                      if (count($parts) > 1) {
2039                          $components['path'] = array_pop($parts);
2040                          $components['host'] .= '/' . implode('/', $parts);
2041                      } else {
2042                          $components['path'] = implode('/', $parts);
2043                      }
2044                  } else {
2045                      $components['host'] = $defaultchannel;
2046                  }
2047              } else {
2048                  if (strpos($components['path'], '/')) {
2049                      $parts = explode('/', $components['path']);
2050                      $components['path'] = array_pop($parts);
2051                      $components['host'] .= '/' . implode('/', $parts);
2052                  }
2053              }
2054  
2055              if (is_array($param)) {
2056                  $param['package'] = $components['path'];
2057              } else {
2058                  $param = array(
2059                      'package' => $components['path']
2060                      );
2061                  if (isset($components['host'])) {
2062                      $param['channel'] = $components['host'];
2063                  }
2064              }
2065              if (isset($components['fragment'])) {
2066                  $param['group'] = $components['fragment'];
2067              }
2068              if (isset($components['user'])) {
2069                  $param['user'] = $components['user'];
2070              }
2071              if (isset($components['pass'])) {
2072                  $param['pass'] = $components['pass'];
2073              }
2074              if (isset($components['query'])) {
2075                  parse_str($components['query'], $param['opts']);
2076              }
2077              // check for extension
2078              $pathinfo = pathinfo($param['package']);
2079              if (isset($pathinfo['extension']) &&
2080                    in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
2081                  $param['extension'] = $pathinfo['extension'];
2082                  $param['package'] = substr($pathinfo['basename'], 0,
2083                      strlen($pathinfo['basename']) - 4);
2084              }
2085              // check for version
2086              if (strpos($param['package'], '-')) {
2087                  $test = explode('-', $param['package']);
2088                  if (count($test) != 2) {
2089                      return PEAR::raiseError('parsePackageName(): only one version/state ' .
2090                          'delimiter "-" is allowed in "' . $saveparam . '"',
2091                          'version', null, null, $param);
2092                  }
2093                  list($param['package'], $param['version']) = $test;
2094              }
2095          }
2096          // validation
2097          $info = $this->channelExists($param['channel']);
2098          if (PEAR::isError($info)) {
2099              return $info;
2100          }
2101          if (!$info) {
2102              return PEAR::raiseError('unknown channel "' . $param['channel'] .
2103                  '" in "' . $saveparam . '"', 'channel', null, null, $param);
2104          }
2105          $chan = $this->getChannel($param['channel']);
2106          if (PEAR::isError($chan)) {
2107              return $chan;
2108          }
2109          if (!$chan) {
2110              return PEAR::raiseError("Exception: corrupt registry, could not " .
2111                  "retrieve channel " . $param['channel'] . " information",
2112                  'registry', null, null, $param);
2113          }
2114          $param['channel'] = $chan->getName();
2115          $validate = $chan->getValidationObject();
2116          $vpackage = $chan->getValidationPackage();
2117          // validate package name
2118          if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
2119              return PEAR::raiseError('parsePackageName(): invalid package name "' .
2120                  $param['package'] . '" in "' . $saveparam . '"',
2121                  'package', null, null, $param);
2122          }
2123          if (isset($param['group'])) {
2124              if (!PEAR_Validate::validGroupName($param['group'])) {
2125                  return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
2126                      '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
2127                      $param);
2128              }
2129          }
2130          if (isset($param['state'])) {
2131              if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
2132                  return PEAR::raiseError('parsePackageName(): state "' . $param['state']
2133                      . '" is not a valid state in "' . $saveparam . '"',
2134                      'state', null, null, $param);
2135              }
2136          }
2137          if (isset($param['version'])) {
2138              if (isset($param['state'])) {
2139                  return PEAR::raiseError('parsePackageName(): cannot contain both ' .
2140                      'a version and a stability (state) in "' . $saveparam . '"',
2141                      'version/state', null, null, $param);
2142              }
2143              // check whether version is actually a state
2144              if (in_array(strtolower($param['version']), $validate->getValidStates())) {
2145                  $param['state'] = strtolower($param['version']);
2146                  unset($param['version']);
2147              } else {
2148                  if (!$validate->validVersion($param['version'])) {
2149                      return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
2150                          '" is neither a valid version nor a valid state in "' .
2151                          $saveparam . '"', 'version/state', null, null, $param);
2152                  }                    
2153              }
2154          }
2155          return $param;
2156      }
2157  
2158      /**
2159       * @param array
2160       * @return string
2161       */
2162      function parsedPackageNameToString($parsed, $brief = false)
2163      {
2164          if (is_string($parsed)) {
2165              return $parsed;
2166          }
2167          if (is_object($parsed)) {
2168              $p = $parsed;
2169              $parsed = array(
2170                  'package' => $p->getPackage(),
2171                  'channel' => $p->getChannel(),
2172                  'version' => $p->getVersion(),
2173              );
2174          }
2175          if (isset($parsed['uri'])) {
2176              return $parsed['uri'];
2177          }
2178          if ($brief) {
2179              if ($channel = $this->channelAlias($parsed['channel'])) {
2180                  return $channel . '/' . $parsed['package'];
2181              }
2182          }
2183          $upass = '';
2184          if (isset($parsed['user'])) {
2185              $upass = $parsed['user'];
2186              if (isset($parsed['pass'])) {
2187                  $upass .= ':' . $parsed['pass'];
2188              }
2189              $upass = "$upass@";
2190          }
2191          $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
2192          if (isset($parsed['version']) || isset($parsed['state'])) {
2193              $ver = isset($parsed['version']) ? $parsed['version'] : '';
2194              $ver .= isset($parsed['state']) ? $parsed['state'] : '';
2195              $ret .= '-' . $ver;
2196          }
2197          if (isset($parsed['extension'])) {
2198              $ret .= '.' . $parsed['extension'];
2199          }
2200          if (isset($parsed['opts'])) {
2201              $ret .= '?';
2202              foreach ($parsed['opts'] as $name => $value) {
2203                  $parsed['opts'][$name] = "$name=$value";
2204              }
2205              $ret .= implode('&', $parsed['opts']);
2206          }
2207          if (isset($parsed['group'])) {
2208              $ret .= '#' . $parsed['group'];
2209          }
2210          return $ret;
2211      }
2212  }
2213  
2214  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7