This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Elgg system log. |
||
4 | * Listens to events and writes crud events into the system log database. |
||
5 | * |
||
6 | * @package Elgg.Core |
||
7 | * @subpackage Logging |
||
8 | */ |
||
9 | |||
10 | /** |
||
11 | * Retrieve the system log based on a number of parameters. |
||
12 | * |
||
13 | * @todo too many args, and the first arg is too confusing |
||
14 | * |
||
15 | * @param int|array $by_user The guid(s) of the user(s) who initiated the event. |
||
16 | * Use 0 for unowned entries. Anything else falsey means anyone. |
||
17 | * @param string $event The event you are searching on. |
||
18 | * @param string $class The class of object it effects. |
||
19 | * @param string $type The type |
||
20 | * @param string $subtype The subtype. |
||
21 | * @param int $limit Maximum number of responses to return. (default from settings) |
||
22 | * @param int $offset Offset of where to start. |
||
23 | * @param bool $count Return count or not |
||
24 | * @param int $timebefore Lower time limit |
||
25 | * @param int $timeafter Upper time limit |
||
26 | * @param int $object_id GUID of an object |
||
27 | * @param string $ip_address The IP address. |
||
28 | * @return mixed |
||
29 | */ |
||
30 | function get_system_log($by_user = "", $event = "", $class = "", $type = "", $subtype = "", $limit = null, |
||
31 | $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0, |
||
32 | $ip_address = "") { |
||
33 | |||
34 | global $CONFIG; |
||
35 | |||
36 | $by_user_orig = $by_user; |
||
37 | if (is_array($by_user) && sizeof($by_user) > 0) { |
||
38 | foreach ($by_user as $key => $val) { |
||
39 | $by_user[$key] = (int) $val; |
||
40 | } |
||
41 | } else { |
||
42 | $by_user = (int)$by_user; |
||
43 | } |
||
44 | |||
45 | $event = sanitise_string($event); |
||
46 | $class = sanitise_string($class); |
||
47 | $type = sanitise_string($type); |
||
48 | $subtype = sanitise_string($subtype); |
||
49 | $ip_address = sanitise_string($ip_address); |
||
50 | if ($limit === null) { |
||
51 | $limit = elgg_get_config('default_limit'); |
||
52 | } |
||
53 | $limit = (int)$limit; |
||
54 | $offset = (int)$offset; |
||
55 | |||
56 | $where = array(); |
||
57 | |||
58 | if ($by_user_orig !== "" && $by_user_orig !== false && $by_user_orig !== null) { |
||
59 | if (is_int($by_user)) { |
||
60 | $where[] = "performed_by_guid=$by_user"; |
||
61 | } else if (is_array($by_user)) { |
||
62 | $where [] = "performed_by_guid in (" . implode(",", $by_user) . ")"; |
||
63 | } |
||
64 | } |
||
65 | if ($event != "") { |
||
66 | $where[] = "event='$event'"; |
||
67 | } |
||
68 | if ($class !== "") { |
||
69 | $where[] = "object_class='$class'"; |
||
70 | } |
||
71 | if ($type != "") { |
||
72 | $where[] = "object_type='$type'"; |
||
73 | } |
||
74 | if ($subtype !== "") { |
||
75 | $where[] = "object_subtype='$subtype'"; |
||
76 | } |
||
77 | |||
78 | if ($timebefore) { |
||
79 | $where[] = "time_created < " . ((int) $timebefore); |
||
80 | } |
||
81 | if ($timeafter) { |
||
82 | $where[] = "time_created > " . ((int) $timeafter); |
||
83 | } |
||
84 | if ($object_id) { |
||
85 | $where[] = "object_id = " . ((int) $object_id); |
||
86 | } |
||
87 | if ($ip_address) { |
||
88 | $where[] = "ip_address = '$ip_address'"; |
||
89 | } |
||
90 | |||
91 | $select = "*"; |
||
92 | if ($count) { |
||
93 | $select = "count(*) as count"; |
||
94 | } |
||
95 | $query = "SELECT $select from {$CONFIG->dbprefix}system_log where 1 "; |
||
96 | foreach ($where as $w) { |
||
97 | $query .= " and $w"; |
||
98 | } |
||
99 | |||
100 | if (!$count) { |
||
101 | $query .= " order by time_created desc"; |
||
102 | $query .= " limit $offset, $limit"; // Add order and limit |
||
103 | } |
||
104 | |||
105 | View Code Duplication | if ($count) { |
|
106 | $numrows = get_data_row($query); |
||
107 | if ($numrows) { |
||
0 ignored issues
–
show
|
|||
108 | return $numrows->count; |
||
109 | } |
||
110 | } else { |
||
111 | return get_data($query); |
||
112 | } |
||
113 | |||
114 | return false; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Return a specific log entry. |
||
119 | * |
||
120 | * @param int $entry_id The log entry |
||
121 | * |
||
122 | * @return mixed |
||
123 | */ |
||
124 | function get_log_entry($entry_id) { |
||
125 | global $CONFIG; |
||
126 | |||
127 | $entry_id = (int)$entry_id; |
||
128 | |||
129 | return get_data_row("SELECT * from {$CONFIG->dbprefix}system_log where id=$entry_id"); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Return the object referred to by a given log entry |
||
134 | * |
||
135 | * @param \stdClass|int $entry The log entry row or its ID |
||
136 | * |
||
137 | * @return mixed |
||
138 | */ |
||
139 | function get_object_from_log_entry($entry) { |
||
140 | if (is_numeric($entry)) { |
||
141 | $entry = get_log_entry($entry); |
||
142 | if (!$entry) { |
||
0 ignored issues
–
show
The expression
$entry of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
143 | return false; |
||
144 | } |
||
145 | } |
||
146 | |||
147 | $class = $entry->object_class; |
||
148 | $id = $entry->object_id; |
||
149 | |||
150 | if (!class_exists($class)) { |
||
151 | // failed autoload |
||
152 | return false; |
||
153 | } |
||
154 | |||
155 | $getters = array( |
||
156 | 'ElggAnnotation' => 'elgg_get_annotation_from_id', |
||
157 | 'ElggMetadata' => 'elgg_get_metadata_from_id', |
||
158 | 'ElggRelationship' => 'get_relationship', |
||
159 | ); |
||
160 | |||
161 | if (isset($getters[$class]) && is_callable($getters[$class])) { |
||
162 | $object = call_user_func($getters[$class], $id); |
||
163 | } elseif (preg_match('~^Elgg[A-Z]~', $class)) { |
||
164 | $object = get_entity($id); |
||
165 | } else { |
||
166 | // surround with try/catch because object could be disabled |
||
167 | try { |
||
168 | $object = new $class($entry->object_id); |
||
169 | return $object; |
||
170 | } catch (Exception $e) { |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
171 | |||
172 | } |
||
173 | } |
||
174 | |||
175 | if (!is_object($object) || get_class($object) !== $class) { |
||
176 | return false; |
||
177 | } |
||
178 | |||
179 | return $object; |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Log a system event related to a specific object. |
||
184 | * |
||
185 | * This is called by the event system and should not be called directly. |
||
186 | * |
||
187 | * @param object $object The object you're talking about. |
||
188 | * @param string $event The event being logged |
||
189 | * @return void |
||
190 | */ |
||
191 | function system_log($object, $event) { |
||
192 | global $CONFIG; |
||
193 | static $log_cache; |
||
194 | static $cache_size = 0; |
||
195 | |||
196 | if ($object instanceof Loggable) { |
||
197 | |||
198 | /* @var \ElggEntity|\ElggExtender $object */ |
||
199 | if (datalist_get('version') < 2012012000) { |
||
200 | // this is a site that doesn't have the ip_address column yet |
||
201 | return; |
||
202 | } |
||
203 | |||
204 | // reset cache if it has grown too large |
||
205 | if (!is_array($log_cache) || $cache_size > 500) { |
||
206 | $log_cache = array(); |
||
207 | $cache_size = 0; |
||
208 | } |
||
209 | |||
210 | // Has loggable interface, extract the necessary information and store |
||
211 | $object_id = (int)$object->getSystemLogID(); |
||
212 | $object_class = get_class($object); |
||
213 | $object_type = $object->getType(); |
||
214 | $object_subtype = $object->getSubtype(); |
||
215 | $event = sanitise_string($event); |
||
216 | $time = time(); |
||
217 | $ip_address = sanitize_string(_elgg_services()->request->getClientIp()); |
||
218 | if (!$ip_address) { |
||
219 | $ip_address = '0.0.0.0'; |
||
220 | } |
||
221 | $performed_by = elgg_get_logged_in_user_guid(); |
||
222 | |||
223 | if (isset($object->access_id)) { |
||
224 | $access_id = $object->access_id; |
||
225 | } else { |
||
226 | $access_id = ACCESS_PUBLIC; |
||
227 | } |
||
228 | if (isset($object->enabled)) { |
||
229 | $enabled = $object->enabled; |
||
230 | } else { |
||
231 | $enabled = 'yes'; |
||
232 | } |
||
233 | |||
234 | if (isset($object->owner_guid)) { |
||
235 | $owner_guid = $object->owner_guid; |
||
236 | } else { |
||
237 | $owner_guid = 0; |
||
238 | } |
||
239 | |||
240 | // Create log if we haven't already created it |
||
241 | if (!isset($log_cache[$time][$object_id][$event])) { |
||
242 | |||
243 | // replaced "insert delayed into" -> "insert into" - insert delayed not supported with InnoDB - CdG |
||
244 | $query = "INSERT into {$CONFIG->dbprefix}system_log |
||
245 | (object_id, object_class, object_type, object_subtype, event, |
||
246 | performed_by_guid, owner_guid, access_id, enabled, time_created, ip_address) |
||
247 | VALUES |
||
248 | ('$object_id','$object_class','$object_type', '$object_subtype', '$event', |
||
249 | $performed_by, $owner_guid, $access_id, '$enabled', '$time', '$ip_address')"; |
||
250 | |||
251 | insert_data($query); |
||
252 | |||
253 | $log_cache[$time][$object_id][$event] = true; |
||
254 | $cache_size += 1; |
||
255 | } |
||
256 | } |
||
257 | } |
||
258 | |||
259 | /** |
||
260 | * This function creates an archive copy of the system log. |
||
261 | * |
||
262 | * @param int $offset An offset in seconds from now to archive (useful for log rotation) |
||
263 | * |
||
264 | * @return bool |
||
265 | */ |
||
266 | function archive_log($offset = 0) { |
||
267 | global $CONFIG; |
||
268 | |||
269 | $offset = (int)$offset; |
||
270 | $now = time(); // Take a snapshot of now |
||
271 | |||
272 | $ts = $now - $offset; |
||
273 | |||
274 | // create table |
||
275 | $query = "CREATE TABLE {$CONFIG->dbprefix}system_log_$now as |
||
276 | SELECT * from {$CONFIG->dbprefix}system_log WHERE time_created<$ts"; |
||
277 | |||
278 | if (!update_data($query)) { |
||
279 | return false; |
||
280 | } |
||
281 | |||
282 | // delete |
||
283 | // Don't delete on time since we are running in a concurrent environment |
||
284 | if (delete_data("DELETE from {$CONFIG->dbprefix}system_log WHERE time_created<$ts") === false) { |
||
285 | return false; |
||
286 | } |
||
287 | |||
288 | // alter table to engine |
||
289 | if (!update_data("ALTER TABLE {$CONFIG->dbprefix}system_log_$now engine=archive")) { |
||
290 | return false; |
||
291 | } |
||
292 | |||
293 | return true; |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * Default system log handler, allows plugins to override, extend or disable logging. |
||
298 | * |
||
299 | * @param string $event Event name |
||
300 | * @param string $object_type Object type |
||
301 | * @param Loggable $object Object to log |
||
302 | * |
||
303 | * @return true |
||
304 | */ |
||
305 | function system_log_default_logger($event, $object_type, $object) { |
||
306 | system_log($object['object'], $object['event']); |
||
307 | |||
308 | return true; |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * System log listener. |
||
313 | * This function listens to all events in the system and logs anything appropriate. |
||
314 | * |
||
315 | * @param String $event Event name |
||
316 | * @param String $object_type Type of object |
||
317 | * @param Loggable $object Object to log |
||
318 | * |
||
319 | * @return true |
||
320 | * @access private |
||
321 | */ |
||
322 | function system_log_listener($event, $object_type, $object) { |
||
323 | if (($object_type != 'systemlog') && ($event != 'log')) { |
||
324 | elgg_trigger_event('log', 'systemlog', array('object' => $object, 'event' => $event)); |
||
0 ignored issues
–
show
array('object' => $object, 'event' => $event) is of type array<string,object<Logg...le>","event":"string"}> , but the function expects a string|null .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
325 | } |
||
326 | |||
327 | return true; |
||
328 | } |
||
329 | |||
330 | return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) { |
||
331 | /** Register event to listen to all events **/ |
||
332 | $events->registerHandler('all', 'all', 'system_log_listener', 400); |
||
333 | |||
334 | /** Register a default system log handler */ |
||
335 | $events->registerHandler('log', 'systemlog', 'system_log_default_logger', 999); |
||
336 | }; |
||
337 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.