Allow overriding the envelope sender in Email::getJobs()
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / core.functions.php
CommitLineData
158bd3ca
TD
1<?php
2/**
3 * @author Marcel Werk
f406809a 4 * @copyright 2001-2016 WoltLab GmbH
158bd3ca
TD
5 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
6 * @package com.woltlab.wcf
0c166126 7 * @category Community Framework
158bd3ca 8 */
5bc5a7e6
TD
9namespace {
10 use wcf\system\WCF;
2b6fbe94 11
5bc5a7e6 12 // set exception handler
d82507dc 13 set_exception_handler([WCF::class, 'handleException']);
5bc5a7e6 14 // set php error handler
d82507dc 15 set_error_handler([WCF::class, 'handleError'], E_ALL);
5bc5a7e6 16 // set shutdown function
d82507dc 17 register_shutdown_function([WCF::class, 'destruct']);
5bc5a7e6 18 // set autoload function
d82507dc 19 spl_autoload_register([WCF::class, 'autoload']);
2b6fbe94 20
5bc5a7e6
TD
21 // define escape string shortcut
22 function escapeString($string) {
23 return WCF::getDB()->escapeString($string);
24 }
f406809a
AE
25
26 /**
27 * Helper method to output debug data for all passed variables,
28 * uses `print_r()` for arrays and objects, `var_dump()` otherwise.
29 */
30 function wcfDebug() {
31 echo "<pre>";
32
33 $args = func_get_args();
34 $length = count($args);
35 if ($length === 0) {
a5cf4a28 36 echo "ERROR: No arguments provided.<hr>";
f406809a
AE
37 }
38 else {
39 for ($i = 0; $i < $length; $i++) {
40 $arg = $args[$i];
41
42 echo "<h2>Argument {$i} (" . gettype($arg) . ")</h2>";
43
44 if (is_array($arg) || is_object($arg)) {
45 print_r($arg);
46 }
47 else {
48 var_dump($arg);
49 }
50
51 echo "<hr>";
52 }
53 }
54
55 $backtrace = debug_backtrace();
56
57 // output call location to help finding these debug outputs again
58 echo "wcfDebug() called in {$backtrace[0]['file']} on line {$backtrace[0]['line']}";
59
60 echo "</pre>";
61
62 exit;
63 }
2b6fbe94 64
5bc5a7e6
TD
65 // define DOCUMENT_ROOT on IIS if not set
66 if (PHP_EOL == "\r\n") {
67 if (!isset($_SERVER['DOCUMENT_ROOT']) && isset($_SERVER['SCRIPT_FILENAME'])) {
68 $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0 - strlen($_SERVER['PHP_SELF'])));
69 }
70 if (!isset($_SERVER['DOCUMENT_ROOT']) && isset($_SERVER['PATH_TRANSLATED'])) {
71 $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0 - strlen($_SERVER['PHP_SELF'])));
72 }
2b6fbe94 73
5bc5a7e6
TD
74 if (!isset($_SERVER['REQUEST_URI'])) {
75 $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'], 1);
76 if (isset($_SERVER['QUERY_STRING'])) {
77 $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
78 }
79 }
80 }
dcb3a44c 81}
322ced57 82
fc23fa20 83// @codingStandardsIgnoreStart
5bc5a7e6 84namespace wcf\functions\exception {
fc23fa20 85 use wcf\system\WCF;
b8e0376c 86 use wcf\system\exception\IExtraInformationException;
5bc5a7e6 87 use wcf\system\exception\SystemException;
5bc5a7e6
TD
88 use wcf\util\FileUtil;
89 use wcf\util\StringUtil;
2b6fbe94 90
76e90abc 91 function logThrowable($e, &$logFile = null) {
8891d4b9 92 if ($logFile === null) $logFile = WCF_DIR . 'log/' . gmdate('Y-m-d', TIME_NOW) . '.txt';
b8149369 93 touch($logFile);
e4499881 94
b8149369 95 // don't forget to update ExceptionLogViewPage, when changing the log file format
e4499881 96 /** @noinspection PhpUndefinedMethodInspection */
b8149369
TD
97 $message = gmdate('r', TIME_NOW)."\n".
98 'Message: '.str_replace("\n", ' ', $e->getMessage())."\n".
99 'PHP version: '.phpversion()."\n".
100 'WCF version: '.WCF_VERSION."\n".
101 'Request URI: '.(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '')."\n".
102 'Referrer: '.(isset($_SERVER['HTTP_REFERER']) ? str_replace("\n", ' ', $_SERVER['HTTP_REFERER']) : '')."\n".
103 'User Agent: '.(isset($_SERVER['HTTP_USER_AGENT']) ? str_replace("\n", ' ', $_SERVER['HTTP_USER_AGENT']) : '')."\n".
104 'Peak Memory Usage: '.memory_get_peak_usage().'/'.FileUtil::getMemoryLimit()."\n";
e4499881 105 /** @noinspection PhpUndefinedMethodInspection */
b8149369 106 do {
e4499881 107 /** @noinspection PhpUndefinedMethodInspection */
b8149369
TD
108 $message .= "======\n".
109 'Error Class: '.get_class($e)."\n".
110 'Error Message: '.str_replace("\n", ' ', $e->getMessage())."\n".
111 'Error Code: '.intval($e->getCode())."\n".
112 'File: '.str_replace("\n", ' ', $e->getFile()).' ('.$e->getLine().')'."\n".
113 'Extra Information: '.($e instanceof IExtraInformationException ? base64_encode(serialize($e->getExtraInformation())) : '-')."\n".
114 'Stack Trace: '.base64_encode(serialize(array_map(function ($item) {
115 $item['args'] = array_map(function ($item) {
116 switch (gettype($item)) {
117 case 'object':
118 return get_class($item);
119 case 'array':
120 return array_map(function () {
121 return '[redacted]';
122 }, $item);
123 default:
124 return $item;
125 }
126 }, $item['args']);
e4499881 127
b8149369
TD
128 return $item;
129 }, sanitizeStacktrace($e, true))))."\n";
130 }
131 while ($e = $e->getPrevious());
e4499881 132
b8149369
TD
133 // calculate Exception-ID
134 $exceptionID = sha1($message);
2b6fbe94 135 $entry = "<<<<<<<<".$exceptionID."<<<<\n".$message."<<<<\n\n";
e4499881 136
b8149369
TD
137 file_put_contents($logFile, $entry, FILE_APPEND);
138 return $exceptionID;
139 }
2b6fbe94 140
5bc5a7e6 141 function printThrowable($e) {
76e90abc 142 $exceptionID = logThrowable($e, $logFile);
614e2466
AE
143
144 $exceptionTitle = $exceptionSubtitle = $exceptionExplanation = '';
145 $logFile = sanitizePath($logFile);
146 try {
04edc2ff
AE
147 if (WCF::getLanguage() !== null) {
148 $exceptionTitle = WCF::getLanguage()->get('wcf.global.exception.title', true);
149 $exceptionSubtitle = str_replace('{$exceptionID}', $exceptionID, WCF::getLanguage()->get('wcf.global.exception.subtitle', true));
150 $exceptionExplanation = str_replace('{$logFile}', $logFile, WCF::getLanguage()->get('wcf.global.exception.explanation', true));
151 }
614e2466
AE
152 }
153 catch (\Exception $e) {
154 // ignore
155 }
156 catch (\Throwable $e) {
157 // ignore
158 }
159
160 if (!$exceptionTitle || !$exceptionSubtitle || !$exceptionExplanation) {
161 // one or more failed, fallback to english
162 $exceptionTitle = 'An error has occured';
a7eb5dda 163 $exceptionSubtitle = 'Internal error code: <span class="exceptionInlineCodeWrapper"><span class="exceptionInlineCode">'.$exceptionID.'</span></span>';
614e2466
AE
164 $exceptionExplanation = <<<EXPLANATION
165<p class="exceptionSubtitle">What happened?</p>
166<p class="exceptionText">An error has occured while trying to handle your request and execution has been terminated. Please forward the above error code to the site administrator.</p>
167<p class="exceptionText">&nbsp;</p> <!-- required to ensure spacing after copy & paste -->
168<p class="exceptionText">
169 The error code can be used by an administrator to lookup the full error message in the Administration Control Panel via “Logs » Errors”.
819d7822 170 In addition the error has been written to the log file located at <span class="exceptionInlineCodeWrapper"><span class="exceptionInlineCode">{$logFile}</span></span> and can be accessed with a FTP program or similar.
614e2466
AE
171</p>
172<p class="exceptionText">&nbsp;</p> <!-- required to ensure spacing after copy & paste -->
173<p class="exceptionText">Notice: The error code was randomly generated and has no use beyond looking up the full message.</p>
174EXPLANATION;
175
176 }
177
178 /*
179 * A notice on the HTML used below:
180 *
181 * It might appear a bit weird to use <p> all over the place where semantically
182 * other elements would fit in way better. The reason behind this is that we avoid
183 * inheriting unwanted styles (e.g. exception displayed in an overlay) and that
184 * the output needs to be properly readable when copied & pasted somewhere.
185 *
186 * Besides the visual appearance, the output was built to provide a maximum of
187 * compatibility and readability when pasted somewhere else, e.g. a WYSIWYG editor
188 * without the potential of messing up the formatting and thus harming the readability.
189 */
5bc5a7e6
TD
190 ?><!DOCTYPE html>
191 <html>
192 <head>
962c9241 193 <?php if (!defined('EXCEPTION_PRIVACY') || EXCEPTION_PRIVACY !== 'private') { ?>
5bc5a7e6
TD
194 <title>Fatal Error: <?php echo StringUtil::encodeHTML($e->getMessage()); ?></title>
195 <?php } else { ?>
196 <title>Fatal Error</title>
197 <?php } ?>
614e2466
AE
198 <meta charset="utf-8">
199 <meta name="viewport" content="width=device-width, initial-scale=1">
5bc5a7e6 200 <style>
614e2466
AE
201 .exceptionBody {
202 margin: 0;
203 padding: 0;
5bc5a7e6 204 }
614e2466
AE
205
206 .exceptionContainer {
207 box-sizing: border-box;
208 font-family: 'Segoe UI', 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
209 font-size: 14px;
210 padding-bottom: 20px;
5bc5a7e6 211 }
614e2466
AE
212
213 .exceptionContainer * {
214 box-sizing: inherit;
215 color: #000;
216 line-height: 1.5em;
217 margin: 0;
218 padding: 0;
5bc5a7e6 219 }
614e2466
AE
220
221 .exceptionHeader {
222 background-color: rgb(44, 62, 80);
89130385 223 padding: 30px 0;
5bc5a7e6 224 }
614e2466
AE
225
226 .exceptionTitle {
227 color: #fff;
228 font-size: 28px;
229 font-weight: 300;
5bc5a7e6 230 }
614e2466
AE
231
232 .exceptionErrorCode {
233 color: #fff;
234 margin-top: .5em;
5bc5a7e6 235 }
614e2466
AE
236
237 .exceptionErrorCode .exceptionInlineCode {
238 background-color: rgb(52, 73, 94);
239 border-radius: 3px;
240 color: #fff;
241 font-family: monospace;
242 padding: 3px 10px;
243 white-space: nowrap;
5bc5a7e6 244 }
614e2466
AE
245
246 .exceptionSubtitle {
247 border-bottom: 1px solid rgb(238, 238, 238);
248 color: rgb(44, 62, 80);
249 font-size: 24px;
250 font-weight: 300;
251 margin-bottom: 15px;
252 padding-bottom: 10px;
5bc5a7e6 253 }
614e2466
AE
254
255 .exceptionContainer > .exceptionBoundary {
256 margin-top: 30px;
5bc5a7e6 257 }
614e2466
AE
258
259 .exceptionText .exceptionInlineCodeWrapper {
260 border: 1px solid rgb(169, 169, 169);
261 border-radius: 3px;
262 padding: 2px 5px;
5bc5a7e6 263 }
614e2466
AE
264
265 .exceptionText .exceptionInlineCode {
266 font-family: monospace;
267 white-space: nowrap;
5bc5a7e6 268 }
614e2466
AE
269
270 .exceptionFieldTitle {
271 color: rgb(59, 109, 169);
5bc5a7e6 272 }
614e2466
AE
273
274 .exceptionFieldTitle .exceptionColon {
275 /* hide colon in browser, but will be visible after copy & paste */
276 opacity: 0;
5bc5a7e6 277 }
614e2466
AE
278
279 .exceptionFieldValue {
280 font-size: 18px;
3d8a295e 281 min-height: 1.5em;
614e2466
AE
282 }
283
284 .exceptionSystemInformation,
285 .exceptionErrorDetails,
286 .exceptionStacktrace {
287 list-style-type: none;
288 }
289
290 .exceptionSystemInformation > li:not(:first-child),
291 .exceptionErrorDetails > li:not(:first-child) {
292 margin-top: 10px;
293 }
294
295 .exceptionStacktrace {
296 display: block;
297 margin-top: 5px;
298 overflow: auto;
299 padding-bottom: 20px;
300 }
301
302 .exceptionStacktraceFile,
303 .exceptionStacktraceFile span,
304 .exceptionStacktraceCall,
305 .exceptionStacktraceCall span {
306 font-family: monospace !important;
307 white-space: nowrap !important;
308 }
309
310 .exceptionStacktraceCall + .exceptionStacktraceFile {
311 margin-top: 5px;
312 }
313
314 .exceptionStacktraceCall {
315 padding-left: 40px;
316 }
317
318 .exceptionStacktraceCall,
319 .exceptionStacktraceCall span {
320 color: rgb(102, 102, 102) !important;
321 font-size: 13px !important;
322 }
323
324 /* mobile */
325 @media (max-width: 767px) {
326 .exceptionBoundary {
327 min-width: 320px;
328 padding: 0 10px;
dd6a2623 329 }
614e2466
AE
330
331 .exceptionText .exceptionInlineCodeWrapper {
332 display: inline-block;
333 overflow: auto;
dd6a2623 334 }
614e2466
AE
335
336 .exceptionErrorCode .exceptionInlineCode {
337 font-size: 13px;
338 padding: 2px 5px;
dd6a2623 339 }
614e2466
AE
340 }
341
342 /* desktop */
343 @media (min-width: 768px) {
344 .exceptionBoundary {
345 margin: 0 auto;
346 max-width: 1400px;
347 min-width: 1200px;
348 padding: 0 10px;
349 }
350
351 .exceptionSystemInformation {
352 display: flex;
353 flex-wrap: wrap;
354 }
355
356 .exceptionSystemInformation1,
357 .exceptionSystemInformation3,
358 .exceptionSystemInformation5 {
359 flex: 0 0 200px;
360 margin: 0 0 10px 0 !important;
361 }
362
363 .exceptionSystemInformation2,
364 .exceptionSystemInformation4,
365 .exceptionSystemInformation6 {
366 flex: 0 0 calc(100% - 210px);
367 margin: 0 0 10px 10px !important;
368 max-width: calc(100% - 210px);
369 }
370
371 .exceptionSystemInformation1 { order: 1; }
372 .exceptionSystemInformation2 { order: 2; }
373 .exceptionSystemInformation3 { order: 3; }
374 .exceptionSystemInformation4 { order: 4; }
375 .exceptionSystemInformation5 { order: 5; }
376 .exceptionSystemInformation6 { order: 6; }
377
378 .exceptionSystemInformation .exceptionFieldValue {
379 overflow: hidden;
380 text-overflow: ellipsis;
381 white-space: nowrap;
382 }
383 }
384 </style>
385 </head>
386 <body class="exceptionBody">
387 <div class="exceptionContainer">
388 <div class="exceptionHeader">
389 <div class="exceptionBoundary">
390 <p class="exceptionTitle"><?php echo $exceptionTitle; ?></p>
391 <p class="exceptionErrorCode"><?php echo str_replace('{$exceptionID}', $exceptionID, $exceptionSubtitle); ?></p>
392 </div>
393 </div>
394
395 <div class="exceptionBoundary">
396 <?php echo $exceptionExplanation; ?>
5bc5a7e6 397 </div>
962c9241 398 <?php if (!defined('EXCEPTION_PRIVACY') || EXCEPTION_PRIVACY !== 'private') { ?>
614e2466
AE
399 <div class="exceptionBoundary">
400 <p class="exceptionSubtitle">System Information</p>
401 <ul class="exceptionSystemInformation">
402 <li class="exceptionSystemInformation1">
403 <p class="exceptionFieldTitle">PHP Version<span class="exceptionColon">:</span></p>
404 <p class="exceptionFieldValue"><?php echo StringUtil::encodeHTML(phpversion()); ?></p>
405 </li>
406 <li class="exceptionSystemInformation3">
407 <p class="exceptionFieldTitle">WCF Version<span class="exceptionColon">:</span></p>
408 <p class="exceptionFieldValue"><?php echo StringUtil::encodeHTML(WCF_VERSION); ?></p>
409 </li>
410 <li class="exceptionSystemInformation5">
411 <p class="exceptionFieldTitle">Peak Memory Usage<span class="exceptionColon">:</span></p>
412 <p class="exceptionFieldValue"><?php echo round(memory_get_peak_usage() / 1024 / 1024, 3); ?>/<?php echo round(FileUtil::getMemoryLimit() / 1024 / 1024, 3); ?> MiB</p>
413 </li>
414 <li class="exceptionSystemInformation2">
415 <p class="exceptionFieldTitle">Request URI<span class="exceptionColon">:</span></p>
416 <p class="exceptionFieldValue"><?php if (isset($_SERVER['REQUEST_URI'])) echo StringUtil::encodeHTML($_SERVER['REQUEST_URI']); ?></p>
417 </li>
418 <li class="exceptionSystemInformation4">
419 <p class="exceptionFieldTitle">Referrer<span class="exceptionColon">:</span></p>
420 <p class="exceptionFieldValue"><?php if (isset($_SERVER['HTTP_REFERER'])) echo StringUtil::encodeHTML($_SERVER['HTTP_REFERER']); ?></p>
421 </li>
422 <li class="exceptionSystemInformation6">
423 <p class="exceptionFieldTitle">User Agent<span class="exceptionColon">:</span></p>
424 <p class="exceptionFieldValue"><?php if (isset($_SERVER['HTTP_USER_AGENT'])) echo StringUtil::encodeHTML($_SERVER['HTTP_USER_AGENT']); ?></p>
425 </li>
426 </ul>
5bc5a7e6 427 </div>
614e2466 428
5bc5a7e6
TD
429 <?php
430 $first = true;
431 do {
432 ?>
614e2466
AE
433 <div class="exceptionBoundary">
434 <p class="exceptionSubtitle"><?php if (!$e->getPrevious() && !$first) { echo "Original "; } else if ($e->getPrevious() && $first) { echo "Final "; } ?>Error</p>
5bc5a7e6 435 <?php if ($e instanceof SystemException && $e->getDescription()) { ?>
614e2466 436 <p class="exceptionText"><?php echo $e->getDescription(); ?></p>
5bc5a7e6 437 <?php } ?>
614e2466 438 <ul class="exceptionErrorDetails">
0b46efcf
TD
439 <li>
440 <p class="exceptionFieldTitle">Error Type<span class="exceptionColon">:</span></p>
441 <p class="exceptionFieldValue"><?php echo StringUtil::encodeHTML(get_class($e)); ?></p>
442 </li>
614e2466
AE
443 <li>
444 <p class="exceptionFieldTitle">Error Message<span class="exceptionColon">:</span></p>
445 <p class="exceptionFieldValue"><?php echo StringUtil::encodeHTML($e->getMessage()); ?></p>
446 </li>
447 <?php if ($e->getCode()) { ?>
448 <li>
449 <p class="exceptionFieldTitle">Error Code<span class="exceptionColon">:</span></p>
450 <p class="exceptionFieldValue"><?php echo intval($e->getCode()); ?></p>
451 </li>
452 <?php } ?>
453 <li>
454 <p class="exceptionFieldTitle">File<span class="exceptionColon">:</span></p>
455 <p class="exceptionFieldValue" style="word-break: break-all"><?php echo StringUtil::encodeHTML(sanitizePath($e->getFile())); ?> (<?php echo $e->getLine(); ?>)</p>
456 </li>
457
5bc5a7e6
TD
458 <?php
459 if ($e instanceof SystemException) {
460 ob_start();
461 $e->show();
462 ob_end_clean();
2b6fbe94 463
5bc5a7e6
TD
464 $reflection = new \ReflectionClass($e);
465 $property = $reflection->getProperty('information');
466 $property->setAccessible(true);
467 if ($property->getValue($e)) {
468 throw new \Exception("Using the 'information' property of SystemException is not supported any more.");
469 }
470 }
b8e0376c
TD
471 if ($e instanceof IExtraInformationException) {
472 foreach ($e->getExtraInformation() as list($key, $value)) {
614e2466
AE
473 ?>
474 <li>
475 <p class="exceptionFieldTitle"><?php echo StringUtil::encodeHTML($key); ?><span class="exceptionColon">:</span></p>
476 <p class="exceptionFieldValue"><?php echo StringUtil::encodeHTML($value); ?></p>
477 </li>
478 <?php
b8e0376c
TD
479 }
480 }
5bc5a7e6 481 ?>
614e2466
AE
482 <li>
483 <p class="exceptionFieldTitle">Stack Trace<span class="exceptionColon">:</span></p>
484 <ul class="exceptionStacktrace">
485 <?php
486 $trace = sanitizeStacktrace($e);
614e2466
AE
487 for ($i = 0, $max = count($trace); $i < $max; $i++) {
488 ?>
489 <li class="exceptionStacktraceFile"><?php echo '#'.$i.' '.StringUtil::encodeHTML($trace[$i]['file']).' ('.$trace[$i]['line'].')'.':'; ?></li>
490 <li class="exceptionStacktraceCall">
491 <?php
492 echo $trace[$i]['class'].$trace[$i]['type'].$trace[$i]['function'].'(';
493 echo implode(', ', array_map(function ($item) {
494 switch (gettype($item)) {
495 case 'integer':
496 case 'double':
497 return $item;
498 case 'NULL':
499 return 'null';
500 case 'string':
aac60824 501 return "'".addcslashes(StringUtil::encodeHTML($item), "\\'")."'";
614e2466
AE
502 case 'boolean':
503 return $item ? 'true' : 'false';
504 case 'array':
505 $keys = array_keys($item);
506 if (count($keys) > 5) return "[ ".count($keys)." items ]";
507 return '[ '.implode(', ', array_map(function ($item) {
508 return $item.' => ';
509 }, $keys)).']';
510 case 'object':
511 return get_class($item);
512 }
513 }, $trace[$i]['args']));
514 echo ')</li>';
515 }
516 ?>
517 </ul>
518 </li>
519 </ul>
5bc5a7e6
TD
520 </div>
521 <?php
522 $first = false;
523 } while ($e = $e->getPrevious());
524 ?>
525 <?php } ?>
526 </div>
527 </body>
528 </html>
529 <?php
322ced57 530 }
5bc5a7e6
TD
531
532 function sanitizeStacktrace($e, $ignorePaths = false) {
533 $trace = $e->getTrace();
2b6fbe94 534
5bc5a7e6 535 return array_map(function ($item) use ($ignorePaths) {
2b6fbe94
TD
536 if (!isset($item['file'])) $item['file'] = '[internal function]';
537 if (!isset($item['line'])) $item['line'] = '?';
538 if (!isset($item['class'])) $item['class'] = '';
539 if (!isset($item['type'])) $item['type'] = '';
335aae2b 540 if (!isset($item['args'])) $item['args'] = [];
2b6fbe94 541
5bc5a7e6 542 // strip database credentials
2b6fbe94
TD
543 if (preg_match('~\\\\?wcf\\\\system\\\\database\\\\[a-zA-Z]*Database~', $item['class']) || $item['class'] === 'PDO') {
544 if ($item['function'] === '__construct') {
545 $item['args'] = array_map(function () {
546 return '[redacted]';
547 }, $item['args']);
5bc5a7e6
TD
548 }
549 }
390ec505 550
5bc5a7e6
TD
551 if (!$ignorePaths) {
552 $item['args'] = array_map(function ($item) {
b8e0376c 553 if (!is_string($item)) return $item;
390ec505
TD
554
555 if (preg_match('~^('.preg_quote($_SERVER['DOCUMENT_ROOT'], '~').'|'.preg_quote(WCF_DIR, '~').')~', $item)) {
5bc5a7e6
TD
556 $item = sanitizePath($item);
557 }
2b6fbe94 558
390ec505 559 return $item;
5bc5a7e6 560 }, $item['args']);
390ec505 561
2b6fbe94 562 $item['file'] = sanitizePath($item['file']);
5bc5a7e6 563 }
390ec505 564
5bc5a7e6
TD
565 return $item;
566 }, $trace);
322ced57 567 }
390ec505 568
5bc5a7e6 569 function sanitizePath($path) {
962c9241
TD
570 if (WCF::debugModeIsEnabled() && defined('EXCEPTION_PRIVACY') && EXCEPTION_PRIVACY === 'public') {
571 return $path;
572 }
390ec505 573
5bc5a7e6 574 return '*/'.FileUtil::removeTrailingSlash(FileUtil::getRelativePath(WCF_DIR, $path));
322ced57
AE
575 }
576}
fc23fa20 577// @codingStandardsIgnoreEnd