Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
/lib/pear/ -> PEAR.php (source)

Differences Between: [Versions 39 and 402] [Versions 39 and 403]

   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 <sterling@php.net>
  12   * @author     Stig Bakken <ssb@php.net>
  13   * @author     Tomas V.V.Cox <cox@idecnet.com>
  14   * @author     Greg Beaver <cellog@php.net>
  15   * @copyright  1997-2010 The Authors
  16   * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  17   * @version    CVS: $Id$
  18   * @link       http://pear.php.net/package/PEAR
  19   * @since      File available since Release 0.1
  20   */
  21  
  22  /**#@+
  23   * ERROR constants
  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  /**#@-*/
  36  define('PEAR_ZE2', (function_exists('version_compare') &&
  37                      version_compare(zend_version(), "2-dev", "ge")));
  38  
  39  if (substr(PHP_OS, 0, 3) == '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  $GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
  50  $GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
  51  $GLOBALS['_PEAR_destructor_object_list'] = array();
  52  $GLOBALS['_PEAR_shutdown_funcs']         = array();
  53  $GLOBALS['_PEAR_error_handler_stack']    = array();
  54  
  55  @ini_set('track_errors', true);
  56  
  57  /**
  58   * Base class for other PEAR classes.  Provides rudimentary
  59   * emulation of destructors.
  60   *
  61   * If you want a destructor in your class, inherit PEAR and make a
  62   * destructor method called _yourclassname (same name as the
  63   * constructor, but with a "_" prefix).  Also, in your constructor you
  64   * have to call the PEAR constructor: $this->PEAR();.
  65   * The destructor method will be called without parameters.  Note that
  66   * at in some SAPI implementations (such as Apache), any output during
  67   * the request shutdown (in which destructors are called) seems to be
  68   * discarded.  If you need to get any debug information from your
  69   * destructor, use error_log(), syslog() or something similar.
  70   *
  71   * IMPORTANT! To use the emulated destructors you need to create the
  72   * objects by reference: $obj =& new PEAR_child;
  73   *
  74   * @category   pear
  75   * @package    PEAR
  76   * @author     Stig Bakken <ssb@php.net>
  77   * @author     Tomas V.V. Cox <cox@idecnet.com>
  78   * @author     Greg Beaver <cellog@php.net>
  79   * @copyright  1997-2006 The PHP Group
  80   * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  81   * @version    Release: 1.9.1
  82   * @link       http://pear.php.net/package/PEAR
  83   * @see        PEAR_Error
  84   * @since      Class available since PHP 4.0.2
  85   * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
  86   */
  87  class PEAR
  88  {
  89      /**
  90       * Whether to enable internal debug messages.
  91       *
  92       * @var     bool
  93       * @access  private
  94       */
  95      var $_debug = false;
  96  
  97      /**
  98       * Default error mode for this object.
  99       *
 100       * @var     int
 101       * @access  private
 102       */
 103      var $_default_error_mode = null;
 104  
 105      /**
 106       * Default error options used for this object when error mode
 107       * is PEAR_ERROR_TRIGGER.
 108       *
 109       * @var     int
 110       * @access  private
 111       */
 112      var $_default_error_options = null;
 113  
 114      /**
 115       * Default error handler (callback) for this object, if error mode is
 116       * PEAR_ERROR_CALLBACK.
 117       *
 118       * @var     string
 119       * @access  private
 120       */
 121      var $_default_error_handler = '';
 122  
 123      /**
 124       * Which class to use for error objects.
 125       *
 126       * @var     string
 127       * @access  private
 128       */
 129      var $_error_class = 'PEAR_Error';
 130  
 131      /**
 132       * An array of expected errors.
 133       *
 134       * @var     array
 135       * @access  private
 136       */
 137      var $_expected_errors = array();
 138  
 139      /**
 140       * Constructor.  Registers this object in
 141       * $_PEAR_destructor_object_list for destructor emulation if a
 142       * destructor object exists.
 143       *
 144       * @param string $error_class  (optional) which class to use for
 145       *        error objects, defaults to PEAR_Error.
 146       * @access public
 147       * @return void
 148       */
 149      function __construct($error_class = null)
 150      {
 151          $classname = strtolower(get_class($this));
 152          if ($this->_debug) {
 153              print "PEAR constructor called, class=$classname\n";
 154          }
 155  
 156          if ($error_class !== null) {
 157              $this->_error_class = $error_class;
 158          }
 159  
 160          while ($classname && strcasecmp($classname, "pear")) {
 161              $destructor = "_$classname";
 162              if (method_exists($this, $destructor)) {
 163                  global $_PEAR_destructor_object_list;
 164                  $_PEAR_destructor_object_list[] = &$this;
 165                  if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
 166                      register_shutdown_function("_PEAR_call_destructors");
 167                      $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
 168                  }
 169                  break;
 170              } else {
 171                  $classname = get_parent_class($classname);
 172              }
 173          }
 174      }
 175  
 176      /**
 177       * Only here for backwards compatibility.
 178       * E.g. Archive_Tar calls $this->PEAR() in its constructor.
 179       *
 180       * @param string $error_class Which class to use for error objects,
 181       *                            defaults to PEAR_Error.
 182       */
 183      public function PEAR($error_class = null)
 184      {
 185          $this->__construct($error_class);
 186      }
 187  
 188      /**
 189       * Destructor (the emulated type of...).  Does nothing right now,
 190       * but is included for forward compatibility, so subclass
 191       * destructors should always call it.
 192       *
 193       * See the note in the class desciption about output from
 194       * destructors.
 195       *
 196       * @access public
 197       * @return void
 198       */
 199      function _PEAR() {
 200          if ($this->_debug) {
 201              printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
 202          }
 203      }
 204  
 205      /**
 206      * If you have a class that's mostly/entirely static, and you need static
 207      * properties, you can use this method to simulate them. Eg. in your method(s)
 208      * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
 209      * You MUST use a reference, or they will not persist!
 210      *
 211      * @access public
 212      * @param  string $class  The calling classname, to prevent clashes
 213      * @param  string $var    The variable to retrieve.
 214      * @return mixed   A reference to the variable. If not set it will be
 215      *                 auto initialised to NULL.
 216      */
 217      function &getStaticProperty($class, $var)
 218      {
 219          static $properties;
 220          if (!isset($properties[$class])) {
 221              $properties[$class] = array();
 222          }
 223  
 224          if (!array_key_exists($var, $properties[$class])) {
 225              $properties[$class][$var] = null;
 226          }
 227  
 228          return $properties[$class][$var];
 229      }
 230  
 231      /**
 232      * Use this function to register a shutdown method for static
 233      * classes.
 234      *
 235      * @access public
 236      * @param  mixed $func  The function name (or array of class/method) to call
 237      * @param  mixed $args  The arguments to pass to the function
 238      * @return void
 239      */
 240      function registerShutdownFunc($func, $args = array())
 241      {
 242          // if we are called statically, there is a potential
 243          // that no shutdown func is registered.  Bug #6445
 244          if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
 245              register_shutdown_function("_PEAR_call_destructors");
 246              $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
 247          }
 248          $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
 249      }
 250  
 251      /**
 252       * Tell whether a value is a PEAR error.
 253       *
 254       * @param   mixed $data   the value to test
 255       * @param   int   $code   if $data is an error object, return true
 256       *                        only if $code is a string and
 257       *                        $obj->getMessage() == $code or
 258       *                        $code is an integer and $obj->getCode() == $code
 259       * @access  public
 260       * @return  bool    true if parameter is an error
 261       */
 262      function isError($data, $code = null)
 263      {
 264          if (!is_a($data, 'PEAR_Error')) {
 265              return false;
 266          }
 267  
 268          if (is_null($code)) {
 269              return true;
 270          } elseif (is_string($code)) {
 271              return $data->getMessage() == $code;
 272          }
 273  
 274          return $data->getCode() == $code;
 275      }
 276  
 277      /**
 278       * Sets how errors generated by this object should be handled.
 279       * Can be invoked both in objects and statically.  If called
 280       * statically, setErrorHandling sets the default behaviour for all
 281       * PEAR objects.  If called in an object, setErrorHandling sets
 282       * the default behaviour for that object.
 283       *
 284       * @param int $mode
 285       *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
 286       *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
 287       *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
 288       *
 289       * @param mixed $options
 290       *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
 291       *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
 292       *
 293       *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
 294       *        to be the callback function or method.  A callback
 295       *        function is a string with the name of the function, a
 296       *        callback method is an array of two elements: the element
 297       *        at index 0 is the object, and the element at index 1 is
 298       *        the name of the method to call in the object.
 299       *
 300       *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
 301       *        a printf format string used when printing the error
 302       *        message.
 303       *
 304       * @access public
 305       * @return void
 306       * @see PEAR_ERROR_RETURN
 307       * @see PEAR_ERROR_PRINT
 308       * @see PEAR_ERROR_TRIGGER
 309       * @see PEAR_ERROR_DIE
 310       * @see PEAR_ERROR_CALLBACK
 311       * @see PEAR_ERROR_EXCEPTION
 312       *
 313       * @since PHP 4.0.5
 314       */
 315      function setErrorHandling($mode = null, $options = null)
 316      {
 317          if (isset($this) && is_a($this, 'PEAR')) {
 318              $setmode     = &$this->_default_error_mode;
 319              $setoptions  = &$this->_default_error_options;
 320          } else {
 321              $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
 322              $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
 323          }
 324  
 325          switch ($mode) {
 326              case PEAR_ERROR_EXCEPTION:
 327              case PEAR_ERROR_RETURN:
 328              case PEAR_ERROR_PRINT:
 329              case PEAR_ERROR_TRIGGER:
 330              case PEAR_ERROR_DIE:
 331              case null:
 332                  $setmode = $mode;
 333                  $setoptions = $options;
 334                  break;
 335  
 336              case PEAR_ERROR_CALLBACK:
 337                  $setmode = $mode;
 338                  // class/object method callback
 339                  if (is_callable($options)) {
 340                      $setoptions = $options;
 341                  } else {
 342                      trigger_error("invalid error callback", E_USER_WARNING);
 343                  }
 344                  break;
 345  
 346              default:
 347                  trigger_error("invalid error mode", E_USER_WARNING);
 348                  break;
 349          }
 350      }
 351  
 352      /**
 353       * This method is used to tell which errors you expect to get.
 354       * Expected errors are always returned with error mode
 355       * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
 356       * and this method pushes a new element onto it.  The list of
 357       * expected errors are in effect until they are popped off the
 358       * stack with the popExpect() method.
 359       *
 360       * Note that this method can not be called statically
 361       *
 362       * @param mixed $code a single error code or an array of error codes to expect
 363       *
 364       * @return int     the new depth of the "expected errors" stack
 365       * @access public
 366       */
 367      function expectError($code = '*')
 368      {
 369          if (is_array($code)) {
 370              array_push($this->_expected_errors, $code);
 371          } else {
 372              array_push($this->_expected_errors, array($code));
 373          }
 374          return count($this->_expected_errors);
 375      }
 376  
 377      /**
 378       * This method pops one element off the expected error codes
 379       * stack.
 380       *
 381       * @return array   the list of error codes that were popped
 382       */
 383      function popExpect()
 384      {
 385          return array_pop($this->_expected_errors);
 386      }
 387  
 388      /**
 389       * This method checks unsets an error code if available
 390       *
 391       * @param mixed error code
 392       * @return bool true if the error code was unset, false otherwise
 393       * @access private
 394       * @since PHP 4.3.0
 395       */
 396      function _checkDelExpect($error_code)
 397      {
 398          $deleted = false;
 399          foreach ($this->_expected_errors as $key => $error_array) {
 400              if (in_array($error_code, $error_array)) {
 401                  unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
 402                  $deleted = true;
 403              }
 404  
 405              // clean up empty arrays
 406              if (0 == count($this->_expected_errors[$key])) {
 407                  unset($this->_expected_errors[$key]);
 408              }
 409          }
 410  
 411          return $deleted;
 412      }
 413  
 414      /**
 415       * This method deletes all occurences of the specified element from
 416       * the expected error codes stack.
 417       *
 418       * @param  mixed $error_code error code that should be deleted
 419       * @return mixed list of error codes that were deleted or error
 420       * @access public
 421       * @since PHP 4.3.0
 422       */
 423      function delExpect($error_code)
 424      {
 425          $deleted = false;
 426          if ((is_array($error_code) && (0 != count($error_code)))) {
 427              // $error_code is a non-empty array here; we walk through it trying
 428              // to unset all values
 429              foreach ($error_code as $key => $error) {
 430                  $deleted =  $this->_checkDelExpect($error) ? true : false;
 431              }
 432  
 433              return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
 434          } elseif (!empty($error_code)) {
 435              // $error_code comes alone, trying to unset it
 436              if ($this->_checkDelExpect($error_code)) {
 437                  return true;
 438              }
 439  
 440              return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
 441          }
 442  
 443          // $error_code is empty
 444          return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
 445      }
 446  
 447      /**
 448       * This method is a wrapper that returns an instance of the
 449       * configured error class with this object's default error
 450       * handling applied.  If the $mode and $options parameters are not
 451       * specified, the object's defaults are used.
 452       *
 453       * @param mixed $message a text error message or a PEAR error object
 454       *
 455       * @param int $code      a numeric error code (it is up to your class
 456       *                  to define these if you want to use codes)
 457       *
 458       * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
 459       *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
 460       *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
 461       *
 462       * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
 463       *                  specifies the PHP-internal error level (one of
 464       *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
 465       *                  If $mode is PEAR_ERROR_CALLBACK, this
 466       *                  parameter specifies the callback function or
 467       *                  method.  In other error modes this parameter
 468       *                  is ignored.
 469       *
 470       * @param string $userinfo If you need to pass along for example debug
 471       *                  information, this parameter is meant for that.
 472       *
 473       * @param string $error_class The returned error object will be
 474       *                  instantiated from this class, if specified.
 475       *
 476       * @param bool $skipmsg If true, raiseError will only pass error codes,
 477       *                  the error message parameter will be dropped.
 478       *
 479       * @access public
 480       * @return object   a PEAR error object
 481       * @see PEAR::setErrorHandling
 482       * @since PHP 4.0.5
 483       */
 484      function &raiseError($message = null,
 485                           $code = null,
 486                           $mode = null,
 487                           $options = null,
 488                           $userinfo = null,
 489                           $error_class = null,
 490                           $skipmsg = false)
 491      {
 492          // The error is yet a PEAR error object
 493          if (is_object($message)) {
 494              $code        = $message->getCode();
 495              $userinfo    = $message->getUserInfo();
 496              $error_class = $message->getType();
 497              $message->error_message_prefix = '';
 498              $message     = $message->getMessage();
 499          }
 500  
 501          if (
 502              isset($this) &&
 503              isset($this->_expected_errors) &&
 504              count($this->_expected_errors) > 0 &&
 505              count($exp = end($this->_expected_errors))
 506          ) {
 507              if ($exp[0] == "*" ||
 508                  (is_int(reset($exp)) && in_array($code, $exp)) ||
 509                  (is_string(reset($exp)) && in_array($message, $exp))
 510              ) {
 511                  $mode = PEAR_ERROR_RETURN;
 512              }
 513          }
 514  
 515          // No mode given, try global ones
 516          if ($mode === null) {
 517              // Class error handler
 518              if (isset($this) && isset($this->_default_error_mode)) {
 519                  $mode    = $this->_default_error_mode;
 520                  $options = $this->_default_error_options;
 521              // Global error handler
 522              } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
 523                  $mode    = $GLOBALS['_PEAR_default_error_mode'];
 524                  $options = $GLOBALS['_PEAR_default_error_options'];
 525              }
 526          }
 527  
 528          if ($error_class !== null) {
 529              $ec = $error_class;
 530          } elseif (isset($this) && isset($this->_error_class)) {
 531              $ec = $this->_error_class;
 532          } else {
 533              $ec = 'PEAR_Error';
 534          }
 535  
 536          if (intval(PHP_VERSION) < 5) {
 537              // little non-eval hack to fix bug #12147
 538              include 'PEAR/FixPHP5PEARWarnings.php';
 539              return $a;
 540          }
 541  
 542          if ($skipmsg) {
 543              $a = new $ec($code, $mode, $options, $userinfo);
 544          } else {
 545              $a = new $ec($message, $code, $mode, $options, $userinfo);
 546          }
 547  
 548          return $a;
 549      }
 550  
 551      /**
 552       * Simpler form of raiseError with fewer options.  In most cases
 553       * message, code and userinfo are enough.
 554       *
 555       * @param mixed $message a text error message or a PEAR error object
 556       *
 557       * @param int $code      a numeric error code (it is up to your class
 558       *                  to define these if you want to use codes)
 559       *
 560       * @param string $userinfo If you need to pass along for example debug
 561       *                  information, this parameter is meant for that.
 562       *
 563       * @access public
 564       * @return object   a PEAR error object
 565       * @see PEAR::raiseError
 566       */
 567      function &throwError($message = null, $code = null, $userinfo = null)
 568      {
 569          if (isset($this) && is_a($this, 'PEAR')) {
 570              $a = &$this->raiseError($message, $code, null, null, $userinfo);
 571              return $a;
 572          }
 573  
 574          $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
 575          return $a;
 576      }
 577  
 578      function staticPushErrorHandling($mode, $options = null)
 579      {
 580          $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
 581          $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
 582          $def_options = &$GLOBALS['_PEAR_default_error_options'];
 583          $stack[] = array($def_mode, $def_options);
 584          switch ($mode) {
 585              case PEAR_ERROR_EXCEPTION:
 586              case PEAR_ERROR_RETURN:
 587              case PEAR_ERROR_PRINT:
 588              case PEAR_ERROR_TRIGGER:
 589              case PEAR_ERROR_DIE:
 590              case null:
 591                  $def_mode = $mode;
 592                  $def_options = $options;
 593                  break;
 594  
 595              case PEAR_ERROR_CALLBACK:
 596                  $def_mode = $mode;
 597                  // class/object method callback
 598                  if (is_callable($options)) {
 599                      $def_options = $options;
 600                  } else {
 601                      trigger_error("invalid error callback", E_USER_WARNING);
 602                  }
 603                  break;
 604  
 605              default:
 606                  trigger_error("invalid error mode", E_USER_WARNING);
 607                  break;
 608          }
 609          $stack[] = array($mode, $options);
 610          return true;
 611      }
 612  
 613      function staticPopErrorHandling()
 614      {
 615          $stack = &$GLOBALS['_PEAR_error_handler_stack'];
 616          $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
 617          $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
 618          array_pop($stack);
 619          list($mode, $options) = $stack[sizeof($stack) - 1];
 620          array_pop($stack);
 621          switch ($mode) {
 622              case PEAR_ERROR_EXCEPTION:
 623              case PEAR_ERROR_RETURN:
 624              case PEAR_ERROR_PRINT:
 625              case PEAR_ERROR_TRIGGER:
 626              case PEAR_ERROR_DIE:
 627              case null:
 628                  $setmode = $mode;
 629                  $setoptions = $options;
 630                  break;
 631  
 632              case PEAR_ERROR_CALLBACK:
 633                  $setmode = $mode;
 634                  // class/object method callback
 635                  if (is_callable($options)) {
 636                      $setoptions = $options;
 637                  } else {
 638                      trigger_error("invalid error callback", E_USER_WARNING);
 639                  }
 640                  break;
 641  
 642              default:
 643                  trigger_error("invalid error mode", E_USER_WARNING);
 644                  break;
 645          }
 646          return true;
 647      }
 648  
 649      /**
 650       * Push a new error handler on top of the error handler options stack. With this
 651       * you can easily override the actual error handler for some code and restore
 652       * it later with popErrorHandling.
 653       *
 654       * @param mixed $mode (same as setErrorHandling)
 655       * @param mixed $options (same as setErrorHandling)
 656       *
 657       * @return bool Always true
 658       *
 659       * @see PEAR::setErrorHandling
 660       */
 661      function pushErrorHandling($mode, $options = null)
 662      {
 663          $stack = &$GLOBALS['_PEAR_error_handler_stack'];
 664          if (isset($this) && is_a($this, 'PEAR')) {
 665              $def_mode    = &$this->_default_error_mode;
 666              $def_options = &$this->_default_error_options;
 667          } else {
 668              $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
 669              $def_options = &$GLOBALS['_PEAR_default_error_options'];
 670          }
 671          $stack[] = array($def_mode, $def_options);
 672  
 673          if (isset($this) && is_a($this, 'PEAR')) {
 674              $this->setErrorHandling($mode, $options);
 675          } else {
 676              PEAR::setErrorHandling($mode, $options);
 677          }
 678          $stack[] = array($mode, $options);
 679          return true;
 680      }
 681  
 682      /**
 683      * Pop the last error handler used
 684      *
 685      * @return bool Always true
 686      *
 687      * @see PEAR::pushErrorHandling
 688      */
 689      function popErrorHandling()
 690      {
 691          $stack = &$GLOBALS['_PEAR_error_handler_stack'];
 692          array_pop($stack);
 693          list($mode, $options) = $stack[sizeof($stack) - 1];
 694          array_pop($stack);
 695          if (isset($this) && is_a($this, 'PEAR')) {
 696              $this->setErrorHandling($mode, $options);
 697          } else {
 698              PEAR::setErrorHandling($mode, $options);
 699          }
 700          return true;
 701      }
 702  
 703      /**
 704      * OS independant PHP extension load. Remember to take care
 705      * on the correct extension name for case sensitive OSes.
 706      *
 707      * @param string $ext The extension name
 708      * @return bool Success or not on the dl() call
 709      */
 710      function loadExtension($ext)
 711      {
 712          if (extension_loaded($ext)) {
 713              return true;
 714          }
 715  
 716          // if either returns true dl() will produce a FATAL error, stop that
 717          if (
 718              function_exists('dl') === false ||
 719              ini_get('enable_dl') != 1 ||
 720              ini_get('safe_mode') == 1
 721          ) {
 722              return false;
 723          }
 724  
 725          if (OS_WINDOWS) {
 726              $suffix = '.dll';
 727          } elseif (PHP_OS == 'HP-UX') {
 728              $suffix = '.sl';
 729          } elseif (PHP_OS == 'AIX') {
 730              $suffix = '.a';
 731          } elseif (PHP_OS == 'OSX') {
 732              $suffix = '.bundle';
 733          } else {
 734              $suffix = '.so';
 735          }
 736  
 737          return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
 738      }
 739  }
 740  
 741  if (PEAR_ZE2) {
 742      include_once  'PEAR5.php';
 743  }
 744  
 745  function _PEAR_call_destructors()
 746  {
 747      global $_PEAR_destructor_object_list;
 748      if (is_array($_PEAR_destructor_object_list) &&
 749          sizeof($_PEAR_destructor_object_list))
 750      {
 751          reset($_PEAR_destructor_object_list);
 752          if (PEAR_ZE2) {
 753              $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
 754          } else {
 755              $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
 756          }
 757  
 758          if ($destructLifoExists) {
 759              $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
 760          }
 761  
 762          foreach ($_PEAR_destructor_object_list as $k => $objref) {
 763              $classname = get_class($objref);
 764              while ($classname) {
 765                  $destructor = "_$classname";
 766                  if (method_exists($objref, $destructor)) {
 767                      $objref->$destructor();
 768                      break;
 769                  } else {
 770                      $classname = get_parent_class($classname);
 771                  }
 772              }
 773          }
 774          // Empty the object list to ensure that destructors are
 775          // not called more than once.
 776          $_PEAR_destructor_object_list = array();
 777      }
 778  
 779      // Now call the shutdown functions
 780      if (
 781          isset($GLOBALS['_PEAR_shutdown_funcs']) &&
 782          is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
 783          !empty($GLOBALS['_PEAR_shutdown_funcs'])
 784      ) {
 785          foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
 786              call_user_func_array($value[0], $value[1]);
 787          }
 788      }
 789  }
 790  
 791  /**
 792   * Standard PEAR error class for PHP 4
 793   *
 794   * This class is supserseded by {@link PEAR_Exception} in PHP 5
 795   *
 796   * @category   pear
 797   * @package    PEAR
 798   * @author     Stig Bakken <ssb@php.net>
 799   * @author     Tomas V.V. Cox <cox@idecnet.com>
 800   * @author     Gregory Beaver <cellog@php.net>
 801   * @copyright  1997-2006 The PHP Group
 802   * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 803   * @version    Release: 1.9.1
 804   * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
 805   * @see        PEAR::raiseError(), PEAR::throwError()
 806   * @since      Class available since PHP 4.0.2
 807   */
 808  class PEAR_Error
 809  {
 810      var $error_message_prefix = '';
 811      var $mode                 = PEAR_ERROR_RETURN;
 812      var $level                = E_USER_NOTICE;
 813      var $code                 = -1;
 814      var $message              = '';
 815      var $userinfo             = '';
 816      var $backtrace            = null;
 817  
 818      /**
 819       * PEAR_Error constructor
 820       *
 821       * @param string $message  message
 822       *
 823       * @param int $code     (optional) error code
 824       *
 825       * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
 826       * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
 827       * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
 828       *
 829       * @param mixed $options   (optional) error level, _OR_ in the case of
 830       * PEAR_ERROR_CALLBACK, the callback function or object/method
 831       * tuple.
 832       *
 833       * @param string $userinfo (optional) additional user/debug info
 834       *
 835       * @access public
 836       *
 837       */
 838      function __construct($message = 'unknown error', $code = null,
 839                          $mode = null, $options = null, $userinfo = null)
 840      {
 841          if ($mode === null) {
 842              $mode = PEAR_ERROR_RETURN;
 843          }
 844          $this->message   = $message;
 845          $this->code      = $code;
 846          $this->mode      = $mode;
 847          $this->userinfo  = $userinfo;
 848  
 849          if (PEAR_ZE2) {
 850              $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
 851          } else {
 852              $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
 853          }
 854  
 855          if (!$skiptrace) {
 856              $this->backtrace = debug_backtrace();
 857              if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
 858                  unset($this->backtrace[0]['object']);
 859              }
 860          }
 861  
 862          if ($mode & PEAR_ERROR_CALLBACK) {
 863              $this->level = E_USER_NOTICE;
 864              $this->callback = $options;
 865          } else {
 866              if ($options === null) {
 867                  $options = E_USER_NOTICE;
 868              }
 869  
 870              $this->level = $options;
 871              $this->callback = null;
 872          }
 873  
 874          if ($this->mode & PEAR_ERROR_PRINT) {
 875              if (is_null($options) || is_int($options)) {
 876                  $format = "%s";
 877              } else {
 878                  $format = $options;
 879              }
 880  
 881              printf($format, $this->getMessage());
 882          }
 883  
 884          if ($this->mode & PEAR_ERROR_TRIGGER) {
 885              trigger_error($this->getMessage(), $this->level);
 886          }
 887  
 888          if ($this->mode & PEAR_ERROR_DIE) {
 889              $msg = $this->getMessage();
 890              if (is_null($options) || is_int($options)) {
 891                  $format = "%s";
 892                  if (substr($msg, -1) != "\n") {
 893                      $msg .= "\n";
 894                  }
 895              } else {
 896                  $format = $options;
 897              }
 898              die(sprintf($format, $msg));
 899          }
 900  
 901          if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
 902              call_user_func($this->callback, $this);
 903          }
 904  
 905          if ($this->mode & PEAR_ERROR_EXCEPTION) {
 906              trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
 907              eval('$e = new Exception($this->message, $this->code);throw($e);');
 908          }
 909      }
 910  
 911      /**
 912       * Old syntax of class constructor for backward compatibility.
 913       */
 914      public function PEAR_Error($message = 'unknown error', $code = null,
 915                          $mode = null, $options = null, $userinfo = null) {
 916          self::__construct($message, $code, $mode, $options, $userinfo);
 917      }
 918  
 919      /**
 920       * Get the error mode from an error object.
 921       *
 922       * @return int error mode
 923       * @access public
 924       */
 925      function getMode()
 926      {
 927          return $this->mode;
 928      }
 929  
 930      /**
 931       * Get the callback function/method from an error object.
 932       *
 933       * @return mixed callback function or object/method array
 934       * @access public
 935       */
 936      function getCallback()
 937      {
 938          return $this->callback;
 939      }
 940  
 941      /**
 942       * Get the error message from an error object.
 943       *
 944       * @return  string  full error message
 945       * @access public
 946       */
 947      function getMessage()
 948      {
 949          return ($this->error_message_prefix . $this->message);
 950      }
 951  
 952      /**
 953       * Get error code from an error object
 954       *
 955       * @return int error code
 956       * @access public
 957       */
 958       function getCode()
 959       {
 960          return $this->code;
 961       }
 962  
 963      /**
 964       * Get the name of this error/exception.
 965       *
 966       * @return string error/exception name (type)
 967       * @access public
 968       */
 969      function getType()
 970      {
 971          return get_class($this);
 972      }
 973  
 974      /**
 975       * Get additional user-supplied information.
 976       *
 977       * @return string user-supplied information
 978       * @access public
 979       */
 980      function getUserInfo()
 981      {
 982          return $this->userinfo;
 983      }
 984  
 985      /**
 986       * Get additional debug information supplied by the application.
 987       *
 988       * @return string debug information
 989       * @access public
 990       */
 991      function getDebugInfo()
 992      {
 993          return $this->getUserInfo();
 994      }
 995  
 996      /**
 997       * Get the call backtrace from where the error was generated.
 998       * Supported with PHP 4.3.0 or newer.
 999       *
1000       * @param int $frame (optional) what frame to fetch
1001       * @return array Backtrace, or NULL if not available.
1002       * @access public
1003       */
1004      function getBacktrace($frame = null)
1005      {
1006          if (defined('PEAR_IGNORE_BACKTRACE')) {
1007              return null;
1008          }
1009          if ($frame === null) {
1010              return $this->backtrace;
1011          }
1012          return $this->backtrace[$frame];
1013      }
1014  
1015      function addUserInfo($info)
1016      {
1017          if (empty($this->userinfo)) {
1018              $this->userinfo = $info;
1019          } else {
1020              $this->userinfo .= " ** $info";
1021          }
1022      }
1023  
1024      function __toString()
1025      {
1026          return $this->getMessage();
1027      }
1028  
1029      /**
1030       * Make a string representation of this object.
1031       *
1032       * @return string a string with an object summary
1033       * @access public
1034       */
1035      function toString()
1036      {
1037          $modes = array();
1038          $levels = array(E_USER_NOTICE  => 'notice',
1039                          E_USER_WARNING => 'warning',
1040                          E_USER_ERROR   => 'error');
1041          if ($this->mode & PEAR_ERROR_CALLBACK) {
1042              if (is_array($this->callback)) {
1043                  $callback = (is_object($this->callback[0]) ?
1044                      strtolower(get_class($this->callback[0])) :
1045                      $this->callback[0]) . '::' .
1046                      $this->callback[1];
1047              } else {
1048                  $callback = $this->callback;
1049              }
1050              return sprintf('[%s: message="%s" code=%d mode=callback '.
1051                             'callback=%s prefix="%s" info="%s"]',
1052                             strtolower(get_class($this)), $this->message, $this->code,
1053                             $callback, $this->error_message_prefix,
1054                             $this->userinfo);
1055          }
1056          if ($this->mode & PEAR_ERROR_PRINT) {
1057              $modes[] = 'print';
1058          }
1059          if ($this->mode & PEAR_ERROR_TRIGGER) {
1060              $modes[] = 'trigger';
1061          }
1062          if ($this->mode & PEAR_ERROR_DIE) {
1063              $modes[] = 'die';
1064          }
1065          if ($this->mode & PEAR_ERROR_RETURN) {
1066              $modes[] = 'return';
1067          }
1068          return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
1069                         'prefix="%s" info="%s"]',
1070                         strtolower(get_class($this)), $this->message, $this->code,
1071                         implode("|", $modes), $levels[$this->level],
1072                         $this->error_message_prefix,
1073                         $this->userinfo);
1074      }
1075  }
1076  
1077  /*
1078   * Local Variables:
1079   * mode: php
1080   * tab-width: 4
1081   * c-basic-offset: 4
1082   * End:
1083   */