--- /dev/null
+<?php
+
+$desc = get_class($this->exception) . ' making ' . $this->request->method . ' request to ' . $this->request->SERVER['REQUEST_URI'];
+
+$msg = $this->exception->getMessage();
+if ($this->exception->getCode())
+ $msg = $this->exception->getCode(). ' : ' . $msg;
+
+$frames = $this->frames($this->exception);
+
+?><!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title><?php $this->e($desc) ?></title>
+ <style>
+ <?php
+ $do_not_overflow = 'width: 100%; text-overflow: ellipsis; overflow: hidden;';
+ $code = 'font-family: monospace; white-space: pre-wrap; word-wrap: break-word;';
+ ?>
+ html, body { padding: 0;margin:0; font-family: sans-serif; font-size: 12px; height:100%; }
+
+ #summary { background: #F50000; padding:20px; height: 100px; color: #ccc; font-weight: bold; }
+ #summary h1 { margin: 0; <?php echo $do_not_overflow ?> }
+ #summary h2 { margin: 10px 0; color: #eee; <?php echo $do_not_overflow ?> }
+
+ #sidebar { background:#eee; float: left; width: 260px; margin:0; padding: 0 20px; height: calc(100% - 140px); overflow: auto; border-right: 1px solid #ccc; }
+ #sidebar a { display: block; margin: 10px 0; color: #666; text-decoration: none; line-height: 1.5em; border-bottom: 1px dotted #ccc; padding: 10px 0; <?php echo $do_not_overflow ?> }
+ #sidebar h3 { color: #333; font-weight: bold; margin: 20px 0 0; padding-bottom: 1em; border-bottom: 1px solid #ccc; }
+
+ #content { margin-left: 300px; height: calc(100% - 140px); overflow: auto; padding: 0 20px; }
+
+ #content h2 { margin: 20px 0 10px;font-size:200%; }
+ #content h3 { margin: 10px 0 5px;font-size:150%; }
+
+ .dump {border: 1px dotted #666;<?php echo $code ?>}
+
+ table.values { padding: 0;margin:10px 0;border-collapse: collapse;table-layout:fixed;width:100%; }
+ table.values th { vertical-align: top; padding: 0.5em 1em 0.5em 0; text-align: left; width:200px; }
+ table.values td { padding: 0.5em 0; <?php echo $code ?> }
+ table.values tr:hover {background: #eee;}
+
+ .stackframe {padding: 1px 0;}
+
+ ol.source { padding: 10px; margin: 10px 0; list-style-position: outside; border: 1px dotted #666; background: #eee; }
+ ol.source li { color:#333; margin-left: 4em; background: #fff; <?php echo $code ?> }
+ ol.source li.current-line { background-color:#fcc; }
+ </style>
+</head>
+<body>
+ <!-- Summary -->
+ <div id="summary">
+ <h1><?php $this->e($desc) ?></h1>
+ <h2><?php $this->e($msg) ?></h2>
+ <p><?php echo $this->request->method ?> <?php $this->e($this->request->SERVER['REQUEST_URI']) ?></p>
+ </div>
+ <!-- /Summary -->
+
+ <div id="sidebar">
+ <a href="#request" title="Request">Request</a>
+ <a href="#response" title="Response">Response</a>
+ <h3>Stacktrace</h3>
+ <?php $i = 0; foreach ($frames as $frame): ?>
+ <a href="#stackframe-<?php echo $i; ?>" title="<?php echo $frame['func'] ?>">
+ <?php if ($frame['func']): ?>
+ <strong><?php echo $frame['func'] ?></strong><br>
+ <?php endif; ?>
+ <?php echo $frame['file'].' at '.$frame['line'] ?>
+ </a>
+ <?php ++$i; endforeach; ?>
+ </div>
+
+ <div id="content">
+ <div id="request">
+ <h2>Request</h2>
+
+ <?php $this->values('$_GET', $_GET) ?>
+
+ <?php $this->values('$_POST', $_POST) ?>
+
+ <?php $this->values('$_COOKIE', $_COOKIE) ?>
+
+ <?php $this->values('$_SERVER', $_SERVER) ?>
+
+ <?php $this->values('$_ENV', $_ENV) ?>
+
+ <?php $this->values('Raw Headers', $this->request->getHeaders()) ?>
+
+ <?php if ($this->request->getBody()): ?>
+ <h3>Raw Body</h3>
+ <div class="dump"><?php $this->e($this->request->getBody()) ?></div>
+ <?php endif; ?>
+ </div>
+
+ <div id="response">
+ <h2>Response</h2>
+ <?php $this->values('Headers', $this->parse_headers(headers_list())) ?>
+ </div>
+
+ <?php $i = 0; foreach ($frames as $frame): ?>
+ <div class="stackframe" id="stackframe-<?php echo $i; ?>">
+ <h2><?php echo $frame['func'] ? $frame['func'] : 'No function' ?></h2>
+ <h3><?php echo $frame['file'].' at '.$frame['line'] ?></h3>
+
+ <?php echo is_readable($frame['file']) ? $this->sourceFile($frame['file'], $frame['line']) : '' ?>
+
+ <?php $this->values('Arguments', $frame['args']) ?>
+ </div>
+ <?php ++$i; endforeach; ?>
+ </div>
+</body>
+</html>
+
--- /dev/null
+<?php
+
+class IPF_Server_Error_Page_Debug extends IPF_Error_Page
+{
+ protected function templateFile()
+ {
+ return '500_debug.html';
+ }
+
+ function debug_print_r($v, $indent=0)
+ {
+ $result = array();
+
+ if (is_object($v)) {
+ $props = method_exists($v, '__debugInfo') ? $v->__debugInfo() : get_object_vars($v);
+ $result[] = get_class($v) . ' Object';
+ $result[] = '{';
+ foreach ($props as $key => $val) {
+ $result[] = ' [' . $key . '] => ' . $this->debug_print_r($val, $indent+2);
+ }
+ $result[] = '}';
+ } elseif ($v instanceof stdClass) {
+ $result[] = 'stdClass';
+ $result[] = '{';
+ foreach ($v as $k => $v) {
+ $result[] = ' ' . $k . ' => ' . $this->debug_print_r($v, $indent+2);
+ }
+ $result[] = '}';
+ } elseif (is_array($v)) {
+ if ($v) {
+ $result[] = 'Array';
+ $result[] = '{';
+ foreach ($v as $k => $v) {
+ $result[] = ' [' . $k . '] => ' . $this->debug_print_r($v, $indent+2);
+ }
+ $result[] = '}';
+ } else {
+ $result[] = 'Array()';
+ }
+ } elseif (is_bool($v)) {
+ return $v ? 'true' : 'false';
+ } else {
+ $result = explode("\n", print_r($v, true));
+ }
+
+ $i = str_repeat(' ', $indent);
+ foreach ($result as &$line)
+ $line = $i . $line;
+ return ltrim(implode("\n", $result));
+ }
+
+ function parse_headers($list)
+ {
+ $result = array();
+ foreach ($list as $line) {
+ list($name, $value) = explode(':', $line, 2);
+ $result[$name] = $value;
+ }
+ return $result;
+ }
+
+ function values($name, $values)
+ {
+ if ($values) {
+ ?><h3><?php echo $name ?></h3>
+ <table class="values">
+ <?php foreach ($values as $name => $value): ?>
+ <tr>
+ <th><?php $this->e($name) ?></th>
+ <td><?php $this->e($this->debug_print_r($value)) ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </table><?php
+ }
+ }
+
+ function frames($exception)
+ {
+ $result = array();
+
+ $file = $exception->getFile();
+ $line = $exception->getLine();
+ foreach ($exception->getTrace() as $frame) {
+ $params = array();
+ if ($frame["function"]) {
+ try {
+ if ($frame["class"]) {
+ $r = new ReflectionMethod($frame["class"]."::".$frame["function"]);
+ } else {
+ $r = new ReflectionFunction($frame["function"]);
+ }
+ foreach ($r->getParameters() as $p) {
+ $params[$p->getPosition()] = $p->getName();
+ }
+ } catch (ReflectionException $e) {
+ }
+ }
+
+ $args = array();
+ foreach ($frame['args'] as $index => $arg) {
+ $name = array_key_exists($index, $params) ? $params[$index] : "<arg-{$index}>";
+ $args[$name] = $arg;
+ }
+
+ $result[] = array(
+ 'file' => $file,
+ 'line' => $line,
+ 'class' => @$frame['class'],
+ 'type' => @$frame['type'],
+ 'function' => @$frame['function'],
+ 'func' => @$frame['class'].@$frame['type'].@$frame['function'],
+ 'args' => $args,
+ );
+
+ $file = $frame['file'];
+ $line = $frame['line'];
+ }
+
+ $result[] = array(
+ 'file' => $file,
+ 'line' => $line,
+ 'class' => '',
+ 'type' => '',
+ 'function' => '',
+ 'func' => '',
+ 'args' => array(),
+ );
+
+ return $result;
+ }
+
+ function sourceFile($file, $line)
+ {
+ $start = max($line - 10, 0);
+ $ol = "<ol start={$start} class=source>";
+
+ $rows = explode('<br />', nl2br(highlight_file($file, true)));
+ $rows = array_slice($rows, $start, 20);
+
+ foreach ($rows as $k => $row) {
+ $attrs = ($k + $start === $line) ? ' class=current-line' : '';
+ $ol .= "<li{$attrs}>{$row}</li>";
+ }
+ $ol .= '</ol>';
+ return $ol;
+ }
+}
+
+++ /dev/null
-<?php
-
-use \PFF\HtmlBuilder\Tag as Tag;
-
-class IPF_HTTP_Response_ServerErrorDebug extends IPF_HTTP_Response
-{
- function __construct($request, $exception, $mimetype=null)
- {
- $this->status_code = 500;
- $page = new IPF_HTTP_ServerErrorDebugPage($request, $exception);
- $this->content = $page->html();
- }
-}
-
-function debug_print_r($v, $indent=0)
-{
- $result = array();
-
- if (is_object($v) && method_exists($v, '__debugInfo')) {
- $result[] = get_class($v) . ' Object';
- $result[] = '{';
- foreach ($v->__debugInfo() as $key => $val) {
- $result[] = ' [' . $key . '] => ' . debug_print_r($val, $indent+2);
- }
- $result[] = '}';
- } elseif ($v instanceof stdClass) {
- $result[] = 'stdClass';
- $result[] = '{';
- foreach ($v as $k => $v) {
- $result[] = ' ' . $k . ' => ' . debug_print_r($v, $indent+2);
- }
- $result[] = '}';
- } elseif (is_array($v)) {
- $result[] = 'Array';
- $result[] = '{';
- foreach ($v as $k => $v) {
- $result[] = ' [' . $k . '] => ' . debug_print_r($v, $indent+2);
- }
- $result[] = '}';
- } elseif (is_bool($v)) {
- return $v ? 'true' : 'false';
- } else {
- $result = explode("\n", print_r($v, true));
- }
-
- $i = str_repeat(' ', $indent);
- foreach ($result as &$line)
- $line = $i . $line;
- return ltrim(implode("\n", $result));
-}
-
-class IPF_HTTP_ServerErrorDebugPage
-{
- private $request, $exception, $desc;
-
- public function __construct($request, $exception)
- {
- $this->request = $request;
- $this->exception = $exception;
- $this->desc = get_class($this->exception)." making ".$_SERVER['REQUEST_METHOD']." request to ".$_SERVER['REQUEST_URI'];
- }
-
- function html()
- {
- return "<!DOCTYPE html>\n" . Tag::create('html', array('lang' => 'en'),
- Tag::head(null,
- Tag::meta(array('charset' => 'utf-8')),
- Tag::title(null, $this->desc),
- $this->css(),
- $this->js()),
- Tag::body(null,
- $this->Summary(),
- $this->SectionStacktrace(),
- $this->SectionRequest(),
- $this->SectionResponse()));
- }
-
-
- function Summary()
- {
- $msg = $this->exception->getMessage();
- if ($this->exception->getCode())
- $msg = $this->exception->getCode(). ' : ' . $msg;
-
- return Tag::div(array('id' => 'summary'),
- Tag::h1(null, $this->desc),
- Tag::h2(null, $msg),
- Tag::table(null,
- Tag::tr(null,
- Tag::th(null, 'PHP'),
- Tag::td(null, $this->exception->getFile().', line '.$this->exception->getLine())),
- Tag::tr(null,
- Tag::th(null, 'URI'),
- Tag::td(null, $_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI']))));
- }
-
-
- private function section($id, $title, $content)
- {
- return Tag::div(array('id' => $id, 'class' => 'section'))
- ->append(Tag::h2()
- ->append($title)
- ->append(' ')
- ->append(Tag::a(array('href' => '#', 'class' => 'section-toggle'))
- ->append(Tag::span(array('class' => 'section-switch'))->append('▶'))))
- ->append(Tag::div(array('class' => 'section-body'))
- ->append($content));
- }
-
-
- function SectionStacktrace()
- {
- return $this->section('traceback', 'Stacktrace',
- $this->StacktraceFrames());
- }
-
- function StacktraceFrames()
- {
- $ul = Tag::ul(array('class' => 'traceback'));
-
- $frames = $this->exception->getTrace();
- foreach ($frames as $frame) {
- if (!isset($frame['file'])) {
- $frame['file'] = 'No File';
- $frame['line'] = '0';
- }
- $name = '';
- if (isset($frame["class"]))
- $name .= $frame["class"].$frame["type"];
- if (isset($frame["function"]))
- $name .= $frame["function"];
-
- $li = Tag::li(array('class' => 'frame'),
- Tag::strong(null, $name),
- ' ['.$frame['file'].', line '.$frame['line'].']');
-
- if (isset($frame['args']) && count($frame['args']) > 0) {
- $li->append($this->StacktraceArgs($frame));
- }
-
- if (is_readable($frame['file']) ) {
- $li->append($this->StacktraceSourceFile($frame['file'], $frame['line']));
- } else {
- $li->append(Tag::div(array('class' => 'commands'), 'No src available'));
- }
-
- $ul->append($li);
- }
- return $ul;
- }
-
- function StacktraceArgs($frame)
- {
- $params = array();
- if (isset($frame["function"])) {
- if (isset($frame["class"])) {
- $r = new ReflectionMethod($frame["class"]."::".$frame["function"]);
- } else {
- $r = new ReflectionFunction($frame["function"]);
- }
- $params = $r->getParameters();
- }
-
- $tbody = Tag::tbody();
- foreach ($frame['args'] as $k => $v) {
- $name = isset($params[$k]) ? '$'.$params[$k]->name : '?';
- $tbody->append(Tag::tr(null,
- Tag::td(null, $k),
- Tag::td(null, $name),
- Tag::td(array('class' => 'code'),
- Tag::div()->raw(highlight_string(debug_print_r($v), true)))));
- }
-
- return Tag::div(array('class' => 'section'),
- Tag::div(array('class' => 'commands'),
- Tag::a(array('href' => '#', 'class' => 'section-toggle'),
- Tag::span(array('class' => 'section-switch'), '▶'),
- ' Args')),
- Tag::table(array('class' => 'section-body vars'),
- Tag::thead(null,
- Tag::tr(null,
- Tag::th(null, 'Arg'),
- Tag::th(null, 'Name'),
- Tag::th(null, 'Value'))),
- $tbody));
- }
-
- function StacktraceSourceFile($file, $line)
- {
- $start = max($line - 5, 0);
- $ol = Tag::ol(array('start' => $start));
-
- $rows = explode('<br />', nl2br(highlight_file($file, true)));
- $rows = array_slice($rows, $start, 10);
-
- foreach ($rows as $k => $row) {
- $li = Tag::li(null, Tag::code()->raw($row));
- if ($k + $start === $line)
- $li->addClass('current-line');
- $ol->append($li);
- }
-
- return Tag::div(array('class' => 'section'),
- Tag::div(array('class' => 'commands'),
- Tag::a(array('href' => '#', 'class' => 'section-toggle'),
- Tag::span(array('class' => 'section-switch'), '▶'),
- ' Src')),
- Tag::div(array('class' => 'section-body context'),
- $ol));
- }
-
-
- function SectionRequest()
- {
- return $this->section('request', 'Request', array(
- $this->RequestRaw(),
-
- Tag::h3(null, 'Request <span>(parsed)</span>'),
- Tag::h4(null, '$_GET'),
- $this->RequestSuperlobal($_GET),
-
- Tag::h4(null, '$_POST'),
- $this->RequestSuperlobal($_POST),
-
- Tag::h4(null, '$_COOKIE'),
- $this->RequestSuperlobal($_COOKIE),
-
- Tag::h4(null, '$_SERVER'),
- $this->RequestSuperlobal($_SERVER),
-
- Tag::h4(null, '$_ENV'),
- $this->RequestSuperlobal($_ENV),
- ));
- }
-
-
- function RequestRaw()
- {
- return array(
- Tag::h3(null, 'Request ', Tag::span('(raw)')),
- $this->RequestRawHeaders(),
- $this->RequestRawBody(),
- );
- }
-
- function RequestRawHeaders()
- {
- $r = array(
- Tag::h4('Headers'),
- );
- $headers = $this->request->getHeaders();
- if ($headers) {
- $h = Tag::p(array('class' => 'headers'));
- foreach ($headers as $name => $val) {
- $h->append($name.': '.$val)->append(Tag::br());
- }
- $r[] = $h;
- } else {
- $r[] = Tag::p(null, 'No headers.');
- }
- return $r;
- }
-
- function RequestRawBody()
- {
- $body = $this->request->getBody();
- if (!$body)
- return '';
-
- return array(
- Tag::h4('Body'),
- Tag::p(array('class' => 'req', 'style' => 'padding-bottom: 2em'),
- Tag::code(null, $body)),
- );
- }
-
-
- function RequestSuperlobal($var)
- {
- if (count($var)) {
- $table = Tag::table(array('class' => 'req'));
-
- $thead = Tag::thead()
- ->append(Tag::tr()
- ->append(Tag::th(null, 'Variable'))
- ->append(Tag::th(null, 'Value')));
-
- $tbody = Tag::tbody();
- foreach ($var as $k => $v) {
- $tbody->append(Tag::tr()
- ->append(Tag::td()
- ->append($k))
- ->append(Tag::td(array('class' => 'code'))
- ->append(Tag::div()->append(print_r($v, true)))));
- }
-
- return $table->append($thead)->append($tbody);
- } else {
- return Tag::p(array('class' => 'whitemsg'), 'No data');
- }
- }
-
-
- function SectionResponse()
- {
- return $this->section('response', 'Response',
- $this->ResponseHeaders());
- }
-
- function ResponseHeaders()
- {
- $r = array(
- Tag::h3('Headers'),
- );
- $headers = headers_list();
- if ($headers) {
- $h = Tag::p(array('class' => 'headers'));
- foreach ($headers as $header) {
- $h->append($header)->append(Tag::br());
- }
- $r[] = $h;
- } else {
- $r[] = Tag::p(null, 'No headers.');
- }
- return $r;
- }
-
-
- function css()
- {
- return Tag::style()->raw('html * { padding:0; margin:0; }
-body * { padding:10px 20px; }
-body * * { padding:0; }
-body { font:small sans-serif; background: #70DBFF; }
-body>div { border-bottom:1px solid #ddd; }
-h1 { font-weight:normal; }
-h2 { margin-bottom:.8em; }
-h2 span { font-size:80%; color:#666; font-weight:normal; }
-h2 a { text-decoration:none; }
-h3 { margin:1em 0 .5em 0; }
-h4 { margin:0.5em 0 .5em 0; font-weight: normal; font-style: italic; }
-table { border:1px solid #ccc; border-collapse: collapse; background:white; }
-tbody td, tbody th { vertical-align:top; padding:2px 3px; }
-thead th { padding:1px 6px 1px 3px; background:#70FF94; text-align:left; font-weight:bold; font-size:11px; border:1px solid #ddd; }
-tbody th { text-align:right; color:#666; padding-right:.5em; }
-.vars table { margin:5px 0 2px 40px; }
-.vars table td, table.req td { font-family:monospace; }
-table td { background: #70FFDB; }
-table td.code { width:95%;}
-table td.code div { overflow:hidden; }
-table.source th { color:#666; }
-table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
-ul.traceback { list-style-type:none; }
-ul.traceback li.frame { margin-bottom:1em; }
-div.context { margin:5px 0 2px 40px; background: #fff; border: 1px dashed #666; }
-div.context ol { padding-left:10px; margin:0 10px; list-style-position: inside; }
-div.context ol li { font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
-div.context li.current-line { color:black; background-color:#70FF94; }
-div.commands { margin-left: 40px; }
-div.commands a { color:black; text-decoration:none; }
-p.headers { background: #70FFDB; font-family:monospace; padding: 2px; }
-#summary { background: #00B8F5; }
-#summary h2 { font-weight: normal; color: #666; }
-#traceback { background:#eee; }
-#request { background:#f6f6f6; }
-#response { background:#eee; }
-#summary table { border:none; background:#00B8F5; }
-#summary td { background:#00B8F5; }
-.switch { text-decoration: none; }
-.whitemsg { background:white; color:black;}');
- }
-
- function js()
- {
- return Tag::script()->raw('
-window.onload = function() {
- function onClick(e, c) {
- var args = Array.prototype.slice.call(arguments, 2);
- if (e.addEventListener)
- e.addEventListener("click", function(ev) { c.apply(this, args); ev.preventDefault(); }, false);
- else
- e.attachEvent("onclick", function(ev) { c.apply(this, args); ev.returnValue = false; });
- }
-
- var i, bd, sections = document.querySelectorAll(".section");
- for (i = 0; i < sections.length; ++i) {
- bd = sections[i].querySelector(".section-body");
- bd.style.display = \'none\';
- onClick(sections[i].querySelector(".section-toggle"), function (sw, bd) {
- bd.style.display = bd.style.display == \'none\' ? \'block\' : \'none\';
-
- var uarr = String.fromCharCode(0x25b6);
- var darr = String.fromCharCode(0x25bc);
- sw.innerHTML = sw.innerHTML == uarr ? darr : uarr;
- },
- sections[i].querySelector(".section-switch"),
- bd);
- }
-}');
- }
-}
-