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 | * Logging functionalities |
||||
8 | */ |
||||
9 | |||||
10 | class Syslog extends Log { |
||||
11 | protected $program_name = ''; |
||||
12 | protected $host; |
||||
13 | protected $port; |
||||
14 | |||||
15 | /** |
||||
16 | * @return string |
||||
17 | */ |
||||
18 | public function GetProgramName() { |
||||
19 | return $this->program_name; |
||||
20 | } |
||||
21 | |||||
22 | /** |
||||
23 | * @param string $value |
||||
24 | */ |
||||
25 | public function SetProgramName($value) { |
||||
26 | $this->program_name = $value; |
||||
27 | } |
||||
28 | |||||
29 | /** |
||||
30 | * @return string |
||||
31 | */ |
||||
32 | public function GetHost() { |
||||
33 | return $this->host; |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
34 | } |
||||
35 | |||||
36 | /** |
||||
37 | * @param string $value |
||||
38 | */ |
||||
39 | public function SetHost($value) { |
||||
40 | $this->host = $value; |
||||
41 | } |
||||
42 | |||||
43 | /** |
||||
44 | * @return int |
||||
45 | */ |
||||
46 | public function GetPort() { |
||||
47 | return $this->port; |
||||
48 | } |
||||
49 | |||||
50 | /** |
||||
51 | * @param int $value |
||||
52 | */ |
||||
53 | public function SetPort($value) { |
||||
54 | if (is_numeric($value)) { |
||||
0 ignored issues
–
show
|
|||||
55 | $this->port = (int) $value; |
||||
56 | } |
||||
57 | } |
||||
58 | |||||
59 | /** |
||||
60 | * Constructor. |
||||
61 | * Sets configured values if no parameters are given. |
||||
62 | * |
||||
63 | * @param string $program_name |
||||
64 | * @param string $host |
||||
65 | * @param string $port |
||||
66 | */ |
||||
67 | public function __construct($program_name = null, $host = null, $port = null) { |
||||
68 | parent::__construct(); |
||||
69 | |||||
70 | if (is_null($program_name)) { |
||||
71 | $program_name = LOG_SYSLOG_PROGRAM; |
||||
72 | } |
||||
73 | if (is_null($host)) { |
||||
74 | $host = LOG_SYSLOG_HOST; |
||||
75 | } |
||||
76 | if (is_null($port)) { |
||||
77 | $port = LOG_SYSLOG_PORT; |
||||
78 | } |
||||
79 | |||||
80 | $this->SetProgramName($program_name); |
||||
81 | $this->SetHost($host); |
||||
0 ignored issues
–
show
It seems like
$host can also be of type false ; however, parameter $value of Syslog::SetHost() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
82 | $this->SetPort($port); |
||||
0 ignored issues
–
show
It seems like
$port can also be of type string ; however, parameter $value of Syslog::SetPort() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
83 | } |
||||
84 | |||||
85 | /** |
||||
86 | * Return the full program name for syslog. |
||||
87 | * The name can be grommunio-sync/core or grommunio-sync/{backend} where backend is the backend that initiated the log. |
||||
88 | * |
||||
89 | * @return string |
||||
90 | */ |
||||
91 | protected function GenerateProgramName() { |
||||
92 | // @TODO Use another mechanism than debug_backtrace to determine to origin of the log |
||||
93 | $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); |
||||
94 | // Shift the "syslog.php" entry. |
||||
95 | array_shift($backtrace); |
||||
96 | foreach ($backtrace as $trace) { |
||||
97 | if (!isset($trace['file'])) { |
||||
98 | continue; |
||||
99 | } |
||||
100 | if (strpos($trace['file'], REAL_BASE_PATH . 'backend/') !== false) { |
||||
101 | preg_match('/\/backend\/([a-zA-Z]*)/', $trace['file'], $match); |
||||
102 | if (isset($match[1])) { |
||||
103 | return $this->GetProgramName() . '/' . $match[1]; |
||||
104 | } |
||||
105 | } |
||||
106 | elseif (basename($trace['file'], '.php') != 'slog') { |
||||
107 | return $this->GetProgramName() . '/core'; |
||||
108 | } |
||||
109 | } |
||||
110 | |||||
111 | return $this->GetProgramName() . '/core'; |
||||
112 | } |
||||
113 | |||||
114 | /** |
||||
115 | * Maps the grommunio-sync loglevel with those of syslog. |
||||
116 | * |
||||
117 | * @param int $loglevel |
||||
118 | * |
||||
119 | * @return int one of many LOG_* syslog level |
||||
120 | */ |
||||
121 | protected function GetGsyncLogLevelToSyslogLogLevel($loglevel) { |
||||
122 | switch ($loglevel) { |
||||
123 | case LOGLEVEL_FATAL: |
||||
124 | return LOG_ALERT; |
||||
125 | |||||
126 | case LOGLEVEL_ERROR: |
||||
127 | return LOG_ERR; |
||||
128 | |||||
129 | case LOGLEVEL_WARN: |
||||
130 | return LOG_WARNING; |
||||
131 | |||||
132 | case LOGLEVEL_INFO: |
||||
133 | return LOG_INFO; |
||||
134 | |||||
135 | case LOGLEVEL_DEBUG: |
||||
136 | return LOG_DEBUG; |
||||
137 | |||||
138 | case LOGLEVEL_WBXML: |
||||
139 | return LOG_DEBUG; |
||||
140 | |||||
141 | case LOGLEVEL_DEVICEID: |
||||
142 | return LOG_DEBUG; |
||||
143 | |||||
144 | case LOGLEVEL_WBXMLSTACK: |
||||
145 | return LOG_DEBUG; |
||||
146 | } |
||||
147 | |||||
148 | return null; |
||||
149 | } |
||||
150 | |||||
151 | /** |
||||
152 | * Build the log string for syslog. |
||||
153 | * |
||||
154 | * @param int $loglevel |
||||
155 | * @param string $message |
||||
156 | * @param bool $includeUserDevice puts username and device in the string, default: true |
||||
157 | * |
||||
158 | * @return string |
||||
159 | */ |
||||
160 | public function BuildLogString($loglevel, $message, $includeUserDevice = true) { |
||||
0 ignored issues
–
show
The parameter
$includeUserDevice is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
161 | $log = $this->GetLogLevelString($loglevel); // Never pad syslog log because syslog log are usually read with a software. |
||||
162 | // when the users differ, we need to log both |
||||
163 | if (strcasecmp($this->GetAuthUser(), $this->GetUser()) == 0) { |
||||
164 | $log .= ' [' . $this->GetUser() . ']'; |
||||
165 | } |
||||
166 | else { |
||||
167 | $log .= ' [' . $this->GetAuthUser() . Request::IMPERSONATE_DELIM . $this->GetUser() . ']'; |
||||
168 | } |
||||
169 | if ($loglevel >= LOGLEVEL_DEVICEID) { |
||||
170 | $log .= '[' . $this->GetDevid() . ']'; |
||||
171 | } |
||||
172 | $log .= ' ' . $message; |
||||
173 | |||||
174 | return $log; |
||||
175 | } |
||||
176 | |||||
177 | // |
||||
178 | // Implementation of Log |
||||
179 | // |
||||
180 | |||||
181 | /** |
||||
182 | * Writes a log message to the general log. |
||||
183 | * |
||||
184 | * @param int $loglevel |
||||
185 | * @param string $message |
||||
186 | */ |
||||
187 | protected function Write($loglevel, $message) { |
||||
188 | if ($this->GetHost() && $this->GetPort()) { |
||||
189 | $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); |
||||
190 | $facility = 1; // user level |
||||
191 | $pri = ($facility * 8) + $loglevel; // multiplying the Facility number by 8 + adding the level |
||||
192 | $data = $this->BuildLogString($loglevel, $message); |
||||
193 | if (strlen(trim($data)) > 0) { |
||||
194 | $syslog_message = "<{$pri}>" . date('M d H:i:s ') . '[' . $this->GetProgramName() . ']: ' . $data; |
||||
195 | socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, $this->GetHost(), $this->GetPort()); |
||||
196 | } |
||||
197 | socket_close($sock); |
||||
198 | } |
||||
199 | else { |
||||
200 | openlog($this->GenerateProgramName(), LOG_PID, LOG_SYSLOG_FACILITY); |
||||
201 | syslog( |
||||
202 | $this->GetGsyncLogLevelToSyslogLogLevel($loglevel), |
||||
203 | $this->BuildLogString($loglevel, $message) |
||||
204 | ); |
||||
205 | } |
||||
206 | } |
||||
207 | |||||
208 | /** |
||||
209 | * This function is used as an event for log implementer. |
||||
210 | * It happens when the a call to the Log function is finished. |
||||
211 | * |
||||
212 | * @param mixed $loglevel |
||||
213 | * @param mixed $message |
||||
214 | */ |
||||
215 | public function WriteForUser($loglevel, $message) { |
||||
216 | $this->Write(LOGLEVEL_DEBUG, $message); // Always pass the logleveldebug so it uses syslog level LOG_DEBUG |
||||
217 | } |
||||
218 | } |
||||
219 |