~ubuntu-branches/ubuntu/hardy/php5/hardy-updates

« back to all changes in this revision

Viewing changes to pear/PEAR/Config.php

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-10-09 03:14:32 UTC
  • Revision ID: james.westby@ubuntu.com-20051009031432-kspik3lobxstafv9
Tags: upstream-5.0.5
ImportĀ upstreamĀ versionĀ 5.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
//
 
3
// +----------------------------------------------------------------------+
 
4
// | PHP Version 5                                                        |
 
5
// +----------------------------------------------------------------------+
 
6
// | Copyright (c) 1997-2004 The PHP Group                                |
 
7
// +----------------------------------------------------------------------+
 
8
// | This source file is subject to version 3.0 of the PHP license,       |
 
9
// | that is bundled with this package in the file LICENSE, and is        |
 
10
// | available through the world-wide-web at the following url:           |
 
11
// | http://www.php.net/license/3_0.txt.                                  |
 
12
// | If you did not receive a copy of the PHP license and are unable to   |
 
13
// | obtain it through the world-wide-web, please send a note to          |
 
14
// | license@php.net so we can mail you a copy immediately.               |
 
15
// +----------------------------------------------------------------------+
 
16
// | Author: Stig Bakken <ssb@php.net>                                    |
 
17
// +----------------------------------------------------------------------+
 
18
//
 
19
// $Id: Config.php,v 1.52 2004/01/08 17:33:12 sniper Exp $
 
20
 
 
21
require_once 'PEAR.php';
 
22
require_once 'System.php';
 
23
 
 
24
/**
 
25
 * Last created PEAR_Config instance.
 
26
 * @var object
 
27
 */
 
28
$GLOBALS['_PEAR_Config_instance'] = null;
 
29
if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
 
30
    $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
 
31
} else {
 
32
    $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
 
33
}
 
34
 
 
35
// Below we define constants with default values for all configuration
 
36
// parameters except username/password.  All of them can have their
 
37
// defaults set through environment variables.  The reason we use the
 
38
// PHP_ prefix is for some security, PHP protects environment
 
39
// variables starting with PHP_*.
 
40
 
 
41
if (getenv('PHP_PEAR_SYSCONF_DIR')) {
 
42
    define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
 
43
} elseif (getenv('SystemRoot')) {
 
44
    define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
 
45
} else {
 
46
    define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
 
47
}
 
48
 
 
49
// Default for master_server
 
50
if (getenv('PHP_PEAR_MASTER_SERVER')) {
 
51
    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
 
52
} else {
 
53
    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
 
54
}
 
55
 
 
56
// Default for http_proxy
 
57
if (getenv('PHP_PEAR_HTTP_PROXY')) {
 
58
    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
 
59
} elseif (getenv('http_proxy')) {
 
60
    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
 
61
} else {
 
62
    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
 
63
}
 
64
 
 
65
// Default for php_dir
 
66
if (getenv('PHP_PEAR_INSTALL_DIR')) {
 
67
    define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
 
68
} else {
 
69
    if (@is_dir($PEAR_INSTALL_DIR)) {
 
70
        define('PEAR_CONFIG_DEFAULT_PHP_DIR',
 
71
               $PEAR_INSTALL_DIR);
 
72
    } else {
 
73
        define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
 
74
    }
 
75
}
 
76
 
 
77
// Default for ext_dir
 
78
if (getenv('PHP_PEAR_EXTENSION_DIR')) {
 
79
    define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
 
80
} else {
 
81
    if (ini_get('extension_dir')) {
 
82
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
 
83
    } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) {
 
84
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
 
85
    } elseif (defined('PHP_EXTENSION_DIR')) {
 
86
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
 
87
    } else {
 
88
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
 
89
    }
 
90
}
 
91
 
 
92
// Default for doc_dir
 
93
if (getenv('PHP_PEAR_DOC_DIR')) {
 
94
    define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
 
95
} else {
 
96
    define('PEAR_CONFIG_DEFAULT_DOC_DIR',
 
97
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
 
98
}
 
99
 
 
100
// Default for bin_dir
 
101
if (getenv('PHP_PEAR_BIN_DIR')) {
 
102
    define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
 
103
} else {
 
104
    define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
 
105
}
 
106
 
 
107
// Default for data_dir
 
108
if (getenv('PHP_PEAR_DATA_DIR')) {
 
109
    define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
 
110
} else {
 
111
    define('PEAR_CONFIG_DEFAULT_DATA_DIR',
 
112
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
 
113
}
 
114
 
 
115
// Default for test_dir
 
116
if (getenv('PHP_PEAR_TEST_DIR')) {
 
117
    define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
 
118
} else {
 
119
    define('PEAR_CONFIG_DEFAULT_TEST_DIR',
 
120
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
 
121
}
 
122
 
 
123
// Default for cache_dir
 
124
if (getenv('PHP_PEAR_CACHE_DIR')) {
 
125
    define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
 
126
} else {
 
127
    define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
 
128
           System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
 
129
           DIRECTORY_SEPARATOR . 'cache');
 
130
}
 
131
 
 
132
// Default for php_bin
 
133
if (getenv('PHP_PEAR_PHP_BIN')) {
 
134
    define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
 
135
} else {
 
136
    define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
 
137
           DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
 
138
}
 
139
 
 
140
// Default for verbose
 
141
if (getenv('PHP_PEAR_VERBOSE')) {
 
142
    define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
 
143
} else {
 
144
    define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
 
145
}
 
146
 
 
147
// Default for preferred_state
 
148
if (getenv('PHP_PEAR_PREFERRED_STATE')) {
 
149
    define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
 
150
} else {
 
151
    define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
 
152
}
 
153
 
 
154
// Default for umask
 
155
if (getenv('PHP_PEAR_UMASK')) {
 
156
    define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
 
157
} else {
 
158
    define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
 
159
}
 
160
 
 
161
// Default for cache_ttl
 
162
if (getenv('PHP_PEAR_CACHE_TTL')) {
 
163
    define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
 
164
} else {
 
165
    define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
 
166
}
 
167
 
 
168
// Default for sig_type
 
169
if (getenv('PHP_PEAR_SIG_TYPE')) {
 
170
    define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
 
171
} else {
 
172
    define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
 
173
}
 
174
 
 
175
// Default for sig_bin
 
176
if (getenv('PHP_PEAR_SIG_BIN')) {
 
177
    define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
 
178
} else {
 
179
    define('PEAR_CONFIG_DEFAULT_SIG_BIN',
 
180
           System::which(
 
181
               'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
 
182
}
 
183
 
 
184
// Default for sig_keydir
 
185
if (getenv('PHP_PEAR_SIG_KEYDIR')) {
 
186
    define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
 
187
} else {
 
188
    define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
 
189
           PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
 
190
}
 
191
 
 
192
/**
 
193
 * This is a class for storing configuration data, keeping track of
 
194
 * which are system-defined, user-defined or defaulted.
 
195
 */
 
196
class PEAR_Config extends PEAR
 
197
{
 
198
    // {{{ properties
 
199
 
 
200
    /**
 
201
     * Array of config files used.
 
202
     *
 
203
     * @var array layer => config file
 
204
     */
 
205
    var $files = array(
 
206
        'system' => '',
 
207
        'user' => '',
 
208
        );
 
209
 
 
210
    var $layers = array();
 
211
 
 
212
    /**
 
213
     * Configuration data, two-dimensional array where the first
 
214
     * dimension is the config layer ('user', 'system' and 'default'),
 
215
     * and the second dimension is keyname => value.
 
216
     *
 
217
     * The order in the first dimension is important!  Earlier
 
218
     * layers will shadow later ones when a config value is
 
219
     * requested (if a 'user' value exists, it will be returned first,
 
220
     * then 'system' and finally 'default').
 
221
     *
 
222
     * @var array layer => array(keyname => value, ...)
 
223
     */
 
224
    var $configuration = array(
 
225
        'user' => array(),
 
226
        'system' => array(),
 
227
        'default' => array(),
 
228
        );
 
229
 
 
230
    /**
 
231
     * Information about the configuration data.  Stores the type,
 
232
     * default value and a documentation string for each configuration
 
233
     * value.
 
234
     *
 
235
     * @var array layer => array(infotype => value, ...)
 
236
     */
 
237
    var $configuration_info = array(
 
238
        // Internet Access
 
239
        'master_server' => array(
 
240
            'type' => 'string',
 
241
            'default' => 'pear.php.net',
 
242
            'doc' => 'name of the main PEAR server',
 
243
            'prompt' => 'PEAR server',
 
244
            'group' => 'Internet Access',
 
245
            ),
 
246
        'http_proxy' => array(
 
247
            'type' => 'string',
 
248
            'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
 
249
            'doc' => 'HTTP proxy (host:port) to use when downloading packages',
 
250
            'prompt' => 'HTTP Proxy Server Address',
 
251
            'group' => 'Internet Access',
 
252
            ),
 
253
        // File Locations
 
254
        'php_dir' => array(
 
255
            'type' => 'directory',
 
256
            'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
 
257
            'doc' => 'directory where .php files are installed',
 
258
            'prompt' => 'PEAR directory',
 
259
            'group' => 'File Locations',
 
260
            ),
 
261
        'ext_dir' => array(
 
262
            'type' => 'directory',
 
263
            'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
 
264
            'doc' => 'directory where loadable extensions are installed',
 
265
            'prompt' => 'PHP extension directory',
 
266
            'group' => 'File Locations',
 
267
            ),
 
268
        'doc_dir' => array(
 
269
            'type' => 'directory',
 
270
            'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
 
271
            'doc' => 'directory where documentation is installed',
 
272
            'prompt' => 'PEAR documentation directory',
 
273
            'group' => 'File Locations',
 
274
            ),
 
275
        'bin_dir' => array(
 
276
            'type' => 'directory',
 
277
            'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
 
278
            'doc' => 'directory where executables are installed',
 
279
            'prompt' => 'PEAR executables directory',
 
280
            'group' => 'File Locations',
 
281
            ),
 
282
        'data_dir' => array(
 
283
            'type' => 'directory',
 
284
            'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
 
285
            'doc' => 'directory where data files are installed',
 
286
            'prompt' => 'PEAR data directory',
 
287
            'group' => 'File Locations (Advanced)',
 
288
            ),
 
289
        'test_dir' => array(
 
290
            'type' => 'directory',
 
291
            'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
 
292
            'doc' => 'directory where regression tests are installed',
 
293
            'prompt' => 'PEAR test directory',
 
294
            'group' => 'File Locations (Advanced)',
 
295
            ),
 
296
        'cache_dir' => array(
 
297
            'type' => 'directory',
 
298
            'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
 
299
            'doc' => 'directory which is used for XMLRPC cache',
 
300
            'prompt' => 'PEAR Installer cache directory',
 
301
            'group' => 'File Locations (Advanced)',
 
302
            ),
 
303
        'php_bin' => array(
 
304
            'type' => 'file',
 
305
            'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
 
306
            'doc' => 'PHP CLI/CGI binary for executing scripts',
 
307
            'prompt' => 'PHP CLI/CGI binary',
 
308
            'group' => 'File Locations (Advanced)',
 
309
            ),
 
310
        // Maintainers
 
311
        'username' => array(
 
312
            'type' => 'string',
 
313
            'default' => '',
 
314
            'doc' => '(maintainers) your PEAR account name',
 
315
            'prompt' => 'PEAR username (for maintainers)',
 
316
            'group' => 'Maintainers',
 
317
            ),
 
318
        'password' => array(
 
319
            'type' => 'password',
 
320
            'default' => '',
 
321
            'doc' => '(maintainers) your PEAR account password',
 
322
            'prompt' => 'PEAR password (for maintainers)',
 
323
            'group' => 'Maintainers',
 
324
            ),
 
325
        // Advanced
 
326
        'verbose' => array(
 
327
            'type' => 'integer',
 
328
            'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
 
329
            'doc' => 'verbosity level
 
330
0: really quiet
 
331
1: somewhat quiet
 
332
2: verbose
 
333
3: debug',
 
334
            'prompt' => 'Debug Log Level',
 
335
            'group' => 'Advanced',
 
336
            ),
 
337
        'preferred_state' => array(
 
338
            'type' => 'set',
 
339
            'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
 
340
            'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
 
341
            'valid_set' => array(
 
342
                'stable', 'beta', 'alpha', 'devel', 'snapshot'),
 
343
            'prompt' => 'Preferred Package State',
 
344
            'group' => 'Advanced',
 
345
            ),
 
346
        'umask' => array(
 
347
            'type' => 'mask',
 
348
            'default' => PEAR_CONFIG_DEFAULT_UMASK,
 
349
            'doc' => 'umask used when creating files (Unix-like systems only)',
 
350
            'prompt' => 'Unix file mask',
 
351
            'group' => 'Advanced',
 
352
            ),
 
353
        'cache_ttl' => array(
 
354
            'type' => 'integer',
 
355
            'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
 
356
            'doc' => 'amount of secs where the local cache is used and not updated',
 
357
            'prompt' => 'Cache TimeToLive',
 
358
            'group' => 'Advanced',
 
359
            ),
 
360
        'sig_type' => array(
 
361
            'type' => 'set',
 
362
            'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
 
363
            'doc' => 'which package signature mechanism to use',
 
364
            'valid_set' => array('gpg'),
 
365
            'prompt' => 'Package Signature Type',
 
366
            'group' => 'Maintainers',
 
367
            ),
 
368
        'sig_bin' => array(
 
369
            'type' => 'string',
 
370
            'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
 
371
            'doc' => 'which package signature mechanism to use',
 
372
            'prompt' => 'Signature Handling Program',
 
373
            'group' => 'Maintainers',
 
374
            ),
 
375
        'sig_keyid' => array(
 
376
            'type' => 'string',
 
377
            'default' => '',
 
378
            'doc' => 'which key to use for signing with',
 
379
            'prompt' => 'Signature Key Id',
 
380
            'group' => 'Maintainers',
 
381
            ),
 
382
        'sig_keydir' => array(
 
383
            'type' => 'string',
 
384
            'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
 
385
            'doc' => 'which package signature mechanism to use',
 
386
            'prompt' => 'Signature Key Directory',
 
387
            'group' => 'Maintainers',
 
388
            ),
 
389
        );
 
390
 
 
391
    // }}}
 
392
 
 
393
    // {{{ PEAR_Config([file], [defaults_file])
 
394
 
 
395
    /**
 
396
     * Constructor.
 
397
     *
 
398
     * @param string (optional) file to read user-defined options from
 
399
     * @param string (optional) file to read system-wide defaults from
 
400
     *
 
401
     * @access public
 
402
     *
 
403
     * @see PEAR_Config::singleton
 
404
     */
 
405
    function PEAR_Config($user_file = '', $system_file = '')
 
406
    {
 
407
        $this->PEAR();
 
408
        $sl = DIRECTORY_SEPARATOR;
 
409
        if (empty($user_file)) {
 
410
            if (OS_WINDOWS) {
 
411
                $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
 
412
            } else {
 
413
                $user_file = getenv('HOME') . $sl . '.pearrc';
 
414
            }
 
415
        }
 
416
        if (empty($system_file)) {
 
417
            if (OS_WINDOWS) {
 
418
                $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';
 
419
            } else {
 
420
                $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';
 
421
            }
 
422
        }
 
423
        $this->layers = array_keys($this->configuration);
 
424
        $this->files['user'] = $user_file;
 
425
        $this->files['system'] = $system_file;
 
426
        if ($user_file && file_exists($user_file)) {
 
427
            $this->readConfigFile($user_file);
 
428
        }
 
429
        if ($system_file && file_exists($system_file)) {
 
430
            $this->mergeConfigFile($system_file, false, 'system');
 
431
        }
 
432
        foreach ($this->configuration_info as $key => $info) {
 
433
            $this->configuration['default'][$key] = $info['default'];
 
434
        }
 
435
        //$GLOBALS['_PEAR_Config_instance'] = &$this;
 
436
    }
 
437
 
 
438
    // }}}
 
439
    // {{{ singleton([file], [defaults_file])
 
440
 
 
441
    /**
 
442
     * Static singleton method.  If you want to keep only one instance
 
443
     * of this class in use, this method will give you a reference to
 
444
     * the last created PEAR_Config object if one exists, or create a
 
445
     * new object.
 
446
     *
 
447
     * @param string (optional) file to read user-defined options from
 
448
     * @param string (optional) file to read system-wide defaults from
 
449
     *
 
450
     * @return object an existing or new PEAR_Config instance
 
451
     *
 
452
     * @access public
 
453
     *
 
454
     * @see PEAR_Config::PEAR_Config
 
455
     */
 
456
    function &singleton($user_file = '', $system_file = '')
 
457
    {
 
458
        if (is_object($GLOBALS['_PEAR_Config_instance'])) {
 
459
            return $GLOBALS['_PEAR_Config_instance'];
 
460
        }
 
461
        $GLOBALS['_PEAR_Config_instance'] =
 
462
             &new PEAR_Config($user_file, $system_file);
 
463
        return $GLOBALS['_PEAR_Config_instance'];
 
464
    }
 
465
 
 
466
    // }}}
 
467
    // {{{ readConfigFile([file], [layer])
 
468
 
 
469
    /**
 
470
     * Reads configuration data from a file.  All existing values in
 
471
     * the config layer are discarded and replaced with data from the
 
472
     * file.
 
473
     *
 
474
     * @param string (optional) file to read from, if NULL or not
 
475
     * specified, the last-used file for the same layer (second param)
 
476
     * is used
 
477
     *
 
478
     * @param string (optional) config layer to insert data into
 
479
     * ('user' or 'system')
 
480
     *
 
481
     * @return bool TRUE on success or a PEAR error on failure
 
482
     *
 
483
     * @access public
 
484
     */
 
485
    function readConfigFile($file = null, $layer = 'user')
 
486
    {
 
487
        if (empty($this->files[$layer])) {
 
488
            return $this->raiseError("unknown config file type `$layer'");
 
489
        }
 
490
        if ($file === null) {
 
491
            $file = $this->files[$layer];
 
492
        }
 
493
        $data = $this->_readConfigDataFrom($file);
 
494
        if (PEAR::isError($data)) {
 
495
            return $data;
 
496
        }
 
497
        $this->_decodeInput($data);
 
498
        $this->configuration[$layer] = $data;
 
499
        return true;
 
500
    }
 
501
 
 
502
    // }}}
 
503
    // {{{ mergeConfigFile(file, [override], [layer])
 
504
 
 
505
    /**
 
506
     * Merges data into a config layer from a file.  Does the same
 
507
     * thing as readConfigFile, except it does not replace all
 
508
     * existing values in the config layer.
 
509
     *
 
510
     * @param string file to read from
 
511
     *
 
512
     * @param bool (optional) whether to overwrite existing data
 
513
     * (default TRUE)
 
514
     *
 
515
     * @param string config layer to insert data into ('user' or
 
516
     * 'system')
 
517
     *
 
518
     * @return bool TRUE on success or a PEAR error on failure
 
519
     *
 
520
     * @access public.
 
521
     */
 
522
    function mergeConfigFile($file, $override = true, $layer = 'user')
 
523
    {
 
524
        if (empty($this->files[$layer])) {
 
525
            return $this->raiseError("unknown config file type `$layer'");
 
526
        }
 
527
        if ($file === null) {
 
528
            $file = $this->files[$layer];
 
529
        }
 
530
        $data = $this->_readConfigDataFrom($file);
 
531
        if (PEAR::isError($data)) {
 
532
            return $data;
 
533
        }
 
534
        $this->_decodeInput($data);
 
535
        if ($override) {
 
536
            $this->configuration[$layer] = array_merge($this->configuration[$layer], $data);
 
537
        } else {
 
538
            $this->configuration[$layer] = array_merge($data, $this->configuration[$layer]);
 
539
        }
 
540
        return true;
 
541
    }
 
542
 
 
543
    // }}}
 
544
    // {{{ writeConfigFile([file], [layer])
 
545
 
 
546
    /**
 
547
     * Writes data into a config layer from a file.
 
548
     *
 
549
     * @param string file to read from
 
550
     *
 
551
     * @param bool (optional) whether to overwrite existing data
 
552
     * (default TRUE)
 
553
     *
 
554
     * @param string config layer to insert data into ('user' or
 
555
     * 'system')
 
556
     *
 
557
     * @return bool TRUE on success or a PEAR error on failure
 
558
     *
 
559
     * @access public.
 
560
     */
 
561
    function writeConfigFile($file = null, $layer = 'user', $data = null)
 
562
    {
 
563
        if ($layer == 'both' || $layer == 'all') {
 
564
            foreach ($this->files as $type => $file) {
 
565
                $err = $this->writeConfigFile($file, $type, $data);
 
566
                if (PEAR::isError($err)) {
 
567
                    return $err;
 
568
                }
 
569
            }
 
570
            return true;
 
571
        }
 
572
        if (empty($this->files[$layer])) {
 
573
            return $this->raiseError("unknown config file type `$layer'");
 
574
        }
 
575
        if ($file === null) {
 
576
            $file = $this->files[$layer];
 
577
        }
 
578
        $data = ($data === null) ? $this->configuration[$layer] : $data;
 
579
        $this->_encodeOutput($data);
 
580
        $opt = array('-p', dirname($file));
 
581
        if (!@System::mkDir($opt)) {
 
582
            return $this->raiseError("could not create directory: " . dirname($file));
 
583
        }
 
584
        if (@is_file($file) && !@is_writeable($file)) {
 
585
            return $this->raiseError("no write access to $file!");
 
586
        }
 
587
        $fp = @fopen($file, "w");
 
588
        if (!$fp) {
 
589
            return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed");
 
590
        }
 
591
        $contents = "#PEAR_Config 0.9\n" . serialize($data);
 
592
        if (!@fwrite($fp, $contents)) {
 
593
            return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed");
 
594
        }
 
595
        return true;
 
596
    }
 
597
 
 
598
    // }}}
 
599
    // {{{ _readConfigDataFrom(file)
 
600
 
 
601
    /**
 
602
     * Reads configuration data from a file and returns the parsed data
 
603
     * in an array.
 
604
     *
 
605
     * @param string file to read from
 
606
     *
 
607
     * @return array configuration data or a PEAR error on failure
 
608
     *
 
609
     * @access private
 
610
     */
 
611
    function _readConfigDataFrom($file)
 
612
    {
 
613
        $fp = @fopen($file, "r");
 
614
        if (!$fp) {
 
615
            return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
 
616
        }
 
617
        $size = filesize($file);
 
618
        $rt = get_magic_quotes_runtime();
 
619
        set_magic_quotes_runtime(0);
 
620
        $contents = fread($fp, $size);
 
621
        set_magic_quotes_runtime($rt);
 
622
        fclose($fp);
 
623
        $version = '0.1';
 
624
        if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
 
625
            $version = $matches[1];
 
626
            $contents = substr($contents, strlen($matches[0]));
 
627
        }
 
628
        if (version_compare("$version", '1', '<')) {
 
629
            $data = unserialize($contents);
 
630
            if (!is_array($data)) {
 
631
                if (strlen(trim($contents)) > 0) {
 
632
                    $error = "PEAR_Config: bad data in $file";
 
633
//                if (isset($this)) {
 
634
                    return $this->raiseError($error);
 
635
//                } else {
 
636
//                    return PEAR::raiseError($error);
 
637
                } else {
 
638
                    $data = array();
 
639
                }
 
640
            }
 
641
        // add parsing of newer formats here...
 
642
        } else {
 
643
            return $this->raiseError("$file: unknown version `$version'");
 
644
        }
 
645
        return $data;
 
646
    }
 
647
 
 
648
    // }}}
 
649
    // {{{ getConfFile(layer)
 
650
    /**
 
651
    * Gets the file used for storing the config for a layer
 
652
    *
 
653
    * @param string $layer 'user' or 'system'
 
654
    */
 
655
 
 
656
    function getConfFile($layer)
 
657
    {
 
658
        return $this->files[$layer];
 
659
    }
 
660
 
 
661
    // }}}
 
662
    // {{{ _encodeOutput(&data)
 
663
 
 
664
    /**
 
665
     * Encodes/scrambles configuration data before writing to files.
 
666
     * Currently, 'password' values will be base64-encoded as to avoid
 
667
     * that people spot cleartext passwords by accident.
 
668
     *
 
669
     * @param array (reference) array to encode values in
 
670
     *
 
671
     * @return bool TRUE on success
 
672
     *
 
673
     * @access private
 
674
     */
 
675
    function _encodeOutput(&$data)
 
676
    {
 
677
        foreach ($data as $key => $value) {
 
678
            if (!isset($this->configuration_info[$key])) {
 
679
                continue;
 
680
            }
 
681
            $type = $this->configuration_info[$key]['type'];
 
682
            switch ($type) {
 
683
                // we base64-encode passwords so they are at least
 
684
                // not shown in plain by accident
 
685
                case 'password': {
 
686
                    $data[$key] = base64_encode($data[$key]);
 
687
                    break;
 
688
                }
 
689
                case 'mask': {
 
690
                    $data[$key] = octdec($data[$key]);
 
691
                    break;
 
692
                }
 
693
            }
 
694
        }
 
695
        return true;
 
696
    }
 
697
 
 
698
    // }}}
 
699
    // {{{ _decodeInput(&data)
 
700
 
 
701
    /**
 
702
     * Decodes/unscrambles configuration data after reading from files.
 
703
     *
 
704
     * @param array (reference) array to encode values in
 
705
     *
 
706
     * @return bool TRUE on success
 
707
     *
 
708
     * @access private
 
709
     *
 
710
     * @see PEAR_Config::_encodeOutput
 
711
     */
 
712
    function _decodeInput(&$data)
 
713
    {
 
714
        if (!is_array($data)) {
 
715
            return true;
 
716
        }
 
717
        foreach ($data as $key => $value) {
 
718
            if (!isset($this->configuration_info[$key])) {
 
719
                continue;
 
720
            }
 
721
            $type = $this->configuration_info[$key]['type'];
 
722
            switch ($type) {
 
723
                case 'password': {
 
724
                    $data[$key] = base64_decode($data[$key]);
 
725
                    break;
 
726
                }
 
727
                case 'mask': {
 
728
                    $data[$key] = decoct($data[$key]);
 
729
                    break;
 
730
                }
 
731
            }
 
732
        }
 
733
        return true;
 
734
    }
 
735
 
 
736
    // }}}
 
737
    // {{{ get(key, [layer])
 
738
 
 
739
    /**
 
740
     * Returns a configuration value, prioritizing layers as per the
 
741
     * layers property.
 
742
     *
 
743
     * @param string config key
 
744
     *
 
745
     * @return mixed the config value, or NULL if not found
 
746
     *
 
747
     * @access public
 
748
     */
 
749
    function get($key, $layer = null)
 
750
    {
 
751
        if ($layer === null) {
 
752
            foreach ($this->layers as $layer) {
 
753
                if (isset($this->configuration[$layer][$key])) {
 
754
                    return $this->configuration[$layer][$key];
 
755
                }
 
756
            }
 
757
        } elseif (isset($this->configuration[$layer][$key])) {
 
758
            return $this->configuration[$layer][$key];
 
759
        }
 
760
        return null;
 
761
    }
 
762
 
 
763
    // }}}
 
764
    // {{{ set(key, value, [layer])
 
765
 
 
766
    /**
 
767
     * Set a config value in a specific layer (defaults to 'user').
 
768
     * Enforces the types defined in the configuration_info array.  An
 
769
     * integer config variable will be cast to int, and a set config
 
770
     * variable will be validated against its legal values.
 
771
     *
 
772
     * @param string config key
 
773
     *
 
774
     * @param string config value
 
775
     *
 
776
     * @param string (optional) config layer
 
777
     *
 
778
     * @return bool TRUE on success, FALSE on failure
 
779
     *
 
780
     * @access public
 
781
     */
 
782
    function set($key, $value, $layer = 'user')
 
783
    {
 
784
        if (empty($this->configuration_info[$key])) {
 
785
            return false;
 
786
        }
 
787
        extract($this->configuration_info[$key]);
 
788
        switch ($type) {
 
789
            case 'integer':
 
790
                $value = (int)$value;
 
791
                break;
 
792
            case 'set': {
 
793
                // If a valid_set is specified, require the value to
 
794
                // be in the set.  If there is no valid_set, accept
 
795
                // any value.
 
796
                if ($valid_set) {
 
797
                    reset($valid_set);
 
798
                    if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
 
799
                        (key($valid_set) !== 0 && empty($valid_set[$value])))
 
800
                    {
 
801
                        return false;
 
802
                    }
 
803
                }
 
804
                break;
 
805
            }
 
806
        }
 
807
        $this->configuration[$layer][$key] = $value;
 
808
        return true;
 
809
    }
 
810
 
 
811
    // }}}
 
812
    // {{{ getType(key)
 
813
 
 
814
    /**
 
815
     * Get the type of a config value.
 
816
     *
 
817
     * @param string  config key
 
818
     *
 
819
     * @return string type, one of "string", "integer", "file",
 
820
     * "directory", "set" or "password".
 
821
     *
 
822
     * @access public
 
823
     *
 
824
     */
 
825
    function getType($key)
 
826
    {
 
827
        if (isset($this->configuration_info[$key])) {
 
828
            return $this->configuration_info[$key]['type'];
 
829
        }
 
830
        return false;
 
831
    }
 
832
 
 
833
    // }}}
 
834
    // {{{ getDocs(key)
 
835
 
 
836
    /**
 
837
     * Get the documentation for a config value.
 
838
     *
 
839
     * @param string  config key
 
840
     *
 
841
     * @return string documentation string
 
842
     *
 
843
     * @access public
 
844
     *
 
845
     */
 
846
    function getDocs($key)
 
847
    {
 
848
        if (isset($this->configuration_info[$key])) {
 
849
            return $this->configuration_info[$key]['doc'];
 
850
        }
 
851
        return false;
 
852
    }
 
853
       // }}}
 
854
    // {{{ getPrompt(key)
 
855
 
 
856
    /**
 
857
     * Get the short documentation for a config value.
 
858
     *
 
859
     * @param string  config key
 
860
     *
 
861
     * @return string short documentation string
 
862
     *
 
863
     * @access public
 
864
     *
 
865
     */
 
866
    function getPrompt($key)
 
867
    {
 
868
        if (isset($this->configuration_info[$key])) {
 
869
            return $this->configuration_info[$key]['prompt'];
 
870
        }
 
871
        return false;
 
872
    }
 
873
    // }}}
 
874
    // {{{ getGroup(key)
 
875
 
 
876
    /**
 
877
     * Get the parameter group for a config key.
 
878
     *
 
879
     * @param string  config key
 
880
     *
 
881
     * @return string parameter group
 
882
     *
 
883
     * @access public
 
884
     *
 
885
     */
 
886
    function getGroup($key)
 
887
    {
 
888
        if (isset($this->configuration_info[$key])) {
 
889
            return $this->configuration_info[$key]['group'];
 
890
        }
 
891
        return false;
 
892
    }
 
893
 
 
894
    // }}}
 
895
    // {{{ getGroups()
 
896
 
 
897
    /**
 
898
     * Get the list of parameter groups.
 
899
     *
 
900
     * @return array list of parameter groups
 
901
     *
 
902
     * @access public
 
903
     *
 
904
     */
 
905
    function getGroups()
 
906
    {
 
907
        $tmp = array();
 
908
        foreach ($this->configuration_info as $key => $info) {
 
909
            $tmp[$info['group']] = 1;
 
910
        }
 
911
        return array_keys($tmp);
 
912
    }
 
913
 
 
914
    // }}}
 
915
    // {{{ getGroupKeys()
 
916
 
 
917
    /**
 
918
     * Get the list of the parameters in a group.
 
919
     *
 
920
     * @param string $group parameter group
 
921
     *
 
922
     * @return array list of parameters in $group
 
923
     *
 
924
     * @access public
 
925
     *
 
926
     */
 
927
    function getGroupKeys($group)
 
928
    {
 
929
        $keys = array();
 
930
        foreach ($this->configuration_info as $key => $info) {
 
931
            if ($info['group'] == $group) {
 
932
                $keys[] = $key;
 
933
            }
 
934
        }
 
935
        return $keys;
 
936
    }
 
937
 
 
938
    // }}}
 
939
    // {{{ getSetValues(key)
 
940
 
 
941
    /**
 
942
     * Get the list of allowed set values for a config value.  Returns
 
943
     * NULL for config values that are not sets.
 
944
     *
 
945
     * @param string  config key
 
946
     *
 
947
     * @return array enumerated array of set values, or NULL if the
 
948
     *               config key is unknown or not a set
 
949
     *
 
950
     * @access public
 
951
     *
 
952
     */
 
953
    function getSetValues($key)
 
954
    {
 
955
        if (isset($this->configuration_info[$key]) &&
 
956
            isset($this->configuration_info[$key]['type']) &&
 
957
            $this->configuration_info[$key]['type'] == 'set')
 
958
        {
 
959
            $valid_set = $this->configuration_info[$key]['valid_set'];
 
960
            reset($valid_set);
 
961
            if (key($valid_set) === 0) {
 
962
                return $valid_set;
 
963
            }
 
964
            return array_keys($valid_set);
 
965
        }
 
966
        return false;
 
967
    }
 
968
 
 
969
    // }}}
 
970
    // {{{ getKeys()
 
971
 
 
972
    /**
 
973
     * Get all the current config keys.
 
974
     *
 
975
     * @return array simple array of config keys
 
976
     *
 
977
     * @access public
 
978
     */
 
979
    function getKeys()
 
980
    {
 
981
        $keys = array();
 
982
        foreach ($this->layers as $layer) {
 
983
            $keys = array_merge($keys, $this->configuration[$layer]);
 
984
        }
 
985
        return array_keys($keys);
 
986
    }
 
987
 
 
988
    // }}}
 
989
    // {{{ remove(key, [layer])
 
990
 
 
991
    /**
 
992
     * Remove the a config key from a specific config layer.
 
993
     *
 
994
     * @param string config key
 
995
     *
 
996
     * @param string (optional) config layer
 
997
     *
 
998
     * @return bool TRUE on success, FALSE on failure
 
999
     *
 
1000
     * @access public
 
1001
     */
 
1002
    function remove($key, $layer = 'user')
 
1003
    {
 
1004
        if (isset($this->configuration[$layer][$key])) {
 
1005
            unset($this->configuration[$layer][$key]);
 
1006
            return true;
 
1007
        }
 
1008
        return false;
 
1009
    }
 
1010
 
 
1011
    // }}}
 
1012
    // {{{ removeLayer(layer)
 
1013
 
 
1014
    /**
 
1015
     * Temporarily remove an entire config layer.  USE WITH CARE!
 
1016
     *
 
1017
     * @param string config key
 
1018
     *
 
1019
     * @param string (optional) config layer
 
1020
     *
 
1021
     * @return bool TRUE on success, FALSE on failure
 
1022
     *
 
1023
     * @access public
 
1024
     */
 
1025
    function removeLayer($layer)
 
1026
    {
 
1027
        if (isset($this->configuration[$layer])) {
 
1028
            $this->configuration[$layer] = array();
 
1029
            return true;
 
1030
        }
 
1031
        return false;
 
1032
    }
 
1033
 
 
1034
    // }}}
 
1035
    // {{{ store([layer])
 
1036
 
 
1037
    /**
 
1038
     * Stores configuration data in a layer.
 
1039
     *
 
1040
     * @param string config layer to store
 
1041
     *
 
1042
     * @return bool TRUE on success, or PEAR error on failure
 
1043
     *
 
1044
     * @access public
 
1045
     */
 
1046
    function store($layer = 'user', $data = null)
 
1047
    {
 
1048
        return $this->writeConfigFile(null, $layer, $data);
 
1049
    }
 
1050
 
 
1051
    // }}}
 
1052
    // {{{ toDefault(key)
 
1053
 
 
1054
    /**
 
1055
     * Unset the user-defined value of a config key, reverting the
 
1056
     * value to the system-defined one.
 
1057
     *
 
1058
     * @param string config key
 
1059
     *
 
1060
     * @return bool TRUE on success, FALSE on failure
 
1061
     *
 
1062
     * @access public
 
1063
     */
 
1064
    function toDefault($key)
 
1065
    {
 
1066
        trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE);
 
1067
        return $this->remove($key, 'user');
 
1068
    }
 
1069
 
 
1070
    // }}}
 
1071
    // {{{ definedBy(key)
 
1072
 
 
1073
    /**
 
1074
     * Tells what config layer that gets to define a key.
 
1075
     *
 
1076
     * @param string config key
 
1077
     *
 
1078
     * @return string the config layer, or an empty string if not found
 
1079
     *
 
1080
     * @access public
 
1081
     */
 
1082
    function definedBy($key)
 
1083
    {
 
1084
        foreach ($this->layers as $layer) {
 
1085
            if (isset($this->configuration[$layer][$key])) {
 
1086
                return $layer;
 
1087
            }
 
1088
        }
 
1089
        return '';
 
1090
    }
 
1091
 
 
1092
    // }}}
 
1093
    // {{{ isDefaulted(key)
 
1094
 
 
1095
    /**
 
1096
     * Tells whether a config value has a system-defined value.
 
1097
     *
 
1098
     * @param string   config key
 
1099
     *
 
1100
     * @return bool
 
1101
     *
 
1102
     * @access public
 
1103
     *
 
1104
     * @deprecated
 
1105
     */
 
1106
    function isDefaulted($key)
 
1107
    {
 
1108
        trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE);
 
1109
        return $this->definedBy($key) == 'system';
 
1110
    }
 
1111
 
 
1112
    // }}}
 
1113
    // {{{ isDefined(key)
 
1114
 
 
1115
    /**
 
1116
     * Tells whether a given key exists as a config value.
 
1117
     *
 
1118
     * @param string config key
 
1119
     *
 
1120
     * @return bool whether <config key> exists in this object
 
1121
     *
 
1122
     * @access public
 
1123
     */
 
1124
    function isDefined($key)
 
1125
    {
 
1126
        foreach ($this->layers as $layer) {
 
1127
            if (isset($this->configuration[$layer][$key])) {
 
1128
                return true;
 
1129
            }
 
1130
        }
 
1131
        return false;
 
1132
    }
 
1133
 
 
1134
    // }}}
 
1135
    // {{{ isDefinedLayer(key)
 
1136
 
 
1137
    /**
 
1138
     * Tells whether a given config layer exists.
 
1139
     *
 
1140
     * @param string config layer
 
1141
     *
 
1142
     * @return bool whether <config layer> exists in this object
 
1143
     *
 
1144
     * @access public
 
1145
     */
 
1146
    function isDefinedLayer($layer)
 
1147
    {
 
1148
        return isset($this->configuration[$layer]);
 
1149
    }
 
1150
 
 
1151
    // }}}
 
1152
    // {{{ getLayers()
 
1153
 
 
1154
    /**
 
1155
     * Returns the layers defined (except the 'default' one)
 
1156
     *
 
1157
     * @return array of the defined layers
 
1158
     */
 
1159
    function getLayers()
 
1160
    {
 
1161
        $cf = $this->configuration;
 
1162
        unset($cf['default']);
 
1163
        return array_keys($cf);
 
1164
    }
 
1165
 
 
1166
    // }}}
 
1167
}
 
1168
 
 
1169
?>