/dbadmin.com/public/libraries/Error_Handler.class.php

https://github.com/slikk66/DbAdmin · PHP · 450 lines · 226 code · 33 blank · 191 comment · 31 complexity · 8f8628a99965edaa8116449c4d11c2a5 MD5 · raw file

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Holds class PMA_Error_Handler
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. *
  13. */
  14. require_once './libraries/Error.class.php';
  15. /**
  16. * handling errors
  17. *
  18. * @package PhpMyAdmin
  19. */
  20. class PMA_Error_Handler
  21. {
  22. /**
  23. * holds errors to be displayed or reported later ...
  24. *
  25. * @var array of PMA_Error
  26. */
  27. protected $errors = array();
  28. /**
  29. * Constructor - set PHP error handler
  30. *
  31. */
  32. public function __construct()
  33. {
  34. /**
  35. * Do not set ourselves as error handler in case of testsuite.
  36. *
  37. * This behavior is not tested there and breaks other tests as they
  38. * rely on PHPUnit doing it's own error handling which we break here.
  39. */
  40. if (!defined('TESTSUITE')) {
  41. set_error_handler(array($this, 'handleError'));
  42. }
  43. }
  44. /**
  45. * Destructor
  46. *
  47. * stores errors in session
  48. *
  49. */
  50. public function __destruct()
  51. {
  52. if (isset($_SESSION)) {
  53. if (! isset($_SESSION['errors'])) {
  54. $_SESSION['errors'] = array();
  55. }
  56. if (isset($GLOBALS['cfg']['Error_Handler'])
  57. && $GLOBALS['cfg']['Error_Handler']['gather']
  58. ) {
  59. // remember all errors
  60. $_SESSION['errors'] = array_merge(
  61. $_SESSION['errors'],
  62. $this->errors
  63. );
  64. } else {
  65. // remember only not displayed errors
  66. foreach ($this->errors as $key => $error) {
  67. /**
  68. * We don't want to store all errors here as it would
  69. * explode user session. In case you want them all set
  70. * $GLOBALS['cfg']['Error_Handler']['gather'] to true
  71. */
  72. if (count($_SESSION['errors']) >= 20) {
  73. $error = new PMA_Error(
  74. 0,
  75. __('Too many error messages, some are not displayed.'),
  76. __FILE__,
  77. __LINE__
  78. );
  79. $_SESSION['errors'][$error->getHash()] = $error;
  80. break;
  81. } else if (($error instanceof PMA_Error)
  82. && ! $error->isDisplayed()
  83. ) {
  84. $_SESSION['errors'][$key] = $error;
  85. }
  86. }
  87. }
  88. }
  89. }
  90. /**
  91. * returns array with all errors
  92. *
  93. * @return array PMA_Error_Handler::$_errors
  94. */
  95. protected function getErrors()
  96. {
  97. $this->checkSavedErrors();
  98. return $this->errors;
  99. }
  100. /**
  101. * Error handler - called when errors are triggered/occured
  102. *
  103. * This calls the addError() function, escaping the error string
  104. *
  105. * @param integer $errno error number
  106. * @param string $errstr error string
  107. * @param string $errfile error file
  108. * @param integer $errline error line
  109. *
  110. * @return void
  111. */
  112. public function handleError($errno, $errstr, $errfile, $errline)
  113. {
  114. $this->addError($errstr, $errno, $errfile, $errline, true);
  115. }
  116. /**
  117. * Add an error; can also be called directly (with or without escaping)
  118. *
  119. * The following error types cannot be handled with a user defined function:
  120. * E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR,
  121. * E_COMPILE_WARNING,
  122. * and most of E_STRICT raised in the file where set_error_handler() is called.
  123. *
  124. * Do not use the context parameter as we want to avoid storing the
  125. * complete $GLOBALS inside $_SESSION['errors']
  126. *
  127. * @param string $errstr error string
  128. * @param integer $errno error number
  129. * @param string $errfile error file
  130. * @param integer $errline error line
  131. * @param boolean $escape whether to escape the error string
  132. *
  133. * @return void
  134. */
  135. public function addError($errstr, $errno, $errfile, $errline, $escape = true)
  136. {
  137. if ($escape) {
  138. $errstr = htmlspecialchars($errstr);
  139. }
  140. // create error object
  141. $error = new PMA_Error(
  142. $errno,
  143. $errstr,
  144. $errfile,
  145. $errline
  146. );
  147. // do not repeat errors
  148. $this->errors[$error->getHash()] = $error;
  149. switch ($error->getNumber()) {
  150. case E_USER_NOTICE:
  151. case E_USER_WARNING:
  152. case E_STRICT:
  153. case E_DEPRECATED:
  154. case E_NOTICE:
  155. case E_WARNING:
  156. case E_CORE_WARNING:
  157. case E_COMPILE_WARNING:
  158. case E_USER_ERROR:
  159. case E_RECOVERABLE_ERROR:
  160. // just collect the error
  161. // display is called from outside
  162. break;
  163. case E_ERROR:
  164. case E_PARSE:
  165. case E_CORE_ERROR:
  166. case E_COMPILE_ERROR:
  167. default:
  168. // FATAL error, dislay it and exit
  169. $this->dispFatalError($error);
  170. exit;
  171. break;
  172. }
  173. }
  174. /**
  175. * log error to configured log facility
  176. *
  177. * @param PMA_Error $error the error
  178. *
  179. * @return bool
  180. *
  181. * @todo finish!
  182. */
  183. protected function logError($error)
  184. {
  185. return error_log($error->getMessage());
  186. }
  187. /**
  188. * trigger a custom error
  189. *
  190. * @param string $errorInfo error message
  191. * @param integer $errorNumber error number
  192. * @param string $file file name
  193. * @param integer $line line number
  194. *
  195. * @return void
  196. */
  197. public function triggerError($errorInfo, $errorNumber = null,
  198. $file = null, $line = null
  199. ) {
  200. // we could also extract file and line from backtrace
  201. // and call handleError() directly
  202. trigger_error($errorInfo, $errorNumber);
  203. }
  204. /**
  205. * display fatal error and exit
  206. *
  207. * @param PMA_Error $error the error
  208. *
  209. * @return void
  210. */
  211. protected function dispFatalError($error)
  212. {
  213. if (! headers_sent()) {
  214. $this->dispPageStart($error);
  215. }
  216. $error->display();
  217. $this->dispPageEnd();
  218. exit;
  219. }
  220. /**
  221. * display the whole error page with all errors
  222. *
  223. * @return void
  224. */
  225. public function dispErrorPage()
  226. {
  227. if (! headers_sent()) {
  228. $this->dispPageStart();
  229. }
  230. $this->dispAllErrors();
  231. $this->dispPageEnd();
  232. }
  233. /**
  234. * Displays user errors not displayed
  235. *
  236. * @return void
  237. */
  238. public function dispUserErrors()
  239. {
  240. echo $this->getDispUserErrors();
  241. }
  242. /**
  243. * Renders user errors not displayed
  244. *
  245. * @return string
  246. */
  247. public function getDispUserErrors()
  248. {
  249. $retval = '';
  250. foreach ($this->getErrors() as $error) {
  251. if ($error->isUserError() && ! $error->isDisplayed()) {
  252. $retval .= $error->getDisplay();
  253. }
  254. }
  255. return $retval;
  256. }
  257. /**
  258. * display HTML header
  259. *
  260. * @param PMA_error $error the error
  261. *
  262. * @return void
  263. */
  264. protected function dispPageStart($error = null)
  265. {
  266. PMA_Response::getInstance()->disable();
  267. echo '<html><head><title>';
  268. if ($error) {
  269. echo $error->getTitle();
  270. } else {
  271. echo 'phpMyAdmin error reporting page';
  272. }
  273. echo '</title></head>';
  274. }
  275. /**
  276. * display HTML footer
  277. *
  278. * @return void
  279. */
  280. protected function dispPageEnd()
  281. {
  282. echo '</body></html>';
  283. }
  284. /**
  285. * display all errors regardless already displayed or user errors
  286. *
  287. * @return void
  288. */
  289. public function dispAllErrors()
  290. {
  291. foreach ($this->getErrors() as $error) {
  292. $error->display();
  293. }
  294. }
  295. /**
  296. * renders errors not displayed
  297. *
  298. * @return void
  299. */
  300. public function getDispErrors()
  301. {
  302. $retval = '';
  303. if ($GLOBALS['cfg']['Error_Handler']['display']) {
  304. foreach ($this->getErrors() as $error) {
  305. if ($error instanceof PMA_Error) {
  306. if (! $error->isDisplayed()) {
  307. $retval .= $error->getDisplay();
  308. }
  309. } else {
  310. ob_start();
  311. var_dump($error);
  312. $retval .= ob_get_contents();
  313. ob_end_clean();
  314. }
  315. }
  316. } else {
  317. $retval .= $this->getDispUserErrors();
  318. }
  319. return $retval;
  320. }
  321. /**
  322. * displays errors not displayed
  323. *
  324. * @return void
  325. */
  326. public function dispErrors()
  327. {
  328. echo $this->getDispErrors();
  329. }
  330. /**
  331. * look in session for saved errors
  332. *
  333. * @return void
  334. */
  335. protected function checkSavedErrors()
  336. {
  337. if (isset($_SESSION['errors'])) {
  338. // restore saved errors
  339. foreach ($_SESSION['errors'] as $hash => $error) {
  340. if ($error instanceof PMA_Error && ! isset($this->errors[$hash])) {
  341. $this->errors[$hash] = $error;
  342. }
  343. }
  344. //$this->errors = array_merge($_SESSION['errors'], $this->errors);
  345. // delete stored errors
  346. $_SESSION['errors'] = array();
  347. unset($_SESSION['errors']);
  348. }
  349. }
  350. /**
  351. * return count of errors
  352. *
  353. * @return integer number of errors occoured
  354. */
  355. public function countErrors()
  356. {
  357. return count($this->getErrors());
  358. }
  359. /**
  360. * return count of user errors
  361. *
  362. * @return integer number of user errors occoured
  363. */
  364. public function countUserErrors()
  365. {
  366. $count = 0;
  367. if ($this->countErrors()) {
  368. foreach ($this->getErrors() as $error) {
  369. if ($error->isUserError()) {
  370. $count++;
  371. }
  372. }
  373. }
  374. return $count;
  375. }
  376. /**
  377. * whether use errors occured or not
  378. *
  379. * @return boolean
  380. */
  381. public function hasUserErrors()
  382. {
  383. return (bool) $this->countUserErrors();
  384. }
  385. /**
  386. * whether errors occured or not
  387. *
  388. * @return boolean
  389. */
  390. public function hasErrors()
  391. {
  392. return (bool) $this->countErrors();
  393. }
  394. /**
  395. * number of errors to be displayed
  396. *
  397. * @return integer number of errors to be displayed
  398. */
  399. public function countDisplayErrors()
  400. {
  401. if ($GLOBALS['cfg']['Error_Handler']['display']) {
  402. return $this->countErrors();
  403. } else {
  404. return $this->countUserErrors();
  405. }
  406. }
  407. /**
  408. * whether there are errors to display or not
  409. *
  410. * @return boolean
  411. */
  412. public function hasDisplayErrors()
  413. {
  414. return (bool) $this->countDisplayErrors();
  415. }
  416. }
  417. ?>