PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / trunk
Defender Security – Malware Scanner, Login Security & Firewall vtrunk
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 3.1.1 All 140 releases
defender-security / src / controller / class-hub.php

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

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