PageRenderTime 80ms CodeModel.GetById 41ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/Error.class.php

https://github.com/lanner/phpmyadmin
PHP | 413 lines | 226 code | 35 blank | 152 comment | 15 complexity | 064488760eff22ee6fe992ce53664165 MD5 | raw file
  1<?php
  2/* vim: set expandtab sw=4 ts=4 sts=4: */
  3/**
  4 * Holds class PMA_Error
  5 *
  6 * @package PhpMyAdmin
  7 */
  8
  9if (! defined('PHPMYADMIN')) {
 10    exit;
 11}
 12
 13/**
 14 * base class
 15 */
 16require_once './libraries/Message.class.php';
 17
 18/**
 19 * a single error
 20 *
 21 * @package PhpMyAdmin
 22 */
 23class PMA_Error extends PMA_Message
 24{
 25    /**
 26     * Error types
 27     *
 28     * @var array
 29     */
 30    static public $errortype = array (
 31        E_ERROR              => 'Error',
 32        E_WARNING            => 'Warning',
 33        E_PARSE              => 'Parsing Error',
 34        E_NOTICE             => 'Notice',
 35        E_CORE_ERROR         => 'Core Error',
 36        E_CORE_WARNING       => 'Core Warning',
 37        E_COMPILE_ERROR      => 'Compile Error',
 38        E_COMPILE_WARNING    => 'Compile Warning',
 39        E_USER_ERROR         => 'User Error',
 40        E_USER_WARNING       => 'User Warning',
 41        E_USER_NOTICE        => 'User Notice',
 42        E_STRICT             => 'Runtime Notice',
 43        E_DEPRECATED         => 'Deprecation Notice',
 44        E_RECOVERABLE_ERROR  => 'Catchable Fatal Error',
 45    );
 46
 47    /**
 48     * Error levels
 49     *
 50     * @var array
 51     */
 52    static public $errorlevel = array (
 53        E_ERROR              => 'error',
 54        E_WARNING            => 'error',
 55        E_PARSE              => 'error',
 56        E_NOTICE             => 'notice',
 57        E_CORE_ERROR         => 'error',
 58        E_CORE_WARNING       => 'error',
 59        E_COMPILE_ERROR      => 'error',
 60        E_COMPILE_WARNING    => 'error',
 61        E_USER_ERROR         => 'error',
 62        E_USER_WARNING       => 'error',
 63        E_USER_NOTICE        => 'notice',
 64        E_STRICT             => 'notice',
 65        E_DEPRECATED         => 'notice',
 66        E_RECOVERABLE_ERROR  => 'error',
 67    );
 68
 69    /**
 70     * The file in which the error occured
 71     *
 72     * @var string
 73     */
 74    protected $file = '';
 75
 76    /**
 77     * The line in which the error occured
 78     *
 79     * @var integer
 80     */
 81    protected $line = 0;
 82
 83    /**
 84     * Holds the backtrace for this error
 85     *
 86     * @var array
 87     */
 88    protected $backtrace = array();
 89
 90    /**
 91     * Unique id
 92     *
 93     * @var string
 94     */
 95    protected $hash = null;
 96
 97    /**
 98     * Constructor
 99     *
100     * @param integer $errno   error number
101     * @param string  $errstr  error message
102     * @param string  $errfile file
103     * @param integer $errline line
104     */
105    public function __construct($errno, $errstr, $errfile, $errline)
106    {
107        $this->setNumber($errno);
108        $this->setMessage($errstr, false);
109        $this->setFile($errfile);
110        $this->setLine($errline);
111
112        $backtrace = debug_backtrace();
113        // remove last three calls:
114        // debug_backtrace(), handleError() and addError()
115        $backtrace = array_slice($backtrace, 3);
116
117        $this->setBacktrace($backtrace);
118    }
119
120    /**
121     * sets PMA_Error::$_backtrace
122     *
123     * @param array $backtrace backtrace
124     *
125     * @return void
126     */
127    public function setBacktrace($backtrace)
128    {
129        $this->backtrace = $backtrace;
130    }
131
132    /**
133     * sets PMA_Error::$_line
134     *
135     * @param integer $line the line
136     *
137     * @return void
138     */
139    public function setLine($line)
140    {
141        $this->line = $line;
142    }
143
144    /**
145     * sets PMA_Error::$_file
146     *
147     * @param string $file the file
148     *
149     * @return void
150     */
151    public function setFile($file)
152    {
153        $this->file = PMA_Error::relPath($file);
154    }
155
156
157    /**
158     * returns unique PMA_Error::$hash, if not exists it will be created
159     *
160     * @return string PMA_Error::$hash
161     */
162    public function getHash()
163    {
164        try {
165            $backtrace = serialize($this->getBacktrace());
166        } catch(Exception $e) {
167            $backtrace = '';
168        }
169        if ($this->hash === null) {
170            $this->hash = md5(
171                $this->getNumber() .
172                $this->getMessage() .
173                $this->getFile() .
174                $this->getLine() .
175                $backtrace
176            );
177        }
178
179        return $this->hash;
180    }
181
182    /**
183     * returns PMA_Error::$_backtrace
184     *
185     * @return array PMA_Error::$_backtrace
186     */
187    public function getBacktrace()
188    {
189        return $this->backtrace;
190    }
191
192    /**
193     * returns PMA_Error::$file
194     *
195     * @return string PMA_Error::$file
196     */
197    public function getFile()
198    {
199        return $this->file;
200    }
201
202    /**
203     * returns PMA_Error::$line
204     *
205     * @return integer PMA_Error::$line
206     */
207    public function getLine()
208    {
209        return $this->line;
210    }
211
212    /**
213     * returns type of error
214     *
215     * @return string  type of error
216     */
217    public function getType()
218    {
219        return PMA_Error::$errortype[$this->getNumber()];
220    }
221
222    /**
223     * returns level of error
224     *
225     * @return string  level of error
226     */
227    public function getLevel()
228    {
229        return PMA_Error::$errorlevel[$this->getNumber()];
230    }
231
232    /**
233     * returns title prepared for HTML Title-Tag
234     *
235     * @return string   HTML escaped and truncated title
236     */
237    public function getHtmlTitle()
238    {
239        return htmlspecialchars(substr($this->getTitle(), 0, 100));
240    }
241
242    /**
243     * returns title for error
244     *
245     * @return string
246     */
247    public function getTitle()
248    {
249        return $this->getType() . ': ' . $this->getMessage();
250    }
251
252    /**
253     * Get HTML backtrace
254     *
255     * @return void
256     */
257    public function getBacktraceDisplay()
258    {
259        $retval = '';
260
261        foreach ($this->getBacktrace() as $step) {
262            if (isset($step['file']) && isset($step['line'])) {
263                $retval .= PMA_Error::relPath($step['file']) . '#' . $step['line'] . ': ';
264            }
265            if (isset($step['class'])) {
266                $retval .= $step['class'] . $step['type'];
267            }
268            $retval .= $step['function'] . '(';
269            if (isset($step['args']) && (count($step['args']) > 1)) {
270                $retval .= "<br />\n";
271                foreach ($step['args'] as $arg) {
272                    $retval .= "\t";
273                    $retval .= $this->getArg($arg, $step['function']);
274                    $retval .= ',' . "<br />\n";
275                }
276            } elseif (isset($step['args']) && (count($step['args']) > 0)) {
277                foreach ($step['args'] as $arg) {
278                    $retval .= $this->getArg($arg, $step['function']);
279                }
280            }
281            $retval .= ')' . "<br />\n";
282        }
283
284        return $retval;
285    }
286
287    /**
288     * Get a single function argument
289     *
290     * if $function is one of include/require
291     * the $arg is converted to a relative path
292     *
293     * @param string $arg
294     * @param string $function
295     *
296     * @return string
297     */
298    protected function getArg($arg, $function)
299    {
300        $retval = '';
301        $include_functions = array(
302            'include',
303            'include_once',
304            'require',
305            'require_once',
306        );
307        $connect_functions = array(
308            'mysql_connect',
309            'mysql_pconnect',
310            'mysqli_connect',
311            'mysqli_real_connect',
312            'PMA_DBI_connect',
313            'PMA_DBI_real_connect',
314        );
315
316        if (in_array($function, $include_functions)) {
317            $retval .= PMA_Error::relPath($arg);
318        } elseif (in_array($function, $connect_functions)
319            && getType($arg) === 'string'
320        ) {
321            $retval .= getType($arg) . ' ********';
322        } elseif (is_scalar($arg)) {
323            $retval .= getType($arg) . ' ' . htmlspecialchars($arg);
324        } else {
325            $retval .= getType($arg);
326        }
327
328        return $retval;
329    }
330
331    /**
332     * Gets the error as string of HTML
333     *
334     * @return string
335     */
336    public function getDisplay()
337    {
338        $this->isDisplayed(true);
339        $retval = '<div class="' . $this->getLevel() . '">';
340        if (! $this->isUserError()) {
341            $retval .= '<strong>' . $this->getType() . '</strong>';
342            $retval .= ' in ' . $this->getFile() . '#' . $this->getLine();
343            $retval .= "<br />\n";
344        }
345        $retval .= $this->getMessage();
346        if (! $this->isUserError()) {
347            $retval .= "<br />\n";
348            $retval .= "<br />\n";
349            $retval .= "<strong>Backtrace</strong><br />\n";
350            $retval .= "<br />\n";
351            $retval .= $this->getBacktraceDisplay();
352        }
353        $retval .= '</div>';
354
355        return $retval;
356    }
357
358    /**
359     * whether this error is a user error
360     *
361     * @return boolean
362     */
363    public function isUserError()
364    {
365        return $this->getNumber() & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE);
366    }
367
368    /**
369     * return short relative path to phpMyAdmin basedir
370     *
371     * prevent path disclusore in error message,
372     * and make users feel save to submit error reports
373     *
374     * @param string $dest path to be shorten
375     *
376     * @return string shortened path
377     * @static
378     */
379    static function relPath($dest)
380    {
381        $dest = realpath($dest);
382
383        if (substr(PHP_OS, 0, 3) == 'WIN') {
384            $path_separator = '\\';
385        } else {
386            $path_separator = '/';
387        }
388
389        $Ahere = explode(
390            $path_separator,
391            realpath(dirname(__FILE__) . $path_separator . '..')
392        );
393        $Adest = explode($path_separator, $dest);
394
395        $result = '.';
396        // && count ($Adest)>0 && count($Ahere)>0 )
397        while (implode($path_separator, $Adest) != implode($path_separator, $Ahere)) {
398            if (count($Ahere) > count($Adest)) {
399                array_pop($Ahere);
400                $result .= $path_separator . '..';
401            } else {
402                array_pop($Adest);
403            }
404        }
405        $path = $result . str_replace(implode($path_separator, $Adest), '', $dest);
406        return str_replace(
407            $path_separator . $path_separator,
408            $path_separator,
409            $path
410        );
411    }
412}
413?>