Translated using Weblate (Norwegian Bokmål)
[phpmyadmin.git] / libraries / Error.php
blob5901c0746cba15c972dd992aa8965fef9ec5c2a7
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Holds class PMA\libraries\Error
6 * @package PhpMyAdmin
7 */
8 namespace PMA\libraries;
10 use Exception;
12 /**
13 * a single error
15 * @package PhpMyAdmin
17 class Error extends Message
19 /**
20 * Error types
22 * @var array
24 static public $errortype = array (
25 0 => 'Internal error',
26 E_ERROR => 'Error',
27 E_WARNING => 'Warning',
28 E_PARSE => 'Parsing Error',
29 E_NOTICE => 'Notice',
30 E_CORE_ERROR => 'Core Error',
31 E_CORE_WARNING => 'Core Warning',
32 E_COMPILE_ERROR => 'Compile Error',
33 E_COMPILE_WARNING => 'Compile Warning',
34 E_USER_ERROR => 'User Error',
35 E_USER_WARNING => 'User Warning',
36 E_USER_NOTICE => 'User Notice',
37 E_STRICT => 'Runtime Notice',
38 E_DEPRECATED => 'Deprecation Notice',
39 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
42 /**
43 * Error levels
45 * @var array
47 static public $errorlevel = array (
48 0 => 'error',
49 E_ERROR => 'error',
50 E_WARNING => 'error',
51 E_PARSE => 'error',
52 E_NOTICE => 'notice',
53 E_CORE_ERROR => 'error',
54 E_CORE_WARNING => 'error',
55 E_COMPILE_ERROR => 'error',
56 E_COMPILE_WARNING => 'error',
57 E_USER_ERROR => 'error',
58 E_USER_WARNING => 'error',
59 E_USER_NOTICE => 'notice',
60 E_STRICT => 'notice',
61 E_DEPRECATED => 'notice',
62 E_RECOVERABLE_ERROR => 'error',
65 /**
66 * The file in which the error occurred
68 * @var string
70 protected $file = '';
72 /**
73 * The line in which the error occurred
75 * @var integer
77 protected $line = 0;
79 /**
80 * Holds the backtrace for this error
82 * @var array
84 protected $backtrace = array();
86 /**
87 * Hide location of errors
89 protected $hide_location = false;
91 /**
92 * Constructor
94 * @param integer $errno error number
95 * @param string $errstr error message
96 * @param string $errfile file
97 * @param integer $errline line
99 public function __construct($errno, $errstr, $errfile, $errline)
101 $this->setNumber($errno);
102 $this->setMessage($errstr, false);
103 $this->setFile($errfile);
104 $this->setLine($errline);
106 // This function can be disabled in php.ini
107 if (function_exists('debug_backtrace')) {
108 $backtrace = @debug_backtrace();
109 // remove last three calls:
110 // debug_backtrace(), handleError() and addError()
111 $backtrace = array_slice($backtrace, 3);
112 } else {
113 $backtrace = array();
116 $this->setBacktrace($backtrace);
120 * Process backtrace to avoid path disclossures, objects and so on
122 * @param array $backtrace backtrace
124 * @return array
126 public static function processBacktrace($backtrace)
128 $result = array();
130 $members = array('line', 'function', 'class', 'type');
132 foreach ($backtrace as $idx => $step) {
133 /* Create new backtrace entry */
134 $result[$idx] = array();
136 /* Make path relative */
137 if (isset($step['file'])) {
138 $result[$idx]['file'] = self::relPath($step['file']);
141 /* Store members we want */
142 foreach ($members as $name) {
143 if (isset($step[$name])) {
144 $result[$idx][$name] = $step[$name];
148 /* Store simplified args */
149 if (isset($step['args'])) {
150 foreach ($step['args'] as $key => $arg) {
151 $result[$idx]['args'][$key] = self::getArg($arg, $step['function']);
156 return $result;
160 * Toggles location hiding
162 * @param boolean $hide Whether to hide
164 * @return void
166 public function setHideLocation($hide)
168 $this->hide_location = $hide;
172 * sets PMA\libraries\Error::$_backtrace
174 * We don't store full arguments to avoid wakeup or memory problems.
176 * @param array $backtrace backtrace
178 * @return void
180 public function setBacktrace($backtrace)
182 $this->backtrace = self::processBacktrace($backtrace);
186 * sets PMA\libraries\Error::$_line
188 * @param integer $line the line
190 * @return void
192 public function setLine($line)
194 $this->line = $line;
198 * sets PMA\libraries\Error::$_file
200 * @param string $file the file
202 * @return void
204 public function setFile($file)
206 $this->file = self::relPath($file);
211 * returns unique PMA\libraries\Error::$hash, if not exists it will be created
213 * @return string PMA\libraries\Error::$hash
215 public function getHash()
217 try {
218 $backtrace = serialize($this->getBacktrace());
219 } catch(Exception $e) {
220 $backtrace = '';
222 if ($this->hash === null) {
223 $this->hash = md5(
224 $this->getNumber() .
225 $this->getMessage() .
226 $this->getFile() .
227 $this->getLine() .
228 $backtrace
232 return $this->hash;
236 * returns PMA\libraries\Error::$_backtrace for first $count frames
237 * pass $count = -1 to get full backtrace.
238 * The same can be done by not passing $count at all.
240 * @param integer $count Number of stack frames.
242 * @return array PMA\libraries\Error::$_backtrace
244 public function getBacktrace($count = -1)
246 if ($count != -1) {
247 return array_slice($this->backtrace, 0, $count);
249 return $this->backtrace;
253 * returns PMA\libraries\Error::$file
255 * @return string PMA\libraries\Error::$file
257 public function getFile()
259 return $this->file;
263 * returns PMA\libraries\Error::$line
265 * @return integer PMA\libraries\Error::$line
267 public function getLine()
269 return $this->line;
273 * returns type of error
275 * @return string type of error
277 public function getType()
279 return self::$errortype[$this->getNumber()];
283 * returns level of error
285 * @return string level of error
287 public function getLevel()
289 return self::$errorlevel[$this->getNumber()];
293 * returns title prepared for HTML Title-Tag
295 * @return string HTML escaped and truncated title
297 public function getHtmlTitle()
299 return htmlspecialchars(
300 mb_substr($this->getTitle(), 0, 100)
305 * returns title for error
307 * @return string
309 public function getTitle()
311 return $this->getType() . ': ' . $this->getMessage();
315 * Get HTML backtrace
317 * @return string
319 public function getBacktraceDisplay()
321 return self::formatBacktrace(
322 $this->getBacktrace(),
323 "<br />\n",
324 "<br />\n"
329 * return formatted backtrace field
331 * @param array $backtrace Backtrace data
332 * @param string $separator Arguments separator to use
333 * @param string $lines Lines separator to use
335 * @return string formatted backtrace
337 public static function formatBacktrace($backtrace, $separator, $lines)
339 $retval = '';
341 foreach ($backtrace as $step) {
342 if (isset($step['file']) && isset($step['line'])) {
343 $retval .= self::relPath($step['file'])
344 . '#' . $step['line'] . ': ';
346 if (isset($step['class'])) {
347 $retval .= $step['class'] . $step['type'];
349 $retval .= self::getFunctionCall($step, $separator);
350 $retval .= $lines;
353 return $retval;
357 * Formats function call in a backtrace
359 * @param array $step backtrace step
360 * @param string $separator Arguments separator to use
362 * @return string
364 public static function getFunctionCall($step, $separator)
366 $retval = $step['function'] . '(';
367 if (isset($step['args'])) {
368 if (count($step['args']) > 1) {
369 $retval .= $separator;
370 foreach ($step['args'] as $arg) {
371 $retval .= "\t";
372 $retval .= $arg;
373 $retval .= ',' . $separator;
375 } elseif (count($step['args']) > 0) {
376 foreach ($step['args'] as $arg) {
377 $retval .= $arg;
381 $retval .= ')';
382 return $retval;
386 * Get a single function argument
388 * if $function is one of include/require
389 * the $arg is converted to a relative path
391 * @param string $arg argument to process
392 * @param string $function function name
394 * @return string
396 public static function getArg($arg, $function)
398 $retval = '';
399 $include_functions = array(
400 'include',
401 'include_once',
402 'require',
403 'require_once',
405 $connect_functions = array(
406 'mysql_connect',
407 'mysql_pconnect',
408 'mysqli_connect',
409 'mysqli_real_connect',
410 'connect',
411 '_realConnect'
414 if (in_array($function, $include_functions)) {
415 $retval .= self::relPath($arg);
416 } elseif (in_array($function, $connect_functions)
417 && getType($arg) === 'string'
419 $retval .= getType($arg) . ' ********';
420 } elseif (is_scalar($arg)) {
421 $retval .= getType($arg) . ' '
422 . htmlspecialchars(var_export($arg, true));
423 } elseif (is_object($arg)) {
424 $retval .= '<Class:' . get_class($arg) . '>';
425 } else {
426 $retval .= getType($arg);
429 return $retval;
433 * Gets the error as string of HTML
435 * @return string
437 public function getDisplay()
439 $this->isDisplayed(true);
440 $retval = '<div class="' . $this->getLevel() . '">';
441 if (! $this->isUserError()) {
442 $retval .= '<strong>' . $this->getType() . '</strong>';
443 $retval .= ' in ' . $this->getFile() . '#' . $this->getLine();
444 $retval .= "<br />\n";
446 $retval .= $this->getMessage();
447 if (! $this->isUserError()) {
448 $retval .= "<br />\n";
449 $retval .= "<br />\n";
450 $retval .= "<strong>Backtrace</strong><br />\n";
451 $retval .= "<br />\n";
452 $retval .= $this->getBacktraceDisplay();
454 $retval .= '</div>';
456 return $retval;
460 * whether this error is a user error
462 * @return boolean
464 public function isUserError()
466 return $this->hide_location ||
467 ($this->getNumber() & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE));
471 * return short relative path to phpMyAdmin basedir
473 * prevent path disclosure in error message,
474 * and make users feel safe to submit error reports
476 * @param string $path path to be shorten
478 * @return string shortened path
480 public static function relPath($path)
482 $dest = @realpath($path);
484 /* Probably affected by open_basedir */
485 if ($dest === FALSE) {
486 return basename($path);
489 $Ahere = explode(
490 DIRECTORY_SEPARATOR,
491 realpath(__DIR__ . DIRECTORY_SEPARATOR . '..')
493 $Adest = explode(DIRECTORY_SEPARATOR, $dest);
495 $result = '.';
496 // && count ($Adest)>0 && count($Ahere)>0 )
497 while (implode(DIRECTORY_SEPARATOR, $Adest) != implode(DIRECTORY_SEPARATOR, $Ahere)) {
498 if (count($Ahere) > count($Adest)) {
499 array_pop($Ahere);
500 $result .= DIRECTORY_SEPARATOR . '..';
501 } else {
502 array_pop($Adest);
505 $path = $result . str_replace(implode(DIRECTORY_SEPARATOR, $Adest), '', $dest);
506 return str_replace(
507 DIRECTORY_SEPARATOR . PATH_SEPARATOR,
508 DIRECTORY_SEPARATOR,
509 $path