home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / tmp / PEAR-1.7.1 / PEAR / Config.php < prev    next >
Encoding:
PHP Script  |  2008-02-15  |  69.4 KB  |  2,164 lines

  1. <?php
  2. /**
  3.  * PEAR_Config, customized configuration handling for the PEAR Installer
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   pear
  14.  * @package    PEAR
  15.  * @author     Stig Bakken <ssb@php.net>
  16.  * @author     Greg Beaver <cellog@php.net>
  17.  * @copyright  1997-2008 The PHP Group
  18.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  19.  * @version    CVS: $Id: Config.php,v 1.144 2008/01/03 20:26:34 cellog Exp $
  20.  * @link       http://pear.php.net/package/PEAR
  21.  * @since      File available since Release 0.1
  22.  */
  23.  
  24. /**
  25.  * Required for error handling
  26.  */
  27. require_once 'PEAR.php';
  28. require_once 'PEAR/Registry.php';
  29. require_once 'PEAR/Installer/Role.php';
  30. require_once 'System.php';
  31. require_once 'PEAR/Remote.php';
  32.  
  33. /**
  34.  * Last created PEAR_Config instance.
  35.  * @var object
  36.  */
  37. $GLOBALS['_PEAR_Config_instance'] = null;
  38. if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
  39.     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
  40. } else {
  41.     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
  42. }
  43.  
  44. // Below we define constants with default values for all configuration
  45. // parameters except username/password.  All of them can have their
  46. // defaults set through environment variables.  The reason we use the
  47. // PHP_ prefix is for some security, PHP protects environment
  48. // variables starting with PHP_*.
  49.  
  50. // default channel and preferred mirror is based on whether we are invoked through
  51. // the "pear" or the "pecl" command
  52.  
  53. if (!defined('PEAR_RUNTYPE') || PEAR_RUNTYPE == 'pear') {
  54.     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
  55. } else {
  56.     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
  57. }
  58.  
  59. if (getenv('PHP_PEAR_SYSCONF_DIR')) {
  60.     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
  61. } elseif (getenv('SystemRoot')) {
  62.     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
  63. } else {
  64.     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
  65. }
  66.  
  67. // Default for master_server
  68. if (getenv('PHP_PEAR_MASTER_SERVER')) {
  69.     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
  70. } else {
  71.     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
  72. }
  73.  
  74. // Default for http_proxy
  75. if (getenv('PHP_PEAR_HTTP_PROXY')) {
  76.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
  77. } elseif (getenv('http_proxy')) {
  78.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
  79. } else {
  80.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
  81. }
  82.  
  83. // Default for php_dir
  84. if (getenv('PHP_PEAR_INSTALL_DIR')) {
  85.     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
  86. } else {
  87.     if (file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {
  88.         define('PEAR_CONFIG_DEFAULT_PHP_DIR',
  89.                $PEAR_INSTALL_DIR);
  90.     } else {
  91.         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
  92.     }
  93. }
  94.  
  95. // Default for ext_dir
  96. if (getenv('PHP_PEAR_EXTENSION_DIR')) {
  97.     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
  98. } else {
  99.     if (ini_get('extension_dir')) {
  100.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
  101.     } elseif (defined('PEAR_EXTENSION_DIR') &&
  102.               file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
  103.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
  104.     } elseif (defined('PHP_EXTENSION_DIR')) {
  105.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
  106.     } else {
  107.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
  108.     }
  109. }
  110.  
  111. // Default for doc_dir
  112. if (getenv('PHP_PEAR_DOC_DIR')) {
  113.     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
  114. } else {
  115.     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
  116.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
  117. }
  118.  
  119. // Default for bin_dir
  120. if (getenv('PHP_PEAR_BIN_DIR')) {
  121.     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
  122. } else {
  123.     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
  124. }
  125.  
  126. // Default for data_dir
  127. if (getenv('PHP_PEAR_DATA_DIR')) {
  128.     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
  129. } else {
  130.     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
  131.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
  132. }
  133.  
  134. // Default for cfg_dir
  135. if (getenv('PHP_PEAR_CFG_DIR')) {
  136.     define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
  137. } else {
  138.     define('PEAR_CONFIG_DEFAULT_CFG_DIR',
  139.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
  140. }
  141.  
  142. // Default for www_dir
  143. if (getenv('PHP_PEAR_WWW_DIR')) {
  144.     define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
  145. } else {
  146.     define('PEAR_CONFIG_DEFAULT_WWW_DIR',
  147.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
  148. }
  149.  
  150. // Default for test_dir
  151. if (getenv('PHP_PEAR_TEST_DIR')) {
  152.     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
  153. } else {
  154.     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
  155.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
  156. }
  157.  
  158. // Default for temp_dir
  159. if (getenv('PHP_PEAR_TEMP_DIR')) {
  160.     define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
  161. } else {
  162.     define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
  163.            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
  164.            DIRECTORY_SEPARATOR . 'temp');
  165. }
  166.  
  167. // Default for cache_dir
  168. if (getenv('PHP_PEAR_CACHE_DIR')) {
  169.     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
  170. } else {
  171.     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
  172.            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
  173.            DIRECTORY_SEPARATOR . 'cache');
  174. }
  175.  
  176. // Default for download_dir
  177. if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
  178.     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
  179. } else {
  180.     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
  181.            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
  182.            DIRECTORY_SEPARATOR . 'download');
  183. }
  184.  
  185. // Default for php_bin
  186. if (getenv('PHP_PEAR_PHP_BIN')) {
  187.     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
  188. } else {
  189.     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
  190.            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
  191. }
  192.  
  193. // Default for verbose
  194. if (getenv('PHP_PEAR_VERBOSE')) {
  195.     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
  196. } else {
  197.     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
  198. }
  199.  
  200. // Default for preferred_state
  201. if (getenv('PHP_PEAR_PREFERRED_STATE')) {
  202.     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
  203. } else {
  204.     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
  205. }
  206.  
  207. // Default for umask
  208. if (getenv('PHP_PEAR_UMASK')) {
  209.     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
  210. } else {
  211.     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
  212. }
  213.  
  214. // Default for cache_ttl
  215. if (getenv('PHP_PEAR_CACHE_TTL')) {
  216.     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
  217. } else {
  218.     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
  219. }
  220.  
  221. // Default for sig_type
  222. if (getenv('PHP_PEAR_SIG_TYPE')) {
  223.     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
  224. } else {
  225.     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
  226. }
  227.  
  228. // Default for sig_bin
  229. if (getenv('PHP_PEAR_SIG_BIN')) {
  230.     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
  231. } else {
  232.     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
  233.            System::which(
  234.                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
  235. }
  236.  
  237. // Default for sig_keydir
  238. if (getenv('PHP_PEAR_SIG_KEYDIR')) {
  239.     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
  240. } else {
  241.     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
  242.            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
  243. }
  244.  
  245. /**
  246.  * This is a class for storing configuration data, keeping track of
  247.  * which are system-defined, user-defined or defaulted.
  248.  * @category   pear
  249.  * @package    PEAR
  250.  * @author     Stig Bakken <ssb@php.net>
  251.  * @author     Greg Beaver <cellog@php.net>
  252.  * @copyright  1997-2008 The PHP Group
  253.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  254.  * @version    Release: 1.7.1
  255.  * @link       http://pear.php.net/package/PEAR
  256.  * @since      Class available since Release 0.1
  257.  */
  258. class PEAR_Config extends PEAR
  259. {
  260.     // {{{ properties
  261.  
  262.     /**
  263.      * Array of config files used.
  264.      *
  265.      * @var array layer => config file
  266.      */
  267.     var $files = array(
  268.         'system' => '',
  269.         'user' => '',
  270.         );
  271.  
  272.     var $layers = array();
  273.     
  274.     /**
  275.      * Configuration data, two-dimensional array where the first
  276.      * dimension is the config layer ('user', 'system' and 'default'),
  277.      * and the second dimension is keyname => value.
  278.      *
  279.      * The order in the first dimension is important!  Earlier
  280.      * layers will shadow later ones when a config value is
  281.      * requested (if a 'user' value exists, it will be returned first,
  282.      * then 'system' and finally 'default').
  283.      *
  284.      * @var array layer => array(keyname => value, ...)
  285.      */
  286.     var $configuration = array(
  287.         'user' => array(),
  288.         'system' => array(),
  289.         'default' => array(),
  290.         );
  291.     
  292.     /**
  293.      * Configuration values that can be set for a channel
  294.      *
  295.      * All other configuration values can only have a global value
  296.      * @var array
  297.      * @access private
  298.      */
  299.     var $_channelConfigInfo = array(
  300.         'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
  301.         'test_dir', 'www_dir', 'php_bin', 'username', 'password', 'verbose',
  302.         'preferred_state', 'umask', 'preferred_mirror',
  303.         );
  304.  
  305.     /**
  306.      * Channels that can be accessed
  307.      * @see setChannels()
  308.      * @var array
  309.      * @access private
  310.      */
  311.     var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
  312.  
  313.     /**
  314.      * This variable is used to control the directory values returned
  315.      * @see setInstallRoot();
  316.      * @var string|false
  317.      * @access private
  318.      */
  319.     var $_installRoot = false;
  320.  
  321.     /**
  322.      * If requested, this will always refer to the registry
  323.      * contained in php_dir
  324.      * @var PEAR_Registry
  325.      */
  326.     var $_registry = array();
  327.  
  328.     /**
  329.      * @var array
  330.      * @access private
  331.      */
  332.     var $_regInitialized = array();
  333.  
  334.     /**
  335.      * @var bool
  336.      * @access private
  337.      */
  338.     var $_noRegistry = false;
  339.  
  340.     /**
  341.      * amount of errors found while parsing config
  342.      * @var integer
  343.      * @access private
  344.      */
  345.     var $_errorsFound = 0;
  346.     var $_lastError = null;
  347.  
  348.     /**
  349.      * Information about the configuration data.  Stores the type,
  350.      * default value and a documentation string for each configuration
  351.      * value.
  352.      *
  353.      * @var array layer => array(infotype => value, ...)
  354.      */
  355.     var $configuration_info = array(
  356.         // Channels/Internet Access
  357.         'default_channel' => array(
  358.             'type' => 'string',
  359.             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
  360.             'doc' => 'the default channel to use for all non explicit commands',
  361.             'prompt' => 'Default Channel',
  362.             'group' => 'Internet Access',
  363.             ),
  364.         'preferred_mirror' => array(
  365.             'type' => 'string',
  366.             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
  367.             'doc' => 'the default server or mirror to use for channel actions',
  368.             'prompt' => 'Default Channel Mirror',
  369.             'group' => 'Internet Access',
  370.             ),
  371.         'remote_config' => array(
  372.             'type' => 'password',
  373.             'default' => '',
  374.             'doc' => 'ftp url of remote configuration file to use for synchronized install',
  375.             'prompt' => 'Remote Configuration File',
  376.             'group' => 'Internet Access',
  377.             ),
  378.         'auto_discover' => array(
  379.             'type' => 'integer',
  380.             'default' => 0,
  381.             'doc' => 'whether to automatically discover new channels',
  382.             'prompt' => 'Auto-discover new Channels',
  383.             'group' => 'Internet Access',
  384.             ),
  385.         // Internet Access
  386.         'master_server' => array(
  387.             'type' => 'string',
  388.             'default' => 'pear.php.net',
  389.             'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
  390.             'prompt' => 'PEAR server [DEPRECATED]',
  391.             'group' => 'Internet Access',
  392.             ),
  393.         'http_proxy' => array(
  394.             'type' => 'string',
  395.             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
  396.             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
  397.             'prompt' => 'HTTP Proxy Server Address',
  398.             'group' => 'Internet Access',
  399.             ),
  400.         // File Locations
  401.         'php_dir' => array(
  402.             'type' => 'directory',
  403.             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
  404.             'doc' => 'directory where .php files are installed',
  405.             'prompt' => 'PEAR directory',
  406.             'group' => 'File Locations',
  407.             ),
  408.         'ext_dir' => array(
  409.             'type' => 'directory',
  410.             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
  411.             'doc' => 'directory where loadable extensions are installed',
  412.             'prompt' => 'PHP extension directory',
  413.             'group' => 'File Locations',
  414.             ),
  415.         'doc_dir' => array(
  416.             'type' => 'directory',
  417.             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
  418.             'doc' => 'directory where documentation is installed',
  419.             'prompt' => 'PEAR documentation directory',
  420.             'group' => 'File Locations',
  421.             ),
  422.         'bin_dir' => array(
  423.             'type' => 'directory',
  424.             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
  425.             'doc' => 'directory where executables are installed',
  426.             'prompt' => 'PEAR executables directory',
  427.             'group' => 'File Locations',
  428.             ),
  429.         'data_dir' => array(
  430.             'type' => 'directory',
  431.             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
  432.             'doc' => 'directory where data files are installed',
  433.             'prompt' => 'PEAR data directory',
  434.             'group' => 'File Locations (Advanced)',
  435.             ),
  436.         'cfg_dir' => array(
  437.             'type' => 'directory',
  438.             'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
  439.             'doc' => 'directory where modifiable configuration files are installed',
  440.             'prompt' => 'PEAR configuration file directory',
  441.             'group' => 'File Locations (Advanced)',
  442.             ),
  443.         'www_dir' => array(
  444.             'type' => 'directory',
  445.             'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
  446.             'doc' => 'directory where www frontend files (html/js) are installed',
  447.             'prompt' => 'PEAR www files directory',
  448.             'group' => 'File Locations (Advanced)',
  449.             ),
  450.         'test_dir' => array(
  451.             'type' => 'directory',
  452.             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
  453.             'doc' => 'directory where regression tests are installed',
  454.             'prompt' => 'PEAR test directory',
  455.             'group' => 'File Locations (Advanced)',
  456.             ),
  457.         'cache_dir' => array(
  458.             'type' => 'directory',
  459.             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
  460.             'doc' => 'directory which is used for XMLRPC cache',
  461.             'prompt' => 'PEAR Installer cache directory',
  462.             'group' => 'File Locations (Advanced)',
  463.             ),
  464.         'temp_dir' => array(
  465.             'type' => 'directory',
  466.             'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
  467.             'doc' => 'directory which is used for all temp files',
  468.             'prompt' => 'PEAR Installer temp directory',
  469.             'group' => 'File Locations (Advanced)',
  470.             ),
  471.         'download_dir' => array(
  472.             'type' => 'directory',
  473.             'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
  474.             'doc' => 'directory which is used for all downloaded files',
  475.             'prompt' => 'PEAR Installer download directory',
  476.             'group' => 'File Locations (Advanced)',
  477.             ),
  478.         'php_bin' => array(
  479.             'type' => 'file',
  480.             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
  481.             'doc' => 'PHP CLI/CGI binary for executing scripts',
  482.             'prompt' => 'PHP CLI/CGI binary',
  483.             'group' => 'File Locations (Advanced)',
  484.             ),
  485.         'php_ini' => array(
  486.             'type' => 'file',
  487.             'default' => '',
  488.             'doc' => 'location of php.ini in which to enable PECL extensions on install',
  489.             'prompt' => 'php.ini location',
  490.             'group' => 'File Locations (Advanced)',
  491.             ),
  492.         // Maintainers
  493.         'username' => array(
  494.             'type' => 'string',
  495.             'default' => '',
  496.             'doc' => '(maintainers) your PEAR account name',
  497.             'prompt' => 'PEAR username (for maintainers)',
  498.             'group' => 'Maintainers',
  499.             ),
  500.         'password' => array(
  501.             'type' => 'password',
  502.             'default' => '',
  503.             'doc' => '(maintainers) your PEAR account password',
  504.             'prompt' => 'PEAR password (for maintainers)',
  505.             'group' => 'Maintainers',
  506.             ),
  507.         // Advanced
  508.         'verbose' => array(
  509.             'type' => 'integer',
  510.             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
  511.             'doc' => 'verbosity level
  512. 0: really quiet
  513. 1: somewhat quiet
  514. 2: verbose
  515. 3: debug',
  516.             'prompt' => 'Debug Log Level',
  517.             'group' => 'Advanced',
  518.             ),
  519.         'preferred_state' => array(
  520.             'type' => 'set',
  521.             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
  522.             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
  523.             'valid_set' => array(
  524.                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
  525.             'prompt' => 'Preferred Package State',
  526.             'group' => 'Advanced',
  527.             ),
  528.         'umask' => array(
  529.             'type' => 'mask',
  530.             'default' => PEAR_CONFIG_DEFAULT_UMASK,
  531.             'doc' => 'umask used when creating files (Unix-like systems only)',
  532.             'prompt' => 'Unix file mask',
  533.             'group' => 'Advanced',
  534.             ),
  535.         'cache_ttl' => array(
  536.             'type' => 'integer',
  537.             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
  538.             'doc' => 'amount of secs where the local cache is used and not updated',
  539.             'prompt' => 'Cache TimeToLive',
  540.             'group' => 'Advanced',
  541.             ),
  542.         'sig_type' => array(
  543.             'type' => 'set',
  544.             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
  545.             'doc' => 'which package signature mechanism to use',
  546.             'valid_set' => array('gpg'),
  547.             'prompt' => 'Package Signature Type',
  548.             'group' => 'Maintainers',
  549.             ),
  550.         'sig_bin' => array(
  551.             'type' => 'string',
  552.             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
  553.             'doc' => 'which package signature mechanism to use',
  554.             'prompt' => 'Signature Handling Program',
  555.             'group' => 'Maintainers',
  556.             ),
  557.         'sig_keyid' => array(
  558.             'type' => 'string',
  559.             'default' => '',
  560.             'doc' => 'which key to use for signing with',
  561.             'prompt' => 'Signature Key Id',
  562.             'group' => 'Maintainers',
  563.             ),
  564.         'sig_keydir' => array(
  565.             'type' => 'directory',
  566.             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
  567.             'doc' => 'directory where signature keys are located',
  568.             'prompt' => 'Signature Key Directory',
  569.             'group' => 'Maintainers',
  570.             ),
  571.         // __channels is reserved - used for channel-specific configuration
  572.         );
  573.  
  574.     // }}}
  575.  
  576.     // {{{ PEAR_Config([file], [defaults_file])
  577.  
  578.     /**
  579.      * Constructor.
  580.      *
  581.      * @param string file to read user-defined options from
  582.      * @param string file to read system-wide defaults from
  583.      * @param bool   determines whether a registry object "follows"
  584.      *               the value of php_dir (is automatically created
  585.      *               and moved when php_dir is changed)
  586.      * @param bool   if true, fails if configuration files cannot be loaded
  587.      *
  588.      * @access public
  589.      *
  590.      * @see PEAR_Config::singleton
  591.      */
  592.     function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
  593.                          $strict = true)
  594.     {
  595.         $this->PEAR();
  596.         PEAR_Installer_Role::initializeConfig($this);
  597.         $sl = DIRECTORY_SEPARATOR;
  598.         if (empty($user_file)) {
  599.             if (OS_WINDOWS) {
  600.                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
  601.             } else {
  602.                 $user_file = getenv('HOME') . $sl . '.pearrc';
  603.             }
  604.         }
  605.         if (empty($system_file)) {
  606.             if (OS_WINDOWS) {
  607.                 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';
  608.             } else {
  609.                 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';
  610.             }
  611.         }
  612.  
  613.         $this->layers = array_keys($this->configuration);
  614.         $this->files['user'] = $user_file;
  615.         $this->files['system'] = $system_file;
  616.         if ($user_file && file_exists($user_file)) {
  617.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  618.             $this->readConfigFile($user_file, 'user', $strict);
  619.             $this->popErrorHandling();
  620.             if ($this->_errorsFound > 0) {
  621.                 return;
  622.             }
  623.         }
  624.  
  625.         if ($system_file && file_exists($system_file)) {
  626.             $this->mergeConfigFile($system_file, false, 'system', $strict);
  627.             if ($this->_errorsFound > 0) {
  628.                 return;
  629.             }
  630.  
  631.         }
  632.  
  633.         if (!$ftp_file) {
  634.             $ftp_file = $this->get('remote_config');
  635.         }
  636.  
  637.         if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
  638.             $this->readFTPConfigFile($ftp_file);
  639.         }
  640.  
  641.         foreach ($this->configuration_info as $key => $info) {
  642.             $this->configuration['default'][$key] = $info['default'];
  643.         }
  644.  
  645.         $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);
  646.         $this->_registry['default']->setConfig($this);
  647.         $this->_regInitialized['default'] = false;
  648.         //$GLOBALS['_PEAR_Config_instance'] = &$this;
  649.     }
  650.  
  651.     // }}}
  652.     /**
  653.      * Return the default locations of user and system configuration files
  654.      * @static
  655.      */
  656.     function getDefaultConfigFiles()
  657.     {
  658.         $sl = DIRECTORY_SEPARATOR;
  659.         if (OS_WINDOWS) {
  660.             return array(
  661.                 'user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
  662.                 'system' =>  PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
  663.             );
  664.         } else {
  665.             return array(
  666.                 'user' => getenv('HOME') . $sl . '.pearrc',
  667.                 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
  668.             );
  669.         }
  670.     }
  671.     // {{{ singleton([file], [defaults_file])
  672.  
  673.     /**
  674.      * Static singleton method.  If you want to keep only one instance
  675.      * of this class in use, this method will give you a reference to
  676.      * the last created PEAR_Config object if one exists, or create a
  677.      * new object.
  678.      *
  679.      * @param string (optional) file to read user-defined options from
  680.      * @param string (optional) file to read system-wide defaults from
  681.      *
  682.      * @return object an existing or new PEAR_Config instance
  683.      *
  684.      * @access public
  685.      *
  686.      * @see PEAR_Config::PEAR_Config
  687.      */
  688.     function &singleton($user_file = '', $system_file = '', $strict = true)
  689.     {
  690.         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
  691.             return $GLOBALS['_PEAR_Config_instance'];
  692.         }
  693.  
  694.         $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);
  695.         if ($t_conf->_errorsFound > 0) {
  696.              return $t_conf->lastError;
  697.         }
  698.  
  699.         $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
  700.         return $GLOBALS['_PEAR_Config_instance'];
  701.     }
  702.  
  703.     // }}}
  704.     // {{{ validConfiguration()
  705.  
  706.     /**
  707.      * Determine whether any configuration files have been detected, and whether a
  708.      * registry object can be retrieved from this configuration.
  709.      * @return bool
  710.      * @since PEAR 1.4.0a1
  711.      */
  712.     function validConfiguration()
  713.     {
  714.         if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
  715.             return true;
  716.         }
  717.         return false;
  718.     }
  719.  
  720.     // }}}
  721.     // {{{ readConfigFile([file], [layer])
  722.  
  723.     /**
  724.      * Reads configuration data from a file.  All existing values in
  725.      * the config layer are discarded and replaced with data from the
  726.      * file.
  727.      * @param string file to read from, if NULL or not specified, the
  728.      *               last-used file for the same layer (second param) is used
  729.      * @param string config layer to insert data into ('user' or 'system')
  730.      * @return bool TRUE on success or a PEAR error on failure
  731.      */
  732.     function readConfigFile($file = null, $layer = 'user', $strict = true)
  733.     {
  734.         if (empty($this->files[$layer])) {
  735.             return $this->raiseError("unknown config layer `$layer'");
  736.         }
  737.  
  738.         if ($file === null) {
  739.             $file = $this->files[$layer];
  740.         }
  741.  
  742.         $data = $this->_readConfigDataFrom($file);
  743.  
  744.         if (PEAR::isError($data)) {
  745.             if ($strict) {
  746.                 $this->_errorsFound++;
  747.                 $this->lastError = $data;
  748.  
  749.                 return $data;
  750.             } else {
  751.                 return true;
  752.             }
  753.         } else {
  754.             $this->files[$layer] = $file;
  755.         }
  756.  
  757.         $this->_decodeInput($data);
  758.         $this->configuration[$layer] = $data;
  759.         $this->_setupChannels();
  760.         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
  761.             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
  762.             $this->_registry[$layer]->setConfig($this);
  763.             $this->_regInitialized[$layer] = false;
  764.         } else {
  765.             unset($this->_registry[$layer]);
  766.         }
  767.         return true;
  768.     }
  769.  
  770.     // }}}
  771.  
  772.     /**
  773.      * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
  774.      * @return true|PEAR_Error
  775.      */
  776.     function readFTPConfigFile($path)
  777.     {
  778.         do { // poor man's try
  779.             if (!class_exists('PEAR_FTP')) {
  780.                 if (!class_exists('PEAR_Common')) {
  781.                     require_once 'PEAR/Common.php';
  782.                 }
  783.                 if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
  784.                     require_once 'PEAR/FTP.php';
  785.                 }
  786.             }
  787.             if (class_exists('PEAR_FTP')) {
  788.                 $this->_ftp = &new PEAR_FTP;
  789.                 $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
  790.                 $e = $this->_ftp->init($path);
  791.                 if (PEAR::isError($e)) {
  792.                     $this->_ftp->popErrorHandling();
  793.                     return $e;
  794.                 }
  795.                 $tmp = System::mktemp('-d');
  796.                 PEAR_Common::addTempFile($tmp);
  797.                 $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
  798.                     'pear.ini', false, FTP_BINARY);
  799.                 if (PEAR::isError($e)) {
  800.                     $this->_ftp->popErrorHandling();
  801.                     return $e;
  802.                 }
  803.                 PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
  804.                 $this->_ftp->disconnect();
  805.                 $this->_ftp->popErrorHandling();
  806.                 $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
  807.                 $e = $this->readConfigFile(null, 'ftp');
  808.                 if (PEAR::isError($e)) {
  809.                     return $e;
  810.                 }
  811.                 $fail = array();
  812.                 foreach ($this->configuration_info as $key => $val) {
  813.                     if (in_array($this->getGroup($key),
  814.                           array('File Locations', 'File Locations (Advanced)')) &&
  815.                           $this->getType($key) == 'directory') {
  816.                         // any directory configs must be set for this to work
  817.                         if (!isset($this->configuration['ftp'][$key])) {
  818.                             $fail[] = $key;
  819.                         }
  820.                     }
  821.                 }
  822.                 if (count($fail)) {
  823.                     $fail = '"' . implode('", "', $fail) . '"';
  824.                     unset($this->files['ftp']);
  825.                     unset($this->configuration['ftp']);
  826.                     return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
  827.                         'directory configuration variables.  These variables were not set: ' .
  828.                         $fail);
  829.                 } else {
  830.                     return true;
  831.                 }
  832.             } else {
  833.                 return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
  834.             }
  835.         } while (false); // poor man's catch
  836.         unset($this->files['ftp']);
  837.         return PEAR::raiseError('no remote host specified');
  838.     }
  839.  
  840.     // {{{ _setupChannels()
  841.     
  842.     /**
  843.      * Reads the existing configurations and creates the _channels array from it
  844.      */
  845.     function _setupChannels()
  846.     {
  847.         $set = array_flip(array_values($this->_channels));
  848.         foreach ($this->configuration as $layer => $data) {
  849.             $i = 1000;
  850.             if (isset($data['__channels']) && is_array($data['__channels'])) {
  851.                 foreach ($data['__channels'] as $channel => $info) {
  852.                     $set[$channel] = $i++;
  853.                 }
  854.             }
  855.         }
  856.         $this->_channels = array_values(array_flip($set));
  857.         $this->setChannels($this->_channels);
  858.     }
  859.  
  860.     // }}}
  861.     // {{{ deleteChannel(channel)
  862.  
  863.     function deleteChannel($channel)
  864.     {
  865.         foreach ($this->configuration as $layer => $data) {
  866.             if (isset($data['__channels'])) {
  867.                 if (isset($data['__channels'][strtolower($channel)])) {
  868.                     unset($this->configuration[$layer]['__channels'][strtolower($channel)]);
  869.                 }
  870.             }
  871.         }
  872.         $this->_channels = array_flip($this->_channels);
  873.         unset($this->_channels[strtolower($channel)]);
  874.         $this->_channels = array_flip($this->_channels);
  875.     }
  876.  
  877.     // }}}
  878.     // {{{ mergeConfigFile(file, [override], [layer])
  879.  
  880.     /**
  881.      * Merges data into a config layer from a file.  Does the same
  882.      * thing as readConfigFile, except it does not replace all
  883.      * existing values in the config layer.
  884.      * @param string file to read from
  885.      * @param bool whether to overwrite existing data (default TRUE)
  886.      * @param string config layer to insert data into ('user' or 'system')
  887.      * @param string if true, errors are returned if file opening fails
  888.      * @return bool TRUE on success or a PEAR error on failure
  889.      */
  890.     function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
  891.     {
  892.         if (empty($this->files[$layer])) {
  893.             return $this->raiseError("unknown config layer `$layer'");
  894.         }
  895.         if ($file === null) {
  896.             $file = $this->files[$layer];
  897.         }
  898.         $data = $this->_readConfigDataFrom($file);
  899.         if (PEAR::isError($data)) {
  900.             if ($strict) {
  901.                 $this->_errorsFound++;
  902.                 $this->lastError = $data;
  903.  
  904.                 return $data;
  905.             } else {
  906.                 return true;
  907.             }
  908.         }
  909.         $this->_decodeInput($data);
  910.         if ($override) {
  911.             $this->configuration[$layer] =
  912.                 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
  913.         } else {
  914.             $this->configuration[$layer] =
  915.                 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
  916.         }
  917.         $this->_setupChannels();
  918.         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
  919.             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
  920.             $this->_registry[$layer]->setConfig($this);
  921.             $this->_regInitialized[$layer] = false;
  922.         } else {
  923.             unset($this->_registry[$layer]);
  924.         }
  925.         return true;
  926.     }
  927.  
  928.     // }}}
  929.     // {{{ arrayMergeRecursive($arr2, $arr1)
  930.     /**
  931.      * @param array
  932.      * @param array
  933.      * @return array
  934.      * @static
  935.      */
  936.     function arrayMergeRecursive($arr2, $arr1)
  937.     {
  938.         $ret = array();
  939.         foreach ($arr2 as $key => $data) {
  940.             if (!isset($arr1[$key])) {
  941.                 $ret[$key] = $data;
  942.                 unset($arr1[$key]);
  943.                 continue;
  944.             }
  945.             if (is_array($data)) {
  946.                 if (!is_array($arr1[$key])) {
  947.                     $ret[$key] = $arr1[$key];
  948.                     unset($arr1[$key]);
  949.                     continue;
  950.                 }
  951.                 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
  952.                 unset($arr1[$key]);
  953.             }
  954.         }
  955.         return array_merge($ret, $arr1);
  956.     }
  957.  
  958.     // }}}
  959.     // {{{ writeConfigFile([file], [layer])
  960.  
  961.     /**
  962.      * Writes data into a config layer from a file.
  963.      *
  964.      * @param string|null file to read from, or null for default
  965.      * @param string config layer to insert data into ('user' or
  966.      *               'system')
  967.      * @param string|null data to write to config file or null for internal data [DEPRECATED]
  968.      * @return bool TRUE on success or a PEAR error on failure
  969.      */
  970.     function writeConfigFile($file = null, $layer = 'user', $data = null)
  971.     {
  972.         $this->_lazyChannelSetup($layer);
  973.         if ($layer == 'both' || $layer == 'all') {
  974.             foreach ($this->files as $type => $file) {
  975.                 $err = $this->writeConfigFile($file, $type, $data);
  976.                 if (PEAR::isError($err)) {
  977.                     return $err;
  978.                 }
  979.             }
  980.             return true;
  981.         }
  982.         if (empty($this->files[$layer])) {
  983.             return $this->raiseError("unknown config file type `$layer'");
  984.         }
  985.         if ($file === null) {
  986.             $file = $this->files[$layer];
  987.         }
  988.         $data = ($data === null) ? $this->configuration[$layer] : $data;
  989.         $this->_encodeOutput($data);
  990.         $opt = array('-p', dirname($file));
  991.         if (!@System::mkDir($opt)) {
  992.             return $this->raiseError("could not create directory: " . dirname($file));
  993.         }
  994.         if (file_exists($file) && is_file($file) && !is_writeable($file)) {
  995.             return $this->raiseError("no write access to $file!");
  996.         }
  997.         $fp = @fopen($file, "w");
  998.         if (!$fp) {
  999.             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
  1000.         }
  1001.         $contents = "#PEAR_Config 0.9\n" . serialize($data);
  1002.         if (!@fwrite($fp, $contents)) {
  1003.             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
  1004.         }
  1005.         return true;
  1006.     }
  1007.  
  1008.     // }}}
  1009.     // {{{ _readConfigDataFrom(file)
  1010.  
  1011.     /**
  1012.      * Reads configuration data from a file and returns the parsed data
  1013.      * in an array.
  1014.      *
  1015.      * @param string file to read from
  1016.      *
  1017.      * @return array configuration data or a PEAR error on failure
  1018.      *
  1019.      * @access private
  1020.      */
  1021.     function _readConfigDataFrom($file)
  1022.     {
  1023.         $fp = false;
  1024.         if (file_exists($file)) {
  1025.             $fp = @fopen($file, "r");
  1026.         }
  1027.         if (!$fp) {
  1028.             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
  1029.         }
  1030.         $size = filesize($file);
  1031.         $rt = get_magic_quotes_runtime();
  1032.         set_magic_quotes_runtime(0);
  1033.         fclose($fp);
  1034.         $contents = file_get_contents($file);
  1035.         if (empty($contents)) {
  1036.             return $this->raiseError('Configuration file "' . $file . '" is empty');
  1037.         }
  1038.         
  1039.         set_magic_quotes_runtime($rt);
  1040.  
  1041.         $version = false;
  1042.         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
  1043.             $version = $matches[1];
  1044.             $contents = substr($contents, strlen($matches[0]));
  1045.         } else {
  1046.             // Museum config file
  1047.             if (substr($contents,0,2) == 'a:') {
  1048.                 $version = '0.1';
  1049.             }
  1050.         }
  1051.         if ($version && version_compare("$version", '1', '<')) {
  1052.  
  1053.             // no '@', it is possible that unserialize
  1054.             // raises a notice but it seems to block IO to
  1055.             // STDOUT if a '@' is used and a notice is raise
  1056.             $data = unserialize($contents);
  1057.  
  1058.             if (!is_array($data) && !$data) {
  1059.                 if ($contents == serialize(false)) {
  1060.                     $data = array();
  1061.                 } else {
  1062.                     $err = $this->raiseError("PEAR_Config: bad data in $file");
  1063.                     return $err;
  1064.                 }
  1065.             }
  1066.             if (!is_array($data)) {
  1067.                 if (strlen(trim($contents)) > 0) {
  1068.                     $error = "PEAR_Config: bad data in $file";
  1069.                     $err = $this->raiseError($error);
  1070.                     return $err;
  1071.                 } else {
  1072.                     $data = array();
  1073.                 }
  1074.             }
  1075.         // add parsing of newer formats here...
  1076.         } else {
  1077.             $err = $this->raiseError("$file: unknown version `$version'");
  1078.             return $err; 
  1079.         }
  1080.         return $data;
  1081.     }
  1082.  
  1083.     // }}}
  1084.     // {{{ getConfFile(layer)
  1085.     /**
  1086.     * Gets the file used for storing the config for a layer
  1087.     *
  1088.     * @param string $layer 'user' or 'system'
  1089.     */
  1090.  
  1091.     function getConfFile($layer)
  1092.     {
  1093.         return $this->files[$layer];
  1094.     }
  1095.  
  1096.     // }}}
  1097.  
  1098.     /**
  1099.      * @param string Configuration class name, used for detecting duplicate calls
  1100.      * @param array information on a role as parsed from its xml file
  1101.      * @return true|PEAR_Error
  1102.      * @access private
  1103.      */
  1104.     function _addConfigVars($class, $vars)
  1105.     {
  1106.         static $called = array();
  1107.         if (isset($called[$class])) {
  1108.             return;
  1109.         }
  1110.         $called[$class] = 1;
  1111.         if (count($vars) > 3) {
  1112.             return $this->raiseError('Roles can only define 3 new config variables or less');
  1113.         }
  1114.         foreach ($vars as $name => $var) {
  1115.             if (!is_array($var)) {
  1116.                 return $this->raiseError('Configuration information must be an array');
  1117.             }
  1118.             if (!isset($var['type'])) {
  1119.                 return $this->raiseError('Configuration information must contain a type');
  1120.             } else {
  1121.                 if (!in_array($var['type'],
  1122.                       array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
  1123.                     return $this->raiseError(
  1124.                         'Configuration type must be one of directory, file, string, ' .
  1125.                         'mask, set, or password');
  1126.                 }
  1127.             }
  1128.             if (!isset($var['default'])) {
  1129.                 return $this->raiseError(
  1130.                     'Configuration information must contain a default value ("default" index)');
  1131.             } else {
  1132.                 if (is_array($var['default'])) {
  1133.                     $real_default = '';
  1134.                     foreach ($var['default'] as $config_var => $val) {
  1135.                         if (strpos($config_var, 'text') === 0) {
  1136.                             $real_default .= $val;
  1137.                         } elseif (strpos($config_var, 'constant') === 0) {
  1138.                             if (defined($val)) {
  1139.                                 $real_default .= constant($val);
  1140.                             } else {
  1141.                                 return $this->raiseError(
  1142.                                     'Unknown constant "' . $val . '" requested in ' .
  1143.                                     'default value for configuration variable "' .
  1144.                                     $name . '"');
  1145.                             }
  1146.                         } elseif (isset($this->configuration_info[$config_var])) {
  1147.                             $real_default .=
  1148.                                 $this->configuration_info[$config_var]['default'];
  1149.                         } else {
  1150.                             return $this->raiseError(
  1151.                                 'Unknown request for "' . $config_var . '" value in ' .
  1152.                                 'default value for configuration variable "' .
  1153.                                 $name . '"');
  1154.                         }
  1155.                     }
  1156.                     $var['default'] = $real_default;
  1157.                 }
  1158.                 if ($var['type'] == 'integer') {
  1159.                     $var['default'] = (integer) $var['default'];
  1160.                 }
  1161.             }
  1162.             if (!isset($var['doc'])) {
  1163.                 return $this->raiseError(
  1164.                     'Configuration information must contain a summary ("doc" index)');
  1165.             }
  1166.             if (!isset($var['prompt'])) {
  1167.                 return $this->raiseError(
  1168.                     'Configuration information must contain a simple prompt ("prompt" index)');
  1169.             }
  1170.             if (!isset($var['group'])) {
  1171.                 return $this->raiseError(
  1172.                     'Configuration information must contain a simple group ("group" index)');
  1173.             }
  1174.             if (isset($this->configuration_info[$name])) {
  1175.                 return $this->raiseError('Configuration variable "' . $name .
  1176.                     '" already exists');
  1177.             }
  1178.             $this->configuration_info[$name] = $var;
  1179.             // fix bug #7351: setting custom config variable in a channel fails
  1180.             $this->_channelConfigInfo[] = $name;
  1181.         }
  1182.         return true;
  1183.     }
  1184.  
  1185.     // {{{ _encodeOutput(&data)
  1186.  
  1187.     /**
  1188.      * Encodes/scrambles configuration data before writing to files.
  1189.      * Currently, 'password' values will be base64-encoded as to avoid
  1190.      * that people spot cleartext passwords by accident.
  1191.      *
  1192.      * @param array (reference) array to encode values in
  1193.      *
  1194.      * @return bool TRUE on success
  1195.      *
  1196.      * @access private
  1197.      */
  1198.     function _encodeOutput(&$data)
  1199.     {
  1200.         foreach ($data as $key => $value) {
  1201.             if ($key == '__channels') {
  1202.                 foreach ($data['__channels'] as $channel => $blah) {
  1203.                     $this->_encodeOutput($data['__channels'][$channel]);
  1204.                 }
  1205.             }
  1206.             if (!isset($this->configuration_info[$key])) {
  1207.                 continue;
  1208.             }
  1209.             $type = $this->configuration_info[$key]['type'];
  1210.             switch ($type) {
  1211.                 // we base64-encode passwords so they are at least
  1212.                 // not shown in plain by accident
  1213.                 case 'password': {
  1214.                     $data[$key] = base64_encode($data[$key]);
  1215.                     break;
  1216.                 }
  1217.                 case 'mask': {
  1218.                     $data[$key] = octdec($data[$key]);
  1219.                     break;
  1220.                 }
  1221.             }
  1222.         }
  1223.         return true;
  1224.     }
  1225.  
  1226.     // }}}
  1227.     // {{{ _decodeInput(&data)
  1228.  
  1229.     /**
  1230.      * Decodes/unscrambles configuration data after reading from files.
  1231.      *
  1232.      * @param array (reference) array to encode values in
  1233.      *
  1234.      * @return bool TRUE on success
  1235.      *
  1236.      * @access private
  1237.      *
  1238.      * @see PEAR_Config::_encodeOutput
  1239.      */
  1240.     function _decodeInput(&$data)
  1241.     {
  1242.         if (!is_array($data)) {
  1243.             return true;
  1244.         }
  1245.         foreach ($data as $key => $value) {
  1246.             if ($key == '__channels') {
  1247.                 foreach ($data['__channels'] as $channel => $blah) {
  1248.                     $this->_decodeInput($data['__channels'][$channel]);
  1249.                 }
  1250.             }
  1251.             if (!isset($this->configuration_info[$key])) {
  1252.                 continue;
  1253.             }
  1254.             $type = $this->configuration_info[$key]['type'];
  1255.             switch ($type) {
  1256.                 case 'password': {
  1257.                     $data[$key] = base64_decode($data[$key]);
  1258.                     break;
  1259.                 }
  1260.                 case 'mask': {
  1261.                     $data[$key] = decoct($data[$key]);
  1262.                     break;
  1263.                 }
  1264.             }
  1265.         }
  1266.         return true;
  1267.     }
  1268.  
  1269.     // }}}
  1270.     // {{{ getDefaultChannel([layer])
  1271.     /**
  1272.      * Retrieve the default channel.
  1273.      *
  1274.      * On startup, channels are not initialized, so if the default channel is not
  1275.      * pear.php.net, then initialize the config.
  1276.      * @param string registry layer
  1277.      * @return string|false
  1278.      */
  1279.     function getDefaultChannel($layer = null)
  1280.     {
  1281.         $ret = false;
  1282.         if ($layer === null) {
  1283.             foreach ($this->layers as $layer) {
  1284.                 if (isset($this->configuration[$layer]['default_channel'])) {
  1285.                     $ret = $this->configuration[$layer]['default_channel'];
  1286.                     break;
  1287.                 }
  1288.             }
  1289.         } elseif (isset($this->configuration[$layer]['default_channel'])) {
  1290.             $ret = $this->configuration[$layer]['default_channel'];
  1291.         }
  1292.         if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
  1293.             $ret = 'pecl.php.net';
  1294.         }
  1295.         if ($ret) {
  1296.             if ($ret != 'pear.php.net') {
  1297.                 $this->_lazyChannelSetup();
  1298.             }
  1299.             return $ret;
  1300.         }
  1301.         return PEAR_CONFIG_DEFAULT_CHANNEL;
  1302.     }
  1303.  
  1304.     // {{{ get(key, [layer])
  1305.     /**
  1306.      * Returns a configuration value, prioritizing layers as per the
  1307.      * layers property.
  1308.      *
  1309.      * @param string config key
  1310.      *
  1311.      * @return mixed the config value, or NULL if not found
  1312.      *
  1313.      * @access public
  1314.      */
  1315.     function get($key, $layer = null, $channel = false)
  1316.     {
  1317.         if (!isset($this->configuration_info[$key])) {
  1318.             return null;
  1319.         }
  1320.         if ($key == '__channels') {
  1321.             return null;
  1322.         }
  1323.         if ($key == 'default_channel') {
  1324.             return $this->getDefaultChannel($layer);
  1325.         }
  1326.         if (!$channel) {
  1327.             $channel = $this->getDefaultChannel();
  1328.         } elseif ($channel != 'pear.php.net') {
  1329.             $this->_lazyChannelSetup();
  1330.         }
  1331.         $channel = strtolower($channel);
  1332.         
  1333.         $test = (in_array($key, $this->_channelConfigInfo)) ?
  1334.             $this->_getChannelValue($key, $layer, $channel) :
  1335.             null;
  1336.         if ($test !== null) {
  1337.             if ($this->_installRoot) {
  1338.                 if (in_array($this->getGroup($key),
  1339.                       array('File Locations', 'File Locations (Advanced)')) &&
  1340.                       $this->getType($key) == 'directory') {
  1341.                     return $this->_prependPath($test, $this->_installRoot);
  1342.                 }
  1343.             }
  1344.             return $test;
  1345.         }
  1346.         if ($layer === null) {
  1347.             foreach ($this->layers as $layer) {
  1348.                 if (isset($this->configuration[$layer][$key])) {
  1349.                     $test = $this->configuration[$layer][$key];
  1350.                     if ($this->_installRoot) {
  1351.                         if (in_array($this->getGroup($key),
  1352.                               array('File Locations', 'File Locations (Advanced)')) &&
  1353.                               $this->getType($key) == 'directory') {
  1354.                             return $this->_prependPath($test, $this->_installRoot);
  1355.                         }
  1356.                     }
  1357.                     if ($key == 'preferred_mirror') {
  1358.                         $reg = &$this->getRegistry();
  1359.                         if (is_object($reg)) {
  1360.                             $chan = &$reg->getChannel($channel);
  1361.                             if (PEAR::isError($chan)) {
  1362.                                 return $channel;
  1363.                             }
  1364.                             if (!$chan->getMirror($test) && $chan->getName() != $test) {
  1365.                                 return $channel; // mirror does not exist
  1366.                             }
  1367.                         }
  1368.                     }
  1369.                     return $test;
  1370.                 }
  1371.             }
  1372.         } elseif (isset($this->configuration[$layer][$key])) {
  1373.             $test = $this->configuration[$layer][$key];
  1374.             if ($this->_installRoot) {
  1375.                 if (in_array($this->getGroup($key),
  1376.                       array('File Locations', 'File Locations (Advanced)')) &&
  1377.                       $this->getType($key) == 'directory') {
  1378.                     return $this->_prependPath($test, $this->_installRoot);
  1379.                 }
  1380.             }
  1381.             if ($key == 'preferred_mirror') {
  1382.                 $reg = &$this->getRegistry();
  1383.                 if (is_object($reg)) {
  1384.                     $chan = &$reg->getChannel($channel);
  1385.                     if (PEAR::isError($chan)) {
  1386.                         return $channel;
  1387.                     }
  1388.                     if (!$chan->getMirror($test) && $chan->getName() != $test) {
  1389.                         return $channel; // mirror does not exist
  1390.                     }
  1391.                 }
  1392.             }
  1393.             return $test;
  1394.         }
  1395.         return null;
  1396.     }
  1397.  
  1398.     // }}}
  1399.     // {{{ _getChannelValue(key, value, [layer])
  1400.     /**
  1401.      * Returns a channel-specific configuration value, prioritizing layers as per the
  1402.      * layers property.
  1403.      *
  1404.      * @param string config key
  1405.      *
  1406.      * @return mixed the config value, or NULL if not found
  1407.      *
  1408.      * @access private
  1409.      */
  1410.     function _getChannelValue($key, $layer, $channel)
  1411.     {
  1412.         if ($key == '__channels' || $channel == 'pear.php.net') {
  1413.             return null;
  1414.         }
  1415.         $ret = null;
  1416.         if ($layer === null) {
  1417.             foreach ($this->layers as $ilayer) {
  1418.                 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
  1419.                     $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
  1420.                     break;
  1421.                 }
  1422.             }
  1423.         } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
  1424.             $ret = $this->configuration[$layer]['__channels'][$channel][$key];
  1425.         }
  1426.         if ($key == 'preferred_mirror') {
  1427.             if ($ret !== null) {
  1428.                 $reg = &$this->getRegistry($layer);
  1429.                 if (is_object($reg)) {
  1430.                     $chan = &$reg->getChannel($channel);
  1431.                     if (PEAR::isError($chan)) {
  1432.                         return $channel;
  1433.                     }
  1434.                     if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
  1435.                         return $channel; // mirror does not exist
  1436.                     }
  1437.                 }
  1438.                 return $ret;
  1439.             }
  1440.             if ($channel != $this->getDefaultChannel($layer)) {
  1441.                 return $channel; // we must use the channel name as the preferred mirror
  1442.                                  // if the user has not chosen an alternate
  1443.             } else {
  1444.                 return $this->getDefaultChannel($layer);
  1445.             }
  1446.         }
  1447.         return $ret;
  1448.     }
  1449.  
  1450.  
  1451.     // }}}
  1452.     // {{{ set(key, value, [layer])
  1453.  
  1454.     /**
  1455.      * Set a config value in a specific layer (defaults to 'user').
  1456.      * Enforces the types defined in the configuration_info array.  An
  1457.      * integer config variable will be cast to int, and a set config
  1458.      * variable will be validated against its legal values.
  1459.      *
  1460.      * @param string config key
  1461.      * @param string config value
  1462.      * @param string (optional) config layer
  1463.      * @param string channel to set this value for, or null for global value
  1464.      * @return bool TRUE on success, FALSE on failure
  1465.      */
  1466.     function set($key, $value, $layer = 'user', $channel = false)
  1467.     {
  1468.         if ($key == '__channels') {
  1469.             return false;
  1470.         }
  1471.         if (!isset($this->configuration[$layer])) {
  1472.             return false;
  1473.         }
  1474.         if ($key == 'default_channel') {
  1475.             // can only set this value globally
  1476.             $channel = 'pear.php.net';
  1477.             if ($value != 'pear.php.net') {
  1478.                 $this->_lazyChannelSetup($layer);
  1479.             }
  1480.         }
  1481.         if ($key == 'preferred_mirror') {
  1482.             if ($channel == '__uri') {
  1483.                 return false; // can't set the __uri pseudo-channel's mirror
  1484.             }
  1485.             $reg = &$this->getRegistry($layer);
  1486.             if (is_object($reg)) {
  1487.                 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
  1488.                 if (PEAR::isError($chan)) {
  1489.                     return false;
  1490.                 }
  1491.                 if (!$chan->getMirror($value) && $chan->getName() != $value) {
  1492.                     return false; // mirror does not exist
  1493.                 }
  1494.             }
  1495.         }
  1496.         if (!isset($this->configuration_info[$key])) {
  1497.             return false;
  1498.         }
  1499.         extract($this->configuration_info[$key]);
  1500.         switch ($type) {
  1501.             case 'integer':
  1502.                 $value = (int)$value;
  1503.                 break;
  1504.             case 'set': {
  1505.                 // If a valid_set is specified, require the value to
  1506.                 // be in the set.  If there is no valid_set, accept
  1507.                 // any value.
  1508.                 if ($valid_set) {
  1509.                     reset($valid_set);
  1510.                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
  1511.                         (key($valid_set) !== 0 && empty($valid_set[$value])))
  1512.                     {
  1513.                         return false;
  1514.                     }
  1515.                 }
  1516.                 break;
  1517.             }
  1518.         }
  1519.         if (!$channel) {
  1520.             $channel = $this->get('default_channel', null, 'pear.php.net');
  1521.         }
  1522.         if (!in_array($channel, $this->_channels)) {
  1523.             $this->_lazyChannelSetup($layer);
  1524.             $reg = &$this->getRegistry($layer);
  1525.             if ($reg) {
  1526.                 $channel = $reg->channelName($channel);
  1527.             }
  1528.             if (!in_array($channel, $this->_channels)) {
  1529.                 return false;
  1530.             }
  1531.         }
  1532.         if ($channel != 'pear.php.net') {
  1533.             if (in_array($key, $this->_channelConfigInfo)) {
  1534.                 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
  1535.                 return true;
  1536.             } else {
  1537.                 return false;
  1538.             }
  1539.         } else {
  1540.             if ($key == 'default_channel') {
  1541.                 if (!isset($reg)) {
  1542.                     $reg = &$this->getRegistry($layer);
  1543.                     if (!$reg) {
  1544.                         $reg = &$this->getRegistry();
  1545.                     }
  1546.                 }
  1547.                 if ($reg) {
  1548.                     $value = $reg->channelName($value);
  1549.                 }
  1550.                 if (!$value) {
  1551.                     return false;
  1552.                 }
  1553.             }
  1554.         }
  1555.         $this->configuration[$layer][$key] = $value;
  1556.         if ($key == 'php_dir' && !$this->_noRegistry) {
  1557.             if (!isset($this->_registry[$layer]) ||
  1558.                   $value != $this->_registry[$layer]->install_dir) {
  1559.                 $this->_registry[$layer] = &new PEAR_Registry($value);
  1560.                 $this->_regInitialized[$layer] = false;
  1561.                 $this->_registry[$layer]->setConfig($this);
  1562.             }
  1563.         }
  1564.         return true;
  1565.     }
  1566.  
  1567.     // }}}
  1568.     function _lazyChannelSetup($uselayer = false)
  1569.     {
  1570.         if ($this->_noRegistry) {
  1571.             return;
  1572.         }
  1573.         $merge = false;
  1574.         foreach ($this->_registry as $layer => $p) {
  1575.             if ($uselayer && $uselayer != $layer) {
  1576.                 continue;
  1577.             }
  1578.             if (!$this->_regInitialized[$layer]) {
  1579.                 if ($layer == 'default' && isset($this->_registry['user']) ||
  1580.                       isset($this->_registry['system'])) {
  1581.                     // only use the default registry if there are no alternatives
  1582.                     continue;
  1583.                 }
  1584.                 if (!is_object($this->_registry[$layer])) {
  1585.                     if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
  1586.                         $this->_registry[$layer] = &new PEAR_Registry($phpdir);
  1587.                         $this->_registry[$layer]->setConfig($this);
  1588.                         $this->_regInitialized[$layer] = false;
  1589.                     } else {
  1590.                         unset($this->_registry[$layer]);
  1591.                         return;
  1592.                     }
  1593.                 }
  1594.                 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
  1595.                 $this->_regInitialized[$layer] = true;
  1596.                 $merge = true;
  1597.             }
  1598.         }
  1599.     }
  1600.     // {{{ setChannels()
  1601.     
  1602.     /**
  1603.      * Set the list of channels.
  1604.      *
  1605.      * This should be set via a call to {@link PEAR_Registry::listChannels()}
  1606.      * @param array
  1607.      * @param bool
  1608.      * @return bool success of operation
  1609.      */
  1610.     function setChannels($channels, $merge = false)
  1611.     {
  1612.         if (!is_array($channels)) {
  1613.             return false;
  1614.         }
  1615.         if ($merge) {
  1616.             $this->_channels = array_merge($this->_channels, $channels);
  1617.         } else {
  1618.             $this->_channels = $channels;
  1619.         }
  1620.         foreach ($channels as $channel) {
  1621.             $channel = strtolower($channel);
  1622.             if ($channel == 'pear.php.net') {
  1623.                 continue;
  1624.             }
  1625.             foreach ($this->layers as $layer) {
  1626.                 if (!isset($this->configuration[$layer]['__channels'])) {
  1627.                     $this->configuration[$layer]['__channels'] = array();
  1628.                 }
  1629.                 if (!isset($this->configuration[$layer]['__channels'][$channel])
  1630.                       || !is_array($this->configuration[$layer]['__channels'][$channel])) {
  1631.                     $this->configuration[$layer]['__channels'][$channel] = array();
  1632.                 }
  1633.             }
  1634.         }
  1635.         return true;
  1636.     }
  1637.  
  1638.     // }}}
  1639.     // {{{ getType(key)
  1640.  
  1641.     /**
  1642.      * Get the type of a config value.
  1643.      *
  1644.      * @param string  config key
  1645.      *
  1646.      * @return string type, one of "string", "integer", "file",
  1647.      * "directory", "set" or "password".
  1648.      *
  1649.      * @access public
  1650.      *
  1651.      */
  1652.     function getType($key)
  1653.     {
  1654.         if (isset($this->configuration_info[$key])) {
  1655.             return $this->configuration_info[$key]['type'];
  1656.         }
  1657.         return false;
  1658.     }
  1659.  
  1660.     // }}}
  1661.     // {{{ getDocs(key)
  1662.  
  1663.     /**
  1664.      * Get the documentation for a config value.
  1665.      *
  1666.      * @param string  config key
  1667.      *
  1668.      * @return string documentation string
  1669.      *
  1670.      * @access public
  1671.      *
  1672.      */
  1673.     function getDocs($key)
  1674.     {
  1675.         if (isset($this->configuration_info[$key])) {
  1676.             return $this->configuration_info[$key]['doc'];
  1677.         }
  1678.         return false;
  1679.     }
  1680.        // }}}
  1681.     // {{{ getPrompt(key)
  1682.  
  1683.     /**
  1684.      * Get the short documentation for a config value.
  1685.      *
  1686.      * @param string  config key
  1687.      *
  1688.      * @return string short documentation string
  1689.      *
  1690.      * @access public
  1691.      *
  1692.      */
  1693.     function getPrompt($key)
  1694.     {
  1695.         if (isset($this->configuration_info[$key])) {
  1696.             return $this->configuration_info[$key]['prompt'];
  1697.         }
  1698.         return false;
  1699.     }
  1700.     // }}}
  1701.     // {{{ getGroup(key)
  1702.  
  1703.     /**
  1704.      * Get the parameter group for a config key.
  1705.      *
  1706.      * @param string  config key
  1707.      *
  1708.      * @return string parameter group
  1709.      *
  1710.      * @access public
  1711.      *
  1712.      */
  1713.     function getGroup($key)
  1714.     {
  1715.         if (isset($this->configuration_info[$key])) {
  1716.             return $this->configuration_info[$key]['group'];
  1717.         }
  1718.         return false;
  1719.     }
  1720.  
  1721.     // }}}
  1722.     // {{{ getGroups()
  1723.  
  1724.     /**
  1725.      * Get the list of parameter groups.
  1726.      *
  1727.      * @return array list of parameter groups
  1728.      *
  1729.      * @access public
  1730.      *
  1731.      */
  1732.     function getGroups()
  1733.     {
  1734.         $tmp = array();
  1735.         foreach ($this->configuration_info as $key => $info) {
  1736.             $tmp[$info['group']] = 1;
  1737.         }
  1738.         return array_keys($tmp);
  1739.     }
  1740.  
  1741.     // }}}
  1742.     // {{{ getGroupKeys()
  1743.  
  1744.     /**
  1745.      * Get the list of the parameters in a group.
  1746.      *
  1747.      * @param string $group parameter group
  1748.      *
  1749.      * @return array list of parameters in $group
  1750.      *
  1751.      * @access public
  1752.      *
  1753.      */
  1754.     function getGroupKeys($group)
  1755.     {
  1756.         $keys = array();
  1757.         foreach ($this->configuration_info as $key => $info) {
  1758.             if ($info['group'] == $group) {
  1759.                 $keys[] = $key;
  1760.             }
  1761.         }
  1762.         return $keys;
  1763.     }
  1764.  
  1765.     // }}}
  1766.     // {{{ getSetValues(key)
  1767.  
  1768.     /**
  1769.      * Get the list of allowed set values for a config value.  Returns
  1770.      * NULL for config values that are not sets.
  1771.      *
  1772.      * @param string  config key
  1773.      *
  1774.      * @return array enumerated array of set values, or NULL if the
  1775.      *               config key is unknown or not a set
  1776.      *
  1777.      * @access public
  1778.      *
  1779.      */
  1780.     function getSetValues($key)
  1781.     {
  1782.         if (isset($this->configuration_info[$key]) &&
  1783.             isset($this->configuration_info[$key]['type']) &&
  1784.             $this->configuration_info[$key]['type'] == 'set')
  1785.         {
  1786.             $valid_set = $this->configuration_info[$key]['valid_set'];
  1787.             reset($valid_set);
  1788.             if (key($valid_set) === 0) {
  1789.                 return $valid_set;
  1790.             }
  1791.             return array_keys($valid_set);
  1792.         }
  1793.         return null;
  1794.     }
  1795.  
  1796.     // }}}
  1797.     // {{{ getKeys()
  1798.  
  1799.     /**
  1800.      * Get all the current config keys.
  1801.      *
  1802.      * @return array simple array of config keys
  1803.      *
  1804.      * @access public
  1805.      */
  1806.     function getKeys()
  1807.     {
  1808.         $keys = array();
  1809.         foreach ($this->layers as $layer) {
  1810.             $test = $this->configuration[$layer];
  1811.             if (isset($test['__channels'])) {
  1812.                 foreach ($test['__channels'] as $channel => $configs) {
  1813.                     $keys = array_merge($keys, $configs);
  1814.                 }
  1815.             }
  1816.             unset($test['__channels']);
  1817.             $keys = array_merge($keys, $test);
  1818.         }
  1819.         return array_keys($keys);
  1820.     }
  1821.  
  1822.     // }}}
  1823.     // {{{ remove(key, [layer])
  1824.  
  1825.     /**
  1826.      * Remove the a config key from a specific config layer.
  1827.      *
  1828.      * @param string config key
  1829.      *
  1830.      * @param string (optional) config layer
  1831.      *
  1832.      * @return bool TRUE on success, FALSE on failure
  1833.      *
  1834.      * @access public
  1835.      */
  1836.     function remove($key, $layer = 'user')
  1837.     {
  1838.         $channel = $this->getDefaultChannel();
  1839.         if ($channel !== 'pear.php.net') {
  1840.             if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
  1841.                 unset($this->configuration[$layer]['__channels'][$channel][$key]);
  1842.                 return true;
  1843.             }
  1844.         }
  1845.         if (isset($this->configuration[$layer][$key])) {
  1846.             unset($this->configuration[$layer][$key]);
  1847.             return true;
  1848.         }
  1849.         return false;
  1850.     }
  1851.  
  1852.     // }}}
  1853.     // {{{ removeLayer(layer)
  1854.  
  1855.     /**
  1856.      * Temporarily remove an entire config layer.  USE WITH CARE!
  1857.      *
  1858.      * @param string config key
  1859.      *
  1860.      * @param string (optional) config layer
  1861.      *
  1862.      * @return bool TRUE on success, FALSE on failure
  1863.      *
  1864.      * @access public
  1865.      */
  1866.     function removeLayer($layer)
  1867.     {
  1868.         if (isset($this->configuration[$layer])) {
  1869.             $this->configuration[$layer] = array();
  1870.             return true;
  1871.         }
  1872.         return false;
  1873.     }
  1874.  
  1875.     // }}}
  1876.     // {{{ store([layer])
  1877.  
  1878.     /**
  1879.      * Stores configuration data in a layer.
  1880.      *
  1881.      * @param string config layer to store
  1882.      *
  1883.      * @return bool TRUE on success, or PEAR error on failure
  1884.      *
  1885.      * @access public
  1886.      */
  1887.     function store($layer = 'user', $data = null)
  1888.     {
  1889.         return $this->writeConfigFile(null, $layer, $data);
  1890.     }
  1891.  
  1892.     // }}}
  1893.     // {{{ toDefault(key)
  1894.  
  1895.     /**
  1896.      * Unset the user-defined value of a config key, reverting the
  1897.      * value to the system-defined one.
  1898.      *
  1899.      * @param string config key
  1900.      *
  1901.      * @return bool TRUE on success, FALSE on failure
  1902.      *
  1903.      * @access public
  1904.      */
  1905.     function toDefault($key)
  1906.     {
  1907.         trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE);
  1908.         return $this->remove($key, 'user');
  1909.     }
  1910.  
  1911.     // }}}
  1912.     // {{{ definedBy(key)
  1913.  
  1914.     /**
  1915.      * Tells what config layer that gets to define a key.
  1916.      *
  1917.      * @param string config key
  1918.      * @param boolean return the defining channel
  1919.      *
  1920.      * @return string|array the config layer, or an empty string if not found.
  1921.      *
  1922.      *         if $returnchannel, the return is an array array('layer' => layername,
  1923.      *         'channel' => channelname), or an empty string if not found
  1924.      *
  1925.      * @access public
  1926.      */
  1927.     function definedBy($key, $returnchannel = false)
  1928.     {
  1929.         foreach ($this->layers as $layer) {
  1930.             $channel = $this->getDefaultChannel();
  1931.             if ($channel !== 'pear.php.net') {
  1932.                 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
  1933.                     if ($returnchannel) {
  1934.                         return array('layer' => $layer, 'channel' => $channel);
  1935.                     }
  1936.                     return $layer;
  1937.                 }
  1938.             }
  1939.             if (isset($this->configuration[$layer][$key])) {
  1940.                 if ($returnchannel) {
  1941.                     return array('layer' => $layer, 'channel' => 'pear.php.net');
  1942.                 }
  1943.                 return $layer;
  1944.             }
  1945.         }
  1946.         return '';
  1947.     }
  1948.  
  1949.     // }}}
  1950.     // {{{ isDefaulted(key)
  1951.  
  1952.     /**
  1953.      * Tells whether a config value has a system-defined value.
  1954.      *
  1955.      * @param string   config key
  1956.      *
  1957.      * @return bool
  1958.      *
  1959.      * @access public
  1960.      *
  1961.      * @deprecated
  1962.      */
  1963.     function isDefaulted($key)
  1964.     {
  1965.         trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE);
  1966.         return $this->definedBy($key) == 'system';
  1967.     }
  1968.  
  1969.     // }}}
  1970.     // {{{ isDefined(key)
  1971.  
  1972.     /**
  1973.      * Tells whether a given key exists as a config value.
  1974.      *
  1975.      * @param string config key
  1976.      *
  1977.      * @return bool whether <config key> exists in this object
  1978.      *
  1979.      * @access public
  1980.      */
  1981.     function isDefined($key)
  1982.     {
  1983.         foreach ($this->layers as $layer) {
  1984.             if (isset($this->configuration[$layer][$key])) {
  1985.                 return true;
  1986.             }
  1987.         }
  1988.         return false;
  1989.     }
  1990.  
  1991.     // }}}
  1992.     // {{{ isDefinedLayer(key)
  1993.  
  1994.     /**
  1995.      * Tells whether a given config layer exists.
  1996.      *
  1997.      * @param string config layer
  1998.      *
  1999.      * @return bool whether <config layer> exists in this object
  2000.      *
  2001.      * @access public
  2002.      */
  2003.     function isDefinedLayer($layer)
  2004.     {
  2005.         return isset($this->configuration[$layer]);
  2006.     }
  2007.  
  2008.     // }}}
  2009.     // {{{ getLayers()
  2010.  
  2011.     /**
  2012.      * Returns the layers defined (except the 'default' one)
  2013.      *
  2014.      * @return array of the defined layers
  2015.      */
  2016.     function getLayers()
  2017.     {
  2018.         $cf = $this->configuration;
  2019.         unset($cf['default']);
  2020.         return array_keys($cf);
  2021.     }
  2022.  
  2023.     // }}}
  2024.     // {{{ apiVersion()
  2025.     function apiVersion()
  2026.     {
  2027.         return '1.1';
  2028.     }
  2029.     // }}}
  2030.  
  2031.     /**
  2032.      * @return PEAR_Registry
  2033.      */
  2034.     function &getRegistry($use = null)
  2035.     {
  2036.         if ($use === null) {
  2037.             $layer = 'user';
  2038.         } else {
  2039.             $layer = $use;
  2040.         }
  2041.         if (isset($this->_registry[$layer])) {
  2042.             return $this->_registry[$layer];
  2043.         } elseif ($use === null && isset($this->_registry['system'])) {
  2044.             return $this->_registry['system'];
  2045.         } elseif ($use === null && isset($this->_registry['default'])) {
  2046.             return $this->_registry['default'];
  2047.         } elseif ($use) {
  2048.             $a = false;
  2049.             return $a;
  2050.         } else {
  2051.             // only go here if null was passed in
  2052.             echo "CRITICAL ERROR: Registry could not be initialized from any value";
  2053.             exit(1);
  2054.         }
  2055.     }
  2056.     /**
  2057.      * This is to allow customization like the use of installroot
  2058.      * @param PEAR_Registry
  2059.      * @return bool
  2060.      */
  2061.     function setRegistry(&$reg, $layer = 'user')
  2062.     {
  2063.         if ($this->_noRegistry) {
  2064.             return false;
  2065.         }
  2066.         if (!in_array($layer, array('user', 'system'))) {
  2067.             return false;
  2068.         }
  2069.         $this->_registry[$layer] = &$reg;
  2070.         if (is_object($reg)) {
  2071.             $this->_registry[$layer]->setConfig($this);
  2072.         }
  2073.         return true;
  2074.     }
  2075.  
  2076.     function noRegistry()
  2077.     {
  2078.         $this->_noRegistry = true;
  2079.     }
  2080.  
  2081.     /**
  2082.      * @return PEAR_Remote
  2083.      */
  2084.     function &getRemote()
  2085.     {
  2086.         $remote = &new PEAR_Remote($this);
  2087.         return $remote;
  2088.     }
  2089.  
  2090.     /**
  2091.      * @return PEAR_REST
  2092.      */
  2093.     function &getREST($version, $options = array())
  2094.     {
  2095.         $version = str_replace('.', '', $version);
  2096.         if (!class_exists($class = 'PEAR_REST_' . $version)) {
  2097.             require_once 'PEAR/REST/' . $version . '.php';
  2098.         }
  2099.         $remote = &new $class($this, $options);
  2100.         return $remote;
  2101.     }
  2102.  
  2103.     /**
  2104.      * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
  2105.      * remote configuration file has been specified
  2106.      * @return PEAR_FTP|false
  2107.      */
  2108.     function &getFTP()
  2109.     {
  2110.         if (isset($this->_ftp)) {
  2111.             return $this->_ftp;
  2112.         } else {
  2113.             $a = false;
  2114.             return $a;
  2115.         }
  2116.     }
  2117.  
  2118.     // {{{ _prependPath($path, $prepend)
  2119.  
  2120.     function _prependPath($path, $prepend)
  2121.     {
  2122.         if (strlen($prepend) > 0) {
  2123.             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
  2124.                 if (preg_match('/^[a-z]:/i', $prepend)) {
  2125.                     $prepend = substr($prepend, 2);
  2126.                 } elseif ($prepend{0} != '\\') {
  2127.                     $prepend = "\\$prepend";
  2128.                 }
  2129.                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
  2130.             } else {
  2131.                 $path = $prepend . $path;
  2132.             }
  2133.         }
  2134.         return $path;
  2135.     }
  2136.     // }}}
  2137.  
  2138.     /**
  2139.      * @param string|false installation directory to prepend to all _dir variables, or false to
  2140.      *                     disable
  2141.      */
  2142.     function setInstallRoot($root)
  2143.     {
  2144.         if (substr($root, -1) == DIRECTORY_SEPARATOR) {
  2145.             $root = substr($root, 0, -1);
  2146.         }
  2147.         $old = $this->_installRoot;
  2148.         $this->_installRoot = $root;
  2149.         if (($old != $root) && !$this->_noRegistry) {
  2150.             foreach (array_keys($this->_registry) as $layer) {
  2151.                 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
  2152.                     continue;
  2153.                 }
  2154.                 $this->_registry[$layer] =
  2155.                     &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
  2156.                 $this->_registry[$layer]->setConfig($this);
  2157.                 $this->_regInitialized[$layer] = false;
  2158.             }
  2159.         }
  2160.     }
  2161. }
  2162.  
  2163. ?>
  2164.