Issues (992)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/pear/PEAR.php (4 issues)

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'] = [];
49
$GLOBALS['_PEAR_shutdown_funcs']         = [];
50
$GLOBALS['_PEAR_error_handler_stack']    = [];
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.12
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
     * Default error mode for this object.
95
     *
96
     * @var     int
97
     * @access  private
98
     */
99
    public $_default_error_mode = null;
100
    /**
101
     * Default error options used for this object when error mode
102
     * is PEAR_ERROR_TRIGGER.
103
     *
104
     * @var     int
105
     * @access  private
106
     */
107
    public $_default_error_options = null;
108
    /**
109
     * Default error handler (callback) for this object, if error mode is
110
     * PEAR_ERROR_CALLBACK.
111
     *
112
     * @var     string
113
     * @access  private
114
     */
115
    public $_default_error_handler = '';
116
    /**
117
     * Which class to use for error objects.
118
     *
119
     * @var     string
120
     * @access  private
121
     */
122
    public $_error_class = 'PEAR_Error';
123
    /**
124
     * An array of expected errors.
125
     *
126
     * @var     array
127
     * @access  private
128
     */
129
    public $_expected_errors = [];
130
    /**
131
     * List of methods that can be called both statically and non-statically.
132
     * @var array
133
     */
134
    protected static $bivalentMethods = [
135
        'setErrorHandling'  => true,
136
        'raiseError'        => true,
137
        'throwError'        => true,
138
        'pushErrorHandling' => true,
139
        'popErrorHandling'  => true,
140
    ];
141
142
    /**
143
     * Constructor.  Registers this object in
144
     * $_PEAR_destructor_object_list for destructor emulation if a
145
     * destructor object exists.
146
     *
147
     * @param string $error_class (optional) which class to use for
148
     *                            error objects, defaults to PEAR_Error.
149
     * @access public
150
     * @return void
151
     */
152
    public function __construct($error_class = null)
153
    {
154
        $classname = strtolower(get_class($this));
155
        if ($this->_debug) {
156
            print "PEAR constructor called, class=$classname\n";
157
        }
158
159
        if (null !== $error_class) {
160
            $this->_error_class = $error_class;
161
        }
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
     * Only here for backwards compatibility.
181
     * E.g. Archive_Tar calls $this->PEAR() in its constructor.
182
     *
183
     * @param string $error_class Which class to use for error objects,
184
     *                            defaults to PEAR_Error.
185
     */
186
    public function PEAR($error_class = null)
187
    {
188
        self::__construct($error_class);
189
    }
190
191
    /**
192
     * Destructor (the emulated type of...).  Does nothing right now,
193
     * but is included for forward compatibility, so subclass
194
     * destructors should always call it.
195
     *
196
     * See the note in the class desciption about output from
197
     * destructors.
198
     *
199
     * @access public
200
     * @return void
201
     */
202
    public function _PEAR()
203
    {
204
        if ($this->_debug) {
205
            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
206
        }
207
    }
208
209
    public function __call($method, $arguments)
210
    {
211
        if (!isset(self::$bivalentMethods[$method])) {
212
            trigger_error(
213
                'Call to undefined method PEAR::' . $method . '()',
214
                E_USER_ERROR
215
            );
216
        }
217
        return call_user_func_array(
218
            [get_class(), '_' . $method],
219
            array_merge([$this], $arguments)
220
        );
221
    }
222
223
    public static function __callStatic($method, $arguments)
224
    {
225
        if (!isset(self::$bivalentMethods[$method])) {
226
            trigger_error(
227
                'Call to undefined method PEAR::' . $method . '()',
228
                E_USER_ERROR
229
            );
230
        }
231
        return call_user_func_array(
232
            [get_class(), '_' . $method],
233
            array_merge([null], $arguments)
234
        );
235
    }
236
237
    /**
238
     * If you have a class that's mostly/entirely static, and you need static
239
     * properties, you can use this method to simulate them. Eg. in your method(s)
240
     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
241
     * You MUST use a reference, or they will not persist!
242
     *
243
     * @param string $class The calling classname, to prevent clashes
244
     * @param string $var   The variable to retrieve.
245
     * @return mixed   A reference to the variable. If not set it will be
246
     *                      auto initialised to NULL.
247
     */
248
    public static function &getStaticProperty($class, $var)
249
    {
250
        static $properties;
251
        if (!isset($properties[$class])) {
252
            $properties[$class] = [];
253
        }
254
255
        if (!array_key_exists($var, $properties[$class])) {
256
            $properties[$class][$var] = null;
257
        }
258
259
        return $properties[$class][$var];
260
    }
261
262
    /**
263
     * Use this function to register a shutdown method for static
264
     * classes.
265
     *
266
     * @param mixed $func The function name (or array of class/method) to call
267
     * @param mixed $args The arguments to pass to the function
268
     *
269
     * @return void
270
     */
271
    public static function registerShutdownFunc($func, $args = [])
272
    {
273
        // if we are called statically, there is a potential
274
        // that no shutdown func is registered.  Bug #6445
275
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
276
            register_shutdown_function('_PEAR_call_destructors');
277
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
278
        }
279
        $GLOBALS['_PEAR_shutdown_funcs'][] = [$func, $args];
280
    }
281
282
    /**
283
     * Tell whether a value is a PEAR error.
284
     *
285
     * @param mixed $data     the value to test
286
     * @param int   $code     if $data is an error object, return true
287
     *                        only if $code is a string and
288
     *                        $obj->getMessage() == $code or
289
     *                        $code is an integer and $obj->getCode() == $code
290
     *
291
     * @return  bool    true if parameter is an error
292
     */
293
    public static function isError($data, $code = null)
294
    {
295
        if (!is_a($data, 'PEAR_Error')) {
296
            return false;
297
        }
298
299
        if (null === $code) {
300
            return true;
301
        } elseif (is_string($code)) {
302
            return $data->getMessage() == $code;
303
        }
304
305
        return $data->getCode() == $code;
306
    }
307
308
    /**
309
     * Sets how errors generated by this object should be handled.
310
     * Can be invoked both in objects and statically.  If called
311
     * statically, setErrorHandling sets the default behaviour for all
312
     * PEAR objects.  If called in an object, setErrorHandling sets
313
     * the default behaviour for that object.
314
     *
315
     * @param object $object
316
     *        Object the method was called on (non-static mode)
317
     *
318
     * @param int    $mode
319
     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
320
     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
321
     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
322
     *
323
     * @param mixed  $options
324
     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
325
     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
326
     *
327
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
328
     *        to be the callback function or method.  A callback
329
     *        function is a string with the name of the function, a
330
     *        callback method is an array of two elements: the element
331
     *        at index 0 is the object, and the element at index 1 is
332
     *        the name of the method to call in the object.
333
     *
334
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
335
     *        a printf format string used when printing the error
336
     *        message.
337
     *
338
     * @access public
339
     * @return void
340
     * @see    PEAR_ERROR_RETURN
341
     * @see    PEAR_ERROR_PRINT
342
     * @see    PEAR_ERROR_TRIGGER
343
     * @see    PEAR_ERROR_DIE
344
     * @see    PEAR_ERROR_CALLBACK
345
     * @see    PEAR_ERROR_EXCEPTION
346
     *
347
     * @since  PHP 4.0.5
348
     */
349
    protected static function _setErrorHandling(
350
        $object,
351
        $mode = null,
352
        $options = null
353
    ) {
354
        if (null !== $object) {
355
            $setmode    = &$object->_default_error_mode;
356
            $setoptions = &$object->_default_error_options;
357
        } else {
358
            $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
359
            $setoptions = &$GLOBALS['_PEAR_default_error_options'];
360
        }
361
362
        switch ($mode) {
363
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

363
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
364
            case PEAR_ERROR_RETURN:
365
            case PEAR_ERROR_PRINT:
366
            case PEAR_ERROR_TRIGGER:
367
            case PEAR_ERROR_DIE:
368
            case null:
369
                $setmode    = $mode;
370
                $setoptions = $options;
371
                break;
372
373
            case PEAR_ERROR_CALLBACK:
374
                $setmode = $mode;
375
                // class/object method callback
376
                if (is_callable($options)) {
377
                    $setoptions = $options;
378
                } else {
379
                    trigger_error('invalid error callback', E_USER_WARNING);
380
                }
381
                break;
382
383
            default:
384
                trigger_error('invalid error mode', E_USER_WARNING);
385
                break;
386
        }
387
    }
388
389
    /**
390
     * This method is used to tell which errors you expect to get.
391
     * Expected errors are always returned with error mode
392
     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
393
     * and this method pushes a new element onto it.  The list of
394
     * expected errors are in effect until they are popped off the
395
     * stack with the popExpect() method.
396
     *
397
     * Note that this method can not be called statically
398
     *
399
     * @param mixed $code a single error code or an array of error codes to expect
400
     *
401
     * @return int     the new depth of the "expected errors" stack
402
     * @access public
403
     */
404
    public function expectError($code = '*')
405
    {
406
        if (is_array($code)) {
407
            array_push($this->_expected_errors, $code);
408
        } else {
409
            array_push($this->_expected_errors, [$code]);
410
        }
411
        return count($this->_expected_errors);
412
    }
413
414
    /**
415
     * This method pops one element off the expected error codes
416
     * stack.
417
     *
418
     * @return array   the list of error codes that were popped
419
     */
420
    public function popExpect()
421
    {
422
        return array_pop($this->_expected_errors);
423
    }
424
425
    /**
426
     * This method checks unsets an error code if available
427
     *
428
     * @param mixed error code
429
     * @return bool true if the error code was unset, false otherwise
430
     * @access private
431
     * @since  PHP 4.3.0
432
     */
433
    public function _checkDelExpect($error_code)
434
    {
435
        $deleted = false;
436
        foreach ($this->_expected_errors as $key => $error_array) {
437
            if (in_array($error_code, $error_array)) {
438
                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
439
                $deleted = true;
440
            }
441
442
            // clean up empty arrays
443
            if (0 == count($this->_expected_errors[$key])) {
444
                unset($this->_expected_errors[$key]);
445
            }
446
        }
447
448
        return $deleted;
449
    }
450
451
    /**
452
     * This method deletes all occurrences of the specified element from
453
     * the expected error codes stack.
454
     *
455
     * @param mixed $error_code error code that should be deleted
456
     * @return mixed list of error codes that were deleted or error
457
     * @access public
458
     * @since  PHP 4.3.0
459
     */
460
    public function delExpect($error_code)
461
    {
462
        $deleted = false;
463
        if ((is_array($error_code) && (0 != count($error_code)))) {
464
            // $error_code is a non-empty array here; we walk through it trying
465
            // to unset all values
466
            foreach ($error_code as $key => $error) {
467
                $deleted = $this->_checkDelExpect($error) ? true : false;
468
            }
469
470
            return $deleted ? true : self::raiseError('The expected error you submitted does not exist'); // IMPROVE ME
471
        } elseif (!empty($error_code)) {
472
            // $error_code comes alone, trying to unset it
473
            if ($this->_checkDelExpect($error_code)) {
474
                return true;
475
            }
476
477
            return self::raiseError('The expected error you submitted does not exist'); // IMPROVE ME
478
        }
479
480
        // $error_code is empty
481
        return self::raiseError('The expected error you submitted is empty'); // IMPROVE ME
482
    }
483
484
    /**
485
     * This method is a wrapper that returns an instance of the
486
     * configured error class with this object's default error
487
     * handling applied.  If the $mode and $options parameters are not
488
     * specified, the object's defaults are used.
489
     *
490
     * @param mixed  $message     a text error message or a PEAR error object
491
     *
492
     * @param int    $code        a numeric error code (it is up to your class
493
     *                            to define these if you want to use codes)
494
     *
495
     * @param int    $mode        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
496
     *                            PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
497
     *                            PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
498
     *
499
     * @param mixed  $options     If $mode is PEAR_ERROR_TRIGGER, this parameter
500
     *                            specifies the PHP-internal error level (one of
501
     *                            E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
502
     *                            If $mode is PEAR_ERROR_CALLBACK, this
503
     *                            parameter specifies the callback function or
504
     *                            method.  In other error modes this parameter
505
     *                            is ignored.
506
     *
507
     * @param string $userinfo    If you need to pass along for example debug
508
     *                            information, this parameter is meant for that.
509
     *
510
     * @param string $error_class The returned error object will be
511
     *                            instantiated from this class, if specified.
512
     *
513
     * @param bool   $skipmsg     If true, raiseError will only pass error codes,
514
     *                            the error message parameter will be dropped.
515
     *
516
     * @return object   a PEAR error object
517
     * @see   PEAR::setErrorHandling
518
     * @since PHP 4.0.5
519
     */
520
    protected static function _raiseError(
521
        $object,
522
        $message = null,
523
        $code = null,
524
        $mode = null,
525
        $options = null,
526
        $userinfo = null,
527
        $error_class = null,
528
        $skipmsg = false
529
    ) {
530
        // The error is yet a PEAR error object
531
        if (is_object($message)) {
532
            $code                          = $message->getCode();
533
            $userinfo                      = $message->getUserInfo();
534
            $error_class                   = $message->getType();
535
            $message->error_message_prefix = '';
536
            $message                       = $message->getMessage();
537
        }
538
539
        if (null !== $object
540
            && isset($object->_expected_errors)
541
            && count($object->_expected_errors) > 0
542
            && count($exp = end($object->_expected_errors))) {
543
            if ('*' === $exp[0]
544
                || (is_int(reset($exp)) && in_array($code, $exp))
545
                || (is_string(reset($exp)) && in_array($message, $exp))) {
546
                $mode = PEAR_ERROR_RETURN;
547
            }
548
        }
549
550
        // No mode given, try global ones
551
        if (null === $mode) {
552
            // Class error handler
553
            if (null !== $object && isset($object->_default_error_mode)) {
554
                $mode    = $object->_default_error_mode;
555
                $options = $object->_default_error_options;
556
                // Global error handler
557
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
558
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
559
                $options = $GLOBALS['_PEAR_default_error_options'];
560
            }
561
        }
562
563
        if (null !== $error_class) {
564
            $ec = $error_class;
565
        } elseif (null !== $object && isset($object->_error_class)) {
566
            $ec = $object->_error_class;
567
        } else {
568
            $ec = 'PEAR_Error';
569
        }
570
571
        if ($skipmsg) {
572
            $a = new $ec($code, $mode, $options, $userinfo);
573
        } else {
574
            $a = new $ec($message, $code, $mode, $options, $userinfo);
575
        }
576
577
        return $a;
578
    }
579
580
    /**
581
     * Simpler form of raiseError with fewer options.  In most cases
582
     * message, code and userinfo are enough.
583
     *
584
     * @param mixed  $message  a text error message or a PEAR error object
585
     *
586
     * @param int    $code     a numeric error code (it is up to your class
587
     *                         to define these if you want to use codes)
588
     *
589
     * @param string $userinfo If you need to pass along for example debug
590
     *                         information, this parameter is meant for that.
591
     *
592
     * @return object   a PEAR error object
593
     * @see PEAR::raiseError
594
     */
595
    protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
596
    {
597
        if (null !== $object) {
598
            $a = $object->raiseError($message, $code, null, null, $userinfo);
599
            return $a;
600
        }
601
602
        $a = self::raiseError($message, $code, null, null, $userinfo);
603
        return $a;
604
    }
605
606
    public static function staticPushErrorHandling($mode, $options = null)
607
    {
608
        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
609
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
610
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
611
        $stack[]     = [$def_mode, $def_options];
612
        switch ($mode) {
613
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

613
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
614
            case PEAR_ERROR_RETURN:
615
            case PEAR_ERROR_PRINT:
616
            case PEAR_ERROR_TRIGGER:
617
            case PEAR_ERROR_DIE:
618
            case null:
619
                $def_mode    = $mode;
620
                $def_options = $options;
621
                break;
622
623
            case PEAR_ERROR_CALLBACK:
624
                $def_mode = $mode;
625
                // class/object method callback
626
                if (is_callable($options)) {
627
                    $def_options = $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
        $stack[] = [$mode, $options];
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
        [$mode, $options] = $stack[count($stack) - 1];
648
        array_pop($stack);
649
        switch ($mode) {
650
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

650
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
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
        return true;
675
    }
676
677
    /**
678
     * Push a new error handler on top of the error handler options stack. With this
679
     * you can easily override the actual error handler for some code and restore
680
     * it later with popErrorHandling.
681
     *
682
     * @param mixed $mode    (same as setErrorHandling)
683
     * @param mixed $options (same as setErrorHandling)
684
     *
685
     * @return bool Always true
686
     *
687
     * @see PEAR::setErrorHandling
688
     */
689
    protected static function _pushErrorHandling($object, $mode, $options = null)
690
    {
691
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
692
        if (null !== $object) {
693
            $def_mode    = &$object->_default_error_mode;
694
            $def_options = &$object->_default_error_options;
695
        } else {
696
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
697
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
698
        }
699
        $stack[] = [$def_mode, $def_options];
700
701
        if (null !== $object) {
702
            $object->setErrorHandling($mode, $options);
703
        } else {
704
            self::setErrorHandling($mode, $options);
705
        }
706
        $stack[] = [$mode, $options];
707
        return true;
708
    }
709
710
    /**
711
     * Pop the last error handler used
712
     *
713
     * @return bool Always true
714
     *
715
     * @see PEAR::pushErrorHandling
716
     */
717
    protected static function _popErrorHandling($object)
718
    {
719
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
720
        array_pop($stack);
721
        [$mode, $options] = $stack[count($stack) - 1];
722
        array_pop($stack);
723
        if (null !== $object) {
724
            $object->setErrorHandling($mode, $options);
725
        } else {
726
            self::setErrorHandling($mode, $options);
727
        }
728
        return true;
729
    }
730
731
    /**
732
     * OS independent PHP extension load. Remember to take care
733
     * on the correct extension name for case sensitive OSes.
734
     *
735
     * @param string $ext The extension name
736
     * @return bool Success or not on the dl() call
737
     */
738
    public static function loadExtension($ext)
739
    {
740
        if (extension_loaded($ext)) {
741
            return true;
742
        }
743
744
        // if either returns true dl() will produce a FATAL error, stop that
745
        if (false === function_exists('dl')
746
            || 1 != ini_get('enable_dl')) {
747
            return false;
748
        }
749
750
        if (OS_WINDOWS) {
751
            $suffix = '.dll';
752
        } elseif (PHP_OS == 'HP-UX') {
753
            $suffix = '.sl';
754
        } elseif (PHP_OS == 'AIX') {
755
            $suffix = '.a';
756
        } elseif (PHP_OS == 'OSX') {
757
            $suffix = '.bundle';
758
        } else {
759
            $suffix = '.so';
760
        }
761
762
        return @dl('php_' . $ext . $suffix) || @dl($ext . $suffix);
763
    }
764
765
    /**
766
     * Get SOURCE_DATE_EPOCH environment variable
767
     * See https://reproducible-builds.org/specs/source-date-epoch/
768
     *
769
     * @return int
770
     * @access public
771
     */
772
    public static function getSourceDateEpoch()
773
    {
774
        if ($source_date_epoch = getenv('SOURCE_DATE_EPOCH')) {
775
            if (preg_match('/^\d+$/', $source_date_epoch)) {
776
                return (int)$source_date_epoch;
777
            } else {
778
                //  "If the value is malformed, the build process SHOULD exit with a non-zero error code."
779
                self::raiseError("Invalid SOURCE_DATE_EPOCH: $source_date_epoch");
780
                exit(1);
781
            }
782
        } else {
783
            return time();
784
        }
785
    }
786
}
787
788
function _PEAR_call_destructors()
789
{
790
    global $_PEAR_destructor_object_list;
791
    if (is_array($_PEAR_destructor_object_list)
792
        && count($_PEAR_destructor_object_list)) {
793
        reset($_PEAR_destructor_object_list);
794
795
        $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
796
797
        if ($destructLifoExists) {
798
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
799
        }
800
801
        foreach ($_PEAR_destructor_object_list as $k => $objref) {
802
            $classname = get_class($objref);
803
            while ($classname) {
804
                $destructor = "_$classname";
805
                if (method_exists($objref, $destructor)) {
806
                    $objref->$destructor();
807
                    break;
808
                } else {
809
                    $classname = get_parent_class($classname);
810
                }
811
            }
812
        }
813
        // Empty the object list to ensure that destructors are
814
        // not called more than once.
815
        $_PEAR_destructor_object_list = [];
816
    }
817
818
    // Now call the shutdown functions
819
    if (isset($GLOBALS['_PEAR_shutdown_funcs'])
820
        && is_array($GLOBALS['_PEAR_shutdown_funcs'])
821
        && !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
822
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
823
            call_user_func_array($value[0], $value[1]);
824
        }
825
    }
826
}
827
828
/**
829
 * Standard PEAR error class for PHP 4
830
 *
831
 * This class is supserseded by {@link PEAR_Exception} in PHP 5
832
 *
833
 * @category   pear
834
 * @package    PEAR
835
 * @author     Stig Bakken <[email protected]>
836
 * @author     Tomas V.V. Cox <[email protected]>
837
 * @author     Gregory Beaver <[email protected]>
838
 * @copyright  1997-2006 The PHP Group
839
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
840
 * @version    Release: 1.10.12
841
 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
842
 * @see        PEAR::raiseError(), PEAR::throwError()
843
 * @since      Class available since PHP 4.0.2
844
 */
845
class PEAR_Error
846
{
847
    public $error_message_prefix = '';
848
    public $mode                 = PEAR_ERROR_RETURN;
849
    public $level                = E_USER_NOTICE;
850
    public $code                 = -1;
851
    public $message              = '';
852
    public $userinfo             = '';
853
    public $backtrace            = null;
854
855
    /**
856
     * PEAR_Error constructor
857
     *
858
     * @param string $message  message
859
     *
860
     * @param int    $code     (optional) error code
861
     *
862
     * @param int    $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
863
     *                         PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
864
     *                         PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
865
     *
866
     * @param mixed  $options  (optional) error level, _OR_ in the case of
867
     *                         PEAR_ERROR_CALLBACK, the callback function or object/method
868
     *                         tuple.
869
     *
870
     * @param string $userinfo (optional) additional user/debug info
871
     *
872
     * @access public
873
     *
874
     */
875
    public function __construct(
876
        $message = 'unknown error',
877
        $code = null,
878
        $mode = null,
879
        $options = null,
880
        $userinfo = null
881
    ) {
882
        if (null === $mode) {
883
            $mode = PEAR_ERROR_RETURN;
884
        }
885
        $this->message  = $message;
886
        $this->code     = $code;
887
        $this->mode     = $mode;
888
        $this->userinfo = $userinfo;
889
890
        $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
891
892
        if (!$skiptrace) {
893
            $this->backtrace = debug_backtrace();
894
            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
895
                unset($this->backtrace[0]['object']);
896
            }
897
        }
898
899
        if ($mode & PEAR_ERROR_CALLBACK) {
900
            $this->level    = E_USER_NOTICE;
901
            $this->callback = $options;
902
        } else {
903
            if (null === $options) {
904
                $options = E_USER_NOTICE;
905
            }
906
907
            $this->level    = $options;
908
            $this->callback = null;
909
        }
910
911
        if ($this->mode & PEAR_ERROR_PRINT) {
912
            if (null === $options || is_int($options)) {
913
                $format = '%s';
914
            } else {
915
                $format = $options;
916
            }
917
918
            printf($format, $this->getMessage());
919
        }
920
921
        if ($this->mode & PEAR_ERROR_TRIGGER) {
922
            trigger_error($this->getMessage(), $this->level);
923
        }
924
925
        if ($this->mode & PEAR_ERROR_DIE) {
926
            $msg = $this->getMessage();
927
            if (null === $options || is_int($options)) {
928
                $format = '%s';
929
                if ("\n" != substr($msg, -1)) {
930
                    $msg .= "\n";
931
                }
932
            } else {
933
                $format = $options;
934
            }
935
            printf($format, $msg);
936
            exit($code);
937
        }
938
939
        if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
940
            call_user_func($this->callback, $this);
941
        }
942
943
        if ($this->mode & PEAR_ERROR_EXCEPTION) {
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

943
        if ($this->mode & /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION) {
Loading history...
944
            trigger_error('PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions', E_USER_WARNING);
945
            eval('$e = new Exception($this->message, $this->code);throw($e);');
946
        }
947
    }
948
949
    /**
950
     * Only here for backwards compatibility.
951
     *
952
     * Class "Cache_Error" still uses it, among others.
953
     *
954
     * @param string $message  Message
955
     * @param int    $code     Error code
956
     * @param int    $mode     Error mode
957
     * @param mixed  $options  See __construct()
958
     * @param string $userinfo Additional user/debug info
959
     */
960
    public function PEAR_Error(
961
        $message = 'unknown error',
962
        $code = null,
963
        $mode = null,
964
        $options = null,
965
        $userinfo = null
966
    ) {
967
        self::__construct($message, $code, $mode, $options, $userinfo);
968
    }
969
970
    /**
971
     * Get the error mode from an error object.
972
     *
973
     * @return int error mode
974
     * @access public
975
     */
976
    public function getMode()
977
    {
978
        return $this->mode;
979
    }
980
981
    /**
982
     * Get the callback function/method from an error object.
983
     *
984
     * @return mixed callback function or object/method array
985
     * @access public
986
     */
987
    public function getCallback()
988
    {
989
        return $this->callback;
990
    }
991
992
    /**
993
     * Get the error message from an error object.
994
     *
995
     * @return  string  full error message
996
     * @access public
997
     */
998
    public function getMessage()
999
    {
1000
        return ($this->error_message_prefix . $this->message);
1001
    }
1002
1003
    /**
1004
     * Get error code from an error object
1005
     *
1006
     * @return int error code
1007
     * @access public
1008
     */
1009
    public function getCode()
1010
    {
1011
        return $this->code;
1012
    }
1013
1014
    /**
1015
     * Get the name of this error/exception.
1016
     *
1017
     * @return string error/exception name (type)
1018
     * @access public
1019
     */
1020
    public function getType()
1021
    {
1022
        return get_class($this);
1023
    }
1024
1025
    /**
1026
     * Get additional user-supplied information.
1027
     *
1028
     * @return string user-supplied information
1029
     * @access public
1030
     */
1031
    public function getUserInfo()
1032
    {
1033
        return $this->userinfo;
1034
    }
1035
1036
    /**
1037
     * Get additional debug information supplied by the application.
1038
     *
1039
     * @return string debug information
1040
     * @access public
1041
     */
1042
    public function getDebugInfo()
1043
    {
1044
        return $this->getUserInfo();
1045
    }
1046
1047
    /**
1048
     * Get the call backtrace from where the error was generated.
1049
     * Supported with PHP 4.3.0 or newer.
1050
     *
1051
     * @param int $frame (optional) what frame to fetch
1052
     * @return array Backtrace, or NULL if not available.
1053
     * @access public
1054
     */
1055
    public function getBacktrace($frame = null)
1056
    {
1057
        if (defined('PEAR_IGNORE_BACKTRACE')) {
1058
            return null;
1059
        }
1060
        if (null === $frame) {
1061
            return $this->backtrace;
1062
        }
1063
        return $this->backtrace[$frame];
1064
    }
1065
1066
    public function addUserInfo($info)
1067
    {
1068
        if (empty($this->userinfo)) {
1069
            $this->userinfo = $info;
1070
        } else {
1071
            $this->userinfo .= " ** $info";
1072
        }
1073
    }
1074
1075
    public function __toString()
1076
    {
1077
        return $this->getMessage();
1078
    }
1079
1080
    /**
1081
     * Make a string representation of this object.
1082
     *
1083
     * @return string a string with an object summary
1084
     * @access public
1085
     */
1086
    public function toString()
1087
    {
1088
        $modes  = [];
1089
        $levels = [
1090
            E_USER_NOTICE  => 'notice',
1091
            E_USER_WARNING => 'warning',
1092
            E_USER_ERROR   => 'error',
1093
        ];
1094
        if ($this->mode & PEAR_ERROR_CALLBACK) {
1095
            if (is_array($this->callback)) {
1096
                $callback = (is_object($this->callback[0]) ? strtolower(get_class($this->callback[0])) : $this->callback[0]) . '::' . $this->callback[1];
1097
            } else {
1098
                $callback = $this->callback;
1099
            }
1100
            return sprintf(
1101
                '[%s: message="%s" code=%d mode=callback ' . 'callback=%s prefix="%s" info="%s"]',
1102
                strtolower(get_class($this)),
1103
                $this->message,
1104
                $this->code,
1105
                $callback,
1106
                $this->error_message_prefix,
1107
                $this->userinfo
1108
            );
1109
        }
1110
        if ($this->mode & PEAR_ERROR_PRINT) {
1111
            $modes[] = 'print';
1112
        }
1113
        if ($this->mode & PEAR_ERROR_TRIGGER) {
1114
            $modes[] = 'trigger';
1115
        }
1116
        if ($this->mode & PEAR_ERROR_DIE) {
1117
            $modes[] = 'die';
1118
        }
1119
        if ($this->mode & PEAR_ERROR_RETURN) {
1120
            $modes[] = 'return';
1121
        }
1122
        return sprintf(
1123
            '[%s: message="%s" code=%d mode=%s level=%s ' . 'prefix="%s" info="%s"]',
1124
            strtolower(get_class($this)),
1125
            $this->message,
1126
            $this->code,
1127
            implode('|', $modes),
1128
            $levels[$this->level],
1129
            $this->error_message_prefix,
1130
            $this->userinfo
1131
        );
1132
    }
1133
}
1134
1135
/*
1136
 * Local Variables:
1137
 * mode: php
1138
 * tab-width: 4
1139
 * c-basic-offset: 4
1140
 * End:
1141
 */
1142