3 use wcf\system\exception\SystemException
;
7 * Contains helper functions to process the Exception log.
9 * @author Tim Duesterhus
10 * @copyright 2001-2019 WoltLab GmbH
11 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12 * @package WoltLabSuite\Core\Util
15 final class ExceptionLogUtil
{
17 * Splits the given string of Exceptions into an array.
19 * @param string $contents
22 public static function splitLog($contents) {
24 $contents = StringUtil
::unifyNewlines($contents);
27 $split = new Regex('(?:^|\n<<<<\n\n)(?:<<<<<<<<([a-f0-9]{40})<<<<\n|$)');
28 $contents = $split->split($contents, Regex
::SPLIT_NON_EMPTY_ONLY | Regex
::CAPTURE_SPLIT_DELIMITER
);
30 // even items become keys, odd items become values
31 return array_merge(...array_map(
33 return [$v[0] => $v[1]];
35 array_chunk($contents, 2)
40 * Parses the given log entry.
42 * @param string $entry
45 public static function parseException($entry) {
47 static $chainRegex = null;
48 if ($regex === null ||
$chainRegex === null) {
49 $regex = new Regex("(?P<date>[MTWFS][a-z]{2}, \d{1,2} [JFMASOND][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} [+-]\d{4})\s*\n".
50 "Message: (?P<message>.*?)\s*\n".
51 "PHP version: (?P<phpVersion>.*?)\s*\n".
52 "WoltLab Suite version: (?P<wcfVersion>.*?)\s*\n".
53 "Request URI: (?P<requestURI>.*?)\s*\n".
54 "Referrer: (?P<referrer>.*?)\s*\n".
55 "User Agent: (?P<userAgent>.*?)\s*\n".
56 "Peak Memory Usage: (?<peakMemory>\d+)/(?<maxMemory>(?:\d+|-1))\s*\n".
58 ".*)", Regex
::DOT_ALL
);
59 $chainRegex = new Regex("======\n".
60 "Error Class: (?P<class>.*?)\s*\n".
61 "Error Message: (?P<message>.*?)\s*\n".
62 "Error Code: (?P<code>[a-zA-Z0-9]+)\s*\n".
63 "File: (?P<file>.*?) \((?P<line>\d+)\)\s*\n".
64 "Extra Information: (?P<information>(?:-|[a-zA-Z0-9+/]+={0,2}))\s*\n".
65 "Stack Trace: (?P<stack>\[[^\n]+\])", Regex
::DOT_ALL
);
68 if (!$regex->match($entry)) {
69 throw new \
InvalidArgumentException('The given entry is malformed.');
71 $matches = $regex->getMatches();
72 $chainRegex->match($matches['chain'], true, Regex
::ORDER_MATCH_BY_SET
);
74 $chainMatches = array_map(function ($item) {
75 if ($item['information'] === '-') {
76 $item['information'] = null;
80 $item['information'] = unserialize(base64_decode($item['information']), ['allowed_classes' => false]);
82 catch (SystemException
$e) {
83 throw new \
InvalidArgumentException('The additional information section of the given entry is malformed.', 0, $e);
88 $item['stack'] = JSON
::decode($item['stack']);
90 catch (SystemException
$e) {
91 throw new \
InvalidArgumentException('The stack trace of the given entry is malformed.', 0, $e);
95 }, $chainRegex->getMatches());
97 $matches['stackHash'] = sha1(implode("\0", array_map(function ($item) {
99 foreach ($item['stack'] as $stack) {
100 $result .= $stack['file']."\t".$stack['line']."\t".$stack['class'].$stack['type'].$stack['function']."\n";
105 $matches['date'] = strtotime($matches['date']);
106 $matches['chain'] = $chainMatches;
112 * Forbid creation of ExceptionLogUtil objects.
114 private function __construct() {