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