ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
PEAR.php
Go to the documentation of this file.
1 <?php
31 define('PEAR_ERROR_RETURN', 1);
32 define('PEAR_ERROR_PRINT', 2);
33 define('PEAR_ERROR_TRIGGER', 4);
34 define('PEAR_ERROR_DIE', 8);
35 define('PEAR_ERROR_CALLBACK', 16);
40 define('PEAR_ERROR_EXCEPTION', 32);
42 define('PEAR_ZE2', (function_exists('version_compare') &&
43  version_compare(zend_version(), "2-dev", "ge")));
44 
45 if (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
56 if (!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 
102 class PEAR
103 {
104  // {{{ properties
105 
112  var $_debug = false;
113 
121 
130 
139 
146  var $_error_class = 'PEAR_Error';
147 
154  var $_expected_errors = array();
155 
156  // }}}
157 
158  // {{{ constructor
159 
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 
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 
230  function &getStaticProperty($class, $var)
231  {
232  static $properties;
233  if (!isset($properties[$class])) {
234  $properties[$class] = array();
235  }
236  if (!array_key_exists($var, $properties[$class])) {
237  $properties[$class][$var] = null;
238  }
239  return $properties[$class][$var];
240  }
241 
242  // }}}
243  // {{{ registerShutdownFunc()
244 
254  function registerShutdownFunc($func, $args = array())
255  {
256  // if we are called statically, there is a potential
257  // that no shutdown func is registered. Bug #6445
258  if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
259  register_shutdown_function("_PEAR_call_destructors");
260  $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
261  }
262  $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
263  }
264 
265  // }}}
266  // {{{ isError()
267 
279  function isError($data, $code = null)
280  {
281  if (is_a($data, 'PEAR_Error')) {
282  if (is_null($code)) {
283  return true;
284  } elseif (is_string($code)) {
285  return $data->getMessage() == $code;
286  } else {
287  return $data->getCode() == $code;
288  }
289  }
290  return false;
291  }
292 
293  // }}}
294  // {{{ setErrorHandling()
295 
335  function setErrorHandling($mode = null, $options = null)
336  {
337  if (isset($this) && is_a($this, 'PEAR')) {
338  $setmode = &$this->_default_error_mode;
339  $setoptions = &$this->_default_error_options;
340  } else {
341  $setmode = &$GLOBALS['_PEAR_default_error_mode'];
342  $setoptions = &$GLOBALS['_PEAR_default_error_options'];
343  }
344 
345  switch ($mode) {
347  case PEAR_ERROR_RETURN:
348  case PEAR_ERROR_PRINT:
349  case PEAR_ERROR_TRIGGER:
350  case PEAR_ERROR_DIE:
351  case null:
352  $setmode = $mode;
353  $setoptions = $options;
354  break;
355 
356  case PEAR_ERROR_CALLBACK:
357  $setmode = $mode;
358  // class/object method callback
359  if (is_callable($options)) {
360  $setoptions = $options;
361  } else {
362  trigger_error("invalid error callback", E_USER_WARNING);
363  }
364  break;
365 
366  default:
367  trigger_error("invalid error mode", E_USER_WARNING);
368  break;
369  }
370  }
371 
372  // }}}
373  // {{{ expectError()
374 
390  function expectError($code = '*')
391  {
392  if (is_array($code)) {
393  array_push($this->_expected_errors, $code);
394  } else {
395  array_push($this->_expected_errors, array($code));
396  }
397  return sizeof($this->_expected_errors);
398  }
399 
400  // }}}
401  // {{{ popExpect()
402 
409  function popExpect()
410  {
411  return array_pop($this->_expected_errors);
412  }
413 
414  // }}}
415  // {{{ _checkDelExpect()
416 
425  function _checkDelExpect($error_code)
426  {
427  $deleted = false;
428 
429  foreach ($this->_expected_errors AS $key => $error_array) {
430  if (in_array($error_code, $error_array)) {
431  unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
432  $deleted = true;
433  }
434 
435  // clean up empty arrays
436  if (0 == count($this->_expected_errors[$key])) {
437  unset($this->_expected_errors[$key]);
438  }
439  }
440  return $deleted;
441  }
442 
443  // }}}
444  // {{{ delExpect()
445 
455  function delExpect($error_code)
456  {
457  $deleted = false;
458 
459  if ((is_array($error_code) && (0 != count($error_code)))) {
460  // $error_code is a non-empty array here;
461  // we walk through it trying to unset all
462  // values
463  foreach($error_code as $key => $error) {
464  if ($this->_checkDelExpect($error)) {
465  $deleted = true;
466  } else {
467  $deleted = false;
468  }
469  }
470  return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
471  } elseif (!empty($error_code)) {
472  // $error_code comes alone, trying to unset it
473  if ($this->_checkDelExpect($error_code)) {
474  return true;
475  } else {
476  return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
477  }
478  } else {
479  // $error_code is empty
480  return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
481  }
482  }
483 
484  // }}}
485  // {{{ raiseError()
486 
524  function &raiseError($message = null,
525  $code = null,
526  $mode = null,
527  $options = null,
528  $userinfo = null,
529  $error_class = null,
530  $skipmsg = false)
531  {
532  // The error is yet a PEAR error object
533  if (is_object($message)) {
534  $code = $message->getCode();
535  $userinfo = $message->getUserInfo();
536  $error_class = $message->getType();
537  $message->error_message_prefix = '';
538  $message = $message->getMessage();
539  }
540 
541  if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
542  if ($exp[0] == "*" ||
543  (is_int(reset($exp)) && in_array($code, $exp)) ||
544  (is_string(reset($exp)) && in_array($message, $exp))) {
545  $mode = PEAR_ERROR_RETURN;
546  }
547  }
548  // No mode given, try global ones
549  if ($mode === null) {
550  // Class error handler
551  if (isset($this) && isset($this->_default_error_mode)) {
554  // Global error handler
555  } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
556  $mode = $GLOBALS['_PEAR_default_error_mode'];
557  $options = $GLOBALS['_PEAR_default_error_options'];
558  }
559  }
560 
561  if ($error_class !== null) {
562  $ec = $error_class;
563  } elseif (isset($this) && isset($this->_error_class)) {
564  $ec = $this->_error_class;
565  } else {
566  $ec = 'PEAR_Error';
567  }
568  if (intval(PHP_VERSION) < 5) {
569  // little non-eval hack to fix bug #12147
570  include 'PEAR/FixPHP5PEARWarnings.php';
571  return $a;
572  }
573  if ($skipmsg) {
574  $a = new $ec($code, $mode, $options, $userinfo);
575  } else {
576  $a = new $ec($message, $code, $mode, $options, $userinfo);
577  }
578  return $a;
579  }
580 
581  // }}}
582  // {{{ throwError()
583 
591  function &throwError($message = null,
592  $code = null,
593  $userinfo = null)
594  {
595  if (isset($this) && is_a($this, 'PEAR')) {
596  $a = &$this->raiseError($message, $code, null, null, $userinfo);
597  return $a;
598  } else {
599  $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
600  return $a;
601  }
602  }
603 
604  // }}}
605  function staticPushErrorHandling($mode, $options = null)
606  {
607  $stack = &$GLOBALS['_PEAR_error_handler_stack'];
608  $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
609  $def_options = &$GLOBALS['_PEAR_default_error_options'];
610  $stack[] = array($def_mode, $def_options);
611  switch ($mode) {
613  case PEAR_ERROR_RETURN:
614  case PEAR_ERROR_PRINT:
615  case PEAR_ERROR_TRIGGER:
616  case PEAR_ERROR_DIE:
617  case null:
618  $def_mode = $mode;
619  $def_options = $options;
620  break;
621 
622  case PEAR_ERROR_CALLBACK:
623  $def_mode = $mode;
624  // class/object method callback
625  if (is_callable($options)) {
626  $def_options = $options;
627  } else {
628  trigger_error("invalid error callback", E_USER_WARNING);
629  }
630  break;
631 
632  default:
633  trigger_error("invalid error mode", E_USER_WARNING);
634  break;
635  }
636  $stack[] = array($mode, $options);
637  return true;
638  }
639 
641  {
642  $stack = &$GLOBALS['_PEAR_error_handler_stack'];
643  $setmode = &$GLOBALS['_PEAR_default_error_mode'];
644  $setoptions = &$GLOBALS['_PEAR_default_error_options'];
645  array_pop($stack);
646  list($mode, $options) = $stack[sizeof($stack) - 1];
647  array_pop($stack);
648  switch ($mode) {
650  case PEAR_ERROR_RETURN:
651  case PEAR_ERROR_PRINT:
652  case PEAR_ERROR_TRIGGER:
653  case PEAR_ERROR_DIE:
654  case null:
655  $setmode = $mode;
656  $setoptions = $options;
657  break;
658 
659  case PEAR_ERROR_CALLBACK:
660  $setmode = $mode;
661  // class/object method callback
662  if (is_callable($options)) {
663  $setoptions = $options;
664  } else {
665  trigger_error("invalid error callback", E_USER_WARNING);
666  }
667  break;
668 
669  default:
670  trigger_error("invalid error mode", E_USER_WARNING);
671  break;
672  }
673  return true;
674  }
675 
676  // {{{ pushErrorHandling()
677 
690  function pushErrorHandling($mode, $options = null)
691  {
692  $stack = &$GLOBALS['_PEAR_error_handler_stack'];
693  if (isset($this) && is_a($this, 'PEAR')) {
694  $def_mode = &$this->_default_error_mode;
695  $def_options = &$this->_default_error_options;
696  } else {
697  $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
698  $def_options = &$GLOBALS['_PEAR_default_error_options'];
699  }
700  $stack[] = array($def_mode, $def_options);
701 
702  if (isset($this) && is_a($this, 'PEAR')) {
703  $this->setErrorHandling($mode, $options);
704  } else {
706  }
707  $stack[] = array($mode, $options);
708  return true;
709  }
710 
711  // }}}
712  // {{{ popErrorHandling()
713 
721  function popErrorHandling()
722  {
723  $stack = &$GLOBALS['_PEAR_error_handler_stack'];
724  array_pop($stack);
725  list($mode, $options) = $stack[sizeof($stack) - 1];
726  array_pop($stack);
727  if (isset($this) && is_a($this, 'PEAR')) {
728  $this->setErrorHandling($mode, $options);
729  } else {
731  }
732  return true;
733  }
734 
735  // }}}
736  // {{{ loadExtension()
737 
745  function loadExtension($ext)
746  {
747  if (!extension_loaded($ext)) {
748  // if either returns true dl() will produce a FATAL error, stop that
749  if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
750  return false;
751  }
752  if (OS_WINDOWS) {
753  $suffix = '.dll';
754  } elseif (PHP_OS == 'HP-UX') {
755  $suffix = '.sl';
756  } elseif (PHP_OS == 'AIX') {
757  $suffix = '.a';
758  } elseif (PHP_OS == 'OSX') {
759  $suffix = '.bundle';
760  } else {
761  $suffix = '.so';
762  }
763  return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
764  }
765  return true;
766  }
767 
768  // }}}
769 }
770 
771 // {{{ _PEAR_call_destructors()
772 
774 {
775  global $_PEAR_destructor_object_list;
776  if (is_array($_PEAR_destructor_object_list) &&
777  sizeof($_PEAR_destructor_object_list))
778  {
779  reset($_PEAR_destructor_object_list);
780  if (PEAR::getStaticProperty('PEAR', 'destructlifo')) {
781  $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
782  }
783  while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
784  $classname = get_class($objref);
785  while ($classname) {
786  $destructor = "_$classname";
787  if (method_exists($objref, $destructor)) {
788  $objref->$destructor();
789  break;
790  } else {
791  $classname = get_parent_class($classname);
792  }
793  }
794  }
795  // Empty the object list to ensure that destructors are
796  // not called more than once.
797  $_PEAR_destructor_object_list = array();
798  }
799 
800  // Now call the shutdown functions
801  if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
802  foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
803  call_user_func_array($value[0], $value[1]);
804  }
805  }
806 }
807 
808 // }}}
827 {
828  // {{{ properties
829 
832  var $level = E_USER_NOTICE;
833  var $code = -1;
834  var $message = '';
835  var $userinfo = '';
836  var $backtrace = null;
837 
838  // }}}
839  // {{{ constructor
840 
861  function PEAR_Error($message = 'unknown error', $code = null,
862  $mode = null, $options = null, $userinfo = null)
863  {
864  if ($mode === null) {
866  }
867  $this->message = $message;
868  $this->code = $code;
869  $this->mode = $mode;
870  $this->userinfo = $userinfo;
871  if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
872  $this->backtrace = debug_backtrace();
873  if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
874  unset($this->backtrace[0]['object']);
875  }
876  }
877  if ($mode & PEAR_ERROR_CALLBACK) {
878  $this->level = E_USER_NOTICE;
879  $this->callback = $options;
880  } else {
881  if ($options === null) {
882  $options = E_USER_NOTICE;
883  }
884  $this->level = $options;
885  $this->callback = null;
886  }
887  if ($this->mode & PEAR_ERROR_PRINT) {
888  if (is_null($options) || is_int($options)) {
889  $format = "%s";
890  } else {
891  $format = $options;
892  }
893  printf($format, $this->getMessage());
894  }
895  if ($this->mode & PEAR_ERROR_TRIGGER) {
896  trigger_error($this->getMessage(), $this->level);
897  }
898  if ($this->mode & PEAR_ERROR_DIE) {
899  $msg = $this->getMessage();
900  if (is_null($options) || is_int($options)) {
901  $format = "%s";
902  if (substr($msg, -1) != "\n") {
903  $msg .= "\n";
904  }
905  } else {
906  $format = $options;
907  }
908  die(sprintf($format, $msg));
909  }
910  if ($this->mode & PEAR_ERROR_CALLBACK) {
911  if (is_callable($this->callback)) {
912  call_user_func($this->callback, $this);
913  }
914  }
915  if ($this->mode & PEAR_ERROR_EXCEPTION) {
916  trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
917  eval('$e = new Exception($this->message, $this->code);throw($e);');
918  }
919  }
920 
921  // }}}
922  // {{{ getMode()
923 
930  function getMode() {
931  return $this->mode;
932  }
933 
934  // }}}
935  // {{{ getCallback()
936 
943  function getCallback() {
944  return $this->callback;
945  }
946 
947  // }}}
948  // {{{ getMessage()
949 
950 
957  function getMessage()
958  {
959  return ($this->error_message_prefix . $this->message);
960  }
961 
962 
963  // }}}
964  // {{{ getCode()
965 
972  function getCode()
973  {
974  return $this->code;
975  }
976 
977  // }}}
978  // {{{ getType()
979 
986  function getType()
987  {
988  return get_class($this);
989  }
990 
991  // }}}
992  // {{{ getUserInfo()
993 
1000  function getUserInfo()
1001  {
1002  return $this->userinfo;
1003  }
1004 
1005  // }}}
1006  // {{{ getDebugInfo()
1007 
1014  function getDebugInfo()
1015  {
1016  return $this->getUserInfo();
1017  }
1018 
1019  // }}}
1020  // {{{ getBacktrace()
1021 
1030  function getBacktrace($frame = null)
1031  {
1032  if (defined('PEAR_IGNORE_BACKTRACE')) {
1033  return null;
1034  }
1035  if ($frame === null) {
1036  return $this->backtrace;
1037  }
1038  return $this->backtrace[$frame];
1039  }
1040 
1041  // }}}
1042  // {{{ addUserInfo()
1043 
1044  function addUserInfo($info)
1045  {
1046  if (empty($this->userinfo)) {
1047  $this->userinfo = $info;
1048  } else {
1049  $this->userinfo .= " ** $info";
1050  }
1051  }
1052 
1053  // }}}
1054  // {{{ toString()
1055  function __toString()
1056  {
1057  return $this->getMessage();
1058  }
1059  // }}}
1060  // {{{ toString()
1061 
1068  function toString() {
1069  $modes = array();
1070  $levels = array(E_USER_NOTICE => 'notice',
1071  E_USER_WARNING => 'warning',
1072  E_USER_ERROR => 'error');
1073  if ($this->mode & PEAR_ERROR_CALLBACK) {
1074  if (is_array($this->callback)) {
1075  $callback = (is_object($this->callback[0]) ?
1076  strtolower(get_class($this->callback[0])) :
1077  $this->callback[0]) . '::' .
1078  $this->callback[1];
1079  } else {
1080  $callback = $this->callback;
1081  }
1082  return sprintf('[%s: message="%s" code=%d mode=callback '.
1083  'callback=%s prefix="%s" info="%s"]',
1084  strtolower(get_class($this)), $this->message, $this->code,
1085  $callback, $this->error_message_prefix,
1086  $this->userinfo);
1087  }
1088  if ($this->mode & PEAR_ERROR_PRINT) {
1089  $modes[] = 'print';
1090  }
1091  if ($this->mode & PEAR_ERROR_TRIGGER) {
1092  $modes[] = 'trigger';
1093  }
1094  if ($this->mode & PEAR_ERROR_DIE) {
1095  $modes[] = 'die';
1096  }
1097  if ($this->mode & PEAR_ERROR_RETURN) {
1098  $modes[] = 'return';
1099  }
1100  return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
1101  'prefix="%s" info="%s"]',
1102  strtolower(get_class($this)), $this->message, $this->code,
1103  implode("|", $modes), $levels[$this->level],
1104  $this->error_message_prefix,
1105  $this->userinfo);
1106  }
1107 
1108  // }}}
1109 }
1110 
1111 /*
1112  * Local Variables:
1113  * mode: php
1114  * tab-width: 4
1115  * c-basic-offset: 4
1116  * End:
1117  */
1118 ?>