Source for file Config.php
Documentation is available at Config.php
* PEAR_Config, customized configuration handling for the PEAR Installer
* @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 CVS: $Id: Config.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
* Required for error handling
require_once 'PEAR/Registry.php';
require_once 'PEAR/Installer/Role.php';
require_once 'System.php';
* Last created PEAR_Config instance.
$GLOBALS['_PEAR_Config_instance'] = null;
if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR ) {
$PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
$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" command
define('PEAR_RUNTYPE', 'pear');
define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
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'));
define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR );
// Default for master_server
if (getenv('PHP_PEAR_MASTER_SERVER')) {
define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv ('PHP_PEAR_MASTER_SERVER'));
define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
// Default for http_proxy
if (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'));
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
if (getenv('PHP_PEAR_INSTALL_DIR')) {
define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv ('PHP_PEAR_INSTALL_DIR'));
define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
if (getenv('PHP_PEAR_EXTENSION_DIR')) {
define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv ('PHP_PEAR_EXTENSION_DIR'));
define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get ('extension_dir'));
} elseif (defined('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 );
define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
if (getenv('PHP_PEAR_DOC_DIR')) {
define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv ('PHP_PEAR_DOC_DIR'));
define('PEAR_CONFIG_DEFAULT_DOC_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR. 'docs');
if (getenv('PHP_PEAR_BIN_DIR')) {
define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv ('PHP_PEAR_BIN_DIR'));
define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR );
if (getenv('PHP_PEAR_DATA_DIR')) {
define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv ('PHP_PEAR_DATA_DIR'));
define('PEAR_CONFIG_DEFAULT_DATA_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR. 'data');
if (getenv('PHP_PEAR_CFG_DIR')) {
define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv ('PHP_PEAR_CFG_DIR'));
define('PEAR_CONFIG_DEFAULT_CFG_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR. 'cfg');
if (getenv('PHP_PEAR_WWW_DIR')) {
define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv ('PHP_PEAR_WWW_DIR'));
define('PEAR_CONFIG_DEFAULT_WWW_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR. 'www');
if (getenv('PHP_PEAR_TEST_DIR')) {
define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv ('PHP_PEAR_TEST_DIR'));
define('PEAR_CONFIG_DEFAULT_TEST_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR. 'tests');
if (getenv('PHP_PEAR_TEMP_DIR')) {
define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv ('PHP_PEAR_TEMP_DIR'));
define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
System ::tmpdir () . DIRECTORY_SEPARATOR . 'pear' .
DIRECTORY_SEPARATOR . 'temp');
if (getenv('PHP_PEAR_CACHE_DIR')) {
define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv ('PHP_PEAR_CACHE_DIR'));
define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
System ::tmpdir () . DIRECTORY_SEPARATOR . 'pear' .
DIRECTORY_SEPARATOR . 'cache');
// Default for download_dir
if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv ('PHP_PEAR_DOWNLOAD_DIR'));
define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
System ::tmpdir () . DIRECTORY_SEPARATOR . 'pear' .
DIRECTORY_SEPARATOR . 'download');
if (getenv('PHP_PEAR_PHP_BIN')) {
define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv ('PHP_PEAR_PHP_BIN'));
define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
DIRECTORY_SEPARATOR. 'php'. (OS_WINDOWS ? '.exe' : ''));
if (getenv('PHP_PEAR_VERBOSE')) {
define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv ('PHP_PEAR_VERBOSE'));
define('PEAR_CONFIG_DEFAULT_VERBOSE', 1 );
// Default for preferred_state
if (getenv('PHP_PEAR_PREFERRED_STATE')) {
define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv ('PHP_PEAR_PREFERRED_STATE'));
define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
if (getenv('PHP_PEAR_UMASK')) {
define('PEAR_CONFIG_DEFAULT_UMASK', getenv ('PHP_PEAR_UMASK'));
define('PEAR_CONFIG_DEFAULT_UMASK', decoct (umask ()));
if (getenv('PHP_PEAR_CACHE_TTL')) {
define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv ('PHP_PEAR_CACHE_TTL'));
define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600 );
if (getenv('PHP_PEAR_SIG_TYPE')) {
define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv ('PHP_PEAR_SIG_TYPE'));
define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
if (getenv('PHP_PEAR_SIG_BIN')) {
define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv ('PHP_PEAR_SIG_BIN'));
define('PEAR_CONFIG_DEFAULT_SIG_BIN',
'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
// Default for sig_keydir
if (getenv('PHP_PEAR_SIG_KEYDIR')) {
define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv ('PHP_PEAR_SIG_KEYDIR'));
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.
* @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.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* Array of config files used.
* @var array layer => config file
* 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, ...)
* Configuration values that can be set for a channel
* All other configuration values can only have a global value
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
var $_channels = array ('pear.php.net', 'pecl.php.net', '__uri');
* This variable is used to control the directory values returned
var $_installRoot = false;
* If requested, this will always refer to the registry
var $_registry = array ();
var $_regInitialized = array ();
var $_noRegistry = false;
* amount of errors found while parsing config
* Information about the configuration data. Stores the type,
* default value and a documentation string for each configuration
* @var array layer => array(infotype => value, ...)
// Channels/Internet Access
'default_channel' => array (
'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 (
'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 (
'doc' => 'ftp url of remote configuration file to use for synchronized install',
'prompt' => 'Remote Configuration File',
'group' => 'Internet Access',
'auto_discover' => array (
'doc' => 'whether to automatically discover new channels',
'prompt' => 'Auto-discover new Channels',
'group' => 'Internet Access',
'master_server' => array (
'default' => 'pear.php.net',
'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
'prompt' => 'PEAR server [DEPRECATED]',
'group' => 'Internet Access',
'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY ,
'doc' => 'HTTP proxy (host:port) to use when downloading packages',
'prompt' => 'HTTP Proxy Server Address',
'group' => 'Internet Access',
'default' => PEAR_CONFIG_DEFAULT_PHP_DIR ,
'doc' => 'directory where .php files are installed',
'prompt' => 'PEAR directory',
'group' => 'File Locations',
'default' => PEAR_CONFIG_DEFAULT_EXT_DIR ,
'doc' => 'directory where loadable extensions are installed',
'prompt' => 'PHP extension directory',
'group' => 'File Locations',
'default' => PEAR_CONFIG_DEFAULT_DOC_DIR ,
'doc' => 'directory where documentation is installed',
'prompt' => 'PEAR documentation directory',
'group' => 'File Locations',
'default' => PEAR_CONFIG_DEFAULT_BIN_DIR ,
'doc' => 'directory where executables are installed',
'prompt' => 'PEAR executables directory',
'group' => 'File Locations',
'default' => PEAR_CONFIG_DEFAULT_DATA_DIR ,
'doc' => 'directory where data files are installed',
'prompt' => 'PEAR data directory',
'group' => 'File Locations (Advanced)',
'default' => PEAR_CONFIG_DEFAULT_CFG_DIR ,
'doc' => 'directory where modifiable configuration files are installed',
'prompt' => 'PEAR configuration file directory',
'group' => 'File Locations (Advanced)',
'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)',
'default' => PEAR_CONFIG_DEFAULT_TEST_DIR ,
'doc' => 'directory where regression tests are installed',
'prompt' => 'PEAR test directory',
'group' => 'File Locations (Advanced)',
'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR ,
'doc' => 'directory which is used for web service cache',
'prompt' => 'PEAR Installer cache directory',
'group' => 'File Locations (Advanced)',
'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR ,
'doc' => 'directory which is used for all temp files',
'prompt' => 'PEAR Installer temp directory',
'group' => 'File Locations (Advanced)',
'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR ,
'doc' => 'directory which is used for all downloaded files',
'prompt' => 'PEAR Installer download directory',
'group' => 'File Locations (Advanced)',
'default' => PEAR_CONFIG_DEFAULT_PHP_BIN ,
'doc' => 'PHP CLI/CGI binary for executing scripts',
'prompt' => 'PHP CLI/CGI binary',
'group' => 'File Locations (Advanced)',
'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
'prompt' => '--program-prefix passed to PHP\'s ./configure',
'group' => 'File Locations (Advanced)',
'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
'prompt' => '--program-suffix passed to PHP\'s ./configure',
'group' => 'File Locations (Advanced)',
'doc' => 'location of php.ini in which to enable PECL extensions on install',
'prompt' => 'php.ini location',
'group' => 'File Locations (Advanced)',
'doc' => '(maintainers) your PEAR account name',
'prompt' => 'PEAR username (for maintainers)',
'group' => 'Maintainers',
'doc' => '(maintainers) your PEAR account password',
'prompt' => 'PEAR password (for maintainers)',
'group' => 'Maintainers',
'default' => PEAR_CONFIG_DEFAULT_VERBOSE ,
'doc' => 'verbosity level
'prompt' => 'Debug Log Level',
'preferred_state' => array (
'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE ,
'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
'stable', 'beta', 'alpha', 'devel', 'snapshot'),
'prompt' => 'Preferred Package State',
'default' => PEAR_CONFIG_DEFAULT_UMASK ,
'doc' => 'umask used when creating files (Unix-like systems only)',
'prompt' => 'Unix file mask',
'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL ,
'doc' => 'amount of secs where the local cache is used and not updated',
'prompt' => 'Cache TimeToLive',
'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE ,
'doc' => 'which package signature mechanism to use',
'valid_set' => array ('gpg'),
'prompt' => 'Package Signature Type',
'group' => 'Maintainers',
'default' => PEAR_CONFIG_DEFAULT_SIG_BIN ,
'doc' => 'which package signature mechanism to use',
'prompt' => 'Signature Handling Program',
'group' => 'Maintainers',
'doc' => 'which key to use for signing with',
'prompt' => 'Signature Key Id',
'group' => 'Maintainers',
'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
* @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
* @see PEAR_Config::singleton
function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false ,
$sl = DIRECTORY_SEPARATOR;
$user_file = getenv('HOME') . $sl . '.pearrc';
if (empty ($system_file)) {
$system_file .= 'pearsys.ini';
$system_file .= 'pear.conf';
$this->files['user'] = $user_file;
$this->files['system'] = $system_file;
if ($this->_errorsFound > 0 ) {
if ($this->_errorsFound > 0 ) {
$ftp_file = $this->get('remote_config');
if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
$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
$sl = DIRECTORY_SEPARATOR;
'user' => getenv('HOME') . $sl . '.pearrc',
* 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
* @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
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.
* Reads configuration data from a file. All existing values in
* the config layer are discarded and replaced with data from the
* @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'" );
$file = $this->files[$layer];
$data = $this->_readConfigDataFrom ($file);
$this->lastError = $data;
$this->files[$layer] = $file;
$this->_decodeInput ($data);
if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
$this->_registry[$layer]->setConfig ($this, false );
$this->_regInitialized[$layer] = false;
unset ($this->_registry[$layer]);
* @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
* @return true|PEAR_Error
require_once 'PEAR/Common.php';
require_once 'PEAR/FTP.php';
return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
$this->_ftp = &new PEAR_FTP;
$e = $this->_ftp->init ($path);
$this->_ftp->popErrorHandling ();
$e = $this->_ftp->get (basename($path), $tmp . DIRECTORY_SEPARATOR .
'pear.ini', false , FTP_BINARY );
$this->_ftp->popErrorHandling ();
$this->_ftp->disconnect ();
$this->_ftp->popErrorHandling ();
$this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
array ('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
// any directory configs must be set for this to work
$fail = '"' . implode('", "', $fail) . '"';
unset ($this->files['ftp']);
return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
'directory configuration variables. These variables were not set: ' .
} while (false ); // poor man's catch
unset ($this->files['ftp']);
* Reads the existing configurations and creates the _channels array from it
function _setupChannels ()
if (isset ($data['__channels']) && is_array($data['__channels'])) {
foreach ($data['__channels'] as $channel => $info) {
if (isset ($data['__channels']) && isset ($data['__channels'][$ch])) {
unset ($this->_channels[$ch]);
* 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'" );
$file = $this->files[$layer];
$data = $this->_readConfigDataFrom ($file);
$this->lastError = $data;
$this->_decodeInput ($data);
if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
$this->_registry[$layer]->setConfig ($this, false );
$this->_regInitialized[$layer] = false;
unset ($this->_registry[$layer]);
foreach ($arr2 as $key => $data) {
if (!isset ($arr1[$key])) {
$ret[$key] = $arr1[$key];
* Writes data into a config layer from a file.
* @param string|nullfile to read from, or null for default
* @param string config layer to insert data into ('user' or
* @param string|nulldata to write to config file or null for internal data [DEPRECATED]
* @return bool TRUE on success or a PEAR error on failure
$this->_lazyChannelSetup ($layer);
if ($layer == 'both' || $layer == 'all') {
foreach ($this->files as $type => $file) {
if (empty ($this->files[$layer])) {
return $this->raiseError(" unknown config file type `$layer'" );
$file = $this->files[$layer];
$this->_encodeOutput ($data);
$opt = array ('-p', dirname($file));
return $this->raiseError(" no write access to $file!" );
$fp = @fopen($file, "w");
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)" );
* Reads configuration data from a file and returns the parsed data
* @param string file to read from
* @return array configuration data or a PEAR error on failure
function _readConfigDataFrom ($file)
$fp = @fopen($file, "r");
return $this->raiseError(" PEAR_Config::readConfigFile fopen('$file','r') failed" );
return $this->raiseError('Configuration file "' . $file . '" is empty');
if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
if (substr($contents,0 ,2 ) == 'a:') {
// 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
$err = $this->raiseError(" PEAR_Config: bad data in $file" );
$error = " PEAR_Config: bad data in $file";
// add parsing of newer formats here...
$err = $this->raiseError(" $file: unknown version `$version'" );
* Gets the file used for storing the config for a layer
* @param string $layer 'user' or 'system'
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
function _addConfigVars ($class, $vars)
static $called = array ();
if (isset ($called[$class])) {
return $this->raiseError('Roles can only define 3 new config variables or less');
foreach ($vars as $name => $var) {
return $this->raiseError('Configuration information must be an array');
if (!isset ($var['type'])) {
return $this->raiseError('Configuration information must contain a type');
array ('string', 'mask', 'password', 'directory', 'file', 'set'))) {
'Configuration type must be one of directory, file, string, ' .
'mask, set, or password');
if (!isset ($var['default'])) {
'Configuration information must contain a default value ("default" index)');
foreach ($var['default'] as $config_var => $val) {
if (strpos($config_var, 'text') === 0 ) {
} elseif (strpos($config_var, 'constant') === 0 ) {
'Unknown constant "' . $val . '" requested in ' .
'default value for configuration variable "' .
'Unknown request for "' . $config_var . '" value in ' .
'default value for configuration variable "' .
$var['default'] = $real_default;
if ($var['type'] == 'integer') {
$var['default'] = (integer) $var['default'];
if (!isset ($var['doc'])) {
'Configuration information must contain a summary ("doc" index)');
if (!isset ($var['prompt'])) {
'Configuration information must contain a simple prompt ("prompt" index)');
if (!isset ($var['group'])) {
'Configuration information must contain a simple group ("group" index)');
return $this->raiseError('Configuration variable "' . $name .
// fix bug #7351: setting custom config variable in a channel fails
$this->_channelConfigInfo [] = $name;
* 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
function _encodeOutput (&$data)
foreach ($data as $key => $value) {
if ($key == '__channels') {
foreach ($data['__channels'] as $channel => $blah) {
$this->_encodeOutput ($data['__channels'][$channel]);
// we base64-encode passwords so they are at least
// not shown in plain by accident
$data[$key] = octdec($data[$key]);
* Decodes/unscrambles configuration data after reading from files.
* @param array (reference) array to encode values in
* @return bool TRUE on success
* @see PEAR_Config::_encodeOutput
function _decodeInput (&$data)
foreach ($data as $key => $value) {
if ($key == '__channels') {
foreach ($data['__channels'] as $channel => $blah) {
$this->_decodeInput ($data['__channels'][$channel]);
$data[$key] = decoct($data[$key]);
* 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
foreach ($this->layers as $layer) {
} elseif (isset ($this->configuration[$layer]['default_channel'])) {
if ($ret != 'pear.php.net') {
$this->_lazyChannelSetup ();
* Returns a configuration value, prioritizing layers as per the
* @param string config key
* @return mixed the config value, or NULL if not found
function get($key, $layer = null , $channel = false )
if ($key == '__channels') {
if ($key == 'default_channel') {
} elseif ($channel != 'pear.php.net') {
$this->_lazyChannelSetup ();
$test = (in_array($key, $this->_channelConfigInfo )) ?
$this->_getChannelValue ($key, $layer, $channel) :
if ($this->_installRoot ) {
array ('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
return $this->_prependPath ($test, $this->_installRoot );
foreach ($this->layers as $layer) {
if ($this->_installRoot ) {
array ('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
return $this->_prependPath ($test, $this->_installRoot );
if ($key == 'preferred_mirror') {
$chan = &$reg->getChannel ($channel);
if (!$chan->getMirror ($test) && $chan->getName () != $test) {
return $channel; // mirror does not exist
if ($this->_installRoot ) {
array ('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
return $this->_prependPath ($test, $this->_installRoot );
if ($key == 'preferred_mirror') {
$chan = &$reg->getChannel ($channel);
if (!$chan->getMirror ($test) && $chan->getName () != $test) {
return $channel; // mirror does not exist
* Returns a channel-specific configuration value, prioritizing layers as per the
* @param string config key
* @return mixed the config value, or NULL if not found
function _getChannelValue ($key, $layer, $channel)
if ($key == '__channels' || $channel == 'pear.php.net') {
foreach ($this->layers as $ilayer) {
if (isset ($this->configuration[$ilayer]['__channels'][$channel][$key])) {
$ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
} elseif (isset ($this->configuration[$layer]['__channels'][$channel][$key])) {
$ret = $this->configuration[$layer]['__channels'][$channel][$key];
if ($key != 'preferred_mirror') {
$chan = &$reg->getChannel ($channel);
if (!$chan->getMirror ($ret) && $chan->getName () != $ret) {
return $channel; // mirror does not exist
return $channel; // we must use the channel name as the preferred mirror
// if the user has not chosen an alternate
* 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') {
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
$chan = &$reg->getChannel ($channel ? $channel : 'pear.php.net');
if (!$chan->getMirror ($value) && $chan->getName () != $value) {
return false; // mirror does not exist
// If a valid_set is specified, require the value to
// be in the set. If there is no valid_set, accept
if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
(key($valid_set) !== 0 && empty ($valid_set[$value])))
$channel = $this->get('default_channel', null , 'pear.php.net');
if (!in_array($channel, $this->_channels )) {
$this->_lazyChannelSetup ($layer);
$channel = $reg->channelName ($channel);
if (!in_array($channel, $this->_channels )) {
if ($channel != 'pear.php.net') {
if (in_array($key, $this->_channelConfigInfo )) {
$this->configuration[$layer]['__channels'][$channel][$key] = $value;
if ($key == 'default_channel') {
$value = $reg->channelName ($value);
if ($key == 'php_dir' && !$this->_noRegistry ) {
if (!isset ($this->_registry [$layer]) ||
$value != $this->_registry [$layer]->install_dir ) {
$this->_regInitialized [$layer] = false;
$this->_registry [$layer]->setConfig ($this, false );
function _lazyChannelSetup ($uselayer = false )
if ($this->_noRegistry ) {
foreach ($this->_registry as $layer => $p) {
if ($uselayer && $uselayer != $layer) {
if (!$this->_regInitialized [$layer]) {
if ($layer == 'default' && isset ($this->_registry ['user']) ||
isset ($this->_registry ['system'])) {
// only use the default registry if there are no alternatives
if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
$this->_registry [$layer]->setConfig ($this, false );
$this->_regInitialized [$layer] = false;
unset ($this->_registry [$layer]);
$this->setChannels($this->_registry [$layer]->listChannels (), $merge);
$this->_regInitialized [$layer] = true;
* Set the list of channels.
* This should be set via a call to {@link PEAR_Registry::listChannels()}
* @return bool success of operation
$this->_channels = array_merge($this->_channels , $channels);
$this->_channels = $channels;
foreach ($channels as $channel) {
if ($channel == 'pear.php.net') {
foreach ($this->layers as $layer) {
* Get the type of a config value.
* @param string config key
* @return string type, one of "string", "integer", "file",
* "directory", "set" or "password".
* Get the documentation for a config value.
* @param string config key
* @return string documentation string
* Get the short documentation for a config value.
* @param string config key
* @return string short documentation string
* Get the parameter group for a config key.
* @param string config key
* @return string parameter group
* Get the list of parameter groups.
* @return array list of parameter groups
$tmp[$info['group']] = 1;
* Get the list of the parameters in a group.
* @param string $group parameter group
* @return array list of parameters in $group
if ($info['group'] == $group) {
* 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
if (key($valid_set) === 0 ) {
* Get all the current config keys.
* @return array simple array of config keys
foreach ($this->layers as $layer) {
if (isset ($test['__channels'])) {
foreach ($test['__channels'] as $channel => $configs) {
unset ($test['__channels']);
* 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
function remove($key, $layer = 'user', $channel = null )
if ($channel !== 'pear.php.net') {
if (isset ($this->configuration[$layer]['__channels'][$channel][$key])) {
unset ($this->configuration[$layer]['__channels'][$channel][$key]);
* 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
* Stores configuration data in a layer.
* @param string config layer to store
* @return bool TRUE on success, or PEAR error on failure
function store($layer = 'user', $data = null )
* Tells what config layer that gets to define a key.
* @param string config key
* @param boolean return the defining channel
* @return string|arraythe 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
function definedBy($key, $returnchannel = false )
foreach ($this->layers as $layer) {
if ($channel !== 'pear.php.net') {
if (isset ($this->configuration[$layer]['__channels'][$channel][$key])) {
return array ('layer' => $layer, 'channel' => $channel);
return array ('layer' => $layer, 'channel' => 'pear.php.net');
* Tells whether a given key exists as a config value.
* @param string config key
* @return bool whether <config key> exists in this object
foreach ($this->layers as $layer) {
* Tells whether a given config layer exists.
* @param string config layer
* @return bool whether <config layer> exists in this object
* Returns the layers defined (except the 'default' one)
* @return array of the defined layers
$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'];
// only go here if null was passed in
echo "CRITICAL ERROR: Registry could not be initialized from any value";
* This is to allow customization like the use of installroot
if ($this->_noRegistry ) {
if (!in_array($layer, array ('user', 'system'))) {
$this->_registry [$layer] = &$reg;
$this->_registry [$layer]->setConfig ($this, false );
$this->_noRegistry = true;
function &getREST($version, $options = array ())
require_once 'PEAR/REST/' . $version . '.php';
$remote = &new $class($this, $options);
* The ftp server is set in {@link readFTPConfigFile()}. It exists only if a
* remote configuration file has been specified
if (isset ($this->_ftp )) {
function _prependPath ($path, $prepend)
$prepend = substr($prepend, 2 );
} elseif ($prepend{0 } != '\\') {
$path = $prepend . $path;
* @param string|falseinstallation directory to prepend to all _dir variables, or false to
if (substr($root, -1 ) == DIRECTORY_SEPARATOR ) {
$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])) {
$this->_registry [$layer] =
$this->_registry [$layer]->setConfig ($this, false );
$this->_regInitialized [$layer] = false;
Documentation generated on Wed, 06 Jul 2011 23:30:38 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.
|