Version Description
- Enhancement: Display user lockouts in Lockout Sidebar.
- Bug Fix: Load translations on the plugins_loaded hook.
- Bug Fix: Fixed method that could be used to discover hidden login slug on some sites.
- Bug Fix: Fixed issue that could prevent Sync from loading Malware Scan results if a scan previously failed.
- Bug Fix: Update to the REST API "Restricted Access" feature to protect against methods to work around the restricted access.
- Bug Fix: Prevent login page being hidden when following the "Confirm Email Address" notification URL.
- Bug Fix: Hide Backend notifications not being properly sent when first enabled.
Download this release
Release Info
Developer | chrisjean |
Plugin | iThemes Security (formerly Better WP Security) |
Version | 6.8.1 |
Comparing to | |
See all releases |
Code changes from version 6.8.0 to 6.8.1
- better-wp-security.php +16 -5
- core/core.php +19 -8
- core/history.txt +9 -1
- core/lib/class-itsec-scheduler.php +12 -0
- core/lockout.php +4 -52
- core/modules/hide-backend/class-itsec-hide-backend.php +56 -6
- core/modules/hide-backend/css/index.php +1 -0
- core/modules/hide-backend/css/login-page.css +3 -0
- core/modules/hide-backend/settings.php +15 -8
- core/modules/malware/sync-verbs/itsec-get-malware-scan-log.php +1 -1
- core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php +1 -1
- core/sidebar-widget-active-lockouts.php +52 -15
- history.txt +8 -0
- readme.txt +13 -4
better-wp-security.php
CHANGED
@@ -6,16 +6,27 @@
|
|
6 |
* Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
|
7 |
* Author: iThemes
|
8 |
* Author URI: https://ithemes.com
|
9 |
-
* Version: 6.8.
|
10 |
* Text Domain: better-wp-security
|
11 |
* Network: True
|
12 |
* License: GPLv2
|
13 |
*/
|
14 |
|
|
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
if ( isset( $itsec_dir ) || class_exists( 'ITSEC_Core' ) ) {
|
21 |
include( dirname( __FILE__ ) . '/core/show-multiple-version-notice.php' );
|
@@ -31,4 +42,4 @@ if ( is_admin() ) {
|
|
31 |
|
32 |
require( "$itsec_dir/core/core.php" );
|
33 |
$itsec_core = ITSEC_Core::get_instance();
|
34 |
-
$itsec_core->init( __FILE__,
|
6 |
* Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
|
7 |
* Author: iThemes
|
8 |
* Author URI: https://ithemes.com
|
9 |
+
* Version: 6.8.1
|
10 |
* Text Domain: better-wp-security
|
11 |
* Network: True
|
12 |
* License: GPLv2
|
13 |
*/
|
14 |
|
15 |
+
function itsec_load_textdomain() {
|
16 |
|
17 |
+
if ( function_exists( 'get_user_locale' ) && is_admin() ) {
|
18 |
+
$locale = get_user_locale();
|
19 |
+
} else {
|
20 |
+
$locale = get_locale();
|
21 |
+
}
|
22 |
+
|
23 |
+
$locale = apply_filters( 'plugin_locale', $locale, 'better-wp-security' );
|
24 |
+
|
25 |
+
load_textdomain( 'better-wp-security', WP_LANG_DIR . "/plugins/better-wp-security/better-wp-security-$locale.mo" );
|
26 |
+
load_plugin_textdomain( 'better-wp-security' );
|
27 |
+
}
|
28 |
+
|
29 |
+
add_action( 'plugins_loaded', 'itsec_load_textdomain' );
|
30 |
|
31 |
if ( isset( $itsec_dir ) || class_exists( 'ITSEC_Core' ) ) {
|
32 |
include( dirname( __FILE__ ) . '/core/show-multiple-version-notice.php' );
|
42 |
|
43 |
require( "$itsec_dir/core/core.php" );
|
44 |
$itsec_core = ITSEC_Core::get_instance();
|
45 |
+
$itsec_core->init( __FILE__, 'iThemes Security' );
|
core/core.php
CHANGED
@@ -106,7 +106,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
106 |
register_deactivation_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_deactivation' ) );
|
107 |
register_uninstall_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_uninstall' ) );
|
108 |
|
109 |
-
|
110 |
require( $this->plugin_dir . 'core/modules.php' );
|
111 |
add_action( 'itsec-register-modules', array( $this, 'register_modules' ) );
|
112 |
ITSEC_Modules::init_modules();
|
@@ -123,8 +122,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
123 |
require( $this->plugin_dir . 'core/lib/class-itsec-scheduler.php' );
|
124 |
require( $this->plugin_dir . 'core/lib/class-itsec-job.php' );
|
125 |
|
126 |
-
$this->setup_scheduler();
|
127 |
-
|
128 |
$this->itsec_files = ITSEC_Files::get_instance();
|
129 |
$this->itsec_notify = new ITSEC_Notify();
|
130 |
$itsec_logger = new ITSEC_Logger();
|
@@ -132,10 +129,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
132 |
$itsec_lockout->run();
|
133 |
|
134 |
// Handle upgrade if needed.
|
135 |
-
|
136 |
-
add_action( 'plugins_loaded', array( $this, 'handle_upgrade' ), -100 );
|
137 |
-
}
|
138 |
-
|
139 |
|
140 |
if ( is_admin() ) {
|
141 |
require( $this->plugin_dir . 'core/admin-pages/init.php' );
|
@@ -158,6 +152,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
158 |
* Perform initialization that requires the plugins_loaded hook to be fired.
|
159 |
*/
|
160 |
public function continue_init() {
|
|
|
161 |
ITSEC_Modules::run_active_modules();
|
162 |
|
163 |
//Admin bar links
|
@@ -181,6 +176,10 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
181 |
|
182 |
private function setup_scheduler() {
|
183 |
|
|
|
|
|
|
|
|
|
184 |
$choices = array(
|
185 |
'ITSEC_Scheduler_Cron' => $this->plugin_dir . 'core/lib/class-itsec-scheduler-cron.php',
|
186 |
'ITSEC_Scheduler_Page_Load' => $this->plugin_dir . 'core/lib/class-itsec-scheduler-page-load.php',
|
@@ -251,7 +250,14 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
251 |
* @return ITSEC_Scheduler
|
252 |
*/
|
253 |
public static function get_scheduler() {
|
254 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
}
|
256 |
|
257 |
/**
|
@@ -439,6 +445,11 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
439 |
* @param int|bool $build The version of the data storage format. Pass false to default to the current version.
|
440 |
*/
|
441 |
public function handle_upgrade( $build = false ) {
|
|
|
|
|
|
|
|
|
|
|
442 |
$this->doing_data_upgrade = true;
|
443 |
|
444 |
require_once( self::get_core_dir() . '/setup.php' );
|
106 |
register_deactivation_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_deactivation' ) );
|
107 |
register_uninstall_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_uninstall' ) );
|
108 |
|
|
|
109 |
require( $this->plugin_dir . 'core/modules.php' );
|
110 |
add_action( 'itsec-register-modules', array( $this, 'register_modules' ) );
|
111 |
ITSEC_Modules::init_modules();
|
122 |
require( $this->plugin_dir . 'core/lib/class-itsec-scheduler.php' );
|
123 |
require( $this->plugin_dir . 'core/lib/class-itsec-job.php' );
|
124 |
|
|
|
|
|
125 |
$this->itsec_files = ITSEC_Files::get_instance();
|
126 |
$this->itsec_notify = new ITSEC_Notify();
|
127 |
$itsec_logger = new ITSEC_Logger();
|
129 |
$itsec_lockout->run();
|
130 |
|
131 |
// Handle upgrade if needed.
|
132 |
+
add_action( 'plugins_loaded', array( $this, 'handle_upgrade' ), -100, 0 );
|
|
|
|
|
|
|
133 |
|
134 |
if ( is_admin() ) {
|
135 |
require( $this->plugin_dir . 'core/admin-pages/init.php' );
|
152 |
* Perform initialization that requires the plugins_loaded hook to be fired.
|
153 |
*/
|
154 |
public function continue_init() {
|
155 |
+
$this->setup_scheduler();
|
156 |
ITSEC_Modules::run_active_modules();
|
157 |
|
158 |
//Admin bar links
|
176 |
|
177 |
private function setup_scheduler() {
|
178 |
|
179 |
+
if ( $this->scheduler ) {
|
180 |
+
return;
|
181 |
+
}
|
182 |
+
|
183 |
$choices = array(
|
184 |
'ITSEC_Scheduler_Cron' => $this->plugin_dir . 'core/lib/class-itsec-scheduler-cron.php',
|
185 |
'ITSEC_Scheduler_Page_Load' => $this->plugin_dir . 'core/lib/class-itsec-scheduler-page-load.php',
|
250 |
* @return ITSEC_Scheduler
|
251 |
*/
|
252 |
public static function get_scheduler() {
|
253 |
+
|
254 |
+
$self = self::get_instance();
|
255 |
+
|
256 |
+
if ( ! $self->scheduler ) {
|
257 |
+
$self->setup_scheduler();
|
258 |
+
}
|
259 |
+
|
260 |
+
return $self->scheduler;
|
261 |
}
|
262 |
|
263 |
/**
|
445 |
* @param int|bool $build The version of the data storage format. Pass false to default to the current version.
|
446 |
*/
|
447 |
public function handle_upgrade( $build = false ) {
|
448 |
+
|
449 |
+
if ( func_num_args() === 0 && ITSEC_Modules::get_setting( 'global', 'build' ) >= $this->plugin_build ) {
|
450 |
+
return;
|
451 |
+
}
|
452 |
+
|
453 |
$this->doing_data_upgrade = true;
|
454 |
|
455 |
require_once( self::get_core_dir() . '/setup.php' );
|
core/history.txt
CHANGED
@@ -621,4 +621,12 @@
|
|
621 |
4.0.3 - 2017-01-04 - Chris Jean & Timothy Jacobs
|
622 |
Bug Fix: Fix scheduling retries for Malware Scans on sites that don't fully support WordPress's cron system.
|
623 |
Bug Fix: Reactivating Away Mode now replaces the active file if you had previously removed it.
|
624 |
-
Bug Fix: Ensure lockouts take effect immediately, even on systems where changes to server configuration files do not take effect immediately.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
4.0.3 - 2017-01-04 - Chris Jean & Timothy Jacobs
|
622 |
Bug Fix: Fix scheduling retries for Malware Scans on sites that don't fully support WordPress's cron system.
|
623 |
Bug Fix: Reactivating Away Mode now replaces the active file if you had previously removed it.
|
624 |
+
Bug Fix: Ensure lockouts take effect immediately, even on systems where changes to server configuration files do not take effect immediately.
|
625 |
+
4.0.4 - 2017-01-29 - Chris Jean & Timothy Jacobs
|
626 |
+
Enhancement: Display user lockouts in Lockout Sidebar.
|
627 |
+
Bug Fix: Load translations on the plugins_loaded hook.
|
628 |
+
Bug Fix: Fixed method that could be used to discover hidden login slug on some sites.
|
629 |
+
Bug Fix: Fixed issue that could prevent Sync from loading Malware Scan results if a scan previously failed.
|
630 |
+
Bug Fix: Update to the REST API "Restricted Access" feature to protect against methods to work around the restricted access.
|
631 |
+
Bug Fix: Prevent login page being hidden when following the "Confirm Email Address" notification URL.
|
632 |
+
Bug Fix: Hide Backend notifications not being properly sent when first enabled.
|
core/lib/class-itsec-scheduler.php
CHANGED
@@ -44,6 +44,18 @@ abstract class ITSEC_Scheduler {
|
|
44 |
*/
|
45 |
abstract public function schedule_once( $at, $id, $data = array() );
|
46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
/**
|
48 |
* Is a recurring event scheduled.
|
49 |
*
|
44 |
*/
|
45 |
abstract public function schedule_once( $at, $id, $data = array() );
|
46 |
|
47 |
+
/**
|
48 |
+
* Schedule a single event to run soon.
|
49 |
+
*
|
50 |
+
* @param string $id
|
51 |
+
* @param array $data
|
52 |
+
*
|
53 |
+
* @return bool
|
54 |
+
*/
|
55 |
+
public function schedule_soon( $id, $data = array() ) {
|
56 |
+
return $this->schedule_once( ITSEC_Core::get_current_time_gmt() + 60 * mt_rand( 1, 10 ), $id, $data );
|
57 |
+
}
|
58 |
+
|
59 |
/**
|
60 |
* Is a recurring event scheduled.
|
61 |
*
|
core/lockout.php
CHANGED
@@ -150,7 +150,7 @@ final class ITSEC_Lockout {
|
|
150 |
* @return void
|
151 |
*/
|
152 |
public function check_lockout( $user = false, $username = false, $type = '' ) {
|
153 |
-
global $wpdb
|
154 |
|
155 |
$wpdb->hide_errors(); //Hide database errors in case the tables aren't there
|
156 |
|
@@ -564,7 +564,7 @@ final class ITSEC_Lockout {
|
|
564 |
*
|
565 |
* @since 4.0
|
566 |
*
|
567 |
-
* @param string $type 'all', 'host', or '
|
568 |
* @param array $args Additional arguments.
|
569 |
*
|
570 |
* @return array all lockouts in the system
|
@@ -1106,7 +1106,7 @@ final class ITSEC_Lockout {
|
|
1106 |
|
1107 |
$lockout = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->base_prefix}itsec_lockouts` WHERE lockout_id = %d;", $id ), ARRAY_A );
|
1108 |
|
1109 |
-
if ( is_array( $lockout ) &&
|
1110 |
|
1111 |
$success = $wpdb->update(
|
1112 |
$wpdb->base_prefix . 'itsec_lockouts',
|
@@ -1120,56 +1120,10 @@ final class ITSEC_Lockout {
|
|
1120 |
|
1121 |
return $success === false ? false : true;
|
1122 |
|
1123 |
-
} else {
|
1124 |
-
|
1125 |
-
return false;
|
1126 |
-
|
1127 |
-
}
|
1128 |
-
|
1129 |
-
} elseif ( isset( $_POST['itsec_release_lockout'] ) && $_POST['itsec_release_lockout'] == 'true' ) {
|
1130 |
-
|
1131 |
-
if ( ! wp_verify_nonce( $_POST['wp_nonce'], 'itsec_release_lockout' ) ) {
|
1132 |
-
die( __( 'Security error!', 'better-wp-security' ) );
|
1133 |
-
}
|
1134 |
-
|
1135 |
-
$type = 'updated';
|
1136 |
-
$message = __( 'The selected lockouts have been cleared.', 'better-wp-security' );
|
1137 |
-
|
1138 |
-
foreach ( $_POST as $key => $value ) {
|
1139 |
-
|
1140 |
-
if ( strstr( $key, "lo_" ) ) { //see if it's a lockout to avoid processing extra post fields
|
1141 |
-
|
1142 |
-
$wpdb->update(
|
1143 |
-
$wpdb->base_prefix . 'itsec_lockouts',
|
1144 |
-
array(
|
1145 |
-
'lockout_active' => 0,
|
1146 |
-
),
|
1147 |
-
array(
|
1148 |
-
'lockout_id' => (int) $value,
|
1149 |
-
)
|
1150 |
-
);
|
1151 |
-
|
1152 |
-
}
|
1153 |
-
|
1154 |
}
|
1155 |
-
|
1156 |
-
ITSEC_Lib::clear_caches();
|
1157 |
-
|
1158 |
-
if ( is_multisite() ) {
|
1159 |
-
|
1160 |
-
$error_handler = new WP_Error();
|
1161 |
-
|
1162 |
-
$error_handler->add( $type, $message );
|
1163 |
-
|
1164 |
-
ITSEC_Lib::show_error_message( $error_handler );
|
1165 |
-
} else {
|
1166 |
-
|
1167 |
-
add_settings_error( 'itsec', esc_attr( 'settings_updated' ), $message, $type );
|
1168 |
-
|
1169 |
-
}
|
1170 |
-
|
1171 |
}
|
1172 |
|
|
|
1173 |
}
|
1174 |
|
1175 |
/**
|
@@ -1294,8 +1248,6 @@ final class ITSEC_Lockout {
|
|
1294 |
*/
|
1295 |
public function set_lockout_error() {
|
1296 |
|
1297 |
-
global $itsec_globals;
|
1298 |
-
|
1299 |
//check to see if it's the logout screen
|
1300 |
if ( isset( $_GET['itsec'] ) && $_GET['itsec'] == true ) {
|
1301 |
return '<div id="login_error">' . ITSEC_Modules::get_setting( 'global', 'user_lockout_message' ) . '</div>' . PHP_EOL;
|
150 |
* @return void
|
151 |
*/
|
152 |
public function check_lockout( $user = false, $username = false, $type = '' ) {
|
153 |
+
global $wpdb;
|
154 |
|
155 |
$wpdb->hide_errors(); //Hide database errors in case the tables aren't there
|
156 |
|
564 |
*
|
565 |
* @since 4.0
|
566 |
*
|
567 |
+
* @param string $type 'all', 'host', 'user' or 'username'.
|
568 |
* @param array $args Additional arguments.
|
569 |
*
|
570 |
* @return array all lockouts in the system
|
1106 |
|
1107 |
$lockout = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->base_prefix}itsec_lockouts` WHERE lockout_id = %d;", $id ), ARRAY_A );
|
1108 |
|
1109 |
+
if ( is_array( $lockout ) && count( $lockout ) >= 1 ) {
|
1110 |
|
1111 |
$success = $wpdb->update(
|
1112 |
$wpdb->base_prefix . 'itsec_lockouts',
|
1120 |
|
1121 |
return $success === false ? false : true;
|
1122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1123 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1124 |
}
|
1125 |
|
1126 |
+
return false;
|
1127 |
}
|
1128 |
|
1129 |
/**
|
1248 |
*/
|
1249 |
public function set_lockout_error() {
|
1250 |
|
|
|
|
|
1251 |
//check to see if it's the logout screen
|
1252 |
if ( isset( $_GET['itsec'] ) && $_GET['itsec'] == true ) {
|
1253 |
return '<div id="login_error">' . ITSEC_Modules::get_setting( 'global', 'user_lockout_message' ) . '</div>' . PHP_EOL;
|
core/modules/hide-backend/class-itsec-hide-backend.php
CHANGED
@@ -24,9 +24,11 @@ class ITSEC_Hide_Backend {
|
|
24 |
|
25 |
add_action( 'init', array( $this, 'handle_specific_page_requests' ), 1000 );
|
26 |
add_action( 'signup_hidden_fields', array( $this, 'add_token_to_registration_form' ) );
|
|
|
27 |
|
28 |
add_filter( 'site_url', array( $this, 'filter_generated_url' ), 100, 2 );
|
29 |
add_filter( 'network_site_url', array( $this, 'filter_generated_url' ), 100, 2 );
|
|
|
30 |
add_filter( 'wp_redirect', array( $this, 'filter_redirect' ) );
|
31 |
add_filter( 'comment_moderation_text', array( $this, 'filter_comment_moderation_text' ) );
|
32 |
add_filter( 'itsec_notify_admin_page_url', array( $this, 'filter_notify_admin_page_urls' ) );
|
@@ -48,7 +50,7 @@ class ITSEC_Hide_Backend {
|
|
48 |
*/
|
49 |
public function filter_comment_moderation_text( $text ) {
|
50 |
if ( $this->disable_filters ) {
|
51 |
-
return $
|
52 |
}
|
53 |
|
54 |
// The email is plain text and the links are at the end of lines, so a lazy match can be used.
|
@@ -86,10 +88,7 @@ class ITSEC_Hide_Backend {
|
|
86 |
$this->handle_canonical_login_page();
|
87 |
} else if ( 'wp-admin' === $request_path || 'wp-admin/' === substr( $request_path, 0, 9 ) ) {
|
88 |
$this->handle_wp_admin_page();
|
89 |
-
} else if (
|
90 |
-
// Only "hide" the signup page if a different slug was chosen for it.
|
91 |
-
return;
|
92 |
-
} else if ( $request_path === $this->settings['register'] ) {
|
93 |
$this->handle_registration_alias();
|
94 |
} else if ( 'wp-signup.php' === $request_path ) {
|
95 |
$this->handle_canonical_signup_page();
|
@@ -143,6 +142,11 @@ class ITSEC_Hide_Backend {
|
|
143 |
* @return void
|
144 |
*/
|
145 |
private function handle_registration_alias() {
|
|
|
|
|
|
|
|
|
|
|
146 |
if ( get_option( 'users_can_register' ) ) {
|
147 |
if ( is_multisite() ) {
|
148 |
$this->do_redirect_with_token( 'register', 'wp-signup.php' );
|
@@ -248,12 +252,15 @@ class ITSEC_Hide_Backend {
|
|
248 |
list( $clean_path ) = explode( '?', $path );
|
249 |
|
250 |
if ( 'wp-login.php' === $clean_path && 'wp-login.php' !== $this->settings['slug'] ) {
|
|
|
|
|
|
|
251 |
if ( false !== strpos( $path, 'action=postpass' ) ) {
|
252 |
// No special handling is needed for a password-protected post.
|
253 |
return $url;
|
254 |
} else if ( false !== strpos( $path, 'action=register' ) ) {
|
255 |
$url = $this->add_token_to_url( $url, 'register' );
|
256 |
-
}
|
257 |
$url = $this->add_token_to_url( $url, 'login' );
|
258 |
}
|
259 |
} else if ( 'wp-signup.php' === $clean_path && 'wp-signup.php' !== $this->settings['register'] ) {
|
@@ -263,6 +270,23 @@ class ITSEC_Hide_Backend {
|
|
263 |
return $url;
|
264 |
}
|
265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
/**
|
267 |
* Filter redirection URLs to login and signup pages to include the access token query arg.
|
268 |
*
|
@@ -320,6 +344,18 @@ class ITSEC_Hide_Backend {
|
|
320 |
}
|
321 |
}
|
322 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
/**
|
324 |
* Register the New Login URL notification.
|
325 |
*
|
@@ -409,4 +445,18 @@ class ITSEC_Hide_Backend {
|
|
409 |
|
410 |
return $this->settings['slug'];
|
411 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
}
|
24 |
|
25 |
add_action( 'init', array( $this, 'handle_specific_page_requests' ), 1000 );
|
26 |
add_action( 'signup_hidden_fields', array( $this, 'add_token_to_registration_form' ) );
|
27 |
+
add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue' ) );
|
28 |
|
29 |
add_filter( 'site_url', array( $this, 'filter_generated_url' ), 100, 2 );
|
30 |
add_filter( 'network_site_url', array( $this, 'filter_generated_url' ), 100, 2 );
|
31 |
+
add_filter( 'admin_url', array( $this, 'filter_admin_url' ), 100, 2 );
|
32 |
add_filter( 'wp_redirect', array( $this, 'filter_redirect' ) );
|
33 |
add_filter( 'comment_moderation_text', array( $this, 'filter_comment_moderation_text' ) );
|
34 |
add_filter( 'itsec_notify_admin_page_url', array( $this, 'filter_notify_admin_page_urls' ) );
|
50 |
*/
|
51 |
public function filter_comment_moderation_text( $text ) {
|
52 |
if ( $this->disable_filters ) {
|
53 |
+
return $text;
|
54 |
}
|
55 |
|
56 |
// The email is plain text and the links are at the end of lines, so a lazy match can be used.
|
88 |
$this->handle_canonical_login_page();
|
89 |
} else if ( 'wp-admin' === $request_path || 'wp-admin/' === substr( $request_path, 0, 9 ) ) {
|
90 |
$this->handle_wp_admin_page();
|
91 |
+
} else if ( $request_path === $this->settings['register'] && $this->allow_access_to_wp_signup() ) {
|
|
|
|
|
|
|
92 |
$this->handle_registration_alias();
|
93 |
} else if ( 'wp-signup.php' === $request_path ) {
|
94 |
$this->handle_canonical_signup_page();
|
142 |
* @return void
|
143 |
*/
|
144 |
private function handle_registration_alias() {
|
145 |
+
|
146 |
+
if ( 'wp-signup.php' === $this->settings['register'] ) {
|
147 |
+
return;
|
148 |
+
}
|
149 |
+
|
150 |
if ( get_option( 'users_can_register' ) ) {
|
151 |
if ( is_multisite() ) {
|
152 |
$this->do_redirect_with_token( 'register', 'wp-signup.php' );
|
252 |
list( $clean_path ) = explode( '?', $path );
|
253 |
|
254 |
if ( 'wp-login.php' === $clean_path && 'wp-login.php' !== $this->settings['slug'] ) {
|
255 |
+
|
256 |
+
$request_path = ITSEC_Lib::get_request_path();
|
257 |
+
|
258 |
if ( false !== strpos( $path, 'action=postpass' ) ) {
|
259 |
// No special handling is needed for a password-protected post.
|
260 |
return $url;
|
261 |
} else if ( false !== strpos( $path, 'action=register' ) ) {
|
262 |
$url = $this->add_token_to_url( $url, 'register' );
|
263 |
+
} elseif ( 'wp-login.php' !== $request_path || empty( $_GET['action'] ) || 'register' !== $_GET['action'] ) {
|
264 |
$url = $this->add_token_to_url( $url, 'login' );
|
265 |
}
|
266 |
} else if ( 'wp-signup.php' === $clean_path && 'wp-signup.php' !== $this->settings['register'] ) {
|
270 |
return $url;
|
271 |
}
|
272 |
|
273 |
+
/**
|
274 |
+
* Filter the admin URL to include hide backend tokens when necessary.
|
275 |
+
*
|
276 |
+
* @param string $url Complete admin URL.
|
277 |
+
* @param string $path Path passed to the admin_url function.
|
278 |
+
*
|
279 |
+
* @return string
|
280 |
+
*/
|
281 |
+
public function filter_admin_url( $url, $path ) {
|
282 |
+
|
283 |
+
if ( 0 === strpos( $path, 'profile.php?newuseremail=' ) ) {
|
284 |
+
$url = $this->add_token_to_url( $url, 'login' );
|
285 |
+
}
|
286 |
+
|
287 |
+
return $url;
|
288 |
+
}
|
289 |
+
|
290 |
/**
|
291 |
* Filter redirection URLs to login and signup pages to include the access token query arg.
|
292 |
*
|
344 |
}
|
345 |
}
|
346 |
|
347 |
+
/**
|
348 |
+
* Hide the navigation links on the registration page.
|
349 |
+
*
|
350 |
+
* These links have their security tokens removed in PHP. We only hide them for UX purposes as they would
|
351 |
+
* lead to a 404 page.
|
352 |
+
*/
|
353 |
+
public function login_enqueue() {
|
354 |
+
if ( ! empty( $_GET['action'] ) && 'register' === $_GET['action'] ) {
|
355 |
+
wp_enqueue_style( 'itsec-hide-backend-login-page', plugins_url( 'css/login-page.css', __FILE__ ) );
|
356 |
+
}
|
357 |
+
}
|
358 |
+
|
359 |
/**
|
360 |
* Register the New Login URL notification.
|
361 |
*
|
445 |
|
446 |
return $this->settings['slug'];
|
447 |
}
|
448 |
+
|
449 |
+
private function allow_access_to_wp_signup() {
|
450 |
+
|
451 |
+
if ( is_multisite() ) {
|
452 |
+
// Multisite will show its own error message and without links if signups are disabled.
|
453 |
+
return true;
|
454 |
+
}
|
455 |
+
|
456 |
+
if ( get_option( 'users_can_register' ) ) {
|
457 |
+
return true;
|
458 |
+
}
|
459 |
+
|
460 |
+
return false;
|
461 |
+
}
|
462 |
}
|
core/modules/hide-backend/css/index.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<?php // Silence is golden.
|
core/modules/hide-backend/css/login-page.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
#nav {
|
2 |
+
display: none;
|
3 |
+
}
|
core/modules/hide-backend/settings.php
CHANGED
@@ -18,20 +18,23 @@ final class ITSEC_Hide_Backend_Settings extends ITSEC_Settings {
|
|
18 |
|
19 |
protected function handle_settings_changes( $old_settings ) {
|
20 |
|
21 |
-
if ( $this->settings['enabled'] &&
|
22 |
-
$url
|
23 |
-
|
24 |
-
$url = get_site_url() . '/' . $this->settings['slug'];
|
25 |
} elseif ( ! $this->settings['enabled'] && $old_settings['enabled'] ) {
|
26 |
-
$url
|
|
|
|
|
|
|
|
|
27 |
} else {
|
28 |
return;
|
29 |
}
|
30 |
|
31 |
-
$this->send_new_login_url( $url );
|
32 |
}
|
33 |
|
34 |
-
private function send_new_login_url( $url ) {
|
35 |
if ( ITSEC_Core::doing_data_upgrade() ) {
|
36 |
// Do not send emails when upgrading data. This prevents spamming users with notifications just because the
|
37 |
// data was ported from an old version to a new version.
|
@@ -39,7 +42,11 @@ final class ITSEC_Hide_Backend_Settings extends ITSEC_Settings {
|
|
39 |
}
|
40 |
|
41 |
$nc = ITSEC_Core::get_notification_center();
|
42 |
-
|
|
|
|
|
|
|
|
|
43 |
|
44 |
$mail = $nc->mail();
|
45 |
|
18 |
|
19 |
protected function handle_settings_changes( $old_settings ) {
|
20 |
|
21 |
+
if ( $this->settings['enabled'] && ! $old_settings['enabled'] ) {
|
22 |
+
$url = get_site_url() . '/' . $this->settings['slug'];
|
23 |
+
$enabling = true;
|
|
|
24 |
} elseif ( ! $this->settings['enabled'] && $old_settings['enabled'] ) {
|
25 |
+
$url = get_site_url() . '/wp-login.php';
|
26 |
+
$enabling = false;
|
27 |
+
} elseif ( $this->settings['enabled'] && $this->settings['slug'] !== $old_settings['slug'] ) {
|
28 |
+
$url = get_site_url() . '/' . $this->settings['slug'];
|
29 |
+
$enabling = false;
|
30 |
} else {
|
31 |
return;
|
32 |
}
|
33 |
|
34 |
+
$this->send_new_login_url( $url, $enabling );
|
35 |
}
|
36 |
|
37 |
+
private function send_new_login_url( $url, $enabling ) {
|
38 |
if ( ITSEC_Core::doing_data_upgrade() ) {
|
39 |
// Do not send emails when upgrading data. This prevents spamming users with notifications just because the
|
40 |
// data was ported from an old version to a new version.
|
42 |
}
|
43 |
|
44 |
$nc = ITSEC_Core::get_notification_center();
|
45 |
+
|
46 |
+
if ( $enabling ) {
|
47 |
+
$nc->clear_notifications_cache();
|
48 |
+
ITSEC_Modules::get_settings_obj( 'notification-center' )->load();
|
49 |
+
}
|
50 |
|
51 |
$mail = $nc->mail();
|
52 |
|
core/modules/malware/sync-verbs/itsec-get-malware-scan-log.php
CHANGED
@@ -19,7 +19,7 @@ class Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log extends Ithemes_Sync_Verb {
|
|
19 |
foreach ( $items as $item ) {
|
20 |
$item['log_data'] = maybe_unserialize( $item['log_data'] );
|
21 |
|
22 |
-
if ( ! isset( $item['log_data']['SCAN']['SITE'] ) ) {
|
23 |
// Don't return old scan data.
|
24 |
continue;
|
25 |
}
|
19 |
foreach ( $items as $item ) {
|
20 |
$item['log_data'] = maybe_unserialize( $item['log_data'] );
|
21 |
|
22 |
+
if ( ! is_array( $item['log_data'] ) || ! isset( $item['log_data']['SCAN']['SITE'] ) ) {
|
23 |
// Don't return old scan data.
|
24 |
continue;
|
25 |
}
|
core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php
CHANGED
@@ -185,7 +185,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
185 |
return $result;
|
186 |
}
|
187 |
|
188 |
-
$route = $request->get_route();
|
189 |
$route_parts = explode( '/', trim( $route, '/' ) );
|
190 |
|
191 |
if ( 'wp' !== $route_parts[0] ) {
|
185 |
return $result;
|
186 |
}
|
187 |
|
188 |
+
$route = strtolower( $request->get_route() );
|
189 |
$route_parts = explode( '/', trim( $route, '/' ) );
|
190 |
|
191 |
if ( 'wp' !== $route_parts[0] ) {
|
core/sidebar-widget-active-lockouts.php
CHANGED
@@ -15,6 +15,7 @@ class ITSEC_Settings_Page_Sidebar_Widget_Active_Lockouts extends ITSEC_Settings_
|
|
15 |
global $itsec_lockout;
|
16 |
|
17 |
$lockouts = $itsec_lockout->get_lockouts();
|
|
|
18 |
$users = array();
|
19 |
$hosts = array();
|
20 |
|
@@ -31,26 +32,36 @@ class ITSEC_Settings_Page_Sidebar_Widget_Active_Lockouts extends ITSEC_Settings_
|
|
31 |
|
32 |
$data = array( $lockout['lockout_id'], $expiration );
|
33 |
|
34 |
-
if ( ! empty( $lockout['
|
35 |
-
$users[$lockout['
|
36 |
-
}
|
37 |
-
$
|
|
|
|
|
38 |
}
|
39 |
}
|
40 |
|
41 |
|
42 |
-
if (
|
43 |
echo '<p>' . __( 'There are no active lockouts at this time.', 'better-wp-security' ) . "</p>\n";
|
44 |
return;
|
45 |
}
|
46 |
|
47 |
if ( ! empty( $users ) ) {
|
48 |
-
|
49 |
-
echo '<p><strong>' . _n( 'User', 'Users', count( $users ), 'better-wp-security' ) . "</strong></p>\n";
|
50 |
echo "<ul>\n";
|
51 |
|
52 |
-
foreach ( $users as $
|
53 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
echo '<li><label>';
|
55 |
$form->add_multi_checkbox( 'users', $data[0] );
|
56 |
echo " $label</label></li>\n";
|
@@ -59,13 +70,28 @@ class ITSEC_Settings_Page_Sidebar_Widget_Active_Lockouts extends ITSEC_Settings_
|
|
59 |
echo "</ul>\n";
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
if ( ! empty( $hosts ) ) {
|
63 |
-
|
64 |
-
echo '<p><strong>' . _n( 'Host', 'Hosts', count( $hosts ), 'better-wp-security' ) . "</strong></p>\n";
|
65 |
echo "<ul>\n";
|
66 |
|
67 |
foreach ( $hosts as $host => $data ) {
|
68 |
-
|
|
|
69 |
echo '<li><label>';
|
70 |
$form->add_multi_checkbox( 'hosts', $data[0] );
|
71 |
echo " $label</label></li>\n";
|
@@ -92,7 +118,18 @@ class ITSEC_Settings_Page_Sidebar_Widget_Active_Lockouts extends ITSEC_Settings_
|
|
92 |
$count++;
|
93 |
|
94 |
if ( ! $result ) {
|
95 |
-
$this->errors[] = sprintf( __( 'An unknown error prevented releasing the lockout
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
}
|
97 |
}
|
98 |
}
|
@@ -103,14 +140,14 @@ class ITSEC_Settings_Page_Sidebar_Widget_Active_Lockouts extends ITSEC_Settings_
|
|
103 |
$count++;
|
104 |
|
105 |
if ( ! $result ) {
|
106 |
-
$this->errors[] = sprintf( __( 'An unknown error prevented releasing the lockout
|
107 |
}
|
108 |
}
|
109 |
}
|
110 |
|
111 |
if ( empty( $this->errors ) ) {
|
112 |
if ( $count > 0 ) {
|
113 |
-
$this->messages[] = _n( 'Successfully removed the selected lockout.', '
|
114 |
} else {
|
115 |
$this->errors[] = __( 'No lockouts were selected for removal.', 'better-wp-security' );
|
116 |
}
|
15 |
global $itsec_lockout;
|
16 |
|
17 |
$lockouts = $itsec_lockout->get_lockouts();
|
18 |
+
$usernames = array();
|
19 |
$users = array();
|
20 |
$hosts = array();
|
21 |
|
32 |
|
33 |
$data = array( $lockout['lockout_id'], $expiration );
|
34 |
|
35 |
+
if ( ! empty( $lockout['lockout_user'] ) ) {
|
36 |
+
$users[ $lockout['lockout_user'] ] = $data;
|
37 |
+
} elseif ( ! empty( $lockout['lockout_username'] ) ) {
|
38 |
+
$usernames[ $lockout['lockout_username'] ] = $data;
|
39 |
+
} elseif ( ! empty( $lockout['lockout_host'] ) ) {
|
40 |
+
$hosts[ $lockout['lockout_host'] ] = $data;
|
41 |
}
|
42 |
}
|
43 |
|
44 |
|
45 |
+
if ( ! $users && ! $usernames && ! $hosts ) {
|
46 |
echo '<p>' . __( 'There are no active lockouts at this time.', 'better-wp-security' ) . "</p>\n";
|
47 |
return;
|
48 |
}
|
49 |
|
50 |
if ( ! empty( $users ) ) {
|
51 |
+
echo '<p><strong>' . __( 'Users', 'better-wp-security' ) . "</strong></p>\n";
|
|
|
52 |
echo "<ul>\n";
|
53 |
|
54 |
+
foreach ( $users as $user_id => $data ) {
|
55 |
+
$user = get_userdata( $user_id );
|
56 |
+
|
57 |
+
if ( $user ) {
|
58 |
+
$label = $user->user_login;
|
59 |
+
} else {
|
60 |
+
$label = sprintf( __( 'Deleted #%d', 'better-wp-security' ), $user_id );
|
61 |
+
}
|
62 |
+
|
63 |
+
/* translators: 1. Username 2. Expiration as human time diff */
|
64 |
+
$label = sprintf( _x( '%1$s - Expires in %2$s', 'User lockout', 'better-wp-security' ), "<strong>{$label}</strong>", '<em>' . human_time_diff( $data[1] ) . '</em>' );
|
65 |
echo '<li><label>';
|
66 |
$form->add_multi_checkbox( 'users', $data[0] );
|
67 |
echo " $label</label></li>\n";
|
70 |
echo "</ul>\n";
|
71 |
}
|
72 |
|
73 |
+
if ( ! empty( $usernames ) ) {
|
74 |
+
echo '<p><strong>' . __( 'Usernames', 'better-wp-security' ) . "</strong></p>\n";
|
75 |
+
echo "<ul>\n";
|
76 |
+
|
77 |
+
foreach ( $usernames as $username => $data ) {
|
78 |
+
/* translators: 1. Username 2. Expiration as human time diff */
|
79 |
+
$label = sprintf( _x( '%1$s - Expires in %2$s', 'Username lockout', 'better-wp-security' ), '<strong>' . esc_html( $username ) . '</strong>', '<em>' . human_time_diff( $data[1] ) . '</em>' );
|
80 |
+
echo '<li><label>';
|
81 |
+
$form->add_multi_checkbox( 'usernames', $data[0] );
|
82 |
+
echo " $label</label></li>\n";
|
83 |
+
}
|
84 |
+
|
85 |
+
echo "</ul>\n";
|
86 |
+
}
|
87 |
+
|
88 |
if ( ! empty( $hosts ) ) {
|
89 |
+
echo '<p><strong>' . __( 'Hosts', 'better-wp-security' ) . "</strong></p>\n";
|
|
|
90 |
echo "<ul>\n";
|
91 |
|
92 |
foreach ( $hosts as $host => $data ) {
|
93 |
+
/* translators: 1. IP Address 2. Expiration as human time diff */
|
94 |
+
$label = sprintf( _x( '%1$s - Expires in %2$s', 'Host lockout', 'better-wp-security' ), '<strong>' . esc_html( strtoupper( $host ) ) . '</strong>', '<em>' . human_time_diff( $data[1] ) . '</em>' );
|
95 |
echo '<li><label>';
|
96 |
$form->add_multi_checkbox( 'hosts', $data[0] );
|
97 |
echo " $label</label></li>\n";
|
118 |
$count++;
|
119 |
|
120 |
if ( ! $result ) {
|
121 |
+
$this->errors[] = sprintf( __( 'An unknown error prevented releasing the user lockout with a lockout ID of %d', 'better-wp-security' ), $id );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
if ( ! empty( $data['usernames'] ) && is_array( $data['usernames'] ) ) {
|
127 |
+
foreach ( $data['usernames'] as $id ) {
|
128 |
+
$result = $itsec_lockout->release_lockout( $id );
|
129 |
+
$count++;
|
130 |
+
|
131 |
+
if ( ! $result ) {
|
132 |
+
$this->errors[] = sprintf( __( 'An unknown error prevented releasing the username lockout with a lockout ID of %d', 'better-wp-security' ), $id );
|
133 |
}
|
134 |
}
|
135 |
}
|
140 |
$count++;
|
141 |
|
142 |
if ( ! $result ) {
|
143 |
+
$this->errors[] = sprintf( __( 'An unknown error prevented releasing the host lockout with a lockout ID of %d', 'better-wp-security' ), $id );
|
144 |
}
|
145 |
}
|
146 |
}
|
147 |
|
148 |
if ( empty( $this->errors ) ) {
|
149 |
if ( $count > 0 ) {
|
150 |
+
$this->messages[] = _n( 'Successfully removed the selected lockout.', 'Successfully remove the selected lockouts.', $count, 'better-wp-security' );
|
151 |
} else {
|
152 |
$this->errors[] = __( 'No lockouts were selected for removal.', 'better-wp-security' );
|
153 |
}
|
history.txt
CHANGED
@@ -709,3 +709,11 @@
|
|
709 |
Bug Fix: Fixed issue where scheduled events could repeat on sites that do not properly support WordPress's cron system.
|
710 |
Bug Fix: Reactivating Away Mode now replaces the active file if you had previously removed it.
|
711 |
Bug Fix: Ensure lockouts take effect immediately, even on systems where changes to server configuration files do not take effect immediately.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
709 |
Bug Fix: Fixed issue where scheduled events could repeat on sites that do not properly support WordPress's cron system.
|
710 |
Bug Fix: Reactivating Away Mode now replaces the active file if you had previously removed it.
|
711 |
Bug Fix: Ensure lockouts take effect immediately, even on systems where changes to server configuration files do not take effect immediately.
|
712 |
+
6.8.1 - 2017-01-29 - Chris Jean & Timothy Jacobs
|
713 |
+
Enhancement: Display user lockouts in Lockout Sidebar.
|
714 |
+
Bug Fix: Load translations on the plugins_loaded hook.
|
715 |
+
Bug Fix: Fixed method that could be used to discover hidden login slug on some sites.
|
716 |
+
Bug Fix: Fixed issue that could prevent Sync from loading Malware Scan results if a scan previously failed.
|
717 |
+
Bug Fix: Update to the REST API "Restricted Access" feature to protect against methods to work around the restricted access.
|
718 |
+
Bug Fix: Prevent login page being hidden when following the "Confirm Email Address" notification URL.
|
719 |
+
Bug Fix: Hide Backend notifications not being properly sent when first enabled.
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: ithemes, chrisjean, gerroald, mattdanner, timothyblynjacobs
|
3 |
Tags: security, security plugin, malware, hack, secure, block, SSL, admin, htaccess, lockdown, login, protect, protection, anti virus, attack, injection, login security, maintenance, permissions, prevention, authentication, administration, password, brute force, ban, permissions, bots, user agents, xml rpc, security log
|
4 |
Requires at least: 4.7
|
5 |
-
Tested up to: 4.9.
|
6 |
-
Stable tag: 6.8.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -188,6 +188,15 @@ Free support may be available with the help of the community in the <a href="htt
|
|
188 |
|
189 |
== Changelog ==
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
= 6.8.0 =
|
192 |
* New Feature: Introduces a scheduling framework for handling events. Cron is now used by default, and will switch to using an alternate scheduling system if it detects an error. To disable this detection set ITSEC_DISABLE_CRON_TEST in your wp-config.php file.
|
193 |
* Important: The ITSEC_FILE_CHECK_CRON and ITSEC_BACKUP_CRON constants have been deprecated. Use ITSEC_USE_CRON instead.
|
@@ -391,5 +400,5 @@ Free support may be available with the help of the community in the <a href="htt
|
|
391 |
|
392 |
== Upgrade Notice ==
|
393 |
|
394 |
-
= 6.8.
|
395 |
-
Version 6.8.
|
2 |
Contributors: ithemes, chrisjean, gerroald, mattdanner, timothyblynjacobs
|
3 |
Tags: security, security plugin, malware, hack, secure, block, SSL, admin, htaccess, lockdown, login, protect, protection, anti virus, attack, injection, login security, maintenance, permissions, prevention, authentication, administration, password, brute force, ban, permissions, bots, user agents, xml rpc, security log
|
4 |
Requires at least: 4.7
|
5 |
+
Tested up to: 4.9.2
|
6 |
+
Stable tag: 6.8.1
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
188 |
|
189 |
== Changelog ==
|
190 |
|
191 |
+
= 6.8.1 =
|
192 |
+
* Enhancement: Display user lockouts in Lockout Sidebar.
|
193 |
+
* Bug Fix: Load translations on the plugins_loaded hook.
|
194 |
+
* Bug Fix: Fixed method that could be used to discover hidden login slug on some sites.
|
195 |
+
* Bug Fix: Fixed issue that could prevent Sync from loading Malware Scan results if a scan previously failed.
|
196 |
+
* Bug Fix: Update to the REST API "Restricted Access" feature to protect against methods to work around the restricted access.
|
197 |
+
* Bug Fix: Prevent login page being hidden when following the "Confirm Email Address" notification URL.
|
198 |
+
* Bug Fix: Hide Backend notifications not being properly sent when first enabled.
|
199 |
+
|
200 |
= 6.8.0 =
|
201 |
* New Feature: Introduces a scheduling framework for handling events. Cron is now used by default, and will switch to using an alternate scheduling system if it detects an error. To disable this detection set ITSEC_DISABLE_CRON_TEST in your wp-config.php file.
|
202 |
* Important: The ITSEC_FILE_CHECK_CRON and ITSEC_BACKUP_CRON constants have been deprecated. Use ITSEC_USE_CRON instead.
|
400 |
|
401 |
== Upgrade Notice ==
|
402 |
|
403 |
+
= 6.8.1 =
|
404 |
+
Version 6.8.1 contains important bug fixes and improvements. It is recommended for all users.
|