Хранилища Subversion ant

Редакция

Содержимое файла | Последнее изменение | Открыть журнал | RSS

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