PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
← All changes | src/component/class-audit.php +31 -104 5.9.0 → 6.3.0 View file →
@@ -39,15 +39,19 @@
39 39 * @param array $events Specific events to fetch.
40 40 * @param string $user_id User ID to filter logs.
41 41 * @param string $ip IP address to filter logs.
42 42 * @param int $paged Pagination page number.
43 + * @param int $per_page Number of logs per page.
43 44 *
44 45 * @return Audit_Log[]|WP_Error Returns an array of Audit_Log objects or WP_Error on failure.
45 46 * @throws Exception Throws exception on failure.
46 47 */
47 - public function fetch( $date_from, $date_to, $events = array(), $user_id = '', $ip = '', $paged = 1 ) {
48 - $internal = Audit_Log::query( $date_from, $date_to, $events, $user_id, $ip, $paged );
48 + public function fetch( $date_from, $date_to, $events = array(), $user_id = '', $ip = '', $paged = 1, $per_page = 10 ) {
49 + $internal = Audit_Log::query( $date_from, $date_to, $events, $user_id, $ip, $paged, $per_page );
49 50 $this->log( sprintf( 'Found %s from local', count( $internal ) ), self::AUDIT_LOG );
51 + if ( ! wd_di()->get( WPMUDEV::class )->is_pro() ) {
52 + return $internal;
53 + }
50 54 $checkpoint = get_site_option( self::CACHE_LAST_CHECKPOINT );
51 55 if ( false === $checkpoint ) {
52 56 // This case where user install the plugin, have some local data but never reach to Logs page, then check point will be today.
53 57 $checkpoint = time();
@@ -67,9 +71,9 @@
67 71 if ( count( $cloud ) ) {
68 72 // No data from cloud too.
69 73 Audit_Log::mass_insert( $cloud );
70 74 // Because this is roughly fetch, so we have to filter out again using the local data.
71 - $internal = Audit_Log::query( $date_from, $date_to, $events, $user_id, $ip, $paged );
75 + $internal = Audit_Log::query( $date_from, $date_to, $events, $user_id, $ip, $paged, $per_page );
72 76 }
73 77 // Cache the last time fetch, this will be useful in case of mixed data.
74 78 update_site_option( self::CACHE_LAST_CHECKPOINT, $date_from );
75 79 // This case we have the data, however, maybe it can be out of the cached range, so we have to check.
@@ -92,9 +96,9 @@
92 96 }
93 97 if ( is_array( $cloud ) ) {
94 98 // Silence the error here, as we actually have data.
95 99 Audit_Log::mass_insert( $cloud );
96 - $internal = Audit_Log::query( $date_from, $date_to, $events, $user_id, $ip, $paged );
100 + $internal = Audit_Log::query( $date_from, $date_to, $events, $user_id, $ip, $paged, $per_page );
97 101 // Cache the last time fetch, this will be useful in case of mixed data.
98 102 update_site_option( self::CACHE_LAST_CHECKPOINT, $date_from );
99 103 }
100 104 }
@@ -148,33 +152,17 @@
148 152
149 153 return $data['data'];
150 154 }
151 155
156 +
152 157 /**
153 - * Flushes logs that need to be synced with the cloud.
158 + * Delete all local audit log entries from database and reset checkpoint.
159 + *
160 + * @return void
154 161 */
155 - public function flush() {
156 - $logs = Audit_Log::get_logs_need_flush();
157 - // Build the data.
158 - $data = array();
159 - foreach ( $logs as $log ) {
160 - $item = $log->export();
161 - unset( $item['synced'] );
162 - unset( $item['safe'] );
163 - unset( $item['id'] );
164 - $item['msg'] = addslashes( $item['msg'] );
165 - $data[] = $item;
166 - }
167 - if ( count( $data ) ) {
168 - $ret = $this->curl_to_api( $data );
169 - if ( ! is_wp_error( $ret ) ) {
170 - $this->log( sprintf( 'API sync successful, marking %s logs as synced', count( $data ) ), self::AUDIT_LOG );
171 - foreach ( $logs as $log_item ) {
172 - $log_item->synced = 1;
173 - $log_item->save();
174 - }
175 - }
176 - }
162 + public function reset(): void {
163 + Audit_Log::truncate();
164 + delete_site_option( self::CACHE_LAST_CHECKPOINT );
177 165 }
178 166
179 167 /**
180 168 * Cleans up old logs based on storage settings.
@@ -241,84 +229,8 @@
241 229 return $ret;
242 230 }
243 231
244 232 /**
245 - * Sends data to the API using a socket connection.
246 - *
247 - * @param array $data Data to be sent to the API.
248 - *
249 - * @return bool Returns true on success, false on failure.
250 - */
251 - public function socket_to_api( $data ) {
252 - $sockets = Array_Cache::get( 'sockets', 'audit', array() );
253 - // We will need to wait a bit.
254 - if ( 0 === ( is_array( $sockets ) || $sockets instanceof Countable ? count( $sockets ) : 0 ) ) {
255 - // Fall back.
256 - return false;
257 - }
258 - $this->log(
259 - sprintf( 'Flush %s to cloud', is_array( $data ) || $data instanceof Countable ? count( $data ) : 0 ),
260 - self::AUDIT_LOG
261 - );
262 - $start_time = microtime( true );
263 - $sks = $sockets;
264 - $r = null;
265 - $e = null;
266 - if ( ( false === stream_select( $r, $sks, $e, 1 ) ) ) {
267 - // This case error happen.
268 - return false;
269 - }
270 -
271 - $fp = array_shift( $sockets );
272 -
273 - $uri = '/logs/add_multiple';
274 - $vars = http_build_query( $data );
275 - $this->attach_behavior( WPMUDEV::class, WPMUDEV::class );
276 - // We're sending data to the server, so we're not manipulating files. Ignore the error.
277 - // @codingStandardsIgnoreStart
278 - fwrite( $fp, 'POST ' . $uri . " HTTP/1.1\r\n" );
279 - fwrite( $fp, 'Host: ' . $this->strip_protocol( $this->get_endpoint() ) . "\r\n" );
280 - fwrite( $fp, "Content-Type: application/x-www-form-urlencoded\r\n" );
281 - fwrite( $fp, 'Content-Length: ' . strlen( $vars ) . "\r\n" );
282 - fwrite( $fp, 'apikey: ' . $this->get_apikey() . "\r\n" );
283 - fwrite( $fp, "Connection: close\r\n" );
284 - fwrite( $fp, "\r\n" );
285 - fwrite( $fp, $vars );
286 - stream_set_timeout( $fp, 5 );
287 - $res = '';
288 - while ( ! feof( $fp ) ) {
289 - $res .= fgets( $fp, 1024 );
290 - // Check if the transfer has taken too long.
291 - $end_time = microtime( true );
292 - if ( $end_time - $start_time > 3 ) {
293 - fclose( $fp );
294 - break;
295 - }
296 - }
297 - // @codingStandardsIgnoreEnd
298 - return true;
299 - }
300 -
301 - /**
302 - * Open a socket to API for faster transmit.
303 - */
304 - public function open_socket() {
305 - $sockets = Array_Cache::get( 'sockets', 'audit', array() );
306 - $endpoint = $this->strip_protocol( $this->get_endpoint() );
307 - if ( array() === $sockets ) {
308 - $fp = stream_socket_client(
309 - 'ssl://' . $endpoint . ':443',
310 - $errno,
311 - $errstr,
312 - 5
313 - );
314 - if ( is_resource( $fp ) ) {
315 - Array_Cache::set( 'sockets', array( $fp ), 'audit' );
316 - }
317 - }
318 - }
319 -
320 - /**
321 233 * Strips the protocol from a URL.
322 234 *
323 235 * @param string $url URL to process.
324 236 *
@@ -410,9 +322,9 @@
410 322 $model = new Audit_Log();
411 323
412 324 if ( ( is_array( $events ) || $events instanceof Countable ? count( $events ) : 0 ) > 1 ) {
413 325 if ( $model->has_method( 'mass_insert' ) ) {
414 - $model->mass_insert( $events );
326 + $model->mass_insert( $events, 0 );
415 327
416 328 return;
417 329 }
418 330 }
@@ -421,6 +333,21 @@
421 333 $model->import( $event );
422 334 $model->synced = 0;
423 335 $model->save();
424 336 }
337 + }
338 +
339 + /**
340 + * Get audit events per week.
341 + */
342 + public static function get_audit_events_per_week(): int {
343 + $timezone = wp_timezone();
344 + $date_to = ( new DateTime( 'now', $timezone ) )
345 + ->setTime( 23, 59, 59 )
346 + ->getTimestamp();
347 + $date_from = ( new DateTime( '-7 days', $timezone ) )
348 + ->setTime( 0, 0, 0 )
349 + ->getTimestamp();
350 +
351 + return Audit_Log::count( $date_from, $date_to );
425 352 }
426 353 }