Skip to content

Commit

Permalink
Merge pull request #1486 from RaspAP/maint/exception-handler
Browse files Browse the repository at this point in the history
Exception handler class
  • Loading branch information
billz committed Dec 27, 2023
2 parents 27bc1d6 + e24b4cb commit fd38a22
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 0 deletions.
1 change: 1 addition & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
define('RASPI_ADMIN_DETAILS', RASPI_CONFIG.'/raspap.auth');
define('RASPI_WIFI_AP_INTERFACE', 'wlan0');
define('RASPI_CACHE_PATH', sys_get_temp_dir() . '/raspap');
define('RASPI_ERROR_LOG', sys_get_temp_dir() . '/raspap_error.log');
define('RASPI_DEBUG_LOG', 'raspap_debug.log');
define('RASPI_LOG_SIZE_LIMIT', 64);

Expand Down
1 change: 1 addition & 0 deletions includes/defaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'RASPI_ADMIN_DETAILS' => RASPI_CONFIG.'/raspap.auth',
'RASPI_WIFI_AP_INTERFACE' => 'wlan0',
'RASPI_CACHE_PATH' => sys_get_temp_dir() . '/raspap',
'RASPI_ERROR_LOG' => sys_get_temp_dir() . '/raspap_error.log',
'RASPI_DEBUG_LOG' => 'raspap_debug.log',
'RASPI_LOG_SIZE_LIMIT' => 64,

Expand Down
6 changes: 6 additions & 0 deletions includes/exceptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
require_once 'src/RaspAP/Exceptions/ExceptionHandler.php';

$handler = new RaspAP\Exceptions\ExceptionHandler;
?>

1 change: 1 addition & 0 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
require 'includes/csrf.php';
ensureCSRFSessionToken();

require_once 'includes/exceptions.php';
require_once 'includes/config.php';
require_once 'includes/autoload.php';
require_once 'includes/defaults.php';
Expand Down
Binary file modified locale/en_US/LC_MESSAGES/messages.mo
Binary file not shown.
8 changes: 8 additions & 0 deletions locale/en_US/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1520,3 +1520,11 @@ msgstr "Update complete"
msgid "An error occurred. Check the log at <code>/tmp/raspap_install.log</code>"
msgstr "An error occurred. Check the log at <code>/tmp/raspap_install.log</code>"

#: includes/exceptions.php

msgid "RaspAP Exception"
msgstr "RaspAP Exception"

msgid "An exception occurred"
msgstr "An exception occurred"

69 changes: 69 additions & 0 deletions src/RaspAP/Exceptions/ExceptionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/**
* Exception handler class
*
* @description A simple exception handler for RaspAP
* @author Bill Zimmerman <billzimmerman@gmail.com>
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
* @see
*/

declare(strict_types=1);

namespace RaspAP\Exceptions;

use RaspAP\Exceptions\HtmlErrorRenderer;

class ExceptionHandler
{

public function __construct()
{
$this->setExceptionHandler();
$this->setShutdownHandler();
}

public static function handleException($exception)
{
$errorMessage = (
'[' . date('Y-m-d H:i:s') . '] ' .
$exception->getMessage() . ' in ' .
$exception->getFile() . ' on line ' .
$exception->getLine() . PHP_EOL
);
// Log the exception
error_log($errorMessage, 3, RASPI_ERROR_LOG);

$renderer = new HtmlErrorRenderer();
$renderer->render($exception);
}

public static function handleShutdown()
{
$error = error_get_last();
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
$errorMessage = (
'[' . date('Y-m-d H:i:s') . '] ' .
$error['message'] . ' in ' .
$error['file'] . ' on line ' .
$error['line'] . PHP_EOL
);
error_log($errorMessage, 3, RASPI_ERROR_LOG);

$renderer = new HtmlErrorRenderer();
$renderer->render($exception);
}
}

protected function setExceptionHandler()
{
set_exception_handler(array($this, 'handleException'));
}

protected function setShutdownHandler()
{
register_shutdown_function(array($this, 'handleShutdown'));
}
}

106 changes: 106 additions & 0 deletions src/RaspAP/Exceptions/HtmlErrorRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

/**
* HTML error renderer class
*
* @description An HTML error renderer for RaspAP
* @author Bill Zimmerman <billzimmerman@gmail.com>
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
* @see
*/

declare(strict_types=1);

namespace RaspAP\Exceptions;

class HtmlErrorRenderer
{

public function __construct()
{
$this->charset = 'UTF-8';
$this->projectDir = $_SERVER['DOCUMENT_ROOT'];
$this->template = '/templates/exception.php';
$this->debug = true;
}

public function render($exception)
{
$message = $exception->getMessage();
$code = $exception->getCode();
$file = $exception->getFile();
$line = $exception->getLine();
$trace = $this->getExceptionTraceAsString($exception);

header('Content-Type: text/html; charset='.$this->charset);
if ($this->debug) {
header('X-Debug-Exception: '. rawurlencode($message));
header('X-Debug-Exception-File: '. rawurlencode($file).':'.$line);
}
$__template_data = compact(
"message",
"code",
"file",
"line",
"trace"
);
if (is_array($__template_data)) {
extract($__template_data);
}
$file = $this->projectDir . $this->template;
ob_start();
include $file;
echo ob_get_clean();
}

/**
* Improved exception trace
* @param object $e : exception
* @param array $seen : passed to recursive calls to accumulate trace lines already seen
* @return array of strings, one entry per trace line
* @see https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c
*/
public function getExceptionTraceAsString($e, $seen = null) {

$starter = $seen ? 'Thrown by: ' : '';
$result = array();
if (!$seen) $seen = array();
$trace = $e->getTrace();
$prev = $e->getPrevious();
$result[] = sprintf('%s%s: %s', $starter, get_class($e), $e->getMessage());
$file = $e->getFile();
$line = $e->getLine();

while (true) {
$current = "$file:$line";
if (is_array($seen) && in_array($current, $seen)) {
$result[] = sprintf(' ... %d more', count($trace)+1);
break;
}
$result[] = sprintf(' at %s%s%s(%s%s%s)',
count($trace) && array_key_exists('class', $trace[0]) ? str_replace('\\', '.', $trace[0]['class']) : '',
count($trace) && array_key_exists('class', $trace[0]) && array_key_exists('function', $trace[0]) ? '.' : '',
count($trace) && array_key_exists('function', $trace[0]) ? str_replace('\\', '.', $trace[0]['function']) : '(main)',
$line === null ? $file : basename($file),
$line === null ? '' : ':',
$line === null ? '' : $line);

if (is_array($seen)) {
$seen[] = "$file:$line";
}
if (!count($trace)) {
break;
}
$file = array_key_exists('file', $trace[0]) ? $trace[0]['file'] : 'Unknown Source';
$line = array_key_exists('file', $trace[0]) && array_key_exists('line', $trace[0]) && $trace[0]['line'] ? $trace[0]['line'] : null;
array_shift($trace);
}
$result = join(PHP_EOL, $result);
if ($prev) {
$result .= PHP_EOL . getExceptionTraceAsString($prev, $seen);
}
return $result;
}

}

30 changes: 30 additions & 0 deletions templates/exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo _("RaspAP Exception"); ?></title>
<link href="dist/bootstrap/css/bootstrap.css" rel="stylesheet">
<link href="dist/sb-admin-2/css/sb-admin-2.min.css" rel="stylesheet">
<link rel="shortcut icon" type="image/png" href="app/icons/favicon.png?ver=2.0">
</head>
<body id="page-top">
<div id="wrapper">
<div id="content-wrapper" class="d-flex flex-column">
<div id="content">
<div class="row">
<div class="col-lg-12">
<p class="text-light bg-danger pl-3 p-1"><?php echo _("RaspAP Exception"); ?></p>
</div>
<div class="col-lg-12 ml-3">
<h3 class="mt-2"><?php echo _("An exception occurred"); ?></h3>
<h5>Stack trace:</h5>
<pre><?php print_r($trace); ?></pre>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

0 comments on commit fd38a22

Please sign in to comment.