Rev 187 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** PEAR_Config, customized configuration handling for the PEAR Installer** PHP versions 4 and 5** @category pear* @package PEAR* @author Stig Bakken <ssb@php.net>* @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*//*** Required for error handling*/require_once 'PEAR.php';require_once 'PEAR/Registry.php';require_once 'PEAR/Installer/Role.php';require_once 'System.php';/*** Last created PEAR_Config instance.* @var object*/$GLOBALS['_PEAR_Config_instance'] = null;if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {$PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';} else {$PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;}// Below we define constants with default values for all configuration// parameters except username/password. All of them can have their// defaults set through environment variables. The reason we use the// PHP_ prefix is for some security, PHP protects environment// variables starting with PHP_*.// default channel and preferred mirror is based on whether we are invoked through// the "pear" or the "pecl" commandif (!defined('PEAR_RUNTYPE')) {define('PEAR_RUNTYPE', 'pear');}if (PEAR_RUNTYPE == 'pear') {define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');} else {define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');}if (getenv('PHP_PEAR_SYSCONF_DIR')) {define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));} elseif (getenv('SystemRoot')) {define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));} else {define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);}// Default for master_serverif (getenv('PHP_PEAR_MASTER_SERVER')) {define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));} else {define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');}// Default for http_proxyif (getenv('PHP_PEAR_HTTP_PROXY')) {define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));} elseif (getenv('http_proxy')) {define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));} else {define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');}// Default for php_dirif (getenv('PHP_PEAR_INSTALL_DIR')) {define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));} else {if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);} else {define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);}}// Default for metadata_dirif (getenv('PHP_PEAR_METADATA_DIR')) {define('PEAR_CONFIG_DEFAULT_METADATA_DIR', getenv('PHP_PEAR_METADATA_DIR'));} else {define('PEAR_CONFIG_DEFAULT_METADATA_DIR', '');}// Default for ext_dirif (getenv('PHP_PEAR_EXTENSION_DIR')) {define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));} else {if (ini_get('extension_dir')) {define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));} elseif (defined('PEAR_EXTENSION_DIR') &&file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);} elseif (defined('PHP_EXTENSION_DIR')) {define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);} else {define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');}}// Default for doc_dirif (getenv('PHP_PEAR_DOC_DIR')) {define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));} else {define('PEAR_CONFIG_DEFAULT_DOC_DIR',$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');}// Default for bin_dirif (getenv('PHP_PEAR_BIN_DIR')) {define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));} else {define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);}// Default for data_dirif (getenv('PHP_PEAR_DATA_DIR')) {define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));} else {define('PEAR_CONFIG_DEFAULT_DATA_DIR',$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');}// Default for cfg_dirif (getenv('PHP_PEAR_CFG_DIR')) {define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));} else {define('PEAR_CONFIG_DEFAULT_CFG_DIR',$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');}// Default for www_dirif (getenv('PHP_PEAR_WWW_DIR')) {define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));} else {define('PEAR_CONFIG_DEFAULT_WWW_DIR',$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');}// Default for man_dirif (getenv('PHP_PEAR_MAN_DIR')) {define('PEAR_CONFIG_DEFAULT_MAN_DIR', getenv('PHP_PEAR_MAN_DIR'));} else {if (defined('PHP_MANDIR')) { // Added in PHP5.3.7define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_MANDIR);} else {define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_PREFIX . DIRECTORY_SEPARATOR .'local' . DIRECTORY_SEPARATOR .'man');}}// Default for test_dirif (getenv('PHP_PEAR_TEST_DIR')) {define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));} else {define('PEAR_CONFIG_DEFAULT_TEST_DIR',$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');}// Default for temp_dirif (getenv('PHP_PEAR_TEMP_DIR')) {define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));} else {define('PEAR_CONFIG_DEFAULT_TEMP_DIR',System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .DIRECTORY_SEPARATOR . 'temp');}// Default for cache_dirif (getenv('PHP_PEAR_CACHE_DIR')) {define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));} else {define('PEAR_CONFIG_DEFAULT_CACHE_DIR',System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .DIRECTORY_SEPARATOR . 'cache');}// Default for download_dirif (getenv('PHP_PEAR_DOWNLOAD_DIR')) {define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));} else {define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .DIRECTORY_SEPARATOR . 'download');}// Default for php_binif (getenv('PHP_PEAR_PHP_BIN')) {define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));} else {define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));}// Default for verboseif (getenv('PHP_PEAR_VERBOSE')) {define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));} else {define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);}// Default for preferred_stateif (getenv('PHP_PEAR_PREFERRED_STATE')) {define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));} else {define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');}// Default for umaskif (getenv('PHP_PEAR_UMASK')) {define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));} else {define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));}// Default for cache_ttlif (getenv('PHP_PEAR_CACHE_TTL')) {define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));} else {define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);}// Default for sig_typeif (getenv('PHP_PEAR_SIG_TYPE')) {define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));} else {define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');}// Default for sig_binif (getenv('PHP_PEAR_SIG_BIN')) {define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));} else {define('PEAR_CONFIG_DEFAULT_SIG_BIN',System::which('gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));}// Default for sig_keydirif (getenv('PHP_PEAR_SIG_KEYDIR')) {define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));} else {define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');}/*** This is a class for storing configuration data, keeping track of* which are system-defined, user-defined or defaulted.* @category pear* @package PEAR* @author Stig Bakken <ssb@php.net>* @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.1* @link http://pear.php.net/package/PEAR* @since Class available since Release 0.1*/class PEAR_Config extends PEAR{/*** Array of config files used.** @var array layer => config file*/var $files = array('system' => '','user' => '',);var $layers = array();/*** Configuration data, two-dimensional array where the first* dimension is the config layer ('user', 'system' and 'default'),* and the second dimension is keyname => value.** The order in the first dimension is important! Earlier* layers will shadow later ones when a config value is* requested (if a 'user' value exists, it will be returned first,* then 'system' and finally 'default').** @var array layer => array(keyname => value, ...)*/var $configuration = array('user' => array(),'system' => array(),'default' => array(),);/*** Configuration values that can be set for a channel** All other configuration values can only have a global value* @var array* @access private*/var $_channelConfigInfo = array('php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir','test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username','password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini');/*** Channels that can be accessed* @see setChannels()* @var array* @access private*/var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');/*** This variable is used to control the directory values returned* @see setInstallRoot();* @var string|false* @access private*/var $_installRoot = false;/*** If requested, this will always refer to the registry* contained in php_dir* @var PEAR_Registry*/var $_registry = array();/*** @var array* @access private*/var $_regInitialized = array();/*** @var bool* @access private*/var $_noRegistry = false;/*** amount of errors found while parsing config* @var integer* @access private*/var $_errorsFound = 0;var $_lastError = null;/*** Information about the configuration data. Stores the type,* default value and a documentation string for each configuration* value.** @var array layer => array(infotype => value, ...)*/var $configuration_info = array(// Channels/Internet Access'default_channel' => array('type' => 'string','default' => PEAR_CONFIG_DEFAULT_CHANNEL,'doc' => 'the default channel to use for all non explicit commands','prompt' => 'Default Channel','group' => 'Internet Access',),'preferred_mirror' => array('type' => 'string','default' => PEAR_CONFIG_DEFAULT_CHANNEL,'doc' => 'the default server or mirror to use for channel actions','prompt' => 'Default Channel Mirror','group' => 'Internet Access',),'remote_config' => array('type' => 'password','default' => '','doc' => 'ftp url of remote configuration file to use for synchronized install','prompt' => 'Remote Configuration File','group' => 'Internet Access',),'auto_discover' => array('type' => 'integer','default' => 0,'doc' => 'whether to automatically discover new channels','prompt' => 'Auto-discover new Channels','group' => 'Internet Access',),// Internet Access'master_server' => array('type' => 'string','default' => 'pear.php.net','doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]','prompt' => 'PEAR server [DEPRECATED]','group' => 'Internet Access',),'http_proxy' => array('type' => 'string','default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,'doc' => 'HTTP proxy (host:port) to use when downloading packages','prompt' => 'HTTP Proxy Server Address','group' => 'Internet Access',),// File Locations'php_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_PHP_DIR,'doc' => 'directory where .php files are installed','prompt' => 'PEAR directory','group' => 'File Locations',),'ext_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_EXT_DIR,'doc' => 'directory where loadable extensions are installed','prompt' => 'PHP extension directory','group' => 'File Locations',),'doc_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_DOC_DIR,'doc' => 'directory where documentation is installed','prompt' => 'PEAR documentation directory','group' => 'File Locations',),'bin_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_BIN_DIR,'doc' => 'directory where executables are installed','prompt' => 'PEAR executables directory','group' => 'File Locations',),'data_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_DATA_DIR,'doc' => 'directory where data files are installed','prompt' => 'PEAR data directory','group' => 'File Locations (Advanced)',),'cfg_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_CFG_DIR,'doc' => 'directory where modifiable configuration files are installed','prompt' => 'PEAR configuration file directory','group' => 'File Locations (Advanced)',),'www_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_WWW_DIR,'doc' => 'directory where www frontend files (html/js) are installed','prompt' => 'PEAR www files directory','group' => 'File Locations (Advanced)',),'man_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_MAN_DIR,'doc' => 'directory where unix manual pages are installed','prompt' => 'Systems manpage files directory','group' => 'File Locations (Advanced)',),'test_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_TEST_DIR,'doc' => 'directory where regression tests are installed','prompt' => 'PEAR test directory','group' => 'File Locations (Advanced)',),'cache_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,'doc' => 'directory which is used for web service cache','prompt' => 'PEAR Installer cache directory','group' => 'File Locations (Advanced)',),'temp_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,'doc' => 'directory which is used for all temp files','prompt' => 'PEAR Installer temp directory','group' => 'File Locations (Advanced)',),'download_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,'doc' => 'directory which is used for all downloaded files','prompt' => 'PEAR Installer download directory','group' => 'File Locations (Advanced)',),'php_bin' => array('type' => 'file','default' => PEAR_CONFIG_DEFAULT_PHP_BIN,'doc' => 'PHP CLI/CGI binary for executing scripts','prompt' => 'PHP CLI/CGI binary','group' => 'File Locations (Advanced)',),'php_prefix' => array('type' => 'string','default' => '','doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs','prompt' => '--program-prefix passed to PHP\'s ./configure','group' => 'File Locations (Advanced)',),'php_suffix' => array('type' => 'string','default' => '','doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs','prompt' => '--program-suffix passed to PHP\'s ./configure','group' => 'File Locations (Advanced)',),'php_ini' => array('type' => 'file','default' => '','doc' => 'location of php.ini in which to enable PECL extensions on install','prompt' => 'php.ini location','group' => 'File Locations (Advanced)',),'metadata_dir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_METADATA_DIR,'doc' => 'directory where metadata files are installed (registry, filemap, channels, ...)','prompt' => 'PEAR metadata directory','group' => 'File Locations (Advanced)',),// Maintainers'username' => array('type' => 'string','default' => '','doc' => '(maintainers) your PEAR account name','prompt' => 'PEAR username (for maintainers)','group' => 'Maintainers',),'password' => array('type' => 'password','default' => '','doc' => '(maintainers) your PEAR account password','prompt' => 'PEAR password (for maintainers)','group' => 'Maintainers',),// Advanced'verbose' => array('type' => 'integer','default' => PEAR_CONFIG_DEFAULT_VERBOSE,'doc' => 'verbosity level0: really quiet1: somewhat quiet2: verbose3: debug','prompt' => 'Debug Log Level','group' => 'Advanced',),'preferred_state' => array('type' => 'set','default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified','valid_set' => array('stable', 'beta', 'alpha', 'devel', 'snapshot'),'prompt' => 'Preferred Package State','group' => 'Advanced',),'umask' => array('type' => 'mask','default' => PEAR_CONFIG_DEFAULT_UMASK,'doc' => 'umask used when creating files (Unix-like systems only)','prompt' => 'Unix file mask','group' => 'Advanced',),'cache_ttl' => array('type' => 'integer','default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,'doc' => 'amount of secs where the local cache is used and not updated','prompt' => 'Cache TimeToLive','group' => 'Advanced',),'sig_type' => array('type' => 'set','default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,'doc' => 'which package signature mechanism to use','valid_set' => array('gpg'),'prompt' => 'Package Signature Type','group' => 'Maintainers',),'sig_bin' => array('type' => 'string','default' => PEAR_CONFIG_DEFAULT_SIG_BIN,'doc' => 'which package signature mechanism to use','prompt' => 'Signature Handling Program','group' => 'Maintainers',),'sig_keyid' => array('type' => 'string','default' => '','doc' => 'which key to use for signing with','prompt' => 'Signature Key Id','group' => 'Maintainers',),'sig_keydir' => array('type' => 'directory','default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,'doc' => 'directory where signature keys are located','prompt' => 'Signature Key Directory','group' => 'Maintainers',),// __channels is reserved - used for channel-specific configuration);/*** Constructor.** @param string file to read user-defined options from* @param string file to read system-wide defaults from* @param bool determines whether a registry object "follows"* the value of php_dir (is automatically created* and moved when php_dir is changed)* @param bool if true, fails if configuration files cannot be loaded** @access public** @see PEAR_Config::singleton*/function __construct($user_file = '', $system_file = '', $ftp_file = false,$strict = true){parent::__construct();PEAR_Installer_Role::initializeConfig($this);$sl = DIRECTORY_SEPARATOR;if (empty($user_file)) {if (OS_WINDOWS) {$user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';} else {$user_file = getenv('HOME') . $sl . '.pearrc';}}if (empty($system_file)) {$system_file = PEAR_CONFIG_SYSCONFDIR . $sl;if (OS_WINDOWS) {$system_file .= 'pearsys.ini';} else {$system_file .= 'pear.conf';}}$this->layers = array_keys($this->configuration);$this->files['user'] = $user_file;$this->files['system'] = $system_file;if ($user_file && file_exists($user_file)) {$this->pushErrorHandling(PEAR_ERROR_RETURN);$this->readConfigFile($user_file, 'user', $strict);$this->popErrorHandling();if ($this->_errorsFound > 0) {return;}}if ($system_file && @file_exists($system_file)) {$this->mergeConfigFile($system_file, false, 'system', $strict);if ($this->_errorsFound > 0) {return;}}if (!$ftp_file) {$ftp_file = $this->get('remote_config');}if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {$this->readFTPConfigFile($ftp_file);}foreach ($this->configuration_info as $key => $info) {$this->configuration['default'][$key] = $info['default'];}$this->_registry['default'] = new PEAR_Registry($this->configuration['default']['php_dir'], false, false,$this->configuration['default']['metadata_dir']);$this->_registry['default']->setConfig($this, false);$this->_regInitialized['default'] = false;//$GLOBALS['_PEAR_Config_instance'] = &$this;}/*** Return the default locations of user and system configuration files*/public static function getDefaultConfigFiles(){$sl = DIRECTORY_SEPARATOR;if (OS_WINDOWS) {return array('user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini','system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini');}return array('user' => getenv('HOME') . $sl . '.pearrc','system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf');}/*** Static singleton method. If you want to keep only one instance* of this class in use, this method will give you a reference to* the last created PEAR_Config object if one exists, or create a* new object.** @param string (optional) file to read user-defined options from* @param string (optional) file to read system-wide defaults from** @return object an existing or new PEAR_Config instance** @see PEAR_Config::PEAR_Config*/public static function &singleton($user_file = '', $system_file = '', $strict = true){if (is_object($GLOBALS['_PEAR_Config_instance'])) {return $GLOBALS['_PEAR_Config_instance'];}$t_conf = new PEAR_Config($user_file, $system_file, false, $strict);if ($t_conf->_errorsFound > 0) {return $t_conf->lastError;}$GLOBALS['_PEAR_Config_instance'] = &$t_conf;return $GLOBALS['_PEAR_Config_instance'];}/*** Determine whether any configuration files have been detected, and whether a* registry object can be retrieved from this configuration.* @return bool* @since PEAR 1.4.0a1*/function validConfiguration(){if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {return true;}return false;}/*** Reads configuration data from a file. All existing values in* the config layer are discarded and replaced with data from the* file.* @param string file to read from, if NULL or not specified, the* last-used file for the same layer (second param) is used* @param string config layer to insert data into ('user' or 'system')* @return bool TRUE on success or a PEAR error on failure*/function readConfigFile($file = null, $layer = 'user', $strict = true){if (empty($this->files[$layer])) {return $this->raiseError("unknown config layer `$layer'");}if ($file === null) {$file = $this->files[$layer];}$data = $this->_readConfigDataFrom($file);if (PEAR::isError($data)) {if (!$strict) {return true;}$this->_errorsFound++;$this->lastError = $data;return $data;}$this->files[$layer] = $file;$this->_decodeInput($data);$this->configuration[$layer] = $data;$this->_setupChannels();if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {$this->_registry[$layer] = new PEAR_Registry($phpdir, false, false,$this->get('metadata_dir', $layer, 'pear.php.net'));$this->_registry[$layer]->setConfig($this, false);$this->_regInitialized[$layer] = false;} else {unset($this->_registry[$layer]);}return true;}/*** @param string url to the remote config file, like ftp://www.example.com/pear/config.ini* @return true|PEAR_Error*/function readFTPConfigFile($path){do { // poor man's tryif (!class_exists('PEAR_FTP')) {if (!class_exists('PEAR_Common')) {require_once 'PEAR/Common.php';}if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {require_once 'PEAR/FTP.php';}}if (!class_exists('PEAR_FTP')) {return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');}$this->_ftp = new PEAR_FTP;$this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);$e = $this->_ftp->init($path);if (PEAR::isError($e)) {$this->_ftp->popErrorHandling();return $e;}$tmp = System::mktemp('-d');PEAR_Common::addTempFile($tmp);$e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .'pear.ini', false, FTP_BINARY);if (PEAR::isError($e)) {$this->_ftp->popErrorHandling();return $e;}PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');$this->_ftp->disconnect();$this->_ftp->popErrorHandling();$this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';$e = $this->readConfigFile(null, 'ftp');if (PEAR::isError($e)) {return $e;}$fail = array();foreach ($this->configuration_info as $key => $val) {if (in_array($this->getGroup($key),array('File Locations', 'File Locations (Advanced)')) &&$this->getType($key) == 'directory') {// any directory configs must be set for this to workif (!isset($this->configuration['ftp'][$key])) {$fail[] = $key;}}}if (!count($fail)) {return true;}$fail = '"' . implode('", "', $fail) . '"';unset($this->files['ftp']);unset($this->configuration['ftp']);return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .'directory configuration variables. These variables were not set: ' .$fail);} while (false); // poor man's catchunset($this->files['ftp']);return PEAR::raiseError('no remote host specified');}/*** Reads the existing configurations and creates the _channels array from it*/function _setupChannels(){$set = array_flip(array_values($this->_channels));foreach ($this->configuration as $layer => $data) {$i = 1000;if (isset($data['__channels']) && is_array($data['__channels'])) {foreach ($data['__channels'] as $channel => $info) {$set[$channel] = $i++;}}}$this->_channels = array_values(array_flip($set));$this->setChannels($this->_channels);}function deleteChannel($channel){$ch = strtolower($channel);foreach ($this->configuration as $layer => $data) {if (isset($data['__channels']) && isset($data['__channels'][$ch])) {unset($this->configuration[$layer]['__channels'][$ch]);}}$this->_channels = array_flip($this->_channels);unset($this->_channels[$ch]);$this->_channels = array_flip($this->_channels);}/*** Merges data into a config layer from a file. Does the same* thing as readConfigFile, except it does not replace all* existing values in the config layer.* @param string file to read from* @param bool whether to overwrite existing data (default TRUE)* @param string config layer to insert data into ('user' or 'system')* @param string if true, errors are returned if file opening fails* @return bool TRUE on success or a PEAR error on failure*/function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true){if (empty($this->files[$layer])) {return $this->raiseError("unknown config layer `$layer'");}if ($file === null) {$file = $this->files[$layer];}$data = $this->_readConfigDataFrom($file);if (PEAR::isError($data)) {if (!$strict) {return true;}$this->_errorsFound++;$this->lastError = $data;return $data;}$this->_decodeInput($data);if ($override) {$this->configuration[$layer] =PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);} else {$this->configuration[$layer] =PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);}$this->_setupChannels();if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {$this->_registry[$layer] = new PEAR_Registry($phpdir, false, false,$this->get('metadata_dir', $layer, 'pear.php.net'));$this->_registry[$layer]->setConfig($this, false);$this->_regInitialized[$layer] = false;} else {unset($this->_registry[$layer]);}return true;}/*** @param array* @param array* @return array*/public static function arrayMergeRecursive($arr2, $arr1){$ret = array();foreach ($arr2 as $key => $data) {if (!isset($arr1[$key])) {$ret[$key] = $data;unset($arr1[$key]);continue;}if (is_array($data)) {if (!is_array($arr1[$key])) {$ret[$key] = $arr1[$key];unset($arr1[$key]);continue;}$ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);unset($arr1[$key]);}}return array_merge($ret, $arr1);}/*** Writes data into a config layer from a file.** @param string|null file to read from, or null for default* @param string config layer to insert data into ('user' or* 'system')* @param string|null data to write to config file or null for internal data [DEPRECATED]* @return bool TRUE on success or a PEAR error on failure*/function writeConfigFile($file = null, $layer = 'user', $data = null){$this->_lazyChannelSetup($layer);if ($layer == 'both' || $layer == 'all') {foreach ($this->files as $type => $file) {$err = $this->writeConfigFile($file, $type, $data);if (PEAR::isError($err)) {return $err;}}return true;}if (empty($this->files[$layer])) {return $this->raiseError("unknown config file type `$layer'");}if ($file === null) {$file = $this->files[$layer];}$data = ($data === null) ? $this->configuration[$layer] : $data;$this->_encodeOutput($data);$opt = array('-p', dirname($file));if (!@System::mkDir($opt)) {return $this->raiseError("could not create directory: " . dirname($file));}if (file_exists($file) && is_file($file) && !is_writeable($file)) {return $this->raiseError("no write access to $file!");}$fp = @fopen($file, "w");if (!$fp) {return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");}$contents = "#PEAR_Config 0.9\n" . serialize($data);if (!@fwrite($fp, $contents)) {return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");}return true;}/*** Reads configuration data from a file and returns the parsed data* in an array.** @param string file to read from* @return array configuration data or a PEAR error on failure* @access private*/function _readConfigDataFrom($file){$fp = false;if (file_exists($file)) {$fp = @fopen($file, "r");}if (!$fp) {return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");}$size = filesize($file);fclose($fp);$contents = file_get_contents($file);if (empty($contents)) {return $this->raiseError('Configuration file "' . $file . '" is empty');}$version = false;if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {$version = $matches[1];$contents = substr($contents, strlen($matches[0]));} else {// Museum config fileif (substr($contents,0,2) == 'a:') {$version = '0.1';}}if ($version && version_compare("$version", '1', '<')) {// no '@', it is possible that unserialize// raises a notice but it seems to block IO to// STDOUT if a '@' is used and a notice is raise$data = unserialize($contents);if (!is_array($data) && !$data) {if ($contents == serialize(false)) {$data = array();} else {$err = $this->raiseError("PEAR_Config: bad data in $file");return $err;}}if (!is_array($data)) {if (strlen(trim($contents)) > 0) {$error = "PEAR_Config: bad data in $file";$err = $this->raiseError($error);return $err;}$data = array();}// add parsing of newer formats here...} else {$err = $this->raiseError("$file: unknown version `$version'");return $err;}return $data;}/*** Gets the file used for storing the config for a layer** @param string $layer 'user' or 'system'*/function getConfFile($layer){return $this->files[$layer];}/*** @param string Configuration class name, used for detecting duplicate calls* @param array information on a role as parsed from its xml file* @return true|PEAR_Error* @access private*/function _addConfigVars($class, $vars){static $called = array();if (isset($called[$class])) {return;}$called[$class] = 1;if (count($vars) > 3) {return $this->raiseError('Roles can only define 3 new config variables or less');}foreach ($vars as $name => $var) {if (!is_array($var)) {return $this->raiseError('Configuration information must be an array');}if (!isset($var['type'])) {return $this->raiseError('Configuration information must contain a type');} elseif (!in_array($var['type'],array('string', 'mask', 'password', 'directory', 'file', 'set'))) {return $this->raiseError('Configuration type must be one of directory, file, string, ' .'mask, set, or password');}if (!isset($var['default'])) {return $this->raiseError('Configuration information must contain a default value ("default" index)');}if (is_array($var['default'])) {$real_default = '';foreach ($var['default'] as $config_var => $val) {if (strpos($config_var, 'text') === 0) {$real_default .= $val;} elseif (strpos($config_var, 'constant') === 0) {if (!defined($val)) {return $this->raiseError('Unknown constant "' . $val . '" requested in ' .'default value for configuration variable "' .$name . '"');}$real_default .= constant($val);} elseif (isset($this->configuration_info[$config_var])) {$real_default .=$this->configuration_info[$config_var]['default'];} else {return $this->raiseError('Unknown request for "' . $config_var . '" value in ' .'default value for configuration variable "' .$name . '"');}}$var['default'] = $real_default;}if ($var['type'] == 'integer') {$var['default'] = (integer) $var['default'];}if (!isset($var['doc'])) {return $this->raiseError('Configuration information must contain a summary ("doc" index)');}if (!isset($var['prompt'])) {return $this->raiseError('Configuration information must contain a simple prompt ("prompt" index)');}if (!isset($var['group'])) {return $this->raiseError('Configuration information must contain a simple group ("group" index)');}if (isset($this->configuration_info[$name])) {return $this->raiseError('Configuration variable "' . $name .'" already exists');}$this->configuration_info[$name] = $var;// fix bug #7351: setting custom config variable in a channel fails$this->_channelConfigInfo[] = $name;}return true;}/*** Encodes/scrambles configuration data before writing to files.* Currently, 'password' values will be base64-encoded as to avoid* that people spot cleartext passwords by accident.** @param array (reference) array to encode values in* @return bool TRUE on success* @access private*/function _encodeOutput(&$data){foreach ($data as $key => $value) {if ($key == '__channels') {foreach ($data['__channels'] as $channel => $blah) {$this->_encodeOutput($data['__channels'][$channel]);}}if (!isset($this->configuration_info[$key])) {continue;}$type = $this->configuration_info[$key]['type'];switch ($type) {// we base64-encode passwords so they are at least// not shown in plain by accidentcase 'password': {$data[$key] = base64_encode($data[$key]);break;}case 'mask': {$data[$key] = octdec($data[$key]);break;}}}return true;}/*** Decodes/unscrambles configuration data after reading from files.** @param array (reference) array to encode values in* @return bool TRUE on success* @access private** @see PEAR_Config::_encodeOutput*/function _decodeInput(&$data){if (!is_array($data)) {return true;}foreach ($data as $key => $value) {if ($key == '__channels') {foreach ($data['__channels'] as $channel => $blah) {$this->_decodeInput($data['__channels'][$channel]);}}if (!isset($this->configuration_info[$key])) {continue;}$type = $this->configuration_info[$key]['type'];switch ($type) {case 'password': {$data[$key] = base64_decode($data[$key]);break;}case 'mask': {$data[$key] = decoct($data[$key]);break;}}}return true;}/*** Retrieve the default channel.** On startup, channels are not initialized, so if the default channel is not* pear.php.net, then initialize the config.* @param string registry layer* @return string|false*/function getDefaultChannel($layer = null){$ret = false;if ($layer === null) {foreach ($this->layers as $layer) {if (isset($this->configuration[$layer]['default_channel'])) {$ret = $this->configuration[$layer]['default_channel'];break;}}} elseif (isset($this->configuration[$layer]['default_channel'])) {$ret = $this->configuration[$layer]['default_channel'];}if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {$ret = 'pecl.php.net';}if ($ret) {if ($ret != 'pear.php.net') {$this->_lazyChannelSetup();}return $ret;}return PEAR_CONFIG_DEFAULT_CHANNEL;}/*** Returns a configuration value, prioritizing layers as per the* layers property.** @param string config key* @return mixed the config value, or NULL if not found* @access public*/function get($key, $layer = null, $channel = false){if (!isset($this->configuration_info[$key])) {return null;}if ($key == '__channels') {return null;}if ($key == 'default_channel') {return $this->getDefaultChannel($layer);}if (!$channel) {$channel = $this->getDefaultChannel();} elseif ($channel != 'pear.php.net') {$this->_lazyChannelSetup();}$channel = strtolower($channel);$test = (in_array($key, $this->_channelConfigInfo)) ?$this->_getChannelValue($key, $layer, $channel) :null;if ($test !== null) {if ($this->_installRoot) {if (in_array($this->getGroup($key),array('File Locations', 'File Locations (Advanced)')) &&$this->getType($key) == 'directory') {return $this->_prependPath($test, $this->_installRoot);}}return $test;}if ($layer === null) {foreach ($this->layers as $layer) {if (isset($this->configuration[$layer][$key])) {$test = $this->configuration[$layer][$key];if ($this->_installRoot) {if (in_array($this->getGroup($key),array('File Locations', 'File Locations (Advanced)')) &&$this->getType($key) == 'directory') {return $this->_prependPath($test, $this->_installRoot);}}if ($key == 'preferred_mirror') {$reg = &$this->getRegistry();if (is_object($reg)) {$chan = $reg->getChannel($channel);if (PEAR::isError($chan)) {return $channel;}if (!$chan->getMirror($test) && $chan->getName() != $test) {return $channel; // mirror does not exist}}}return $test;}}} elseif (isset($this->configuration[$layer][$key])) {$test = $this->configuration[$layer][$key];if ($this->_installRoot) {if (in_array($this->getGroup($key),array('File Locations', 'File Locations (Advanced)')) &&$this->getType($key) == 'directory') {return $this->_prependPath($test, $this->_installRoot);}}if ($key == 'preferred_mirror') {$reg = &$this->getRegistry();if (is_object($reg)) {$chan = $reg->getChannel($channel);if (PEAR::isError($chan)) {return $channel;}if (!$chan->getMirror($test) && $chan->getName() != $test) {return $channel; // mirror does not exist}}}return $test;}return null;}/*** Returns a channel-specific configuration value, prioritizing layers as per the* layers property.** @param string config key* @return mixed the config value, or NULL if not found* @access private*/function _getChannelValue($key, $layer, $channel){if ($key == '__channels' || $channel == 'pear.php.net') {return null;}$ret = null;if ($layer === null) {foreach ($this->layers as $ilayer) {if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {$ret = $this->configuration[$ilayer]['__channels'][$channel][$key];break;}}} elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {$ret = $this->configuration[$layer]['__channels'][$channel][$key];}if ($key != 'preferred_mirror') {return $ret;}if ($ret !== null) {$reg = &$this->getRegistry($layer);if (is_object($reg)) {$chan = $reg->getChannel($channel);if (PEAR::isError($chan)) {return $channel;}if (!$chan->getMirror($ret) && $chan->getName() != $ret) {return $channel; // mirror does not exist}}return $ret;}if ($channel != $this->getDefaultChannel($layer)) {return $channel; // we must use the channel name as the preferred mirror// if the user has not chosen an alternate}return $this->getDefaultChannel($layer);}/*** Set a config value in a specific layer (defaults to 'user').* Enforces the types defined in the configuration_info array. An* integer config variable will be cast to int, and a set config* variable will be validated against its legal values.** @param string config key* @param string config value* @param string (optional) config layer* @param string channel to set this value for, or null for global value* @return bool TRUE on success, FALSE on failure*/function set($key, $value, $layer = 'user', $channel = false){if ($key == '__channels') {return false;}if (!isset($this->configuration[$layer])) {return false;}if ($key == 'default_channel') {// can only set this value globally$channel = 'pear.php.net';if ($value != 'pear.php.net') {$this->_lazyChannelSetup($layer);}}if ($key == 'preferred_mirror') {if ($channel == '__uri') {return false; // can't set the __uri pseudo-channel's mirror}$reg = &$this->getRegistry($layer);if (is_object($reg)) {$chan = $reg->getChannel($channel ? $channel : 'pear.php.net');if (PEAR::isError($chan)) {return false;}if (!$chan->getMirror($value) && $chan->getName() != $value) {return false; // mirror does not exist}}}if (!isset($this->configuration_info[$key])) {return false;}extract($this->configuration_info[$key]);switch ($type) {case 'integer':$value = (int)$value;break;case 'set': {// If a valid_set is specified, require the value to// be in the set. If there is no valid_set, accept// any value.if ($valid_set) {reset($valid_set);if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||(key($valid_set) !== 0 && empty($valid_set[$value]))){return false;}}break;}}if (!$channel) {$channel = $this->get('default_channel', null, 'pear.php.net');}if (!in_array($channel, $this->_channels)) {$this->_lazyChannelSetup($layer);$reg = &$this->getRegistry($layer);if ($reg) {$channel = $reg->channelName($channel);}if (!in_array($channel, $this->_channels)) {return false;}}if ($channel != 'pear.php.net') {if (in_array($key, $this->_channelConfigInfo)) {$this->configuration[$layer]['__channels'][$channel][$key] = $value;return true;}return false;}if ($key == 'default_channel') {if (!isset($reg)) {$reg = &$this->getRegistry($layer);if (!$reg) {$reg = &$this->getRegistry();}}if ($reg) {$value = $reg->channelName($value);}if (!$value) {return false;}}$this->configuration[$layer][$key] = $value;if ($key == 'php_dir' && !$this->_noRegistry) {if (!isset($this->_registry[$layer]) ||$value != $this->_registry[$layer]->install_dir) {$this->_registry[$layer] = new PEAR_Registry($value);$this->_regInitialized[$layer] = false;$this->_registry[$layer]->setConfig($this, false);}}return true;}function _lazyChannelSetup($uselayer = false){if ($this->_noRegistry) {return;}$merge = false;foreach ($this->_registry as $layer => $p) {if ($uselayer && $uselayer != $layer) {continue;}if (!$this->_regInitialized[$layer]) {if ($layer == 'default' && isset($this->_registry['user']) ||isset($this->_registry['system'])) {// only use the default registry if there are no alternativescontinue;}if (!is_object($this->_registry[$layer])) {if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {$this->_registry[$layer] = new PEAR_Registry($phpdir, false, false,$this->get('metadata_dir', $layer, 'pear.php.net'));$this->_registry[$layer]->setConfig($this, false);$this->_regInitialized[$layer] = false;} else {unset($this->_registry[$layer]);return;}}$this->setChannels($this->_registry[$layer]->listChannels(), $merge);$this->_regInitialized[$layer] = true;$merge = true;}}}/*** Set the list of channels.** This should be set via a call to {@link PEAR_Registry::listChannels()}* @param array* @param bool* @return bool success of operation*/function setChannels($channels, $merge = false){if (!is_array($channels)) {return false;}if ($merge) {$this->_channels = array_merge($this->_channels, $channels);} else {$this->_channels = $channels;}foreach ($channels as $channel) {$channel = strtolower($channel);if ($channel == 'pear.php.net') {continue;}foreach ($this->layers as $layer) {if (!isset($this->configuration[$layer]['__channels'])) {$this->configuration[$layer]['__channels'] = array();}if (!isset($this->configuration[$layer]['__channels'][$channel])|| !is_array($this->configuration[$layer]['__channels'][$channel])) {$this->configuration[$layer]['__channels'][$channel] = array();}}}return true;}/*** Get the type of a config value.** @param string config key** @return string type, one of "string", "integer", "file",* "directory", "set" or "password".** @access public**/function getType($key){if (isset($this->configuration_info[$key])) {return $this->configuration_info[$key]['type'];}return false;}/*** Get the documentation for a config value.** @param string config key* @return string documentation string** @access public**/function getDocs($key){if (isset($this->configuration_info[$key])) {return $this->configuration_info[$key]['doc'];}return false;}/*** Get the short documentation for a config value.** @param string config key* @return string short documentation string** @access public**/function getPrompt($key){if (isset($this->configuration_info[$key])) {return $this->configuration_info[$key]['prompt'];}return false;}/*** Get the parameter group for a config key.** @param string config key* @return string parameter group** @access public**/function getGroup($key){if (isset($this->configuration_info[$key])) {return $this->configuration_info[$key]['group'];}return false;}/*** Get the list of parameter groups.** @return array list of parameter groups** @access public**/function getGroups(){$tmp = array();foreach ($this->configuration_info as $key => $info) {$tmp[$info['group']] = 1;}return array_keys($tmp);}/*** Get the list of the parameters in a group.** @param string $group parameter group* @return array list of parameters in $group** @access public**/function getGroupKeys($group){$keys = array();foreach ($this->configuration_info as $key => $info) {if ($info['group'] == $group) {$keys[] = $key;}}return $keys;}/*** Get the list of allowed set values for a config value. Returns* NULL for config values that are not sets.** @param string config key* @return array enumerated array of set values, or NULL if the* config key is unknown or not a set** @access public**/function getSetValues($key){if (isset($this->configuration_info[$key]) &&isset($this->configuration_info[$key]['type']) &&$this->configuration_info[$key]['type'] == 'set'){$valid_set = $this->configuration_info[$key]['valid_set'];reset($valid_set);if (key($valid_set) === 0) {return $valid_set;}return array_keys($valid_set);}return null;}/*** Get all the current config keys.** @return array simple array of config keys** @access public*/function getKeys(){$keys = array();foreach ($this->layers as $layer) {$test = $this->configuration[$layer];if (isset($test['__channels'])) {foreach ($test['__channels'] as $channel => $configs) {$keys = array_merge($keys, $configs);}}unset($test['__channels']);$keys = array_merge($keys, $test);}return array_keys($keys);}/*** Remove the a config key from a specific config layer.** @param string config key* @param string (optional) config layer* @param string (optional) channel (defaults to default channel)* @return bool TRUE on success, FALSE on failure** @access public*/function remove($key, $layer = 'user', $channel = null){if ($channel === null) {$channel = $this->getDefaultChannel();}if ($channel !== 'pear.php.net') {if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {unset($this->configuration[$layer]['__channels'][$channel][$key]);return true;}}if (isset($this->configuration[$layer][$key])) {unset($this->configuration[$layer][$key]);return true;}return false;}/*** Temporarily remove an entire config layer. USE WITH CARE!** @param string config key* @param string (optional) config layer* @return bool TRUE on success, FALSE on failure** @access public*/function removeLayer($layer){if (isset($this->configuration[$layer])) {$this->configuration[$layer] = array();return true;}return false;}/*** Stores configuration data in a layer.** @param string config layer to store* @return bool TRUE on success, or PEAR error on failure** @access public*/function store($layer = 'user', $data = null){return $this->writeConfigFile(null, $layer, $data);}/*** Tells what config layer that gets to define a key.** @param string config key* @param boolean return the defining channel** @return string|array the config layer, or an empty string if not found.** if $returnchannel, the return is an array array('layer' => layername,* 'channel' => channelname), or an empty string if not found** @access public*/function definedBy($key, $returnchannel = false){foreach ($this->layers as $layer) {$channel = $this->getDefaultChannel();if ($channel !== 'pear.php.net') {if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {if ($returnchannel) {return array('layer' => $layer, 'channel' => $channel);}return $layer;}}if (isset($this->configuration[$layer][$key])) {if ($returnchannel) {return array('layer' => $layer, 'channel' => 'pear.php.net');}return $layer;}}return '';}/*** Tells whether a given key exists as a config value.** @param string config key* @return bool whether <config key> exists in this object** @access public*/function isDefined($key){foreach ($this->layers as $layer) {if (isset($this->configuration[$layer][$key])) {return true;}}return false;}/*** Tells whether a given config layer exists.** @param string config layer* @return bool whether <config layer> exists in this object** @access public*/function isDefinedLayer($layer){return isset($this->configuration[$layer]);}/*** Returns the layers defined (except the 'default' one)** @return array of the defined layers*/function getLayers(){$cf = $this->configuration;unset($cf['default']);return array_keys($cf);}function apiVersion(){return '1.1';}/*** @return PEAR_Registry*/function &getRegistry($use = null){$layer = $use === null ? 'user' : $use;if (isset($this->_registry[$layer])) {return $this->_registry[$layer];} elseif ($use === null && isset($this->_registry['system'])) {return $this->_registry['system'];} elseif ($use === null && isset($this->_registry['default'])) {return $this->_registry['default'];} elseif ($use) {$a = false;return $a;}// only go here if null was passed inecho "CRITICAL ERROR: Registry could not be initialized from any value";exit(1);}/*** This is to allow customization like the use of installroot* @param PEAR_Registry* @return bool*/function setRegistry(&$reg, $layer = 'user'){if ($this->_noRegistry) {return false;}if (!in_array($layer, array('user', 'system'))) {return false;}$this->_registry[$layer] = &$reg;if (is_object($reg)) {$this->_registry[$layer]->setConfig($this, false);}return true;}function noRegistry(){$this->_noRegistry = true;}/*** @return PEAR_REST*/function &getREST($version, $options = array()){$version = str_replace('.', '', $version);if (!class_exists($class = 'PEAR_REST_' . $version)) {require_once 'PEAR/REST/' . $version . '.php';}$remote = new $class($this, $options);return $remote;}/*** The ftp server is set in {@link readFTPConfigFile()}. It exists only if a* remote configuration file has been specified* @return PEAR_FTP|false*/function &getFTP(){if (isset($this->_ftp)) {return $this->_ftp;}$a = false;return $a;}function _prependPath($path, $prepend){if (strlen($prepend) > 0) {if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {if (preg_match('/^[a-z]:/i', $prepend)) {$prepend = substr($prepend, 2);} elseif ($prepend{0} != '\\') {$prepend = "\\$prepend";}$path = substr($path, 0, 2) . $prepend . substr($path, 2);} else {$path = $prepend . $path;}}return $path;}/*** @param string|false installation directory to prepend to all _dir variables, or false to* disable*/function setInstallRoot($root){if (substr($root, -1) == DIRECTORY_SEPARATOR) {$root = substr($root, 0, -1);}$old = $this->_installRoot;$this->_installRoot = $root;if (($old != $root) && !$this->_noRegistry) {foreach (array_keys($this->_registry) as $layer) {if ($layer == 'ftp' || !isset($this->_registry[$layer])) {continue;}$this->_registry[$layer] =new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'), false, false,$this->get('metadata_dir', $layer, 'pear.php.net'));$this->_registry[$layer]->setConfig($this, false);$this->_regInitialized[$layer] = false;}}}}