Classes

File core/error/HTTPFatalExceptionPrinter.class.php

File core/error/HTTPFatalExceptionPrinter.class.php

  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 
<?php
/**
 * @package     Core
 * @subpackage  Error
 * @copyright   &copy; 2005-2019 PHPBoost
 * @license     https://www.gnu.org/licenses/gpl-3.0.html GNU/GPL-3.0
 * @author      Loic ROUCHON <horn@phpboost.com>
 * @version     PHPBoost 5.2 - last update: 2017 04 20
 * @since       PHPBoost 3.0 - 2010 10 18
 * @contributor Julien BRISWALTER <j1.seth@phpboost.com>
 * @contributor Arnaud GENET <elenwii@phpboost.com>
*/

defined('TPL_PATH_TO_ROOT') or define('TPL_PATH_TO_ROOT', PATH_TO_ROOT);

class HTTPFatalExceptionPrinter
{
    private $type;
    private $message;
    private $exception;
    private $ob_content = '';
    private $is_row_odd = true;
    private $output = '';

    public function __construct($exception)
    {
        $this->exception = $exception;
        $this->type = get_class($this->exception);
        $this->message = str_replace("\n", "<br />", $this->exception->getMessage());
        $this->ob_content = AppContext::get_response()->get_previous_ob_content();
    }

    public function render()
    {
        $this->output .= '<!DOCTYPE html>
<html lang="en">
    <head>
        <title>' . $this->type . ' caught</title>
        <meta charset="UTF-8" />
        <style type="text/css">
            body {background-color:#dddddd;}
            table {width:100%;}
            caption {text-align:left;font-size:26px;font-weight:bold;background-color:#536F8B;padding:5px;border-bottom:1px #aaaaaa solid;}
            th {font-size:18px;background-color:#7A99B1;height:30px;}
            tr.section {}
            tr.oddRow {background-color:#ECEEEF;}
            tr.evenRow {background-color:#D2E3F1;}
            td.parameterName {font-size:14px;font-weight:bold;padding:0 10px;}
            td.parameterValue {font-size:14px;}
            h1 {background-color:#536F8B;border:1px #aaaaaa solid;padding:10px;margin:0px;}
            div#exceptionContext .message {font-weight:bold;background-color:#eeeeee;border:1px #aaaaaa solid;padding:10px;}
            .outputBuffer {font-size:12px;background-color:#eeeeee;border-left:1px #aaaaaa solid;border-right:1px #aaaaaa solid;padding:10px;}
            table.stack td.prototype {font-weight:bold;padding-right:10px;}
            table.stack td.file {font-size:14px;font-style:italic;}
            table.stack td.line {text-align:right;font-size:12px;width:30px;}
            table.stack td.args {font-size:14px;padding-right:10px;}
            table.stack td.argsDetails {border-top:1px #aaaaaa solid;}
            div#exceptionContext {background-color:#eeeeee;border:1px #aaaaaa solid;padding:10px;}
            div#whyISeeThisPage {background-color:#eeeeee;border:1px #aaaaaa solid;padding:10px;}
            div#httpContext {background-color:#eeeeee;border:1px #aaaaaa solid;padding:10px;}
        </style>
        <script>
        <!--
        function toggleDisplay(link, eltId) {
            var elt = document.getElementById(eltId);
            var mode = elt.style.display;
            if (mode != \'none\') {
                elt.style.display = \'none\';
                link.innerHTML = \'+\';
            } else {
                elt.style.display = \'table-row\';
                link.innerHTML = \'-\';
            }
        }
        function getOutputBufferContent() {
            return \'' . str_replace("\n", '\n\' + ' . "\n" . '\'', str_replace("\r", '', addslashes(TextHelper::htmlspecialchars($this->ob_content)))) . '\';
        }
        function openOutputBufferPopup(content) {
            var obWindow = window.open(\'\', \'Output Buffer\', \'\');
            obWindow.document.open();
            obWindow.document.write(content);
            obWindow.document.close();
        }
        function displayOutputBufferContent() {
            var content = getOutputBufferContent();
            content = \'&lt;html&gt;&lt;head&gt;&lt;title&gt;OUTPUT BUFFER RAW&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;pre&gt;\'.replace(/&lt;/g, \'<\').replace(/&gt;/g, \'>\') +
                content + \'&lt;/body&gt;&lt;/html&gt;\'.replace(/&lt;/g, \'<\').replace(/&gt;/g, \'>\');
            openOutputBufferPopup(content);
        }
        -->
        </script>
    </head>
    <body>
        <div id="exceptionContext">
            <h1>' . $this->type . '</h1>
            <div class="message">' . $this->message. '</div>
            <table cellpadding="2" cellspacing="0" class="stack">
                <caption>STACKTRACE</caption>
                <tr><th></th><th>METHOD</th><th>FILE</th><th>LINE</th></tr>' . $this->build_stack_trace() . '
            </table>
        </div>
        <div class="outputBuffer"><a href="javascript:displayOutputBufferContent()">output buffer</a></div>
        <div id="whyISeeThisPage">
            You see this page because your site is configured to use the <em>DEBUG</em> mode.<br />
            If you want to see the related user error page, you have to disable the <em>DEBUG</em> mode
            from the <a href="' . TPL_PATH_TO_ROOT . '/admin/config/?url=/advanced/">administration panel</a>.
        </div>
        <div id="httpContext">
            <table cellspacing="0" cellpadding="3 5px"><caption>HTTP Request</caption>
            ' . $this->get_http_context() . '
            </table>
        </div>
    </body>
</html>';
        return $this->output;
    }

    private function build_stack_trace()
    {
        $i = 0;
        $this->is_row_odd = true;
        $stack = '';
        foreach ($this->exception->getTrace() as $call)
        {
            $row_class = $this->is_row_odd ? 'oddRow' : 'evenRow';
            $has_args = ExceptionUtils::has_args($call);
            $id = 'call' . $i . 'Arguments';
            $stack .= '<tr class="' . $row_class . '">';
            $stack .= '<td class="args">';
            if ($has_args)
            {
                $stack .= '<a href="javascript:toggleDisplay(this, \'' . $id . '\');">+</a>';
            }
            $stack .= '</td>';
            $stack .= '<td class="prototype">' . ExceptionUtils::get_method_prototype($call) . '</td>';
            $stack .= '<td class="file">' . ExceptionUtils::get_file($call) . '</td>';
            $stack .= '<td class="line">' . ExceptionUtils::get_line($call) . '</td>';
            $stack .= '</tr>';
            if ($has_args)
            {
                $stack .= '<tr id="' . $id . '" style="display: none;" class="' . $row_class . '">
                <td colspan="4" class="argsDetails">' . ExceptionUtils::get_args($call) . '</td></tr>';
            }
            $i++;
            $this->is_row_odd = !$this->is_row_odd;
        }
        return $stack;
    }

    private function get_http_context()
    {
        $http_context = '';
        $http_context .= $this->dump_var('GET', $_GET);
        $http_context .= $this->dump_var('POST', $_POST);
        $http_context .= $this->dump_var('COOKIE', $_COOKIE);
        $http_context .= $this->dump_var('SERVER', $_SERVER);
        return $http_context;
    }

    private function dump_var($title, $parameters)
    {
        $dump =  '';
        if (!empty($parameters))
        {
            $this->is_row_odd = true;
            $dump .= '<tr class="section"><th colspan="2" style="text-align:left;padding:0 10px;">' . $title . '</th></tr>';
            foreach ($parameters as $key => $value)
            {
                $dump .= $this->add_parameter($key, $value);
            }
        }
        return $dump;
    }

    private function add_parameter($key, $value)
    {
        $value_to_display = '';
        if (is_array($value))
        {
            $value_to_display = '<ul>';
            foreach ($value as $a_value)
            {
                $value_to_display .= '<li>' . TextHelper::htmlspecialchars($a_value) . '</li>';
            }
            $value_to_display .= '</ul>';
        }
        else
        {
            $value_to_display = TextHelper::htmlspecialchars($value);
        }
        $row_class = $this->is_row_odd ? 'oddRow' : 'evenRow';
        $this->is_row_odd = !$this->is_row_odd;
        return '<tr class="' . $row_class. '">' .
            '<td class="parameterName">' . $key . '</td>' .
            '<td class="parameterValue">' . str_replace("\n", '<br />', $value_to_display) . '</td>' .
        '</tr>' ;
    }
}
?>