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