leilukin-tumbleblog/includes/error.php

483 lines
16 KiB
PHP

<?php
/**
* File: error
* Functions for handling and reporting errors.
*/
ini_set("display_errors", false);
ini_set("error_log", MAIN_DIR.DIR."error_log.txt");
# Set the appropriate error reporting level.
if (DEBUG)
error_reporting(E_ALL | E_STRICT);
else
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_USER_NOTICE);
# Set the error and exception handlers.
set_error_handler("error_composer");
set_exception_handler("exception_composer");
/**
* Function: error_composer
* Composes a message for the error() function to display.
*/
function error_composer($errno, $message, $file, $line) {
# Test for suppressed errors and excluded error levels.
if (!(error_reporting() & $errno))
return true;
$normalized = str_replace(
array("\t", "\n", "\r", "\0", "\x0B"),
" ",
$message
);
if (DEBUG)
error_log(
"ERROR: ".$errno." ".strip_tags($normalized).
" (".$file." on line ".$line.")"
);
error(body:$message, backtrace:debug_backtrace());
}
/**
* Function: exception_composer
* Composes a message for the error() function to display.
*/
function exception_composer($e) {
$errno = $e->getCode();
$message = $e->getMessage();
$file = $e->getFile();
$line = $e->getLine();
$normalized = str_replace(
array("\t", "\n", "\r", "\0", "\x0B"),
" ",
$message
);
if (DEBUG)
error_log(
"ERROR: ".$errno." ".strip_tags($normalized).
" (".$file." on line ".$line.")"
);
error(body:$message, backtrace:$e->getTrace());
}
/**
* Function: error
* Displays an error message via direct call or handler.
*
* Parameters:
* $title - The title for the error dialog.
* $body - The message for the error dialog.
* $backtrace - The trace of the error.
* $code - Numeric HTTP status code to set.
*/
function error($title = "", $body = "", $backtrace = array(), $code = 500)/*: never*/{
# Discard any additional output buffers.
while (OB_BASE_LEVEL < ob_get_level())
ob_end_clean();
# Clean the output buffer before we begin.
if (ob_get_contents() !== false)
ob_clean();
# Attempt to set headers to sane values and send a status code.
if (!headers_sent()) {
header("Content-Type: text/html; charset=UTF-8");
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 03 Jun 1991 05:30:00 GMT");
# Resend the content encoding header if transparent compression is on.
if (CAN_USE_ZLIB and ini_get("zlib.output_compression"))
header("Content-Encoding: ".(HTTP_ACCEPT_GZIP ? "gzip" : "deflate"));
switch ($code) {
case 400:
header($_SERVER['SERVER_PROTOCOL']." 400 Bad Request");
break;
case 401:
header($_SERVER['SERVER_PROTOCOL']." 401 Unauthorized");
break;
case 403:
header($_SERVER['SERVER_PROTOCOL']." 403 Forbidden");
break;
case 404:
header($_SERVER['SERVER_PROTOCOL']." 404 Not Found");
break;
case 405:
header($_SERVER['SERVER_PROTOCOL']." 405 Method Not Allowed");
break;
case 409:
header($_SERVER['SERVER_PROTOCOL']." 409 Conflict");
break;
case 410:
header($_SERVER['SERVER_PROTOCOL']." 410 Gone");
break;
case 413:
header($_SERVER['SERVER_PROTOCOL']." 413 Payload Too Large");
break;
case 422:
header($_SERVER['SERVER_PROTOCOL']." 422 Unprocessable Entity");
break;
case 429:
header($_SERVER['SERVER_PROTOCOL']." 429 Too Many Requests");
break;
case 431:
header($_SERVER['SERVER_PROTOCOL']." 431 Request Header Fields Too Large");
break;
case 501:
header($_SERVER['SERVER_PROTOCOL']." 501 Not Implemented");
break;
case 502:
header($_SERVER['SERVER_PROTOCOL']." 502 Bad Gateway");
break;
case 503:
header($_SERVER['SERVER_PROTOCOL']." 503 Service Unavailable");
break;
case 504:
header($_SERVER['SERVER_PROTOCOL']." 504 Gateway Timeout");
break;
default:
header($_SERVER['SERVER_PROTOCOL']." 500 Internal Server Error");
}
}
# Report in plain text if desirable or necessary because of a deep error.
if (
AJAX or
!function_exists("__") or
!function_exists("_f") or
!function_exists("fallback") or
!function_exists("fix") or
!function_exists("sanitize_html") or
!function_exists("logged_in") or
!file_exists(INCLUDES_DIR.DIR."config.json.php") or
!class_exists("Config") or
!method_exists("Config", "current") or
!isset(Config::current()->locale) or
!isset(Config::current()->chyrp_url)
)
exit("ERROR: ".strip_tags($body));
# We need this for the pretty error page.
$chyrp_url = fix(Config::current()->chyrp_url, true);
# Set fallbacks.
fallback($title, __("Error"));
fallback($body, __("An unspecified error has occurred."));
fallback($backtrace, array());
# Redact and escape the backtrace for display.
foreach ($backtrace as $index => &$trace) {
if (!isset($trace["file"]) or !isset($trace["line"]))
unset($backtrace[$index]);
else
$trace["file"] = fix(
str_replace(MAIN_DIR.DIR, "", $trace["file"]),
false,
true
);
}
#---------------------------------------------
# Output Starts
#---------------------------------------------
?>
<!DOCTYPE html>
<html dir="auto">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=640">
<title><?php echo strip_tags($title); ?></title>
<style type="text/css">
@font-face {
font-family: 'Open Sans webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/OpenSans-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/OpenSans-SemiBold.woff') format('woff');
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/OpenSans-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/OpenSans-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/OpenSans-SemiBoldItalic.woff') format('woff');
font-weight: 600;
font-style: italic;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/OpenSans-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'Cousine webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/Cousine-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Cousine webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/Cousine-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Cousine webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/Cousine-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Cousine webfont';
src: url('<?php echo $chyrp_url; ?>/fonts/Cousine-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
}
:root {
color-scheme: light dark;
}
*::selection {
color: #ffffff;
background-color: #ff7f00;
}
html, body, div, dl, dt, dd, ul, ol, li, p,
h1, h2, h3, h4, h5, h6, img, pre, code,
form, fieldset, input, select, textarea,
table, tbody, tr, th, td, legend, caption,
blockquote, aside, figure, figcaption {
margin: 0em;
padding: 0em;
border: 0em;
}
html {
font-size: 16px;
}
body {
font-size: 1rem;
font-family: "Open Sans webfont", sans-serif;
line-height: 1.5;
color: #1f1f23;
tab-size: 4;
background: #efefef;
margin: 2rem;
}
h1 {
font-size: 2em;
font-weight: bold;
margin: 1rem 0rem;
text-align: center;
}
h2 {
font-size: 1.5em;
font-weight: bold;
text-align: center;
margin: 1rem 0rem;
}
h3 {
font-size: 1em;
font-weight: 600;
margin: 1rem 0rem;
border-bottom: 1px solid #cfcfcf;
}
p {
width: fit-content;
margin: 0rem auto 1rem auto;
}
pre {
font-family: "Cousine webfont", monospace;
font-size: 0.85em;
background-color: #efefef;
margin: 1rem 0rem;
padding: 1rem;
overflow-x: auto;
white-space: pre;
}
code {
font-family: "Cousine webfont", monospace;
font-size: 0.85em;
background-color: #efefef;
padding: 0px 2px;
border: 1px solid #cfcfcf;
vertical-align: bottom;
white-space: break-spaces;
}
pre > code {
font-size: 0.85rem;
display: block;
border: none;
padding: 0px;
white-space: inherit;
}
strong {
font: inherit;
font-weight: bold;
color: #c11600;
}
em, dfn, cite, var {
font: inherit;
font-style: italic;
}
ul, ol {
margin-bottom: 1rem;
margin-inline-start: 2rem;
list-style-position: outside;
}
ol.backtrace {
font-family: "Cousine webfont", monospace;
font-size: 0.85rem;
word-break: break-all;
}
a:link,
a:visited {
color: #1f1f23;
text-decoration: underline;
text-underline-offset: 0.125em;
}
a:focus {
outline: #ff7f00 dashed 2px;
outline-offset: 1px;
}
a:hover,
a:focus,
a:active {
color: #1e57ba;
text-decoration: underline;
text-underline-offset: 0.125em;
}
a.big,
button {
box-sizing: border-box;
display: block;
clear: both;
font: inherit;
font-size: 1.25em;
text-align: center;
color: #1f1f23;
text-decoration: none;
margin: 1rem 0rem;
padding: 0.5rem;
background-color: #f2fbff;
border: 2px solid #b8cdd9;
border-radius: 0.25em;
cursor: pointer;
}
button {
width: 100%;
}
a.big:hover,
button:hover,
a.big:focus,
button:focus,
a.big:active,
button:active {
border-color: #1e57ba;
outline: none;
}
hr {
border: none;
clear: both;
border-top: 1px solid #cfcfcf;
margin: 2rem 0rem;
}
aside {
margin-bottom: 1rem;
padding: 0.5rem 1rem;
border: 1px solid #e5d7a1;
border-radius: 0.25em;
background-color: #fffecd;
}
.window {
width: 30rem;
background: #ffffff;
padding: 2rem;
margin: 0rem auto 0rem auto;
border-radius: 2rem;
}
.window > *:first-child {
margin-top: 0rem;
}
.window > *:last-child {
margin-bottom: 0rem;
}
@media (prefers-color-scheme: dark) {
body {
color: #ffffff;
background-color: #1f1f23;
}
.window {
color: #1f1f23;
background-color: #efefef;
}
hr {
border-color: #afafaf;
}
aside {
border-color: #afafaf;
}
pre {
background-color: #dfdfdf;
}
code {
background-color: #dfdfdf;
border-color: #afafaf;
}
}
</style>
</head>
<body>
<div role="alert" class="window">
<h1><?php echo sanitize_html($title); ?></h1>
<p><?php echo sanitize_html($body); ?>
<?php if (!empty($backtrace) and DEBUG): ?>
<h3><?php echo __("Backtrace"); ?></h3>
<ol class="backtrace">
<?php foreach ($backtrace as $trace): ?>
<li>
<?php echo _f("%s on line %d", array($trace["file"], (int) $trace["line"])); ?>
</li>
<?php endforeach; ?>
</ol>
<?php endif; ?>
<?php if (!logged_in() and ADMIN and $code == 403): ?>
<hr>
<a class="big" href="<?php echo $chyrp_url.'/admin/?action=login'; ?>">
<?php echo __("Log in"); ?>
</a>
<?php elseif (isset($_SESSION['redirect_to'])): ?>
<hr>
<a class="big" href="<?php echo $_SESSION['redirect_to']; ?>">
<?php echo __("Go back"); ?>
</a>
<?php endif; ?>
</div>
</body>
</html>
<?php
#---------------------------------------------
# Output Ends
#---------------------------------------------
# Terminate execution.
exit;
}