Issues (1844)

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 (29 issues)

1
<?php
2
//
3
// +----------------------------------------------------------------------+
4
// | PEAR, the PHP Extension and Application Repository                   |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2004 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.0 of the PHP license,       |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available through the world-wide-web at the following url:           |
11
// | https://www.php.net/license/3_0.txt.                                  |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | [email protected] so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Authors: Sterling Hughes <[email protected]>                          |
17
// |          Stig Bakken <[email protected]>                                   |
18
// |          Tomas V.V.Cox <[email protected]>                             |
19
// +----------------------------------------------------------------------+
20
//
21
//
22
23
define('PEAR_ERROR_RETURN', 1);
24
define('PEAR_ERROR_PRINT', 2);
25
define('PEAR_ERROR_TRIGGER', 4);
26
define('PEAR_ERROR_DIE', 8);
27
define('PEAR_ERROR_CALLBACK', 16);
28
/**
29
 * WARNING: obsolete
30
 * @deprecated
31
 */
32
define('PEAR_ERROR_EXCEPTION', 32);
33
define(
34
    'PEAR_ZE2',
35
    function_exists('version_compare')
36
    && version_compare(zend_version(), '2-dev', 'ge')
37
);
38
39
if (0 === mb_strpos(PHP_OS, 'WIN')) {
40
    define('OS_WINDOWS', true);
41
    define('OS_UNIX', false);
42
    define('PEAR_OS', 'Windows');
43
} else {
44
    define('OS_WINDOWS', false);
45
    define('OS_UNIX', true);
46
    define('PEAR_OS', 'Unix'); // blatant assumption
47
}
48
49
// instant backwards compatibility
50
if (!defined('PATH_SEPARATOR')) {
51
    if (OS_WINDOWS) {
52
        define('PATH_SEPARATOR', ';');
53
    } else {
54
        define('PATH_SEPARATOR', ':');
55
    }
56
}
57
58
$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
59
$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
60
$GLOBALS['_PEAR_destructor_object_list'] = [];
61
$GLOBALS['_PEAR_shutdown_funcs']         = [];
62
$GLOBALS['_PEAR_errorHandler_stack']     = [];
63
64
ini_set('track_errors', true);
0 ignored issues
show
true of type true is incompatible with the type string expected by parameter $value of ini_set(). ( Ignorable by Annotation )

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

64
ini_set('track_errors', /** @scrutinizer ignore-type */ true);
Loading history...
65
66
/**
67
 * Base class for other PEAR classes.  Provides rudimentary
68
 * emulation of destructors.
69
 *
70
 * If you want a destructor in your class, inherit PEAR and make a
71
 * destructor method called _yourclassname (same name as the
72
 * constructor, but with a "_" prefix).  Also, in your constructor you
73
 * have to call the PEAR constructor: $this->PEAR();.
74
 * The destructor method will be called without parameters.  Note that
75
 * at in some SAPI implementations (such as Apache), any output during
76
 * the request shutdown (in which destructors are called) seems to be
77
 * discarded.  If you need to get any debug information from your
78
 * destructor, use error_log(), syslog() or something similar.
79
 *
80
 * IMPORTANT! To use the emulated destructors you need to create the
81
 * objects by reference: $obj = new PEAR_child;
82
 *
83
 * @since  PHP 4.0.2
84
 * @author Stig Bakken <[email protected]>
85
 * @see    https://pear.php.net/manual/
86
 */
87
class PEAR
88
{
89
    // {{{ properties
90
    /**
91
     * Whether to enable internal debug messages.
92
     *
93
     * @var bool
94
     */
95
    public $_debug = false;
96
    /**
97
     * Default error mode for this object.
98
     *
99
     * @var int
100
     */
101
    public $_default_error_mode = null;
102
    /**
103
     * Default error options used for this object when error mode
104
     * is PEAR_ERROR_TRIGGER.
105
     *
106
     * @var int
107
     */
108
    public $_default_error_options = null;
109
    /**
110
     * Default error handler (callback) for this object, if error mode is
111
     * PEAR_ERROR_CALLBACK.
112
     *
113
     * @var string
114
     */
115
    public $_default_errorHandler = '';
116
    /**
117
     * Which class to use for error objects.
118
     *
119
     * @var string
120
     */
121
    public $_error_class = 'PEAR_Error';
122
    /**
123
     * An array of expected errors.
124
     *
125
     * @var array
126
     */
127
    public $_expected_errors = [];
128
    // }}}
129
130
    // {{{ constructor
131
132
    /**
133
     * Constructor.  Registers this object in
134
     * $_PEAR_destructor_object_list for destructor emulation if a
135
     * destructor object exists.
136
     *
137
     * @param null $error_class    (optional) which class to use for
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $error_class is correct as it would always require null to be passed?
Loading history...
138
     *                             error objects, defaults to PEAR_Error.
139
     */
140
    public function __construct($error_class = null)
141
    {
142
        $classname = get_class($this);
143
        if ($this->_debug) {
144
            print "PEAR constructor called, class=$classname\n";
145
        }
146
        if (null !== $error_class) {
0 ignored issues
show
The condition null !== $error_class is always false.
Loading history...
147
            $this->_error_class = $error_class;
148
        }
149
        while ($classname) {
150
            $destructor = "_$classname";
151
            if (method_exists($this, $destructor)) {
152
                global $_PEAR_destructor_object_list;
153
                $_PEAR_destructor_object_list[] = &$this;
154
                break;
155
            }
156
            $classname = get_parent_class($classname);
157
        }
158
    }
159
160
    // }}}
161
    // {{{ destructor
162
163
    /**
164
     * Destructor (the emulated type of...).  Does nothing right now,
165
     * but is included for forward compatibility, so subclass
166
     * destructors should always call it.
167
     *
168
     * See the note in the class desciption about output from
169
     * destructors.
170
     */
171
    public function _PEAR(): void
172
    {
173
        if ($this->_debug) {
174
            printf("PEAR destructor called, class=%s\n", get_class($this));
175
        }
176
    }
177
178
    // }}}
179
    // {{{ getStaticProperty()
180
181
    /**
182
     * If you have a class that's mostly/entirely static, and you need static
183
     * properties, you can use this method to simulate them. Eg. in your method(s)
184
     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
185
     * You MUST use a reference, or they will not persist!
186
     *
187
     * @param string $class  The calling classname, to prevent clashes
188
     * @param string $var    The variable to retrieve.
189
     * @return mixed  A reference to the variable. If not set it will be
190
     *                       auto initialised to NULL.
191
     */
192
    public function &getStaticProperty(string $class, string $var)
193
    {
194
        static $properties;
195
196
        return $properties[$class][$var];
197
    }
198
199
    // }}}
200
    // {{{ registerShutdownFunc()
201
202
    /**
203
     * Use this function to register a shutdown method for static
204
     * classes.
205
     *
206
     * @param mixed $func The function name (or array of class/method) to call
207
     * @param mixed $args The arguments to pass to the function
208
     */
209
    public function registerShutdownFunc($func, $args = []): void
210
    {
211
        $GLOBALS['_PEAR_shutdown_funcs'][] = [$func, $args];
212
    }
213
214
    // }}}
215
    // {{{ isError()
216
217
    /**
218
     * Tell whether a value is a PEAR error.
219
     *
220
     * @param mixed $data  the value to test
221
     * @param null  $code  if $data is an error object, return true
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $code is correct as it would always require null to be passed?
Loading history...
222
     *                     only if $code is a string and
223
     *                     $obj->getMessage() == $code or
224
     *                     $code is an integer and $obj->getCode() == $code
225
     * @return bool  true if parameter is an error
226
     */
227
    public function isError($data, $code = null): bool
228
    {
229
        if (is_a($data, 'PEAR_Error')) {
230
            if (null === $code) {
0 ignored issues
show
The condition null === $code is always true.
Loading history...
231
                return true;
232
            } elseif (is_string($code)) {
233
                return $data->getMessage() == $code;
234
            }
235
236
            return $data->getCode() == $code;
237
        }
238
239
        return false;
240
    }
241
242
    // }}}
243
    // {{{ setErrorHandling()
244
245
    /**
246
     * Sets how errors generated by this object should be handled.
247
     * Can be invoked both in objects and statically.  If called
248
     * statically, setErrorHandling sets the default behaviour for all
249
     * PEAR objects.  If called in an object, setErrorHandling sets
250
     * the default behaviour for that object.
251
     *
252
     * @param null  $mode
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $mode is correct as it would always require null to be passed?
Loading history...
253
     *                       One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
254
     *                       PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
255
     *                       PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
256
     *
257
     * @param mixed $options
258
     *                       When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
259
     *                       of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
260
     *
261
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
262
     *        to be the callback function or method.  A callback
263
     *        function is a string with the name of the function, a
264
     *        callback method is an array of two elements: the element
265
     *        at index 0 is the object, and the element at index 1 is
266
     *        the name of the method to call in the object.
267
     *
268
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
269
     *        a printf format string used when printing the error
270
     *        message.
271
     *
272
     * @see    PEAR_ERROR_RETURN
273
     * @see    PEAR_ERROR_PRINT
274
     * @see    PEAR_ERROR_TRIGGER
275
     * @see    PEAR_ERROR_DIE
276
     * @see    PEAR_ERROR_CALLBACK
277
     * @see    PEAR_ERROR_EXCEPTION
278
     *
279
     * @since  PHP 4.0.5
280
     */
281
    public function setErrorHandling($mode = null, $options = null): void
282
    {
283
        if (isset($this) && $this instanceof self) {
284
            $setmode    = &$this->_default_error_mode;
285
            $setoptions = &$this->_default_error_options;
286
        } else {
287
            $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
288
            $setoptions = &$GLOBALS['_PEAR_default_error_options'];
289
        }
290
291
        switch ($mode) {
292
            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

292
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
293
            case PEAR_ERROR_RETURN:
294
            case PEAR_ERROR_PRINT:
295
            case PEAR_ERROR_TRIGGER:
296
            case PEAR_ERROR_DIE:
297
            case null:
298
                $setmode    = $mode;
299
                $setoptions = $options;
300
                break;
301
            case PEAR_ERROR_CALLBACK:
302
                $setmode = $mode;
303
                // class/object method callback
304
                if (is_callable($options)) {
305
                    $setoptions = $options;
306
                } else {
307
                    trigger_error('invalid error callback', E_USER_WARNING);
308
                }
309
                break;
310
            default:
311
                trigger_error('invalid error mode', E_USER_WARNING);
312
                break;
313
        }
314
    }
315
316
    // }}}
317
    // {{{ expectError()
318
319
    /**
320
     * This method is used to tell which errors you expect to get.
321
     * Expected errors are always returned with error mode
322
     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
323
     * and this method pushes a new element onto it.  The list of
324
     * expected errors are in effect until they are popped off the
325
     * stack with the popExpect() method.
326
     *
327
     * Note that this method can not be called statically
328
     *
329
     * @param mixed $code a single error code or an array of error codes to expect
330
     *
331
     * @return int the new depth of the "expected errors" stack
332
     */
333
    public function expectError($code = '*'): int
334
    {
335
        if (is_array($code)) {
336
            $this->_expected_errors[] = $code;
337
        } else {
338
            $this->_expected_errors[] = [$code];
339
        }
340
341
        return count($this->_expected_errors);
342
    }
343
344
    // }}}
345
    // {{{ popExpect()
346
347
    /**
348
     * This method pops one element off the expected error codes
349
     * stack.
350
     *
351
     * @return array the list of error codes that were popped
352
     */
353
    public function popExpect(): array
354
    {
355
        return array_pop($this->_expected_errors);
356
    }
357
358
    // }}}
359
    // {{{ _checkDelExpect()
360
361
    /**
362
     * This method checks unsets an error code if available
363
     *
364
     * @param mixed $error_code
365
     * @return bool true if the error code was unset, false otherwise
366
     * @since  PHP 4.3.0
367
     */
368
    public function _checkDelExpect($error_code): bool
369
    {
370
        $deleted = false;
371
372
        foreach ($this->_expected_errors as $key => $error_array) {
373
            if (in_array($error_code, $error_array, true)) {
374
                unset($this->_expected_errors[$key][array_search($error_code, $error_array, true)]);
375
                $deleted = true;
376
            }
377
378
            // clean up empty arrays
379
            if (0 == count($this->_expected_errors[$key])) {
380
                unset($this->_expected_errors[$key]);
381
            }
382
        }
383
384
        return $deleted;
385
    }
386
387
    // }}}
388
    // {{{ delExpect()
389
390
    /**
391
     * This method deletes all occurences of the specified element from
392
     * the expected error codes stack.
393
     *
394
     * @param mixed $error_code error code that should be deleted
395
     * @return bool|\PEAR_Error list of error codes that were deleted or error
396
     * @since  PHP 4.3.0
397
     */
398
    public function delExpect($error_code)
399
    {
400
        $deleted = false;
401
402
        if (is_array($error_code) && (0 != count($error_code))) {
403
            // $error_code is a non-empty array here;
404
            // we walk through it trying to unset all
405
            // values
406
            foreach ($error_code as $key => $error) {
407
                if ($this->_checkDelExpect($error)) {
408
                    $deleted = true;
409
                } else {
410
                    $deleted = false;
411
                }
412
            }
413
414
            return $deleted ? true : self::raiseError('The expected error you submitted does not exist'); // IMPROVE ME
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::raiseError() is not static, but was called statically. ( Ignorable by Annotation )

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

414
            return $deleted ? true : self::/** @scrutinizer ignore-call */ raiseError('The expected error you submitted does not exist'); // IMPROVE ME
Loading history...
415
        } elseif (!empty($error_code)) {
416
            // $error_code comes alone, trying to unset it
417
            if ($this->_checkDelExpect($error_code)) {
418
                return true;
419
            }
420
421
            return self::raiseError('The expected error you submitted does not exist'); // IMPROVE ME
422
        }
423
        // $error_code is empty
424
        return self::raiseError('The expected error you submitted is empty'); // IMPROVE ME
425
    }
426
427
    // }}}
428
    // {{{ raiseError()
429
430
    /**
431
     * This method is a wrapper that returns an instance of the
432
     * configured error class with this object's default error
433
     * handling applied.  If the $mode and $options parameters are not
434
     * specified, the object's defaults are used.
435
     *
436
     * @param mixed $message      a text error message or a PEAR error object
437
     *
438
     * @param null  $code         a numeric error code (it is up to your class
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $code is correct as it would always require null to be passed?
Loading history...
439
     *                            to define these if you want to use codes)
440
     *
441
     * @param null  $mode         One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $mode is correct as it would always require null to be passed?
Loading history...
442
     *                            PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
443
     *                            PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
444
     *
445
     * @param mixed $options      If $mode is PEAR_ERROR_TRIGGER, this parameter
446
     *                            specifies the PHP-internal error level (one of
447
     *                            E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
448
     *                            If $mode is PEAR_ERROR_CALLBACK, this
449
     *                            parameter specifies the callback function or
450
     *                            method.  In other error modes this parameter
451
     *                            is ignored.
452
     *
453
     * @param null  $userinfo     If you need to pass along for example debug
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $userinfo is correct as it would always require null to be passed?
Loading history...
454
     *                            information, this parameter is meant for that.
455
     *
456
     * @param null  $error_class  The returned error object will be
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $error_class is correct as it would always require null to be passed?
Loading history...
457
     *                            instantiated from this class, if specified.
458
     *
459
     * @param bool  $skipmsg      If true, raiseError will only pass error codes,
460
     *                            the error message parameter will be dropped.
461
     *
462
     * @return PEAR_Error a PEAR error object
463
     * @see    PEAR::setErrorHandling
464
     * @since  PHP 4.0.5
465
     */
466
    public function raiseError(
467
        $message = null, $code = null, $mode = null, $options = null, $userinfo = null, $error_class = null, bool $skipmsg = false
468
    ): PEAR_Error {
469
        // The error is yet a PEAR error object
470
        if (is_object($message)) {
471
            $code                          = $message->getCode();
472
            $userinfo                      = $message->getUserInfo();
473
            $error_class                   = $message->getType();
474
            $message->error_message_prefix = '';
475
            $message                       = $message->getMessage();
476
        }
477
478
        if (isset($this) && isset($this->_expected_errors) && count($this->_expected_errors) > 0 && count($exp = end($this->_expected_errors))) {
479
            if ('*' === $exp[0]
480
                || (is_int(reset($exp)) && in_array($code, $exp, true))
481
                || (is_string(reset($exp)) && in_array($message, $exp, true))) {
482
                $mode = PEAR_ERROR_RETURN;
483
            }
484
        }
485
        // No mode given, try global ones
486
        if (null === $mode) {
487
            // Class error handler
488
            if (isset($this) && isset($this->_default_error_mode)) {
489
                $mode    = $this->_default_error_mode;
490
                $options = $this->_default_error_options;
491
                // Global error handler
492
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
493
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
494
                $options = $GLOBALS['_PEAR_default_error_options'];
495
            }
496
        }
497
498
        if (null !== $error_class) {
499
            $ec = $error_class;
500
        } elseif (isset($this) && isset($this->_error_class)) {
501
            $ec = $this->_error_class;
502
        } else {
503
            $ec = 'PEAR_Error';
504
        }
505
        if ($skipmsg) {
506
            return new $ec($code, $mode, $options, $userinfo);
507
        }
508
509
        return new $ec($message, $code, $mode, $options, $userinfo);
510
    }
511
512
    // }}}
513
    // {{{ throwError()
514
515
    /**
516
     * Simpler form of raiseError with fewer options.  In most cases
517
     * message, code and userinfo are enough.
518
     *
519
     * @param null $message
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $message is correct as it would always require null to be passed?
Loading history...
520
     *
521
     * @param null $code
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $code is correct as it would always require null to be passed?
Loading history...
522
     * @param null $userinfo
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $userinfo is correct as it would always require null to be passed?
Loading history...
523
     * @return object
524
     */
525
    public function throwError(
526
        $message = null, $code = null, $userinfo = null
527
    ) {
528
        if (isset($this) && $this instanceof self) {
529
            return $this->raiseError($message, $code, null, null, $userinfo);
530
        }
531
532
        return self::raiseError($message, $code, null, null, $userinfo);
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::raiseError() is not static, but was called statically. ( Ignorable by Annotation )

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

532
        return self::/** @scrutinizer ignore-call */ raiseError($message, $code, null, null, $userinfo);
Loading history...
533
    }
534
535
    // }}}
536
    // {{{ pushErrorHandling()
537
538
    /**
539
     * Push a new error handler on top of the error handler options stack. With this
540
     * you can easily override the actual error handler for some code and restore
541
     * it later with popErrorHandling.
542
     *
543
     * @param mixed $mode    (same as setErrorHandling)
544
     * @param mixed $options (same as setErrorHandling)
545
     *
546
     * @return bool Always true
547
     *
548
     * @see PEAR::setErrorHandling
549
     */
550
    public function pushErrorHandling($mode, $options = null): bool
551
    {
552
        $stack = &$GLOBALS['_PEAR_errorHandler_stack'];
553
        if (isset($this) && $this instanceof self) {
554
            $def_mode    = &$this->_default_error_mode;
555
            $def_options = &$this->_default_error_options;
556
        } else {
557
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
558
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
559
        }
560
        $stack[] = [$def_mode, $def_options];
561
562
        if (isset($this) && $this instanceof self) {
563
            $this->setErrorHandling($mode, $options);
564
        } else {
565
            self::setErrorHandling($mode, $options);
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::setErrorHandling() is not static, but was called statically. ( Ignorable by Annotation )

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

565
            self::/** @scrutinizer ignore-call */ 
566
                  setErrorHandling($mode, $options);
Loading history...
566
        }
567
        $stack[] = [$mode, $options];
568
569
        return true;
570
    }
571
572
    // }}}
573
    // {{{ popErrorHandling()
574
575
    /**
576
     * Pop the last error handler used
577
     *
578
     * @return bool Always true
579
     *
580
     * @see PEAR::pushErrorHandling
581
     */
582
    public function popErrorHandling(): bool
583
    {
584
        $stack = &$GLOBALS['_PEAR_errorHandler_stack'];
585
        array_pop($stack);
586
        [$mode, $options] = $stack[count($stack) - 1];
587
        array_pop($stack);
588
        if (isset($this) && $this instanceof self) {
589
            $this->setErrorHandling($mode, $options);
590
        } else {
591
            self::setErrorHandling($mode, $options);
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::setErrorHandling() is not static, but was called statically. ( Ignorable by Annotation )

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

591
            self::/** @scrutinizer ignore-call */ 
592
                  setErrorHandling($mode, $options);
Loading history...
592
        }
593
594
        return true;
595
    }
596
597
    // }}}
598
    // {{{ loadExtension()
599
600
    /**
601
     * OS independant PHP extension load. Remember to take care
602
     * on the correct extension name for case sensitive OSes.
603
     *
604
     * @param string $ext The extension name
605
     * @return bool   Success or not on the dl() call
606
     */
607
    public function loadExtension(string $ext): bool
608
    {
609
        if (!extension_loaded($ext)) {
610
            // if either returns true dl() will produce a FATAL error, stop that
611
            if ((1 != ini_get('enable_dl')) || (1 == ini_get('safe_mode'))) {
612
                return false;
613
            }
614
            if (OS_WINDOWS) {
615
                $suffix = '.dll';
616
            } elseif (PHP_OS === 'HP-UX') {
617
                $suffix = '.sl';
618
            } elseif (PHP_OS === 'AIX') {
619
                $suffix = '.a';
620
            } elseif (PHP_OS === 'OSX') {
621
                $suffix = '.bundle';
622
            } else {
623
                $suffix = '.so';
624
            }
625
626
            return @dl('php_' . $ext . $suffix) || @dl($ext . $suffix);
627
        }
628
629
        return true;
630
    }
631
    // }}}
632
}
633
634
// {{{ _PEAR_call_destructors()
635
636
function _PEAR_call_destructors(): void
637
{
638
    global $_PEAR_destructor_object_list;
639
    if (is_array($_PEAR_destructor_object_list)
640
        && count($_PEAR_destructor_object_list)) {
641
        reset($_PEAR_destructor_object_list);
642
        foreach ($_PEAR_destructor_object_list as $objref) {
643
            $classname = get_class($objref);
644
            while ($classname) {
645
                $destructor = "_$classname";
646
                if (method_exists($objref, $destructor)) {
647
                    $objref->$destructor();
648
                    break;
649
                }
650
                $classname = get_parent_class($classname);
651
            }
652
        }
653
        // Empty the object list to ensure that destructors are
654
        // not called more than once.
655
        $_PEAR_destructor_object_list = [];
656
    }
657
658
    // Now call the shutdown functions
659
    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) && !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
660
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
661
            call_user_func_array($value[0], $value[1]);
662
        }
663
    }
664
}
665
666
// }}}
667
668
/**
669
 * Class PEAR_Error
670
 */
671
class PEAR_Error
672
{
673
    // {{{ properties
674
675
    public $error_message_prefix = '';
676
    public $mode                 = PEAR_ERROR_RETURN;
677
    public $level                = E_USER_NOTICE;
678
    public $code                 = -1;
679
    public $message              = '';
680
    public $userinfo             = '';
681
    public $backtrace            = null;
682
    // }}}
683
    // {{{ constructor
684
685
    /**
686
     * PEAR_Error constructor
687
     *
688
     * @param string $message  message
689
     *
690
     * @param null   $code     (optional) error code
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $code is correct as it would always require null to be passed?
Loading history...
691
     *
692
     * @param null   $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $mode is correct as it would always require null to be passed?
Loading history...
693
     *                         PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
694
     *                         PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
695
     *
696
     * @param mixed  $options  (optional) error level, _OR_ in the case of
697
     *                         PEAR_ERROR_CALLBACK, the callback function or object/method
698
     *                         tuple.
699
     *
700
     * @param null   $userinfo (optional) additional user/debug info
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $userinfo is correct as it would always require null to be passed?
Loading history...
701
     */
702
    public function __construct(
703
        string $message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null
704
    ) {
705
        if (null === $mode) {
0 ignored issues
show
The condition null === $mode is always true.
Loading history...
706
            $mode = PEAR_ERROR_RETURN;
707
        }
708
        $this->message  = $message;
709
        $this->code     = $code;
710
        $this->mode     = $mode;
711
        $this->userinfo = $userinfo;
712
        if (function_exists('debug_backtrace')) {
713
            $this->backtrace = debug_backtrace();
714
        }
715
        if ($mode & PEAR_ERROR_CALLBACK) {
716
            $this->level    = E_USER_NOTICE;
717
            $this->callback = $options;
0 ignored issues
show
Bug Best Practice introduced by
The property callback does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
718
        } else {
719
            if (null === $options) {
720
                $options = E_USER_NOTICE;
721
            }
722
            $this->level    = $options;
723
            $this->callback = null;
724
        }
725
        if ($this->mode & PEAR_ERROR_PRINT) {
726
            if (null === $options || is_int($options)) {
727
                $format = '%s';
728
            } else {
729
                $format = $options;
730
            }
731
            printf($format, $this->getMessage());
732
        }
733
        if ($this->mode & PEAR_ERROR_TRIGGER) {
734
            trigger_error($this->getMessage(), $this->level);
735
        }
736
        if ($this->mode & PEAR_ERROR_DIE) {
737
            $msg = $this->getMessage();
738
            if (null === $options || is_int($options)) {
739
                $format = '%s';
740
                if ("\n" !== mb_substr($msg, -1)) {
741
                    $msg .= "\n";
742
                }
743
            } else {
744
                $format = $options;
745
            }
746
            exit(sprintf($format, $msg));
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
747
        }
748
        if ($this->mode & PEAR_ERROR_CALLBACK) {
749
            if (is_callable($this->callback)) {
750
                call_user_func($this->callback, $this);
0 ignored issues
show
It seems like $this->callback can also be of type null; however, parameter $callback of call_user_func() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

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

750
                call_user_func(/** @scrutinizer ignore-type */ $this->callback, $this);
Loading history...
751
            }
752
        }
753
        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

753
        if ($this->mode & /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION) {
Loading history...
754
            trigger_error('PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_ErrorStack for exceptions', E_USER_WARNING);
755
            eval('$e = new Exception($this->message, $this->code);$e->PEAR_Error = $this;throw($e);');
0 ignored issues
show
The use of eval() is discouraged.
Loading history...
756
        }
757
    }
758
759
    // }}}
760
    // {{{ getMode()
761
762
    /**
763
     * Get the error mode from an error object.
764
     *
765
     * @return int error mode
766
     */
767
    public function getMode(): ?int
768
    {
769
        return $this->mode;
770
    }
771
772
    // }}}
773
    // {{{ getCallback()
774
775
    /**
776
     * Get the callback function/method from an error object.
777
     *
778
     * @return mixed callback function or object/method array
779
     */
780
    public function getCallback()
781
    {
782
        return $this->callback;
783
    }
784
785
    // }}}
786
    // {{{ getMessage()
787
788
    /**
789
     * Get the error message from an error object.
790
     *
791
     * @return string full error message
792
     */
793
    public function getMessage(): string
794
    {
795
        return ($this->error_message_prefix . $this->message);
796
    }
797
798
    // }}}
799
    // {{{ getCode()
800
801
    /**
802
     * Get error code from an error object
803
     *
804
     * @return int error code
805
     */
806
    public function getCode(): ?int
807
    {
808
        return $this->code;
809
    }
810
811
    // }}}
812
    // {{{ getType()
813
814
    /**
815
     * Get the name of this error/exception.
816
     *
817
     * @return string error/exception name (type)
818
     */
819
    public function getType(): string
820
    {
821
        return get_class($this);
822
    }
823
824
    // }}}
825
    // {{{ getUserInfo()
826
827
    /**
828
     * Get additional user-supplied information.
829
     *
830
     * @return string user-supplied information
831
     */
832
    public function getUserInfo(): ?string
833
    {
834
        return $this->userinfo;
835
    }
836
837
    // }}}
838
    // {{{ getDebugInfo()
839
840
    /**
841
     * Get additional debug information supplied by the application.
842
     *
843
     * @return string debug information
844
     */
845
    public function getDebugInfo(): ?string
846
    {
847
        return $this->getUserInfo();
848
    }
849
850
    // }}}
851
    // {{{ getBacktrace()
852
853
    /**
854
     * Get the call backtrace from where the error was generated.
855
     * Supported with PHP 4.3.0 or newer.
856
     *
857
     * @param null $frame (optional) what frame to fetch
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $frame is correct as it would always require null to be passed?
Loading history...
858
     * @return array Backtrace, or NULL if not available.
859
     */
860
    public function getBacktrace($frame = null): ?array
861
    {
862
        if (null === $frame) {
0 ignored issues
show
The condition null === $frame is always true.
Loading history...
863
            return $this->backtrace;
864
        }
865
866
        return $this->backtrace[$frame];
867
    }
868
869
    // }}}
870
    // {{{ addUserInfo()
871
872
    /**
873
     * @param string $info
874
     */
875
    public function addUserInfo($info): void
876
    {
877
        if (empty($this->userinfo)) {
878
            $this->userinfo = $info;
879
        } else {
880
            $this->userinfo .= " ** $info";
881
        }
882
    }
883
884
    // }}}
885
    // {{{ toString()
886
887
    /**
888
     * Make a string representation of this object.
889
     *
890
     * @return string a string with an object summary
891
     */
892
    public function toString(): string
893
    {
894
        $modes  = [];
895
        $levels = [
896
            E_USER_NOTICE  => 'notice',
897
            E_USER_WARNING => 'warning',
898
            E_USER_ERROR   => 'error',
899
        ];
900
        if ($this->mode & PEAR_ERROR_CALLBACK) {
901
            if (is_array($this->callback)) {
902
                $callback = get_class($this->callback[0]) . '::' . $this->callback[1];
903
            } else {
904
                $callback = $this->callback;
905
            }
906
907
            return sprintf('[%s: message="%s" code=%d mode=callback ' . 'callback=%s prefix="%s" info="%s"]', get_class($this), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo);
908
        }
909
        if ($this->mode & PEAR_ERROR_PRINT) {
910
            $modes[] = 'print';
911
        }
912
        if ($this->mode & PEAR_ERROR_TRIGGER) {
913
            $modes[] = 'trigger';
914
        }
915
        if ($this->mode & PEAR_ERROR_DIE) {
916
            $modes[] = 'die';
917
        }
918
        if ($this->mode & PEAR_ERROR_RETURN) {
919
            $modes[] = 'return';
920
        }
921
922
        return sprintf('[%s: message="%s" code=%d mode=%s level=%s ' . 'prefix="%s" info="%s"]', get_class($this), $this->message, $this->code, implode('|', $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo);
923
    }
924
    // }}}
925
}
926
927
register_shutdown_function('_PEAR_call_destructors');
928
929
/*
930
 * Local Variables:
931
 * mode: php
932
 * tab-width: 4
933
 * c-basic-offset: 4
934
 * End:
935
 */
936