Commit | Line | Data |
---|---|---|
ff49a0be S |
1 | <?php |
2 | namespace dns\system; | |
3 | ||
4 | /** | |
5 | * A SystemException is thrown when an unexpected error occurs. | |
6 | * | |
7 | * @author Marcel Werk | |
8 | * @copyright 2001-2015 WoltLab GmbH | |
9 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> | |
10 | * @package com.woltlab.wcf | |
11 | * @subpackage system.exception | |
12 | * @category Community Framework | |
13 | */ | |
14 | // @codingStandardsIgnoreFile | |
15 | class SystemException extends \Exception { | |
16 | /** | |
17 | * error description | |
18 | * @var string | |
19 | */ | |
20 | protected $description = null; | |
21 | ||
22 | /** | |
23 | * additional information | |
24 | * @var string | |
25 | */ | |
26 | protected $information = ''; | |
27 | ||
28 | /** | |
29 | * additional information | |
30 | * @var string | |
31 | */ | |
32 | protected $functions = ''; | |
33 | ||
34 | /** | |
35 | * exception id | |
36 | * @var string | |
37 | */ | |
38 | protected $exceptionID = ''; | |
39 | ||
40 | /** | |
41 | * Creates a new SystemException. | |
42 | * | |
43 | * @param string $message error message | |
44 | * @param integer $code error code | |
45 | * @param string $description description of the error | |
46 | * @param \Exception $previous repacked Exception | |
47 | */ | |
48 | public function __construct($message = '', $code = 0, $description = '', \Exception $previous = null) { | |
49 | parent::__construct((string) $message, (int) $code, $previous); | |
50 | $this->description = $description; | |
51 | } | |
52 | ||
53 | /** | |
54 | * Removes database password from stack trace. | |
55 | * @see \Exception::getTraceAsString() | |
56 | */ | |
57 | public function __getTraceAsString() { | |
58 | $e = ($this->getPrevious() ?: $this); | |
59 | $string = $e->getTraceAsString(); | |
60 | $string = preg_replace('/PDO->__construct\(.*\)/', 'PDO->__construct(...)', $string); | |
61 | $string = preg_replace('/DB->__construct\(.*\)/', 'DB->__construct(...)', $string); | |
62 | return $string; | |
63 | } | |
64 | ||
65 | /** | |
66 | * @see \Exception::getMessage() | |
67 | */ | |
68 | public function _getMessage() { | |
69 | $e = ($this->getPrevious() ?: $this); | |
70 | return $e->getMessage(); | |
71 | } | |
72 | ||
73 | /** | |
74 | * Returns the description of this exception. | |
75 | * | |
76 | * @return string | |
77 | */ | |
78 | public function getDescription() { | |
79 | return $this->description; | |
80 | } | |
81 | ||
82 | /** | |
83 | * Returns exception id | |
84 | * | |
85 | * @return string | |
86 | */ | |
87 | public function getExceptionID() { | |
88 | if (empty($this->exceptionID)) { | |
89 | $this->logError(); | |
90 | } | |
91 | ||
92 | return $this->exceptionID; | |
93 | } | |
94 | ||
95 | /** | |
96 | * Writes an error to log file. | |
97 | */ | |
98 | protected function logError() { | |
99 | if (!empty($this->exceptionID)) { | |
100 | return; | |
101 | } | |
102 | ||
103 | $logFile = DNS_DIR . '/log/' . gmdate('Y-m-d', time()) . '.txt'; | |
104 | ||
105 | // try to create file | |
106 | @touch($logFile); | |
107 | ||
108 | // validate if file exists and is accessible for us | |
109 | if (!file_exists($logFile) || !is_writable($logFile)) { | |
110 | /* | |
111 | We cannot recover if we reached this point, the server admin | |
112 | is urged to fix his pretty much broken configuration. | |
113 | ||
114 | GLaDOS: Look at you, sailing through the air majestically, like an eagle... piloting a blimp. | |
115 | */ | |
116 | return; | |
117 | } | |
118 | ||
119 | $e = ($this->getPrevious() ?: $this); | |
120 | ||
121 | // don't forget to update ExceptionLogViewPage, when changing the log file format | |
122 | $message = gmdate('r', time())."\n". | |
123 | 'Message: '.$e->getMessage()."\n". | |
124 | 'File: '.$e->getFile().' ('.$e->getLine().")\n". | |
125 | 'PHP version: '.phpversion()."\n". | |
126 | 'DNS version: '.DNS_VERSION."\n". | |
127 | 'Request URI: '.(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '')."\n". | |
128 | 'Referrer: '.(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '')."\n". | |
129 | 'User-Agent: '.(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '')."\n". | |
130 | 'Information: '.json_encode($this->information)."\n". | |
131 | "Stacktrace: \n ".implode("\n ", explode("\n", $this->__getTraceAsString()))."\n"; | |
132 | ||
133 | // calculate Exception-ID | |
134 | $this->exceptionID = sha1($message); | |
135 | $message = "<<<<<<<<".$this->exceptionID."<<<<\n".$message."<<<<\n\n"; | |
136 | ||
137 | // append | |
138 | @file_put_contents($logFile, $message, FILE_APPEND); | |
139 | } | |
140 | ||
141 | /** | |
142 | * @see \wcf\system\exception\IPrintableException::show() | |
143 | */ | |
144 | public function show() { | |
145 | // send status code | |
146 | @header('HTTP/1.1 503 Service Unavailable'); | |
147 | ||
148 | // print report | |
149 | $e = ($this->getPrevious() ?: $this); | |
150 | ?><!DOCTYPE html> | |
151 | <html> | |
152 | <head> | |
153 | <title>Fatal error: <?php echo htmlspecialchars($this->_getMessage(), ENT_COMPAT, 'UTF-8'); ?></title> | |
154 | <meta charset="utf-8" /> | |
155 | <style> | |
156 | .systemException { | |
157 | font-family: 'Trebuchet MS', Arial, sans-serif !important; | |
158 | font-size: 80% !important; | |
159 | text-align: left !important; | |
160 | border: 1px solid #036; | |
161 | border-radius: 7px; | |
162 | background-color: #eee !important; | |
163 | overflow: auto !important; | |
164 | } | |
165 | .systemException h1 { | |
166 | font-size: 130% !important; | |
167 | font-weight: bold !important; | |
168 | line-height: 1.1 !important; | |
169 | text-decoration: none !important; | |
170 | text-shadow: 0 -1px 0 #003 !important; | |
171 | color: #fff !important; | |
172 | word-wrap: break-word !important; | |
173 | border-bottom: 1px solid #036; | |
174 | border-top-right-radius: 6px; | |
175 | border-top-left-radius: 6px; | |
176 | background-color: #369 !important; | |
177 | margin: 0 !important; | |
178 | padding: 5px 10px !important; | |
179 | } | |
180 | .systemException div { | |
181 | border-top: 1px solid #fff; | |
182 | border-bottom-right-radius: 6px; | |
183 | border-bottom-left-radius: 6px; | |
184 | padding: 0 10px !important; | |
185 | } | |
186 | .systemException h2 { | |
187 | font-size: 130% !important; | |
188 | font-weight: bold !important; | |
189 | color: #369 !important; | |
190 | text-shadow: 0 1px 0 #fff !important; | |
191 | margin: 5px 0 !important; | |
192 | } | |
193 | .systemException pre, .systemException p { | |
194 | text-shadow: none !important; | |
195 | color: #555 !important; | |
196 | margin: 0 !important; | |
197 | } | |
198 | .systemException pre { | |
199 | font-size: .85em !important; | |
200 | font-family: "Courier New" !important; | |
201 | text-overflow: ellipsis; | |
202 | padding-bottom: 1px; | |
203 | overflow: hidden !important; | |
204 | } | |
205 | .systemException pre:hover{ | |
206 | text-overflow: clip; | |
207 | overflow: auto !important; | |
208 | } | |
209 | </style> | |
210 | </head> | |
211 | <body> | |
212 | <div class="systemException"> | |
213 | <h1>Fatal error: <?php if(!$this->getExceptionID()) { ?>Unable to write log file, please make "<?php echo DNS_DIR; ?>/log/" writable!<?php } else { echo htmlspecialchars($this->_getMessage(), ENT_COMPAT, 'UTF-8'); } ?></h1> | |
214 | ||
215 | <?php if (DNS::debugModeIsEnabled()) { ?> | |
216 | <div> | |
217 | <?php if ($this->getDescription()) { ?><p><br /><?php echo $this->getDescription(); ?></p><?php } ?> | |
218 | ||
219 | <h2>Information:</h2> | |
220 | <p> | |
221 | <b>error message:</b> <?php echo htmlspecialchars($this->_getMessage(), ENT_COMPAT, 'UTF-8'); ?><br> | |
222 | <b>error code:</b> <?php echo intval($e->getCode()); ?><br> | |
223 | <?php echo $this->information; ?> | |
224 | <b>file:</b> <?php echo htmlspecialchars($e->getFile(), ENT_COMPAT, 'UTF-8'); ?> (<?php echo $e->getLine(); ?>)<br> | |
225 | <b>php version:</b> <?php echo htmlspecialchars(phpversion(), ENT_COMPAT, 'UTF-8'); ?><br> | |
226 | <b>dns version:</b> <?php echo DNS_VERSION; ?><br> | |
227 | <b>date:</b> <?php echo gmdate('r'); ?><br> | |
228 | <b>request:</b> <?php if (isset($_SERVER['REQUEST_URI'])) echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_COMPAT, 'UTF-8'); ?><br> | |
229 | <b>referer:</b> <?php if (isset($_SERVER['HTTP_REFERER'])) echo htmlspecialchars($_SERVER['HTTP_REFERER'], ENT_COMPAT, 'UTF-8'); ?><br> | |
230 | </p> | |
231 | ||
232 | <h2>Stacktrace:</h2> | |
233 | <pre><?php echo htmlspecialchars($this->__getTraceAsString(), ENT_COMPAT, 'UTF-8'); ?></pre> | |
234 | </div> | |
235 | <?php } else { ?> | |
236 | <div> | |
237 | <h2>Information:</h2> | |
238 | <p> | |
239 | <?php if (!$this->getExceptionID()) { ?> | |
240 | Unable to write log file, please make "<?php echo DNS_DIR; ?>/log/" writable! | |
241 | <?php } else { ?> | |
242 | <b>ID:</b> <code><?php echo $this->getExceptionID(); ?></code><br> | |
243 | Please send the ID above to the site administrator. | |
244 | <?php } ?> | |
245 | </p> | |
246 | </div> | |
247 | <?php } ?> | |
248 | <?php echo $this->functions; ?> | |
249 | </div> | |
250 | </body> | |
251 | </html> | |
252 | ||
253 | <?php | |
254 | } | |
255 | } |