Passed
Branch master (f497d2)
by Mike
03:18
created

gsync_error_handler()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 38
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 24
nc 22
nop 4
dl 0
loc 38
rs 6.9666
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * SPDX-License-Identifier: AGPL-3.0-only
4
 * SPDX-FileCopyrightText: Copyright 2007-2016 Zarafa Deutschland GmbH
5
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
6
 *
7
 * Debug and logging
8
 */
9
10
class SLog {
11
	private static $wbxmlDebug = '';
12
	private static $lastLogs = [];
13
14
	/**
15
	 * @var Log
16
	 */
17
	private static $logger;
18
19
	/**
20
	 * Initializes the logging.
21
	 *
22
	 * @return bool
23
	 */
24
	public static function Initialize() {
25
		// define some constants for the logging
26
		if (!defined('LOGUSERLEVEL')) {
27
			define('LOGUSERLEVEL', LOGLEVEL_OFF);
28
		}
29
30
		if (!defined('LOGLEVEL')) {
31
			define('LOGLEVEL', LOGLEVEL_OFF);
32
		}
33
34
		$logger = self::getLogger();
0 ignored issues
show
Unused Code introduced by
The assignment to $logger is dead and can be removed.
Loading history...
35
36
		return true;
37
	}
38
39
	/**
40
	 * Check if WBXML logging is enabled in current LOG(USER)LEVEL.
41
	 *
42
	 * @return bool
43
	 */
44
	public static function IsWbxmlDebugEnabled() {
45
		return LOGLEVEL >= LOGLEVEL_WBXML || (LOGUSERLEVEL >= LOGLEVEL_WBXML && self::getLogger()->HasSpecialLogUsers());
46
	}
47
48
	/**
49
	 * Writes a log line.
50
	 *
51
	 * @param int    $loglevel one of the defined LOGLEVELS
52
	 * @param string $message
53
	 * @param bool   $truncate indicate if the message should be truncated, default true
54
	 */
55
	public static function Write($loglevel, $message, $truncate = true) {
56
		// truncate messages longer than 10 KB
57
		$messagesize = strlen($message);
58
		if ($truncate && $messagesize > 10240) {
59
			$message = substr($message, 0, 10240) . sprintf(" <log message with %d bytes truncated>", $messagesize);
60
		}
61
62
		self::$lastLogs[$loglevel] = $message;
63
64
		try {
65
			self::getLogger()->Log($loglevel, $message);
66
		}
67
		catch (\Exception $e) {
68
			// @TODO How should we handle logging error ?
69
			// Ignore any error.
70
		}
71
72
		if ($loglevel & LOGLEVEL_WBXMLSTACK) {
73
			self::$wbxmlDebug .= $message . PHP_EOL;
74
		}
75
	}
76
77
	/**
78
	 * Returns logged information about the WBXML stack.
79
	 *
80
	 * @return string
81
	 */
82
	public static function GetWBXMLDebugInfo() {
83
		return trim(self::$wbxmlDebug);
84
	}
85
86
	/**
87
	 * Returns the last message logged for a log level.
88
	 *
89
	 * @param int $loglevel one of the defined LOGLEVELS
90
	 *
91
	 * @return string/false     returns false if there was no message logged in that level
0 ignored issues
show
Documentation Bug introduced by
The doc comment string/false at position 0 could not be parsed: Unknown type name 'string/false' at position 0 in string/false.
Loading history...
92
	 */
93
	public static function GetLastMessage($loglevel) {
94
		return (isset(self::$lastLogs[$loglevel])) ? self::$lastLogs[$loglevel] : false;
95
	}
96
97
	/**
98
	 * If called, the authenticated current user gets an extra log-file.
99
	 *
100
	 * If called until the user is authenticated (e.g. at the end of IBackend->Logon()) all log
101
	 * messages that happened until this point will also be logged.
102
	 */
103
	public static function SpecialLogUser() {
104
		self::getLogger()->SpecialLogUser();
105
	}
106
107
	/**
108
	 * Returns the logger object. If no logger has been initialized, FileLog will be initialized and returned.
109
	 *
110
	 * @throws Exception thrown if the logger class cannot be instantiated
111
	 *
112
	 * @return Log
113
	 */
114
	private static function getLogger() {
115
		if (!self::$logger) {
116
			global $specialLogUsers; // This variable comes from the configuration file (config.php)
117
118
			$logger = LOGBACKEND_CLASS;
119
			if (!class_exists($logger)) {
120
				$errmsg = 'The configured logging class `' . $logger . '` does not exist. Check your configuration.';
121
				error_log($errmsg);
122
123
				throw new \Exception($errmsg);
124
			}
125
126
			// if there is an impersonated user it's used instead of the GET user
127
			if (Request::GetImpersonatedUser()) {
128
				$user = Request::GetImpersonatedUser();
129
			}
130
			else {
131
				list($user) = Utils::SplitDomainUser(strtolower(Request::GetGETUser()));
132
			}
133
134
			self::$logger = new $logger();
135
			self::$logger->SetUser($user);
136
			self::$logger->SetAuthUser(Request::GetAuthUser());
137
			self::$logger->SetSpecialLogUsers($specialLogUsers);
138
			self::$logger->SetDevid(Request::GetDeviceID());
139
			self::$logger->SetPid(@getmypid());
140
			self::$logger->AfterInitialize();
141
		}
142
143
		return self::$logger;
144
	}
145
146
	/*----------------------------------------------------------------------------------------------------------
147
	 * private log stuff
148
	 */
149
}
150
151
/*----------------------------------------------------------------------------------------------------------
152
 * Legacy debug stuff
153
 */
154
155
// TODO review error handler
156
function gsync_error_handler($errno, $errstr, $errfile, $errline) {
157
	if (defined('LOG_ERROR_MASK')) {
158
		$errno &= LOG_ERROR_MASK;
0 ignored issues
show
Bug introduced by
The constant LOG_ERROR_MASK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
159
	}
160
161
	switch ($errno) {
162
		case 0:
163
			// logging disabled by LOG_ERROR_MASK
164
			break;
165
166
		case E_DEPRECATED:
167
			// do not handle this message
168
			break;
169
170
		case E_NOTICE:
171
		case E_WARNING:
172
			// TODO check if there is a better way to avoid these messages
173
			if (stripos($errfile, 'interprocessdata') !== false && stripos($errstr, 'shm_get_var()') !== false) {
174
				break;
175
			}
176
			SLog::Write(LOGLEVEL_WARN, "{$errfile}:{$errline} {$errstr} ({$errno})");
177
			break;
178
179
		default:
180
			$bt = debug_backtrace();
181
			SLog::Write(LOGLEVEL_ERROR, "trace error: {$errfile}:{$errline} {$errstr} ({$errno}) - backtrace: " . (count($bt) - 1) . " steps");
182
			for ($i = 1, $bt_length = count($bt); $i < $bt_length; ++$i) {
183
				$file = $line = "unknown";
184
				if (isset($bt[$i]['file'])) {
185
					$file = $bt[$i]['file'];
186
				}
187
				if (isset($bt[$i]['line'])) {
188
					$line = $bt[$i]['line'];
189
				}
190
				SLog::Write(LOGLEVEL_ERROR, "trace: {$i}:" . $file . ":" . $line . " - " . ((isset($bt[$i]['class'])) ? $bt[$i]['class'] . $bt[$i]['type'] : "") . $bt[$i]['function'] . "()");
191
			}
192
			// throw new Exception("An error occurred.");
193
			break;
194
	}
195
}
196
197
error_reporting(E_ALL);
198
set_error_handler("gsync_error_handler");
199
200
function gsync_fatal_handler() {
201
	$errfile = "unknown file";
0 ignored issues
show
Unused Code introduced by
The assignment to $errfile is dead and can be removed.
Loading history...
202
	$errstr = "shutdown";
0 ignored issues
show
Unused Code introduced by
The assignment to $errstr is dead and can be removed.
Loading history...
203
	$errno = E_CORE_ERROR;
0 ignored issues
show
Unused Code introduced by
The assignment to $errno is dead and can be removed.
Loading history...
204
	$errline = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $errline is dead and can be removed.
Loading history...
205
206
	$error = error_get_last();
207
208
	if ($error !== null) {
209
		$errno = $error["type"];
210
		$errfile = $error["file"];
211
		$errline = $error["line"];
212
		$errstr = $error["message"];
213
214
		// do NOT log PHP Notice, Warning, Deprecated or Strict as FATAL
215
		if ($errno & ~(E_NOTICE | E_WARNING | E_DEPRECATED | E_STRICT)) {
216
			SLog::Write(LOGLEVEL_FATAL, sprintf("Fatal error: %s:%d - %s (%s)", $errfile, $errline, $errstr, $errno));
217
		}
218
	}
219
}
220
register_shutdown_function("gsync_fatal_handler");
221