PluginProbe
Loginizer / trunk
Loginizer vtrunk
2.1.0 2.0.9 2.0.8 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 All 74 releases
← All changes | init.php +91 -64 2.0.6 → trunk View file →
@@ -4,9 +4,9 @@
4 4 echo 'You are not allowed to access this page directly.';
5 5 exit;
6 6 }
7 7
8 -define('LOGINIZER_VERSION', '2.0.6');
8 +define('LOGINIZER_VERSION', '2.1.1');
9 9 define('LOGINIZER_DIR', dirname(LOGINIZER_FILE));
10 10 define('LOGINIZER_URL', plugins_url('', LOGINIZER_FILE));
11 11 define('LOGINIZER_PRO_URL', 'https://loginizer.com/features#compare');
12 12 define('LOGINIZER_PRICING_URL', 'https://loginizer.com/pricing');
@@ -225,9 +225,9 @@
225 225 }
226 226
227 227 }
228 228
229 -// Add the action to load the plugin
229 +// Add the action to load the plugin
230 230 add_action('plugins_loaded', 'loginizer_load_plugin');
231 231
232 232 // The function that will be called when the plugin is loaded
233 233 function loginizer_load_plugin(){
@@ -235,8 +235,18 @@
235 235 global $loginizer;
236 236
237 237 // Check if the installed version is outdated
238 238 loginizer_update_check();
239 +
240 + // There was an issue were for some users update was stuck, and free was able to get updated through auto updater option
241 + // removing these filters fixes that issue, and our Pro update blocker was improved in 2.1.1
242 + // This check can be removed 1 year from 28.09.2026
243 + if(defined('LOGINIZER_PRO_VERSION') && version_compare(LOGINIZER_PRO_VERSION, '2.1.1', '<')){
244 + foreach(['site_transient_update_plugins', 'pre_site_transient_update_plugins'] as $hook){
245 + remove_filter($hook, 'loginizer_pro_disable_manual_update_for_plugin'); // Older Pro used the default priority
246 + remove_filter($hook, 'loginizer_pro_disable_manual_update_for_plugin', 99);
247 + }
248 + }
239 249
240 250 // Set the array
241 251 if(empty($loginizer)){
242 252 $loginizer = array();
@@ -332,21 +342,22 @@
332 342 // Is called before displaying the error message so that we dont show that the username is wrong or the password
333 343 // Update Error message
334 344 add_action('wp_login_errors', 'loginizer_error_handler', 10001, 2);
335 345 add_action('woocommerce_login_failed', 'loginizer_woocommerce_error_handler', 10001);
336 - add_action('wp_login', 'loginizer_login_success', 10, 2);
346 + add_action('wp_login', 'loginizer_login_success', 11, 2);
347 + add_action('rsssl_two_factor_user_authenticated', 'loginizer_rsssl_2fa_success');
337 348
338 349 if(!empty($loginizer['ultimate-member-active'])){
339 350 add_action('wp_login_failed', 'loginizer_ultimatemember_error_handler', 10001);
340 351 }
341 352
342 - if(!empty($_COOKIE['lz_social_error']) && !empty($loginizer['social_settings']) && !loginizer_is_blacklisted()){
353 + if(!empty($_COOKIE['lz_social_error']) && !empty($loginizer['social_settings'])){
343 354 add_filter('wp_login_errors', 'loginizer_social_login_error_handler', 10000, 2);
344 355 }
345 356 }
346 357
347 358 // Social Login Form Actions
348 - if(!empty($loginizer['social_settings']) && !loginizer_is_blacklisted()){
359 + if(!empty($loginizer['social_settings'])){
349 360 if(!empty($loginizer['social_settings']['login']['login_form'])){
350 361 add_action('login_form', 'loginizer_social_btn_login');
351 362 }
352 363 }
@@ -555,53 +566,78 @@
555 566
556 567 if(empty($lz_cannot_login) && empty($loginizer['ip_is_whitelisted']) && empty($loginizer['no_loginizer_logs'])){
557 568
558 569 // The params which comes when social login returns an error, have some characters, which WordPress could not save.
559 - $server_uri = $_SERVER['REQUEST_URI'];
560 - if(!empty($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], 'lz_social_provider') !== FALSE){
561 - $request_uri = explode('=', $_SERVER['REQUEST_URI']);
570 + // REQUEST_URI / HTTP_HOST are not always set (WP-CLI, some CGI and XML-RPC setups)
571 + $server_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
572 + $http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
573 +
574 + if(!empty($server_uri) && strpos($server_uri, 'lz_social_provider') !== FALSE){
575 + $request_uri = explode('=', $server_uri);
562 576 $server_uri = $request_uri[0];
563 577 }
564 578
565 - $url = @addslashes((!empty($_SERVER['HTTPS']) ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$server_uri);
566 - $url = esc_url($url);
579 + // No addslashes() here, $wpdb->prepare() below does the escaping
580 + $url = esc_url((!empty($_SERVER['HTTPS']) ? 'https://' : 'http://').$http_host.$server_uri);
567 581
582 + // Must never be 0, we divide by it below
583 + $max_retries = (int) $loginizer['max_retries'] < 1 ? 1 : (int) $loginizer['max_retries'];
584 +
585 + // This way is atomic now, the earlier one were causing race condition.
586 + // NOTE : In the UPDATE part `count` is already the new value, as MySQL / MariaDB
587 + // evaluate the assignments from left to right, so lockout must NOT add 1 again
588 + $upsert = $wpdb->prepare(
589 + "INSERT INTO `".$wpdb->prefix."loginizer_logs`
590 + (username, time, count, ip, lockout, url)
591 + VALUES
592 + (%s, %d, 1, %s, FLOOR(1 / %d), %s)
593 + ON DUPLICATE KEY UPDATE
594 + username = VALUES(username),
595 + time = VALUES(time),
596 + count = count + 1,
597 + lockout = FLOOR(count / %d),
598 + url = VALUES(url)",
599 + $username,
600 + time(),
601 + $loginizer['current_ip'],
602 + $max_retries,
603 + $url,
604 + $max_retries
605 + );
606 + $wpdb->query($upsert);
607 +
608 + // Re-read the persisted row so email/retries-left reflect the actual count
568 609 $sel_query = $wpdb->prepare("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = %s", $loginizer['current_ip']);
569 610 $result = lz_selectquery($sel_query);
570 -
571 - if(!empty($result)){
572 - $lockout = floor((($result['count']+1) / $loginizer['max_retries']));
573 -
574 - $update_data = array('username' => $username,
575 - 'time' => time(),
576 - 'count' => $result['count']+1,
577 - 'lockout' => $lockout,
578 - 'url' => $url);
579 -
580 - $where_data = array('ip' => $loginizer['current_ip']);
581 -
582 - $format = array('%s','%d','%d','%d','%s');
583 - $where_format = array('%s');
584 -
585 - $wpdb->update($wpdb->prefix.'loginizer_logs', $update_data, $where_data, $format, $where_format);
586 -
587 - // Do we need to email admin ?
588 - if(!empty($loginizer['notify_email']) && $lockout >= $loginizer['notify_email']){
589 -
590 - $lockout_time = $loginizer['lockout_time'];
591 -
592 - if($lockout >= $loginizer['max_lockouts']){
593 - // extended lockout is in hours so we have to convert to minute
594 - $lockout_time = $loginizer['lockouts_extend'];
595 - }
596 -
597 - $sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
598 - $mail = array();
599 - $mail['to'] = $loginizer['notify_email_address'];
600 - $mail['subject'] = 'Failed '.$fail_type.' Attempts from IP '.$loginizer['current_ip'].' ('.$sitename.')';
601 - $mail['message'] = 'Hi,
602 611
603 -'.($result['count']+1).' failed '.strtolower($fail_type).' attempts and '.$lockout.' lockout(s) from IP '.$loginizer['current_ip'].' on your site :
612 + if(empty($result)){
613 + $result = array('count' => 0);
614 + }
615 +
616 + $count = (int) $result['count'];
617 + $lockout = !empty($result['lockout']) ? (int) $result['lockout'] : 0;
618 +
619 + // The lockout goes up only on every max_retries'th failure, which is the
620 + // attempt that actually locks the IP out. On the failures in between there
621 + // is nothing new to report, so we must not email on each one of them
622 + $is_new_lockout = !empty($count) && ($count % $max_retries) == 0;
623 +
624 + // Do we need to email admin ?
625 + if(!empty($loginizer['notify_email']) && !empty($is_new_lockout) && $lockout >= $loginizer['notify_email']){
626 +
627 + $lockout_time = $loginizer['lockout_time'];
628 +
629 + if($lockout >= $loginizer['max_lockouts']){
630 + $lockout_time = $loginizer['lockouts_extend'];
631 + }
632 +
633 + $sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
634 + $mail = array();
635 + $mail['to'] = $loginizer['notify_email_address'];
636 + $mail['subject'] = 'Failed '.$fail_type.' Attempts from IP '.$loginizer['current_ip'].' ('.$sitename.')';
637 + $mail['message'] = 'Hi,
638 +
639 +'.(int) $result['count'].' failed '.strtolower($fail_type).' attempts and '.$lockout.' lockout(s) from IP '.$loginizer['current_ip'].' on your site :
604 640 '.home_url().'
605 641
606 642 Last '.$fail_type.' Attempt : '.date('d/M/Y H:i:s P', time()).'
607 643 Last User Attempt : '.$username.'
@@ -609,35 +645,22 @@
609 645
610 646 Regards,
611 647 Loginizer';
612 648
613 - @wp_mail($mail['to'], $mail['subject'], $mail['message']);
614 - }
615 - }else{
616 - $result = array();
617 - $result['count'] = 0;
618 -
619 - $insert_data = array('username' => $username,
620 - 'time' => time(),
621 - 'count' => 1,
622 - 'ip' => $loginizer['current_ip'],
623 - 'lockout' => 0,
624 - 'url' => $url);
625 -
626 - $format = array('%s','%d','%d','%s','%d','%s');
627 -
628 - $wpdb->insert($wpdb->prefix.'loginizer_logs', $insert_data, $format);
649 + @wp_mail($mail['to'], $mail['subject'], $mail['message']);
629 650 }
630 -
631 - // We need to add one as this is a failed attempt as well
632 - $result['count'] = $result['count'] + 1;
651 +
633 652 loginizer_update_attempt_stats(0);
634 - $loginizer['retries_left'] = ($loginizer['max_retries'] - ($result['count'] % $loginizer['max_retries']));
635 - $loginizer['retries_left'] = $loginizer['retries_left'] == $loginizer['max_retries'] ? 0 : $loginizer['retries_left'];
653 + $loginizer['retries_left'] = $max_retries - ($count % $max_retries);
654 + $loginizer['retries_left'] = $loginizer['retries_left'] == $max_retries ? 0 : $loginizer['retries_left'];
636 655
637 656 }
638 657 }
639 658
659 +function loginizer_rsssl_2fa_success($user){
660 + loginizer_login_success('', $user);
661 +}
662 +
640 663 function loginizer_login_success($user_login, $user) {
641 664 global $wp_version, $loginizer;
642 665
643 666 loginizer_update_attempt_stats(1);
@@ -801,8 +824,12 @@
801 824
802 825 // Handles social login URL
803 826 function loginizer_social_login_error_handler($errors = '', $redirect_to = ''){
804 827 global $loginizer;
828 +
829 + if(loginizer_is_blacklisted()){
830 + return $errors;
831 + }
805 832
806 833 loginizer_get_social_error();
807 834
808 835 if(empty($loginizer['social_errors'])){