Fixed the exception system up.
This commit is contained in:
parent
5ce8c55ebf
commit
f3ff6ad6c2
12 changed files with 233 additions and 178 deletions
108
app/ExceptionHandler.php
Normal file
108
app/ExceptionHandler.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
/**
|
||||
* Holds the exception (and error) handler.
|
||||
* @package Sakura
|
||||
*/
|
||||
|
||||
namespace Sakura;
|
||||
|
||||
use ErrorException;
|
||||
use stdClass;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Exception handler.
|
||||
* @package Sakura
|
||||
* @author Julian van de Groep <me@flash.moe>
|
||||
*/
|
||||
class ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* Disables checking if the templating engine is available
|
||||
* @var bool
|
||||
*/
|
||||
private static $disableTemplate = false;
|
||||
|
||||
/**
|
||||
* The entry point for set_exception_handler.
|
||||
* @param Throwable $ex
|
||||
*/
|
||||
public static function exception(Throwable $ex)
|
||||
{
|
||||
try {
|
||||
$report = config('dev.report_host');
|
||||
} catch (Exception $ex) {
|
||||
$report = null;
|
||||
}
|
||||
|
||||
if ($report !== null) {
|
||||
self::report($ex, $report);
|
||||
}
|
||||
|
||||
self::view($ex, $report !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The entry point for set_error_handler.
|
||||
* @param int $severity
|
||||
* @param string $message
|
||||
* @param string $file
|
||||
* @param int $line
|
||||
*/
|
||||
public static function error($severity, $message, $file, $line)
|
||||
{
|
||||
throw new ErrorException($message, 0, $severity, $file, $line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an error message.
|
||||
* @param Throwable $ex
|
||||
* @param bool $reported
|
||||
*/
|
||||
private static function view(Throwable $ex, $reported = false)
|
||||
{
|
||||
http_response_code(500);
|
||||
|
||||
try {
|
||||
$debug = config('dev.show_errorsa');
|
||||
} catch (Exception $ex) {
|
||||
$debug = false;
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
header('Content-Type: text/plain');
|
||||
echo $ex;
|
||||
} else {
|
||||
if (!self::$disableTemplate && Template::available()) {
|
||||
echo view('errors/500', compact('reported'));
|
||||
} else {
|
||||
// Disable templates permanently so we don't get stuck in an infinite loop
|
||||
// if an exception is caused by the templating engine.
|
||||
self::$disableTemplate = true;
|
||||
echo "Something broke so badly that the error page failed to render.";
|
||||
|
||||
if ($reported) {
|
||||
echo " The developers have been notified of the issue.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts the exception as json to a remote server.
|
||||
* @param Throwable $ex
|
||||
* @param string $destination
|
||||
*/
|
||||
private static function report(Throwable $ex, $destination)
|
||||
{
|
||||
$send = new stdClass;
|
||||
$send->Date = date('c');
|
||||
$send->Message = $ex->getMessage();
|
||||
$send->Code = $ex->getCode();
|
||||
$send->File = $ex->getFile();
|
||||
$send->Line = $ex->getLine();
|
||||
$send->Trace = $ex->getTraceAsString();
|
||||
|
||||
Net::request($destination, 'POST', json_encode($send));
|
||||
}
|
||||
}
|
33
app/Net.php
33
app/Net.php
|
@ -201,26 +201,35 @@ class Net
|
|||
}
|
||||
|
||||
/**
|
||||
* Fetch a remote file.
|
||||
* Make a web request.
|
||||
* @param string $url
|
||||
* @return mixed
|
||||
* @param string $method
|
||||
* @param mixed $params
|
||||
* @return string
|
||||
*/
|
||||
public static function fetch($url)
|
||||
public static function request($url, $method = 'GET', $params = null)
|
||||
{
|
||||
// Create a curl instance
|
||||
$curl = curl_init();
|
||||
|
||||
// Set options
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 4);
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, 'Sakura/' . SAKURA_VERSION);
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CONNECTTIMEOUT => 2,
|
||||
CURLOPT_TIMEOUT => 4,
|
||||
CURLOPT_USERAGENT => 'Sakura/' . SAKURA_VERSION,
|
||||
]);
|
||||
|
||||
switch (strtolower($method)) {
|
||||
case 'post':
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_POST => is_array($params) ? count($params) : 1,
|
||||
CURLOPT_POSTFIELDS => is_array($params) ? http_build_query($params) : $params,
|
||||
]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Execute
|
||||
$curl = curl_exec($curl);
|
||||
|
||||
// Return the data
|
||||
return $curl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,11 +172,10 @@ class Router
|
|||
return self::$dispatcher->dispatch($method, $url);
|
||||
} catch (HttpMethodNotAllowedException $e) {
|
||||
http_response_code(403);
|
||||
return view('errors/403');
|
||||
} catch (HttpRouteNotFoundException $e) {
|
||||
http_response_code(404);
|
||||
return view('errors/404');
|
||||
}
|
||||
|
||||
// Default to the not found page
|
||||
return Template::render('global/notfound');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,15 @@ class Template
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if twig is available.
|
||||
* @return bool
|
||||
*/
|
||||
public static function available()
|
||||
{
|
||||
return self::$engine !== null && self::$name !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the parse variables.
|
||||
* @param array $vars
|
||||
|
|
|
@ -87,6 +87,9 @@ show_changelog = false
|
|||
; Host for the mahou serve command
|
||||
host = localhost:8000
|
||||
|
||||
; Host for dumping exceptions, sends the exception as a json object in a raw post request. Leave empty to disable.
|
||||
report_host =
|
||||
|
||||
; Mailing settings
|
||||
[mail]
|
||||
contact_address = sakura@localhost
|
||||
|
|
1
resources/views/yuuno/errors/403.twig
Normal file
1
resources/views/yuuno/errors/403.twig
Normal file
|
@ -0,0 +1 @@
|
|||
{% include 'errors/404.twig' %}
|
47
resources/views/yuuno/errors/404.twig
Normal file
47
resources/views/yuuno/errors/404.twig
Normal file
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Cannot find page</title>
|
||||
<link rel="stylesheet" type="text/css" href="/error.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<h1>
|
||||
<img src="/images/404-info.gif">
|
||||
The page cannot be found
|
||||
</h1>
|
||||
<p>
|
||||
The page you are looking for might have been removed, had its
|
||||
name changed, or is temporarily unavailable.
|
||||
</p>
|
||||
<hr>
|
||||
<h2>
|
||||
Please try the following:
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
If you typed the page address in the Address bar, make
|
||||
sure that it is spelled correctly.
|
||||
</li>
|
||||
<li>
|
||||
Open the <a href="{{ route('main.index') }}">flashii.net</a>
|
||||
home page, and then look for links to the information you want.
|
||||
</li>
|
||||
<li>
|
||||
Click the <img src="/images/404-back.gif"><a href="javascript:void(0);" onclick="history.go(-1);">Back</a>
|
||||
button to try another link.
|
||||
</li>
|
||||
<li>
|
||||
Click <img src="/images/404-search.gif"><a href="{{ route('main.search') }}">Search</a>
|
||||
to look for information on the Internet.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
HTTP 404 - File not found
|
||||
<br>
|
||||
Internet Explorer
|
||||
</h3>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
35
resources/views/yuuno/errors/500.twig
Normal file
35
resources/views/yuuno/errors/500.twig
Normal file
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Internal Server Error</title>
|
||||
<link rel="stylesheet" type="text/css" href="/error.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<h1>
|
||||
<img src="/images/404-info.gif">
|
||||
The page is currently unavailable
|
||||
</h1>
|
||||
<p>
|
||||
The page you are looking for experienced a severe explosion.
|
||||
</p>
|
||||
{% if reported %}
|
||||
<p>
|
||||
The developers have been notified of this issue, sorry for the inconvenience!
|
||||
</p>
|
||||
{% endif %}
|
||||
<hr>
|
||||
{% if message %}
|
||||
<h2>
|
||||
{{ message }}
|
||||
</h2>
|
||||
{% endif %}
|
||||
<h3>
|
||||
HTTP 500 - Internal Server Error
|
||||
<br>
|
||||
Internet Explorer
|
||||
</h3>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,47 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Cannot find page</title>
|
||||
<link rel="stylesheet" type="text/css" href="/error.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<h1>
|
||||
<img src="/images/404-info.gif">
|
||||
The page cannot be found
|
||||
</h1>
|
||||
<p>
|
||||
The page you are looking for might have been removed, had its
|
||||
name changed, or is temporarily unavailable.
|
||||
</p>
|
||||
<hr>
|
||||
<h2>
|
||||
Please try the following:
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
If you typed the page address in the Address bar, make
|
||||
sure that it is spelled correctly.
|
||||
</li>
|
||||
<li>
|
||||
Open the <a href="{{ route('main.index') }}">flashii.net</a>
|
||||
home page, and then look for links to the information you want.
|
||||
</li>
|
||||
<li>
|
||||
Click the <img src="/images/404-back.gif"><a href="javascript:void(0);" onclick="history.go(-1);">Back</a>
|
||||
button to try another link.
|
||||
</li>
|
||||
<li>
|
||||
Click <img src="/images/404-search.gif"><a href="{{ route('main.search') }}">Search</a>
|
||||
to look for information on the Internet.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
HTTP 404 - File not found
|
||||
<br>
|
||||
Internet Explorer
|
||||
</h3>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
10
sakura.php
10
sakura.php
|
@ -15,6 +15,9 @@ if (php_sapi_name() === 'cli') {
|
|||
define('IN_CLI', true);
|
||||
}
|
||||
|
||||
// Turn error reporting on regardless of anything
|
||||
error_reporting(-1);
|
||||
|
||||
// Override expiration variables
|
||||
ignore_user_abort(true);
|
||||
set_time_limit(0);
|
||||
|
@ -35,12 +38,13 @@ if (!file_exists(ROOT . 'vendor/autoload.php')) {
|
|||
// Include the autoloader
|
||||
require_once ROOT . 'vendor/autoload.php';
|
||||
|
||||
// Register the handlers
|
||||
set_exception_handler(['Sakura\ExceptionHandler', 'exception']);
|
||||
set_error_handler(['Sakura\ExceptionHandler', 'error']);
|
||||
|
||||
// Load the configuration
|
||||
Config::init(ROOT . 'config/config.ini');
|
||||
|
||||
set_error_handler('error_handler');
|
||||
error_reporting(config('dev.show_errors') ? -1 : 0);
|
||||
|
||||
// Start the database module
|
||||
$capsule = new DB;
|
||||
$capsule->addConnection(config('database'));
|
||||
|
|
113
utility.php
113
utility.php
|
@ -169,116 +169,3 @@ function send_mail($to, $subject, $body)
|
|||
|
||||
return $mailer->send($message);
|
||||
}
|
||||
|
||||
function error_handler($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
// Remove ROOT path from the error string and file location
|
||||
$errstr = str_replace(ROOT, '', $errstr);
|
||||
$errfile = str_replace(ROOT, '', $errfile);
|
||||
|
||||
switch ($errno) {
|
||||
case E_ERROR:
|
||||
case E_USER_ERROR:
|
||||
$error = "<b>FATAL ERROR</b>";
|
||||
break;
|
||||
|
||||
case E_WARNING:
|
||||
case E_USER_WARNING:
|
||||
$error = "<b>WARNING</b>";
|
||||
break;
|
||||
|
||||
case E_NOTICE:
|
||||
case E_USER_NOTICE:
|
||||
$error = "<b>NOTICE</b>";
|
||||
break;
|
||||
|
||||
default:
|
||||
$error = "<b>Unknown error type</b> [{$errno}]";
|
||||
}
|
||||
|
||||
$error .= ": {$errstr} on line {$errline} in {$errfile}";
|
||||
|
||||
// Truncate all previous outputs
|
||||
ob_clean();
|
||||
ob_end_clean();
|
||||
|
||||
// Check for dev mode
|
||||
$detailed = config('dev.show_errors');
|
||||
|
||||
// Build page (not even going to bother cleaning this one up)
|
||||
$errorPage = '<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sakura Internal Error</title>
|
||||
<style type="text/css">
|
||||
body { margin: 0; padding: 0; background: #EEE; color: #000;
|
||||
font: 12px/20px Verdana, Arial, Helvetica, sans-serif; }
|
||||
h1, h2 { font-weight: 100; background: #CAA; padding: 8px 5px 10px;
|
||||
margin: 0; font-style: italic; font-family: serif; }
|
||||
h1 { border-radius: 8px 8px 0 0; }
|
||||
h2 { margin: 0 -10px; }
|
||||
.container { border: 1px solid #CAA; margin: 10px auto; background: #FFF;
|
||||
box-shadow: 2px 2px 1em #888; max-width: 1024px; border-radius: 10px; }
|
||||
.container .inner { padding: 0 10px; }
|
||||
.container .inner .error { background: #555; color: #EEE; border-left: 5px solid #C22;
|
||||
padding: 4px 6px; text-shadow: 0 1px 1px #888; white-space: pre-wrap;
|
||||
word-wrap: break-word; margin: 12px 0; border-radius: 5px; box-shadow: inset 0 0 1em #333; }
|
||||
.container .footer { border-top: 1px solid #CAA; font-size: x-small; padding: 0 5px 1px; }
|
||||
a { color: #77E; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
a:active { color: #E77; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>An error occurred while executing the script.</h1>
|
||||
<div class="inner">
|
||||
<p>To prevent potential security risks or data loss Sakura has stopped execution of the script.</p>';
|
||||
|
||||
if (isset($errid)) {
|
||||
$errorPage .= '<p>The error and surrounding data has been logged.</p>
|
||||
<h2>' . (!$detailed ? 'Report the following text to a staff member' : 'Logged as') . '</h2>
|
||||
<pre class="error">' . $errid . '</pre>';
|
||||
} else {
|
||||
$errorPage .= '<p>Sakura was not able to log this error which could mean that there was an error
|
||||
with the database connection. If you\'re the system administrator check the database credentials
|
||||
and make sure the server is running and if you\'re not please let the system administrator
|
||||
know about this error if it occurs again.</p>';
|
||||
}
|
||||
|
||||
if ($detailed) {
|
||||
$errorPage .= ' <h2>Summary</h2>
|
||||
<pre class="error">' . $error . '</pre>
|
||||
<h2>Backtraces</h2>';
|
||||
|
||||
foreach (debug_backtrace() as $num => $trace) {
|
||||
$errorPage .= '<h3>#' . $num . '</h3><pre class="error">';
|
||||
|
||||
foreach ($trace as $key => $val) {
|
||||
$errorPage .=
|
||||
str_pad(
|
||||
'[' . $key . ']',
|
||||
12
|
||||
) . '=> ' . (
|
||||
is_array($val) || is_object($val) ?
|
||||
json_encode($val) :
|
||||
$val
|
||||
) . "\r\n";
|
||||
}
|
||||
|
||||
$errorPage .= '</pre>';
|
||||
}
|
||||
}
|
||||
|
||||
$errorPage .= '</div>
|
||||
<div class="footer">
|
||||
Sakura r' . SAKURA_VERSION . '.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
// Die and display error message
|
||||
die($errorPage);
|
||||
}
|
||||
|
|
Reference in a new issue