PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file Config.php

Documentation is available at Config.php

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

Documentation generated on Wed, 06 Jul 2011 23:30:38 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.