Completed
Push — master ( 72613d...069c91 )
by Michael
02:16
created

class/pear/PEAR.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * PEAR, the PHP Extension and Application Repository
4
 *
5
 * PEAR class and PEAR_Error class
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * @category   pear
10
 * @package    PEAR
11
 * @author     Sterling Hughes <[email protected]>
12
 * @author     Stig Bakken <[email protected]>
13
 * @author     Tomas V.V.Cox <[email protected]>
14
 * @author     Greg Beaver <[email protected]>
15
 * @copyright  1997-2010 The Authors
16
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
17
 * @link       http://pear.php.net/package/PEAR
18
 * @since      File available since Release 0.1
19
 */
20
21
/**#@+
22
 * ERROR constants
23
 */
24
define('PEAR_ERROR_RETURN', 1);
25
define('PEAR_ERROR_PRINT', 2);
26
define('PEAR_ERROR_TRIGGER', 4);
27
define('PEAR_ERROR_DIE', 8);
28
define('PEAR_ERROR_CALLBACK', 16);
29
/**
30
 * WARNING: obsolete
31
 * @deprecated
32
 */
33
define('PEAR_ERROR_EXCEPTION', 32);
34
/**#@-*/
35
36
if ('WIN' == substr(PHP_OS, 0, 3)) {
37
    define('OS_WINDOWS', true);
38
    define('OS_UNIX', false);
39
    define('PEAR_OS', 'Windows');
40
} else {
41
    define('OS_WINDOWS', false);
42
    define('OS_UNIX', true);
43
    define('PEAR_OS', 'Unix'); // blatant assumption
44
}
45
46
$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
47
$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
48
$GLOBALS['_PEAR_destructor_object_list'] = array();
49
$GLOBALS['_PEAR_shutdown_funcs']         = array();
50
$GLOBALS['_PEAR_error_handler_stack']    = array();
51
52
@ini_set('track_errors', true);
53
54
/**
55
 * Base class for other PEAR classes.  Provides rudimentary
56
 * emulation of destructors.
57
 *
58
 * If you want a destructor in your class, inherit PEAR and make a
59
 * destructor method called _yourclassname (same name as the
60
 * constructor, but with a "_" prefix).  Also, in your constructor you
61
 * have to call the PEAR constructor: $this->PEAR();.
62
 * The destructor method will be called without parameters.  Note that
63
 * at in some SAPI implementations (such as Apache), any output during
64
 * the request shutdown (in which destructors are called) seems to be
65
 * discarded.  If you need to get any debug information from your
66
 * destructor, use error_log(), syslog() or something similar.
67
 *
68
 * IMPORTANT! To use the emulated destructors you need to create the
69
 * objects by reference: $obj =& new PEAR_child;
70
 *
71
 * @category    pear
72
 * @package     PEAR
73
 * @author      Stig Bakken <[email protected]>
74
 * @author      Tomas V.V. Cox <[email protected]>
75
 * @author      Greg Beaver <[email protected]>
76
 * @copyright   1997-2006 The PHP Group
77
 * @license     http://opensource.org/licenses/bsd-license.php New BSD License
78
 * @version     Release: 1.10.3
79
 * @link        http://pear.php.net/package/PEAR
80
 * @see         PEAR_Error
81
 * @since       Class available since PHP 4.0.2
82
 * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
83
 */
84
class PEAR
85
{
86
    /**
87
     * Whether to enable internal debug messages.
88
     *
89
     * @var     bool
90
     * @access  private
91
     */
92
    public $_debug = false;
93
94
    /**
95
     * Default error mode for this object.
96
     *
97
     * @var     int
98
     * @access  private
99
     */
100
    public $_default_error_mode = null;
101
102
    /**
103
     * Default error options used for this object when error mode
104
     * is PEAR_ERROR_TRIGGER.
105
     *
106
     * @var     int
107
     * @access  private
108
     */
109
    public $_default_error_options = null;
110
111
    /**
112
     * Default error handler (callback) for this object, if error mode is
113
     * PEAR_ERROR_CALLBACK.
114
     *
115
     * @var     string
116
     * @access  private
117
     */
118
    public $_default_error_handler = '';
119
120
    /**
121
     * Which class to use for error objects.
122
     *
123
     * @var     string
124
     * @access  private
125
     */
126
    public $_error_class = 'PEAR_Error';
127
128
    /**
129
     * An array of expected errors.
130
     *
131
     * @var     array
132
     * @access  private
133
     */
134
    public $_expected_errors = array();
135
136
    /**
137
     * List of methods that can be called both statically and non-statically.
138
     * @var array
139
     */
140
    protected static $bivalentMethods = array(
141
        'setErrorHandling'  => true,
142
        'raiseError'        => true,
143
        'throwError'        => true,
144
        'pushErrorHandling' => true,
145
        'popErrorHandling'  => true,
146
    );
147
148
    /**
149
     * Constructor.  Registers this object in
150
     * $_PEAR_destructor_object_list for destructor emulation if a
151
     * destructor object exists.
152
     *
153
     * @param string $error_class (optional) which class to use for
154
     *                            error objects, defaults to PEAR_Error.
155
     * @access public
156
     * @return void
157
     */
158
    public function __construct($error_class = null)
159
    {
160
        $classname = strtolower(get_class($this));
161
        if ($this->_debug) {
162
            print "PEAR constructor called, class=$classname\n";
163
        }
164
165
        if (null !== $error_class) {
166
            $this->_error_class = $error_class;
167
        }
168
169
        while ($classname && strcasecmp($classname, "pear")) {
170
            $destructor = "_$classname";
171
            if (method_exists($this, $destructor)) {
172
                global $_PEAR_destructor_object_list;
173
                $_PEAR_destructor_object_list[] = &$this;
174
                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
175
                    register_shutdown_function("_PEAR_call_destructors");
176
                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
177
                }
178
                break;
179
            } else {
180
                $classname = get_parent_class($classname);
181
            }
182
        }
183
    }
184
185
    /**
186
     * Only here for backwards compatibility.
187
     * E.g. Archive_Tar calls $this->PEAR() in its constructor.
188
     *
189
     * @param string $error_class Which class to use for error objects,
190
     *                            defaults to PEAR_Error.
191
     */
192
    public function PEAR($error_class = null)
193
    {
194
        self::__construct($error_class);
195
    }
196
197
    /**
198
     * Destructor (the emulated type of...).  Does nothing right now,
199
     * but is included for forward compatibility, so subclass
200
     * destructors should always call it.
201
     *
202
     * See the note in the class desciption about output from
203
     * destructors.
204
     *
205
     * @access public
206
     * @return void
207
     */
208
    public function _PEAR()
209
    {
210
        if ($this->_debug) {
211
            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
212
        }
213
    }
214
215 View Code Duplication
    public function __call($method, $arguments)
216
    {
217
        if (!isset(self::$bivalentMethods[$method])) {
218
            trigger_error('Call to undefined method PEAR::' . $method . '()', E_USER_ERROR);
219
        }
220
221
        return call_user_func_array(array(get_class(), '_' . $method), array_merge(array($this), $arguments));
222
    }
223
224 View Code Duplication
    public static function __callStatic($method, $arguments)
225
    {
226
        if (!isset(self::$bivalentMethods[$method])) {
227
            trigger_error('Call to undefined method PEAR::' . $method . '()', E_USER_ERROR);
228
        }
229
230
        return call_user_func_array(array(get_class(), '_' . $method), array_merge(array(null), $arguments));
231
    }
232
233
    /**
234
     * If you have a class that's mostly/entirely static, and you need static
235
     * properties, you can use this method to simulate them. Eg. in your method(s)
236
     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
237
     * You MUST use a reference, or they will not persist!
238
     *
239
     * @param  string $class The calling classname, to prevent clashes
240
     * @param  string $var   The variable to retrieve.
241
     * @return mixed   A reference to the variable. If not set it will be
242
     *                       auto initialised to NULL.
243
     */
244
    public static function &getStaticProperty($class, $var)
245
    {
246
        static $properties;
247
        if (!isset($properties[$class])) {
248
            $properties[$class] = array();
249
        }
250
251
        if (!array_key_exists($var, $properties[$class])) {
252
            $properties[$class][$var] = null;
253
        }
254
255
        return $properties[$class][$var];
256
    }
257
258
    /**
259
     * Use this function to register a shutdown method for static
260
     * classes.
261
     *
262
     * @param  mixed $func The function name (or array of class/method) to call
263
     * @param  mixed $args The arguments to pass to the function
264
     *
265
     * @return void
266
     */
267
    public static function registerShutdownFunc($func, $args = array())
268
    {
269
        // if we are called statically, there is a potential
270
        // that no shutdown func is registered.  Bug #6445
271
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
272
            register_shutdown_function("_PEAR_call_destructors");
273
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
274
        }
275
        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
276
    }
277
278
    /**
279
     * Tell whether a value is a PEAR error.
280
     *
281
     * @param   mixed $data   the value to test
282
     * @param   int   $code   if $data is an error object, return true
283
     *                        only if $code is a string and
284
     *                        $obj->getMessage() == $code or
285
     *                        $code is an integer and $obj->getCode() == $code
286
     *
287
     * @return  bool    true if parameter is an error
288
     */
289
    public static function isError($data, $code = null)
290
    {
291
        if (!is_a($data, 'PEAR_Error')) {
292
            return false;
293
        }
294
295
        if (is_null($code)) {
296
            return true;
297
        } elseif (is_string($code)) {
298
            return $data->getMessage() == $code;
299
        }
300
301
        return $data->getCode() == $code;
302
    }
303
304
    /**
305
     * Sets how errors generated by this object should be handled.
306
     * Can be invoked both in objects and statically.  If called
307
     * statically, setErrorHandling sets the default behaviour for all
308
     * PEAR objects.  If called in an object, setErrorHandling sets
309
     * the default behaviour for that object.
310
     *
311
     * @param object $object
312
     *        Object the method was called on (non-static mode)
313
     *
314
     * @param int    $mode
315
     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
316
     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
317
     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
318
     *
319
     * @param mixed  $options
320
     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
321
     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
322
     *
323
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
324
     *        to be the callback function or method.  A callback
325
     *        function is a string with the name of the function, a
326
     *        callback method is an array of two elements: the element
327
     *        at index 0 is the object, and the element at index 1 is
328
     *        the name of the method to call in the object.
329
     *
330
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
331
     *        a printf format string used when printing the error
332
     *        message.
333
     *
334
     * @access public
335
     * @return void
336
     * @see    PEAR_ERROR_RETURN
337
     * @see    PEAR_ERROR_PRINT
338
     * @see    PEAR_ERROR_TRIGGER
339
     * @see    PEAR_ERROR_DIE
340
     * @see    PEAR_ERROR_CALLBACK
341
     * @see    PEAR_ERROR_EXCEPTION
342
     *
343
     * @since  PHP 4.0.5
344
     */
345
    protected static function _setErrorHandling(
346
        $object,
347
        $mode = null,
348
        $options = null
349
    ) {
350 View Code Duplication
        if (null !== $object) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
351
            $setmode    = &$object->_default_error_mode;
352
            $setoptions = &$object->_default_error_options;
353
        } else {
354
            $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
355
            $setoptions = &$GLOBALS['_PEAR_default_error_options'];
356
        }
357
358 View Code Duplication
        switch ($mode) {
359
            case PEAR_ERROR_EXCEPTION:
360
            case PEAR_ERROR_RETURN:
361
            case PEAR_ERROR_PRINT:
362
            case PEAR_ERROR_TRIGGER:
363
            case PEAR_ERROR_DIE:
364
            case null:
365
                $setmode    = $mode;
366
                $setoptions = $options;
367
                break;
368
369
            case PEAR_ERROR_CALLBACK:
370
                $setmode = $mode;
371
                // class/object method callback
372
                if (is_callable($options)) {
373
                    $setoptions = $options;
374
                } else {
375
                    trigger_error("invalid error callback", E_USER_WARNING);
376
                }
377
                break;
378
379
            default:
380
                trigger_error("invalid error mode", E_USER_WARNING);
381
                break;
382
        }
383
    }
384
385
    /**
386
     * This method is used to tell which errors you expect to get.
387
     * Expected errors are always returned with error mode
388
     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
389
     * and this method pushes a new element onto it.  The list of
390
     * expected errors are in effect until they are popped off the
391
     * stack with the popExpect() method.
392
     *
393
     * Note that this method can not be called statically
394
     *
395
     * @param mixed $code a single error code or an array of error codes to expect
396
     *
397
     * @return int     the new depth of the "expected errors" stack
398
     * @access public
399
     */
400
    public function expectError($code = '*')
401
    {
402
        if (is_array($code)) {
403
            array_push($this->_expected_errors, $code);
404
        } else {
405
            array_push($this->_expected_errors, array($code));
406
        }
407
408
        return count($this->_expected_errors);
409
    }
410
411
    /**
412
     * This method pops one element off the expected error codes
413
     * stack.
414
     *
415
     * @return array   the list of error codes that were popped
416
     */
417
    public function popExpect()
418
    {
419
        return array_pop($this->_expected_errors);
420
    }
421
422
    /**
423
     * This method checks unsets an error code if available
424
     *
425
     * @param mixed error code
426
     * @return bool true if the error code was unset, false otherwise
427
     * @access private
428
     * @since  PHP 4.3.0
429
     */
430
    public function _checkDelExpect($error_code)
431
    {
432
        $deleted = false;
433
        foreach ($this->_expected_errors as $key => $error_array) {
434
            if (in_array($error_code, $error_array)) {
435
                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
436
                $deleted = true;
437
            }
438
439
            // clean up empty arrays
440
            if (0 == count($this->_expected_errors[$key])) {
441
                unset($this->_expected_errors[$key]);
442
            }
443
        }
444
445
        return $deleted;
446
    }
447
448
    /**
449
     * This method deletes all occurrences of the specified element from
450
     * the expected error codes stack.
451
     *
452
     * @param  mixed $error_code error code that should be deleted
453
     * @return mixed list of error codes that were deleted or error
454
     * @access public
455
     * @since  PHP 4.3.0
456
     */
457
    public function delExpect($error_code)
458
    {
459
        $deleted = false;
460
        if ((is_array($error_code) && (0 != count($error_code)))) {
461
            // $error_code is a non-empty array here; we walk through it trying
462
            // to unset all values
463
            foreach ($error_code as $key => $error) {
464
                $deleted = $this->_checkDelExpect($error) ? true : false;
465
            }
466
467
            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
468
        } elseif (!empty($error_code)) {
469
            // $error_code comes alone, trying to unset it
470
            if ($this->_checkDelExpect($error_code)) {
471
                return true;
472
            }
473
474
            return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
475
        }
476
477
        // $error_code is empty
478
        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
479
    }
480
481
    /**
482
     * This method is a wrapper that returns an instance of the
483
     * configured error class with this object's default error
484
     * handling applied.  If the $mode and $options parameters are not
485
     * specified, the object's defaults are used.
486
     *
487
     * @param mixed  $message     a text error message or a PEAR error object
488
     *
489
     * @param int    $code        a numeric error code (it is up to your class
490
     *                            to define these if you want to use codes)
491
     *
492
     * @param int    $mode        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
493
     *                            PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
494
     *                            PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
495
     *
496
     * @param mixed  $options     If $mode is PEAR_ERROR_TRIGGER, this parameter
497
     *                            specifies the PHP-internal error level (one of
498
     *                            E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
499
     *                            If $mode is PEAR_ERROR_CALLBACK, this
500
     *                            parameter specifies the callback function or
501
     *                            method.  In other error modes this parameter
502
     *                            is ignored.
503
     *
504
     * @param string $userinfo    If you need to pass along for example debug
505
     *                            information, this parameter is meant for that.
506
     *
507
     * @param string $error_class The returned error object will be
508
     *                            instantiated from this class, if specified.
509
     *
510
     * @param bool   $skipmsg     If true, raiseError will only pass error codes,
511
     *                            the error message parameter will be dropped.
512
     *
513
     * @return object   a PEAR error object
514
     * @see   PEAR::setErrorHandling
515
     * @since PHP 4.0.5
516
     */
517
    protected static function _raiseError(
518
        $object,
519
        $message = null,
520
        $code = null,
521
        $mode = null,
522
        $options = null,
523
        $userinfo = null,
524
        $error_class = null,
525
        $skipmsg = false
526
    ) {
527
        // The error is yet a PEAR error object
528
        if (is_object($message)) {
529
            $code                          = $message->getCode();
530
            $userinfo                      = $message->getUserInfo();
531
            $error_class                   = $message->getType();
532
            $message->error_message_prefix = '';
533
            $message                       = $message->getMessage();
534
        }
535
536
        if (null !== $object
537
            && isset($object->_expected_errors)
538
            && count($object->_expected_errors) > 0
539
            && count($exp = end($object->_expected_errors))) {
540
            if ("*" == $exp[0]
541
                || (is_int(reset($exp)) && in_array($code, $exp))
542
                || (is_string(reset($exp)) && in_array($message, $exp))) {
543
                $mode = PEAR_ERROR_RETURN;
544
            }
545
        }
546
547
        // No mode given, try global ones
548
        if (null === $mode) {
549
            // Class error handler
550
            if (null !== $object && isset($object->_default_error_mode)) {
551
                $mode    = $object->_default_error_mode;
552
                $options = $object->_default_error_options;
553
                // Global error handler
554
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
555
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
556
                $options = $GLOBALS['_PEAR_default_error_options'];
557
            }
558
        }
559
560
        if (null !== $error_class) {
561
            $ec = $error_class;
562
        } elseif (null !== $object && isset($object->_error_class)) {
563
            $ec = $object->_error_class;
564
        } else {
565
            $ec = 'PEAR_Error';
566
        }
567
568
        if ($skipmsg) {
569
            $a = new $ec($code, $mode, $options, $userinfo);
570
        } else {
571
            $a = new $ec($message, $code, $mode, $options, $userinfo);
572
        }
573
574
        return $a;
575
    }
576
577
    /**
578
     * Simpler form of raiseError with fewer options.  In most cases
579
     * message, code and userinfo are enough.
580
     *
581
     * @param mixed  $message  a text error message or a PEAR error object
582
     *
583
     * @param int    $code     a numeric error code (it is up to your class
584
     *                         to define these if you want to use codes)
585
     *
586
     * @param string $userinfo If you need to pass along for example debug
587
     *                         information, this parameter is meant for that.
588
     *
589
     * @return object   a PEAR error object
590
     * @see PEAR::raiseError
591
     */
592
    protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
593
    {
594
        if (null !== $object) {
595
            $a = &$object->raiseError($message, $code, null, null, $userinfo);
596
597
            return $a;
598
        }
599
600
        $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
601
602
        return $a;
603
    }
604
605
    public static function staticPushErrorHandling($mode, $options = null)
606
    {
607
        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
608
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
609
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
610
        $stack[]     = array($def_mode, $def_options);
611 View Code Duplication
        switch ($mode) {
612
            case PEAR_ERROR_EXCEPTION:
613
            case PEAR_ERROR_RETURN:
614
            case PEAR_ERROR_PRINT:
615
            case PEAR_ERROR_TRIGGER:
616
            case PEAR_ERROR_DIE:
617
            case null:
618
                $def_mode    = $mode;
619
                $def_options = $options;
620
                break;
621
622
            case PEAR_ERROR_CALLBACK:
623
                $def_mode = $mode;
624
                // class/object method callback
625
                if (is_callable($options)) {
626
                    $def_options = $options;
627
                } else {
628
                    trigger_error("invalid error callback", E_USER_WARNING);
629
                }
630
                break;
631
632
            default:
633
                trigger_error("invalid error mode", E_USER_WARNING);
634
                break;
635
        }
636
        $stack[] = array($mode, $options);
637
638
        return true;
639
    }
640
641
    public static function staticPopErrorHandling()
642
    {
643
        $stack      = &$GLOBALS['_PEAR_error_handler_stack'];
644
        $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
645
        $setoptions = &$GLOBALS['_PEAR_default_error_options'];
646
        array_pop($stack);
647
        list($mode, $options) = $stack[sizeof($stack) - 1];
648
        array_pop($stack);
649 View Code Duplication
        switch ($mode) {
650
            case PEAR_ERROR_EXCEPTION:
651
            case PEAR_ERROR_RETURN:
652
            case PEAR_ERROR_PRINT:
653
            case PEAR_ERROR_TRIGGER:
654
            case PEAR_ERROR_DIE:
655
            case null:
656
                $setmode    = $mode;
657
                $setoptions = $options;
658
                break;
659
660
            case PEAR_ERROR_CALLBACK:
661
                $setmode = $mode;
662
                // class/object method callback
663
                if (is_callable($options)) {
664
                    $setoptions = $options;
665
                } else {
666
                    trigger_error("invalid error callback", E_USER_WARNING);
667
                }
668
                break;
669
670
            default:
671
                trigger_error("invalid error mode", E_USER_WARNING);
672
                break;
673
        }
674
675
        return true;
676
    }
677
678
    /**
679
     * Push a new error handler on top of the error handler options stack. With this
680
     * you can easily override the actual error handler for some code and restore
681
     * it later with popErrorHandling.
682
     *
683
     * @param mixed $mode    (same as setErrorHandling)
684
     * @param mixed $options (same as setErrorHandling)
685
     *
686
     * @return bool Always true
687
     *
688
     * @see PEAR::setErrorHandling
689
     */
690
    protected static function _pushErrorHandling($object, $mode, $options = null)
691
    {
692
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
693 View Code Duplication
        if (null !== $object) {
694
            $def_mode    = &$object->_default_error_mode;
695
            $def_options = &$object->_default_error_options;
696
        } else {
697
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
698
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
699
        }
700
        $stack[] = array($def_mode, $def_options);
701
702
        if (null !== $object) {
703
            $object->setErrorHandling($mode, $options);
704
        } else {
705
            PEAR::setErrorHandling($mode, $options);
706
        }
707
        $stack[] = array($mode, $options);
708
709
        return true;
710
    }
711
712
    /**
713
     * Pop the last error handler used
714
     *
715
     * @return bool Always true
716
     *
717
     * @see PEAR::pushErrorHandling
718
     */
719
    protected static function _popErrorHandling($object)
720
    {
721
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
722
        array_pop($stack);
723
        list($mode, $options) = $stack[sizeof($stack) - 1];
724
        array_pop($stack);
725
        if (null !== $object) {
726
            $object->setErrorHandling($mode, $options);
727
        } else {
728
            PEAR::setErrorHandling($mode, $options);
729
        }
730
731
        return true;
732
    }
733
734
    /**
735
     * OS independent PHP extension load. Remember to take care
736
     * on the correct extension name for case sensitive OSes.
737
     *
738
     * @param string $ext The extension name
739
     * @return bool Success or not on the dl() call
740
     */
741
    public static function loadExtension($ext)
742
    {
743
        if (extension_loaded($ext)) {
744
            return true;
745
        }
746
747
        // if either returns true dl() will produce a FATAL error, stop that
748
        if (false === function_exists('dl')
749
            || 1 != ini_get('enable_dl')) {
750
            return false;
751
        }
752
753
        if (OS_WINDOWS) {
754
            $suffix = '.dll';
755
        } elseif (PHP_OS == 'HP-UX') {
756
            $suffix = '.sl';
757
        } elseif (PHP_OS == 'AIX') {
758
            $suffix = '.a';
759
        } elseif (PHP_OS == 'OSX') {
760
            $suffix = '.bundle';
761
        } else {
762
            $suffix = '.so';
763
        }
764
765
        return @dl('php_' . $ext . $suffix) || @dl($ext . $suffix);
766
    }
767
}
768
769
function _PEAR_call_destructors()
770
{
771
    global $_PEAR_destructor_object_list;
772
    if (is_array($_PEAR_destructor_object_list)
773
        && sizeof($_PEAR_destructor_object_list)) {
774
        reset($_PEAR_destructor_object_list);
775
776
        $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
777
778
        if ($destructLifoExists) {
779
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
780
        }
781
782
        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
783
            $classname = get_class($objref);
784
            while ($classname) {
785
                $destructor = "_$classname";
786
                if (method_exists($objref, $destructor)) {
787
                    $objref->$destructor();
788
                    break;
789
                } else {
790
                    $classname = get_parent_class($classname);
791
                }
792
            }
793
        }
794
        // Empty the object list to ensure that destructors are
795
        // not called more than once.
796
        $_PEAR_destructor_object_list = array();
797
    }
798
799
    // Now call the shutdown functions
800
    if (isset($GLOBALS['_PEAR_shutdown_funcs'])
801
        && is_array($GLOBALS['_PEAR_shutdown_funcs'])
802
        && !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
803
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
804
            call_user_func_array($value[0], $value[1]);
805
        }
806
    }
807
}
808
809
/**
810
 * Standard PEAR error class for PHP 4
811
 *
812
 * This class is supserseded by {@link PEAR_Exception} in PHP 5
813
 *
814
 * @category   pear
815
 * @package    PEAR
816
 * @author     Stig Bakken <[email protected]>
817
 * @author     Tomas V.V. Cox <[email protected]>
818
 * @author     Gregory Beaver <[email protected]>
819
 * @copyright  1997-2006 The PHP Group
820
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
821
 * @version    Release: 1.10.3
822
 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
823
 * @see        PEAR::raiseError(), PEAR::throwError()
824
 * @since      Class available since PHP 4.0.2
825
 */
826
class PEAR_Error
827
{
828
    public $error_message_prefix = '';
829
    public $mode                 = PEAR_ERROR_RETURN;
830
    public $level                = E_USER_NOTICE;
831
    public $code                 = -1;
832
    public $message              = '';
833
    public $userinfo             = '';
834
    public $backtrace            = null;
835
836
    /**
837
     * PEAR_Error constructor
838
     *
839
     * @param string $message  message
840
     *
841
     * @param int    $code     (optional) error code
842
     *
843
     * @param int    $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
844
     *                         PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
845
     *                         PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
846
     *
847
     * @param mixed  $options  (optional) error level, _OR_ in the case of
848
     *                         PEAR_ERROR_CALLBACK, the callback function or object/method
849
     *                         tuple.
850
     *
851
     * @param string $userinfo (optional) additional user/debug info
852
     *
853
     * @access public
854
     *
855
     */
856
    public function __construct(
857
        $message = 'unknown error',
858
        $code = null,
859
        $mode = null,
860
        $options = null,
861
        $userinfo = null
862
    ) {
863
        if (null === $mode) {
864
            $mode = PEAR_ERROR_RETURN;
865
        }
866
        $this->message  = $message;
867
        $this->code     = $code;
868
        $this->mode     = $mode;
869
        $this->userinfo = $userinfo;
870
871
        $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
872
873
        if (!$skiptrace) {
874
            $this->backtrace = debug_backtrace();
875
            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
876
                unset($this->backtrace[0]['object']);
877
            }
878
        }
879
880
        if ($mode & PEAR_ERROR_CALLBACK) {
881
            $this->level    = E_USER_NOTICE;
882
            $this->callback = $options;
883
        } else {
884
            if (null === $options) {
885
                $options = E_USER_NOTICE;
886
            }
887
888
            $this->level    = $options;
889
            $this->callback = null;
890
        }
891
892
        if ($this->mode & PEAR_ERROR_PRINT) {
893
            if (is_null($options) || is_int($options)) {
894
                $format = "%s";
895
            } else {
896
                $format = $options;
897
            }
898
899
            printf($format, $this->getMessage());
900
        }
901
902
        if ($this->mode & PEAR_ERROR_TRIGGER) {
903
            trigger_error($this->getMessage(), $this->level);
904
        }
905
906
        if ($this->mode & PEAR_ERROR_DIE) {
907
            $msg = $this->getMessage();
908
            if (is_null($options) || is_int($options)) {
909
                $format = "%s";
910
                if ("\n" != substr($msg, -1)) {
911
                    $msg .= "\n";
912
                }
913
            } else {
914
                $format = $options;
915
            }
916
            printf($format, $msg);
917
            exit($code);
918
        }
919
920
        if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
921
            call_user_func($this->callback, $this);
922
        }
923
924
        if ($this->mode & PEAR_ERROR_EXCEPTION) {
925
            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
926
            eval('$e = new Exception($this->message, $this->code);throw($e);');
927
        }
928
    }
929
930
    /**
931
     * Only here for backwards compatibility.
932
     *
933
     * Class "Cache_Error" still uses it, among others.
934
     *
935
     * @param string $message  Message
936
     * @param int    $code     Error code
937
     * @param int    $mode     Error mode
938
     * @param mixed  $options  See __construct()
939
     * @param string $userinfo Additional user/debug info
940
     */
941
    public function PEAR_Error(
942
        $message = 'unknown error',
943
        $code = null,
944
        $mode = null,
945
        $options = null,
946
        $userinfo = null
947
    ) {
948
        self::__construct($message, $code, $mode, $options, $userinfo);
949
    }
950
951
    /**
952
     * Get the error mode from an error object.
953
     *
954
     * @return int error mode
955
     * @access public
956
     */
957
    public function getMode()
958
    {
959
        return $this->mode;
960
    }
961
962
    /**
963
     * Get the callback function/method from an error object.
964
     *
965
     * @return mixed callback function or object/method array
966
     * @access public
967
     */
968
    public function getCallback()
969
    {
970
        return $this->callback;
971
    }
972
973
    /**
974
     * Get the error message from an error object.
975
     *
976
     * @return  string  full error message
977
     * @access public
978
     */
979
    public function getMessage()
980
    {
981
        return ($this->error_message_prefix . $this->message);
982
    }
983
984
    /**
985
     * Get error code from an error object
986
     *
987
     * @return int error code
988
     * @access public
989
     */
990
    public function getCode()
991
    {
992
        return $this->code;
993
    }
994
995
    /**
996
     * Get the name of this error/exception.
997
     *
998
     * @return string error/exception name (type)
999
     * @access public
1000
     */
1001
    public function getType()
1002
    {
1003
        return get_class($this);
1004
    }
1005
1006
    /**
1007
     * Get additional user-supplied information.
1008
     *
1009
     * @return string user-supplied information
1010
     * @access public
1011
     */
1012
    public function getUserInfo()
1013
    {
1014
        return $this->userinfo;
1015
    }
1016
1017
    /**
1018
     * Get additional debug information supplied by the application.
1019
     *
1020
     * @return string debug information
1021
     * @access public
1022
     */
1023
    public function getDebugInfo()
1024
    {
1025
        return $this->getUserInfo();
1026
    }
1027
1028
    /**
1029
     * Get the call backtrace from where the error was generated.
1030
     * Supported with PHP 4.3.0 or newer.
1031
     *
1032
     * @param int $frame (optional) what frame to fetch
1033
     * @return array Backtrace, or NULL if not available.
1034
     * @access public
1035
     */
1036
    public function getBacktrace($frame = null)
1037
    {
1038
        if (defined('PEAR_IGNORE_BACKTRACE')) {
1039
            return null;
1040
        }
1041
        if (null === $frame) {
1042
            return $this->backtrace;
1043
        }
1044
1045
        return $this->backtrace[$frame];
1046
    }
1047
1048
    public function addUserInfo($info)
1049
    {
1050
        if (empty($this->userinfo)) {
1051
            $this->userinfo = $info;
1052
        } else {
1053
            $this->userinfo .= " ** $info";
1054
        }
1055
    }
1056
1057
    public function __toString()
1058
    {
1059
        return $this->getMessage();
1060
    }
1061
1062
    /**
1063
     * Make a string representation of this object.
1064
     *
1065
     * @return string a string with an object summary
1066
     * @access public
1067
     */
1068
    public function toString()
1069
    {
1070
        $modes  = array();
1071
        $levels = array(
1072
            E_USER_NOTICE  => 'notice',
1073
            E_USER_WARNING => 'warning',
1074
            E_USER_ERROR   => 'error'
1075
        );
1076
        if ($this->mode & PEAR_ERROR_CALLBACK) {
1077
            if (is_array($this->callback)) {
1078
                $callback = (is_object($this->callback[0]) ? strtolower(get_class($this->callback[0])) : $this->callback[0]) . '::' . $this->callback[1];
1079
            } else {
1080
                $callback = $this->callback;
1081
            }
1082
1083
            return sprintf('[%s: message="%s" code=%d mode=callback ' . 'callback=%s prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo);
1084
        }
1085
        if ($this->mode & PEAR_ERROR_PRINT) {
1086
            $modes[] = 'print';
1087
        }
1088
        if ($this->mode & PEAR_ERROR_TRIGGER) {
1089
            $modes[] = 'trigger';
1090
        }
1091
        if ($this->mode & PEAR_ERROR_DIE) {
1092
            $modes[] = 'die';
1093
        }
1094
        if ($this->mode & PEAR_ERROR_RETURN) {
1095
            $modes[] = 'return';
1096
        }
1097
1098
        return sprintf('[%s: message="%s" code=%d mode=%s level=%s ' . 'prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, implode("|", $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo);
1099
    }
1100
}
1101
1102
/*
1103
 * Local Variables:
1104
 * mode: php
1105
 * tab-width: 4
1106
 * c-basic-offset: 4
1107
 * End:
1108
 */
1109