PluginProbe
Block wp-login / 1.5.7
Block wp-login v1.5.7
1.5.8 1.5.7 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5 1.5.1 1.5.2 1.5.3 1.5.4 All 40 releases
block-wp-login / block-wp-login.php

block-wp-login.php in Block wp-login 1.5.7, at block-wp-login.php

1,050 lines 30.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Plugin Name: Block wp-login
4 * Version: 1.5.7
5 * Requires at least: 5.0
6 * Requires PHP: 7.0
7 * Plugin URI: https://webd.uk/support/
8 * Description: Blocks direct access to wp-login.php and replaces it with a secret login URL to reduce brute-force traffic on Apache servers.
9 * Author: Webd Ltd
10 * Author URI: https://webd.uk
11 * License: GPLv2 or later
12 * License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
13 * Text Domain: block-wp-login
14 */
15
16 if (!defined('ABSPATH')) {
17 exit(esc_html(__('This isn\'t the page you\'re looking for. Move along, move along.', 'block-wp-login')));
18 }
19
20 if (!class_exists('bwpl_class')) {
21
22 class bwpl_class {
23
24 const VERSION = '1.5.7';
25
26 private $bwpl_new_slug = '';
27
28 public function bwpl_load() {
29
30 add_action('admin_init', array($this, 'bwpl_configure_slug'));
31 register_deactivation_hook(__FILE__, array($this, 'bwpl_uninstall'));
32
33 if (get_option('bwpl_slug')) {
34
35 if (get_option('bwpl_wp_version') !== get_bloginfo('version')) {
36
37 add_action('admin_init', array($this, 'bwpl_new_wordpress_version'));
38
39 }
40
41 add_filter('login_url', array($this, 'bwpl_change_login_url'), 10, 3);
42 add_filter('logout_url', array($this, 'bwpl_change_logout_url'), 10, 2);
43 add_filter('wp_redirect', array($this, 'bwpl_change_login_redirect'), 10, 2);
44 add_filter('logout_redirect', array($this, 'bwpl_change_logout_redirect'), 10, 3);
45 add_filter('lostpassword_url', array($this, 'bwpl_change_lostpassword_url'), 10, 2);
46 add_filter('register_url', array($this, 'bwpl_change_register_url'));
47 add_filter('site_url', array($this, 'bwpl_change_password_reset_url'), 10, 3);
48 add_filter('network_site_url', array($this, 'bwpl_change_password_reset_url'), 10, 3);
49
50 } else {
51
52 add_action('admin_notices', array($this, 'bwpl_setup_admin_notice'));
53
54 }
55
56 if (is_admin()) {
57
58 add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'bwpl_add_plugin_action_links'));
59 add_action('admin_notices', 'bwplCommon::admin_notices');
60 add_action('admin_notices', array($this, 'bwpl_daf_upgrade_notice'));
61 add_action('wp_ajax_dismiss_bwpl_notice_handler', 'bwplCommon::ajax_notice_handler');
62
63 }
64
65 add_action('wp_login', 'bwpl_class::wp_login', 10, 2);
66
67 }
68
69 function bwpl_add_plugin_action_links($links) {
70
71 $settings_links = bwplCommon::plugin_action_links(admin_url('options-permalink.php'));
72
73 return array_merge($settings_links, $links);
74
75 }
76
77 function bwpl_configure_slug() {
78
79 if (isset($_POST['bwpl_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['bwpl_nonce'])), 'bwpl_slug_change') && isset($_POST['bwpl_slug']) && current_user_can('manage_options')) {
80
81 $this->bwpl_new_slug = trim(sanitize_key(wp_strip_all_tags(wp_unslash($_POST['bwpl_slug']))));
82
83 if ($this->bwpl_new_slug) {
84
85 $notify = (isset($_POST['bwpl_notify']) && 'true' === $_POST['bwpl_notify']);
86 $this->bwpl_uninstall();
87 $this->bwpl_install(false, $notify);
88
89 } else {
90
91 if (isset($_POST['bwpl_notify']) && 'true' === $_POST['bwpl_notify']) {
92
93 $this->bwpl_send_emails(false);
94
95 }
96
97 $this->bwpl_uninstall();
98
99 }
100
101 update_option('bwpl_slug', $this->bwpl_new_slug);
102 add_filter('login_url', array($this, 'bwpl_change_login_url'), 10, 3);
103 add_filter('logout_url', array($this, 'bwpl_change_logout_url'), 10, 2);
104 add_filter('logout_redirect', array($this, 'bwpl_change_logout_redirect'), 10, 3);
105 add_filter('lostpassword_url', array($this, 'bwpl_change_lostpassword_url'), 10, 2);
106 add_filter('register_url', array($this, 'bwpl_change_register_url'));
107 add_filter('site_url', array($this, 'bwpl_change_password_reset_url'), 10, 3);
108 add_filter('network_site_url', array($this, 'bwpl_change_password_reset_url'), 10, 3);
109
110 $this->bwpl_refresh_daf_rules();
111
112 if (
113 isset($_POST['bwpl_unknown_admin']) &&
114 sanitize_text_field(wp_unslash($_POST['bwpl_unknown_admin'])) &&
115 isset($_POST['bwpl_known_ips']) &&
116 sanitize_textarea_field(wp_unslash($_POST['bwpl_known_ips']))
117 ) {
118
119 $known_ips = preg_split('/\r\n|[\r\n]/', sanitize_textarea_field(wp_unslash($_POST['bwpl_known_ips'])));
120
121 foreach ($known_ips AS $key => $known_ip) {
122
123 if (!(
124 filter_var($known_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ||
125 filter_var($known_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
126 )) {
127
128 unset($known_ips[$key]);
129
130 }
131
132 }
133
134 if ($known_ips) {
135
136 update_option('bwpl_known_ips', implode(PHP_EOL, $known_ips));
137
138 } else {
139
140 delete_option('bwpl_known_ips');
141
142 }
143
144 } else {
145
146 delete_option('bwpl_known_ips');
147
148 }
149
150 }
151
152 add_settings_section('bwpl', _x('Block wp-login', 'UI Strings', 'block-wp-login'), array($this, 'bwpl_settings_title'), 'permalink');
153 add_settings_field('bwpl_slug', __('Login address', 'block-wp-login'), array($this, 'bwpl_settings_html'), 'permalink', 'bwpl', array('label_for' => 'bwpl_slug'));
154 register_setting('permalink', 'bwpl_slug', 'strval');
155
156 }
157
158 function bwpl_settings_title() {
159
160 ?>
161 <p><?php esc_html_e('Use the options below to completely block access to wp-login.php and create a new secret login address.', 'block-wp-login'); ?></p>
162 <?php
163
164 }
165
166 function bwpl_settings_html() {
167
168 wp_nonce_field('bwpl_slug_change', 'bwpl_nonce');
169
170 $characters = 'abcdefghijklmnopqrstuvwxyz';
171 $randomString = '';
172
173 for ($i = 0; $i < 8; $i++) {
174
175 $randomString .= $characters[wp_rand(0, strlen($characters) - 1)];
176
177 }
178
179 ?>
180 <input id="bwpl_slug" name="bwpl_slug" type="text" class="regular-text code" value="<?php echo esc_attr(get_option('bwpl_slug')); ?>" />
181
182 <script type="text/javascript">
183 jQuery('#bwpl_slug').change(function() {
184 jQuery(this).val(jQuery(this).val().toLowerCase().replace(/[^a-z0-9]+/g,''));
185 if (jQuery(this).val().length !== 0) {
186 alert(<?php echo wp_json_encode(__('WARNING! DO NOT LOCK YOURSELF OUT! Your new login address will be', 'block-wp-login') . ' ' . get_site_url() . '/'); ?> + jQuery(this).val() + '/');
187 }
188 jQuery('#bwpl_notify').prop('checked', true);
189 });
190 </script>
191
192 <p><?php esc_html_e('To change your WordPress login address, enter your chosen slug above. Leave it blank to enable the default login address.', 'block-wp-login'); ?></p>
193
194 <p><a href="javascript:void(0)" class="randomlogin"><?php echo esc_html(__('Click here', 'block-wp-login')); ?></a> <?php echo esc_html(__('to generate a random login address.', 'block-wp-login')); ?></p>
195
196 <script type="text/javascript">
197 jQuery('.randomlogin').on('click',function() {
198 var result = '',
199 characters = 'abcdefghijklmnopqrstuvwxyz';
200 for (var i = 0; i < 8; i++) {
201 result += characters.charAt(Math.floor(Math.random() * characters.length));
202 }
203 jQuery('#bwpl_slug').val(result);
204 alert(<?php echo wp_json_encode(__('WARNING! DO NOT LOCK YOURSELF OUT! Your new login address will be', 'block-wp-login') . ' ' . get_site_url() . '/'); ?> + result + '/');
205 jQuery('#bwpl_notify').prop('checked', true);
206 });
207 </script>
208
209 <p><strong><?php esc_html_e('Current Login URL: ', 'block-wp-login'); ?></strong><?php
210
211 if (get_option('bwpl_slug')) {
212
213 echo esc_url(get_site_url(null, (get_option('bwpl_slug') . '/')));
214
215 } else {
216
217 echo esc_url(get_site_url(null, 'wp-login.php'));
218
219 } ?></p>
220
221 <p><input id="bwpl_notify" name="bwpl_notify" type="checkbox" value="true"> <?php esc_html_e('Notify administrators about the new login URL.', 'block-wp-login'); ?></p>
222
223 <?php
224
225 $known_ips = get_option('bwpl_known_ips');
226
227 if (!$known_ips) { $known_ips = false; }
228
229 ?>
230 <p><input id="bwpl_unknown_admin" name="bwpl_unknown_admin" type="checkbox" value="true"<?php if ($known_ips) { echo ' checked'; } ?>> <?php esc_html_e('Notify site owner if an admin signs in with an unknown IP address (advanced)', 'block-wp-login'); ?></p>
231 <p id="bwpl_known_ips_wrapper"<?php if (!$known_ips) { echo ' style="display: none;"'; } ?>><label for="bwpl_known_ips"><?php esc_html_e('Known IPs (one IP per line)', 'block-wp-login'); ?></label><br>
232 <textarea name="bwpl_known_ips" id="bwpl_known_ips" class="large-text code" rows="5"><?php echo ($known_ips ? esc_html($known_ips) : esc_html(self::get_current_ip())); ?></textarea></p>
233 <script type="text/javascript">
234 jQuery('#bwpl_unknown_admin').on('change',function() {
235 jQuery('#bwpl_known_ips_wrapper').toggle();
236 });
237 </script>
238 <?php
239
240 if (!class_exists('daf_class')) {
241
242 ?>
243 <p><strong><?php esc_html_e('Please Note: ', 'block-wp-login'); ?></strong><?php
244
245 echo wp_kses(sprintf(
246 /* translators: link to plugin install page */
247 __('To lock down your website to only serve legitimate content, please take a look at our new plugin "%s".', 'block-wp-login'),
248 '<a href="' . esc_url(add_query_arg(array('s' => 'deny-all-firewall+genuine', 'tab' => 'search', 'type' => 'term'), self_admin_url('plugin-install.php'))) . '" title="' . esc_attr(__('Deny All Firewall', 'block-wp-login')) . '">' . __('Deny All Firewall', 'block-wp-login') . '</a>'
249 ), 'post');
250
251 ?></p>
252 <?php
253
254 }
255
256 }
257
258 function bwpl_send_emails($new_version) {
259
260 $blogusers = get_users('role=Administrator');
261 $admin_emails = array();
262
263 foreach ($blogusers as $user) {
264 if ($user->user_email) {
265 $this->bwpl_send_email($user->user_email, $new_version);
266 array_push($admin_emails, $user->user_email);
267 }
268 }
269
270 if (get_bloginfo('admin_email') && !in_array(get_bloginfo('admin_email'),$admin_emails)) {
271 $this->bwpl_send_email(get_bloginfo('admin_email'), $new_version);
272 }
273
274 }
275
276 function bwpl_install($new_version = false, $notify = true) {
277
278 global $wp_filesystem;
279
280 if (!$wp_filesystem) {
281
282 require_once ABSPATH . 'wp-admin/includes/file.php';
283
284 if (!WP_Filesystem()) {
285
286 return false;
287
288 }
289
290 }
291
292 if (!is_object($wp_filesystem)) {
293
294 return false;
295
296 }
297
298 $home_path = bwplCommon::get_home_path();
299 $login_file = $home_path . 'wp-login.php';
300
301 if ($wp_filesystem->exists($login_file)) {
302
303 $content = $wp_filesystem->get_contents($login_file);
304
305 if (false === $content) {
306
307 return false;
308
309 }
310
311 $content_chunks = explode('wp-login.php', $content);
312 $content = implode($this->bwpl_new_slug . '-wp-login.php', $content_chunks);
313 $new_login_file = $home_path . $this->bwpl_new_slug . '-wp-login.php';
314
315 if ((!$wp_filesystem->exists($new_login_file) && $wp_filesystem->is_writable($home_path)) || $wp_filesystem->is_writable($new_login_file)) {
316
317 if (!$wp_filesystem->put_contents($new_login_file, $content, FS_CHMOD_FILE)) {
318
319 return false;
320
321 }
322
323 } else {
324
325 return false;
326
327 }
328
329 } else {
330
331 return false;
332
333 }
334
335 $htaccess_file = $home_path . '.htaccess';
336
337 if ((!$wp_filesystem->exists($htaccess_file) && $wp_filesystem->is_writable($home_path)) || $wp_filesystem->is_writable($htaccess_file)) {
338
339 $markerdata = $wp_filesystem->exists($htaccess_file) ? $wp_filesystem->get_contents($htaccess_file) : '';
340
341 if (false !== $markerdata) {
342
343 $markerdata = explode("\n", $markerdata);
344 $found = false;
345 $newdata = '';
346
347 foreach ($markerdata as $line) {
348
349 if (!$found) {
350
351 $newdata .= "# BEGIN BlockWPLogin\n";
352 $newdata .= "<IfModule mod_rewrite.c>\n";
353 $newdata .= "RewriteEngine On\n";
354
355 $newdata .= "RewriteCond %{QUERY_STRING} \"^action=postpass$\"
356 RewriteRule \"^" . str_replace('.', '\.', substr(site_url('wp-login.php', 'relative'), 1)) . "$\" " . str_replace('.', '\.', site_url($this->bwpl_new_slug . '-wp-login.php', 'relative')) . " [QSA,L]
357 ";
358
359 $newdata .= "RewriteRule \"^" . str_replace('.', '\.', substr(site_url('wp-login.php', 'relative'), 1)) . "\" - [F]\n";
360 $newdata .= "RewriteRule \"^$this->bwpl_new_slug\\/?$\" " . str_replace('.', '\.', site_url($this->bwpl_new_slug . '-wp-login.php', 'relative')) . " [R=301,QSA,L]\n";
361 $newdata .= "</IfModule>\n";
362 $newdata .= "# END BlockWPLogin\n\n";
363 $newdata .= "$line\n";
364 $found = true;
365
366 } else {
367
368 $newdata .= "$line\n";
369
370 }
371
372 }
373
374 if (!$wp_filesystem->put_contents($htaccess_file, $newdata, FS_CHMOD_FILE)) {
375
376 return false;
377
378 }
379
380 } else {
381
382 return false;
383
384 }
385
386 } else {
387
388 return false;
389
390 }
391
392 update_option('bwpl_wp_version', get_bloginfo('version'));
393
394 if ($new_version || $notify) {
395
396 $this->bwpl_send_emails($new_version);
397
398 }
399
400 return true;
401
402 }
403
404 function bwpl_setup_admin_notice() {
405
406 ?>
407 <div class="notice notice-success">
408 <p><?php
409 /* translators: <strong> HTML tags */
410 echo wp_kses(sprintf(__('%1$sBlock wp-login%2$s activated. ', 'block-wp-login'),'<strong>','</strong>'), 'post'); ?><a href="<?php echo esc_url(admin_url('options-permalink.php')); ?>"><?php esc_html_e('Configure the plugin here.', 'block-wp-login'); ?></a></p>
411 </div>
412 <?php
413
414 }
415
416 function bwpl_uninstall() {
417
418 global $wp_filesystem;
419
420 if (!$wp_filesystem) {
421
422 require_once ABSPATH . 'wp-admin/includes/file.php';
423
424 if (!WP_Filesystem()) {
425
426 return false;
427
428 }
429
430 }
431
432 if (!is_object($wp_filesystem)) {
433
434 return false;
435
436 }
437
438 $home_path = bwplCommon::get_home_path();
439 $htaccess_file = $home_path . '.htaccess';
440
441 if ($wp_filesystem->exists($htaccess_file)) {
442
443 if (!$wp_filesystem->is_writable($htaccess_file)) {
444
445 return false;
446
447 }
448
449 $markerdata = $wp_filesystem->get_contents($htaccess_file);
450
451 if (false === $markerdata) {
452
453 return false;
454
455 }
456
457 $markerdata = explode("\n", $markerdata);
458 $found = false;
459 $blank_line = false;
460 $newdata = '';
461
462 foreach ($markerdata as $line) {
463
464 if ($blank_line && !$line) {
465
466 $found = true;
467
468 }
469
470 if ($blank_line && $line) {
471
472 $found = false;
473
474 }
475
476 if ($line) {
477
478 $blank_line = false;
479
480 } else {
481
482 $blank_line = true;
483
484 }
485
486 if ('# BEGIN BlockWPLogin' === $line) {
487
488 $found = true;
489
490 }
491
492 if (!$found) {
493
494 $newdata .= "$line\n";
495
496 }
497
498 if ('# END BlockWPLogin' === $line) {
499
500 $found = false;
501
502 }
503
504 }
505
506 if (!$wp_filesystem->put_contents($htaccess_file, $newdata, FS_CHMOD_FILE)) {
507
508 return false;
509
510 }
511
512 }
513
514 add_filter('logout_url', array($this, 'bwpl_reset_logout_url'));
515 add_filter('logout_redirect', array($this, 'bwpl_reset_logout_url'));
516 add_filter('lostpassword_url', array($this, 'bwpl_reset_logout_url'));
517
518 $slug = get_option('bwpl_slug');
519 $login_file = $home_path . $slug . '-wp-login.php';
520
521 if ($slug && $wp_filesystem->exists($login_file)) {
522
523 if (!$wp_filesystem->is_writable($login_file) || !$wp_filesystem->delete($login_file)) {
524
525 return false;
526
527 }
528
529 }
530
531 update_option('bwpl_slug', '');
532
533 $this->bwpl_refresh_daf_rules();
534
535 return true;
536
537 }
538
539 function bwpl_change_login_url($login_url, $redirect, $force_reauth) {
540
541 if (
542 function_exists('is_user_logged_in') &&
543 (
544 is_user_logged_in() ||
545 did_action('password_reset') ||
546 $this->bwpl_is_secret_login_request()
547 )
548 ) {
549
550 $login_url = str_replace('/wp-login.php', '/' . get_option('bwpl_slug') . '-wp-login.php', $login_url);
551
552 }
553
554 return $login_url;
555
556 }
557
558 function bwpl_change_logout_url($logout_url, $redirect) {
559
560 if (
561 (function_exists('is_user_logged_in') && is_user_logged_in()) ||
562 $this->bwpl_is_secret_login_request()
563 ) {
564
565 $logout_url = str_replace('/wp-login.php', '/' . get_option('bwpl_slug') . '-wp-login.php', $logout_url);
566
567 }
568
569 return $logout_url;
570
571 }
572
573 function bwpl_change_lostpassword_url($lostpassword_url, $redirect) {
574
575 if ($this->bwpl_is_secret_login_request()) {
576
577 $lostpassword_url = str_replace('/wp-login.php', '/' . get_option('bwpl_slug') . '-wp-login.php', $lostpassword_url);
578
579 }
580
581 return $lostpassword_url;
582
583 }
584
585 function bwpl_change_register_url($register_url) {
586
587 if ($this->bwpl_is_secret_login_request()) {
588
589 $register_url = str_replace('/wp-login.php', '/' . get_option('bwpl_slug') . '-wp-login.php', $register_url);
590
591 }
592
593 return $register_url;
594
595 }
596
597 function bwpl_change_password_reset_url($url, $path, $scheme) {
598
599 if (
600 !is_string($path) ||
601 1 !== preg_match('/\Awp-login\.php\?login=[^&]+&key=[^&]+&action=rp\z/D', $path)
602 ) {
603
604 return $url;
605
606 }
607
608 return preg_replace(
609 '/\/wp-login\.php(?=\?|$)/',
610 '/' . get_option('bwpl_slug') . '-wp-login.php',
611 $url,
612 1
613 );
614
615 }
616
617 function bwpl_change_login_redirect($location, $status) {
618
619 $path = wp_parse_url($location, PHP_URL_PATH);
620 $query = wp_parse_url($location, PHP_URL_QUERY);
621
622 if (
623 !did_action('wp_login') ||
624 !is_string($path) ||
625 '/wp-login.php' !== substr($path, -13) ||
626 !is_string($query)
627 ) {
628
629 return $location;
630
631 }
632
633 preg_match_all('/(?:^|&)action=([^&]*)/', $query, $action_matches);
634
635 if (
636 1 === count($action_matches[1]) &&
637 'confirm_admin_email' === rawurldecode($action_matches[1][0])
638 ) {
639
640 $location = preg_replace(
641 '/\/wp-login\.php(?=\?|$)/',
642 '/' . get_option('bwpl_slug') . '-wp-login.php',
643 $location,
644 1
645 );
646
647 }
648
649 return $location;
650
651 }
652
653 function bwpl_change_logout_redirect($redirect_to, $requested_redirect_to, $user) {
654
655 if ($user->ID) {
656
657 $redirect_to = str_replace('/wp-login.php', '/' . get_option('bwpl_slug') . '-wp-login.php', $redirect_to);
658
659 }
660
661 return $redirect_to;
662
663 }
664
665 private function bwpl_is_secret_login_request() {
666
667 if (empty($_SERVER['SCRIPT_FILENAME']) || !is_string($_SERVER['SCRIPT_FILENAME'])) {
668
669 return false;
670
671 }
672
673 $script_filename = sanitize_text_field(wp_unslash($_SERVER['SCRIPT_FILENAME']));
674 $slug = get_option('bwpl_slug');
675
676 return $slug && $slug . '-wp-login.php' === basename($script_filename);
677
678 }
679
680 function bwpl_reset_logout_url($logout_url) {
681
682 $logout_url = str_replace('/' . get_option('bwpl_slug') . '-wp-login.php', '/wp-login.php', $logout_url);
683
684 return $logout_url;
685
686 }
687
688 function bwpl_send_email($recipient, $new_version) {
689
690 if ($new_version) {
691
692 $message = __('A recent WordPress core update has been detected and “Block wp-login” has been re-installed. Here is a reminder of your login address:', 'block-wp-login');
693
694 } else {
695
696 $message = __('Your WordPress login address has been changed:', 'block-wp-login');
697
698 }
699
700 $message .= "\r\n\r\n";
701
702 if ($this->bwpl_new_slug) {
703
704 $message .= get_site_url(null, ($this->bwpl_new_slug . '/')) . "\r\n\r\n";
705
706 } else {
707
708 $message .= get_site_url(null, 'wp-login.php') . "\r\n\r\n";
709
710 }
711
712 $message .= __('Keep this link handy! Bookmarking it is the best way to ensure you never get locked out.', 'block-wp-login');
713 $message .= "\r\n\r\n---\r\n\r\n";
714 $message .= __('Does your site need a glow-up?', 'block-wp-login');
715 $message .= "\r\n";
716 $message .= __('Running slowly?', 'block-wp-login');
717 $message .= "\r\n";
718 $message .= __('Want new features?', 'block-wp-login');
719 $message .= "\r\n\r\n";
720 $message .= __('See how we can help', 'block-wp-login');
721 $message .= ' https://webd.uk';
722
723 if (is_multisite()) {
724
725 $blogname = get_network()->site_name;
726
727 } else {
728
729 $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
730
731 }
732
733 if ($new_version) {
734
735 /* translators: website title */
736 $title = sprintf(__('[%s] WordPress Login Reminder', 'block-wp-login'), $blogname);
737
738 } else {
739
740 /* translators: website title */
741 $title = sprintf(__('[%s] WordPress Login Changed', 'block-wp-login'), $blogname);
742
743 }
744
745 if (!wp_mail($recipient, wp_specialchars_decode($title), $message)) {
746
747 add_action('admin_notices', array($this, 'bwpl_admin_notice_email_html'));
748
749 }
750
751 }
752
753 function bwpl_admin_notice_email_html() {
754
755 ?>
756 <div class="notice notice-error">
757 <p><?php
758 /* translators: <strong> HTML tags */
759 echo wp_kses(sprintf(__('%1$sBlock wp-login%2$s activated email could not be sent.', 'block-wp-login'),'<strong>','</strong>'), 'post'); ?></p>
760 </div>
761 <?php
762
763 }
764
765 function bwpl_new_wordpress_version() {
766
767 if (self::is_server_overloaded()) {
768
769 return;
770
771 }
772
773 if (self::acquire_lock()) {
774
775 try {
776
777 if (get_option('bwpl_wp_version') !== get_bloginfo('version')) {
778
779 $bwpl_old_slug = get_option('bwpl_slug');
780
781 if ($this->bwpl_uninstall()) {
782
783 $this->bwpl_new_slug = $bwpl_old_slug;
784 $this->bwpl_install(true);
785 update_option('bwpl_slug', $bwpl_old_slug);
786 $this->bwpl_refresh_daf_rules();
787
788 }
789
790 }
791
792 } finally {
793
794 usleep(500000);
795 self::release_lock();
796
797 }
798
799 }
800
801 }
802
803 public static function wp_login($user_login, $user) {
804
805 if (user_can($user->ID, 'manage_options')) {
806
807 $ip = self::get_current_ip();
808
809 if ($ip) {
810
811 $known_ips = get_option('bwpl_known_ips');
812
813 if ($known_ips) {
814
815 $known_ips = preg_split('/\r\n|[\r\n]/', $known_ips);
816
817 if (!in_array($ip, $known_ips, true)) {
818
819 if (is_multisite()) {
820
821 $blogname = get_network()->site_name;
822
823 } else {
824
825 $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
826
827 }
828
829 /* translators: website title */
830 $title = sprintf(__('[%s] WordPress Login Alert', 'block-wp-login'), $blogname);
831
832 $message = __('An administrator with an un-recognised IP address has signed in:', 'block-wp-login') . "\r\n\r\n";
833 $message .= __('User: ', 'block-wp-login') . $user_login . "\r\n\r\n";
834 $message .= __('IP: ', 'block-wp-login') . $ip . "\r\n\r\n";
835 $message .= __('Contact us if you are having trouble with WordPress https://webd.uk', 'block-wp-login') . "\r\n\r\n";
836 $message .= __('If you like our plugin please leave a short review: https://wordpress.org/support/plugin/block-wp-login/reviews/#new-post', 'block-wp-login') . "\r\n\r\n";
837
838 wp_mail(get_bloginfo('admin_email'), wp_specialchars_decode($title), $message);
839
840 }
841
842 }
843
844 }
845
846 }
847
848 }
849
850 /**
851 * Ask Deny All Firewall to rebuild its rules.
852 *
853 * Deny All Firewall 2.0 provides a public action for integrations. Keep
854 * the legacy calls as a compatibility fallback for older releases.
855 */
856 private function bwpl_refresh_daf_rules() {
857
858 $daf_options = get_option('daf_options');
859
860 if (empty($daf_options['enable_firewall'])) {
861
862 return;
863
864 }
865
866 if (has_action('deny_all_firewall_refresh_rules')) {
867
868 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
869 do_action('deny_all_firewall_refresh_rules');
870 return;
871
872 }
873
874 global $daf;
875
876 if (
877 is_object($daf) &&
878 is_callable(array($daf, 'daf_create_htaccess')) &&
879 is_callable(array($daf, 'daf_remove_rules')) &&
880 is_callable(array($daf, 'daf_inject_rules'))
881 ) {
882
883 $daf_htaccess = $daf->daf_create_htaccess();
884
885 if ($daf_htaccess && $daf->daf_remove_rules()) {
886
887 $daf->daf_inject_rules($daf_htaccess);
888
889 }
890
891 }
892
893 }
894
895 /**
896 * Prompt administrators to install the available Deny All Firewall 2.0 update.
897 */
898 public function bwpl_daf_upgrade_notice() {
899
900 $screen = get_current_screen();
901 $notice_screens = array('plugins', 'update-core', 'options-permalink');
902
903 if (
904 !$screen ||
905 !in_array($screen->id, $notice_screens, true) ||
906 !current_user_can('update_plugins') ||
907 !class_exists('daf_class') ||
908 has_action('deny_all_firewall_refresh_rules')
909 ) {
910
911 return;
912
913 }
914
915 $plugin_file = 'deny-all-firewall/deny-all-firewall.php';
916 $updates = get_site_transient('update_plugins');
917
918 if (
919 !is_object($updates) ||
920 empty($updates->response[$plugin_file]) ||
921 empty($updates->response[$plugin_file]->new_version) ||
922 version_compare($updates->response[$plugin_file]->new_version, '2.0', '<')
923 ) {
924
925 return;
926
927 }
928
929 $update_url = wp_nonce_url(
930 self_admin_url('update.php?action=upgrade-plugin&plugin=' . rawurlencode($plugin_file)),
931 'upgrade-plugin_' . $plugin_file
932 );
933
934 ?>
935 <div class="notice notice-warning">
936 <p><strong><?php esc_html_e('Block wp-login', 'block-wp-login'); ?></strong></p>
937 <p><?php esc_html_e('Deny All Firewall 2.0 or newer is available. Please update Deny All Firewall so Block wp-login can refresh its firewall rules through the supported integration.', 'block-wp-login'); ?></p>
938 <p><a class="button button-primary" href="<?php echo esc_url($update_url); ?>"><?php esc_html_e('Update Deny All Firewall', 'block-wp-login'); ?></a></p>
939 </div>
940 <?php
941
942 }
943
944 private static function get_current_ip() {
945
946 $ip = false;
947
948 if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
949
950 $ip = filter_var(wp_unslash($_SERVER['HTTP_CF_CONNECTING_IP']), FILTER_VALIDATE_IP);
951
952 } elseif (isset($_SERVER['REMOTE_ADDR'])) {
953
954 $ip = filter_var(wp_unslash($_SERVER['REMOTE_ADDR']), FILTER_VALIDATE_IP);
955
956 }
957
958
959 if (
960 $ip &&
961 !(
962 filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ||
963 filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
964 )
965 ) {
966
967 $ip = false;
968
969 }
970
971 return $ip;
972
973 }
974
975 /**
976 * Determine whether server load is too high for filesystem maintenance.
977 *
978 * Failure to detect either load or CPU capacity is treated as normal
979 * load so the reinstall can proceed as before.
980 */
981 private static function is_server_overloaded() {
982
983 if (!function_exists('sys_getloadavg')) {
984
985 return false;
986
987 }
988
989 $load_average = sys_getloadavg();
990
991 if (!is_array($load_average) || !isset($load_average[0])) {
992
993 return false;
994
995 }
996
997 $cores_available = 0;
998
999 $cpu_directories = glob('/sys/devices/system/cpu/cpu[0-9]*', GLOB_ONLYDIR);
1000
1001 if (is_array($cpu_directories) && $cpu_directories) {
1002
1003 $cores_available = count($cpu_directories);
1004
1005 } elseif (false !== getenv('NUMBER_OF_PROCESSORS')) {
1006
1007 $cores_available = absint(getenv('NUMBER_OF_PROCESSORS'));
1008
1009 }
1010
1011 if (!$cores_available) {
1012
1013 return false;
1014
1015 }
1016
1017 return ((float) $load_average[0] / $cores_available) > 1;
1018
1019 }
1020
1021 private static function acquire_lock() {
1022
1023 global $wpdb;
1024
1025 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1026 return (bool) $wpdb->get_var($wpdb->prepare("SELECT GET_LOCK(%s, %d)", 'bwpl_lock', 0));
1027
1028 }
1029
1030 private static function release_lock() {
1031
1032 global $wpdb;
1033
1034 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1035 return (bool) $wpdb->get_var($wpdb->prepare("SELECT RELEASE_LOCK(%s)", 'bwpl_lock'));
1036
1037 }
1038
1039 }
1040
1041 if (!class_exists('bwplCommon')) {
1042
1043 require_once(dirname(__FILE__) . '/includes/class-bwpl-common.php');
1044
1045 }
1046
1047 (new bwpl_class())->bwpl_load();
1048
1049 }
1050