PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.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 / bootstrap.php

bootstrap.php in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at src/bootstrap.php

517 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WP_Defender;
4
5 use Calotes\DB\Mapper;
6 use Calotes\Helper\Array_Cache;
7 use WP_Defender\Behavior\WPMUDEV;
8 use WP_Defender\Component\Cli;
9 use WP_Defender\Controller\Advanced_Tools;
10 use WP_Defender\Controller\Dashboard;
11 use WP_Defender\Controller\Audit_Logging;
12 use WP_Defender\Controller\Firewall;
13 use WP_Defender\Controller\HUB;
14 use WP_Defender\Controller\Mask_Login;
15 use WP_Defender\Controller\Notification;
16 use WP_Defender\Controller\Onboard;
17 use WP_Defender\Controller\Password_Protection;
18 use WP_Defender\Controller\Recaptcha;
19 use WP_Defender\Controller\Scan;
20 use WP_Defender\Controller\Security_Headers;
21 use WP_Defender\Controller\Security_Tweaks;
22 use WP_Defender\Controller\Two_Factor;
23 use WP_Defender\Controller\Main_Setting;
24 use WP_Defender\Controller\WAF;
25 use WP_Defender\Controller\Tutorial;
26 use WP_Defender\Controller\Blocklist_Monitor;
27 use WP_Defender\Controller\Password_Reset;
28 use WP_Defender\Controller\Webauthn;
29
30 /**
31 * Class Bootstrap
32 * @package WP_Defender
33 */
34 class Bootstrap {
35 /**
36 * Activation.
37 */
38 public function activation_hook() {
39 $this->create_database_tables();
40 $this->set_free_installation_timestamp();
41 $this->on_activation();
42 }
43
44 /**
45 * Deactivation.
46 */
47 public function deactivation_hook() {
48 wp_clear_scheduled_hook( 'firewall_clean_up_logs' );
49 wp_clear_scheduled_hook( 'audit_sync_events' );
50 wp_clear_scheduled_hook( 'audit_clean_up_logs' );
51 wp_clear_scheduled_hook( 'wdf_maybe_send_report' );
52 wp_clear_scheduled_hook( 'wp_defender_clear_logs' );
53 wp_clear_scheduled_hook( 'wpdef_sec_key_gen' );
54 wp_clear_scheduled_hook( 'wpdef_clear_scan_logs' );
55 wp_clear_scheduled_hook( 'wpdef_log_rotational_delete' );
56 wp_clear_scheduled_hook( 'wpdef_update_geoip' );
57
58 // Remove old legacy cron jobs if they exist.
59 wp_clear_scheduled_hook( 'lockoutReportCron' );
60 wp_clear_scheduled_hook( 'auditReportCron' );
61 wp_clear_scheduled_hook( 'cleanUpOldLog' );
62 wp_clear_scheduled_hook( 'scanReportCron' );
63 wp_clear_scheduled_hook( 'tweaksSendNotification' );
64 }
65
66 /**
67 * Creates Defender's tables.
68 * @since 2.7.1 No use dbDelta because PHP v8.1 triggers an error when calling query "DESCRIBE {$table};" if the table doesn't exist.
69 */
70 protected function create_database_tables() {
71 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
72
73 global $wpdb;
74
75 $charset_collate = $wpdb->get_charset_collate();
76 // Hide errors.
77 $wpdb->hide_errors();
78 // Email log table.
79 if ( ! $this->table_exists( 'defender_email_log' ) ) {
80 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_email_log (
81 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
82 `timestamp` int NOT NULL,
83 `source` varchar(255) NOT NULL,
84 `to` varchar(255) NOT NULL,
85 PRIMARY KEY (`id`),
86 KEY `source` (`source`)
87 ) $charset_collate;";
88 $wpdb->query( $sql );
89 }
90 // Audit log table. Though our data mainly store on API side, we will need a table for caching.
91 if ( ! $this->table_exists( 'defender_audit_log' ) ) {
92 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_audit_log (
93 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
94 `timestamp` int NOT NULL,
95 `event_type` varchar(255) NOT NULL,
96 `action_type` varchar(255) NOT NULL,
97 `site_url` varchar(255) NOT NULL,
98 `user_id` int NOT NULL,
99 `context` varchar(255) NOT NULL,
100 `ip` varchar(255) NOT NULL,
101 `msg` varchar(255) NOT NULL,
102 `blog_id` int NOT NULL,
103 `synced` int NOT NULL,
104 `ttl` int NOT NULL,
105 PRIMARY KEY (`id`),
106 KEY `event_type` (`event_type`),
107 KEY `action_type` (`action_type`),
108 KEY `user_id` (`user_id`),
109 KEY `context` (`context`),
110 KEY `ip` (`ip`)
111 ) $charset_collate;";
112 $wpdb->query( $sql );
113 }
114 // Scan item table.
115 if ( ! $this->table_exists( 'defender_scan_item' ) ) {
116 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_scan_item (
117 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
118 `parent_id` int NOT NULL,
119 `type` varchar(255) NOT NULL,
120 `status` varchar(255) NOT NULL,
121 `raw_data` text NOT NULL,
122 PRIMARY KEY (`id`),
123 KEY `type` (`type`),
124 KEY `status` (`status`)
125 ) $charset_collate;";
126 $wpdb->query( $sql );
127 }
128 // Scan table.
129 if ( ! $this->table_exists( 'defender_scan' ) ) {
130 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_scan (
131 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
132 `percent` float NOT NULL,
133 `total_tasks` tinyint(4) NOT NULL,
134 `task_checkpoint` varchar(255) NOT NULL,
135 `status` varchar(255) NOT NULL,
136 `date_start` datetime NOT NULL,
137 `date_end` datetime NOT NULL,
138 `is_automation` bool NOT NULL,
139 PRIMARY KEY (`id`)
140 ) $charset_collate;";
141 $wpdb->query( $sql );
142 }
143 // Lockout log table.
144 if ( ! $this->table_exists( 'defender_lockout_log' ) ) {
145 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_lockout_log (
146 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
147 `log` text,
148 `ip` varchar(255) DEFAULT NULL,
149 `date` int(11) DEFAULT NULL,
150 `type` varchar(16) DEFAULT NULL,
151 `user_agent` varchar(255) DEFAULT NULL,
152 `blog_id` int(11) DEFAULT NULL,
153 `tried` varchar(255),
154 `country_iso_code` char(2) DEFAULT NULL,
155 PRIMARY KEY (`id`),
156 KEY `ip` (`ip`),
157 KEY `type` (`type`),
158 KEY `tried` (`tried`),
159 KEY `country_iso_code` (`country_iso_code`)
160 ) $charset_collate;";
161 $wpdb->query( $sql );
162 }
163 // Lockout table.
164 if ( ! $this->table_exists( 'defender_lockout' ) ) {
165 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->base_prefix}defender_lockout (
166 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
167 `ip` varchar(255) DEFAULT NULL,
168 `status` varchar(16) DEFAULT NULL,
169 `lockout_message` text,
170 `release_time` int(11) DEFAULT NULL,
171 `lock_time` int(11) DEFAULT NULL,
172 `lock_time_404` int(11) DEFAULT NULL,
173 `attempt` int(11) DEFAULT NULL,
174 `attempt_404` int(11) DEFAULT NULL,
175 `meta` text,
176 PRIMARY KEY (`id`),
177 KEY `ip` (`ip`),
178 KEY `status` (`status`),
179 KEY `attempt` (`attempt`),
180 KEY `attempt_404` (`attempt_404`)
181 ) $charset_collate;";
182 $wpdb->query( $sql );
183 }
184 }
185
186 /**
187 * Add option with plugin install date.
188 *
189 * @since 2.4
190 */
191 protected function set_free_installation_timestamp() {
192 // It's for both cases because don’t have a Pro checking during plugin activation.
193 if ( empty( get_site_option( 'defender_free_install_date' ) ) ) {
194 update_site_option( 'defender_free_install_date', time() );
195 }
196 }
197
198 /**
199 * Load all modules.
200 */
201 public function init_modules() {
202 // Init main ORM.
203 Array_Cache::set( 'orm', new Mapper() );
204 /**
205 * Display Onboarding if:
206 * it's a fresh install and there were no requests from the Hub before,
207 * after Reset Settings.
208 */
209 $hub_class = wd_di()->get( HUB::class );
210 $hub_class->set_onboarding_status( $this->maybe_show_onboarding() );
211 $hub_class->listen_to_requests();
212 if ( $hub_class->get_onboarding_status() && 'cli' !== php_sapi_name() ) {
213 // If it's cli we should start this normally.
214 Array_Cache::set( 'onboard', wd_di()->get( Onboard::class ) );
215 } else {
216 // Initialize the main controllers of every module.
217 wd_di()->get( Dashboard::class );
218 }
219 wd_di()->get( Security_Tweaks::class );
220 wd_di()->get( Scan::class );
221 wd_di()->get( Audit_Logging::class );
222 wd_di()->get( Firewall::class );
223 wd_di()->get( WAF::class );
224 wd_di()->get( Two_Factor::class );
225 wd_di()->get( Advanced_Tools::class );
226 wd_di()->get( Mask_Login::class );
227 wd_di()->get( Security_Headers::class );
228 wd_di()->get( Recaptcha::class );
229 wd_di()->get( Notification::class );
230 wd_di()->get( Main_Setting::class );
231 wd_di()->get( Tutorial::class );
232 wd_di()->get( Blocklist_Monitor::class );
233 wd_di()->get( Password_Protection::class );
234 wd_di()->get( Password_Reset::class );
235 wd_di()->get( Webauthn::class );
236 $this->init_free_dashboard();
237 }
238
239 /**
240 * @return bool
241 */
242 private function maybe_show_onboarding() {
243 // First we need to check if the site is newly create.
244 global $wpdb;
245 if ( ! is_multisite() ) {
246 $res = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'wp_defender_shown_activator'" );
247 } else {
248 $sql = $wpdb->prepare(
249 "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = 'wp_defender_shown_activator' AND site_id = %d",
250 get_current_network_id()
251 );
252 $res = $wpdb->get_var( $sql );
253 }
254 // Get '1' for direct SQL request if Onboarding was already.
255 if ( empty( $res ) ) {
256 return true;
257 }
258
259 return false;
260 }
261
262 public function init_free_dashboard() {
263 require_once defender_path( 'extra/free-dashboard/module.php' );
264
265 add_filter( 'wdev-email-message-' . DEFENDER_PLUGIN_BASENAME, array( &$this, 'defender_ads_message' ) );
266
267 $screen_prefix = 'defender';
268 $screen_suffix = is_multisite() ? '-network' : '';
269
270 $free_install_date = get_site_option( 'defender_free_install_date', false );
271
272 do_action(
273 'wpmudev_register_notices',
274 'defender',
275 array(
276 'basename' => DEFENDER_PLUGIN_BASENAME,
277 'title' => 'Defender',
278 'wp_slug' => 'defender-security',
279 'cta_email' => __( 'Get Secure!', 'wpdef' ),
280 'mc_list_id' => '0cecf2890e',
281 'installed_on' => $free_install_date ? $free_install_date : time(),
282 'screens' => array(
283 'toplevel_page_wp-defender' . $screen_suffix,
284 $screen_prefix . '_page_wdf-hardener' . $screen_suffix,
285 $screen_prefix . '_page_wdf-scan' . $screen_suffix,
286 $screen_prefix . '_page_wdf-logging' . $screen_suffix,
287 $screen_prefix . '_page_wdf-ip-lockout' . $screen_suffix,
288 $screen_prefix . '_page_wdf-waf' . $screen_suffix,
289 $screen_prefix . '_page_wdf-2fa' . $screen_suffix,
290 $screen_prefix . '_page_wdf-advanced-tools' . $screen_suffix,
291 $screen_prefix . '_page_wdf-notification' . $screen_suffix,
292 $screen_prefix . '_page_wdf-setting' . $screen_suffix,
293 $screen_prefix . '_page_wdf-tutorial' . $screen_suffix,
294 ),
295 )
296 );
297 }
298
299 /**
300 * @param $message
301 *
302 * @return string|void
303 */
304 public function defender_ads_message( $message ) {
305 return __( "You're awesome for installing Defender! Are you interested in how to make the most of this plugin? We've collected all the best security resources we know in a single email - just for users of Defender!", 'wpdef' );
306 }
307
308 public function add_sui_to_body( $classes ) {
309 if ( ! defender_current_page() ) {
310
311 return $classes;
312 }
313 $classes .= sprintf( ' sui-%s ', DEFENDER_SUI );
314
315 return $classes;
316 }
317
318 /**
319 * Register all core assets.
320 */
321 public function register_assets() {
322 $base_url = plugin_dir_url( __DIR__ );
323 wp_enqueue_style( 'defender-menu', $base_url . 'assets/css/defender-icon.css' );
324
325 $css_files = array(
326 'defender' => $base_url . 'assets/css/styles.css',
327 );
328
329 foreach ( $css_files as $slug => $file ) {
330 wp_register_style( $slug, $file, array(), DEFENDER_VERSION );
331 }
332 $is_min = defined( 'SCRIPT_DEBUG' ) && constant( 'SCRIPT_DEBUG' ) === true ? '' : '.min';
333 $dependencies = [
334 'def-vue',
335 'defender',
336 'wp-i18n'
337 ];
338 $js_files = array(
339 'wpmudev-sui' => [
340 $base_url . 'assets/js/shared-ui.js',
341 ],
342 'defender' => [
343 $base_url . 'assets/js/scripts.js',
344 ],
345 'def-vue' => [
346 $base_url . 'assets/js/vendor/vue.runtime' . $is_min . '.js'
347 ],
348 'def-dashboard' => [
349 $base_url . 'assets/app/dashboard.js',
350 $dependencies,
351 ],
352 'def-securitytweaks' => [
353 $base_url . 'assets/app/security-tweak.js',
354 array_merge( $dependencies, [ 'clipboard', 'wpmudev-sui' ] ),
355 ],
356 'def-scan' => [
357 $base_url . 'assets/app/scan.js',
358 $dependencies,
359 ],
360 'def-audit' => [
361 $base_url . 'assets/app/audit.js',
362 $dependencies,
363 ],
364 'def-iplockout' => [
365 $base_url . 'assets/app/ip-lockout.js',
366 $dependencies,
367 ],
368 'def-advancedtools' => [
369 $base_url . 'assets/app/advanced-tools.js',
370 $dependencies,
371 ],
372 'def-settings' => [
373 $base_url . 'assets/app/settings.js',
374 $dependencies,
375 ],
376 'def-2fa' => [
377 $base_url . 'assets/app/two-fa.js',
378 $dependencies
379 ],
380 'def-notification' => [
381 $base_url . 'assets/app/notification.js',
382 $dependencies
383 ],
384 'def-waf' => [
385 $base_url . 'assets/app/waf.js',
386 $dependencies
387 ],
388 'def-onboard' => [
389 $base_url . 'assets/app/onboard.js',
390 $dependencies
391 ],
392 'def-tutorial' => [
393 $base_url . 'assets/app/tutorial.js',
394 $dependencies
395 ]
396 );
397
398 global $wp_defender_central;
399
400 foreach ( $js_files as $slug => $file ) {
401 if ( isset( $file[1] ) ) {
402 wp_register_script( $slug, $file[0], $file[1], DEFENDER_VERSION, true );
403 } else {
404 wp_register_script( $slug, $file[0], array( 'jquery' ), DEFENDER_VERSION, true );
405 }
406 }
407
408 $wpmu_dev = new WPMUDEV();
409
410 wp_localize_script( 'def-vue', 'defender', [
411 'whitelabel' => defender_white_label_status(),
412 'misc' => [
413 'high_contrast' => defender_high_contrast(),
414 ],
415 'site_url' => network_site_url(),
416 'admin_url' => network_admin_url(),
417 'defender_url' => $base_url,
418 'is_free' => $wpmu_dev->is_pro() ? 0 : 1,
419 'is_membership' => true,
420 'is_whitelabel' => $wpmu_dev->is_whitelabel_enabled() ? 'enabled' : 'disabled',
421 'opcache_save_comments' => $wp_defender_central->is_opcache_save_comments_disabled() ? 'disabled' : 'enabled',
422 'wpmudev_url' => 'https://wpmudev.com/docs/wpmu-dev-plugins/defender/',
423 ] );
424
425 wp_localize_script( 'defender', 'defenderGetText', $this->defender_gettext_translations() );
426
427 do_action( 'defender_enqueue_assets' );
428 }
429
430 /**
431 * Check to exist table.
432 *
433 * @param string $table_name
434 *
435 * @return bool
436 */
437 private function table_exists( $table_name ) {
438 global $wpdb;
439 // Full table name.
440 $table_name = $wpdb->base_prefix . $table_name;
441
442 return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) === $table_name;
443 }
444
445 /**
446 * Check and create tables if its aren't existed.
447 */
448 public function check_if_table_exists() {
449 $db_version = get_site_option( 'wd_db_version' );
450 if ( isset( $db_version ) && version_compare( $db_version, '2.4', '>=') ) {
451 return;
452 }
453
454 $this->create_database_tables();
455 }
456
457 /**
458 * Find all the strings from .mo file.
459 * `wpdef` is our text domain.
460 */
461 private function defender_gettext_translations() {
462 global $l10n;
463
464 if ( ! isset( $l10n['wpdef'] ) ) {
465 return array();
466 }
467
468 $items = array();
469
470 foreach ( $l10n['wpdef']->entries as $key => $value ) {
471 $items[ $key ] = count( $value->translations ) ? $value->translations[0] : $key;
472 }
473
474 return $items;
475 }
476
477 /**
478 * Trigger mandatory actions on activation.
479 */
480 private function on_activation() {
481 add_action(
482 'admin_init',
483 function() {
484 $security_tweaks = wd_di()->get( Security_Tweaks::class );
485 $security_tweaks->get_security_key()->cron_schedule();
486 }
487 );
488 }
489
490 /**
491 * @param array $schedules
492 *
493 * @return array
494 */
495 public function cron_schedules( $schedules ) {
496 return defender_cron_schedules( $schedules );
497 }
498
499 public function includes() {
500 add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
501 // Initialize modules.
502 add_action( 'init', array( $this, 'init_modules' ), 8 );
503 // Register routes.
504 add_action( 'init', function () {
505 require_once WP_DEFENDER_DIR . 'src/routes.php';
506 }, 9 );
507 // Include admin class. Don't use is_admin().
508 add_action( 'admin_init', [ ( new \WP_Defender\Admin() ), 'init' ] );
509 // Add WP-CLI commands.
510 if ( defined( 'WP_CLI' ) && WP_CLI ) {
511 \WP_CLI::add_command( 'defender', Cli::class );
512 }
513 // Rotational logger initialization.
514 add_action( 'init', array( ( new \WP_Defender\Component\Logger\Rotation_Logger() ), 'init' ), 99 );
515 }
516 }
517