PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.5.1
Defender Security – Malware Scanner, Login Security & Firewall v5.5.1
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
defender-security / src / controller / class-hub.php

class-hub.php in Defender Security – Malware Scanner, Login Security & Firewall 5.5.1, at src/controller/class-hub.php

910 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle various actions and interactions with the WPMUDEV Hub.
4 *
5 * @package WP_Defender\Controller
6 */
7
8 namespace WP_Defender\Controller;
9
10 use WP_Defender\Event;
11 use WP_Defender\Traits\IO;
12 use WP_Defender\Traits\Formats;
13 use WP_Defender\Behavior\WPMUDEV;
14 use WP_Defender\Model\Lockout_Log;
15 use WP_Defender\Component\Quarantine;
16 use WP_Defender\Model\Setting\Two_Fa;
17 use WP_Defender\Component\IP\Antibot_Global_Firewall;
18 use WP_Defender\Component\IP\Global_IP;
19 use WP_Defender\Component\Backup_Settings;
20 use WP_Defender\Model\Setting\Login_Lockout;
21 use WP_Defender\Model\Setting\Notfound_Lockout;
22 use WP_Defender\Model\Notification\Audit_Report;
23 use WP_Defender\Model\Setting\Blacklist_Lockout;
24 use WP_Defender\Model\Setting\Global_Ip_Lockout;
25 use WP_Defender\Component\Config\Config_Adapter;
26 use WP_Defender\Model\Setting\User_Agent_Lockout;
27 use WP_Defender\Model\Notification\Malware_Report;
28 use WP_Defender\Model\Notification\Tweak_Reminder;
29 use WP_Defender\Component\Config\Config_Hub_Helper;
30 use WP_Defender\Model\Notification\Firewall_Report;
31 use WP_Defender\Model\Notification\Malware_Notification;
32 use WP_Defender\Model\Notification\Firewall_Notification;
33 use WP_Defender\Model\Setting\Audit_Logging as Model_Audit_Logging;
34 use WP_Defender\Model\Setting\Security_Tweaks as Model_Security_Tweaks;
35 use WP_Defender\Model\Setting\Antibot_Global_Firewall_Setting;
36
37 /**
38 * Handles various actions and interactions with the WPMUDEV Hub.
39 */
40 class HUB extends Event {
41
42 use IO;
43 use Formats;
44
45 /**
46 * Flag indicating whether to display the onboarding view or not.
47 *
48 * @var bool
49 */
50 private $view_onboard = false;
51
52 /**
53 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
54 */
55 public function __construct() {
56 $this->attach_behavior( WPMUDEV::class, WPMUDEV::class );
57 add_action( 'wdp_register_hub_action', array( $this, 'add_hub_endpoint' ) );
58 add_action( 'defender_hub_sync', array( $this, 'hub_sync' ) );
59 }
60
61 /**
62 * Add various hub endpoints to the actions array.
63 *
64 * @param array $actions An array of actions.
65 *
66 * @return array The updated actions array with hub endpoints added.
67 */
68 public function add_hub_endpoint( $actions ) {
69 $actions['defender_new_scan'] = array( $this, 'new_scan' );
70 $actions['defender_schedule_scan'] = array( $this, 'schedule_scan' );
71 $actions['defender_manage_audit_log'] = array( $this, 'manage_audit_log' );
72 $actions['defender_manage_lockout'] = array( $this, 'manage_lockout' );
73 $actions['defender_whitelist_ip'] = array( $this, 'whitelist_ip' );
74 $actions['defender_blacklist_ip'] = array( $this, 'blacklist_ip' );
75 $actions['defender_get_scan_progress'] = array( $this, 'get_scan_progress' );
76 $actions['defender_manage_recaptcha'] = array( $this, 'manage_recaptcha' );
77 $actions['defender_manage_2fa'] = array( $this, 'manage_2fa' );
78 $actions['defender_manage_global_ip_list'] = array( $this, 'manage_global_ip_list' );
79 $actions['defender_set_global_ip_list'] = array( $this, 'set_global_ips' );
80 $actions['defender_set_antibot_status'] = array( $this, 'set_antibot_status' );
81 // Backup/restore settings.
82 $actions['defender_export_settings'] = array( $this, 'export_settings' );
83 $actions['defender_import_settings'] = array( $this, 'import_settings' );
84 // Get stats, version#1.
85 $actions['defender_get_stats'] = array( $this, 'get_stats' );
86 // Version#2.
87 $actions['defender_get_stats_v2'] = array( $this, 'defender_get_stats_v2' );
88
89 $actions['defender_get_quarantined_files'] = array( $this, 'get_quarantined_files' );
90 $actions['defender_restore_quarantined_file'] = array( $this, 'restore_quarantined_file' );
91
92 return $actions;
93 }
94
95 /**
96 * Create new scan, triggered from HUB.
97 */
98 public function new_scan() {
99 $scan = \WP_Defender\Model\Scan::create();
100 if ( is_wp_error( $scan ) ) {
101 wp_send_json_error(
102 array(
103 'message' => $scan->get_error_message(),
104 )
105 );
106 }
107 // Todo: need to save Malware_Report last_sent & est_timestamp?
108 $scan_controller = wd_di()->get( Scan::class );
109 $scan_controller->do_async_scan( 'hub' );
110
111 wp_send_json_success();
112 }
113
114 /**
115 * Schedule a scan, from HUB.
116 *
117 * @param array $params Schedule config.
118 */
119 public function schedule_scan( $params ) {
120 $frequency = $params['frequency'];
121 $day = $params['day'];
122 $time = $params['time'];
123 $allowed_freq = array( 1, 7, 30 );
124 if (
125 ! in_array( $frequency, $allowed_freq, true )
126 || ! in_array( $day, $this->get_days_of_week(), true )
127 || ! in_array( $time, $this->get_times(), true )
128 ) {
129 wp_send_json_error();
130 }
131 $malware_report = new Malware_Report();
132 $malware_report->frequency = $frequency;
133 $malware_report->day = $day;
134 $malware_report->time = $time;
135 $malware_report->save();
136
137 wp_send_json_success();
138 }
139
140 /**
141 * Track a feature activation or deactivation from the Hub.
142 *
143 * @param bool $is_active Whether the feature is being activated or deactivated.
144 * @param string $feature_title The title of the feature being tracked.
145 */
146 protected function track_feature_from_hub( bool $is_active, string $feature_title ) {
147 $event = $is_active ? 'def_feature_activated' : 'def_feature_deactivated';
148 $data = array(
149 'Feature' => $feature_title,
150 'Triggered From' => 'Hub',
151 );
152
153 $this->track_feature( $event, $data );
154 }
155
156 /**
157 * Manage the audit log settings by toggling the enabled status of the Audit Logging feature.
158 *
159 * @return void
160 */
161 public function manage_audit_log() {
162 $response = null;
163 if ( class_exists( Model_Audit_Logging::class ) ) {
164 $settings = new Model_Audit_Logging();
165 $response = array();
166 if ( true === $settings->enabled ) {
167 $settings->enabled = false;
168 $response['enabled'] = false;
169 } else {
170 $settings->enabled = true;
171 $response['enabled'] = true;
172 }
173 $settings->save();
174 // Track.
175 if ( $this->is_tracking_active() ) {
176 $this->track_feature_from_hub( ! $settings->enabled, 'Audit Logging' );
177 }
178 }
179
180 wp_send_json_success( $response );
181 }
182
183 /**
184 * Manages the lockout feature based on the given parameters.
185 *
186 * @param array $params The parameters for managing the lockout.
187 * - type (string): The type of lockout to manage. Possible values: 'login', '404',
188 * 'ua-lockout'.
189 * @param string $action The action to perform on the lockout.
190 *
191 * @return void
192 */
193 public function manage_lockout( $params, $action ) {
194 $type = $params['type'];
195 $response = array();
196 if ( 'login' === $type ) {
197 $settings = new Login_Lockout();
198 if ( $settings->enabled ) {
199 $settings->enabled = false;
200 $response[ $type ] = 'disabled';
201 } else {
202 $settings->enabled = true;
203 $response[ $type ] = 'enabled';
204 }
205 $settings->save();
206 $feature = 'Login Protection';
207 } elseif ( '404' === $type ) {
208 $settings = new Notfound_Lockout();
209 if ( $settings->enabled ) {
210 $settings->enabled = false;
211 $response[ $type ] = 'disabled';
212 } else {
213 $settings->enabled = true;
214 $response[ $type ] = 'enabled';
215 }
216 $settings->save();
217 $feature = '404 Detection';
218 } elseif ( 'ua-lockout' === $type ) {
219 $settings = new User_Agent_Lockout();
220 if ( $settings->enabled ) {
221 $settings->enabled = false;
222 $response[ $type ] = 'disabled';
223 } else {
224 $settings->enabled = true;
225 $response[ $type ] = 'enabled';
226 }
227 $settings->save();
228 } else {
229 $response[ $type ] = 'invalid';
230 }
231 // Track. Only for Login & NF Lockouts. Ignoring phpcs error due to all possible types.
232 if ( $this->is_tracking_active() && in_array( $type, array( 'login', '404' ), true ) ) {
233 $event = $settings->enabled ? 'def_feature_deactivated' : 'def_feature_activated';
234 $data = array(
235 'Feature' => $feature,
236 'Triggered From' => 'Hub',
237 );
238
239 $this->track_feature( $event, $data );
240 }
241
242 wp_send_json_success( $response );
243 }
244
245 /**
246 * Whitelists an IP address by removing it from the block list and adding it to the allow list.
247 *
248 * @param array $params An array containing the IP address to whitelist.
249 * @param string $action The action to perform.
250 *
251 * @return void
252 */
253 public function whitelist_ip( $params, $action ) {
254 $settings = new Blacklist_Lockout();
255 $ip = $params['ip'];
256 if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
257 $settings->remove_from_list( $ip, 'blocklist' );
258 $settings->add_to_list( $ip, 'allowlist' );
259 } else {
260 wp_send_json_error();
261 }
262 wp_send_json_success();
263 }
264
265 /**
266 * Blacklist an IP address by removing it from the allow list and adding it to the block list.
267 *
268 * @param array $params An array containing the IP address to blacklist.
269 * @param string $action The action to perform.
270 */
271 public function blacklist_ip( $params, $action ) {
272 $settings = new Blacklist_Lockout();
273 $ip = $params['ip'];
274 if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
275 $settings->remove_from_list( $ip, 'allowlist' );
276 $settings->add_to_list( $ip, 'blocklist' );
277 } else {
278 wp_send_json_error();
279 }
280 wp_send_json_success();
281 }
282
283 /**
284 * Push data into HUB. It's without timezone.
285 *
286 * @param array $params An array containing the data to push.
287 * @param string $action The action to perform.
288 */
289 public function get_stats( $params, $action ) {
290 $data = $this->build_stats_to_hub();
291 wp_send_json_success(
292 array( 'stats' => $data )
293 );
294 }
295
296 /**
297 * Push scan data into HUB.
298 */
299 public function get_scan_progress() {
300 $model = \WP_Defender\Model\Scan::get_active();
301 if ( ! is_object( $model ) ) {
302 wp_send_json_success(
303 array( 'progress' => - 1 )
304 );
305 }
306 $percent = $model->percent;
307 if ( $percent > 100 ) {
308 $percent = 100;
309 }
310 wp_send_json_success(
311 array( 'progress' => $percent )
312 );
313 }
314
315 /**
316 * Export settings to HUB.
317 * Analog to export_strings but return not array. So separated method.
318 */
319 public function export_settings() {
320 $config_component = wd_di()->get( Backup_Settings::class );
321 $data = $config_component->parse_data_for_hub();
322 // Replace all the new line in configs.
323 $configs = $data['configs'];
324 foreach ( $configs as $module => $mdata ) {
325 foreach ( $mdata as $key => $value ) {
326 if ( is_string( $value ) ) {
327 $value = str_replace( array( "\r", "\n" ), '{nl}', $value );
328 $mdata[ $key ] = $value;
329 }
330 }
331 $configs[ $module ] = $mdata;
332 }
333 $data['configs'] = $configs;
334 wp_send_json_success( $data );
335 }
336
337 /**
338 * Import settings from HUB.
339 * Analog to import_data but with object $params. So separated method.
340 *
341 * @param object object $params Request parameters.
342 */
343 public function import_settings( $params ) {
344 // Dirty but quick.
345 if ( empty( $params->configs ) ) {
346 wp_send_json_error(
347 array( 'message' => esc_html__( 'Invalid config', 'defender-security' ) )
348 );
349 }
350
351 $configs = json_decode( wp_json_encode( $params->configs ), true );
352 if ( empty( $configs ) ) {
353 wp_send_json_error(
354 array( 'message' => esc_html__( 'Empty data', 'defender-security' ) )
355 );
356 }
357
358 $config_component = wd_di()->get( Backup_Settings::class );
359 $lockout_service = wd_di()->get( \WP_Defender\Component\Blacklist_Lockout::class );
360 foreach ( $configs as $module => $mdata ) {
361 foreach ( $mdata as $key => $value ) {
362 // Todo: update logic to import/export whitelisted/blocklisted countries via maxmind_license_key.
363 if ( in_array( $key, array( 'geoIP_db', 'geodb_path' ), true ) ) {
364 if ( ! empty( $value ) ) {
365 // Download it.
366 $lockout_service->is_geodb_downloaded();
367 } else {
368 // Reset it.
369 $mdata[ $key ] = '';
370 }
371 } elseif ( is_string( $value ) ) {
372 $value = str_replace( '{nl}', PHP_EOL, $value );
373 $mdata[ $key ] = $value;
374 }
375 }
376 $configs[ $module ] = $mdata;
377 }
378
379 // If it's old config structure then we upgrade configs to new format.
380 if ( ! empty( $configs ) && ! $config_component->check_for_new_structure( $configs ) ) {
381 $adapter = wd_di()->get( Config_Adapter::class );
382 $configs = $adapter->upgrade( $configs );
383 }
384 $restore_result = $config_component->restore_data( $configs, 'hub' );
385 if ( is_string( $restore_result ) ) {
386 wp_send_json_error(
387 array( 'message' => $restore_result )
388 );
389 }
390
391 // Active config.
392 Config_Hub_Helper::active_config_from_hub_id( (int) $params->hub_config_id );
393
394 wp_send_json_success();
395 }
396
397 /**
398 * Build the json data for HUB 2.0.
399 */
400 public function defender_get_stats_v2() {
401 global $wp_version;
402
403 $audit_log = wd_di()->get( Audit_Logging::class );
404 $audit = $audit_log->summary_data( true );
405
406 $scan = \WP_Defender\Model\Scan::get_last();
407 $total = 0;
408 if ( is_object( $scan ) ) {
409 $total += count( $scan->get_issues() );
410 }
411 // Total number of Scan issues and Ignored items.
412 $scan_total_issues = $total;
413 // Exclude direct call of data_frontend().
414 $tweak_arr = wd_di()->get( Model_Security_Tweaks::class )->get_tweak_types();
415
416 $total += $tweak_arr['count_issues'];
417 // Get statuses of login/404/ua-request if Firewall Notification is enabled.
418 $firewall_notification = wd_di()->get( Firewall_Notification::class );
419
420 if ( 'enabled' === $firewall_notification->status ) {
421 $login_lockout = $firewall_notification->configs['login_lockout'];
422 $nf_lockout = $firewall_notification->configs['nf_lockout'];
423 // since 3.3.0.
424 $ua_lockout = $firewall_notification->configs['ua_lockout'] ?? false;
425 } else {
426 $login_lockout = false;
427 $nf_lockout = false;
428 $ua_lockout = false;
429 }
430
431 $status_active = \WP_Defender\Model\Notification::STATUS_ACTIVE;
432 $model_sec_headers = wd_di()->get( \WP_Defender\Model\Setting\Security_Headers::class );
433 $scan_report = wd_di()->get( Malware_Report::class );
434 $two_fa = wd_di()->get( Two_Fa::class );
435
436 $quarantined_files = class_exists( 'WP_Defender\Component\Quarantine' ) ?
437 wd_di()->get( Quarantine::class )->hub_list() : array();
438 $antibot_service = wd_di()->get( Antibot_Global_Firewall::class );
439
440 $ret = array(
441 'summary' => array(
442 'count' => $total,
443 'next_scan' => $scan_report->get_next_run_for_hub(),
444 ),
445 'report' => array(
446 'malware_scan' => $scan_report->get_next_run_as_string( true ),
447 'firewall' => wd_di()->get( Firewall_Report::class )->get_next_run_as_string( true ),
448 'audit_logging' => wd_di()->get( Audit_Report::class )->get_next_run_as_string( true ),
449 ),
450 'security_tweaks' => array(
451 'issues' => $tweak_arr['count_issues'],
452 'fixed' => $tweak_arr['count_fixed'],
453 'notification' => wd_di()->get( Tweak_Reminder::class )->status === $status_active,
454 'wp_version' => $wp_version,
455 'php_version' => PHP_VERSION,
456 ),
457 'malware_scan' => array(
458 'count' => $scan_total_issues,
459 'notification' => wd_di()->get( Malware_Notification::class )->status === $status_active,
460 ),
461 'firewall' => array(
462 'last_lockout' => Lockout_Log::get_last_lockout_date( true ),
463 '24_hours' => array(
464 'login_lockout' => Lockout_Log::count(
465 strtotime( '-24 hours' ),
466 time(),
467 array( Lockout_Log::AUTH_LOCK )
468 ),
469 '404_lockout' => Lockout_Log::count(
470 strtotime( '-24 hours' ),
471 time(),
472 array( Lockout_Log::LOCKOUT_404 )
473 ),
474 'user_agent_lockout' => Lockout_Log::count(
475 strtotime( '-24 hours' ),
476 time(),
477 array( Lockout_Log::LOCKOUT_UA )
478 ),
479 ),
480 '7_days' => array(
481 'login_lockout' => Lockout_Log::count_login_lockout_last_7_days(),
482 '404_lockout' => Lockout_Log::count_404_lockout_last_7_days(),
483 'user_agent_lockout' => Lockout_Log::count_ua_lockout_last_7_days(),
484 ),
485 '30_days' => array(
486 'login_lockout' => Lockout_Log::count(
487 strtotime( '-30 days' ),
488 time(),
489 array( Lockout_Log::AUTH_LOCK )
490 ),
491 '404_lockout' => Lockout_Log::count(
492 strtotime( '-30 days' ),
493 time(),
494 array( Lockout_Log::LOCKOUT_404 )
495 ),
496 'user_agent_lockout' => Lockout_Log::count(
497 strtotime( '-30 days' ),
498 time(),
499 array( Lockout_Log::LOCKOUT_UA )
500 ),
501 ),
502 'notification_status' => array(
503 'login_lockout' => $login_lockout,
504 '404_lockout' => $nf_lockout,
505 'ua_lockout' => $ua_lockout,
506 ),
507 'login_lockout_enabled' => wd_di()->get( Login_Lockout::class )->enabled,
508 'lockout_404_enabled' => wd_di()->get( Notfound_Lockout::class )->enabled,
509 'user_agent_lockout_enabled' => wd_di()->get( User_Agent_Lockout::class )->enabled,
510 'global_ip_list_enabled' => wd_di()->get( Global_Ip_Lockout::class )->enabled,
511 'antibot_enabled' => $antibot_service->frontend_is_enabled(),
512 'antibot_mode' => $antibot_service->frontend_mode(),
513 ),
514 'audit' => array(
515 'last_event' => $audit['lastEvent'],
516 '24_hours' => $audit['dayCount'],
517 '7_days' => $audit['weekCount'],
518 '30_days' => $audit['monthCount'],
519 'enabled' => $audit_log->model->is_active(),
520 ),
521 'advanced_tools' => array(
522 'security_headers' => array(
523 'sh_xframe' => $model_sec_headers->sh_xframe,
524 'sh_xss_protection' => $model_sec_headers->sh_xss_protection,
525 'sh_content_type_options' => $model_sec_headers->sh_content_type_options,
526 'sh_strict_transport' => $model_sec_headers->sh_strict_transport,
527 'sh_referrer_policy' => $model_sec_headers->sh_referrer_policy,
528 'sh_feature_policy' => $model_sec_headers->sh_feature_policy,
529 ),
530 'mask_login' => wd_di()->get( \WP_Defender\Model\Setting\Mask_Login::class )->is_active(),
531 'google_recaptcha' => array(
532 'status' => wd_di()->get( \WP_Defender\Model\Setting\Recaptcha::class )->is_active(),
533 ),
534 'password_protection' => array(
535 'status' => wd_di()->get( \WP_Defender\Model\Setting\Password_Protection::class )->is_active(),
536 ),
537 ),
538 'two_fa' => array(
539 'status' => $two_fa->enabled,
540 'lost_phone' => $two_fa->lost_phone,
541 ),
542 'quarantined_files' => $quarantined_files,
543 );
544
545 wp_send_json_success(
546 array( 'stats' => $ret )
547 );
548 }
549
550 /**
551 * Synchronizes the data with the hub by making a POST request to the WPMUDEV API.
552 *
553 * @return void
554 */
555 public function hub_sync() {
556 $data = $this->build_stats_to_hub();
557 $this->make_wpmu_request(
558 WPMUDEV::API_HUB_SYNC,
559 $data,
560 array( 'method' => 'POST' )
561 );
562 }
563
564 /**
565 * Removes settings for all submodules.
566 */
567 public function remove_settings() {
568 }
569
570 /**
571 * Delete all the data & the cache.
572 */
573 public function remove_data() {
574 }
575
576 /**
577 * Placeholder for frontend data.
578 *
579 * @return void
580 */
581 public function data_frontend() {
582 }
583
584 /**
585 * Converts the current object state to an array.
586 *
587 * @return array The array representation of the object.
588 */
589 public function to_array(): array {
590 return array();
591 }
592
593 /**
594 * Placeholder for importing data.
595 *
596 * @param array $data Data to import.
597 *
598 * @return void
599 */
600 public function import_data( array $data ) {
601 }
602
603 /**
604 * Exports strings.
605 *
606 * @return array An array of strings.
607 */
608 public function export_strings(): array {
609 return array();
610 }
611
612 /**
613 * Display Onboard if the bool value 'true' and vice versa.
614 *
615 * @param bool $is_show Settings to display.
616 */
617 public function set_onboarding_status( $is_show ) {
618 $this->view_onboard = $is_show;
619 }
620
621 /**
622 * Retrieve the Onboard status.
623 *
624 * @return bool
625 */
626 public function get_onboarding_status(): bool {
627 return $this->view_onboard;
628 }
629
630 /**
631 * Activate/deactivate reCaptcha from HUB.
632 */
633 public function manage_recaptcha() {
634 $response = null;
635 if ( class_exists( \WP_Defender\Model\Setting\Recaptcha::class ) ) {
636 $settings = new \WP_Defender\Model\Setting\Recaptcha();
637 $response = array();
638 if ( true === $settings->enabled ) {
639 $settings->enabled = false;
640 $response['enabled'] = false;
641 } else {
642 $settings->enabled = true;
643 $response['enabled'] = true;
644 }
645 $settings->save();
646 // Track.
647 if ( $this->is_tracking_active() ) {
648 $this->track_feature_from_hub( ! $settings->enabled, 'Google reCAPTCHA' );
649 }
650 }
651 wp_send_json_success( $response );
652 }
653
654 /**
655 * Activate/deactivate 2FA from HUB.
656 *
657 * @param array $params Request parameters.
658 */
659 public function manage_2fa( array $params ) {
660 $response = null;
661 if ( class_exists( Two_Fa::class ) ) {
662 $settings = wd_di()->get( Two_Fa::class );
663 $response = array();
664 if ( true === $settings->enabled ) {
665 $settings->enabled = false;
666 $response['enabled'] = false;
667 } else {
668 $settings->enabled = true;
669 $response['enabled'] = true;
670 }
671 $settings->save();
672 // Track.
673 if ( $this->is_tracking_active() ) {
674 // Only deactivation from the Hub.
675 $this->track_feature_from_hub( false, 'Two-Factor Authentication' );
676 }
677 }
678
679 wp_send_json_success( $response );
680 }
681
682 /**
683 * Activate/deactivate Global IP list from HUB.
684 *
685 * @param object $params Request parameters.
686 *
687 * @return void
688 * @since 3.4.0
689 */
690 public function manage_global_ip_list( object $params ): void {
691 if ( ! isset( $params->enable ) ) {
692 wp_send_json_error(
693 array( 'message' => esc_html__( 'Missing parameter(s)', 'defender-security' ) )
694 );
695 }
696
697 $response = null;
698 if ( class_exists( Global_Ip_Lockout::class ) ) {
699 $settings = wd_di()->get( Global_Ip_Lockout::class );
700
701 $response = array();
702 if ( true === $params->enable ) {
703 $settings->enabled = true;
704 $response['enabled'] = true;
705 } else {
706 $settings->enabled = false;
707 $response['enabled'] = false;
708 }
709 $settings->save();
710 }
711 wp_send_json_success( $response );
712 }
713
714 /**
715 * Set Global IP list.
716 *
717 * @param object $params Request parameters.
718 *
719 * @return void
720 * @since 3.4.0
721 */
722 public function set_global_ips( object $params ): void {
723 $global_ip_component = wd_di()->get( Global_IP::class );
724 $result = $global_ip_component->set_global_ip_list( (array) $params );
725
726 if ( is_wp_error( $result ) ) {
727 wp_send_json_error(
728 array(
729 'message' => implode( ' ', $result->get_error_messages() ),
730 )
731 );
732 }
733
734 wp_send_json_success(
735 array( 'enabled' => $global_ip_component->is_global_ip_enabled() )
736 );
737 }
738
739 /**
740 * Get recent quarantined files.
741 */
742 public function get_quarantined_files(): void {
743 if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
744 $result = array(
745 'message' => defender_quarantine_pro_only(),
746 'success' => false,
747 );
748
749 wp_send_json_error( $result );
750 }
751
752 $quarantine_obj = wd_di()->get( Quarantine::class );
753
754 $quarantined_files = $quarantine_obj->hub_list();
755
756 wp_send_json_success(
757 array( 'quarantined_files' => $quarantined_files )
758 );
759 }
760
761 /**
762 * Restores a quarantined file based on the provided parameters.
763 *
764 * @param object $params The parameters for restoring the quarantined file.
765 * Requires the 'id' property to be set.
766 *
767 * @return void
768 */
769 public function restore_quarantined_file( object $params ): void {
770 if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
771 $result = array(
772 'message' => defender_quarantine_pro_only(),
773 'success' => false,
774 );
775
776 wp_send_json_error( $result );
777 }
778
779 if ( isset( $params->id ) ) {
780 $id = (int) $params->id;
781
782 $quarantine_obj = wd_di()->get( Quarantine::class );
783
784 $result = $quarantine_obj->restore_file( $id );
785
786 if ( isset( $result['success'] ) && false === $result['success'] ) {
787 wp_send_json_error( $result );
788 }
789
790 wp_send_json_success( $result );
791 }
792
793 wp_send_json_error(
794 array(
795 'message' => esc_html__( 'Missing parameter: id.', 'defender-security' ),
796 )
797 );
798 }
799
800 /**
801 * Handle plugin deactivation.
802 *
803 * @param string $plugin Path to the plugin file relative to the plugins directory.
804 *
805 * @return void
806 */
807 public function intercept_deactivate( $plugin ) {
808 if ( ! $this->is_tracking_active() ) {
809 return;
810 }
811
812 // Only if Defender.
813 if ( DEFENDER_PLUGIN_BASENAME !== $plugin ) {
814 return;
815 }
816
817 $action = defender_get_data_from_request( 'action', 'r' );
818 // Todo: this is a default value. Need to update it in the future.
819 $triggered_from = 'Unknown';
820 // Deactivated from WPMUDEV Dashboard.
821 if ( 'wdp-project-deactivate' === $action ) {
822 $triggered_from = 'Plugin deactivation - dashboard';
823 } elseif ( 'deactivate' === $action ) {
824 // Deactivated from WP plugins page.
825 $triggered_from = 'Plugin deactivation - wpadmin';
826 } elseif ( $this->is_hub_request() ) {
827 $triggered_from = 'Plugin deactivation - hub';
828 }
829
830 // Send plugin deactivation event.
831 $this->track_opt_toggle( false, $triggered_from );
832 }
833
834 /**
835 * Enable/Disable Antibot Functionality. Only for third party site.
836 *
837 * @param object $params Request parameters.
838 *
839 * @return void
840 * @since 4.11.0
841 */
842 public function set_antibot_status( object $params ): void {
843 if ( ! isset( $params->enable ) && ! isset( $params->mode ) ) {
844 wp_send_json_error(
845 array( 'message' => esc_html__( 'Missing parameter(s)', 'defender-security' ) )
846 );
847 }
848
849 if ( ! class_exists( Antibot_Global_Firewall_Setting::class ) ) {
850 wp_send_json_error(
851 array( 'message' => esc_html__( 'Missing class', 'defender-security' ) )
852 );
853 }
854
855 $is_updated = false;
856 $antibot_settings = wd_di()->get( Antibot_Global_Firewall_Setting::class );
857
858 if ( isset( $params->mode ) ) {
859 if ( ! in_array( $params->mode, Antibot_Global_Firewall_Setting::get_valid_modes(), true ) ) {
860 wp_send_json_error(
861 array( 'message' => esc_html__( 'Invalid mode', 'defender-security' ) )
862 );
863 }
864
865 $old_mode = $antibot_settings->mode;
866 $new_mode = $params->mode;
867 if ( $old_mode !== $new_mode ) {
868 $is_updated = true;
869 $antibot_settings->mode = $new_mode;
870 }
871 }
872
873 if ( isset( $params->enable ) ) {
874 $old_enabled = $antibot_settings->enabled;
875 $new_enabled = (bool) $params->enable;
876 if ( $old_enabled !== $new_enabled ) {
877 $is_updated = true;
878 $antibot_settings->enabled = $new_enabled;
879
880 // Track.
881 if ( $this->is_tracking_active() ) {
882 wd_di()->get( \WP_Defender\Helper\Analytics\Antibot::class )
883 ->track_antibot( $old_enabled, 'Hub' );
884 }
885 }
886 }
887
888 if ( $is_updated ) {
889 $antibot_settings->save();
890
891 /**
892 * Download and store the blocklist.
893 *
894 * @var Antibot_Global_Firewall $antibot_service
895 */
896 $antibot_service = wd_di()->get( Antibot_Global_Firewall::class );
897 if ( 'plugin' === $antibot_service->get_managed_by() && $antibot_service->is_enabled() ) {
898 $antibot_service->download_and_store_blocklist();
899 }
900 }
901
902 wp_send_json_success(
903 array(
904 'enabled' => $antibot_settings->enabled,
905 'mode' => $antibot_settings->mode,
906 )
907 );
908 }
909 }
910