[ Index ]
 

Code source de GeekLog 1.4.1

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

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


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