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/controller/class-hub.php +102 -170 5.6.0 → 6.3.0 View file →
@@ -11,9 +11,8 @@
11 11 use WP_Defender\Traits\IO;
12 12 use WP_Defender\Traits\Formats;
13 13 use WP_Defender\Behavior\WPMUDEV;
14 14 use WP_Defender\Model\Lockout_Log;
15 -use WP_Defender\Component\Quarantine;
16 15 use WP_Defender\Model\Setting\Two_Fa;
17 16 use WP_Defender\Component\IP\Antibot_Global_Firewall;
18 17 use WP_Defender\Component\IP\Global_IP;
19 18 use WP_Defender\Component\Backup_Settings;
@@ -25,8 +24,9 @@
25 24 use WP_Defender\Component\Config\Config_Adapter;
26 25 use WP_Defender\Model\Setting\User_Agent_Lockout;
27 26 use WP_Defender\Model\Notification\Malware_Report;
28 27 use WP_Defender\Model\Notification\Tweak_Reminder;
28 +use WP_Defender\Component\Scan as Scan_Component;
29 29 use WP_Defender\Component\Config\Config_Hub_Helper;
30 30 use WP_Defender\Model\Notification\Firewall_Report;
31 31 use WP_Defender\Model\Notification\Malware_Notification;
32 32 use WP_Defender\Model\Notification\Firewall_Notification;
@@ -42,20 +42,13 @@
42 42 use IO;
43 43 use Formats;
44 44
45 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 46 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
54 47 */
55 48 public function __construct() {
56 49 $this->attach_behavior( WPMUDEV::class, WPMUDEV::class );
57 - add_action( 'wdp_register_hub_action', array( $this, 'add_hub_endpoint' ) );
50 + add_filter( 'wdp_register_hub_action', array( $this, 'add_hub_endpoint' ) );
58 51 add_action( 'defender_hub_sync', array( $this, 'hub_sync' ) );
59 52 }
60 53
61 54 /**
@@ -65,11 +58,12 @@
65 58 *
66 59 * @return array The updated actions array with hub endpoints added.
67 60 */
68 61 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' );
62 + $actions['defender_new_scan'] = array( $this, 'new_scan' );
63 + $actions['defender_get_quarantined_files'] = array( $this, 'get_quarantined_files' );
64 + $actions['defender_restore_quarantined_file'] = array( $this, 'restore_quarantined_file' );
65 +
72 66 $actions['defender_manage_lockout'] = array( $this, 'manage_lockout' );
73 67 $actions['defender_whitelist_ip'] = array( $this, 'whitelist_ip' );
74 68 $actions['defender_blacklist_ip'] = array( $this, 'blacklist_ip' );
75 69 $actions['defender_get_scan_progress'] = array( $this, 'get_scan_progress' );
@@ -85,11 +79,8 @@
85 79 $actions['defender_get_stats'] = array( $this, 'get_stats' );
86 80 // Version#2.
87 81 $actions['defender_get_stats_v2'] = array( $this, 'defender_get_stats_v2' );
88 82
89 - $actions['defender_get_quarantined_files'] = array( $this, 'get_quarantined_files' );
90 - $actions['defender_restore_quarantined_file'] = array( $this, 'restore_quarantined_file' );
91 -
92 83 return $actions;
93 84 }
94 85
95 86 /**
@@ -95,8 +86,17 @@
95 86 /**
96 87 * Create new scan, triggered from HUB.
97 88 */
98 89 public function new_scan() {
90 + $scan_component = wd_di()->get( Scan_Component::class );
91 + if ( ! $scan_component->is_any_scan_type_active() ) {
92 + wp_send_json_error(
93 + array(
94 + 'message' => Scan_Component::get_emergency_scan_stop_text(),
95 + )
96 + );
97 + }
98 +
99 99 $scan = \WP_Defender\Model\Scan::create();
100 100 if ( is_wp_error( $scan ) ) {
101 101 wp_send_json_error(
102 102 array(
@@ -103,38 +103,11 @@
103 103 'message' => $scan->get_error_message(),
104 104 )
105 105 );
106 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 107
111 - wp_send_json_success();
112 - }
108 + wd_di()->get( Scan::class )->run_scan_mechanisms_from( 'hub' );
113 109
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 110 wp_send_json_success();
138 111 }
139 112
140 113 /**
@@ -153,32 +126,66 @@
153 126 $this->track_feature( $event, $data );
154 127 }
155 128
156 129 /**
157 - * Manage the audit log settings by toggling the enabled status of the Audit Logging feature.
130 + * Get recent quarantined files.
131 + */
132 + public function get_quarantined_files(): void {
133 + if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
134 + $result = array(
135 + 'message' => defender_quarantine_pro_only(),
136 + 'success' => false,
137 + );
138 +
139 + wp_send_json_error( $result );
140 + }
141 +
142 + $quarantine_obj = wd_di()->get( \WP_Defender\Component\Quarantine::class );
143 +
144 + $quarantined_files = $quarantine_obj->hub_list();
145 +
146 + wp_send_json_success(
147 + array( 'quarantined_files' => $quarantined_files )
148 + );
149 + }
150 +
151 + /**
152 + * Restores a quarantined file based on the provided parameters.
158 153 *
154 + * @param object $params The parameters for restoring the quarantined file.
155 + * Requires the 'id' property to be set.
156 + *
159 157 * @return void
160 158 */
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;
159 + public function restore_quarantined_file( object $params ): void {
160 + if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
161 + $result = array(
162 + 'message' => defender_quarantine_pro_only(),
163 + 'success' => false,
164 + );
165 +
166 + wp_send_json_error( $result );
167 + }
168 +
169 + if ( isset( $params->id ) ) {
170 + $id = (int) $params->id;
171 +
172 + $quarantine_obj = wd_di()->get( \WP_Defender\Component\Quarantine::class );
173 +
174 + $result = $quarantine_obj->restore_file( $id );
175 +
176 + if ( isset( $result['success'] ) && false === $result['success'] ) {
177 + wp_send_json_error( $result );
172 178 }
173 - $settings->save();
174 - // Track.
175 - if ( $this->is_tracking_active() ) {
176 - $this->track_feature_from_hub( ! $settings->enabled, 'Audit Logging' );
177 - }
179 +
180 + wp_send_json_success( $result );
178 181 }
179 182
180 - wp_send_json_success( $response );
183 + wp_send_json_error(
184 + array(
185 + 'message' => esc_html__( 'Missing parameter: id.', 'defender-security' ),
186 + )
187 + );
181 188 }
182 189
183 190 /**
184 191 * Manages the lockout feature based on the given parameters.
@@ -183,10 +190,9 @@
183 190 /**
184 191 * Manages the lockout feature based on the given parameters.
185 192 *
186 193 * @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'.
194 + * - type (string): The type of lockout to manage. Possible values: 'login', '404', 'ua-lockout'.
189 195 * @param string $action The action to perform on the lockout.
190 196 *
191 197 * @return void
192 198 */
@@ -341,9 +347,14 @@
341 347 * @param object object $params Request parameters.
342 348 */
343 349 public function import_settings( $params ) {
344 350 // Dirty but quick.
345 - if ( empty( $params->configs ) ) {
351 + if (
352 + ! isset( $params->configs )
353 + || ! ( is_array( $params->configs ) || is_object( $params->configs ) )
354 + || ( is_array( $params->configs ) && array() === $params->configs )
355 + || ( is_object( $params->configs ) && 0 === count( get_object_vars( $params->configs ) ) )
356 + ) {
346 357 wp_send_json_error(
347 358 array( 'message' => esc_html__( 'Invalid config', 'defender-security' ) )
348 359 );
349 360 }
@@ -348,9 +359,9 @@
348 359 );
349 360 }
350 361
351 362 $configs = json_decode( wp_json_encode( $params->configs ), true );
352 - if ( empty( $configs ) ) {
363 + if ( array() === $configs ) {
353 364 wp_send_json_error(
354 365 array( 'message' => esc_html__( 'Empty data', 'defender-security' ) )
355 366 );
356 367 }
@@ -360,9 +371,9 @@
360 371 foreach ( $configs as $module => $mdata ) {
361 372 foreach ( $mdata as $key => $value ) {
362 373 // Todo: update logic to import/export whitelisted/blocklisted countries via maxmind_license_key.
363 374 if ( in_array( $key, array( 'geoIP_db', 'geodb_path' ), true ) ) {
364 - if ( ! empty( $value ) ) {
375 + if ( is_string( $value ) && '' !== trim( $value ) ) {
365 376 // Download it.
366 377 $lockout_service->is_geodb_downloaded();
367 378 } else {
368 379 // Reset it.
@@ -376,9 +387,9 @@
376 387 $configs[ $module ] = $mdata;
377 388 }
378 389
379 390 // If it's old config structure then we upgrade configs to new format.
380 - if ( ! empty( $configs ) && ! $config_component->check_for_new_structure( $configs ) ) {
391 + if ( array() !== $configs && ! $config_component->check_for_new_structure( $configs ) ) {
381 392 $adapter = wd_di()->get( Config_Adapter::class );
382 393 $configs = $adapter->upgrade( $configs );
383 394 }
384 395 $restore_result = $config_component->restore_data( $configs, 'hub' );
@@ -431,12 +442,15 @@
431 442 $status_active = \WP_Defender\Model\Notification::STATUS_ACTIVE;
432 443 $model_sec_headers = wd_di()->get( \WP_Defender\Model\Setting\Security_Headers::class );
433 444 $scan_report = wd_di()->get( Malware_Report::class );
434 445 $two_fa = wd_di()->get( Two_Fa::class );
446 + if ( class_exists( 'WP_Defender\Component\Quarantine' ) ) {
447 + $quarantined_files = wd_di()->get( \WP_Defender\Component\Quarantine::class )->hub_list();
448 + } else {
449 + $quarantined_files = array();
450 + }
435 451
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 );
452 + $antibot_service = wd_di()->get( Antibot_Global_Firewall::class );
439 453
440 454 $ret = array(
441 455 'summary' => array(
442 456 'count' => $total,
@@ -442,11 +456,12 @@
442 456 'count' => $total,
443 457 'next_scan' => $scan_report->get_next_run_for_hub(),
444 458 ),
445 459 '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 ),
460 + 'malware_scan' => $scan_report->get_next_run_as_string( true ),
461 + 'firewall' => wd_di()->get( Firewall_Report::class )->get_next_run_as_string( true ),
462 + 'audit_logging' => wd_di()->get( Audit_Report::class )->get_next_run_as_string( true ),
463 + 'tweak_reminder' => wd_di()->get( Tweak_Reminder::class )->get_next_run_as_string( true ),
449 464 ),
450 465 'security_tweaks' => array(
451 466 'issues' => $tweak_arr['count_issues'],
452 467 'fixed' => $tweak_arr['count_fixed'],
@@ -468,15 +483,11 @@
468 483 ),
469 484 '404_lockout' => Lockout_Log::count(
470 485 strtotime( '-24 hours' ),
471 486 time(),
472 - array( Lockout_Log::LOCKOUT_404 )
487 + Lockout_Log::get_404_lockout_types()
473 488 ),
474 - 'user_agent_lockout' => Lockout_Log::count(
475 - strtotime( '-24 hours' ),
476 - time(),
477 - array( Lockout_Log::LOCKOUT_UA )
478 - ),
489 + 'user_agent_lockout' => Lockout_Log::count_ua_lockouts_in_24_hours(),
479 490 ),
480 491 '7_days' => array(
481 492 'login_lockout' => Lockout_Log::count_login_lockout_last_7_days(),
482 493 '404_lockout' => Lockout_Log::count_404_lockout_last_7_days(),
@@ -495,9 +506,9 @@
495 506 ),
496 507 'user_agent_lockout' => Lockout_Log::count(
497 508 strtotime( '-30 days' ),
498 509 time(),
499 - array( Lockout_Log::LOCKOUT_UA )
510 + Lockout_Log::get_ua_lockout_types()
500 511 ),
501 512 ),
502 513 'notification_status' => array(
503 514 'login_lockout' => $login_lockout,
@@ -511,12 +522,12 @@
511 522 'antibot_enabled' => $antibot_service->frontend_is_enabled(),
512 523 'antibot_mode' => $antibot_service->frontend_mode(),
513 524 ),
514 525 'audit' => array(
515 - 'last_event' => $audit['lastEvent'],
516 - '24_hours' => $audit['dayCount'],
517 - '7_days' => $audit['weekCount'],
518 - '30_days' => $audit['monthCount'],
526 + 'last_event' => $audit['lastEvent'] ?? 'n/a',
527 + '24_hours' => $audit['dayCount'] ?? 0,
528 + '7_days' => $audit['weekCount'] ?? 0,
529 + '30_days' => $audit['monthCount'] ?? 0,
519 530 'enabled' => $audit_log->model->is_active(),
520 531 ),
521 532 'advanced_tools' => array(
522 533 'security_headers' => array(
@@ -527,10 +538,11 @@
527 538 'sh_referrer_policy' => $model_sec_headers->sh_referrer_policy,
528 539 'sh_feature_policy' => $model_sec_headers->sh_feature_policy,
529 540 ),
530 541 'mask_login' => wd_di()->get( \WP_Defender\Model\Setting\Mask_Login::class )->is_active(),
542 + // We'll change 'google_recaptcha'-key to 'captcha' in the future.
531 543 'google_recaptcha' => array(
532 - 'status' => wd_di()->get( \WP_Defender\Model\Setting\Recaptcha::class )->is_active(),
544 + 'status' => wd_di()->get( \WP_Defender\Model\Setting\Captcha::class )->is_active(),
533 545 ),
534 546 'password_protection' => array(
535 547 'status' => wd_di()->get( \WP_Defender\Model\Setting\Password_Protection::class )->is_active(),
536 548 ),
@@ -575,11 +587,12 @@
575 587
576 588 /**
577 589 * Placeholder for frontend data.
578 590 *
579 - * @return void
591 + * @return array
580 592 */
581 593 public function data_frontend() {
594 + return array();
582 595 }
583 596
584 597 /**
585 598 * Converts the current object state to an array.
@@ -593,10 +606,8 @@
593 606 /**
594 607 * Placeholder for importing data.
595 608 *
596 609 * @param array $data Data to import.
597 - *
598 - * @return void
599 610 */
600 611 public function import_data( array $data ) {
601 612 }
602 613
@@ -609,32 +620,14 @@
609 620 return array();
610 621 }
611 622
612 623 /**
613 - * Display Onboard if the bool value 'true' and vice versa.
614 - *
615 - * @param bool $is_show Settings to display.
624 + * Activate/deactivate Captcha from HUB.
616 625 */
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 626 public function manage_recaptcha() {
634 627 $response = null;
635 - if ( class_exists( \WP_Defender\Model\Setting\Recaptcha::class ) ) {
636 - $settings = new \WP_Defender\Model\Setting\Recaptcha();
628 + if ( class_exists( \WP_Defender\Model\Setting\Captcha::class ) ) {
629 + $settings = new \WP_Defender\Model\Setting\Captcha();
637 630 $response = array();
638 631 if ( true === $settings->enabled ) {
639 632 $settings->enabled = false;
640 633 $response['enabled'] = false;
@@ -732,69 +725,8 @@
732 725 }
733 726
734 727 wp_send_json_success(
735 728 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 729 );
798 730 }
799 731
800 732 /**