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

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

911 lines 26.6 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 ( User_Agent_Lockout::get_module_slug() === $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 // We'll change 'google_recaptcha'-key to 'captcha' in the future.
532 'google_recaptcha' => array(
533 'status' => wd_di()->get( \WP_Defender\Model\Setting\Captcha::class )->is_active(),
534 ),
535 'password_protection' => array(
536 'status' => wd_di()->get( \WP_Defender\Model\Setting\Password_Protection::class )->is_active(),
537 ),
538 ),
539 'two_fa' => array(
540 'status' => $two_fa->enabled,
541 'lost_phone' => $two_fa->lost_phone,
542 ),
543 'quarantined_files' => $quarantined_files,
544 );
545
546 wp_send_json_success(
547 array( 'stats' => $ret )
548 );
549 }
550
551 /**
552 * Synchronizes the data with the hub by making a POST request to the WPMUDEV API.
553 *
554 * @return void
555 */
556 public function hub_sync() {
557 $data = $this->build_stats_to_hub();
558 $this->make_wpmu_request(
559 WPMUDEV::API_HUB_SYNC,
560 $data,
561 array( 'method' => 'POST' )
562 );
563 }
564
565 /**
566 * Removes settings for all submodules.
567 */
568 public function remove_settings() {
569 }
570
571 /**
572 * Delete all the data & the cache.
573 */
574 public function remove_data() {
575 }
576
577 /**
578 * Placeholder for frontend data.
579 *
580 * @return void
581 */
582 public function data_frontend() {
583 }
584
585 /**
586 * Converts the current object state to an array.
587 *
588 * @return array The array representation of the object.
589 */
590 public function to_array(): array {
591 return array();
592 }
593
594 /**
595 * Placeholder for importing data.
596 *
597 * @param array $data Data to import.
598 *
599 * @return void
600 */
601 public function import_data( array $data ) {
602 }
603
604 /**
605 * Exports strings.
606 *
607 * @return array An array of strings.
608 */
609 public function export_strings(): array {
610 return array();
611 }
612
613 /**
614 * Display Onboard if the bool value 'true' and vice versa.
615 *
616 * @param bool $is_show Settings to display.
617 */
618 public function set_onboarding_status( $is_show ) {
619 $this->view_onboard = $is_show;
620 }
621
622 /**
623 * Retrieve the Onboard status.
624 *
625 * @return bool
626 */
627 public function get_onboarding_status(): bool {
628 return $this->view_onboard;
629 }
630
631 /**
632 * Activate/deactivate Captcha from HUB.
633 */
634 public function manage_recaptcha() {
635 $response = null;
636 if ( class_exists( \WP_Defender\Model\Setting\Captcha::class ) ) {
637 $settings = new \WP_Defender\Model\Setting\Captcha();
638 $response = array();
639 if ( true === $settings->enabled ) {
640 $settings->enabled = false;
641 $response['enabled'] = false;
642 } else {
643 $settings->enabled = true;
644 $response['enabled'] = true;
645 }
646 $settings->save();
647 // Track.
648 if ( $this->is_tracking_active() ) {
649 $this->track_feature_from_hub( ! $settings->enabled, 'Google reCAPTCHA' );
650 }
651 }
652 wp_send_json_success( $response );
653 }
654
655 /**
656 * Activate/deactivate 2FA from HUB.
657 *
658 * @param array $params Request parameters.
659 */
660 public function manage_2fa( array $params ) {
661 $response = null;
662 if ( class_exists( Two_Fa::class ) ) {
663 $settings = wd_di()->get( Two_Fa::class );
664 $response = array();
665 if ( true === $settings->enabled ) {
666 $settings->enabled = false;
667 $response['enabled'] = false;
668 } else {
669 $settings->enabled = true;
670 $response['enabled'] = true;
671 }
672 $settings->save();
673 // Track.
674 if ( $this->is_tracking_active() ) {
675 // Only deactivation from the Hub.
676 $this->track_feature_from_hub( false, 'Two-Factor Authentication' );
677 }
678 }
679
680 wp_send_json_success( $response );
681 }
682
683 /**
684 * Activate/deactivate Global IP list from HUB.
685 *
686 * @param object $params Request parameters.
687 *
688 * @return void
689 * @since 3.4.0
690 */
691 public function manage_global_ip_list( object $params ): void {
692 if ( ! isset( $params->enable ) ) {
693 wp_send_json_error(
694 array( 'message' => esc_html__( 'Missing parameter(s)', 'defender-security' ) )
695 );
696 }
697
698 $response = null;
699 if ( class_exists( Global_Ip_Lockout::class ) ) {
700 $settings = wd_di()->get( Global_Ip_Lockout::class );
701
702 $response = array();
703 if ( true === $params->enable ) {
704 $settings->enabled = true;
705 $response['enabled'] = true;
706 } else {
707 $settings->enabled = false;
708 $response['enabled'] = false;
709 }
710 $settings->save();
711 }
712 wp_send_json_success( $response );
713 }
714
715 /**
716 * Set Global IP list.
717 *
718 * @param object $params Request parameters.
719 *
720 * @return void
721 * @since 3.4.0
722 */
723 public function set_global_ips( object $params ): void {
724 $global_ip_component = wd_di()->get( Global_IP::class );
725 $result = $global_ip_component->set_global_ip_list( (array) $params );
726
727 if ( is_wp_error( $result ) ) {
728 wp_send_json_error(
729 array(
730 'message' => implode( ' ', $result->get_error_messages() ),
731 )
732 );
733 }
734
735 wp_send_json_success(
736 array( 'enabled' => $global_ip_component->is_global_ip_enabled() )
737 );
738 }
739
740 /**
741 * Get recent quarantined files.
742 */
743 public function get_quarantined_files(): void {
744 if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
745 $result = array(
746 'message' => defender_quarantine_pro_only(),
747 'success' => false,
748 );
749
750 wp_send_json_error( $result );
751 }
752
753 $quarantine_obj = wd_di()->get( Quarantine::class );
754
755 $quarantined_files = $quarantine_obj->hub_list();
756
757 wp_send_json_success(
758 array( 'quarantined_files' => $quarantined_files )
759 );
760 }
761
762 /**
763 * Restores a quarantined file based on the provided parameters.
764 *
765 * @param object $params The parameters for restoring the quarantined file.
766 * Requires the 'id' property to be set.
767 *
768 * @return void
769 */
770 public function restore_quarantined_file( object $params ): void {
771 if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
772 $result = array(
773 'message' => defender_quarantine_pro_only(),
774 'success' => false,
775 );
776
777 wp_send_json_error( $result );
778 }
779
780 if ( isset( $params->id ) ) {
781 $id = (int) $params->id;
782
783 $quarantine_obj = wd_di()->get( Quarantine::class );
784
785 $result = $quarantine_obj->restore_file( $id );
786
787 if ( isset( $result['success'] ) && false === $result['success'] ) {
788 wp_send_json_error( $result );
789 }
790
791 wp_send_json_success( $result );
792 }
793
794 wp_send_json_error(
795 array(
796 'message' => esc_html__( 'Missing parameter: id.', 'defender-security' ),
797 )
798 );
799 }
800
801 /**
802 * Handle plugin deactivation.
803 *
804 * @param string $plugin Path to the plugin file relative to the plugins directory.
805 *
806 * @return void
807 */
808 public function intercept_deactivate( $plugin ) {
809 if ( ! $this->is_tracking_active() ) {
810 return;
811 }
812
813 // Only if Defender.
814 if ( DEFENDER_PLUGIN_BASENAME !== $plugin ) {
815 return;
816 }
817
818 $action = defender_get_data_from_request( 'action', 'r' );
819 // Todo: this is a default value. Need to update it in the future.
820 $triggered_from = 'Unknown';
821 // Deactivated from WPMUDEV Dashboard.
822 if ( 'wdp-project-deactivate' === $action ) {
823 $triggered_from = 'Plugin deactivation - dashboard';
824 } elseif ( 'deactivate' === $action ) {
825 // Deactivated from WP plugins page.
826 $triggered_from = 'Plugin deactivation - wpadmin';
827 } elseif ( $this->is_hub_request() ) {
828 $triggered_from = 'Plugin deactivation - hub';
829 }
830
831 // Send plugin deactivation event.
832 $this->track_opt_toggle( false, $triggered_from );
833 }
834
835 /**
836 * Enable/Disable Antibot Functionality. Only for third party site.
837 *
838 * @param object $params Request parameters.
839 *
840 * @return void
841 * @since 4.11.0
842 */
843 public function set_antibot_status( object $params ): void {
844 if ( ! isset( $params->enable ) && ! isset( $params->mode ) ) {
845 wp_send_json_error(
846 array( 'message' => esc_html__( 'Missing parameter(s)', 'defender-security' ) )
847 );
848 }
849
850 if ( ! class_exists( Antibot_Global_Firewall_Setting::class ) ) {
851 wp_send_json_error(
852 array( 'message' => esc_html__( 'Missing class', 'defender-security' ) )
853 );
854 }
855
856 $is_updated = false;
857 $antibot_settings = wd_di()->get( Antibot_Global_Firewall_Setting::class );
858
859 if ( isset( $params->mode ) ) {
860 if ( ! in_array( $params->mode, Antibot_Global_Firewall_Setting::get_valid_modes(), true ) ) {
861 wp_send_json_error(
862 array( 'message' => esc_html__( 'Invalid mode', 'defender-security' ) )
863 );
864 }
865
866 $old_mode = $antibot_settings->mode;
867 $new_mode = $params->mode;
868 if ( $old_mode !== $new_mode ) {
869 $is_updated = true;
870 $antibot_settings->mode = $new_mode;
871 }
872 }
873
874 if ( isset( $params->enable ) ) {
875 $old_enabled = $antibot_settings->enabled;
876 $new_enabled = (bool) $params->enable;
877 if ( $old_enabled !== $new_enabled ) {
878 $is_updated = true;
879 $antibot_settings->enabled = $new_enabled;
880
881 // Track.
882 if ( $this->is_tracking_active() ) {
883 wd_di()->get( \WP_Defender\Helper\Analytics\Antibot::class )
884 ->track_antibot( $old_enabled, 'Hub' );
885 }
886 }
887 }
888
889 if ( $is_updated ) {
890 $antibot_settings->save();
891
892 /**
893 * Download and store the blocklist.
894 *
895 * @var Antibot_Global_Firewall $antibot_service
896 */
897 $antibot_service = wd_di()->get( Antibot_Global_Firewall::class );
898 if ( 'plugin' === $antibot_service->get_managed_by() && $antibot_service->is_enabled() ) {
899 $antibot_service->download_and_store_blocklist();
900 }
901 }
902
903 wp_send_json_success(
904 array(
905 'enabled' => $antibot_settings->enabled,
906 'mode' => $antibot_settings->mode,
907 )
908 );
909 }
910 }
911