PEAR.php 35 KB

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