Project

General

Profile

Download (32.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
// $Id$
3

    
4
//
5
// +--------------------------------------------------------------------+
6
// | PEAR, the PHP Extension and Application Repository                 |
7
// +--------------------------------------------------------------------+
8
// | Copyright (c) 1997-2004 The PHP Group                              |
9
// +--------------------------------------------------------------------+
10
// | This source file is subject to version 3.0 of the PHP license,     |
11
// | that is bundled with this package in the file LICENSE, and is      |
12
// | available through the world-wide-web at the following url:         |
13
// | http://www.php.net/license/3_0.txt.                                |
14
// | If you did not receive a copy of the PHP license and are unable to |
15
// | obtain it through the world-wide-web, please send a note to        |
16
// | license@php.net so we can mail you a copy immediately.             |
17
// +--------------------------------------------------------------------+
18
// | Authors: Sterling Hughes <sterling@php.net>                        |
19
// |          Stig Bakken <ssb@php.net>                                 |
20
// |          Tomas V.V.Cox <cox@idecnet.com>                           |
21
// +--------------------------------------------------------------------+
22
//
23
//
24

    
25
define('PEAR_ERROR_RETURN',     1);
26
define('PEAR_ERROR_PRINT',      2);
27
define('PEAR_ERROR_TRIGGER',    4);
28
define('PEAR_ERROR_DIE',        8);
29
define('PEAR_ERROR_CALLBACK',  16);
30
/**
31
 * WARNING: obsolete
32
 * @deprecated
33
 */
34
define('PEAR_ERROR_EXCEPTION', 32);
35
define('PEAR_ZE2', (function_exists('version_compare') &&
36
                    version_compare(zend_version(), "2-dev", "ge")));
37

    
38
if (substr(PHP_OS, 0, 3) == 'WIN') {
39
    define('OS_WINDOWS', true);
40
    define('OS_UNIX',    false);
41
    define('PEAR_OS',    'Windows');
42
} else {
43
    define('OS_WINDOWS', false);
44
    define('OS_UNIX',    true);
45
    define('PEAR_OS',    'Unix'); // blatant assumption
46
}
47

    
48
// instant backwards compatibility
49
if (!defined('PATH_SEPARATOR')) {
50
    if (OS_WINDOWS) {
51
        define('PATH_SEPARATOR', ';');
52
    } else {
53
        define('PATH_SEPARATOR', ':');
54
    }
55
}
56

    
57
$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
58
$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
59
$GLOBALS['_PEAR_destructor_object_list'] = array();
60
$GLOBALS['_PEAR_shutdown_funcs']         = array();
61
$GLOBALS['_PEAR_error_handler_stack']    = array();
62

    
63
@ini_set('track_errors', true);
64

    
65
/**
66
 * Base class for other PEAR classes.  Provides rudimentary
67
 * emulation of destructors.
68
 *
69
 * If you want a destructor in your class, inherit PEAR and make a
70
 * destructor method called _yourclassname (same name as the
71
 * constructor, but with a "_" prefix).  Also, in your constructor you
72
 * have to call the PEAR constructor: $this->PEAR();.
73
 * The destructor method will be called without parameters.  Note that
74
 * at in some SAPI implementations (such as Apache), any output during
75
 * the request shutdown (in which destructors are called) seems to be
76
 * discarded.  If you need to get any debug information from your
77
 * destructor, use error_log(), syslog() or something similar.
78
 *
79
 * IMPORTANT! To use the emulated destructors you need to create the
80
 * objects by reference: $obj =& new PEAR_child;
81
 *
82
 * @since PHP 4.0.2
83
 * @author Stig Bakken <ssb@php.net>
84
 * @see http://pear.php.net/manual/
85
 */
86
class PEAR
87
{
88
    // {{{ properties
89

    
90
    /**
91
     * Whether to enable internal debug messages.
92
     *
93
     * @var     bool
94
     * @access  private
95
     */
96
    var $_debug = false;
97

    
98
    /**
99
     * Default error mode for this object.
100
     *
101
     * @var     int
102
     * @access  private
103
     */
104
    var $_default_error_mode = null;
105

    
106
    /**
107
     * Default error options used for this object when error mode
108
     * is PEAR_ERROR_TRIGGER.
109
     *
110
     * @var     int
111
     * @access  private
112
     */
113
    var $_default_error_options = null;
114

    
115
    /**
116
     * Default error handler (callback) for this object, if error mode is
117
     * PEAR_ERROR_CALLBACK.
118
     *
119
     * @var     string
120
     * @access  private
121
     */
122
    var $_default_error_handler = '';
123

    
124
    /**
125
     * Which class to use for error objects.
126
     *
127
     * @var     string
128
     * @access  private
129
     */
130
    var $_error_class = 'PEAR_Error';
131

    
132
    /**
133
     * An array of expected errors.
134
     *
135
     * @var     array
136
     * @access  private
137
     */
138
    var $_expected_errors = array();
139

    
140
    // }}}
141

    
142
    // {{{ constructor
143

    
144
    /**
145
     * Constructor.  Registers this object in
146
     * $_PEAR_destructor_object_list for destructor emulation if a
147
     * destructor object exists.
148
     *
149
     * @param string $error_class  (optional) which class to use for
150
     *        error objects, defaults to PEAR_Error.
151
     * @access public
152
     * @return void
153
     */
154
    function PEAR($error_class = null)
155
    {
156
        $classname = strtolower(get_class($this));
157
        if ($this->_debug) {
158
            print "PEAR constructor called, class=$classname\n";
159
        }
160
        if ($error_class !== null) {
161
            $this->_error_class = $error_class;
162
        }
163
        while ($classname && strcasecmp($classname, "pear")) {
164
            $destructor = "_$classname";
165
            if (method_exists($this, $destructor)) {
166
                global $_PEAR_destructor_object_list;
167
                $_PEAR_destructor_object_list[] = &$this;
168
                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
169
                    register_shutdown_function("_PEAR_call_destructors");
170
                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
171
                }
172
                break;
173
            } else {
174
                $classname = get_parent_class($classname);
175
            }
176
        }
177
    }
178

    
179
    // }}}
180
    // {{{ destructor
181

    
182
    /**
183
     * Destructor (the emulated type of...).  Does nothing right now,
184
     * but is included for forward compatibility, so subclass
185
     * destructors should always call it.
186
     *
187
     * See the note in the class desciption about output from
188
     * destructors.
189
     *
190
     * @access public
191
     * @return void
192
     */
193
    function _PEAR() {
194
        if ($this->_debug) {
195
            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
196
        }
197
    }
198

    
199
    // }}}
200
    // {{{ getStaticProperty()
201

    
202
    /**
203
    * If you have a class that's mostly/entirely static, and you need static
204
    * properties, you can use this method to simulate them. Eg. in your method(s)
205
    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
206
    * You MUST use a reference, or they will not persist!
207
    *
208
    * @access public
209
    * @param  string $class  The calling classname, to prevent clashes
210
    * @param  string $var    The variable to retrieve.
211
    * @return mixed   A reference to the variable. If not set it will be
212
    *                 auto initialised to NULL.
213
    */
214
    function &getStaticProperty($class, $var)
215
    {
216
        static $properties;
217
        return $properties[$class][$var];
218
    }
219

    
220
    // }}}
221
    // {{{ registerShutdownFunc()
222

    
223
    /**
224
    * Use this function to register a shutdown method for static
225
    * classes.
226
    *
227
    * @access public
228
    * @param  mixed $func  The function name (or array of class/method) to call
229
    * @param  mixed $args  The arguments to pass to the function
230
    * @return void
231
    */
232
    function registerShutdownFunc($func, $args = array())
233
    {
234
        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
235
    }
236

    
237
    // }}}
238
    // {{{ isError()
239

    
240
    /**
241
     * Tell whether a value is a PEAR error.
242
     *
243
     * @param   mixed $data   the value to test
244
     * @param   int   $code   if $data is an error object, return true
245
     *                        only if $code is a string and
246
     *                        $obj->getMessage() == $code or
247
     *                        $code is an integer and $obj->getCode() == $code
248
     * @access  public
249
     * @return  bool    true if parameter is an error
250
     */
251
    function isError($data, $code = null)
252
    {
253
        if (is_a($data, 'PEAR_Error')) {
254
            if (is_null($code)) {
255
                return true;
256
            } elseif (is_string($code)) {
257
                return $data->getMessage() == $code;
258
            } else {
259
                return $data->getCode() == $code;
260
            }
261
        }
262
        return false;
263
    }
264

    
265
    // }}}
266
    // {{{ setErrorHandling()
267

    
268
    /**
269
     * Sets how errors generated by this object should be handled.
270
     * Can be invoked both in objects and statically.  If called
271
     * statically, setErrorHandling sets the default behaviour for all
272
     * PEAR objects.  If called in an object, setErrorHandling sets
273
     * the default behaviour for that object.
274
     *
275
     * @param int $mode
276
     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
277
     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
278
     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
279
     *
280
     * @param mixed $options
281
     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
282
     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
283
     *
284
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
285
     *        to be the callback function or method.  A callback
286
     *        function is a string with the name of the function, a
287
     *        callback method is an array of two elements: the element
288
     *        at index 0 is the object, and the element at index 1 is
289
     *        the name of the method to call in the object.
290
     *
291
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
292
     *        a printf format string used when printing the error
293
     *        message.
294
     *
295
     * @access public
296
     * @return void
297
     * @see PEAR_ERROR_RETURN
298
     * @see PEAR_ERROR_PRINT
299
     * @see PEAR_ERROR_TRIGGER
300
     * @see PEAR_ERROR_DIE
301
     * @see PEAR_ERROR_CALLBACK
302
     * @see PEAR_ERROR_EXCEPTION
303
     *
304
     * @since PHP 4.0.5
305
     */
306

    
307
    function setErrorHandling($mode = null, $options = null)
308
    {
309
        if (isset($this) && is_a($this, 'PEAR')) {
310
            $setmode     = &$this->_default_error_mode;
311
            $setoptions  = &$this->_default_error_options;
312
        } else {
313
            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
314
            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
315
        }
316

    
317
        switch ($mode) {
318
            case PEAR_ERROR_EXCEPTION:
319
            case PEAR_ERROR_RETURN:
320
            case PEAR_ERROR_PRINT:
321
            case PEAR_ERROR_TRIGGER:
322
            case PEAR_ERROR_DIE:
323
            case null:
324
                $setmode = $mode;
325
                $setoptions = $options;
326
                break;
327

    
328
            case PEAR_ERROR_CALLBACK:
329
                $setmode = $mode;
330
                // class/object method callback
331
                if (is_callable($options)) {
332
                    $setoptions = $options;
333
                } else {
334
                    trigger_error("invalid error callback", E_USER_WARNING);
335
                }
336
                break;
337

    
338
            default:
339
                trigger_error("invalid error mode", E_USER_WARNING);
340
                break;
341
        }
342
    }
343

    
344
    // }}}
345
    // {{{ expectError()
346

    
347
    /**
348
     * This method is used to tell which errors you expect to get.
349
     * Expected errors are always returned with error mode
350
     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
351
     * and this method pushes a new element onto it.  The list of
352
     * expected errors are in effect until they are popped off the
353
     * stack with the popExpect() method.
354
     *
355
     * Note that this method can not be called statically
356
     *
357
     * @param mixed $code a single error code or an array of error codes to expect
358
     *
359
     * @return int     the new depth of the "expected errors" stack
360
     * @access public
361
     */
362
    function expectError($code = '*')
363
    {
364
        if (is_array($code)) {
365
            array_push($this->_expected_errors, $code);
366
        } else {
367
            array_push($this->_expected_errors, array($code));
368
        }
369
        return sizeof($this->_expected_errors);
370
    }
371

    
372
    // }}}
373
    // {{{ popExpect()
374

    
375
    /**
376
     * This method pops one element off the expected error codes
377
     * stack.
378
     *
379
     * @return array   the list of error codes that were popped
380
     */
381
    function popExpect()
382
    {
383
        return array_pop($this->_expected_errors);
384
    }
385

    
386
    // }}}
387
    // {{{ _checkDelExpect()
388

    
389
    /**
390
     * This method checks unsets an error code if available
391
     *
392
     * @param mixed error code
393
     * @return bool true if the error code was unset, false otherwise
394
     * @access private
395
     * @since PHP 4.3.0
396
     */
397
    function _checkDelExpect($error_code)
398
    {
399
        $deleted = false;
400

    
401
        foreach ($this->_expected_errors AS $key => $error_array) {
402
            if (in_array($error_code, $error_array)) {
403
                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
404
                $deleted = true;
405
            }
406

    
407
            // clean up empty arrays
408
            if (0 == count($this->_expected_errors[$key])) {
409
                unset($this->_expected_errors[$key]);
410
            }
411
        }
412
        return $deleted;
413
    }
414

    
415
    // }}}
416
    // {{{ delExpect()
417

    
418
    /**
419
     * This method deletes all occurences of the specified element from
420
     * the expected error codes stack.
421
     *
422
     * @param  mixed $error_code error code that should be deleted
423
     * @return mixed list of error codes that were deleted or error
424
     * @access public
425
     * @since PHP 4.3.0
426
     */
427
    function delExpect($error_code)
428
    {
429
        $deleted = false;
430

    
431
        if ((is_array($error_code) && (0 != count($error_code)))) {
432
            // $error_code is a non-empty array here;
433
            // we walk through it trying to unset all
434
            // values
435
            foreach($error_code as $key => $error) {
436
                if ($this->_checkDelExpect($error)) {
437
                    $deleted =  true;
438
                } else {
439
                    $deleted = false;
440
                }
441
            }
442
            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
443
        } elseif (!empty($error_code)) {
444
            // $error_code comes alone, trying to unset it
445
            if ($this->_checkDelExpect($error_code)) {
446
                return true;
447
            } else {
448
                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
449
            }
450
        } else {
451
            // $error_code is empty
452
            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
453
        }
454
    }
455

    
456
    // }}}
457
    // {{{ raiseError()
458

    
459
    /**
460
     * This method is a wrapper that returns an instance of the
461
     * configured error class with this object's default error
462
     * handling applied.  If the $mode and $options parameters are not
463
     * specified, the object's defaults are used.
464
     *
465
     * @param mixed $message a text error message or a PEAR error object
466
     *
467
     * @param int $code      a numeric error code (it is up to your class
468
     *                  to define these if you want to use codes)
469
     *
470
     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
471
     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
472
     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
473
     *
474
     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
475
     *                  specifies the PHP-internal error level (one of
476
     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
477
     *                  If $mode is PEAR_ERROR_CALLBACK, this
478
     *                  parameter specifies the callback function or
479
     *                  method.  In other error modes this parameter
480
     *                  is ignored.
481
     *
482
     * @param string $userinfo If you need to pass along for example debug
483
     *                  information, this parameter is meant for that.
484
     *
485
     * @param string $error_class The returned error object will be
486
     *                  instantiated from this class, if specified.
487
     *
488
     * @param bool $skipmsg If true, raiseError will only pass error codes,
489
     *                  the error message parameter will be dropped.
490
     *
491
     * @access public
492
     * @return object   a PEAR error object
493
     * @see PEAR::setErrorHandling
494
     * @since PHP 4.0.5
495
     */
496
    function raiseError($message = null,
497
                         $code = null,
498
                         $mode = null,
499
                         $options = null,
500
                         $userinfo = null,
501
                         $error_class = null,
502
                         $skipmsg = false)
503
    {
504
        // The error is yet a PEAR error object
505
        if (is_object($message)) {
506
            $code        = $message->getCode();
507
            $userinfo    = $message->getUserInfo();
508
            $error_class = $message->getType();
509
            $message->error_message_prefix = '';
510
            $message     = $message->getMessage();
511
        }
512

    
513
        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
514
            if ($exp[0] == "*" ||
515
                (is_int(reset($exp)) && in_array($code, $exp)) ||
516
                (is_string(reset($exp)) && in_array($message, $exp))) {
517
                $mode = PEAR_ERROR_RETURN;
518
            }
519
        }
520
        // No mode given, try global ones
521
        if ($mode === null) {
522
            // Class error handler
523
            if (isset($this) && isset($this->_default_error_mode)) {
524
                $mode    = $this->_default_error_mode;
525
                $options = $this->_default_error_options;
526
            // Global error handler
527
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
528
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
529
                $options = $GLOBALS['_PEAR_default_error_options'];
530
            }
531
        }
532

    
533
        if ($error_class !== null) {
534
            $ec = $error_class;
535
        } elseif (isset($this) && isset($this->_error_class)) {
536
            $ec = $this->_error_class;
537
        } else {
538
            $ec = 'PEAR_Error';
539
        }
540
        if ($skipmsg) {
541
            return new $ec($code, $mode, $options, $userinfo);
542
        } else {
543
            return new $ec($message, $code, $mode, $options, $userinfo);
544
        }
545
    }
546

    
547
    // }}}
548
    // {{{ throwError()
549

    
550
    /**
551
     * Simpler form of raiseError with fewer options.  In most cases
552
     * message, code and userinfo are enough.
553
     *
554
     * @param string $message
555
     *
556
     */
557
    function throwError($message = null,
558
                         $code = null,
559
                         $userinfo = null)
560
    {
561
        if (isset($this) && is_a($this, 'PEAR')) {
562
            return $this->raiseError($message, $code, null, null, $userinfo);
563
        } else {
564
            return PEAR::raiseError($message, $code, null, null, $userinfo);
565
        }
566
    }
567

    
568
    // }}}
569
    function staticPushErrorHandling($mode, $options = null)
570
    {
571
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
572
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
573
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
574
        $stack[] = array($def_mode, $def_options);
575
        switch ($mode) {
576
            case PEAR_ERROR_EXCEPTION:
577
            case PEAR_ERROR_RETURN:
578
            case PEAR_ERROR_PRINT:
579
            case PEAR_ERROR_TRIGGER:
580
            case PEAR_ERROR_DIE:
581
            case null:
582
                $def_mode = $mode;
583
                $def_options = $options;
584
                break;
585

    
586
            case PEAR_ERROR_CALLBACK:
587
                $def_mode = $mode;
588
                // class/object method callback
589
                if (is_callable($options)) {
590
                    $def_options = $options;
591
                } else {
592
                    trigger_error("invalid error callback", E_USER_WARNING);
593
                }
594
                break;
595

    
596
            default:
597
                trigger_error("invalid error mode", E_USER_WARNING);
598
                break;
599
        }
600
        $stack[] = array($mode, $options);
601
        return true;
602
    }
603

    
604
    function staticPopErrorHandling()
605
    {
606
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
607
        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
608
        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
609
        array_pop($stack);
610
        list($mode, $options) = $stack[sizeof($stack) - 1];
611
        array_pop($stack);
612
        switch ($mode) {
613
            case PEAR_ERROR_EXCEPTION:
614
            case PEAR_ERROR_RETURN:
615
            case PEAR_ERROR_PRINT:
616
            case PEAR_ERROR_TRIGGER:
617
            case PEAR_ERROR_DIE:
618
            case null:
619
                $setmode = $mode;
620
                $setoptions = $options;
621
                break;
622

    
623
            case PEAR_ERROR_CALLBACK:
624
                $setmode = $mode;
625
                // class/object method callback
626
                if (is_callable($options)) {
627
                    $setoptions = $options;
628
                } else {
629
                    trigger_error("invalid error callback", E_USER_WARNING);
630
                }
631
                break;
632

    
633
            default:
634
                trigger_error("invalid error mode", E_USER_WARNING);
635
                break;
636
        }
637
        return true;
638
    }
639

    
640
    // {{{ pushErrorHandling()
641

    
642
    /**
643
     * Push a new error handler on top of the error handler options stack. With this
644
     * you can easily override the actual error handler for some code and restore
645
     * it later with popErrorHandling.
646
     *
647
     * @param mixed $mode (same as setErrorHandling)
648
     * @param mixed $options (same as setErrorHandling)
649
     *
650
     * @return bool Always true
651
     *
652
     * @see PEAR::setErrorHandling
653
     */
654
    function pushErrorHandling($mode, $options = null)
655
    {
656
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
657
        if (isset($this) && is_a($this, 'PEAR')) {
658
            $def_mode    = &$this->_default_error_mode;
659
            $def_options = &$this->_default_error_options;
660
        } else {
661
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
662
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
663
        }
664
        $stack[] = array($def_mode, $def_options);
665

    
666
        if (isset($this) && is_a($this, 'PEAR')) {
667
            $this->setErrorHandling($mode, $options);
668
        } else {
669
            PEAR::setErrorHandling($mode, $options);
670
        }
671
        $stack[] = array($mode, $options);
672
        return true;
673
    }
674

    
675
    // }}}
676
    // {{{ popErrorHandling()
677

    
678
    /**
679
    * Pop the last error handler used
680
    *
681
    * @return bool Always true
682
    *
683
    * @see PEAR::pushErrorHandling
684
    */
685
    function popErrorHandling()
686
    {
687
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
688
        array_pop($stack);
689
        list($mode, $options) = $stack[sizeof($stack) - 1];
690
        array_pop($stack);
691
        if (isset($this) && is_a($this, 'PEAR')) {
692
            $this->setErrorHandling($mode, $options);
693
        } else {
694
            PEAR::setErrorHandling($mode, $options);
695
        }
696
        return true;
697
    }
698

    
699
    // }}}
700
    // {{{ loadExtension()
701

    
702
    /**
703
    * OS independant PHP extension load. Remember to take care
704
    * on the correct extension name for case sensitive OSes.
705
    *
706
    * @param string $ext The extension name
707
    * @return bool Success or not on the dl() call
708
    */
709
    function loadExtension($ext)
710
    {
711
        if (!extension_loaded($ext)) {
712
            // if either returns true dl() will produce a FATAL error, stop that
713
            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
714
                return false;
715
            }
716
            if (OS_WINDOWS) {
717
                $suffix = '.dll';
718
            } elseif (PHP_OS == 'HP-UX') {
719
                $suffix = '.sl';
720
            } elseif (PHP_OS == 'AIX') {
721
                $suffix = '.a';
722
            } elseif (PHP_OS == 'OSX') {
723
                $suffix = '.bundle';
724
            } else {
725
                $suffix = '.so';
726
            }
727
            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
728
        }
729
        return true;
730
    }
731

    
732
    // }}}
733
}
734

    
735
// {{{ _PEAR_call_destructors()
736

    
737
function _PEAR_call_destructors()
738
{
739
    global $_PEAR_destructor_object_list;
740
    if (is_array($_PEAR_destructor_object_list) &&
741
        sizeof($_PEAR_destructor_object_list))
742
    {
743
        reset($_PEAR_destructor_object_list);
744
        if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) {
745
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
746
        }
747
        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
748
            $classname = get_class($objref);
749
            while ($classname) {
750
                $destructor = "_$classname";
751
                if (method_exists($objref, $destructor)) {
752
                    $objref->$destructor();
753
                    break;
754
                } else {
755
                    $classname = get_parent_class($classname);
756
                }
757
            }
758
        }
759
        // Empty the object list to ensure that destructors are
760
        // not called more than once.
761
        $_PEAR_destructor_object_list = array();
762
    }
763

    
764
    // Now call the shutdown functions
765
    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
766
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
767
            call_user_func_array($value[0], $value[1]);
768
        }
769
    }
770
}
771

    
772
// }}}
773

    
774
class PEAR_Error
775
{
776
    // {{{ properties
777

    
778
    var $error_message_prefix = '';
779
    var $mode                 = PEAR_ERROR_RETURN;
780
    var $level                = E_USER_NOTICE;
781
    var $code                 = -1;
782
    var $message              = '';
783
    var $userinfo             = '';
784
    var $backtrace            = null;
785

    
786
    // }}}
787
    // {{{ constructor
788

    
789
    /**
790
     * PEAR_Error constructor
791
     *
792
     * @param string $message  message
793
     *
794
     * @param int $code     (optional) error code
795
     *
796
     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
797
     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
798
     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
799
     *
800
     * @param mixed $options   (optional) error level, _OR_ in the case of
801
     * PEAR_ERROR_CALLBACK, the callback function or object/method
802
     * tuple.
803
     *
804
     * @param string $userinfo (optional) additional user/debug info
805
     *
806
     * @access public
807
     *
808
     */
809
    function PEAR_Error($message = 'unknown error', $code = null,
810
                        $mode = null, $options = null, $userinfo = null)
811
    {
812
        if ($mode === null) {
813
            $mode = PEAR_ERROR_RETURN;
814
        }
815
        $this->message   = $message;
816
        $this->code      = $code;
817
        $this->mode      = $mode;
818
        $this->userinfo  = $userinfo;
819
        if (function_exists("debug_backtrace")) {
820
            if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
821
                $this->backtrace = debug_backtrace();
822
            }
823
        }
824
        if ($mode & PEAR_ERROR_CALLBACK) {
825
            $this->level = E_USER_NOTICE;
826
            $this->callback = $options;
827
        } else {
828
            if ($options === null) {
829
                $options = E_USER_NOTICE;
830
            }
831
            $this->level = $options;
832
            $this->callback = null;
833
        }
834
        if ($this->mode & PEAR_ERROR_PRINT) {
835
            if (is_null($options) || is_int($options)) {
836
                $format = "%s";
837
            } else {
838
                $format = $options;
839
            }
840
            printf($format, $this->getMessage());
841
        }
842
        if ($this->mode & PEAR_ERROR_TRIGGER) {
843
            trigger_error($this->getMessage(), $this->level);
844
        }
845
        if ($this->mode & PEAR_ERROR_DIE) {
846
            $msg = $this->getMessage();
847
            if (is_null($options) || is_int($options)) {
848
                $format = "%s";
849
                if (substr($msg, -1) != "\n") {
850
                    $msg .= "\n";
851
                }
852
            } else {
853
                $format = $options;
854
            }
855
            die(sprintf($format, $msg));
856
        }
857
        if ($this->mode & PEAR_ERROR_CALLBACK) {
858
            if (is_callable($this->callback)) {
859
                call_user_func($this->callback, $this);
860
            }
861
        }
862
        if ($this->mode & PEAR_ERROR_EXCEPTION) {
863
            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_ErrorStack for exceptions", E_USER_WARNING);
864
            eval('$e = new Exception($this->message, $this->code);$e->PEAR_Error = $this;throw($e);');
865
        }
866
    }
867

    
868
    // }}}
869
    // {{{ getMode()
870

    
871
    /**
872
     * Get the error mode from an error object.
873
     *
874
     * @return int error mode
875
     * @access public
876
     */
877
    function getMode() {
878
        return $this->mode;
879
    }
880

    
881
    // }}}
882
    // {{{ getCallback()
883

    
884
    /**
885
     * Get the callback function/method from an error object.
886
     *
887
     * @return mixed callback function or object/method array
888
     * @access public
889
     */
890
    function getCallback() {
891
        return $this->callback;
892
    }
893

    
894
    // }}}
895
    // {{{ getMessage()
896

    
897

    
898
    /**
899
     * Get the error message from an error object.
900
     *
901
     * @return  string  full error message
902
     * @access public
903
     */
904
    function getMessage()
905
    {
906
        return ($this->error_message_prefix . $this->message);
907
    }
908

    
909

    
910
    // }}}
911
    // {{{ getCode()
912

    
913
    /**
914
     * Get error code from an error object
915
     *
916
     * @return int error code
917
     * @access public
918
     */
919
     function getCode()
920
     {
921
        return $this->code;
922
     }
923

    
924
    // }}}
925
    // {{{ getType()
926

    
927
    /**
928
     * Get the name of this error/exception.
929
     *
930
     * @return string error/exception name (type)
931
     * @access public
932
     */
933
    function getType()
934
    {
935
        return get_class($this);
936
    }
937

    
938
    // }}}
939
    // {{{ getUserInfo()
940

    
941
    /**
942
     * Get additional user-supplied information.
943
     *
944
     * @return string user-supplied information
945
     * @access public
946
     */
947
    function getUserInfo()
948
    {
949
        return $this->userinfo;
950
    }
951

    
952
    // }}}
953
    // {{{ getDebugInfo()
954

    
955
    /**
956
     * Get additional debug information supplied by the application.
957
     *
958
     * @return string debug information
959
     * @access public
960
     */
961
    function getDebugInfo()
962
    {
963
        return $this->getUserInfo();
964
    }
965

    
966
    // }}}
967
    // {{{ getBacktrace()
968

    
969
    /**
970
     * Get the call backtrace from where the error was generated.
971
     * Supported with PHP 4.3.0 or newer.
972
     *
973
     * @param int $frame (optional) what frame to fetch
974
     * @return array Backtrace, or NULL if not available.
975
     * @access public
976
     */
977
    function getBacktrace($frame = null)
978
    {
979
        if ($frame === null) {
980
            return $this->backtrace;
981
        }
982
        return $this->backtrace[$frame];
983
    }
984

    
985
    // }}}
986
    // {{{ addUserInfo()
987

    
988
    function addUserInfo($info)
989
    {
990
        if (empty($this->userinfo)) {
991
            $this->userinfo = $info;
992
        } else {
993
            $this->userinfo .= " ** $info";
994
        }
995
    }
996

    
997
    // }}}
998
    // {{{ toString()
999

    
1000
    /**
1001
     * Make a string representation of this object.
1002
     *
1003
     * @return string a string with an object summary
1004
     * @access public
1005
     */
1006
    function toString() {
1007
        $modes = array();
1008
        $levels = array(E_USER_NOTICE  => 'notice',
1009
                        E_USER_WARNING => 'warning',
1010
                        E_USER_ERROR   => 'error');
1011
        if ($this->mode & PEAR_ERROR_CALLBACK) {
1012
            if (is_array($this->callback)) {
1013
                $callback = (is_object($this->callback[0]) ?
1014
                    strtolower(get_class($this->callback[0])) :
1015
                    $this->callback[0]) . '::' .
1016
                    $this->callback[1];
1017
            } else {
1018
                $callback = $this->callback;
1019
            }
1020
            return sprintf('[%s: message="%s" code=%d mode=callback '.
1021
                           'callback=%s prefix="%s" info="%s"]',
1022
                           strtolower(get_class($this)), $this->message, $this->code,
1023
                           $callback, $this->error_message_prefix,
1024
                           $this->userinfo);
1025
        }
1026
        if ($this->mode & PEAR_ERROR_PRINT) {
1027
            $modes[] = 'print';
1028
        }
1029
        if ($this->mode & PEAR_ERROR_TRIGGER) {
1030
            $modes[] = 'trigger';
1031
        }
1032
        if ($this->mode & PEAR_ERROR_DIE) {
1033
            $modes[] = 'die';
1034
        }
1035
        if ($this->mode & PEAR_ERROR_RETURN) {
1036
            $modes[] = 'return';
1037
        }
1038
        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
1039
                       'prefix="%s" info="%s"]',
1040
                       strtolower(get_class($this)), $this->message, $this->code,
1041
                       implode("|", $modes), $levels[$this->level],
1042
                       $this->error_message_prefix,
1043
                       $this->userinfo);
1044
    }
1045

    
1046
    // }}}
1047
}
1048

    
1049
/*
1050
 * Local Variables:
1051
 * mode: php
1052
 * tab-width: 4
1053
 * c-basic-offset: 4
1054
 * End:
1055
 */
1056
?>
(1-1/27)