Version Description
- Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
- Bug Fix: Skip recovery if File Change storage is empty.
Download this release
Release Info
Developer | TimothyBlynJacobs |
Plugin | iThemes Security (formerly Better WP Security) |
Version | 7.0.1 |
Comparing to | |
See all releases |
Code changes from version 7.1.0 to 7.0.1
- better-wp-security.php +1 -1
- core/admin-pages/css/style.css +0 -19
- core/admin-pages/init.php +1 -6
- core/admin-pages/js/debug.js +0 -90
- core/admin-pages/js/script.js +21 -25
- core/admin-pages/js/settings.js +21 -25
- core/admin-pages/js/util.js +1 -37
- core/admin-pages/logs-list-table.php +23 -88
- core/admin-pages/page-debug.php +0 -425
- core/admin-pages/page-logs.php +0 -22
- core/admin-pages/page-settings.php +0 -2
- core/core.php +12 -20
- core/history.txt +1 -50
- core/lib.php +32 -143
- core/lib/class-itsec-job.php +3 -4
- core/lib/class-itsec-lib-canonical-roles.php +0 -70
- core/lib/class-itsec-lib-password-requirements.php +159 -156
- core/lib/class-itsec-mail.php +28 -148
- core/lib/class-itsec-scheduler-cron.php +12 -19
- core/lib/class-itsec-scheduler-page-load.php +2 -17
- core/lib/class-itsec-scheduler.php +0 -14
- core/lib/class-itsec-wp-list-table.php +11 -9
- core/lib/form.php +0 -39
- core/lib/log-util.php +16 -34
- core/lib/mail-templates/header.html +0 -1
- core/lib/schema.php +0 -1
- core/lib/settings.php +22 -24
- core/lib/validator.php +1 -75
- core/lockout.php +4 -1
- core/modules/404-detection/class-itsec-four-oh-four.php +8 -4
- core/modules/404-detection/logs.php +0 -5
- core/modules/away-mode/class-itsec-away-mode.php +1 -6
- core/modules/file-change/class-itsec-file-change.php +1 -1
- core/modules/file-change/css/settings.css +0 -14
- core/modules/file-change/js/settings-page.js +0 -15
- core/modules/file-change/logs.php +1 -11
- core/modules/file-change/scanner.php +8 -18
- core/modules/file-change/settings-page.php +4 -15
- core/modules/global/active.php +1 -20
- core/modules/global/settings-page.php +0 -14
- core/modules/global/settings.php +0 -12
- core/modules/global/validator.php +1 -2
- core/modules/notification-center/class-notification-center.php +26 -72
- core/modules/notification-center/debug.php +0 -92
- core/modules/notification-center/js/debug.js +0 -22
- core/modules/notification-center/js/settings-page.js +4 -6
- core/modules/notification-center/logs.php +0 -94
- core/modules/notification-center/settings-page.php +75 -103
- core/modules/notification-center/settings.php +29 -79
- core/modules/notification-center/setup.php +2 -19
- core/modules/notification-center/validator.php +5 -60
- core/modules/password-requirements/active.php +0 -6
- core/modules/password-requirements/class-itsec-password-requirements.php +0 -480
- core/modules/password-requirements/css/index.php +0 -1
- core/modules/password-requirements/css/settings-page.css +0 -3
- core/modules/password-requirements/index.php +0 -1
- core/modules/password-requirements/js/index.php +0 -1
- core/modules/password-requirements/js/settings-page.js +0 -24
- core/modules/password-requirements/settings-page.php +0 -115
- core/modules/password-requirements/settings.php +0 -51
- core/modules/password-requirements/validator.php +0 -62
- core/modules/pro/settings-page.php +16 -0
- core/modules/security-check/scanner.php +2 -38
- core/modules/ssl/class-itsec-ssl.php +2 -2
- core/modules/strong-passwords/class-itsec-strong-passwords.php +168 -139
- core/modules/strong-passwords/js/script.js +8 -1
- core/modules/strong-passwords/settings-page.php +51 -0
- core/modules/strong-passwords/setup.php +4 -26
- core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php +5 -155
- core/modules/wordpress-tweaks/settings-page.php +0 -8
- core/modules/wordpress-tweaks/settings.php +0 -1
- core/modules/wordpress-tweaks/validator.php +0 -1
- core/notify.php +5 -10
- core/response.php +8 -22
- core/setup.php +6 -4
- history.txt +0 -38
- readme.txt +4 -46
better-wp-security.php
CHANGED
@@ -6,7 +6,7 @@
|
|
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: 7.1
|
10 |
* Text Domain: better-wp-security
|
11 |
* Network: True
|
12 |
* License: GPLv2
|
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: 7.0.1
|
10 |
* Text Domain: better-wp-security
|
11 |
* Network: True
|
12 |
* License: GPLv2
|
core/admin-pages/css/style.css
CHANGED
@@ -851,22 +851,3 @@ body.security_page_itsec-logs #old-logs-migration-status img {
|
|
851 |
body.security_page_itsec-logs #old-logs-migration-status p {
|
852 |
line-height: 1.4em;
|
853 |
}
|
854 |
-
#itsec-system-info, #itsec-settings-editor {
|
855 |
-
font-family: monospace;
|
856 |
-
width: 100%;
|
857 |
-
margin: 0;
|
858 |
-
height: 300px;
|
859 |
-
padding: 20px;
|
860 |
-
border-radius: 0;
|
861 |
-
resize: none;
|
862 |
-
font-size: 12px;
|
863 |
-
line-height: 20px;
|
864 |
-
outline: 0;
|
865 |
-
}
|
866 |
-
|
867 |
-
#itsec-settings-editor:empty {
|
868 |
-
display: none;
|
869 |
-
}
|
870 |
-
.itsec-module-cards-container .bulkactions:empty {
|
871 |
-
display: none;
|
872 |
-
}
|
851 |
body.security_page_itsec-logs #old-logs-migration-status p {
|
852 |
line-height: 1.4em;
|
853 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/admin-pages/init.php
CHANGED
@@ -16,7 +16,6 @@ final class ITSEC_Admin_Page_Loader {
|
|
16 |
add_action( 'wp_ajax_itsec_settings_page', array( $this, 'handle_ajax_request' ) );
|
17 |
add_action( 'wp_ajax_itsec_logs_page', array( $this, 'handle_ajax_request' ) );
|
18 |
add_action( 'wp_ajax_itsec_help_page', array( $this, 'handle_ajax_request' ) );
|
19 |
-
add_action( 'wp_ajax_itsec_debug_page', array( $this, 'handle_ajax_request' ) );
|
20 |
add_action( 'wp_ajax_itsec-set-user-setting', array( $this, 'handle_user_setting' ) );
|
21 |
|
22 |
// Filters for validating user settings
|
@@ -24,7 +23,7 @@ final class ITSEC_Admin_Page_Loader {
|
|
24 |
}
|
25 |
|
26 |
public function add_scripts() {
|
27 |
-
|
28 |
}
|
29 |
|
30 |
public function add_styles() {
|
@@ -47,10 +46,6 @@ final class ITSEC_Admin_Page_Loader {
|
|
47 |
$page_refs[] = add_submenu_page( 'itsec', '', '<span style="color:#2EA2CC">' . __( 'Go Pro', 'better-wp-security' ) . '</span>', $capability, 'itsec-go-pro', array( $this, 'show_page' ) );
|
48 |
}
|
49 |
|
50 |
-
if ( defined( 'ITSEC_DEBUG' ) && ITSEC_DEBUG ) {
|
51 |
-
$page_refs[] = add_submenu_page( 'itsec', __( 'iThemes Security Debug', 'better-wp-security' ), __( 'Debug' ), $capability, 'itsec-debug', array( $this, 'show_page' ) );
|
52 |
-
}
|
53 |
-
|
54 |
foreach ( $page_refs as $page_ref ) {
|
55 |
add_action( "load-$page_ref", array( $this, 'load' ) );
|
56 |
}
|
16 |
add_action( 'wp_ajax_itsec_settings_page', array( $this, 'handle_ajax_request' ) );
|
17 |
add_action( 'wp_ajax_itsec_logs_page', array( $this, 'handle_ajax_request' ) );
|
18 |
add_action( 'wp_ajax_itsec_help_page', array( $this, 'handle_ajax_request' ) );
|
|
|
19 |
add_action( 'wp_ajax_itsec-set-user-setting', array( $this, 'handle_user_setting' ) );
|
20 |
|
21 |
// Filters for validating user settings
|
23 |
}
|
24 |
|
25 |
public function add_scripts() {
|
26 |
+
ITSEC_Lib::enqueue_util();
|
27 |
}
|
28 |
|
29 |
public function add_styles() {
|
46 |
$page_refs[] = add_submenu_page( 'itsec', '', '<span style="color:#2EA2CC">' . __( 'Go Pro', 'better-wp-security' ) . '</span>', $capability, 'itsec-go-pro', array( $this, 'show_page' ) );
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
49 |
foreach ( $page_refs as $page_ref ) {
|
50 |
add_action( "load-$page_ref", array( $this, 'load' ) );
|
51 |
}
|
core/admin-pages/js/debug.js
DELETED
@@ -1,90 +0,0 @@
|
|
1 |
-
(function ( $, itsecUtil, codeEditor ) {
|
2 |
-
$( function () {
|
3 |
-
var $messages = $( "#itsec-messages" );
|
4 |
-
|
5 |
-
$( '#itsec-scheduler-events' ).on( 'click', '.button', function () {
|
6 |
-
|
7 |
-
var $btn = $( this );
|
8 |
-
$btn.prop( 'disabled', true );
|
9 |
-
|
10 |
-
// We are purposely using attr() so as not to parse the data string as json.
|
11 |
-
itsecUtil.sendAJAXRequest( '', 'run_event', { id: $btn.data( 'id' ), data: $btn.attr( 'data-data' ) }, function ( result ) {
|
12 |
-
|
13 |
-
$btn.prop( 'disabled', false );
|
14 |
-
|
15 |
-
if ( result.success ) {
|
16 |
-
$( 'table', '#itsec-scheduler-events' ).replaceWith( result.response );
|
17 |
-
}
|
18 |
-
|
19 |
-
itsecUtil.displayNotices( result, $messages );
|
20 |
-
} );
|
21 |
-
} );
|
22 |
-
|
23 |
-
$( document ).on( 'click', '#itsec-events-data-toggle', function () {
|
24 |
-
$( '.itsec-events-data' ).toggleClass( 'hidden' );
|
25 |
-
} );
|
26 |
-
|
27 |
-
$( '#itsec-scheduler-reset' ).on( 'click', function () {
|
28 |
-
|
29 |
-
var $btn = $( this );
|
30 |
-
$btn.prop( 'disabled', true );
|
31 |
-
|
32 |
-
itsecUtil.sendAJAXRequest( '', 'reset_scheduler', {}, function ( result ) {
|
33 |
-
|
34 |
-
$btn.prop( 'disabled', false );
|
35 |
-
|
36 |
-
if ( result.success ) {
|
37 |
-
$( 'table', '#itsec-scheduler-events' ).replaceWith( result.response );
|
38 |
-
}
|
39 |
-
|
40 |
-
itsecUtil.displayNotices( result, $messages );
|
41 |
-
} );
|
42 |
-
} );
|
43 |
-
|
44 |
-
var $saveBtn = $( '#itsec-settings-save' ), $loadBtn = $( "#itsec-settings-load" );
|
45 |
-
|
46 |
-
$loadBtn.on( 'click', function () {
|
47 |
-
$loadBtn.prop( 'disabled', true );
|
48 |
-
|
49 |
-
itsecUtil.sendAJAXRequest( $( '#itsec-settings-module' ).val(), 'load_settings', {}, function ( result ) {
|
50 |
-
itsecUtil.displayNotices( result, $messages );
|
51 |
-
|
52 |
-
$loadBtn.prop( 'disabled', false );
|
53 |
-
$saveBtn.prop( 'disabled', false );
|
54 |
-
setEditorContent( JSON.stringify( result.response, null, 4 ) );
|
55 |
-
} );
|
56 |
-
} );
|
57 |
-
|
58 |
-
$saveBtn.on( 'click', function () {
|
59 |
-
|
60 |
-
$loadBtn.prop( 'disabled', true );
|
61 |
-
$saveBtn.prop( 'disabled', true );
|
62 |
-
|
63 |
-
itsecUtil.sendAJAXRequest( $( '#itsec-settings-module' ).val(), 'save_settings', getEditorContent(), function ( result ) {
|
64 |
-
itsecUtil.displayNotices( result, $messages );
|
65 |
-
|
66 |
-
$loadBtn.prop( 'disabled', false );
|
67 |
-
$saveBtn.prop( 'disabled', false );
|
68 |
-
|
69 |
-
if ( result.success ) {
|
70 |
-
setEditorContent( JSON.stringify( result.response, null, 4 ) );
|
71 |
-
}
|
72 |
-
} );
|
73 |
-
} );
|
74 |
-
|
75 |
-
var $editor = $( "#itsec-settings-editor" ), editor;
|
76 |
-
|
77 |
-
function setEditorContent( content ) {
|
78 |
-
if ( codeEditor ) {
|
79 |
-
if ( !editor ) editor = codeEditor.initialize( $editor );
|
80 |
-
editor.codemirror.setValue( content );
|
81 |
-
} else {
|
82 |
-
$editor.val( content );
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
function getEditorContent() {
|
87 |
-
return editor ? editor.codemirror.getValue() : $editor.val();
|
88 |
-
}
|
89 |
-
} );
|
90 |
-
})( jQuery, window.itsecUtil, wp.codeEditor );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/admin-pages/js/script.js
CHANGED
@@ -980,38 +980,34 @@ var itsecSettingsPage = {
|
|
980 |
},
|
981 |
|
982 |
// Make notices dismissible
|
983 |
-
makeNoticesDismissible: function()
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
|
999 |
-
|
1000 |
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
});
|
1005 |
});
|
1006 |
});
|
1007 |
-
|
1008 |
-
$el.append( $button );
|
1009 |
});
|
1010 |
-
},
|
1011 |
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
};
|
1016 |
|
1017 |
jQuery(document).ready(function( $ ) {
|
980 |
},
|
981 |
|
982 |
// Make notices dismissible
|
983 |
+
makeNoticesDismissible: function(){
|
984 |
+
jQuery( '.notice.itsec-is-dismissible' ).each( function() {
|
985 |
+
var $el = jQuery( this ),
|
986 |
+
$button = jQuery( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
|
987 |
+
btnText = itsec_page.translations.dismiss || '';
|
988 |
+
|
989 |
+
// Don't rebind twice
|
990 |
+
if ( jQuery( '.notice-dismiss', $el ).length ) {
|
991 |
+
return;
|
992 |
+
}
|
993 |
|
994 |
+
// Ensure plain text
|
995 |
+
$button.find( '.screen-reader-text' ).text( btnText );
|
996 |
+
$button.on( 'click.wp-dismiss-notice', function( event ) {
|
997 |
+
event.preventDefault();
|
998 |
|
999 |
+
$el.trigger( 'itsec-dismiss-notice' );
|
1000 |
|
1001 |
+
$el.fadeTo( 100, 0, function() {
|
1002 |
+
$el.slideUp( 100, function() {
|
1003 |
+
$el.remove();
|
|
|
1004 |
});
|
1005 |
});
|
|
|
|
|
1006 |
});
|
|
|
1007 |
|
1008 |
+
$el.append( $button );
|
1009 |
+
});
|
1010 |
+
}
|
1011 |
};
|
1012 |
|
1013 |
jQuery(document).ready(function( $ ) {
|
core/admin-pages/js/settings.js
CHANGED
@@ -824,38 +824,34 @@ var itsecSettingsPage = {
|
|
824 |
},
|
825 |
|
826 |
// Make notices dismissible
|
827 |
-
makeNoticesDismissible: function()
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
|
843 |
-
|
844 |
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
});
|
849 |
});
|
850 |
});
|
851 |
-
|
852 |
-
$el.append( $button );
|
853 |
});
|
854 |
-
},
|
855 |
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
};
|
860 |
|
861 |
jQuery(document).ready(function( $ ) {
|
824 |
},
|
825 |
|
826 |
// Make notices dismissible
|
827 |
+
makeNoticesDismissible: function(){
|
828 |
+
jQuery( '.notice.itsec-is-dismissible' ).each( function() {
|
829 |
+
var $el = jQuery( this ),
|
830 |
+
$button = jQuery( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
|
831 |
+
btnText = itsec_page.translations.dismiss || '';
|
832 |
+
|
833 |
+
// Don't rebind twice
|
834 |
+
if ( jQuery( '.notice-dismiss', $el ).length ) {
|
835 |
+
return;
|
836 |
+
}
|
837 |
|
838 |
+
// Ensure plain text
|
839 |
+
$button.find( '.screen-reader-text' ).text( btnText );
|
840 |
+
$button.on( 'click.wp-dismiss-notice', function( event ) {
|
841 |
+
event.preventDefault();
|
842 |
|
843 |
+
$el.trigger( 'itsec-dismiss-notice' );
|
844 |
|
845 |
+
$el.fadeTo( 100, 0, function() {
|
846 |
+
$el.slideUp( 100, function() {
|
847 |
+
$el.remove();
|
|
|
848 |
});
|
849 |
});
|
|
|
|
|
850 |
});
|
|
|
851 |
|
852 |
+
$el.append( $button );
|
853 |
+
});
|
854 |
+
}
|
855 |
};
|
856 |
|
857 |
jQuery(document).ready(function( $ ) {
|
core/admin-pages/js/util.js
CHANGED
@@ -166,42 +166,6 @@ var itsecUtil = {
|
|
166 |
}
|
167 |
// If the requested parameter doesn't exist, return false
|
168 |
return false;
|
169 |
-
}
|
170 |
-
|
171 |
-
buildNotices: function ( response, asAlt ) {
|
172 |
-
var notices = [],
|
173 |
-
types = ['error', 'warning', 'message', 'info'];
|
174 |
-
|
175 |
-
for ( var i = 0; i < types.length; i++ ) {
|
176 |
-
for ( var j = 0; j < response[types[i] + 's'].length; j++ ) {
|
177 |
-
notices.push( itsecUtil.makeNotice( response[types[i] + 's'][j], types[i], asAlt ) );
|
178 |
-
}
|
179 |
-
}
|
180 |
-
|
181 |
-
return notices;
|
182 |
-
},
|
183 |
-
|
184 |
-
makeNotice: function ( message, type, asAlt ) {
|
185 |
-
type = type === 'message' ? 'success' : type;
|
186 |
|
187 |
-
var className = 'notice notice-' + type;
|
188 |
-
|
189 |
-
if ( asAlt ) {
|
190 |
-
className += ' notice-alt';
|
191 |
-
}
|
192 |
-
|
193 |
-
return jQuery( '<div>', { class: className } )
|
194 |
-
.append( jQuery( '<p>', { html: message } ) );
|
195 |
-
},
|
196 |
-
|
197 |
-
displayNotices: function ( response, $container, asAlt ) {
|
198 |
-
var notices = itsecUtil.buildNotices( response, asAlt );
|
199 |
-
|
200 |
-
for ( var i = 0; i < notices.length; i++ ) {
|
201 |
-
(function ( $notice ) {
|
202 |
-
$container.append( $notice );
|
203 |
-
setTimeout( function () {$notice.remove();}, 10000 );
|
204 |
-
})( notices[i].clone() );
|
205 |
-
}
|
206 |
-
},
|
207 |
};
|
166 |
}
|
167 |
// If the requested parameter doesn't exist, return false
|
168 |
return false;
|
169 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
};
|
core/admin-pages/logs-list-table.php
CHANGED
@@ -110,17 +110,12 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
110 |
return;
|
111 |
}
|
112 |
|
113 |
-
if (
|
114 |
-
$
|
115 |
-
$data = array();
|
116 |
} else {
|
117 |
-
|
118 |
-
$data = explode( ',', $data );
|
119 |
}
|
120 |
|
121 |
-
$vars = apply_filters( "itsec_logs_prepare_{$item['module']}_filter_row_action_for_{$column_name}", array( 'filters' => "{$column_name}|{$item[ $column_name ]}"), $item, $code, $data );
|
122 |
-
$url = $this->get_self_link( $vars );
|
123 |
-
|
124 |
$out = ' <a class="dashicons dashicons-filter" href="' . esc_url( $url ) . '" title="' . sprintf( esc_attr__( 'Show only entries for this %s', 'better-wp-security' ), strtolower( $column_header ) ) . '"> </a>';
|
125 |
|
126 |
if ( 'module' === $column_name ) {
|
@@ -273,18 +268,9 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
273 |
$hidden_fields = array( 'id' );
|
274 |
$sortable_columns = $this->get_sortable_columns();
|
275 |
|
276 |
-
if ( isset( $_GET['orderby'], $_GET['order'] )
|
277 |
-
|
278 |
-
|
279 |
-
} else {
|
280 |
-
$sort_by_column = 'timestamp';
|
281 |
-
}
|
282 |
-
|
283 |
-
if ( in_array( strtoupper( $_GET['order'] ), array( 'DESC', 'ASC' ) ) ) {
|
284 |
-
$sort_direction = strtoupper( $_GET['order'] );
|
285 |
-
} else {
|
286 |
-
$sort_direction = 'DESC';
|
287 |
-
}
|
288 |
} else {
|
289 |
$sort_by_column = 'timestamp';
|
290 |
$sort_direction = 'DESC';
|
@@ -377,7 +363,7 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
377 |
$current = $this->get_current_view();
|
378 |
|
379 |
foreach ( $views as $type => $description ) {
|
380 |
-
$url =
|
381 |
|
382 |
if ( $current === $type ) {
|
383 |
$description = '<a href="' . esc_url( $url ) . '" class="current" aria-current="page">' . $description . '</a>';
|
@@ -414,79 +400,28 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
414 |
}
|
415 |
|
416 |
protected function extra_tablenav( $which ) {
|
|
|
417 |
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
?>
|
422 |
-
<div class="alignleft actions">
|
423 |
-
<?php if ( 'top' === $which ): ?>
|
424 |
-
<label for="itsec-module-filter" class="screen-reader-text"><?php esc_html_e( 'Filter by Module', 'better-wp-security' ) ?></label>
|
425 |
-
<select name="filters[]" id="itsec-module-filter">
|
426 |
-
<option value=""><?php esc_html_e( 'All Modules', 'better-wp-security' ); ?></option>
|
427 |
-
<?php foreach ( $this->get_modules() as $module => $label ): ?>
|
428 |
-
<option value="module|<?php echo esc_attr( $module ) ?>" <?php selected( $module, $current ); ?>>
|
429 |
-
<?php echo $label; // Expected to be escaped by modules. ?>
|
430 |
-
</option>
|
431 |
-
<?php endforeach; ?>
|
432 |
-
</select>
|
433 |
-
|
434 |
-
<?php submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'itsec-logs-query-submit' ) ); ?>
|
435 |
-
|
436 |
-
<?php if ( isset( $filters['type'] ) ): ?>
|
437 |
-
<input type="hidden" name="filters[]" value="type|<?php echo esc_attr( $filters['type'] ); ?>">
|
438 |
-
<?php endif; ?>
|
439 |
-
<?php endif; ?>
|
440 |
-
</div>
|
441 |
-
<?php
|
442 |
-
}
|
443 |
-
|
444 |
-
public function no_items() {
|
445 |
-
esc_html_e( 'No events.', 'better-wp-security' );
|
446 |
-
}
|
447 |
-
|
448 |
-
private function get_modules() {
|
449 |
-
$columns = implode(', ', array(
|
450 |
-
'id',
|
451 |
-
'parent_id',
|
452 |
-
'module',
|
453 |
-
'type',
|
454 |
-
'code',
|
455 |
-
'timestamp',
|
456 |
-
'init_timestamp',
|
457 |
-
'remote_ip',
|
458 |
-
'user_id',
|
459 |
-
'url',
|
460 |
-
'memory_current',
|
461 |
-
'memory_peak',
|
462 |
-
) );
|
463 |
-
|
464 |
-
global $wpdb;
|
465 |
|
466 |
-
|
467 |
|
468 |
-
|
469 |
-
|
|
|
|
|
470 |
}
|
471 |
|
472 |
-
$
|
473 |
-
|
474 |
-
|
475 |
-
if ( false === strpos( $item['code'], '::' ) ) {
|
476 |
-
$code = $item['code'];
|
477 |
-
$data = array();
|
478 |
-
} else {
|
479 |
-
list( $code, $data ) = explode( '::', $item['code'], 2 );
|
480 |
-
$data = explode( ',', $data );
|
481 |
-
}
|
482 |
|
483 |
-
|
484 |
-
|
485 |
-
$item = apply_filters( "itsec_logs_prepare_{$item['module']}_entry_for_list_display", $item, $code, $data );
|
486 |
-
|
487 |
-
$modules[ $item['module'] ] = $item['module_display'];
|
488 |
-
}
|
489 |
|
490 |
-
|
|
|
491 |
}
|
492 |
}
|
110 |
return;
|
111 |
}
|
112 |
|
113 |
+
if ( 'four_oh_four' === $item['module'] && 'code' === $column_name ) {
|
114 |
+
$url = self::get_self_link( array( 'filters[10]' => "url|{$item['url']}", 'filters[11]' => 'module|four_oh_four' ) );
|
|
|
115 |
} else {
|
116 |
+
$url = self::get_self_link( array( 'filters' => "$column_name|{$item[$column_name]}" ) );
|
|
|
117 |
}
|
118 |
|
|
|
|
|
|
|
119 |
$out = ' <a class="dashicons dashicons-filter" href="' . esc_url( $url ) . '" title="' . sprintf( esc_attr__( 'Show only entries for this %s', 'better-wp-security' ), strtolower( $column_header ) ) . '"> </a>';
|
120 |
|
121 |
if ( 'module' === $column_name ) {
|
268 |
$hidden_fields = array( 'id' );
|
269 |
$sortable_columns = $this->get_sortable_columns();
|
270 |
|
271 |
+
if ( isset( $_GET['orderby'], $_GET['order'] ) ) {
|
272 |
+
$sort_by_column = $_GET['orderby'];
|
273 |
+
$sort_direction = $_GET['order'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
} else {
|
275 |
$sort_by_column = 'timestamp';
|
276 |
$sort_direction = 'DESC';
|
363 |
$current = $this->get_current_view();
|
364 |
|
365 |
foreach ( $views as $type => $description ) {
|
366 |
+
$url = self::get_self_link( array( 'filters' => "type|$type" ), array() );
|
367 |
|
368 |
if ( $current === $type ) {
|
369 |
$description = '<a href="' . esc_url( $url ) . '" class="current" aria-current="page">' . $description . '</a>';
|
400 |
}
|
401 |
|
402 |
protected function extra_tablenav( $which ) {
|
403 |
+
echo '<div class="alignleft actions">';
|
404 |
|
405 |
+
if ( 'top' === $which ) {
|
406 |
+
/*
|
407 |
+
ob_start();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
|
409 |
+
$output = ob_get_clean();
|
410 |
|
411 |
+
if ( ! empty( $output ) ) {
|
412 |
+
echo $output;
|
413 |
+
submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
|
414 |
+
}*/
|
415 |
}
|
416 |
|
417 |
+
/* if ( $this->is_trash && current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts ) && $this->has_items() ) {
|
418 |
+
submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false );
|
419 |
+
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
|
421 |
+
echo '</div>';
|
422 |
+
}
|
|
|
|
|
|
|
|
|
423 |
|
424 |
+
public function no_items() {
|
425 |
+
esc_html_e( 'No events.', 'better-wp-security' );
|
426 |
}
|
427 |
}
|
core/admin-pages/page-debug.php
DELETED
@@ -1,425 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
final class ITSEC_Debug_Page {
|
4 |
-
|
5 |
-
/** @var string */
|
6 |
-
private $self_url;
|
7 |
-
|
8 |
-
public function __construct() {
|
9 |
-
add_action( 'itsec-page-show', array( $this, 'handle_page_load' ) );
|
10 |
-
add_action( 'itsec-page-ajax', array( $this, 'handle_ajax_request' ) );
|
11 |
-
add_action( 'admin_print_scripts', array( $this, 'add_scripts' ) );
|
12 |
-
add_action( 'admin_print_styles', array( $this, 'add_styles' ) );
|
13 |
-
|
14 |
-
ITSEC_Modules::load_module_file( 'debug.php', ':active' );
|
15 |
-
}
|
16 |
-
|
17 |
-
public function handle_page_load( $self_url ) {
|
18 |
-
$this->self_url = $self_url;
|
19 |
-
|
20 |
-
$this->show_settings_page();
|
21 |
-
}
|
22 |
-
|
23 |
-
public function add_scripts() {
|
24 |
-
|
25 |
-
$deps = array( 'itsec-util' );
|
26 |
-
|
27 |
-
if ( function_exists( 'wp_enqueue_code_editor' ) ) {
|
28 |
-
$deps[] = 'code-editor';
|
29 |
-
wp_enqueue_code_editor( array(
|
30 |
-
'type' => 'application/json'
|
31 |
-
) );
|
32 |
-
}
|
33 |
-
|
34 |
-
ITSEC_Lib::enqueue_util( array( 'action' => 'itsec_debug_page', 'nonce' => 'itsec-debug-page' ) );
|
35 |
-
wp_enqueue_script( 'itsec-debug', plugins_url( 'js/debug.js', __FILE__ ), $deps, ITSEC_Core::get_plugin_build() );
|
36 |
-
|
37 |
-
do_action( 'itsec_debug_page_enqueue' );
|
38 |
-
}
|
39 |
-
|
40 |
-
public function add_styles() {
|
41 |
-
wp_enqueue_style( 'itsec-debug-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
|
42 |
-
}
|
43 |
-
|
44 |
-
public function handle_ajax_request() {
|
45 |
-
if ( WP_DEBUG ) {
|
46 |
-
ini_set( 'display_errors', 1 );
|
47 |
-
}
|
48 |
-
|
49 |
-
ITSEC_Core::set_interactive( true );
|
50 |
-
|
51 |
-
$method = ( isset( $_POST['method'] ) && is_string( $_POST['method'] ) ) ? $_POST['method'] : '';
|
52 |
-
$module = ( isset( $_POST['module'] ) && is_string( $_POST['module'] ) ) ? $_POST['module'] : '';
|
53 |
-
|
54 |
-
if ( empty( $GLOBALS['hook_suffix'] ) ) {
|
55 |
-
$GLOBALS['hook_suffix'] = 'security_page_itsec-debug';
|
56 |
-
}
|
57 |
-
|
58 |
-
if ( false === check_ajax_referer( 'itsec-debug-page', 'nonce', false ) ) {
|
59 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-failed-nonce', __( 'A nonce security check failed, preventing the request from completing as expected. Please try reloading the page and trying again.', 'better-wp-security' ) ) );
|
60 |
-
} elseif ( ! ITSEC_Core::current_user_can_manage() ) {
|
61 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-insufficient-privileges', __( 'A permissions security check failed, preventing the request from completing as expected. The currently logged in user does not have sufficient permissions to make this request. Please try reloading the page and trying again.', 'better-wp-security' ) ) );
|
62 |
-
} elseif ( empty( $method ) ) {
|
63 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-missing-method', __( 'The server did not receive a valid request. The required "method" argument is missing. Please try again.', 'better-wp-security' ) ) );
|
64 |
-
} elseif ( 'handle_module_request' === $method && empty( $module ) ) {
|
65 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-missing-module', __( 'The server did not receive a valid request. The required "module" argument is missing. Please try again.', 'better-wp-security' ) ) );
|
66 |
-
} elseif ( 'handle_module_request' === $method ) {
|
67 |
-
if ( isset( $_POST['data'] ) ) {
|
68 |
-
ITSEC_Modules::load_module_file( 'debug.php', ':active' );
|
69 |
-
/**
|
70 |
-
* Fires when an ajax request is being made to a module.
|
71 |
-
*
|
72 |
-
* At some point this will probably be replaced by a more thought-out framework, but this hook will probably power it.
|
73 |
-
*
|
74 |
-
* The dynamic portion of this hook, {$module}, refers to the module name. For example, 'notification-center'.
|
75 |
-
*
|
76 |
-
* @param array $data
|
77 |
-
*/
|
78 |
-
do_action( "itsec_debug_module_request_{$module}", $_POST['data'] );
|
79 |
-
} else {
|
80 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-module-request-missing-data', __( 'The server did not receive a valid request. The required "data" argument for the module is missing. Please try again.', 'better-wp-security' ) ) );
|
81 |
-
}
|
82 |
-
} elseif ( 'reset_scheduler' === $method ) {
|
83 |
-
ITSEC_Core::get_scheduler()->uninstall();
|
84 |
-
ITSEC_Core::get_scheduler()->register_events();
|
85 |
-
ITSEC_Response::set_response( $this->get_events_table() );
|
86 |
-
ITSEC_Response::set_success( true );
|
87 |
-
ITSEC_Response::add_message( __( 'Scheduler reset.', 'better-wp-security' ) );
|
88 |
-
} elseif ( 'run_event' === $method ) {
|
89 |
-
if ( empty( $_POST['data']['id'] ) ) {
|
90 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-run-event-missing-id', __( 'The server did not receive a valid request. The required "data.id" argument for the "run_event" method is missing.', 'better-wp-security' ) ) );
|
91 |
-
} elseif ( ! empty( $_POST['data']['data'] ) ) {
|
92 |
-
$hash = $_POST['data']['data'];
|
93 |
-
|
94 |
-
if ( ! is_string( $hash ) ) {
|
95 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-run-event-invalid-data', __( 'The server did not receive a valid request. The "data.data" argument for the "run_event" method is an invalid string.', 'better-wp-security' ) ) );
|
96 |
-
} else {
|
97 |
-
ITSEC_Core::get_scheduler()->run_single_event_by_hash( $_POST['data']['id'], $hash );
|
98 |
-
ITSEC_Response::set_response( $this->get_events_table() );
|
99 |
-
ITSEC_Response::set_success( true );
|
100 |
-
ITSEC_Response::add_message( __( 'Event successfully run.', 'better-wp-security' ) );
|
101 |
-
}
|
102 |
-
} else {
|
103 |
-
ITSEC_Core::get_scheduler()->run_recurring_event( $_POST['data']['id'] );
|
104 |
-
ITSEC_Response::set_response( $this->get_events_table() );
|
105 |
-
ITSEC_Response::set_success( true );
|
106 |
-
ITSEC_Response::add_message( __( 'Event successfully run.', 'better-wp-security' ) );
|
107 |
-
}
|
108 |
-
} elseif ( 'load_settings' === $method ) {
|
109 |
-
ITSEC_Response::set_response( ITSEC_Modules::get_settings( $module ) );
|
110 |
-
} elseif ( 'save_settings' === $method ) {
|
111 |
-
$data = json_decode( wp_unslash( $_POST['data'] ), true );
|
112 |
-
|
113 |
-
if ( ! is_array( $data ) ) {
|
114 |
-
ITSEC_Response::set_success( false );
|
115 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-run-event-invalid-data', __( 'The server did not receive a valid request. The "data" argument for the "save_settings" method is invalid.', 'better-wp-security' ) ) );
|
116 |
-
} else {
|
117 |
-
$result = ITSEC_Modules::set_settings( $module, $data );
|
118 |
-
|
119 |
-
if ( is_wp_error( $result ) ) {
|
120 |
-
ITSEC_Response::set_success( false );
|
121 |
-
ITSEC_Response::add_error( $result );
|
122 |
-
} else {
|
123 |
-
ITSEC_Response::set_response( ITSEC_Modules::get_settings( $module ) );
|
124 |
-
|
125 |
-
if ( $result['saved'] ) {
|
126 |
-
ITSEC_Response::add_message( esc_html__( 'Module settings updated.', 'better-wp-security' ) );
|
127 |
-
}
|
128 |
-
}
|
129 |
-
}
|
130 |
-
} else {
|
131 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-unknown-method', __( 'The server did not receive a valid request. An unknown "method" argument was supplied. Please try again.', 'better-wp-security' ) ) );
|
132 |
-
}
|
133 |
-
|
134 |
-
ITSEC_Response::send_json();
|
135 |
-
}
|
136 |
-
|
137 |
-
private function show_settings_page() {
|
138 |
-
|
139 |
-
$sysinfo = $this->get_sysinfo();
|
140 |
-
|
141 |
-
$out = '';
|
142 |
-
|
143 |
-
foreach ( $sysinfo as $category => $info ) {
|
144 |
-
if ( $out ) {
|
145 |
-
$out .= "\r\n";
|
146 |
-
}
|
147 |
-
|
148 |
-
$out .= "### {$category} ###\r\n";
|
149 |
-
|
150 |
-
foreach ( $info as $label => $value ) {
|
151 |
-
$out .= "{$label}: {$value}\r\n";
|
152 |
-
}
|
153 |
-
}
|
154 |
-
|
155 |
-
$out = rtrim( $out );
|
156 |
-
|
157 |
-
$scheduler = ITSEC_Core::get_scheduler();
|
158 |
-
|
159 |
-
$modules = array();
|
160 |
-
|
161 |
-
foreach ( ITSEC_Modules::get_available_modules() as $module ) {
|
162 |
-
if ( ITSEC_Modules::get_settings_obj( $module ) ) {
|
163 |
-
$modules[ $module ] = $module;
|
164 |
-
}
|
165 |
-
}
|
166 |
-
|
167 |
-
sort( $modules );
|
168 |
-
?>
|
169 |
-
<div class="wrap">
|
170 |
-
<h1>
|
171 |
-
<?php _e( 'iThemes Security', 'better-wp-security' ); ?>
|
172 |
-
<a href="<?php echo esc_url( ITSEC_Core::get_settings_page_url() ); ?>" class="page-title-action"><?php _e( 'Manage Settings', 'better-wp-security' ); ?></a>
|
173 |
-
<a href="<?php echo esc_url( apply_filters( 'itsec_support_url', 'https://wordpress.org/support/plugin/better-wp-security' ) ); ?>" class="page-title-action">
|
174 |
-
<?php _e( 'Support', 'better-wp-security' ); ?>
|
175 |
-
</a>
|
176 |
-
</h1>
|
177 |
-
|
178 |
-
<div id="itsec-messages"></div>
|
179 |
-
|
180 |
-
<div>
|
181 |
-
<h2><?php esc_html_e( 'System Info', 'better-wp-security' ); ?></h2>
|
182 |
-
<label for="itsec-system-info"><?php esc_html__( 'System Info Summary', 'better-wp-security' ); ?></label>
|
183 |
-
<textarea readonly id="itsec-system-info"><?php echo esc_textarea( $out ); ?></textarea>
|
184 |
-
</div>
|
185 |
-
|
186 |
-
<div>
|
187 |
-
<h2><?php esc_html_e( 'Settings', 'better-wp-security' ); ?></h2>
|
188 |
-
<p>
|
189 |
-
<label for="itsec-settings-module" class="screen-reader-text"><?php esc_html_e( 'Module', 'better-wp-security' ); ?></label>
|
190 |
-
<select id="itsec-settings-module">
|
191 |
-
<?php foreach ( $modules as $module ) : ?>
|
192 |
-
<option value="<?php echo esc_attr( $module ); ?>"><?php echo esc_html( $module ); ?></option>
|
193 |
-
<?php endforeach; ?>
|
194 |
-
</select>
|
195 |
-
<button class="button" id="itsec-settings-load"><?php esc_html_e( 'Load', 'better-wp-security' ); ?></button>
|
196 |
-
<button class="button" id="itsec-settings-save" disabled><?php esc_html_e( 'Save', 'better-wp-security' ) ?></button>
|
197 |
-
</p>
|
198 |
-
<label for="itsec-settings-editor" class="screen-reader-text"><?php esc_html_e( 'Edit Settings', 'better-wp-security' ); ?></label>
|
199 |
-
<textarea id="itsec-settings-editor"></textarea>
|
200 |
-
</div>
|
201 |
-
|
202 |
-
<div id="itsec-scheduler-events">
|
203 |
-
<h2><?php esc_html_e( 'Scheduler', 'better-wp-security' ); ?></h2>
|
204 |
-
<?php echo $this->get_events_table(); ?>
|
205 |
-
<p style="text-align: right;">
|
206 |
-
<code><?php echo get_class( $scheduler ); ?></code>
|
207 |
-
<button class="button" id="itsec-scheduler-reset"><?php esc_html_e( 'Reset', 'better-wp-security' ) ?></button>
|
208 |
-
</p>
|
209 |
-
</div>
|
210 |
-
|
211 |
-
<?php do_action( 'itsec_debug_page' ); ?>
|
212 |
-
</div>
|
213 |
-
<?php
|
214 |
-
}
|
215 |
-
|
216 |
-
private function get_events_table() {
|
217 |
-
$scheduler = ITSEC_Core::get_scheduler();
|
218 |
-
ob_start();
|
219 |
-
|
220 |
-
?>
|
221 |
-
|
222 |
-
<table class="widefat striped">
|
223 |
-
<thead>
|
224 |
-
<tr>
|
225 |
-
<th><?php esc_html_e( 'ID', 'better-wp-security' ) ?></th>
|
226 |
-
<th><?php esc_html_e( 'Fire At', 'better-wp-security' ) ?></th>
|
227 |
-
<th><?php esc_html_e( 'Schedule', 'better-wp-security' ) ?></th>
|
228 |
-
<th><button class="button-link" id="itsec-events-data-toggle"><?php esc_html_e( 'Data', 'better-wp-security' ) ?></button></th>
|
229 |
-
<th></th>
|
230 |
-
</tr>
|
231 |
-
</thead>
|
232 |
-
<tbody>
|
233 |
-
<?php foreach ( array_merge( $scheduler->get_recurring_events(), $scheduler->get_single_events() ) as $event ) : ?>
|
234 |
-
<tr>
|
235 |
-
<td><?php echo esc_html( $event['id'] ); ?></td>
|
236 |
-
<td><?php echo date( 'Y-m-d H:i:s', $event['fire_at'] ); ?> (<?php echo esc_html( human_time_diff( $event['fire_at'] ) ) ?>)</td>
|
237 |
-
<td><?php echo isset( $event['schedule'] ) ? $event['schedule'] : '–'; ?></td>
|
238 |
-
<td><div class="hidden itsec-events-data"><?php $event['data'] ? ITSEC_Lib::print_r( $event['data'] ) : print( '–' ); ?></div></td>
|
239 |
-
<td>
|
240 |
-
<button class="button" data-id="<?php echo esc_attr( $event['id'] ); ?>"
|
241 |
-
data-data="<?php echo isset( $event['schedule'] ) ? '' : esc_attr( $event['hash'] ); ?>">
|
242 |
-
<?php esc_html_e( 'Run', 'better-wp-security' ) ?>
|
243 |
-
</button>
|
244 |
-
</td>
|
245 |
-
</tr>
|
246 |
-
<?php endforeach; ?>
|
247 |
-
</tbody>
|
248 |
-
</table>
|
249 |
-
|
250 |
-
<?php
|
251 |
-
|
252 |
-
return ob_get_clean();
|
253 |
-
}
|
254 |
-
|
255 |
-
private function get_sysinfo() {
|
256 |
-
|
257 |
-
/** @var $wpdb wpdb */
|
258 |
-
global $wpdb;
|
259 |
-
|
260 |
-
$info = array();
|
261 |
-
|
262 |
-
$info['Site Info'] = array(
|
263 |
-
'Site URL' => site_url(),
|
264 |
-
'Home URL' => home_url(),
|
265 |
-
'Multisite' => is_multisite() ? 'Yes' : 'No'
|
266 |
-
);
|
267 |
-
|
268 |
-
$wp_config = array(
|
269 |
-
'Version' => get_bloginfo( 'version' ),
|
270 |
-
'Language' => defined( 'WPLANG' ) && WPLANG ? WPLANG : 'en_US',
|
271 |
-
'Permalink' => get_option( 'permalink_structure' ) ? get_option( 'permalink_structure' ) : 'Default',
|
272 |
-
'Theme' => wp_get_theme()->Name . ' ' . wp_get_theme()->Version,
|
273 |
-
'Show on Front' => get_option( 'show_on_front' )
|
274 |
-
);
|
275 |
-
|
276 |
-
if ( get_option( 'show_on_front' ) === 'page' ) {
|
277 |
-
$front_page_id = get_option( 'page_on_front' );
|
278 |
-
$blog_page_id = get_option( 'page_for_posts' );
|
279 |
-
|
280 |
-
$wp_config['Page On Front'] = $front_page_id ? get_the_title( $front_page_id ) . " (#$front_page_id)" : 'Unset';
|
281 |
-
$wp_config['Page For Posts'] = $blog_page_id ? get_the_title( $blog_page_id ) . " (#$blog_page_id)" : 'Unset';
|
282 |
-
}
|
283 |
-
|
284 |
-
$wp_config['ABSPATH'] = ABSPATH;
|
285 |
-
$wp_config['Table Prefix'] = 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'Too long' : 'Acceptable' );
|
286 |
-
$wp_config['WP_DEBUG'] = defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' : 'Disabled' : 'Not set';
|
287 |
-
$wp_config['WP_DEBUG_LOG'] = defined( 'WP_DEBUG_LOG' ) ? WP_DEBUG_LOG ? 'Enabled' : 'Disabled' : 'Not set';
|
288 |
-
$wp_config['SCRIPT_DEBUG'] = defined( 'SCRIPT_DEBUG' ) ? SCRIPT_DEBUG ? 'Enabled' : 'Disabled' : 'Not set';
|
289 |
-
$wp_config['Object Cache'] = wp_using_ext_object_cache() ? 'Yes' : 'No';
|
290 |
-
$wp_config['Memory Limit'] = WP_MEMORY_LIMIT;
|
291 |
-
$info['WordPress Configuration'] = $wp_config;
|
292 |
-
|
293 |
-
$defines = array(
|
294 |
-
'ITSEC_USE_CRON',
|
295 |
-
'ITSEC_DISABLE_PASSWORD_REQUIREMENTS',
|
296 |
-
'ITSEC_DEVELOPMENT',
|
297 |
-
'ITSEC_DISABLE_MODULES',
|
298 |
-
'ITSEC_DISABLE_TWO_FACTOR',
|
299 |
-
'ITSEC_DISABLE_CRON_TEST',
|
300 |
-
'ITSEC_SERVER_OVERRIDE',
|
301 |
-
'ITSEC_DOING_FILE_CHECK',
|
302 |
-
'ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE',
|
303 |
-
'ITSEC_TEST_MALWARE_SCAN_SITE_URL',
|
304 |
-
'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSL_VERIFY',
|
305 |
-
'ITSEC_SUCURI_KEY',
|
306 |
-
'ITSEC_NOTIFY_USE_CRON',
|
307 |
-
'ITSEC_DISABLE_SECURITY_CHECK_PRO',
|
308 |
-
'ITSEC_DISABLE_AUTOMATIC_REMOTE_IP_DETECTION',
|
309 |
-
'ITSEC_DISABLE_PASSWORD_STRENGTH',
|
310 |
-
'ITSEC_DISABLE_INACTIVE_USER_CHECK',
|
311 |
-
);
|
312 |
-
|
313 |
-
$info['iThemes Security'] = array(
|
314 |
-
'Build' => ITSEC_Core::get_plugin_build(),
|
315 |
-
'Pro' => ITSEC_Core::is_pro(),
|
316 |
-
'Modules' => wp_sprintf( '%l', ITSEC_Modules::get_active_modules() ),
|
317 |
-
'Cron' => ITSEC_Lib::use_cron(),
|
318 |
-
'Cron Status' => ITSEC_Lib::is_cron_working(),
|
319 |
-
'Scheduler' => get_class( ITSEC_Core::get_scheduler() ),
|
320 |
-
);
|
321 |
-
|
322 |
-
foreach ( $defines as $define ) {
|
323 |
-
if ( defined( $define ) ) {
|
324 |
-
$value = constant( $define );
|
325 |
-
$info['iThemes Security'][ $define ] = $value === true ? 'Enabled' : $value === false ? 'Disabled' : $value;
|
326 |
-
}
|
327 |
-
}
|
328 |
-
|
329 |
-
$plugins = get_plugins();
|
330 |
-
$active_plugins = get_option( 'active_plugins', array() );
|
331 |
-
|
332 |
-
foreach ( $plugins as $plugin_path => $plugin ) {
|
333 |
-
|
334 |
-
if ( ! in_array( $plugin_path, $active_plugins, true ) ) {
|
335 |
-
continue;
|
336 |
-
}
|
337 |
-
|
338 |
-
$info['Active Plugins'][ $plugin['Name'] ] = $plugin['Version'];
|
339 |
-
}
|
340 |
-
|
341 |
-
foreach ( get_mu_plugins() as $plugin ) {
|
342 |
-
$info['MU Plugins'][ $plugin['Name'] ] = $plugin['Version'];
|
343 |
-
}
|
344 |
-
|
345 |
-
if ( is_multisite() ) {
|
346 |
-
$plugins = wp_get_active_network_plugins();
|
347 |
-
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
348 |
-
|
349 |
-
foreach ( $plugins as $plugin_path ) {
|
350 |
-
|
351 |
-
$plugin_base = plugin_basename( $plugin_path );
|
352 |
-
|
353 |
-
if ( ! array_key_exists( $plugin_base, $active_plugins ) ) {
|
354 |
-
continue;
|
355 |
-
}
|
356 |
-
|
357 |
-
$plugin = get_plugin_data( $plugin_path );
|
358 |
-
|
359 |
-
$info['Network Active Plugins'][ $plugin['Name'] ] = $plugin['Version'];
|
360 |
-
}
|
361 |
-
}
|
362 |
-
|
363 |
-
$info['Webserver Configuration'] = array(
|
364 |
-
'PHP Version' => PHP_VERSION,
|
365 |
-
'MySQL Version' => $wpdb->db_version(),
|
366 |
-
'Use MySQLi' => $wpdb->use_mysqli ? 'Yes' : 'No',
|
367 |
-
'Webserver Info' => ITSEC_Lib::get_server(),
|
368 |
-
'Host' => $this->get_host(),
|
369 |
-
);
|
370 |
-
|
371 |
-
$info['PHP Configuration'] = array(
|
372 |
-
'Safe Mode' => ini_get( 'safe_mode' ) ? 'Enabled' : 'Disabled',
|
373 |
-
'Memory Limit' => ini_get( 'memory_limit' ),
|
374 |
-
'Upload Max Size' => ini_get( 'upload_max_filesize' ),
|
375 |
-
'Post Max Size' => ini_get( 'post_max_size' ),
|
376 |
-
'Upload Max Filesize' => ini_get( 'upload_max_filesize' ),
|
377 |
-
'Time Limit' => ini_get( 'max_execution_time' ),
|
378 |
-
'Max Input Vars' => ini_get( 'max_input_vars' ),
|
379 |
-
'Display Errors' => ini_get( 'display_errors' ) ? 'On (' . ini_get( 'display_errors' ) . ')' : 'N/A'
|
380 |
-
);
|
381 |
-
|
382 |
-
$info['PHP Extensions'] = array(
|
383 |
-
'cURL' => function_exists( 'curl_init' ) ? 'Supported' : 'Not Supported',
|
384 |
-
'fsockopen' => function_exists( 'fsockopen' ) ? 'Supported' : 'Not Supported',
|
385 |
-
'SOAP Client' => class_exists( 'SoapClient' ) ? 'Installed' : 'Not Installed',
|
386 |
-
'Suhosin' => extension_loaded( 'suhosin' ) ? 'Installed' : 'Not Installed'
|
387 |
-
);
|
388 |
-
|
389 |
-
return $info;
|
390 |
-
}
|
391 |
-
|
392 |
-
private function get_host() {
|
393 |
-
|
394 |
-
if ( defined( 'WPE_APIKEY' ) ) {
|
395 |
-
$host = 'WP Engine';
|
396 |
-
} elseif ( defined( 'PAGELYBIN' ) ) {
|
397 |
-
$host = 'Pagely';
|
398 |
-
} elseif ( DB_HOST === 'localhost:/tmp/mysql5.sock' ) {
|
399 |
-
$host = 'ICDSoft';
|
400 |
-
} elseif ( DB_HOST === 'mysqlv5' ) {
|
401 |
-
$host = 'NetworkSolutions';
|
402 |
-
} elseif ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
|
403 |
-
$host = 'iPage';
|
404 |
-
} elseif ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
|
405 |
-
$host = 'IPower';
|
406 |
-
} elseif ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
|
407 |
-
$host = 'MediaTemple Grid';
|
408 |
-
} elseif ( strpos( DB_HOST, '.pair.com' ) !== false ) {
|
409 |
-
$host = 'pair Networks';
|
410 |
-
} elseif ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
|
411 |
-
$host = 'Rackspace Cloud';
|
412 |
-
} elseif ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
|
413 |
-
$host = 'SysFix.eu Power Hosting';
|
414 |
-
} elseif ( isset( $_SERVER['SERVER_NAME'] ) && strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
|
415 |
-
$host = 'Flywheel';
|
416 |
-
} else {
|
417 |
-
// Adding a general fallback for data gathering
|
418 |
-
$host = 'DBH/' . DB_HOST . ', SRV/' . ( isset( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : '' );
|
419 |
-
}
|
420 |
-
|
421 |
-
return $host;
|
422 |
-
}
|
423 |
-
}
|
424 |
-
|
425 |
-
new ITSEC_Debug_Page();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/admin-pages/page-logs.php
CHANGED
@@ -37,8 +37,6 @@ final class ITSEC_Logs_Page {
|
|
37 |
}
|
38 |
|
39 |
public function add_scripts() {
|
40 |
-
ITSEC_Lib::enqueue_util();
|
41 |
-
|
42 |
foreach ( $this->modules as $id => $module ) {
|
43 |
$module->enqueue_scripts_and_styles();
|
44 |
}
|
@@ -274,42 +272,34 @@ final class ITSEC_Logs_Page {
|
|
274 |
'module' => array(
|
275 |
'header' => esc_html__( 'Module', 'better-wp-security' ),
|
276 |
'content' => esc_html( $entry['module'] ),
|
277 |
-
'order' => 0,
|
278 |
),
|
279 |
'type' => array(
|
280 |
'header' => esc_html__( 'Type', 'better-wp-security' ),
|
281 |
'content' => $type,
|
282 |
-
'order' => 10,
|
283 |
),
|
284 |
'description' => array(
|
285 |
'header' => esc_html__( 'Description', 'better-wp-security' ),
|
286 |
'content' => esc_html( $code ),
|
287 |
-
'order' => 20,
|
288 |
),
|
289 |
'timestamp' => array(
|
290 |
'header' => esc_html__( 'Timestamp', 'better-wp-security' ),
|
291 |
'content' => esc_html( $datetime ),
|
292 |
-
'order' => 30,
|
293 |
),
|
294 |
'host' => array(
|
295 |
'header' => esc_html__( 'Host', 'better-wp-security' ),
|
296 |
'content' => '<code>' . esc_html( $entry['remote_ip'] ) . '</code>',
|
297 |
-
'order' => 40,
|
298 |
),
|
299 |
'user' => array(
|
300 |
'header' => esc_html__( 'User', 'better-wp-security' ),
|
301 |
'content' => esc_html( $username ),
|
302 |
-
'order' => 50,
|
303 |
),
|
304 |
'url' => array(
|
305 |
'header' => esc_html__( 'URL', 'better-wp-security' ),
|
306 |
'content' => '<code>' . $url . '</code>',
|
307 |
-
'order' => 60,
|
308 |
),
|
309 |
'raw-details' => array(
|
310 |
'header' => esc_html__( 'Raw Details', 'better-wp-security' ),
|
311 |
'content' => true,
|
312 |
-
'order' => PHP_INT_MAX,
|
313 |
),
|
314 |
);
|
315 |
|
@@ -337,17 +327,6 @@ final class ITSEC_Logs_Page {
|
|
337 |
|
338 |
$details['raw-details']['content'] = '<p><a class="itsec-log-raw-details-toggle" href="#">' . $this->translations['show_raw_details'] . '</a></p><div class="itsec-log-raw-details">' . $details['raw-details']['content'] . '</div>';
|
339 |
}
|
340 |
-
|
341 |
-
$i = 1;
|
342 |
-
|
343 |
-
foreach ( $details as $column => $detail ) {
|
344 |
-
if ( ! isset( $detail['order'] ) ) {
|
345 |
-
$details[ $column ]['order'] = PHP_INT_MAX - 10 * $i;
|
346 |
-
$i ++;
|
347 |
-
}
|
348 |
-
}
|
349 |
-
|
350 |
-
$details = wp_list_sort( $details, 'order', 'ASC', true );
|
351 |
}
|
352 |
|
353 |
ob_start();
|
@@ -487,7 +466,6 @@ final class ITSEC_Logs_Page {
|
|
487 |
$list->prepare_items();
|
488 |
$list->views();
|
489 |
$form->start_form( array( 'method' => 'GET' ) );
|
490 |
-
$form->add_hidden( 'page', 'itsec-logs' );
|
491 |
$list->display();
|
492 |
$form->end_form();
|
493 |
?>
|
37 |
}
|
38 |
|
39 |
public function add_scripts() {
|
|
|
|
|
40 |
foreach ( $this->modules as $id => $module ) {
|
41 |
$module->enqueue_scripts_and_styles();
|
42 |
}
|
272 |
'module' => array(
|
273 |
'header' => esc_html__( 'Module', 'better-wp-security' ),
|
274 |
'content' => esc_html( $entry['module'] ),
|
|
|
275 |
),
|
276 |
'type' => array(
|
277 |
'header' => esc_html__( 'Type', 'better-wp-security' ),
|
278 |
'content' => $type,
|
|
|
279 |
),
|
280 |
'description' => array(
|
281 |
'header' => esc_html__( 'Description', 'better-wp-security' ),
|
282 |
'content' => esc_html( $code ),
|
|
|
283 |
),
|
284 |
'timestamp' => array(
|
285 |
'header' => esc_html__( 'Timestamp', 'better-wp-security' ),
|
286 |
'content' => esc_html( $datetime ),
|
|
|
287 |
),
|
288 |
'host' => array(
|
289 |
'header' => esc_html__( 'Host', 'better-wp-security' ),
|
290 |
'content' => '<code>' . esc_html( $entry['remote_ip'] ) . '</code>',
|
|
|
291 |
),
|
292 |
'user' => array(
|
293 |
'header' => esc_html__( 'User', 'better-wp-security' ),
|
294 |
'content' => esc_html( $username ),
|
|
|
295 |
),
|
296 |
'url' => array(
|
297 |
'header' => esc_html__( 'URL', 'better-wp-security' ),
|
298 |
'content' => '<code>' . $url . '</code>',
|
|
|
299 |
),
|
300 |
'raw-details' => array(
|
301 |
'header' => esc_html__( 'Raw Details', 'better-wp-security' ),
|
302 |
'content' => true,
|
|
|
303 |
),
|
304 |
);
|
305 |
|
327 |
|
328 |
$details['raw-details']['content'] = '<p><a class="itsec-log-raw-details-toggle" href="#">' . $this->translations['show_raw_details'] . '</a></p><div class="itsec-log-raw-details">' . $details['raw-details']['content'] . '</div>';
|
329 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
330 |
}
|
331 |
|
332 |
ob_start();
|
466 |
$list->prepare_items();
|
467 |
$list->views();
|
468 |
$form->start_form( array( 'method' => 'GET' ) );
|
|
|
469 |
$list->display();
|
470 |
$form->end_form();
|
471 |
?>
|
core/admin-pages/page-settings.php
CHANGED
@@ -68,8 +68,6 @@ final class ITSEC_Settings_Page {
|
|
68 |
}
|
69 |
|
70 |
public function add_scripts() {
|
71 |
-
ITSEC_Lib::enqueue_util();
|
72 |
-
|
73 |
foreach ( $this->modules as $id => $module ) {
|
74 |
$module->enqueue_scripts_and_styles();
|
75 |
}
|
68 |
}
|
69 |
|
70 |
public function add_scripts() {
|
|
|
|
|
71 |
foreach ( $this->modules as $id => $module ) {
|
72 |
$module->enqueue_scripts_and_styles();
|
73 |
}
|
core/core.php
CHANGED
@@ -24,7 +24,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
24 |
*
|
25 |
* @access private
|
26 |
*/
|
27 |
-
private $plugin_build =
|
28 |
|
29 |
/**
|
30 |
* Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
|
@@ -163,6 +163,13 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
163 |
add_action( 'admin_bar_menu', array( $this, 'modify_admin_bar' ), 99 );
|
164 |
}
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
$login_interstitial = new ITSEC_Lib_Login_Interstitial();
|
167 |
$login_interstitial->run();
|
168 |
|
@@ -321,13 +328,8 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
321 |
}
|
322 |
|
323 |
ITSEC_Modules::register_module( 'network-brute-force', "$path/modules/ipcheck", 'default-active' );
|
324 |
-
|
325 |
-
if ( ! defined( 'ITSEC_DISABLE_PASSWORD_REQUIREMENTS') || ! ITSEC_DISABLE_PASSWORD_REQUIREMENTS ) {
|
326 |
-
ITSEC_Modules::register_module( 'password-requirements', "$path/modules/password-requirements/", 'always-active' );
|
327 |
-
}
|
328 |
-
|
329 |
ITSEC_Modules::register_module( 'ssl', "$path/modules/ssl" );
|
330 |
-
ITSEC_Modules::register_module( 'strong-passwords', "$path/modules/strong-passwords", '
|
331 |
ITSEC_Modules::register_module( 'system-tweaks', "$path/modules/system-tweaks" );
|
332 |
ITSEC_Modules::register_module( 'wordpress-salts', "$path/modules/salts", 'always-active' );
|
333 |
ITSEC_Modules::register_module( 'wordpress-tweaks', "$path/modules/wordpress-tweaks", 'default-active' );
|
@@ -604,21 +606,11 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
604 |
return $url;
|
605 |
}
|
606 |
|
607 |
-
public static function get_logs_page_url( $
|
608 |
$url = network_admin_url( 'admin.php?page=itsec-logs' );
|
609 |
|
610 |
-
|
611 |
-
|
612 |
-
if ( $module ) {
|
613 |
-
$filters[] = rawurlencode("module|{$module}");
|
614 |
-
}
|
615 |
-
|
616 |
-
if ( $type ) {
|
617 |
-
$filters[] = rawurlencode( "type|{$type}" );
|
618 |
-
}
|
619 |
-
|
620 |
-
if ( $filters ) {
|
621 |
-
$url = add_query_arg( array( 'filters' => $filters ), $url );
|
622 |
}
|
623 |
|
624 |
return $url;
|
24 |
*
|
25 |
* @access private
|
26 |
*/
|
27 |
+
private $plugin_build = 4095;
|
28 |
|
29 |
/**
|
30 |
* Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
|
163 |
add_action( 'admin_bar_menu', array( $this, 'modify_admin_bar' ), 99 );
|
164 |
}
|
165 |
|
166 |
+
$disabled = defined( 'ITSEC_DISABLE_PASSWORD_REQUIREMENTS') && ITSEC_DISABLE_PASSWORD_REQUIREMENTS;
|
167 |
+
|
168 |
+
if ( ! $disabled && has_action( 'itsec_validate_password' ) ) {
|
169 |
+
$pass_requirements = new ITSEC_Lib_Password_Requirements();
|
170 |
+
$pass_requirements->run();
|
171 |
+
}
|
172 |
+
|
173 |
$login_interstitial = new ITSEC_Lib_Login_Interstitial();
|
174 |
$login_interstitial->run();
|
175 |
|
328 |
}
|
329 |
|
330 |
ITSEC_Modules::register_module( 'network-brute-force', "$path/modules/ipcheck", 'default-active' );
|
|
|
|
|
|
|
|
|
|
|
331 |
ITSEC_Modules::register_module( 'ssl', "$path/modules/ssl" );
|
332 |
+
ITSEC_Modules::register_module( 'strong-passwords', "$path/modules/strong-passwords", 'default-active' );
|
333 |
ITSEC_Modules::register_module( 'system-tweaks', "$path/modules/system-tweaks" );
|
334 |
ITSEC_Modules::register_module( 'wordpress-salts', "$path/modules/salts", 'always-active' );
|
335 |
ITSEC_Modules::register_module( 'wordpress-tweaks', "$path/modules/wordpress-tweaks", 'default-active' );
|
606 |
return $url;
|
607 |
}
|
608 |
|
609 |
+
public static function get_logs_page_url( $filter = false ) {
|
610 |
$url = network_admin_url( 'admin.php?page=itsec-logs' );
|
611 |
|
612 |
+
if ( ! empty( $filter ) ) {
|
613 |
+
$url = add_query_arg( array( 'filters' => rawurlencode( "module|{$filter}" ) ), $url );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
614 |
}
|
615 |
|
616 |
return $url;
|
core/history.txt
CHANGED
@@ -697,53 +697,4 @@
|
|
697 |
Bug Fix: Changed the rules generated by the Filter Suspicious Query Strings feature in order to avoid blocking privacy export/erasure request confirmations.
|
698 |
4.5.1 - 2018-05-25 - Chris Jean & Timothy Jacobs
|
699 |
Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
|
700 |
-
Bug Fix: Skip recovery if File Change storage is empty.
|
701 |
-
4.5.2 - 2018-05-31 - Chris Jean & Timothy Jacobs
|
702 |
-
Enhancement: Add UI to cancel in progress File Scan.
|
703 |
-
Tweak: Don't write to the tracked files setting if the file hash has not changed.
|
704 |
-
Bug Fix: Ensure scheduling lock is cleared by the Cron Scheduler when not proceeding with running events.
|
705 |
-
Bug Fix: Away Mode would not lock out users who were already logged-in during the "away" period.
|
706 |
-
Bug Fix: Prevent File Change from getting stuck in an infinite rescheduling loop on the first step.
|
707 |
-
4.6.0 - 2018-06-07 - Chris Jean & Timothy Jacobs
|
708 |
-
Enhancement: Introduce Password Requirements module for managing and enforcing password requirements.
|
709 |
-
Enhancement: Continually evaluate password strength for users instead of only during registration.
|
710 |
-
Enhancement: Add basic admin debug page to help diagnosing and resolving issues. Particularly with the events.
|
711 |
-
Bug Fix: Password strength would not be evaluated if password was set using custom PHP or CLI commands.
|
712 |
-
Bug Fix: Only hide "Acknowledge Weak Password" checkbox if the user was not allowed to use a weak password.
|
713 |
-
4.6.1 - 2018-06-11 - Chris Jean & Timothy Jacobs
|
714 |
-
Enhancement: Add debug settings JSON editor.
|
715 |
-
Tweak: If no last password change date is recorded for the user, treat their registration date as the last change date.
|
716 |
-
Bug Fix: If a password requirement has been disabled or is no longer available, don't consider the password as needing a change.
|
717 |
-
Bug Fix: Remove distributed storage table on uninstall.
|
718 |
-
4.6.2 - 2018-06-12 - Chris Jean & Timothy Jacobs
|
719 |
-
Bug Fix: Accessing password requirement settings would not resolve properly in some instances.
|
720 |
-
4.6.3 - 2018-06-14 - Chris Jean & Timothy Jacobs
|
721 |
-
Bug Fix: Enforce the Strong Passwords requirement during Security Check.
|
722 |
-
4.6.4 - 2018-06-18 - Chris Jean & Timothy Jacobs
|
723 |
-
Security Fix: Fixed SQL injection vulnerability in the logs page. Note: Admin privileges are required to exploit this vulnerability. Thanks to Çlirim Emini, Penetration Tester at sentry.co.com, for reporting this vulnerability.
|
724 |
-
Bug Fix: Provide default values for enabled requirements.
|
725 |
-
4.6.5 - 2018-06-27 - Chris Jean & Timothy Jacobs
|
726 |
-
Enhancement: Add mitigation for the WordPress Attachment File Traversal and Deletion vulnerability.
|
727 |
-
Tweak: Fire a WordPress action whenever settings are updated.
|
728 |
-
Bug Fix: Improved input sanitization on the logs page to prevent triggering warnings.
|
729 |
-
4.6.6 - 2018-07-09 - Chris Jean & Timothy Jacobs
|
730 |
-
Tweak: Check if an IP is blacklisted on page load for compatibility with servers that cannot process server configuration level bans immediately.
|
731 |
-
4.7.0 - 2018-07-17 - Chris Jean & Timothy Jacobs
|
732 |
-
Tweak: Display a time diff until the next event on the Debug page.
|
733 |
-
Compatibility Fix: 404 detection for plugins that mark is_404 later in the hook sequence.
|
734 |
-
4.7.1 - 2018-07-24 - Chris Jean & Timothy Jacobs
|
735 |
-
Tweak: Use Logging API for tracking Notification Center errors.
|
736 |
-
Tweak: Register Scheduler Events whenever the plugin build changes.
|
737 |
-
Tweak: Allow for filtering logs by any module recorded.
|
738 |
-
Bug Fix: Account for any CLI PHP SAPI instead of just WP-CLI in the SSL Module.
|
739 |
-
4.7.2 - 2018-07-31 - Chris Jean & Timothy Jacobs
|
740 |
-
New Feature: Allow for globally setting recipients for admin-targeted notifications. All new notifications will default to the recipients in this list. Notifications can be set to use the default list or switch to a custom list.
|
741 |
-
Tweak: Account for 3rd-party Backup Plugin in Security Check.
|
742 |
-
4.7.3 - 2018-08-01 - Chris Jean & Timothy Jacobs
|
743 |
-
Bug Fix: Fix serialization of closure error when a plugin registering a hook with a closure is in the boot-up stack and the notification center is triggered too early in the cycle.
|
744 |
-
4.7.4 - 2018-08-06 - Chris Jean & Timothy Jacobs
|
745 |
-
Enhancement: Added a setting to enable/disable the Grade Report feature of Pro.
|
746 |
-
4.7.5 - 2018-08-07 - Chris Jean & Timothy Jacobs
|
747 |
-
Bug Fix: Fixed how the Grade Report enable/disable status is stored to fix admin page loading issues on some sites.
|
748 |
-
4.7.6 - 2018-08-14 - Chris Jean & Timothy Jacobs
|
749 |
-
Bug Fix: REST API Protection blocked the Taxonomies route for all users.
|
697 |
Bug Fix: Changed the rules generated by the Filter Suspicious Query Strings feature in order to avoid blocking privacy export/erasure request confirmations.
|
698 |
4.5.1 - 2018-05-25 - Chris Jean & Timothy Jacobs
|
699 |
Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
|
700 |
+
Bug Fix: Skip recovery if File Change storage is empty.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/lib.php
CHANGED
@@ -39,7 +39,7 @@ final class ITSEC_Lib {
|
|
39 |
w3tc_dbcache_flush();
|
40 |
w3tc_objectcache_flush();
|
41 |
|
42 |
-
}
|
43 |
|
44 |
wp_cache_clear_cache();
|
45 |
|
@@ -84,7 +84,7 @@ final class ITSEC_Lib {
|
|
84 |
*
|
85 |
* @since 4.0.0
|
86 |
*
|
87 |
-
* @param string $url
|
88 |
*
|
89 |
* @return string domain name or '*' on error or domain mapped multisite
|
90 |
* */
|
@@ -106,7 +106,7 @@ final class ITSEC_Lib {
|
|
106 |
$host_parts = explode( '.', $host );
|
107 |
|
108 |
if ( count( $host_parts ) > 2 ) {
|
109 |
-
$host_parts = array_slice( $host_parts, -
|
110 |
}
|
111 |
|
112 |
return implode( '.', $host_parts );
|
@@ -175,7 +175,6 @@ final class ITSEC_Lib {
|
|
175 |
|
176 |
if ( ! empty( $ip ) ) {
|
177 |
$GLOBALS['__itsec_remote_ip'] = $ip;
|
178 |
-
|
179 |
return $ip;
|
180 |
}
|
181 |
}
|
@@ -185,7 +184,6 @@ final class ITSEC_Lib {
|
|
185 |
|
186 |
if ( ITSEC_Modules::get_setting( 'global', 'proxy_override' ) ) {
|
187 |
$GLOBALS['__itsec_remote_ip'] = $_SERVER['REMOTE_ADDR'];
|
188 |
-
|
189 |
return $GLOBALS['__itsec_remote_ip'];
|
190 |
}
|
191 |
|
@@ -205,19 +203,19 @@ final class ITSEC_Lib {
|
|
205 |
|
206 |
// Loop through twice. The first run won't accept a reserved or private range IP. If an acceptable IP is not
|
207 |
// found, try again while accepting reserved or private range IPs.
|
208 |
-
for ( $x = 0; $x < 2; $x
|
209 |
foreach ( $headers as $header ) {
|
210 |
-
if ( ! isset( $_SERVER[
|
211 |
continue;
|
212 |
}
|
213 |
|
214 |
-
$ip = trim( $_SERVER[
|
215 |
|
216 |
if ( empty( $ip ) ) {
|
217 |
continue;
|
218 |
}
|
219 |
|
220 |
-
if ( false !== ( $comma_index = strpos( $_SERVER[
|
221 |
$ip = substr( $ip, 0, $comma_index );
|
222 |
}
|
223 |
|
@@ -408,21 +406,21 @@ final class ITSEC_Lib {
|
|
408 |
|
409 |
if ( - 1 < $memory_limit ) {
|
410 |
|
411 |
-
$unit
|
412 |
$memory_limit = (int) $memory_limit;
|
413 |
|
414 |
-
$new_unit
|
415 |
$new_memory_limit = (int) $new_memory_limit;
|
416 |
|
417 |
if ( 'm' == $unit ) {
|
418 |
|
419 |
$memory_limit *= 1048576;
|
420 |
|
421 |
-
}
|
422 |
|
423 |
$memory_limit *= 1073741824;
|
424 |
|
425 |
-
}
|
426 |
|
427 |
$memory_limit *= 1024;
|
428 |
|
@@ -432,11 +430,11 @@ final class ITSEC_Lib {
|
|
432 |
|
433 |
$new_memory_limit *= 1048576;
|
434 |
|
435 |
-
}
|
436 |
|
437 |
$new_memory_limit *= 1073741824;
|
438 |
|
439 |
-
}
|
440 |
|
441 |
$new_memory_limit *= 1024;
|
442 |
|
@@ -533,11 +531,11 @@ final class ITSEC_Lib {
|
|
533 |
|
534 |
if ( false === $user ) {
|
535 |
$user = wp_get_current_user();
|
536 |
-
}
|
537 |
$user = get_user_by( 'id', $user );
|
538 |
-
}
|
539 |
$user = get_user_by( 'login', $user );
|
540 |
-
}
|
541 |
$user = get_user_by( 'id', $user->ID );
|
542 |
} else {
|
543 |
if ( is_object( $user ) ) {
|
@@ -609,7 +607,7 @@ final class ITSEC_Lib {
|
|
609 |
|
610 |
if ( 'Basic ' === $http_auth_type ) {
|
611 |
$authentication_types[] = 'header_http_basic_auth';
|
612 |
-
}
|
613 |
$authentication_types[] = 'header_http_oauth';
|
614 |
}
|
615 |
}
|
@@ -626,14 +624,14 @@ final class ITSEC_Lib {
|
|
626 |
$authentication_types[] = 'post_oauth';
|
627 |
}
|
628 |
|
629 |
-
if ( defined(
|
630 |
-
$source
|
631 |
$authentication_types = array( 'username_and_password' );
|
632 |
-
}
|
633 |
-
$source
|
634 |
$authentication_types[] = 'cookie';
|
635 |
} else {
|
636 |
-
$source
|
637 |
$authentication_types = array( 'username_and_password' );
|
638 |
}
|
639 |
|
@@ -675,7 +673,7 @@ final class ITSEC_Lib {
|
|
675 |
*/
|
676 |
public static function get_request_path() {
|
677 |
if ( ! isset( $GLOBALS['__itsec_lib_get_request_path'] ) ) {
|
678 |
-
$request_uri
|
679 |
$GLOBALS['__itsec_lib_get_request_path'] = self::get_url_path( $request_uri, self::get_home_root() );
|
680 |
}
|
681 |
|
@@ -698,8 +696,8 @@ final class ITSEC_Lib {
|
|
698 |
global $wpdb;
|
699 |
$main_options = $wpdb->base_prefix . 'options';
|
700 |
|
701 |
-
$lock
|
702 |
-
$now
|
703 |
$release_at = $now + $expires_in;
|
704 |
|
705 |
if ( is_multisite() ) {
|
@@ -782,7 +780,7 @@ final class ITSEC_Lib {
|
|
782 |
$alloptions = wp_cache_get( 'alloptions' );
|
783 |
|
784 |
if ( is_array( $alloptions ) && isset( $alloptions[ $lock ] ) ) {
|
785 |
-
unset( $alloptions[
|
786 |
wp_cache_set( 'alloptions', $alloptions, 'options' );
|
787 |
} else {
|
788 |
wp_cache_delete( $lock, 'options' );
|
@@ -847,13 +845,13 @@ final class ITSEC_Lib {
|
|
847 |
wp_cache_switch_to_blog( 1 );
|
848 |
|
849 |
$alloptions = wp_cache_get( 'alloptions' );
|
850 |
-
$set_all
|
851 |
|
852 |
foreach ( $rows as $row ) {
|
853 |
$lock = $row->option_name;
|
854 |
|
855 |
if ( is_array( $alloptions ) && isset( $alloptions[ $lock ] ) ) {
|
856 |
-
unset( $alloptions[
|
857 |
$set_all = true;
|
858 |
} else {
|
859 |
wp_cache_delete( $lock, 'options' );
|
@@ -920,7 +918,7 @@ final class ITSEC_Lib {
|
|
920 |
public static function get_ssl_support_probability() {
|
921 |
if ( is_ssl() ) {
|
922 |
$probability = 50; // The site appears to be on an SSL connection but it could be self-signed or otherwise
|
923 |
-
|
924 |
} else {
|
925 |
$probability = 0;
|
926 |
}
|
@@ -1070,10 +1068,8 @@ final class ITSEC_Lib {
|
|
1070 |
* Enqueue the itsec_util script.
|
1071 |
*
|
1072 |
* Will only be included once per page.
|
1073 |
-
*
|
1074 |
-
* @param array $args
|
1075 |
*/
|
1076 |
-
public static function enqueue_util(
|
1077 |
|
1078 |
static $enqueued = false;
|
1079 |
|
@@ -1101,8 +1097,8 @@ final class ITSEC_Lib {
|
|
1101 |
|
1102 |
wp_enqueue_script( 'itsec-util', plugins_url( 'admin-pages/js/util.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build(), true );
|
1103 |
wp_localize_script( 'itsec-util', 'itsec_util', array(
|
1104 |
-
'ajax_action' =>
|
1105 |
-
'ajax_nonce' => wp_create_nonce(
|
1106 |
'translations' => $translations,
|
1107 |
) );
|
1108 |
|
@@ -1157,111 +1153,4 @@ final class ITSEC_Lib {
|
|
1157 |
|
1158 |
return $array;
|
1159 |
}
|
1160 |
-
|
1161 |
-
/**
|
1162 |
-
* Insert an element after a given key.
|
1163 |
-
*
|
1164 |
-
* @param string|int $key
|
1165 |
-
* @param array $array
|
1166 |
-
* @param string|int $new_key
|
1167 |
-
* @param mixed $new_value
|
1168 |
-
*
|
1169 |
-
* @return array
|
1170 |
-
*/
|
1171 |
-
public static function array_insert_after( $key, $array, $new_key, $new_value ) {
|
1172 |
-
if ( array_key_exists( $key, $array ) ) {
|
1173 |
-
$new = array();
|
1174 |
-
foreach ( $array as $k => $value ) {
|
1175 |
-
$new[ $k ] = $value;
|
1176 |
-
if ( $k === $key ) {
|
1177 |
-
$new[ $new_key ] = $new_value;
|
1178 |
-
}
|
1179 |
-
}
|
1180 |
-
|
1181 |
-
return $new;
|
1182 |
-
}
|
1183 |
-
|
1184 |
-
$array[ $new_key ] = $new_value;
|
1185 |
-
|
1186 |
-
return $array;
|
1187 |
-
}
|
1188 |
-
|
1189 |
-
/**
|
1190 |
-
* Array unique implementation that allows for non-scalar values.
|
1191 |
-
*
|
1192 |
-
* Will compare elements using `serialize()`.
|
1193 |
-
*
|
1194 |
-
* Keys are preserved. If a numeric array is given, the array will be re-indexed.
|
1195 |
-
*
|
1196 |
-
* @param array $array
|
1197 |
-
*
|
1198 |
-
* @return array
|
1199 |
-
*/
|
1200 |
-
public static function non_scalar_array_unique( $array ) {
|
1201 |
-
|
1202 |
-
$is_numeric = wp_is_numeric_array( $array );
|
1203 |
-
|
1204 |
-
$hashes = array();
|
1205 |
-
|
1206 |
-
foreach ( $array as $key => $value ) {
|
1207 |
-
$hash = serialize( $value );
|
1208 |
-
|
1209 |
-
if ( isset( $hashes[ $hash ] ) ) {
|
1210 |
-
unset( $array[ $key ] );
|
1211 |
-
} else {
|
1212 |
-
$hashes[ $hash ] = 1;
|
1213 |
-
}
|
1214 |
-
}
|
1215 |
-
|
1216 |
-
if ( $is_numeric ) {
|
1217 |
-
return array_values( $array );
|
1218 |
-
}
|
1219 |
-
|
1220 |
-
return $array;
|
1221 |
-
}
|
1222 |
-
|
1223 |
-
/**
|
1224 |
-
* Get whatever backup plugin is being used on this site.
|
1225 |
-
*
|
1226 |
-
* @return string
|
1227 |
-
*/
|
1228 |
-
public static function get_backup_plugin() {
|
1229 |
-
|
1230 |
-
$possible = array(
|
1231 |
-
'backupbuddy/backupbuddy.php',
|
1232 |
-
'updraftplus/updraftplus.php',
|
1233 |
-
'backwpup/backwpup.php',
|
1234 |
-
'xcloner-backup-and-restore/xcloner.php',
|
1235 |
-
'duplicator/duplicator.php',
|
1236 |
-
'backup/backup.php',
|
1237 |
-
'wp-db-backup/wp-db-backup.php',
|
1238 |
-
'backupwordpress/backupwordpress.php',
|
1239 |
-
'blogvault-real-time-backup/blogvault.php',
|
1240 |
-
'wp-all-backup/wp-all-backup.php',
|
1241 |
-
'vaultpress/vaultpress.php',
|
1242 |
-
);
|
1243 |
-
|
1244 |
-
/**
|
1245 |
-
* Filter the list of possible backup plugins.
|
1246 |
-
*
|
1247 |
-
* @param string[] List of Backup Plugin __FILE__.
|
1248 |
-
*/
|
1249 |
-
$possible = apply_filters( 'itsec_possible_backup_plugins', $possible );
|
1250 |
-
|
1251 |
-
if ( ! function_exists( 'is_plugin_active' ) ) {
|
1252 |
-
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
1253 |
-
}
|
1254 |
-
|
1255 |
-
if ( ! function_exists( 'is_plugin_active' ) ) {
|
1256 |
-
return '';
|
1257 |
-
}
|
1258 |
-
|
1259 |
-
foreach ( $possible as $file ) {
|
1260 |
-
if ( is_plugin_active( $file ) ) {
|
1261 |
-
return $file;
|
1262 |
-
}
|
1263 |
-
}
|
1264 |
-
|
1265 |
-
return '';
|
1266 |
-
}
|
1267 |
}
|
39 |
w3tc_dbcache_flush();
|
40 |
w3tc_objectcache_flush();
|
41 |
|
42 |
+
} else if ( function_exists( 'wp_cache_clear_cache' ) && true == $page ) {
|
43 |
|
44 |
wp_cache_clear_cache();
|
45 |
|
84 |
*
|
85 |
* @since 4.0.0
|
86 |
*
|
87 |
+
* @param string $url URL to filter
|
88 |
*
|
89 |
* @return string domain name or '*' on error or domain mapped multisite
|
90 |
* */
|
106 |
$host_parts = explode( '.', $host );
|
107 |
|
108 |
if ( count( $host_parts ) > 2 ) {
|
109 |
+
$host_parts = array_slice( $host_parts, -2, 2 );
|
110 |
}
|
111 |
|
112 |
return implode( '.', $host_parts );
|
175 |
|
176 |
if ( ! empty( $ip ) ) {
|
177 |
$GLOBALS['__itsec_remote_ip'] = $ip;
|
|
|
178 |
return $ip;
|
179 |
}
|
180 |
}
|
184 |
|
185 |
if ( ITSEC_Modules::get_setting( 'global', 'proxy_override' ) ) {
|
186 |
$GLOBALS['__itsec_remote_ip'] = $_SERVER['REMOTE_ADDR'];
|
|
|
187 |
return $GLOBALS['__itsec_remote_ip'];
|
188 |
}
|
189 |
|
203 |
|
204 |
// Loop through twice. The first run won't accept a reserved or private range IP. If an acceptable IP is not
|
205 |
// found, try again while accepting reserved or private range IPs.
|
206 |
+
for ( $x = 0; $x < 2; $x++ ) {
|
207 |
foreach ( $headers as $header ) {
|
208 |
+
if ( ! isset( $_SERVER[$header] ) ) {
|
209 |
continue;
|
210 |
}
|
211 |
|
212 |
+
$ip = trim( $_SERVER[$header] );
|
213 |
|
214 |
if ( empty( $ip ) ) {
|
215 |
continue;
|
216 |
}
|
217 |
|
218 |
+
if ( false !== ( $comma_index = strpos( $_SERVER[$header], ',' ) ) ) {
|
219 |
$ip = substr( $ip, 0, $comma_index );
|
220 |
}
|
221 |
|
406 |
|
407 |
if ( - 1 < $memory_limit ) {
|
408 |
|
409 |
+
$unit = strtolower( substr( $memory_limit, - 1 ) );
|
410 |
$memory_limit = (int) $memory_limit;
|
411 |
|
412 |
+
$new_unit = strtolower( substr( $new_memory_limit, - 1 ) );
|
413 |
$new_memory_limit = (int) $new_memory_limit;
|
414 |
|
415 |
if ( 'm' == $unit ) {
|
416 |
|
417 |
$memory_limit *= 1048576;
|
418 |
|
419 |
+
} else if ( 'g' == $unit ) {
|
420 |
|
421 |
$memory_limit *= 1073741824;
|
422 |
|
423 |
+
} else if ( 'k' == $unit ) {
|
424 |
|
425 |
$memory_limit *= 1024;
|
426 |
|
430 |
|
431 |
$new_memory_limit *= 1048576;
|
432 |
|
433 |
+
} else if ( 'g' == $new_unit ) {
|
434 |
|
435 |
$new_memory_limit *= 1073741824;
|
436 |
|
437 |
+
} else if ( 'k' == $new_unit ) {
|
438 |
|
439 |
$new_memory_limit *= 1024;
|
440 |
|
531 |
|
532 |
if ( false === $user ) {
|
533 |
$user = wp_get_current_user();
|
534 |
+
} else if ( is_int( $user ) ) {
|
535 |
$user = get_user_by( 'id', $user );
|
536 |
+
} else if ( is_string( $user ) ) {
|
537 |
$user = get_user_by( 'login', $user );
|
538 |
+
} else if ( is_object( $user ) && isset( $user->ID ) ) {
|
539 |
$user = get_user_by( 'id', $user->ID );
|
540 |
} else {
|
541 |
if ( is_object( $user ) ) {
|
607 |
|
608 |
if ( 'Basic ' === $http_auth_type ) {
|
609 |
$authentication_types[] = 'header_http_basic_auth';
|
610 |
+
} else if ( 'OAuth ' === $http_auth_type ) {
|
611 |
$authentication_types[] = 'header_http_oauth';
|
612 |
}
|
613 |
}
|
624 |
$authentication_types[] = 'post_oauth';
|
625 |
}
|
626 |
|
627 |
+
if ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST ) {
|
628 |
+
$source = 'xmlrpc';
|
629 |
$authentication_types = array( 'username_and_password' );
|
630 |
+
} else if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
631 |
+
$source = 'rest_api';
|
632 |
$authentication_types[] = 'cookie';
|
633 |
} else {
|
634 |
+
$source = 'wp-login.php';
|
635 |
$authentication_types = array( 'username_and_password' );
|
636 |
}
|
637 |
|
673 |
*/
|
674 |
public static function get_request_path() {
|
675 |
if ( ! isset( $GLOBALS['__itsec_lib_get_request_path'] ) ) {
|
676 |
+
$request_uri = preg_replace( '|//+|', '/', $_SERVER['REQUEST_URI'] );
|
677 |
$GLOBALS['__itsec_lib_get_request_path'] = self::get_url_path( $request_uri, self::get_home_root() );
|
678 |
}
|
679 |
|
696 |
global $wpdb;
|
697 |
$main_options = $wpdb->base_prefix . 'options';
|
698 |
|
699 |
+
$lock = "itsec-lock-{$name}";
|
700 |
+
$now = ITSEC_Core::get_current_time_gmt();
|
701 |
$release_at = $now + $expires_in;
|
702 |
|
703 |
if ( is_multisite() ) {
|
780 |
$alloptions = wp_cache_get( 'alloptions' );
|
781 |
|
782 |
if ( is_array( $alloptions ) && isset( $alloptions[ $lock ] ) ) {
|
783 |
+
unset( $alloptions[$lock] );
|
784 |
wp_cache_set( 'alloptions', $alloptions, 'options' );
|
785 |
} else {
|
786 |
wp_cache_delete( $lock, 'options' );
|
845 |
wp_cache_switch_to_blog( 1 );
|
846 |
|
847 |
$alloptions = wp_cache_get( 'alloptions' );
|
848 |
+
$set_all = false;
|
849 |
|
850 |
foreach ( $rows as $row ) {
|
851 |
$lock = $row->option_name;
|
852 |
|
853 |
if ( is_array( $alloptions ) && isset( $alloptions[ $lock ] ) ) {
|
854 |
+
unset( $alloptions[$lock] );
|
855 |
$set_all = true;
|
856 |
} else {
|
857 |
wp_cache_delete( $lock, 'options' );
|
918 |
public static function get_ssl_support_probability() {
|
919 |
if ( is_ssl() ) {
|
920 |
$probability = 50; // The site appears to be on an SSL connection but it could be self-signed or otherwise
|
921 |
+
// not valid to a visitor.
|
922 |
} else {
|
923 |
$probability = 0;
|
924 |
}
|
1068 |
* Enqueue the itsec_util script.
|
1069 |
*
|
1070 |
* Will only be included once per page.
|
|
|
|
|
1071 |
*/
|
1072 |
+
public static function enqueue_util() {
|
1073 |
|
1074 |
static $enqueued = false;
|
1075 |
|
1097 |
|
1098 |
wp_enqueue_script( 'itsec-util', plugins_url( 'admin-pages/js/util.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build(), true );
|
1099 |
wp_localize_script( 'itsec-util', 'itsec_util', array(
|
1100 |
+
'ajax_action' => 'itsec_settings_page',
|
1101 |
+
'ajax_nonce' => wp_create_nonce( 'itsec-settings-nonce' ),
|
1102 |
'translations' => $translations,
|
1103 |
) );
|
1104 |
|
1153 |
|
1154 |
return $array;
|
1155 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1156 |
}
|
core/lib/class-itsec-job.php
CHANGED
@@ -34,11 +34,10 @@ class ITSEC_Job {
|
|
34 |
*
|
35 |
* The original event will not fire while a reschedule is pending.
|
36 |
*
|
37 |
-
* @param int
|
38 |
-
* @param array $data Additional data to attach to the rescheduled event.
|
39 |
*/
|
40 |
-
public function reschedule_in( $seconds
|
41 |
-
$data =
|
42 |
|
43 |
if ( isset( $data['retry_count'] ) ) {
|
44 |
$data['retry_count'] ++;
|
34 |
*
|
35 |
* The original event will not fire while a reschedule is pending.
|
36 |
*
|
37 |
+
* @param int $seconds
|
|
|
38 |
*/
|
39 |
+
public function reschedule_in( $seconds ) {
|
40 |
+
$data = $this->get_data();
|
41 |
|
42 |
if ( isset( $data['retry_count'] ) ) {
|
43 |
$data['retry_count'] ++;
|
core/lib/class-itsec-lib-canonical-roles.php
CHANGED
@@ -122,76 +122,6 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
122 |
return '';
|
123 |
}
|
124 |
|
125 |
-
/**
|
126 |
-
* Get the canonical role from any WordPress role.
|
127 |
-
*
|
128 |
-
* @param string $role
|
129 |
-
*
|
130 |
-
* @return string
|
131 |
-
*/
|
132 |
-
public static function get_canonical_role_from_role( $role ) {
|
133 |
-
return self::get_role_from_caps( array_keys( array_filter( wp_roles()->get_role( $role )->capabilities ) ) );
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* Retrieve a canonical role for a user and a role.
|
138 |
-
*
|
139 |
-
* @param string $role
|
140 |
-
* @param WP_User $user
|
141 |
-
*
|
142 |
-
* @return string
|
143 |
-
*/
|
144 |
-
public static function get_canonical_role_from_role_and_user( $role, $user ) {
|
145 |
-
$user = ITSEC_Lib::get_user( $user );
|
146 |
-
|
147 |
-
if ( empty( $role ) ) {
|
148 |
-
$role_caps = array();
|
149 |
-
} else {
|
150 |
-
$role_caps = array_keys( array_filter( wp_roles()->get_role( $role )->capabilities ) );
|
151 |
-
}
|
152 |
-
|
153 |
-
$user_caps = array();
|
154 |
-
|
155 |
-
if ( isset( $user->caps ) ) {
|
156 |
-
$wp_roles = wp_roles();
|
157 |
-
|
158 |
-
foreach ( $user->caps as $cap => $has ) {
|
159 |
-
if ( $has && ! $wp_roles->is_role( $cap ) ) {
|
160 |
-
$user_caps[] = $has;
|
161 |
-
}
|
162 |
-
}
|
163 |
-
}
|
164 |
-
|
165 |
-
return self::get_role_from_caps( array_merge( $role_caps, $user_caps ) );
|
166 |
-
}
|
167 |
-
|
168 |
-
/**
|
169 |
-
* Get all users that have the given canonical role.
|
170 |
-
*
|
171 |
-
* @param string|string[] $canonical
|
172 |
-
* @param array $additional_args
|
173 |
-
*
|
174 |
-
* @return WP_User[]
|
175 |
-
*/
|
176 |
-
public static function get_users_with_canonical_role( $canonical, $additional_args = array() ) {
|
177 |
-
|
178 |
-
$canonical = (array) $canonical;
|
179 |
-
|
180 |
-
$roles = array();
|
181 |
-
|
182 |
-
foreach ( wp_roles()->roles as $role => $_ ) {
|
183 |
-
if ( in_array( self::get_canonical_role_from_role( $role ), $canonical, true ) ) {
|
184 |
-
$roles[] = $role;
|
185 |
-
}
|
186 |
-
}
|
187 |
-
|
188 |
-
if ( empty( $roles ) ) {
|
189 |
-
return array();
|
190 |
-
}
|
191 |
-
|
192 |
-
return get_users( array_merge( $additional_args, array( 'role__in' => $roles ) ) );
|
193 |
-
}
|
194 |
-
|
195 |
/**
|
196 |
* Get a list of all of the capabilities that are unique to each role.
|
197 |
*
|
122 |
return '';
|
123 |
}
|
124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
/**
|
126 |
* Get a list of all of the capabilities that are unique to each role.
|
127 |
*
|
core/lib/class-itsec-lib-password-requirements.php
CHANGED
@@ -1,75 +1,186 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
/**
|
4 |
* Class ITSEC_Lib_Password_Requirements
|
5 |
*/
|
6 |
class ITSEC_Lib_Password_Requirements {
|
7 |
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
/**
|
12 |
-
*
|
13 |
*
|
14 |
-
* @
|
|
|
|
|
15 |
*/
|
16 |
-
public
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
}
|
25 |
|
26 |
-
|
27 |
}
|
28 |
|
29 |
/**
|
30 |
-
*
|
31 |
*
|
32 |
-
* @param
|
33 |
-
* @param
|
34 |
*/
|
35 |
-
public
|
36 |
-
$merged = wp_parse_args( $opts, array(
|
37 |
-
'evaluate' => null,
|
38 |
-
'validate' => null,
|
39 |
-
'flag_check' => null,
|
40 |
-
'reason' => null,
|
41 |
-
'defaults' => null,
|
42 |
-
'settings_config' => null, // Callable returning label, description, render & sanitize callbacks.
|
43 |
-
'meta' => "_itsec_password_evaluation_{$reason_code}",
|
44 |
-
'evaluate_if_not_enabled' => false,
|
45 |
-
) );
|
46 |
|
47 |
-
if (
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
return;
|
52 |
}
|
53 |
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
return;
|
56 |
}
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
}
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
|
68 |
-
|
69 |
-
|
|
|
|
|
70 |
}
|
71 |
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
}
|
74 |
|
75 |
/**
|
@@ -85,24 +196,14 @@ class ITSEC_Lib_Password_Requirements {
|
|
85 |
return '';
|
86 |
}
|
87 |
|
88 |
-
$message = '';
|
89 |
-
|
90 |
-
$registered = self::get_registered();
|
91 |
-
|
92 |
-
if ( isset( $registered[ $reason ] ) ) {
|
93 |
-
$settings = self::get_requirement_settings( $reason );
|
94 |
-
$message = call_user_func( $registered[ $reason ]['reason'], get_user_meta( $user->ID, $registered[ $reason ]['meta'], true ), $settings );
|
95 |
-
}
|
96 |
-
|
97 |
/**
|
98 |
* Retrieve a human readable description as to why a password change has been required for the current user.
|
99 |
*
|
100 |
* Modules MUST HTML escape their reason strings before returning them with this filter.
|
101 |
*
|
102 |
-
* @param string
|
103 |
-
* @param WP_User $user
|
104 |
*/
|
105 |
-
$message = apply_filters( "itsec_password_change_requirement_description_for_{$reason}",
|
106 |
|
107 |
if ( $message ) {
|
108 |
return $message;
|
@@ -124,12 +225,12 @@ class ITSEC_Lib_Password_Requirements {
|
|
124 |
|
125 |
$args = wp_parse_args( $args, array(
|
126 |
'error' => new WP_Error(),
|
127 |
-
'context' => ''
|
128 |
) );
|
129 |
|
130 |
-
|
131 |
-
|
132 |
-
$user
|
133 |
|
134 |
if ( ! $user ) {
|
135 |
$error->add( 'invalid_user', esc_html__( 'Invalid User', 'better-wp-security' ) );
|
@@ -137,27 +238,6 @@ class ITSEC_Lib_Password_Requirements {
|
|
137 |
return $error;
|
138 |
}
|
139 |
|
140 |
-
if ( ! empty( $user->ID ) && wp_check_password( $new_password, get_userdata( $user->ID )->user_pass, $user->ID ) ) {
|
141 |
-
$message = wp_kses( __( '<strong>ERROR</strong>: The password you have chosen appears to have been used before. You must choose a new password.', 'better-wp-security' ), array( 'strong' => array() ) );
|
142 |
-
$error->add( 'pass', $message );
|
143 |
-
|
144 |
-
return $error;
|
145 |
-
}
|
146 |
-
|
147 |
-
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
148 |
-
|
149 |
-
if ( isset( $args['role'] ) && $user instanceof WP_User ) {
|
150 |
-
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $args['role'], $user );
|
151 |
-
} elseif ( isset( $args['role'] ) ) {
|
152 |
-
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $args['role'] );
|
153 |
-
} elseif ( empty( $user->ID ) || ! is_numeric( $user->ID ) ) {
|
154 |
-
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( get_option( 'default_role', 'subscriber' ) );
|
155 |
-
} else {
|
156 |
-
$canonical = ITSEC_Lib_Canonical_Roles::get_user_role( $user );
|
157 |
-
}
|
158 |
-
|
159 |
-
$args['canonical'] = $canonical;
|
160 |
-
|
161 |
/**
|
162 |
* Fires when modules should validate a password according to their rules.
|
163 |
*
|
@@ -207,28 +287,9 @@ class ITSEC_Lib_Password_Requirements {
|
|
207 |
return false;
|
208 |
}
|
209 |
|
210 |
-
$registered = self::get_registered();
|
211 |
-
|
212 |
-
if ( isset( $registered[ $reason ] ) ) {
|
213 |
-
return self::is_requirement_enabled( $reason ) ? $reason : false;
|
214 |
-
}
|
215 |
-
|
216 |
-
if ( ! has_filter( "itsec_password_change_requirement_description_for_{$reason}" ) ) {
|
217 |
-
return false;
|
218 |
-
}
|
219 |
-
|
220 |
return $reason;
|
221 |
}
|
222 |
|
223 |
-
/**
|
224 |
-
* Globally clear all required password changes with a particular reason code.
|
225 |
-
*
|
226 |
-
* @param string $reason
|
227 |
-
*/
|
228 |
-
public static function global_clear_required_password_change( $reason ) {
|
229 |
-
delete_metadata( 'user', 0, 'itsec_password_change_required', $reason, true );
|
230 |
-
}
|
231 |
-
|
232 |
/**
|
233 |
* Get the GMT time the user's password has last been changed.
|
234 |
*
|
@@ -251,64 +312,6 @@ class ITSEC_Lib_Password_Requirements {
|
|
251 |
return $deprecated;
|
252 |
}
|
253 |
|
254 |
-
if ( ! $changed ) {
|
255 |
-
return strtotime( $user->user_registered );
|
256 |
-
}
|
257 |
-
|
258 |
return $changed;
|
259 |
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* Is a password requirement enabled.
|
263 |
-
*
|
264 |
-
* @param string $requirement
|
265 |
-
*
|
266 |
-
* @return bool
|
267 |
-
*/
|
268 |
-
public static function is_requirement_enabled( $requirement ) {
|
269 |
-
|
270 |
-
$requirements = self::get_registered();
|
271 |
-
|
272 |
-
if ( ! isset( $requirements[ $requirement ] ) ) {
|
273 |
-
return false;
|
274 |
-
}
|
275 |
-
|
276 |
-
// If the requirement does not have any settings, than it is always enabled.
|
277 |
-
if ( null === $requirements[ $requirement ]['settings_config'] ) {
|
278 |
-
return true;
|
279 |
-
}
|
280 |
-
|
281 |
-
$enabled = ITSEC_Modules::get_setting( 'password-requirements', 'enabled_requirements' );
|
282 |
-
|
283 |
-
if ( ! empty( $enabled[ $requirement ] ) ) {
|
284 |
-
return true;
|
285 |
-
}
|
286 |
-
|
287 |
-
return false;
|
288 |
-
}
|
289 |
-
|
290 |
-
/**
|
291 |
-
* Get requirement settings.
|
292 |
-
*
|
293 |
-
* @param string $requirement
|
294 |
-
*
|
295 |
-
* @return array|false
|
296 |
-
*/
|
297 |
-
public static function get_requirement_settings( $requirement ) {
|
298 |
-
|
299 |
-
$requirements = self::get_registered();
|
300 |
-
|
301 |
-
if ( ! isset( $requirements[ $requirement ] ) ) {
|
302 |
-
return false;
|
303 |
-
}
|
304 |
-
|
305 |
-
if ( null === $requirements[ $requirement ]['settings_config'] ) {
|
306 |
-
return false;
|
307 |
-
}
|
308 |
-
|
309 |
-
$all_settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
310 |
-
$settings = isset( $all_settings[ $requirement ] ) ? $all_settings[ $requirement ] : array();
|
311 |
-
|
312 |
-
return wp_parse_args( $settings, $requirements[ $requirement ]['defaults'] );
|
313 |
-
}
|
314 |
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Tool to manage password requirements across modules.
|
4 |
+
*
|
5 |
+
* @since 3.9.0
|
6 |
+
* @license GPLv2+
|
7 |
+
*/
|
8 |
|
9 |
/**
|
10 |
* Class ITSEC_Lib_Password_Requirements
|
11 |
*/
|
12 |
class ITSEC_Lib_Password_Requirements {
|
13 |
|
14 |
+
const LOGIN_ACTION = 'itsec_update_password';
|
15 |
+
const META_KEY = '_itsec_update_password_key';
|
16 |
+
|
17 |
+
/** @var string */
|
18 |
+
private $error_message = '';
|
19 |
+
|
20 |
+
public function run() {
|
21 |
+
|
22 |
+
add_action( 'user_profile_update_errors', array( $this, 'forward_profile_pass_update' ), 0, 3 );
|
23 |
+
add_action( 'validate_password_reset', array( $this, 'forward_reset_pass' ), 10, 2 );
|
24 |
+
add_action( 'profile_update', array( $this, 'set_password_last_updated' ), 10, 2 );
|
25 |
+
|
26 |
+
add_action( 'itsec_login_interstitial_init', array( $this, 'register_interstitial' ) );
|
27 |
+
}
|
28 |
|
29 |
/**
|
30 |
+
* When a user's password is updated, or a new user created, verify that the new password is valid.
|
31 |
*
|
32 |
+
* @param WP_Error $errors
|
33 |
+
* @param bool $update
|
34 |
+
* @param WP_User|stdClass $user
|
35 |
*/
|
36 |
+
public function forward_profile_pass_update( $errors, $update, $user ) {
|
37 |
+
|
38 |
+
if ( ! isset( $user->user_pass ) ) {
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
|
42 |
+
if ( ! $update ) {
|
43 |
+
$context = 'admin-user-create';
|
44 |
+
} elseif ( isset( $user->ID ) && $user->ID === get_current_user_id() ) {
|
45 |
+
$context = 'profile-update';
|
46 |
+
} else {
|
47 |
+
$context = 'admin-profile-update';
|
48 |
+
}
|
49 |
+
|
50 |
+
$args = array(
|
51 |
+
'error' => $errors,
|
52 |
+
'context' => $context
|
53 |
+
);
|
54 |
+
|
55 |
+
if ( isset( $user->role ) ) {
|
56 |
+
$args['role'] = $user->role;
|
57 |
}
|
58 |
|
59 |
+
self::validate_password( $user, $user->user_pass, $args );
|
60 |
}
|
61 |
|
62 |
/**
|
63 |
+
* When a user attempts to reset their password, verify that the new password is valid.
|
64 |
*
|
65 |
+
* @param WP_Error $errors
|
66 |
+
* @param WP_User $user
|
67 |
*/
|
68 |
+
public function forward_reset_pass( $errors, $user ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
+
if ( ! isset( $_POST['pass1'] ) || is_wp_error( $user ) ) {
|
71 |
+
// The validate_password_reset action fires when first rendering the reset page and when handling the form
|
72 |
+
// submissions. Since the pass1 data is missing, this must be the initial page render. So, we don't need to
|
73 |
+
// do anything yet.
|
74 |
return;
|
75 |
}
|
76 |
|
77 |
+
self::validate_password( $user, $_POST['pass1'], array(
|
78 |
+
'error' => $errors,
|
79 |
+
'context' => 'reset-password',
|
80 |
+
) );
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Whenever a user object is updated, set when their password was last updated.
|
85 |
+
*
|
86 |
+
* @param int $user_id
|
87 |
+
* @param object $old_user_data
|
88 |
+
*/
|
89 |
+
public function set_password_last_updated( $user_id, $old_user_data ) {
|
90 |
+
|
91 |
+
$user = get_userdata( $user_id );
|
92 |
+
|
93 |
+
if ( $user->user_pass === $old_user_data->user_pass ) {
|
94 |
return;
|
95 |
}
|
96 |
|
97 |
+
delete_user_meta( $user_id, 'itsec_password_change_required' );
|
98 |
+
update_user_meta( $user_id, 'itsec_last_password_change', ITSEC_Core::get_current_time_gmt() );
|
99 |
+
}
|
|
|
100 |
|
101 |
+
/**
|
102 |
+
* Register the password change interstitial.
|
103 |
+
*
|
104 |
+
* @param ITSEC_Lib_Login_Interstitial $lib
|
105 |
+
*/
|
106 |
+
public function register_interstitial( $lib ) {
|
107 |
+
$lib->register( 'update-password', array( $this, 'render_interstitial' ), array(
|
108 |
+
'show_to_user' => array( __CLASS__, 'password_change_required' ),
|
109 |
+
'info_message' => array( __CLASS__, 'get_message_for_password_change_reason' ),
|
110 |
+
'submit' => array( $this, 'submit' ),
|
111 |
+
) );
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Render the interstitial.
|
116 |
+
*
|
117 |
+
* @param WP_User $user
|
118 |
+
*/
|
119 |
+
public function render_interstitial( $user ) {
|
120 |
+
?>
|
121 |
+
|
122 |
+
<div class="user-pass1-wrap">
|
123 |
+
<p><label for="pass1"><?php _e( 'New Password', 'better-wp-security' ); ?></label></p>
|
124 |
+
</div>
|
125 |
+
|
126 |
+
<div class="wp-pwd">
|
127 |
+
<span class="password-input-wrapper">
|
128 |
+
<input type="password" data-reveal="1"
|
129 |
+
data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" name="pass1" id="pass1"
|
130 |
+
class="input" size="20" value="" autocomplete="off" aria-describedby="pass-strength-result"/>
|
131 |
+
</span>
|
132 |
+
<div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator', 'better-wp-security' ); ?></div>
|
133 |
+
</div>
|
134 |
+
|
135 |
+
<p class="user-pass2-wrap">
|
136 |
+
<label for="pass2"><?php _e( 'Confirm new password' ) ?></label><br/>
|
137 |
+
<input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off"/>
|
138 |
+
</p>
|
139 |
+
|
140 |
+
<p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p>
|
141 |
+
<br class="clear"/>
|
142 |
+
|
143 |
+
<p class="submit">
|
144 |
+
<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large"
|
145 |
+
value="<?php esc_attr_e( 'Update Password', 'better-wp-security' ); ?>"/>
|
146 |
+
</p>
|
147 |
+
|
148 |
+
<?php
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Handle the request to update the user's password.
|
153 |
+
*
|
154 |
+
* @param WP_User $user
|
155 |
+
* @param array $data POSTed data.
|
156 |
+
*
|
157 |
+
* @return WP_Error|null
|
158 |
+
*/
|
159 |
+
public function submit( $user, $data ) {
|
160 |
+
|
161 |
+
if ( empty( $data['pass1'] ) ) {
|
162 |
+
return new WP_Error(
|
163 |
+
'itsec-password-requirements-empty-password',
|
164 |
+
__( 'Please enter your new password.', 'better-wp-security' )
|
165 |
+
);
|
166 |
}
|
167 |
|
168 |
+
$error = self::validate_password( $user, $data['pass1'] );
|
169 |
+
|
170 |
+
if ( $error->get_error_message() ) {
|
171 |
+
return $error;
|
172 |
}
|
173 |
|
174 |
+
$error = wp_update_user( array(
|
175 |
+
'ID' => $user->ID,
|
176 |
+
'user_pass' => $data['pass1']
|
177 |
+
) );
|
178 |
+
|
179 |
+
if ( is_wp_error( $error ) ) {
|
180 |
+
return $error;
|
181 |
+
}
|
182 |
+
|
183 |
+
return null;
|
184 |
}
|
185 |
|
186 |
/**
|
196 |
return '';
|
197 |
}
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
/**
|
200 |
* Retrieve a human readable description as to why a password change has been required for the current user.
|
201 |
*
|
202 |
* Modules MUST HTML escape their reason strings before returning them with this filter.
|
203 |
*
|
204 |
+
* @param string $message
|
|
|
205 |
*/
|
206 |
+
$message = apply_filters( "itsec_password_change_requirement_description_for_{$reason}", '' );
|
207 |
|
208 |
if ( $message ) {
|
209 |
return $message;
|
225 |
|
226 |
$args = wp_parse_args( $args, array(
|
227 |
'error' => new WP_Error(),
|
228 |
+
'context' => ''
|
229 |
) );
|
230 |
|
231 |
+
$error = isset( $args['error'] ) ? $args['error'] : new WP_Error();
|
232 |
+
|
233 |
+
$user = $user instanceof stdClass ? $user : ITSEC_Lib::get_user( $user );
|
234 |
|
235 |
if ( ! $user ) {
|
236 |
$error->add( 'invalid_user', esc_html__( 'Invalid User', 'better-wp-security' ) );
|
238 |
return $error;
|
239 |
}
|
240 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
/**
|
242 |
* Fires when modules should validate a password according to their rules.
|
243 |
*
|
287 |
return false;
|
288 |
}
|
289 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
return $reason;
|
291 |
}
|
292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
/**
|
294 |
* Get the GMT time the user's password has last been changed.
|
295 |
*
|
312 |
return $deprecated;
|
313 |
}
|
314 |
|
|
|
|
|
|
|
|
|
315 |
return $changed;
|
316 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
}
|
core/lib/class-itsec-mail.php
CHANGED
@@ -1,19 +1,14 @@
|
|
1 |
<?php
|
2 |
|
3 |
final class ITSEC_Mail {
|
4 |
-
private $name;
|
5 |
private $content = '';
|
6 |
-
private $groups = array();
|
7 |
-
private $current_group;
|
8 |
-
private $deferred = '';
|
9 |
private $subject = '';
|
10 |
private $recipients = array();
|
11 |
private $attachments = array();
|
12 |
private $template_path = '';
|
13 |
|
14 |
-
public function __construct(
|
15 |
$this->template_path = dirname( __FILE__ ) . '/mail-templates/';
|
16 |
-
$this->name = $name;
|
17 |
}
|
18 |
|
19 |
public function add_header( $title, $banner_title, $use_site_logo = false ) {
|
@@ -36,7 +31,7 @@ final class ITSEC_Mail {
|
|
36 |
'title' => $title,
|
37 |
);
|
38 |
|
39 |
-
$this->
|
40 |
}
|
41 |
|
42 |
public function add_footer() {
|
@@ -79,13 +74,13 @@ final class ITSEC_Mail {
|
|
79 |
|
80 |
);
|
81 |
|
82 |
-
$this->
|
83 |
|
84 |
if ( defined( 'ITSEC_DEBUG' ) && ITSEC_DEBUG ) {
|
85 |
$this->include_debug_info();
|
86 |
}
|
87 |
|
88 |
-
$this->
|
89 |
}
|
90 |
|
91 |
public function add_user_footer() {
|
@@ -101,79 +96,51 @@ final class ITSEC_Mail {
|
|
101 |
) );
|
102 |
|
103 |
$footer .= $this->get_template( 'close.html' );
|
104 |
-
$this->
|
105 |
}
|
106 |
|
107 |
public function add_text( $content ) {
|
108 |
-
$this->add_html( $this->get_text( $content ) );
|
109 |
-
}
|
110 |
-
|
111 |
-
public function get_text( $content ) {
|
112 |
$module = $this->get_template( 'text.html' );
|
113 |
$module = $this->replace( $module, 'content', $content );
|
114 |
|
115 |
-
|
116 |
}
|
117 |
|
118 |
public function add_divider() {
|
119 |
-
$this->
|
120 |
-
}
|
121 |
-
|
122 |
-
public function get_divider() {
|
123 |
-
return $this->get_template( 'divider.html' );
|
124 |
}
|
125 |
|
126 |
public function add_large_text( $content ) {
|
127 |
-
$this->add_html( $this->get_large_text( $content ) );
|
128 |
-
}
|
129 |
-
|
130 |
-
public function get_large_text( $content ) {
|
131 |
$module = $this->get_template( 'large-text.html' );
|
132 |
$module = $this->replace( $module, 'content', $content );
|
133 |
|
134 |
-
|
135 |
}
|
136 |
|
137 |
public function add_info_box( $content, $icon_type = 'info' ) {
|
138 |
-
$this->add_html( $this->get_info_box( $content, $icon_type ) );
|
139 |
-
}
|
140 |
-
|
141 |
-
public function get_info_box( $content, $icon_type = 'info' ) {
|
142 |
$icon_url = $this->get_image_url( $icon_type === 'warning' ? 'warning_icon_yellow' : "{$icon_type}_icon" );
|
143 |
|
144 |
$module = $this->get_template( 'info-box.html' );
|
145 |
$module = $this->replace_all( $module, compact( 'content', 'icon_url' ) );
|
146 |
|
147 |
-
|
148 |
}
|
149 |
|
150 |
public function add_details_box( $content ) {
|
151 |
-
$this->add_html( $this->get_details_box( $content ) );
|
152 |
-
}
|
153 |
-
|
154 |
-
public function get_details_box( $content ) {
|
155 |
$module = $this->get_template( 'details-box.html' );
|
156 |
$module = $this->replace( $module, 'content', $content );
|
157 |
|
158 |
-
|
159 |
}
|
160 |
|
161 |
public function add_large_code( $content ) {
|
162 |
-
$this->add_html( $this->get_large_code( $content ) );
|
163 |
-
}
|
164 |
-
|
165 |
-
public function get_large_code( $content ) {
|
166 |
$module = $this->get_template( 'large-code.html' );
|
167 |
$module = $this->replace( $module, 'content', $content );
|
168 |
|
169 |
-
|
170 |
}
|
171 |
|
172 |
public function add_section_heading( $content, $icon_type = false ) {
|
173 |
-
$this->add_html( $this->get_section_heading( $content, $icon_type ) );
|
174 |
-
}
|
175 |
-
|
176 |
-
public function get_section_heading( $content, $icon_type = false ) {
|
177 |
if ( empty( $icon_type ) ) {
|
178 |
$heading = $this->get_template( 'section-heading.html' );
|
179 |
$heading = $this->replace_all( $heading, compact( 'content' ) );
|
@@ -184,7 +151,7 @@ final class ITSEC_Mail {
|
|
184 |
$heading = $this->replace_all( $heading, compact( 'content', 'icon_url' ) );
|
185 |
}
|
186 |
|
187 |
-
|
188 |
}
|
189 |
|
190 |
public function add_lockouts_summary( $user_count, $host_count ) {
|
@@ -199,7 +166,7 @@ final class ITSEC_Mail {
|
|
199 |
|
200 |
$lockouts = $this->replace_all( $lockouts, $replacements );
|
201 |
|
202 |
-
$this->
|
203 |
}
|
204 |
|
205 |
public function add_file_change_summary( $added, $removed, $modified ) {
|
@@ -216,24 +183,19 @@ final class ITSEC_Mail {
|
|
216 |
|
217 |
$lockouts = $this->replace_all( $lockouts, $replacements );
|
218 |
|
219 |
-
$this->
|
220 |
}
|
221 |
|
222 |
public function add_button( $link_text, $href ) {
|
223 |
-
$this->add_html( $this->get_button( $link_text, $href ) );
|
224 |
-
}
|
225 |
-
|
226 |
-
public function get_button( $link_text, $href ) {
|
227 |
-
|
228 |
$module = $this->get_template( 'module-button.html' );
|
229 |
$module = $this->replace( $module, 'href', $href );
|
230 |
$module = $this->replace( $module, 'link_text', $link_text );
|
231 |
|
232 |
-
|
233 |
}
|
234 |
|
235 |
public function add_lockouts_table( $lockouts ) {
|
236 |
-
$entry
|
237 |
$entries = '';
|
238 |
|
239 |
foreach ( $lockouts as $lockout ) {
|
@@ -251,15 +213,15 @@ final class ITSEC_Mail {
|
|
251 |
$table = $this->get_template( 'lockouts-table.html' );
|
252 |
|
253 |
$replacements = array(
|
254 |
-
'heading_types'
|
255 |
-
'heading_until'
|
256 |
-
'heading_reason'
|
257 |
-
'entries'
|
258 |
);
|
259 |
|
260 |
$table = $this->replace_all( $table, $replacements );
|
261 |
|
262 |
-
$this->
|
263 |
}
|
264 |
|
265 |
/**
|
@@ -269,10 +231,6 @@ final class ITSEC_Mail {
|
|
269 |
* @param array[] $entries
|
270 |
*/
|
271 |
public function add_table( $headers, $entries ) {
|
272 |
-
$this->add_html( $this->get_table( $headers, $entries ) );
|
273 |
-
}
|
274 |
-
|
275 |
-
public function get_table( $headers, $entries ) {
|
276 |
|
277 |
$template = $this->get_template( 'table.html' );
|
278 |
$html = $this->build_table_header( $headers );
|
@@ -281,7 +239,7 @@ final class ITSEC_Mail {
|
|
281 |
$html .= $this->build_table_row( $entry, count( $headers ) );
|
282 |
}
|
283 |
|
284 |
-
|
285 |
}
|
286 |
|
287 |
/**
|
@@ -348,10 +306,6 @@ final class ITSEC_Mail {
|
|
348 |
* @param bool $bold_first Whether to emphasize the first item of the list.
|
349 |
*/
|
350 |
public function add_list( $items, $bold_first = false ) {
|
351 |
-
$this->add_html( $this->get_list( $items, $bold_first ) );
|
352 |
-
}
|
353 |
-
|
354 |
-
public function get_list( $items, $bold_first = false ) {
|
355 |
|
356 |
$template = $this->get_template( 'list.html' );
|
357 |
$html = '';
|
@@ -360,7 +314,7 @@ final class ITSEC_Mail {
|
|
360 |
$html .= $this->build_list_item( $item, $bold_first && 0 === $i );
|
361 |
}
|
362 |
|
363 |
-
|
364 |
}
|
365 |
|
366 |
private function build_list_item( $item, $bold = false ) {
|
@@ -369,55 +323,13 @@ final class ITSEC_Mail {
|
|
369 |
return "<li style=\"margin: 0; padding: 5px 10px;{$bold_tag}\">{$item}</li>";
|
370 |
}
|
371 |
|
372 |
-
/**
|
373 |
-
* Add a section of HTML to the email.
|
374 |
-
*
|
375 |
-
* @param string $html
|
376 |
-
* @param string|null $identifier
|
377 |
-
*/
|
378 |
-
public function add_html( $html, $identifier = null ) {
|
379 |
-
|
380 |
-
if ( null !== $this->current_group ) {
|
381 |
-
$this->deferred .= $html;
|
382 |
-
} elseif ( null !== $identifier ) {
|
383 |
-
$this->groups[ $identifier ] = $html;
|
384 |
-
} else {
|
385 |
-
$this->groups[] = $html;
|
386 |
-
}
|
387 |
-
}
|
388 |
-
|
389 |
-
public function start_group( $identifier ) {
|
390 |
-
$this->current_group = $identifier;
|
391 |
-
}
|
392 |
-
|
393 |
-
public function end_group() {
|
394 |
-
$group = $this->current_group;
|
395 |
-
$deferred = $this->deferred;
|
396 |
-
|
397 |
-
$this->current_group = null;
|
398 |
-
$this->deferred = '';
|
399 |
-
|
400 |
-
$this->add_html( $deferred, $group );
|
401 |
-
}
|
402 |
-
|
403 |
/**
|
404 |
* Include debug info in the email.
|
405 |
*
|
406 |
* This is automatically included in non-user emails if ITSEC_DEBUG is turned on.
|
407 |
*/
|
408 |
public function include_debug_info() {
|
409 |
-
|
410 |
-
if ( ( defined( 'DOING_CRON' ) && DOING_CRON ) || ( function_exists( 'wp_doing_cron' ) && wp_doing_cron() ) ) {
|
411 |
-
$page = 'WP-Cron';
|
412 |
-
} elseif ( defined( 'WP_CLI' ) && WP_CLI ) {
|
413 |
-
$page = 'WP-CLI';
|
414 |
-
} elseif ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
|
415 |
-
$page = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
416 |
-
} else {
|
417 |
-
$page = 'unknown';
|
418 |
-
}
|
419 |
-
|
420 |
-
$this->add_text( sprintf( esc_html__( 'Debug info (source page): %s', 'better-wp-security' ), esc_html( $page ) ) );
|
421 |
}
|
422 |
|
423 |
/**
|
@@ -446,22 +358,8 @@ final class ITSEC_Mail {
|
|
446 |
$this->content = $content;
|
447 |
}
|
448 |
|
449 |
-
public function get_content(
|
450 |
-
|
451 |
-
$groups = $this->groups;
|
452 |
-
|
453 |
-
if ( $this->name ) {
|
454 |
-
/**
|
455 |
-
* Filter the HTML groups before building the content.
|
456 |
-
*
|
457 |
-
* @param array $groups
|
458 |
-
* @param ITSEC_Mail $this
|
459 |
-
* @param string $recipient
|
460 |
-
*/
|
461 |
-
$groups = apply_filters( "itsec_mail_{$this->name}", $groups, $this, $recipient );
|
462 |
-
}
|
463 |
-
|
464 |
-
return implode( '', $groups );
|
465 |
}
|
466 |
|
467 |
public function set_subject( $subject, $add_site_url = true ) {
|
@@ -498,7 +396,7 @@ final class ITSEC_Mail {
|
|
498 |
}
|
499 |
|
500 |
public function set_default_recipients() {
|
501 |
-
$recipients
|
502 |
$this->set_recipients( $recipients );
|
503 |
}
|
504 |
|
@@ -523,25 +421,7 @@ final class ITSEC_Mail {
|
|
523 |
$this->set_default_subject();
|
524 |
}
|
525 |
|
526 |
-
$
|
527 |
-
'Content-Type: text/html; charset=UTF-8',
|
528 |
-
);
|
529 |
-
|
530 |
-
if ( $from = ITSEC_Modules::get_setting( 'notification-center', 'from_email' ) ) {
|
531 |
-
$headers[] = "From: <{$from}>";
|
532 |
-
}
|
533 |
-
|
534 |
-
if ( $this->name ) {
|
535 |
-
$result = true;
|
536 |
-
|
537 |
-
foreach ( $this->recipients as $recipient ) {
|
538 |
-
$result = wp_mail( $recipient, $this->get_subject(), $this->content ? $this->content : $this->get_content( $recipient ), $headers, $this->attachments ) && $result;
|
539 |
-
}
|
540 |
-
|
541 |
-
return $result;
|
542 |
-
}
|
543 |
-
|
544 |
-
return wp_mail( $this->recipients, $this->get_subject(), $this->content ? $this->content : $this->get_content(), $headers, $this->attachments );
|
545 |
}
|
546 |
|
547 |
/**
|
1 |
<?php
|
2 |
|
3 |
final class ITSEC_Mail {
|
|
|
4 |
private $content = '';
|
|
|
|
|
|
|
5 |
private $subject = '';
|
6 |
private $recipients = array();
|
7 |
private $attachments = array();
|
8 |
private $template_path = '';
|
9 |
|
10 |
+
public function __construct() {
|
11 |
$this->template_path = dirname( __FILE__ ) . '/mail-templates/';
|
|
|
12 |
}
|
13 |
|
14 |
public function add_header( $title, $banner_title, $use_site_logo = false ) {
|
31 |
'title' => $title,
|
32 |
);
|
33 |
|
34 |
+
$this->content .= $this->replace_all( $header, $replacements );
|
35 |
}
|
36 |
|
37 |
public function add_footer() {
|
74 |
|
75 |
);
|
76 |
|
77 |
+
$this->content .= $this->replace_all( $footer, $replacements );
|
78 |
|
79 |
if ( defined( 'ITSEC_DEBUG' ) && ITSEC_DEBUG ) {
|
80 |
$this->include_debug_info();
|
81 |
}
|
82 |
|
83 |
+
$this->content .= $this->get_template( 'close.html' );
|
84 |
}
|
85 |
|
86 |
public function add_user_footer() {
|
96 |
) );
|
97 |
|
98 |
$footer .= $this->get_template( 'close.html' );
|
99 |
+
$this->content .= $footer;
|
100 |
}
|
101 |
|
102 |
public function add_text( $content ) {
|
|
|
|
|
|
|
|
|
103 |
$module = $this->get_template( 'text.html' );
|
104 |
$module = $this->replace( $module, 'content', $content );
|
105 |
|
106 |
+
$this->content .= $module;
|
107 |
}
|
108 |
|
109 |
public function add_divider() {
|
110 |
+
$this->content .= $this->get_template( 'divider.html' );
|
|
|
|
|
|
|
|
|
111 |
}
|
112 |
|
113 |
public function add_large_text( $content ) {
|
|
|
|
|
|
|
|
|
114 |
$module = $this->get_template( 'large-text.html' );
|
115 |
$module = $this->replace( $module, 'content', $content );
|
116 |
|
117 |
+
$this->content .= $module;
|
118 |
}
|
119 |
|
120 |
public function add_info_box( $content, $icon_type = 'info' ) {
|
|
|
|
|
|
|
|
|
121 |
$icon_url = $this->get_image_url( $icon_type === 'warning' ? 'warning_icon_yellow' : "{$icon_type}_icon" );
|
122 |
|
123 |
$module = $this->get_template( 'info-box.html' );
|
124 |
$module = $this->replace_all( $module, compact( 'content', 'icon_url' ) );
|
125 |
|
126 |
+
$this->content .= $module;
|
127 |
}
|
128 |
|
129 |
public function add_details_box( $content ) {
|
|
|
|
|
|
|
|
|
130 |
$module = $this->get_template( 'details-box.html' );
|
131 |
$module = $this->replace( $module, 'content', $content );
|
132 |
|
133 |
+
$this->content .= $module;
|
134 |
}
|
135 |
|
136 |
public function add_large_code( $content ) {
|
|
|
|
|
|
|
|
|
137 |
$module = $this->get_template( 'large-code.html' );
|
138 |
$module = $this->replace( $module, 'content', $content );
|
139 |
|
140 |
+
$this->content .= $module;
|
141 |
}
|
142 |
|
143 |
public function add_section_heading( $content, $icon_type = false ) {
|
|
|
|
|
|
|
|
|
144 |
if ( empty( $icon_type ) ) {
|
145 |
$heading = $this->get_template( 'section-heading.html' );
|
146 |
$heading = $this->replace_all( $heading, compact( 'content' ) );
|
151 |
$heading = $this->replace_all( $heading, compact( 'content', 'icon_url' ) );
|
152 |
}
|
153 |
|
154 |
+
$this->content .= $heading;
|
155 |
}
|
156 |
|
157 |
public function add_lockouts_summary( $user_count, $host_count ) {
|
166 |
|
167 |
$lockouts = $this->replace_all( $lockouts, $replacements );
|
168 |
|
169 |
+
$this->content .= $lockouts;
|
170 |
}
|
171 |
|
172 |
public function add_file_change_summary( $added, $removed, $modified ) {
|
183 |
|
184 |
$lockouts = $this->replace_all( $lockouts, $replacements );
|
185 |
|
186 |
+
$this->content .= $lockouts;
|
187 |
}
|
188 |
|
189 |
public function add_button( $link_text, $href ) {
|
|
|
|
|
|
|
|
|
|
|
190 |
$module = $this->get_template( 'module-button.html' );
|
191 |
$module = $this->replace( $module, 'href', $href );
|
192 |
$module = $this->replace( $module, 'link_text', $link_text );
|
193 |
|
194 |
+
$this->content .= $module;
|
195 |
}
|
196 |
|
197 |
public function add_lockouts_table( $lockouts ) {
|
198 |
+
$entry = $this->get_template( 'lockouts-entry.html' );
|
199 |
$entries = '';
|
200 |
|
201 |
foreach ( $lockouts as $lockout ) {
|
213 |
$table = $this->get_template( 'lockouts-table.html' );
|
214 |
|
215 |
$replacements = array(
|
216 |
+
'heading_types' => __( 'Host/User', 'better-wp-security' ),
|
217 |
+
'heading_until' => __( 'Lockout in Effect Until', 'better-wp-security' ),
|
218 |
+
'heading_reason' => __( 'Reason', 'better-wp-security' ),
|
219 |
+
'entries' => $entries,
|
220 |
);
|
221 |
|
222 |
$table = $this->replace_all( $table, $replacements );
|
223 |
|
224 |
+
$this->content .= $table;
|
225 |
}
|
226 |
|
227 |
/**
|
231 |
* @param array[] $entries
|
232 |
*/
|
233 |
public function add_table( $headers, $entries ) {
|
|
|
|
|
|
|
|
|
234 |
|
235 |
$template = $this->get_template( 'table.html' );
|
236 |
$html = $this->build_table_header( $headers );
|
239 |
$html .= $this->build_table_row( $entry, count( $headers ) );
|
240 |
}
|
241 |
|
242 |
+
$this->content .= $this->replace( $template, 'html', $html );
|
243 |
}
|
244 |
|
245 |
/**
|
306 |
* @param bool $bold_first Whether to emphasize the first item of the list.
|
307 |
*/
|
308 |
public function add_list( $items, $bold_first = false ) {
|
|
|
|
|
|
|
|
|
309 |
|
310 |
$template = $this->get_template( 'list.html' );
|
311 |
$html = '';
|
314 |
$html .= $this->build_list_item( $item, $bold_first && 0 === $i );
|
315 |
}
|
316 |
|
317 |
+
$this->content .= $this->replace( $template, 'html', $html );
|
318 |
}
|
319 |
|
320 |
private function build_list_item( $item, $bold = false ) {
|
323 |
return "<li style=\"margin: 0; padding: 5px 10px;{$bold_tag}\">{$item}</li>";
|
324 |
}
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
/**
|
327 |
* Include debug info in the email.
|
328 |
*
|
329 |
* This is automatically included in non-user emails if ITSEC_DEBUG is turned on.
|
330 |
*/
|
331 |
public function include_debug_info() {
|
332 |
+
$this->add_text( sprintf( esc_html__( 'Debug info (source page): %s', 'better-wp-security' ), esc_url( $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
}
|
334 |
|
335 |
/**
|
358 |
$this->content = $content;
|
359 |
}
|
360 |
|
361 |
+
public function get_content() {
|
362 |
+
return $this->content;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
}
|
364 |
|
365 |
public function set_subject( $subject, $add_site_url = true ) {
|
396 |
}
|
397 |
|
398 |
public function set_default_recipients() {
|
399 |
+
$recipients = ITSEC_Modules::get_setting( 'global', 'notification_email' );
|
400 |
$this->set_recipients( $recipients );
|
401 |
}
|
402 |
|
421 |
$this->set_default_subject();
|
422 |
}
|
423 |
|
424 |
+
return wp_mail( $this->recipients, $this->subject, $this->content, array( 'Content-Type: text/html; charset=UTF-8' ), $this->attachments );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
}
|
426 |
|
427 |
/**
|
core/lib/class-itsec-scheduler-cron.php
CHANGED
@@ -12,19 +12,15 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
12 |
|
13 |
public function register_cron_schedules( $schedules ) {
|
14 |
|
15 |
-
$schedules[ 'itsec-' . self::
|
16 |
-
'display' => esc_html__( 'Twice Hourly', 'better-wp-security' ),
|
17 |
-
'interval' => HOUR_IN_SECONDS / 2,
|
18 |
-
);
|
19 |
-
$schedules[ 'itsec-' . self::S_FOUR_DAILY ] = array(
|
20 |
'display' => esc_html__( 'Four Times per Day', 'better-wp-security' ),
|
21 |
'interval' => DAY_IN_SECONDS / 4,
|
22 |
);
|
23 |
-
$schedules[ 'itsec-' . self::S_WEEKLY ]
|
24 |
'display' => esc_html__( 'Weekly', 'better-wp-security' ),
|
25 |
'interval' => WEEK_IN_SECONDS,
|
26 |
);
|
27 |
-
$schedules[ 'itsec-' . self::S_MONTHLY ]
|
28 |
'display' => esc_html__( 'Monthly', 'better-wp-security' ),
|
29 |
'interval' => MONTH_IN_SECONDS,
|
30 |
);
|
@@ -66,18 +62,20 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
66 |
$this->run_single_event_by_hash( $id, $this->hash_data( $data ) );
|
67 |
}
|
68 |
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
$opts = array( 'single' => true );
|
72 |
|
73 |
$storage = $this->get_options();
|
|
|
74 |
|
75 |
-
|
76 |
-
return;
|
77 |
-
}
|
78 |
-
|
79 |
-
$data = $storage['single'][ $id ][ $hash ]['data'];
|
80 |
-
$job = $this->make_job( $id, $data, $opts );
|
81 |
|
82 |
$this->unschedule_single( $id, $data );
|
83 |
$this->call_action( $job );
|
@@ -90,8 +88,6 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
90 |
}
|
91 |
|
92 |
if ( ! $crons = _get_cron_array() ) {
|
93 |
-
ITSEC_Lib::release_lock( 'scheduler' );
|
94 |
-
|
95 |
return;
|
96 |
}
|
97 |
|
@@ -101,14 +97,12 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
101 |
}
|
102 |
|
103 |
if ( get_transient( 'doing_cron' ) ) {
|
104 |
-
ITSEC_Lib::release_lock( 'scheduler' );
|
105 |
is_multisite() && restore_current_blog();
|
106 |
|
107 |
return;
|
108 |
}
|
109 |
|
110 |
if ( ITSEC_Lib::get_uncached_option( '_transient_doing_cron' ) ) {
|
111 |
-
ITSEC_Lib::release_lock( 'scheduler' );
|
112 |
is_multisite() && restore_current_blog();
|
113 |
|
114 |
return;
|
@@ -353,7 +347,6 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
353 |
'id' => $id,
|
354 |
'data' => $options['single'][ $id ][ $hash ]['data'],
|
355 |
'fire_at' => $timestamp,
|
356 |
-
'hash' => $hash,
|
357 |
);
|
358 |
}
|
359 |
}
|
12 |
|
13 |
public function register_cron_schedules( $schedules ) {
|
14 |
|
15 |
+
$schedules[ 'itsec-' . self::S_FOUR_DAILY ] = array(
|
|
|
|
|
|
|
|
|
16 |
'display' => esc_html__( 'Four Times per Day', 'better-wp-security' ),
|
17 |
'interval' => DAY_IN_SECONDS / 4,
|
18 |
);
|
19 |
+
$schedules[ 'itsec-' . self::S_WEEKLY ] = array(
|
20 |
'display' => esc_html__( 'Weekly', 'better-wp-security' ),
|
21 |
'interval' => WEEK_IN_SECONDS,
|
22 |
);
|
23 |
+
$schedules[ 'itsec-' . self::S_MONTHLY ] = array(
|
24 |
'display' => esc_html__( 'Monthly', 'better-wp-security' ),
|
25 |
'interval' => MONTH_IN_SECONDS,
|
26 |
);
|
62 |
$this->run_single_event_by_hash( $id, $this->hash_data( $data ) );
|
63 |
}
|
64 |
|
65 |
+
/**
|
66 |
+
* Run a single event.
|
67 |
+
*
|
68 |
+
* @param string $id
|
69 |
+
* @param string $hash
|
70 |
+
*/
|
71 |
+
private function run_single_event_by_hash( $id, $hash ) {
|
72 |
|
73 |
$opts = array( 'single' => true );
|
74 |
|
75 |
$storage = $this->get_options();
|
76 |
+
$data = $storage['single'][ $id ][ $hash ]['data'];
|
77 |
|
78 |
+
$job = $this->make_job( $id, $data, $opts );
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
$this->unschedule_single( $id, $data );
|
81 |
$this->call_action( $job );
|
88 |
}
|
89 |
|
90 |
if ( ! $crons = _get_cron_array() ) {
|
|
|
|
|
91 |
return;
|
92 |
}
|
93 |
|
97 |
}
|
98 |
|
99 |
if ( get_transient( 'doing_cron' ) ) {
|
|
|
100 |
is_multisite() && restore_current_blog();
|
101 |
|
102 |
return;
|
103 |
}
|
104 |
|
105 |
if ( ITSEC_Lib::get_uncached_option( '_transient_doing_cron' ) ) {
|
|
|
106 |
is_multisite() && restore_current_blog();
|
107 |
|
108 |
return;
|
347 |
'id' => $id,
|
348 |
'data' => $options['single'][ $id ][ $hash ]['data'],
|
349 |
'fire_at' => $timestamp,
|
|
|
350 |
);
|
351 |
}
|
352 |
}
|
core/lib/class-itsec-scheduler-page-load.php
CHANGED
@@ -159,7 +159,6 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
|
|
159 |
'id' => $id,
|
160 |
'data' => $event['data'],
|
161 |
'fire_at' => $event['fire_at'],
|
162 |
-
'hash' => $hash,
|
163 |
);
|
164 |
}
|
165 |
}
|
@@ -266,13 +265,6 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
|
|
266 |
}
|
267 |
|
268 |
public function run_single_event( $id, $data = array() ) {
|
269 |
-
$this->run_single_event_by_hash( $id, $this->hash_data( $data ) );
|
270 |
-
}
|
271 |
-
|
272 |
-
/**
|
273 |
-
* @inheritDoc
|
274 |
-
*/
|
275 |
-
public function run_single_event_by_hash( $id, $hash ) {
|
276 |
|
277 |
if ( $this->operating_data ) {
|
278 |
$clear_operating_data = false;
|
@@ -282,19 +274,12 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
|
|
282 |
$storage = $this->operating_data = $this->get_options();
|
283 |
}
|
284 |
|
285 |
-
|
286 |
-
if ( $clear_operating_data ) {
|
287 |
-
$this->operating_data = null;
|
288 |
-
}
|
289 |
-
|
290 |
-
return;
|
291 |
-
}
|
292 |
-
|
293 |
$event = $storage['single'][ $id ][ $hash ];
|
294 |
|
295 |
$job = $this->make_job( $id, $event['data'], array( 'single' => true ) );
|
296 |
|
297 |
-
$this->unschedule_single( $id, $
|
298 |
$this->call_action( $job );
|
299 |
|
300 |
if ( $clear_operating_data ) {
|
159 |
'id' => $id,
|
160 |
'data' => $event['data'],
|
161 |
'fire_at' => $event['fire_at'],
|
|
|
162 |
);
|
163 |
}
|
164 |
}
|
265 |
}
|
266 |
|
267 |
public function run_single_event( $id, $data = array() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
|
269 |
if ( $this->operating_data ) {
|
270 |
$clear_operating_data = false;
|
274 |
$storage = $this->operating_data = $this->get_options();
|
275 |
}
|
276 |
|
277 |
+
$hash = $this->hash_data( $data );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
$event = $storage['single'][ $id ][ $hash ];
|
279 |
|
280 |
$job = $this->make_job( $id, $event['data'], array( 'single' => true ) );
|
281 |
|
282 |
+
$this->unschedule_single( $id, $data );
|
283 |
$this->call_action( $job );
|
284 |
|
285 |
if ( $clear_operating_data ) {
|
core/lib/class-itsec-scheduler.php
CHANGED
@@ -2,7 +2,6 @@
|
|
2 |
|
3 |
abstract class ITSEC_Scheduler {
|
4 |
|
5 |
-
const S_TWICE_HOURLY = 'twice-hourly';
|
6 |
const S_HOURLY = 'hourly';
|
7 |
const S_FOUR_DAILY = 'four-daily';
|
8 |
const S_TWICE_DAILY = 'twice-daily';
|
@@ -141,7 +140,6 @@ abstract class ITSEC_Scheduler {
|
|
141 |
* - id: The ID the event was scheduled with.
|
142 |
* - data: The data the event was scheduled with.
|
143 |
* - fire_at: The time the event should be fired.
|
144 |
-
* - hash: The event's data hash.
|
145 |
*
|
146 |
* @return array
|
147 |
*/
|
@@ -170,16 +168,6 @@ abstract class ITSEC_Scheduler {
|
|
170 |
*/
|
171 |
abstract public function run_single_event( $id, $data = array() );
|
172 |
|
173 |
-
/**
|
174 |
-
* Run a single event by it's hash.
|
175 |
-
*
|
176 |
-
* @param string $id
|
177 |
-
* @param string $hash
|
178 |
-
*
|
179 |
-
* @return void
|
180 |
-
*/
|
181 |
-
abstract public function run_single_event_by_hash( $id, $hash );
|
182 |
-
|
183 |
/**
|
184 |
* Run any events that are due now.
|
185 |
*
|
@@ -338,8 +326,6 @@ abstract class ITSEC_Scheduler {
|
|
338 |
*/
|
339 |
final public function get_schedule_interval( $schedule ) {
|
340 |
switch ( $schedule ) {
|
341 |
-
case self::S_TWICE_HOURLY:
|
342 |
-
return HOUR_IN_SECONDS / 2;
|
343 |
case self::S_HOURLY:
|
344 |
return HOUR_IN_SECONDS;
|
345 |
case self::S_FOUR_DAILY:
|
2 |
|
3 |
abstract class ITSEC_Scheduler {
|
4 |
|
|
|
5 |
const S_HOURLY = 'hourly';
|
6 |
const S_FOUR_DAILY = 'four-daily';
|
7 |
const S_TWICE_DAILY = 'twice-daily';
|
140 |
* - id: The ID the event was scheduled with.
|
141 |
* - data: The data the event was scheduled with.
|
142 |
* - fire_at: The time the event should be fired.
|
|
|
143 |
*
|
144 |
* @return array
|
145 |
*/
|
168 |
*/
|
169 |
abstract public function run_single_event( $id, $data = array() );
|
170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
/**
|
172 |
* Run any events that are due now.
|
173 |
*
|
326 |
*/
|
327 |
final public function get_schedule_interval( $schedule ) {
|
328 |
switch ( $schedule ) {
|
|
|
|
|
329 |
case self::S_HOURLY:
|
330 |
return HOUR_IN_SECONDS;
|
331 |
case self::S_FOUR_DAILY:
|
core/lib/class-itsec-wp-list-table.php
CHANGED
@@ -757,9 +757,9 @@ class ITSEC_WP_List_Table {
|
|
757 |
}
|
758 |
|
759 |
if ( $disable_first ) {
|
760 |
-
$page_links[] = '<span class="tablenav-pages-navspan
|
761 |
} else {
|
762 |
-
$page_links[] = sprintf( "<a class='first-page
|
763 |
esc_url( remove_query_arg( 'paged', $current_url ) ),
|
764 |
__( 'First page' ),
|
765 |
'«'
|
@@ -767,9 +767,9 @@ class ITSEC_WP_List_Table {
|
|
767 |
}
|
768 |
|
769 |
if ( $disable_prev ) {
|
770 |
-
$page_links[] = '<span class="tablenav-pages-navspan
|
771 |
} else {
|
772 |
-
$page_links[] = sprintf( "<a class='prev-page
|
773 |
esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
|
774 |
__( 'Previous page' ),
|
775 |
'‹'
|
@@ -790,9 +790,9 @@ class ITSEC_WP_List_Table {
|
|
790 |
$page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
|
791 |
|
792 |
if ( $disable_next ) {
|
793 |
-
$page_links[] = '<span class="tablenav-pages-navspan
|
794 |
} else {
|
795 |
-
$page_links[] = sprintf( "<a class='next-page
|
796 |
esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
|
797 |
__( 'Next page' ),
|
798 |
'›'
|
@@ -800,9 +800,9 @@ class ITSEC_WP_List_Table {
|
|
800 |
}
|
801 |
|
802 |
if ( $disable_last ) {
|
803 |
-
$page_links[] = '<span class="tablenav-pages-navspan
|
804 |
} else {
|
805 |
-
$page_links[] = sprintf( "<a class='last-page
|
806 |
esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
|
807 |
__( 'Last page' ),
|
808 |
'»'
|
@@ -1134,7 +1134,9 @@ class ITSEC_WP_List_Table {
|
|
1134 |
<div class="tablenav <?php echo esc_attr( $which ); ?>">
|
1135 |
|
1136 |
<?php if ( $this->has_items() ): ?>
|
1137 |
-
<div class="alignleft actions bulkactions"
|
|
|
|
|
1138 |
<?php endif;
|
1139 |
$this->extra_tablenav( $which );
|
1140 |
$this->pagination( $which );
|
757 |
}
|
758 |
|
759 |
if ( $disable_first ) {
|
760 |
+
$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">«</span>';
|
761 |
} else {
|
762 |
+
$page_links[] = sprintf( "<a class='first-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
763 |
esc_url( remove_query_arg( 'paged', $current_url ) ),
|
764 |
__( 'First page' ),
|
765 |
'«'
|
767 |
}
|
768 |
|
769 |
if ( $disable_prev ) {
|
770 |
+
$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">‹</span>';
|
771 |
} else {
|
772 |
+
$page_links[] = sprintf( "<a class='prev-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
773 |
esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
|
774 |
__( 'Previous page' ),
|
775 |
'‹'
|
790 |
$page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
|
791 |
|
792 |
if ( $disable_next ) {
|
793 |
+
$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">›</span>';
|
794 |
} else {
|
795 |
+
$page_links[] = sprintf( "<a class='next-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
796 |
esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
|
797 |
__( 'Next page' ),
|
798 |
'›'
|
800 |
}
|
801 |
|
802 |
if ( $disable_last ) {
|
803 |
+
$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">»</span>';
|
804 |
} else {
|
805 |
+
$page_links[] = sprintf( "<a class='last-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
806 |
esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
|
807 |
__( 'Last page' ),
|
808 |
'»'
|
1134 |
<div class="tablenav <?php echo esc_attr( $which ); ?>">
|
1135 |
|
1136 |
<?php if ( $this->has_items() ): ?>
|
1137 |
+
<div class="alignleft actions bulkactions">
|
1138 |
+
<?php $this->bulk_actions( $which ); ?>
|
1139 |
+
</div>
|
1140 |
<?php endif;
|
1141 |
$this->extra_tablenav( $which );
|
1142 |
$this->pagination( $which );
|
core/lib/form.php
CHANGED
@@ -27,9 +27,6 @@ final class ITSEC_Form {
|
|
27 |
parse_str( $data['data']['--itsec-form-serialized-data'], $data );
|
28 |
}
|
29 |
|
30 |
-
if ( get_magic_quotes_gpc() ) {
|
31 |
-
$data = stripslashes_deep( $data );
|
32 |
-
}
|
33 |
|
34 |
$defaults = array(
|
35 |
'booleans' => false,
|
@@ -465,42 +462,6 @@ final class ITSEC_Form {
|
|
465 |
$this->add_custom_input( $var, $options );
|
466 |
}
|
467 |
|
468 |
-
public function add_canonical_roles( $var, $options = array() ) {
|
469 |
-
$roles = array(
|
470 |
-
'administrator' => translate_user_role( 'Administrator' ),
|
471 |
-
'editor' => translate_user_role( 'Editor' ),
|
472 |
-
'author' => translate_user_role( 'Author' ),
|
473 |
-
'contributor' => translate_user_role( 'Contributor' ),
|
474 |
-
'subscriber' => translate_user_role( 'Subscriber' ),
|
475 |
-
);
|
476 |
-
|
477 |
-
if ( isset( $options['value'] ) ) {
|
478 |
-
$options['value'] = wp_parse_args( $options['value'], $roles );
|
479 |
-
} else {
|
480 |
-
$options['value'] = $roles;
|
481 |
-
}
|
482 |
-
|
483 |
-
$this->add_select( $var, $options );
|
484 |
-
}
|
485 |
-
|
486 |
-
public function get_clean_var( $var ) {
|
487 |
-
$clean_var = trim( preg_replace( '/[^a-z0-9_]+/i', '-', $var ), '-' );
|
488 |
-
|
489 |
-
if ( ! empty( $this->input_group ) ) {
|
490 |
-
if ( false === strpos( $var, '[' ) ) {
|
491 |
-
$var = "[{$var}]";
|
492 |
-
} else {
|
493 |
-
$var = preg_replace( '/^([^\[]+)\[/', '[$1][', $var );
|
494 |
-
}
|
495 |
-
|
496 |
-
$var = "{$this->input_group}{$var}";
|
497 |
-
|
498 |
-
$clean_var = trim( preg_replace( '/[^a-z0-9_]+/i', '-', $var ), '-' );
|
499 |
-
}
|
500 |
-
|
501 |
-
return "itsec-$clean_var";
|
502 |
-
}
|
503 |
-
|
504 |
private function add_custom_input( $var, $options ) {
|
505 |
if ( empty( $options['type'] ) ) {
|
506 |
trigger_error( 'add_custom_input called without a type option set' );
|
27 |
parse_str( $data['data']['--itsec-form-serialized-data'], $data );
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
|
31 |
$defaults = array(
|
32 |
'booleans' => false,
|
462 |
$this->add_custom_input( $var, $options );
|
463 |
}
|
464 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
465 |
private function add_custom_input( $var, $options ) {
|
466 |
if ( empty( $options['type'] ) ) {
|
467 |
trigger_error( 'add_custom_input called without a type option set' );
|
core/lib/log-util.php
CHANGED
@@ -42,22 +42,6 @@ final class ITSEC_Log_Util {
|
|
42 |
global $wpdb;
|
43 |
|
44 |
|
45 |
-
$valid_columns = array(
|
46 |
-
'id',
|
47 |
-
'parent_id',
|
48 |
-
'module',
|
49 |
-
'type',
|
50 |
-
'code',
|
51 |
-
'timestamp',
|
52 |
-
'init_timestamp',
|
53 |
-
'remote_ip',
|
54 |
-
'user_id',
|
55 |
-
'url',
|
56 |
-
'memory_current',
|
57 |
-
'memory_peak',
|
58 |
-
);
|
59 |
-
|
60 |
-
|
61 |
$get_count = false;
|
62 |
$min_timestamp = false;
|
63 |
|
@@ -77,29 +61,27 @@ final class ITSEC_Log_Util {
|
|
77 |
$limit = max( 0, min( 100, intval( $limit ) ) );
|
78 |
$page = max( 1, intval( $page ) );
|
79 |
|
80 |
-
if ( is_array( $sort_by_column ) ) {
|
81 |
-
$regex_valid_columns = '(?:' . implode( '|', $valid_columns ) . ')';
|
82 |
-
|
83 |
-
foreach ( $sort_by_column as $index => $sort_by ) {
|
84 |
-
if ( in_array( $sort_by, $valid_columns ) ) {
|
85 |
-
$sort_by_column[$index] = "$sort_by DESC";
|
86 |
-
} else if ( ! preg_match( "/^$regex_valid_columns\s+(?:DESC|ASC)$/i", $sort_by ) ) {
|
87 |
-
unset( $sort_by_column[$index] );
|
88 |
-
}
|
89 |
-
}
|
90 |
-
|
91 |
-
if ( empty( $sort_by_column ) ) {
|
92 |
-
$sort_by_column = 'timestamp';
|
93 |
-
}
|
94 |
-
} else if ( ! in_array( $sort_by_column, $valid_columns ) ) {
|
95 |
-
$sort_by_column = 'timestamp';
|
96 |
-
}
|
97 |
-
|
98 |
$sort_direction = strtoupper( $sort_direction );
|
99 |
if ( ! in_array( $sort_direction, array( 'DESC', 'ASC' ) ) ) {
|
100 |
$sort_direction = 'DESC';
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
if ( false === $columns ) {
|
104 |
$columns = $valid_columns;
|
105 |
} else if ( 'all' === $columns ) {
|
42 |
global $wpdb;
|
43 |
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
$get_count = false;
|
46 |
$min_timestamp = false;
|
47 |
|
61 |
$limit = max( 0, min( 100, intval( $limit ) ) );
|
62 |
$page = max( 1, intval( $page ) );
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
$sort_direction = strtoupper( $sort_direction );
|
65 |
if ( ! in_array( $sort_direction, array( 'DESC', 'ASC' ) ) ) {
|
66 |
$sort_direction = 'DESC';
|
67 |
}
|
68 |
|
69 |
+
|
70 |
+
$valid_columns = array(
|
71 |
+
'id',
|
72 |
+
'parent_id',
|
73 |
+
'module',
|
74 |
+
'type',
|
75 |
+
'code',
|
76 |
+
'timestamp',
|
77 |
+
'init_timestamp',
|
78 |
+
'remote_ip',
|
79 |
+
'user_id',
|
80 |
+
'url',
|
81 |
+
'memory_current',
|
82 |
+
'memory_peak',
|
83 |
+
);
|
84 |
+
|
85 |
if ( false === $columns ) {
|
86 |
$columns = $valid_columns;
|
87 |
} else if ( 'all' === $columns ) {
|
core/lib/mail-templates/header.html
CHANGED
@@ -77,7 +77,6 @@
|
|
77 |
#security-guide a{font-weight:bold;}
|
78 |
#footer-source-details .container-cell{line-height:200%;padding-top:60px;padding-bottom:0;}
|
79 |
#footer-source-details a{font-size:11px;font-weight:bold;line-height:200%;}
|
80 |
-
.template-container {max-width: 600px !important;}
|
81 |
|
82 |
@media only screen and (max-width:600px){
|
83 |
body{width:100% !important;min-width:100% !important;}
|
77 |
#security-guide a{font-weight:bold;}
|
78 |
#footer-source-details .container-cell{line-height:200%;padding-top:60px;padding-bottom:0;}
|
79 |
#footer-source-details a{font-size:11px;font-weight:bold;line-height:200%;}
|
|
|
80 |
|
81 |
@media only screen and (max-width:600px){
|
82 |
body{width:100% !important;min-width:100% !important;}
|
core/lib/schema.php
CHANGED
@@ -96,6 +96,5 @@ CREATE TABLE {$wpdb->base_prefix}itsec_distributed_storage (
|
|
96 |
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_log;" );
|
97 |
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_lockouts;" );
|
98 |
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_temp;" );
|
99 |
-
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_distributed_storage;" );
|
100 |
}
|
101 |
}
|
96 |
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_log;" );
|
97 |
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_lockouts;" );
|
98 |
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_temp;" );
|
|
|
99 |
}
|
100 |
}
|
core/lib/settings.php
CHANGED
@@ -2,45 +2,45 @@
|
|
2 |
|
3 |
abstract class ITSEC_Settings {
|
4 |
protected $settings;
|
5 |
-
|
6 |
public function __construct() {
|
7 |
$this->load();
|
8 |
-
|
9 |
add_action( 'itsec-lib-clear-caches', array( $this, 'load' ), 0 );
|
10 |
}
|
11 |
-
|
12 |
abstract public function get_id();
|
13 |
abstract public function get_defaults();
|
14 |
protected function after_save() {}
|
15 |
protected function handle_settings_changes( $old_settings ) {}
|
16 |
-
|
17 |
public function export() {
|
18 |
return $this->settings;
|
19 |
}
|
20 |
-
|
21 |
public function import( $settings ) {
|
22 |
$this->set_all( $settings );
|
23 |
}
|
24 |
-
|
25 |
public function get( $name, $default = null ) {
|
26 |
if ( isset( $this->settings[$name] ) ) {
|
27 |
return $this->settings[$name];
|
28 |
}
|
29 |
-
|
30 |
return $default;
|
31 |
}
|
32 |
-
|
33 |
public function get_all() {
|
34 |
return $this->settings;
|
35 |
}
|
36 |
-
|
37 |
public function set( $name, $value ) {
|
38 |
$settings = $this->settings;
|
39 |
$settings[$name] = $value;
|
40 |
-
|
41 |
return $this->set_all( $settings );
|
42 |
}
|
43 |
-
|
44 |
public function set_all( $settings ) {
|
45 |
$retval = array(
|
46 |
'old_settings' => $this->settings,
|
@@ -49,47 +49,45 @@ abstract class ITSEC_Settings {
|
|
49 |
'messages' => array(),
|
50 |
'saved' => false,
|
51 |
);
|
52 |
-
|
53 |
$validator = ITSEC_Modules::get_validator( $this->get_id() );
|
54 |
-
|
55 |
if ( is_null( $validator ) ) {
|
56 |
$retval['errors'][] = new WP_Error( 'itsec-settings-missing-validator-for-' . $this->get_id(), sprintf( __( 'The data validator for %1$s is missing. Data for the module cannot be saved without the validator. This error could indicate a bad install of iThemes Security. Please remove the plugin and reinstall it. If this message persists, please contact support and send them this error message.', 'better-wp-security' ), $this->get_id() ) );
|
57 |
} else {
|
58 |
$validator->validate( $settings );
|
59 |
-
|
60 |
$retval['errors'] = $validator->get_errors();
|
61 |
$retval['messages'] = $validator->get_messages();
|
62 |
-
|
63 |
if ( $validator->can_save() ) {
|
64 |
$this->settings = $validator->get_settings();
|
65 |
-
|
66 |
ITSEC_Storage::set( $this->get_id(), $this->settings );
|
67 |
$this->after_save();
|
68 |
$this->handle_settings_changes( $retval['old_settings'] );
|
69 |
-
|
70 |
$retval['new_settings'] = $this->settings;
|
71 |
$retval['saved'] = true;
|
72 |
-
|
73 |
-
do_action( 'itsec-settings-updated', $this->get_id() );
|
74 |
} else {
|
75 |
ITSEC_Response::set_success( false );
|
76 |
}
|
77 |
}
|
78 |
-
|
79 |
ITSEC_Response::add_errors( $retval['errors'] );
|
80 |
ITSEC_Response::add_messages( $retval['messages'] );
|
81 |
-
|
82 |
return $retval;
|
83 |
}
|
84 |
-
|
85 |
public function load() {
|
86 |
$this->settings = ITSEC_Storage::get( $this->get_id() );
|
87 |
$defaults = $this->get_defaults();
|
88 |
-
|
89 |
if ( ! is_array( $this->settings ) ) {
|
90 |
$this->settings = array();
|
91 |
}
|
92 |
-
|
93 |
$this->settings = array_merge( $defaults, $this->settings );
|
94 |
}
|
95 |
}
|
2 |
|
3 |
abstract class ITSEC_Settings {
|
4 |
protected $settings;
|
5 |
+
|
6 |
public function __construct() {
|
7 |
$this->load();
|
8 |
+
|
9 |
add_action( 'itsec-lib-clear-caches', array( $this, 'load' ), 0 );
|
10 |
}
|
11 |
+
|
12 |
abstract public function get_id();
|
13 |
abstract public function get_defaults();
|
14 |
protected function after_save() {}
|
15 |
protected function handle_settings_changes( $old_settings ) {}
|
16 |
+
|
17 |
public function export() {
|
18 |
return $this->settings;
|
19 |
}
|
20 |
+
|
21 |
public function import( $settings ) {
|
22 |
$this->set_all( $settings );
|
23 |
}
|
24 |
+
|
25 |
public function get( $name, $default = null ) {
|
26 |
if ( isset( $this->settings[$name] ) ) {
|
27 |
return $this->settings[$name];
|
28 |
}
|
29 |
+
|
30 |
return $default;
|
31 |
}
|
32 |
+
|
33 |
public function get_all() {
|
34 |
return $this->settings;
|
35 |
}
|
36 |
+
|
37 |
public function set( $name, $value ) {
|
38 |
$settings = $this->settings;
|
39 |
$settings[$name] = $value;
|
40 |
+
|
41 |
return $this->set_all( $settings );
|
42 |
}
|
43 |
+
|
44 |
public function set_all( $settings ) {
|
45 |
$retval = array(
|
46 |
'old_settings' => $this->settings,
|
49 |
'messages' => array(),
|
50 |
'saved' => false,
|
51 |
);
|
52 |
+
|
53 |
$validator = ITSEC_Modules::get_validator( $this->get_id() );
|
54 |
+
|
55 |
if ( is_null( $validator ) ) {
|
56 |
$retval['errors'][] = new WP_Error( 'itsec-settings-missing-validator-for-' . $this->get_id(), sprintf( __( 'The data validator for %1$s is missing. Data for the module cannot be saved without the validator. This error could indicate a bad install of iThemes Security. Please remove the plugin and reinstall it. If this message persists, please contact support and send them this error message.', 'better-wp-security' ), $this->get_id() ) );
|
57 |
} else {
|
58 |
$validator->validate( $settings );
|
59 |
+
|
60 |
$retval['errors'] = $validator->get_errors();
|
61 |
$retval['messages'] = $validator->get_messages();
|
62 |
+
|
63 |
if ( $validator->can_save() ) {
|
64 |
$this->settings = $validator->get_settings();
|
65 |
+
|
66 |
ITSEC_Storage::set( $this->get_id(), $this->settings );
|
67 |
$this->after_save();
|
68 |
$this->handle_settings_changes( $retval['old_settings'] );
|
69 |
+
|
70 |
$retval['new_settings'] = $this->settings;
|
71 |
$retval['saved'] = true;
|
|
|
|
|
72 |
} else {
|
73 |
ITSEC_Response::set_success( false );
|
74 |
}
|
75 |
}
|
76 |
+
|
77 |
ITSEC_Response::add_errors( $retval['errors'] );
|
78 |
ITSEC_Response::add_messages( $retval['messages'] );
|
79 |
+
|
80 |
return $retval;
|
81 |
}
|
82 |
+
|
83 |
public function load() {
|
84 |
$this->settings = ITSEC_Storage::get( $this->get_id() );
|
85 |
$defaults = $this->get_defaults();
|
86 |
+
|
87 |
if ( ! is_array( $this->settings ) ) {
|
88 |
$this->settings = array();
|
89 |
}
|
90 |
+
|
91 |
$this->settings = array_merge( $defaults, $this->settings );
|
92 |
}
|
93 |
}
|
core/lib/validator.php
CHANGED
@@ -142,19 +142,6 @@ abstract class ITSEC_Validator {
|
|
142 |
if ( empty( $this->settings[$var] ) ) {
|
143 |
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
144 |
}
|
145 |
-
} elseif ( 'text' === $type || 'non-empty-text' === $type ) {
|
146 |
-
$string = (string) $this->settings[ $var ];
|
147 |
-
$string = wp_strip_all_tags( $string );
|
148 |
-
|
149 |
-
if ( $trim_value ) {
|
150 |
-
$string = trim( $string );
|
151 |
-
}
|
152 |
-
|
153 |
-
$this->settings[ $var ] = $string;
|
154 |
-
|
155 |
-
if ( 'non-empty-text' === $type && empty( $this->settings[ $var ] ) ) {
|
156 |
-
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
157 |
-
}
|
158 |
} else if ( 'array' === $type ) {
|
159 |
if ( ! is_array( $this->settings[$var] ) ) {
|
160 |
if ( empty( $this->settings[$var] ) ) {
|
@@ -318,32 +305,6 @@ abstract class ITSEC_Validator {
|
|
318 |
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $type ), 'better-wp-security' ), $name, $type );
|
319 |
$type = 'array';
|
320 |
}
|
321 |
-
} elseif ( 'canonical-roles' === $type ) {
|
322 |
-
$roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
|
323 |
-
|
324 |
-
if ( is_array( $this->settings[$var] ) ) {
|
325 |
-
$invalid_entries = array();
|
326 |
-
|
327 |
-
foreach ( $this->settings[$var] as $index => $entry ) {
|
328 |
-
$entry = sanitize_text_field( trim( $entry ) );
|
329 |
-
$this->settings[$var][$index] = $entry;
|
330 |
-
|
331 |
-
if ( empty( $entry ) ) {
|
332 |
-
unset( $this->settings[$var][$index] );
|
333 |
-
} else if ( ! in_array( $entry, $roles, true ) ) {
|
334 |
-
$invalid_entries[] = $entry;
|
335 |
-
}
|
336 |
-
}
|
337 |
-
|
338 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
339 |
-
|
340 |
-
if ( ! empty( $invalid_entries ) ) {
|
341 |
-
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
342 |
-
}
|
343 |
-
} else if ( ! in_array( $this->settings[$var], $roles, true ) ) {
|
344 |
-
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $roles ), 'better-wp-security' ), $name, $roles );
|
345 |
-
$type = 'array';
|
346 |
-
}
|
347 |
} else if ( 'newline-separated-array' === $type ) {
|
348 |
$this->settings[$var] = $this->convert_string_to_array( $this->settings[$var] );
|
349 |
|
@@ -427,44 +388,13 @@ abstract class ITSEC_Validator {
|
|
427 |
$error = wp_sprintf( _n( 'The following extension in %1$s is invalid: %2$l', 'The following extensions in %1$s are invalid: %2$l', count( $invalid_extensions ), 'better-wp-security' ), $name, $invalid_extensions );
|
428 |
}
|
429 |
}
|
430 |
-
} elseif ( is_string( $type ) && 0 === strpos( $type, 'cb-items:' ) ) {
|
431 |
-
|
432 |
-
list( , $method ) = explode( ':', $type );
|
433 |
-
|
434 |
-
if ( ! is_array( $this->settings[ $var ] ) ) {
|
435 |
-
$error = sprintf( __( 'The %1$s value must be an array.', 'better-wp-security' ), $name );
|
436 |
-
} else {
|
437 |
-
$invalid_entries = array();
|
438 |
-
|
439 |
-
foreach ( $this->settings[ $var ] as $index => $entry ) {
|
440 |
-
|
441 |
-
if ( empty( $entry ) ) {
|
442 |
-
unset( $this->settings[ $var ][ $index ] );
|
443 |
-
} else {
|
444 |
-
$result = $this->{$method}( $entry, $index );
|
445 |
-
|
446 |
-
if ( false === $result ) {
|
447 |
-
$invalid_entries[] = is_string( $entry ) ? $entry : $index;
|
448 |
-
} elseif ( is_wp_error( $result ) ) {
|
449 |
-
$invalid_entries[] = "'{$index}': {$result->get_error_message()}";
|
450 |
-
} else {
|
451 |
-
$this->settings[ $var ][ $index ] = $result;
|
452 |
-
}
|
453 |
-
}
|
454 |
-
}
|
455 |
-
|
456 |
-
if ( ! empty( $invalid_entries ) ) {
|
457 |
-
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
458 |
-
}
|
459 |
-
}
|
460 |
-
|
461 |
} else {
|
462 |
/* translators: 1: sanitize type, 2: input name */
|
463 |
$error = sprintf( __( 'An invalid sanitize type of "%1$s" was received for the %2$s input.', 'better-wp-security' ), $type, $name );
|
464 |
}
|
465 |
|
466 |
if ( false !== $error ) {
|
467 |
-
$this->add_error(
|
468 |
$this->vars_to_skip_validate_matching_types[] = $var;
|
469 |
|
470 |
if ( $prevent_save_on_error && ITSEC_Core::is_interactive() ) {
|
@@ -477,10 +407,6 @@ abstract class ITSEC_Validator {
|
|
477 |
return true;
|
478 |
}
|
479 |
|
480 |
-
protected function generate_error( $id, $var, $type, $error ) {
|
481 |
-
return new WP_Error( "itsec-validator-$id-invalid-type-$var-$type", $error );
|
482 |
-
}
|
483 |
-
|
484 |
final protected function convert_string_to_array( $string ) {
|
485 |
if ( is_string( $string ) ) {
|
486 |
$array = preg_split( "/[\r\n]+/", $string );
|
142 |
if ( empty( $this->settings[$var] ) ) {
|
143 |
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
144 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
} else if ( 'array' === $type ) {
|
146 |
if ( ! is_array( $this->settings[$var] ) ) {
|
147 |
if ( empty( $this->settings[$var] ) ) {
|
305 |
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $type ), 'better-wp-security' ), $name, $type );
|
306 |
$type = 'array';
|
307 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
} else if ( 'newline-separated-array' === $type ) {
|
309 |
$this->settings[$var] = $this->convert_string_to_array( $this->settings[$var] );
|
310 |
|
388 |
$error = wp_sprintf( _n( 'The following extension in %1$s is invalid: %2$l', 'The following extensions in %1$s are invalid: %2$l', count( $invalid_extensions ), 'better-wp-security' ), $name, $invalid_extensions );
|
389 |
}
|
390 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
} else {
|
392 |
/* translators: 1: sanitize type, 2: input name */
|
393 |
$error = sprintf( __( 'An invalid sanitize type of "%1$s" was received for the %2$s input.', 'better-wp-security' ), $type, $name );
|
394 |
}
|
395 |
|
396 |
if ( false !== $error ) {
|
397 |
+
$this->add_error( new WP_Error( "itsec-validator-$id-invalid-type-$var-$type", $error ) );
|
398 |
$this->vars_to_skip_validate_matching_types[] = $var;
|
399 |
|
400 |
if ( $prevent_save_on_error && ITSEC_Core::is_interactive() ) {
|
407 |
return true;
|
408 |
}
|
409 |
|
|
|
|
|
|
|
|
|
410 |
final protected function convert_string_to_array( $string ) {
|
411 |
if ( is_string( $string ) ) {
|
412 |
$array = preg_split( "/[\r\n]+/", $string );
|
core/lockout.php
CHANGED
@@ -84,6 +84,9 @@ final class ITSEC_Lockout {
|
|
84 |
//Set an error message on improper logout
|
85 |
add_action( 'login_head', array( $this, 'set_lockout_error' ) );
|
86 |
|
|
|
|
|
|
|
87 |
add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
|
88 |
add_filter( 'itsec-filter-itsec-get-everything-verbs', array( $this, 'register_sync_get_everything_verbs' ) );
|
89 |
|
@@ -129,7 +132,7 @@ final class ITSEC_Lockout {
|
|
129 |
|
130 |
$host = ITSEC_Lib::get_ip();
|
131 |
|
132 |
-
if ( $this->is_host_locked_out( $host )
|
133 |
$this->execute_lock();
|
134 |
}
|
135 |
}
|
84 |
//Set an error message on improper logout
|
85 |
add_action( 'login_head', array( $this, 'set_lockout_error' ) );
|
86 |
|
87 |
+
//Process clear lockout form
|
88 |
+
add_action( 'itsec_admin_init', array( $this, 'release_lockout' ) );
|
89 |
+
|
90 |
add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
|
91 |
add_filter( 'itsec-filter-itsec-get-everything-verbs', array( $this, 'register_sync_get_everything_verbs' ) );
|
92 |
|
132 |
|
133 |
$host = ITSEC_Lib::get_ip();
|
134 |
|
135 |
+
if ( $this->is_host_locked_out( $host ) ) {
|
136 |
$this->execute_lock();
|
137 |
}
|
138 |
}
|
core/modules/404-detection/class-itsec-four-oh-four.php
CHANGED
@@ -10,7 +10,7 @@ class ITSEC_Four_Oh_Four {
|
|
10 |
|
11 |
add_filter( 'itsec_lockout_modules', array( $this, 'register_lockout' ) );
|
12 |
|
13 |
-
add_action( '
|
14 |
}
|
15 |
|
16 |
/**
|
@@ -29,15 +29,19 @@ class ITSEC_Four_Oh_Four {
|
|
29 |
|
30 |
$uri = explode( '?', $_SERVER['REQUEST_URI'] );
|
31 |
|
32 |
-
if ( in_array( '/' . ITSEC_Lib::get_request_path(), $this->settings['white_list']
|
33 |
-
|
|
|
34 |
}
|
35 |
|
36 |
ITSEC_Log::add_notice( 'four_oh_four', 'found_404', array( 'SERVER' => $_SERVER ) );
|
37 |
|
38 |
-
if ( ! in_array( '.' . pathinfo( $uri[0], PATHINFO_EXTENSION ), $this->settings['types']
|
|
|
39 |
$itsec_lockout->do_lockout( 'four_oh_four' );
|
|
|
40 |
}
|
|
|
41 |
}
|
42 |
|
43 |
/**
|
10 |
|
11 |
add_filter( 'itsec_lockout_modules', array( $this, 'register_lockout' ) );
|
12 |
|
13 |
+
add_action( 'wp', array( $this, 'check_404' ), 9999 );
|
14 |
}
|
15 |
|
16 |
/**
|
29 |
|
30 |
$uri = explode( '?', $_SERVER['REQUEST_URI'] );
|
31 |
|
32 |
+
if ( in_array( '/' . ITSEC_Lib::get_request_path(), $this->settings['white_list'] ) ) {
|
33 |
+
// white listed page.
|
34 |
+
return;
|
35 |
}
|
36 |
|
37 |
ITSEC_Log::add_notice( 'four_oh_four', 'found_404', array( 'SERVER' => $_SERVER ) );
|
38 |
|
39 |
+
if ( ! in_array( '.' . pathinfo( $uri[0], PATHINFO_EXTENSION ), $this->settings['types'] ) ) {
|
40 |
+
|
41 |
$itsec_lockout->do_lockout( 'four_oh_four' );
|
42 |
+
|
43 |
}
|
44 |
+
|
45 |
}
|
46 |
|
47 |
/**
|
core/modules/404-detection/logs.php
CHANGED
@@ -4,7 +4,6 @@ final class ITSEC_Four_Oh_Four_Logs {
|
|
4 |
public function __construct() {
|
5 |
add_filter( 'itsec_logs_prepare_four_oh_four_entry_for_list_display', array( $this, 'filter_entry_for_list_display' ) );
|
6 |
add_filter( 'itsec_logs_prepare_four_oh_four_entry_for_details_display', array( $this, 'filter_entry_for_details_display' ), 10, 4 );
|
7 |
-
add_filter( 'itsec_logs_prepare_four_oh_four_filter_row_action_for_code', array( $this, 'code_row_action' ), 10, 2 );
|
8 |
}
|
9 |
|
10 |
public function filter_entry_for_list_display( $entry ) {
|
@@ -25,9 +24,5 @@ final class ITSEC_Four_Oh_Four_Logs {
|
|
25 |
|
26 |
return $details;
|
27 |
}
|
28 |
-
|
29 |
-
public function code_row_action( $vars, $entry ) {
|
30 |
-
return array( 'filters[10]' => "url|{$entry['url']}", 'filters[11]' => 'module|four_oh_four' );
|
31 |
-
}
|
32 |
}
|
33 |
new ITSEC_Four_Oh_Four_Logs();
|
4 |
public function __construct() {
|
5 |
add_filter( 'itsec_logs_prepare_four_oh_four_entry_for_list_display', array( $this, 'filter_entry_for_list_display' ) );
|
6 |
add_filter( 'itsec_logs_prepare_four_oh_four_entry_for_details_display', array( $this, 'filter_entry_for_details_display' ), 10, 4 );
|
|
|
7 |
}
|
8 |
|
9 |
public function filter_entry_for_list_display( $entry ) {
|
24 |
|
25 |
return $details;
|
26 |
}
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
new ITSEC_Four_Oh_Four_Logs();
|
core/modules/away-mode/class-itsec-away-mode.php
CHANGED
@@ -5,7 +5,7 @@ final class ITSEC_Away_Mode {
|
|
5 |
public function run() {
|
6 |
|
7 |
//Execute away mode functions on admin init
|
8 |
-
add_action( '
|
9 |
add_action( 'login_init', array( $this, 'run_active_check' ) );
|
10 |
|
11 |
add_filter( 'itsec_managed_files', array( $this, 'register_managed_file' ) );
|
@@ -78,11 +78,6 @@ final class ITSEC_Away_Mode {
|
|
78 |
* @return void
|
79 |
*/
|
80 |
public function run_active_check() {
|
81 |
-
|
82 |
-
if ( wp_doing_ajax() ) {
|
83 |
-
return;
|
84 |
-
}
|
85 |
-
|
86 |
$away_mode_details = self::is_active( true );
|
87 |
|
88 |
if ( $away_mode_details['active'] ) {
|
5 |
public function run() {
|
6 |
|
7 |
//Execute away mode functions on admin init
|
8 |
+
add_action( 'itsec_admin_init', array( $this, 'run_active_check' ) );
|
9 |
add_action( 'login_init', array( $this, 'run_active_check' ) );
|
10 |
|
11 |
add_filter( 'itsec_managed_files', array( $this, 'register_managed_file' ) );
|
78 |
* @return void
|
79 |
*/
|
80 |
public function run_active_check() {
|
|
|
|
|
|
|
|
|
|
|
81 |
$away_mode_details = self::is_active( true );
|
82 |
|
83 |
if ( $away_mode_details['active'] ) {
|
core/modules/file-change/class-itsec-file-change.php
CHANGED
@@ -77,7 +77,7 @@ class ITSEC_File_Change {
|
|
77 |
$hashes = ITSEC_Modules::get_setting( 'file-change', 'expected_hashes', array() );
|
78 |
$hash = @md5_file( $file );
|
79 |
|
80 |
-
if ( $hash
|
81 |
$hashes[ $file ] = $hash;
|
82 |
ITSEC_Modules::set_setting( 'file-change', 'expected_hashes', $hashes );
|
83 |
}
|
77 |
$hashes = ITSEC_Modules::get_setting( 'file-change', 'expected_hashes', array() );
|
78 |
$hash = @md5_file( $file );
|
79 |
|
80 |
+
if ( $hash ) {
|
81 |
$hashes[ $file ] = $hash;
|
82 |
ITSEC_Modules::set_setting( 'file-change', 'expected_hashes', $hashes );
|
83 |
}
|
core/modules/file-change/css/settings.css
CHANGED
@@ -90,17 +90,3 @@ UL.jqueryFileTree LI {
|
|
90 |
width : 100%;
|
91 |
}
|
92 |
}
|
93 |
-
|
94 |
-
#itsec-file-change-abort {
|
95 |
-
color: #a00;
|
96 |
-
text-decoration: none;
|
97 |
-
border-color: transparent;
|
98 |
-
box-shadow: none;
|
99 |
-
background: transparent;
|
100 |
-
}
|
101 |
-
|
102 |
-
#itsec-file-change-abort:hover {
|
103 |
-
background: #d54e21;
|
104 |
-
color: #fff;
|
105 |
-
border-color: #d54e21;
|
106 |
-
}
|
90 |
width : 100%;
|
91 |
}
|
92 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/file-change/js/settings-page.js
CHANGED
@@ -62,19 +62,4 @@ jQuery( document ).ready( function ( $ ) {
|
|
62 |
}
|
63 |
|
64 |
initializeScan();
|
65 |
-
|
66 |
-
$( document ).on( 'click', '#itsec-file-change-abort', function () {
|
67 |
-
var $this = $( this );
|
68 |
-
|
69 |
-
$this.prop( 'disabled', true );
|
70 |
-
|
71 |
-
itsecUtil.sendModuleAJAXRequest( 'file-change', { method: 'abort' }, function ( results ) {
|
72 |
-
var $button = $( '#itsec-file-change-one_time_check' );
|
73 |
-
$button.prop( 'disabled', false );
|
74 |
-
$button.prop( 'class', 'button-primary' );
|
75 |
-
$button.val( ITSECFileChangeScannerl10n.button_text );
|
76 |
-
|
77 |
-
$this.remove();
|
78 |
-
} );
|
79 |
-
} );
|
80 |
} );
|
62 |
}
|
63 |
|
64 |
initializeScan();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
} );
|
core/modules/file-change/logs.php
CHANGED
@@ -44,17 +44,7 @@ final class ITSEC_File_Change_Logs {
|
|
44 |
} elseif ( 'recovery-scheduled' === $code ) {
|
45 |
$entry['description'] = esc_html__( 'Recovery Scheduled', 'better-wp-security' );
|
46 |
} elseif ( 'file-scan-aborted' === $code ) {
|
47 |
-
|
48 |
-
if ( $user = get_userdata( $code_data[0] ) ) {
|
49 |
-
$by = $user->display_name;
|
50 |
-
} else {
|
51 |
-
$by = "#{$code_data[0]}";
|
52 |
-
}
|
53 |
-
|
54 |
-
$entry['description'] = sprintf( esc_html__( 'Scan Cancelled by %s', 'better-wp-security' ), $by );
|
55 |
-
} else {
|
56 |
-
$entry['description'] = esc_html__( 'Scan Failed', 'better-wp-security' );
|
57 |
-
}
|
58 |
} elseif ( 'rescheduling' === $code ) {
|
59 |
$entry['description'] = esc_html__( 'Rescheduling', 'better-wp-security' );
|
60 |
}
|
44 |
} elseif ( 'recovery-scheduled' === $code ) {
|
45 |
$entry['description'] = esc_html__( 'Recovery Scheduled', 'better-wp-security' );
|
46 |
} elseif ( 'file-scan-aborted' === $code ) {
|
47 |
+
$entry['description'] = esc_html__( 'Scan Failed', 'better-wp-security' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
} elseif ( 'rescheduling' === $code ) {
|
49 |
$entry['description'] = esc_html__( 'Rescheduling', 'better-wp-security' );
|
50 |
}
|
core/modules/file-change/scanner.php
CHANGED
@@ -21,6 +21,7 @@ do_action( 'itsec_load_file_change_scanner' );
|
|
21 |
class ITSEC_File_Change_Scanner {
|
22 |
|
23 |
const DESTROYED = 'itsec_file_change_scan_destroyed';
|
|
|
24 |
|
25 |
const C_ADMIN = 'admin';
|
26 |
const C_INCLUDES = 'includes';
|
@@ -286,7 +287,7 @@ class ITSEC_File_Change_Scanner {
|
|
286 |
$job_data['step'] = $store['step'];
|
287 |
$job_data['chunk'] = $store['chunk'];
|
288 |
|
289 |
-
if (
|
290 |
ITSEC_Log::add_debug( 'file_change', 'recovery-failed-first-loop' );
|
291 |
|
292 |
self::abort();
|
@@ -318,10 +319,8 @@ class ITSEC_File_Change_Scanner {
|
|
318 |
|
319 |
/**
|
320 |
* Abort an in-progress scan.
|
321 |
-
*
|
322 |
-
* @param bool $user_initiated
|
323 |
*/
|
324 |
-
public static function abort(
|
325 |
$storage = ITSEC_File_Change::make_progress_storage();
|
326 |
|
327 |
if ( 'file-change-fast' === $storage->get( 'id' ) ) {
|
@@ -335,20 +334,11 @@ class ITSEC_File_Change_Scanner {
|
|
335 |
ITSEC_Log::add_process_stop( $process, array( 'aborted' => true ) );
|
336 |
}
|
337 |
|
338 |
-
|
339 |
-
$
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
'chunk' => $storage->get( 'chunk' ),
|
344 |
-
) );
|
345 |
-
} else {
|
346 |
-
ITSEC_Log::add_fatal_error( 'file_change', 'file-scan-aborted', array(
|
347 |
-
'id' => $storage->get( 'id' ),
|
348 |
-
'step' => $storage->get( 'step' ),
|
349 |
-
'chunk' => $storage->get( 'chunk' ),
|
350 |
-
) );
|
351 |
-
}
|
352 |
|
353 |
$storage->clear();
|
354 |
update_site_option( self::DESTROYED, ITSEC_Core::get_current_time_gmt() );
|
21 |
class ITSEC_File_Change_Scanner {
|
22 |
|
23 |
const DESTROYED = 'itsec_file_change_scan_destroyed';
|
24 |
+
const FILE_LIST = 'itsec_file_list';
|
25 |
|
26 |
const C_ADMIN = 'admin';
|
27 |
const C_INCLUDES = 'includes';
|
287 |
$job_data['step'] = $store['step'];
|
288 |
$job_data['chunk'] = $store['chunk'];
|
289 |
|
290 |
+
if ( 'get-files' === $job_data['step'] && self::C_ADMIN === $job_data['chunk'] ) {
|
291 |
ITSEC_Log::add_debug( 'file_change', 'recovery-failed-first-loop' );
|
292 |
|
293 |
self::abort();
|
319 |
|
320 |
/**
|
321 |
* Abort an in-progress scan.
|
|
|
|
|
322 |
*/
|
323 |
+
public static function abort() {
|
324 |
$storage = ITSEC_File_Change::make_progress_storage();
|
325 |
|
326 |
if ( 'file-change-fast' === $storage->get( 'id' ) ) {
|
334 |
ITSEC_Log::add_process_stop( $process, array( 'aborted' => true ) );
|
335 |
}
|
336 |
|
337 |
+
ITSEC_Log::add_fatal_error( 'file_change', 'file-scan-aborted', array(
|
338 |
+
'id' => $storage->get( 'id' ),
|
339 |
+
'step' => $storage->get( 'step' ),
|
340 |
+
'chunk' => $storage->get( 'chunk' ),
|
341 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
|
343 |
$storage->clear();
|
344 |
update_site_option( self::DESTROYED, ITSEC_Core::get_current_time_gmt() );
|
core/modules/file-change/settings-page.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
final class ITSEC_File_Change_Settings_Page extends ITSEC_Module_Settings_Page {
|
4 |
-
private $script_version =
|
5 |
|
6 |
|
7 |
public function __construct() {
|
@@ -26,9 +26,8 @@ final class ITSEC_File_Change_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
26 |
require_once( dirname( __FILE__ ) . '/admin.php' );
|
27 |
}
|
28 |
|
29 |
-
ITSEC_Lib::enqueue_util();
|
30 |
ITSEC_File_Change_Admin::enqueue_scanner();
|
31 |
-
wp_enqueue_script( 'itsec-file-change-settings-script', plugins_url( 'js/settings-page.js', __FILE__ ), array( 'jquery', 'itsec-file-change-scanner'
|
32 |
wp_localize_script( 'itsec-file-change-settings-script', 'itsec_file_change_settings', $vars );
|
33 |
|
34 |
|
@@ -55,11 +54,6 @@ final class ITSEC_File_Change_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
55 |
} else {
|
56 |
ITSEC_Response::set_success( true );
|
57 |
}
|
58 |
-
} elseif ( 'abort' === $data['method'] ) {
|
59 |
-
require_once( dirname( __FILE__ ) . '/scanner.php' );
|
60 |
-
ITSEC_File_Change_Scanner::abort( true );
|
61 |
-
|
62 |
-
ITSEC_Response::set_success( true );
|
63 |
} else if ( 'get-filetree-data' === $data['method'] ) {
|
64 |
ITSEC_Response::set_response( $this->get_filetree_data( $data ) );
|
65 |
}
|
@@ -87,7 +81,7 @@ final class ITSEC_File_Change_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
87 |
|
88 |
require_once( dirname( __FILE__ ) . '/scanner.php' );
|
89 |
|
90 |
-
if (
|
91 |
$status = ITSEC_File_Change_Scanner::get_status();
|
92 |
|
93 |
$button = array(
|
@@ -104,12 +98,7 @@ final class ITSEC_File_Change_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
104 |
?>
|
105 |
<div class="hide-if-no-js">
|
106 |
<p><?php _e( "Press the button below to scan your site's files for changes. Note that if changes are found this will take you to the logs page for details.", 'better-wp-security' ); ?></p>
|
107 |
-
<p>
|
108 |
-
<?php $form->add_button( 'one_time_check', $button ); ?>
|
109 |
-
<?php if ( $is_running ) : ?>
|
110 |
-
<?php $form->add_button( 'abort', array( 'value' => _x( 'Cancel', 'Cancel File Change scan.', 'better-wp-security' ), 'class' => 'button' ) ); ?>
|
111 |
-
<?php endif; ?>
|
112 |
-
</p>
|
113 |
<div id="itsec_file_change_status"></div>
|
114 |
</div>
|
115 |
|
1 |
<?php
|
2 |
|
3 |
final class ITSEC_File_Change_Settings_Page extends ITSEC_Module_Settings_Page {
|
4 |
+
private $script_version = 3;
|
5 |
|
6 |
|
7 |
public function __construct() {
|
26 |
require_once( dirname( __FILE__ ) . '/admin.php' );
|
27 |
}
|
28 |
|
|
|
29 |
ITSEC_File_Change_Admin::enqueue_scanner();
|
30 |
+
wp_enqueue_script( 'itsec-file-change-settings-script', plugins_url( 'js/settings-page.js', __FILE__ ), array( 'jquery', 'itsec-file-change-scanner' ), $this->script_version, true );
|
31 |
wp_localize_script( 'itsec-file-change-settings-script', 'itsec_file_change_settings', $vars );
|
32 |
|
33 |
|
54 |
} else {
|
55 |
ITSEC_Response::set_success( true );
|
56 |
}
|
|
|
|
|
|
|
|
|
|
|
57 |
} else if ( 'get-filetree-data' === $data['method'] ) {
|
58 |
ITSEC_Response::set_response( $this->get_filetree_data( $data ) );
|
59 |
}
|
81 |
|
82 |
require_once( dirname( __FILE__ ) . '/scanner.php' );
|
83 |
|
84 |
+
if ( ITSEC_File_Change_Scanner::is_running() ) {
|
85 |
$status = ITSEC_File_Change_Scanner::get_status();
|
86 |
|
87 |
$button = array(
|
98 |
?>
|
99 |
<div class="hide-if-no-js">
|
100 |
<p><?php _e( "Press the button below to scan your site's files for changes. Note that if changes are found this will take you to the logs page for details.", 'better-wp-security' ); ?></p>
|
101 |
+
<p><?php $form->add_button( 'one_time_check', $button ); ?></p>
|
|
|
|
|
|
|
|
|
|
|
102 |
<div id="itsec_file_change_status"></div>
|
103 |
</div>
|
104 |
|
core/modules/global/active.php
CHANGED
@@ -157,23 +157,4 @@ function itsec_record_first_login( $username, $user ) {
|
|
157 |
}
|
158 |
}
|
159 |
|
160 |
-
add_action( 'wp_login', 'itsec_record_first_login', 15, 2 );
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Basename the 'thumb' for attachments to prevent directory traversal
|
164 |
-
* when deleting the main attachment.
|
165 |
-
*
|
166 |
-
* @param array $data
|
167 |
-
*
|
168 |
-
* @return array
|
169 |
-
*/
|
170 |
-
function itsec_basename_attachment_thumbs( $data ) {
|
171 |
-
|
172 |
-
if ( isset( $data['thumb'] ) && ITSEC_Modules::get_setting( 'wordpress-tweaks', 'patch_thumb_file_traversal' ) ) {
|
173 |
-
$data['thumb'] = basename( $data['thumb'] );
|
174 |
-
}
|
175 |
-
|
176 |
-
return $data;
|
177 |
-
}
|
178 |
-
|
179 |
-
add_filter( 'wp_update_attachment_metadata', 'itsec_basename_attachment_thumbs' );
|
157 |
}
|
158 |
}
|
159 |
|
160 |
+
add_action( 'wp_login', 'itsec_record_first_login', 15, 2 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/global/settings-page.php
CHANGED
@@ -73,11 +73,6 @@ final class ITSEC_Global_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
73 |
true => __( 'Yes' ),
|
74 |
);
|
75 |
|
76 |
-
$enable_grade_report_options = array(
|
77 |
-
false => __( 'No (default)' ),
|
78 |
-
true => __( 'Yes' ),
|
79 |
-
);
|
80 |
-
|
81 |
?>
|
82 |
<table class="form-table itsec-settings-section">
|
83 |
<tr>
|
@@ -247,15 +242,6 @@ final class ITSEC_Global_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
247 |
<p class="description"><?php _e( 'Each error message in iThemes Security has an associated error code that can help diagnose an issue. Changing this setting to "Yes" causes these codes to display. This setting should be left set to "No" unless iThemes Security support requests that you change it.', 'better-wp-security' ); ?></p>
|
248 |
</td>
|
249 |
</tr>
|
250 |
-
<?php if ( ITSEC_Core::is_pro() ) : ?>
|
251 |
-
<tr>
|
252 |
-
<th scope="row"><label for="itsec-global-enable_grade_report"><?php _e( 'Enable Grade Report', 'better-wp-security' ); ?></label></th>
|
253 |
-
<td>
|
254 |
-
<?php $form->add_select( 'enable_grade_report', $enable_grade_report_options ); ?>
|
255 |
-
<p class="description"><?php _e( 'The Grade Report feature can help you identify vulnerabilities on the site. Visit the Notification Center to select which users receive emails from this feature.', 'better-wp-security' ); ?></p>
|
256 |
-
</td>
|
257 |
-
</tr>
|
258 |
-
<?php endif; ?>
|
259 |
</table>
|
260 |
<?php
|
261 |
|
73 |
true => __( 'Yes' ),
|
74 |
);
|
75 |
|
|
|
|
|
|
|
|
|
|
|
76 |
?>
|
77 |
<table class="form-table itsec-settings-section">
|
78 |
<tr>
|
242 |
<p class="description"><?php _e( 'Each error message in iThemes Security has an associated error code that can help diagnose an issue. Changing this setting to "Yes" causes these codes to display. This setting should be left set to "No" unless iThemes Security support requests that you change it.', 'better-wp-security' ); ?></p>
|
243 |
</td>
|
244 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
</table>
|
246 |
<?php
|
247 |
|
core/modules/global/settings.php
CHANGED
@@ -35,7 +35,6 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
|
|
35 |
'cron_status' => - 1,
|
36 |
'use_cron' => true,
|
37 |
'cron_test_time' => 0,
|
38 |
-
'enable_grade_report' => false,
|
39 |
);
|
40 |
}
|
41 |
|
@@ -48,17 +47,6 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
|
|
48 |
if ( $this->settings['use_cron'] !== $old_settings['use_cron'] ) {
|
49 |
$this->handle_cron_change( $this->settings['use_cron'] );
|
50 |
}
|
51 |
-
|
52 |
-
if ( $this->settings['enable_grade_report'] && ! $old_settings['enable_grade_report'] ) {
|
53 |
-
update_site_option( 'itsec-enable-grade-report', true );
|
54 |
-
ITSEC_Modules::load_module_file( 'activate.php', 'grade-report' );
|
55 |
-
ITSEC_Response::flag_new_notifications_available();
|
56 |
-
ITSEC_Response::refresh_page();
|
57 |
-
} else if ( ! $this->settings['enable_grade_report'] && $old_settings['enable_grade_report'] ) {
|
58 |
-
update_site_option( 'itsec-enable-grade-report', false );
|
59 |
-
ITSEC_Modules::load_module_file( 'deactivate.php', 'grade-report' );
|
60 |
-
ITSEC_Response::refresh_page();
|
61 |
-
}
|
62 |
}
|
63 |
|
64 |
private function handle_cron_change( $new_use_cron ) {
|
35 |
'cron_status' => - 1,
|
36 |
'use_cron' => true,
|
37 |
'cron_test_time' => 0,
|
|
|
38 |
);
|
39 |
}
|
40 |
|
47 |
if ( $this->settings['use_cron'] !== $old_settings['use_cron'] ) {
|
48 |
$this->handle_cron_change( $this->settings['use_cron'] );
|
49 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
|
52 |
private function handle_cron_change( $new_use_cron ) {
|
core/modules/global/validator.php
CHANGED
@@ -21,7 +21,7 @@ class ITSEC_Global_Validator extends ITSEC_Validator {
|
|
21 |
|
22 |
$this->vars_to_skip_validate_matching_fields = array( 'digest_last_sent', 'digest_messages', 'digest_email', 'email_notifications', 'notification_email', 'backup_email', 'show_new_dashboard_notice' );
|
23 |
$this->set_previous_if_empty( array( 'did_upgrade', 'log_info', 'show_security_check', 'build', 'activation_timestamp', 'lock_file', 'cron_status', 'use_cron', 'cron_test_time' ) );
|
24 |
-
$this->set_default_if_empty( array( 'log_location', 'nginx_file'
|
25 |
$this->preserve_setting_if_exists( array( 'digest_email', 'email_notifications', 'notification_email', 'backup_email' ) );
|
26 |
|
27 |
|
@@ -31,7 +31,6 @@ class ITSEC_Global_Validator extends ITSEC_Validator {
|
|
31 |
$this->sanitize_setting( 'bool', 'proxy_override', __( 'Override Proxy Detection', 'better-wp-security' ) );
|
32 |
$this->sanitize_setting( 'bool', 'hide_admin_bar', __( 'Hide Security Menu in Admin Bar', 'better-wp-security' ) );
|
33 |
$this->sanitize_setting( 'bool', 'show_error_codes', __( 'Show Error Codes', 'better-wp-security' ) );
|
34 |
-
$this->sanitize_setting( 'bool', 'enable_grade_report', __( 'Enable Grade Report', 'better-wp-security' ) );
|
35 |
|
36 |
$this->sanitize_setting( 'string', 'lockout_message', __( 'Host Lockout Message', 'better-wp-security' ) );
|
37 |
$this->sanitize_setting( 'string', 'user_lockout_message', __( 'User Lockout Message', 'better-wp-security' ) );
|
21 |
|
22 |
$this->vars_to_skip_validate_matching_fields = array( 'digest_last_sent', 'digest_messages', 'digest_email', 'email_notifications', 'notification_email', 'backup_email', 'show_new_dashboard_notice' );
|
23 |
$this->set_previous_if_empty( array( 'did_upgrade', 'log_info', 'show_security_check', 'build', 'activation_timestamp', 'lock_file', 'cron_status', 'use_cron', 'cron_test_time' ) );
|
24 |
+
$this->set_default_if_empty( array( 'log_location', 'nginx_file' ) );
|
25 |
$this->preserve_setting_if_exists( array( 'digest_email', 'email_notifications', 'notification_email', 'backup_email' ) );
|
26 |
|
27 |
|
31 |
$this->sanitize_setting( 'bool', 'proxy_override', __( 'Override Proxy Detection', 'better-wp-security' ) );
|
32 |
$this->sanitize_setting( 'bool', 'hide_admin_bar', __( 'Hide Security Menu in Admin Bar', 'better-wp-security' ) );
|
33 |
$this->sanitize_setting( 'bool', 'show_error_codes', __( 'Show Error Codes', 'better-wp-security' ) );
|
|
|
34 |
|
35 |
$this->sanitize_setting( 'string', 'lockout_message', __( 'Host Lockout Message', 'better-wp-security' ) );
|
36 |
$this->sanitize_setting( 'string', 'user_lockout_message', __( 'User Lockout Message', 'better-wp-security' ) );
|
core/modules/notification-center/class-notification-center.php
CHANGED
@@ -71,14 +71,6 @@ final class ITSEC_Notification_Center {
|
|
71 |
public function get_notifications() {
|
72 |
|
73 |
if ( null === $this->notifications ) {
|
74 |
-
|
75 |
-
if ( ! did_action( 'itsec_initialized' ) ) {
|
76 |
-
ITSEC_Log::add_debug( 'core', 'doing-it-wrong', array(
|
77 |
-
'method' => __METHOD__,
|
78 |
-
'backtrace' => wp_debug_backtrace_summary(),
|
79 |
-
) );
|
80 |
-
}
|
81 |
-
|
82 |
/**
|
83 |
* Filter the registered notifications.
|
84 |
*
|
@@ -171,10 +163,9 @@ final class ITSEC_Notification_Center {
|
|
171 |
|
172 |
$schedules = self::get_schedule_order();
|
173 |
$schedule = array(
|
174 |
-
'min'
|
175 |
-
'max'
|
176 |
-
'default'
|
177 |
-
'setting_only' => false,
|
178 |
);
|
179 |
|
180 |
if ( $args['schedule'] === self::S_CONFIGURABLE ) {
|
@@ -326,39 +317,27 @@ final class ITSEC_Notification_Center {
|
|
326 |
}
|
327 |
|
328 |
$settings = $this->get_notification_settings( $notification );
|
329 |
-
|
330 |
-
if ( empty( $settings['recipient_type'] ) || 'custom' === $settings['recipient_type'] ) {
|
331 |
-
$contacts = $settings['user_list'];
|
332 |
-
} else {
|
333 |
-
$contacts = ITSEC_Modules::get_setting( 'notification-center', 'default_recipients' );
|
334 |
-
$contacts = isset( $contacts['user_list'] ) ? $contacts['user_list'] : array();
|
335 |
-
}
|
336 |
|
337 |
$addresses = array();
|
338 |
|
339 |
-
$users = array();
|
340 |
-
$roles = array();
|
341 |
-
|
342 |
foreach ( $contacts as $contact ) {
|
343 |
if ( (string) $contact === (string) intval( $contact ) ) {
|
344 |
-
$users
|
345 |
} else {
|
346 |
-
list( , $role ) = explode( ':', $contact, 2 );
|
347 |
|
348 |
if ( empty( $role ) ) {
|
349 |
continue;
|
350 |
}
|
351 |
|
352 |
-
$
|
353 |
}
|
354 |
-
}
|
355 |
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
if ( is_object( $user ) && ! empty( $user->user_email ) ) {
|
361 |
-
$addresses[] = $user->user_email;
|
362 |
}
|
363 |
}
|
364 |
|
@@ -382,18 +361,6 @@ final class ITSEC_Notification_Center {
|
|
382 |
return isset( $last_sent[ $notification ] ) ? $last_sent[ $notification ] : 0;
|
383 |
}
|
384 |
|
385 |
-
/**
|
386 |
-
* Update the last sent time for a notification.
|
387 |
-
*
|
388 |
-
* @param string $notification
|
389 |
-
*/
|
390 |
-
public function update_last_sent( $notification ) {
|
391 |
-
$setting = ITSEC_Modules::get_setting( 'notification-center', 'last_sent', array() );
|
392 |
-
$setting[ $notification ] = ITSEC_Core::get_current_time_gmt();
|
393 |
-
|
394 |
-
ITSEC_Modules::set_setting( 'notification-center', 'last_sent', $setting );
|
395 |
-
}
|
396 |
-
|
397 |
/**
|
398 |
* Get the time that the notification should next be sent.
|
399 |
*
|
@@ -419,7 +386,7 @@ final class ITSEC_Notification_Center {
|
|
419 |
$notification_data[] = $data;
|
420 |
|
421 |
if ( $enforce_unique ) {
|
422 |
-
$notification_data =
|
423 |
}
|
424 |
|
425 |
$all_data[ $notification ] = $notification_data;
|
@@ -444,14 +411,12 @@ final class ITSEC_Notification_Center {
|
|
444 |
/**
|
445 |
* Initialize a Mail instance.
|
446 |
*
|
447 |
-
* @param string $name
|
448 |
-
*
|
449 |
* @return ITSEC_Mail
|
450 |
*/
|
451 |
-
public function mail(
|
452 |
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-mail.php' );
|
453 |
|
454 |
-
return new ITSEC_Mail(
|
455 |
}
|
456 |
|
457 |
/**
|
@@ -478,11 +443,6 @@ final class ITSEC_Notification_Center {
|
|
478 |
|
479 |
add_action( 'wp_mail_failed', array( $this, 'capture_mail_fail' ) );
|
480 |
|
481 |
-
ITSEC_Log::add_debug( 'notification_center', "send::{$notification}", array(
|
482 |
-
'recipients' => $mail->get_recipients(),
|
483 |
-
'subject' => $mail->get_subject(),
|
484 |
-
) );
|
485 |
-
|
486 |
$this->_sending_notification = $notification;
|
487 |
$result = $mail->send();
|
488 |
$this->_sending_notification = '';
|
@@ -498,7 +458,9 @@ final class ITSEC_Notification_Center {
|
|
498 |
* @param string $error_id
|
499 |
*/
|
500 |
public function dismiss_mail_error( $error_id ) {
|
501 |
-
|
|
|
|
|
502 |
}
|
503 |
|
504 |
/**
|
@@ -507,10 +469,7 @@ final class ITSEC_Notification_Center {
|
|
507 |
* @return array
|
508 |
*/
|
509 |
public function get_mail_errors() {
|
510 |
-
|
511 |
-
_deprecated_function( __METHOD__, '4.7.1' );
|
512 |
-
|
513 |
-
return array();
|
514 |
}
|
515 |
|
516 |
/**
|
@@ -529,9 +488,15 @@ final class ITSEC_Notification_Center {
|
|
529 |
*/
|
530 |
public function capture_mail_fail( $error ) {
|
531 |
|
532 |
-
|
533 |
|
534 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
535 |
|
536 |
if ( ITSEC_Core::is_interactive() ) {
|
537 |
ITSEC_Response::reload_module( 'notification-center' );
|
@@ -693,13 +658,6 @@ final class ITSEC_Notification_Center {
|
|
693 |
*/
|
694 |
public function send_scheduled_notifications( $notification_slugs, $silent = false ) {
|
695 |
|
696 |
-
if ( doing_action( self::CRON_ACTION ) || doing_action( 'init' ) ) {
|
697 |
-
ITSEC_Log::add_debug( 'notification_center', 'send_scheduled', array(
|
698 |
-
'notifications' => $notification_slugs,
|
699 |
-
'silent' => $silent,
|
700 |
-
) );
|
701 |
-
}
|
702 |
-
|
703 |
@set_time_limit( 120 );
|
704 |
$sent = array();
|
705 |
|
@@ -921,10 +879,6 @@ final class ITSEC_Notification_Center {
|
|
921 |
return false; // This is an on-demand
|
922 |
}
|
923 |
|
924 |
-
if ( ( $config = $this->get_notification( $notification ) ) && is_array( $config['schedule'] ) && ! empty( $config['schedule']['setting_only'] ) ) {
|
925 |
-
return false;
|
926 |
-
}
|
927 |
-
|
928 |
switch ( $schedule ) {
|
929 |
case self::S_DAILY:
|
930 |
$period = DAY_IN_SECONDS;
|
71 |
public function get_notifications() {
|
72 |
|
73 |
if ( null === $this->notifications ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
/**
|
75 |
* Filter the registered notifications.
|
76 |
*
|
163 |
|
164 |
$schedules = self::get_schedule_order();
|
165 |
$schedule = array(
|
166 |
+
'min' => $schedules[0],
|
167 |
+
'max' => $schedules[ count( $schedules ) - 1 ],
|
168 |
+
'default' => self::S_DAILY,
|
|
|
169 |
);
|
170 |
|
171 |
if ( $args['schedule'] === self::S_CONFIGURABLE ) {
|
317 |
}
|
318 |
|
319 |
$settings = $this->get_notification_settings( $notification );
|
320 |
+
$contacts = $settings['user_list'];
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
|
322 |
$addresses = array();
|
323 |
|
|
|
|
|
|
|
324 |
foreach ( $contacts as $contact ) {
|
325 |
if ( (string) $contact === (string) intval( $contact ) ) {
|
326 |
+
$users = array( get_userdata( $contact ) );
|
327 |
} else {
|
328 |
+
list( $prefix, $role ) = explode( ':', $contact, 2 );
|
329 |
|
330 |
if ( empty( $role ) ) {
|
331 |
continue;
|
332 |
}
|
333 |
|
334 |
+
$users = get_users( array( 'role' => $role ) );
|
335 |
}
|
|
|
336 |
|
337 |
+
foreach ( $users as $user ) {
|
338 |
+
if ( is_object( $user ) && ! empty( $user->user_email ) ) {
|
339 |
+
$addresses[] = $user->user_email;
|
340 |
+
}
|
|
|
|
|
341 |
}
|
342 |
}
|
343 |
|
361 |
return isset( $last_sent[ $notification ] ) ? $last_sent[ $notification ] : 0;
|
362 |
}
|
363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
364 |
/**
|
365 |
* Get the time that the notification should next be sent.
|
366 |
*
|
386 |
$notification_data[] = $data;
|
387 |
|
388 |
if ( $enforce_unique ) {
|
389 |
+
$notification_data = array_unique( $notification_data, SORT_REGULAR );
|
390 |
}
|
391 |
|
392 |
$all_data[ $notification ] = $notification_data;
|
411 |
/**
|
412 |
* Initialize a Mail instance.
|
413 |
*
|
|
|
|
|
414 |
* @return ITSEC_Mail
|
415 |
*/
|
416 |
+
public function mail() {
|
417 |
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-mail.php' );
|
418 |
|
419 |
+
return new ITSEC_Mail();
|
420 |
}
|
421 |
|
422 |
/**
|
443 |
|
444 |
add_action( 'wp_mail_failed', array( $this, 'capture_mail_fail' ) );
|
445 |
|
|
|
|
|
|
|
|
|
|
|
446 |
$this->_sending_notification = $notification;
|
447 |
$result = $mail->send();
|
448 |
$this->_sending_notification = '';
|
458 |
* @param string $error_id
|
459 |
*/
|
460 |
public function dismiss_mail_error( $error_id ) {
|
461 |
+
$errors = ITSEC_Modules::get_setting( 'notification-center', 'mail_errors', array() );
|
462 |
+
unset( $errors[ $error_id ] );
|
463 |
+
ITSEC_Modules::set_setting( 'notification-center', 'mail_errors', $errors );
|
464 |
}
|
465 |
|
466 |
/**
|
469 |
* @return array
|
470 |
*/
|
471 |
public function get_mail_errors() {
|
472 |
+
return ITSEC_Modules::get_setting( 'notification-center', 'mail_errors', array() );
|
|
|
|
|
|
|
473 |
}
|
474 |
|
475 |
/**
|
488 |
*/
|
489 |
public function capture_mail_fail( $error ) {
|
490 |
|
491 |
+
$errors = ITSEC_Modules::get_setting( 'notification-center', 'mail_errors', array() );
|
492 |
|
493 |
+
$errors[ uniqid() ] = array(
|
494 |
+
'error' => array( 'message' => $error->get_error_message(), 'code' => $error->get_error_code() ),
|
495 |
+
'time' => ITSEC_Core::get_current_time_gmt(),
|
496 |
+
'notification' => $this->_sending_notification,
|
497 |
+
);
|
498 |
+
|
499 |
+
ITSEC_Modules::set_setting( 'notification-center', 'mail_errors', $errors );
|
500 |
|
501 |
if ( ITSEC_Core::is_interactive() ) {
|
502 |
ITSEC_Response::reload_module( 'notification-center' );
|
658 |
*/
|
659 |
public function send_scheduled_notifications( $notification_slugs, $silent = false ) {
|
660 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
661 |
@set_time_limit( 120 );
|
662 |
$sent = array();
|
663 |
|
879 |
return false; // This is an on-demand
|
880 |
}
|
881 |
|
|
|
|
|
|
|
|
|
882 |
switch ( $schedule ) {
|
883 |
case self::S_DAILY:
|
884 |
$period = DAY_IN_SECONDS;
|
core/modules/notification-center/debug.php
DELETED
@@ -1,92 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class ITSEC_Notification_Center_Debug
|
5 |
-
*/
|
6 |
-
class ITSEC_Notification_Center_Debug {
|
7 |
-
|
8 |
-
public function __construct() {
|
9 |
-
add_action( 'itsec_debug_page', array( $this, 'render' ) );
|
10 |
-
add_action( 'itsec_debug_page_enqueue', array( $this, 'enqueue_scripts_and_styles' ) );
|
11 |
-
add_action( 'itsec_debug_module_request_notification-center', array( $this, 'handle_ajax_request' ) );
|
12 |
-
}
|
13 |
-
|
14 |
-
public function enqueue_scripts_and_styles() {
|
15 |
-
wp_enqueue_script( 'itsec-notification-center-debug', plugins_url( 'js/debug.js', __FILE__ ), array( 'itsec-util' ), ITSEC_Core::get_plugin_build() );
|
16 |
-
}
|
17 |
-
|
18 |
-
public function handle_ajax_request( $data ) {
|
19 |
-
if ( empty( $data['id'] ) ) {
|
20 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-notification-center-missing-id', __( 'The server did not receive a valid request. The notification id is missing.', 'better-wp-security' ) ) );
|
21 |
-
|
22 |
-
return;
|
23 |
-
}
|
24 |
-
|
25 |
-
$result = ITSEC_Core::get_notification_center()->send_scheduled_notifications( array( $data['id'] ), ! empty( $data['silent'] ) );
|
26 |
-
|
27 |
-
if ( is_wp_error( $result ) ) {
|
28 |
-
ITSEC_Response::add_error( $result );
|
29 |
-
} elseif ( ! $result ) {
|
30 |
-
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-notification-center-send-failed', __( 'The server could not send the requested notification.', 'better-wp-security' ) ) );
|
31 |
-
} else {
|
32 |
-
ITSEC_Response::set_response( $this->get_table() );
|
33 |
-
ITSEC_Response::set_success( true );
|
34 |
-
ITSEC_Response::add_message( __( 'Notification sent.', 'better-wp-security' ) );
|
35 |
-
}
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Render our data to the Debug Page.
|
40 |
-
*/
|
41 |
-
public function render() {
|
42 |
-
?>
|
43 |
-
|
44 |
-
<div id="itsec-notification-center-notifications">
|
45 |
-
<h2><?php esc_html_e( 'Notification Center', 'better-wp-security' ); ?></h2>
|
46 |
-
<?php echo $this->get_table(); ?>
|
47 |
-
</div>
|
48 |
-
|
49 |
-
<?php
|
50 |
-
}
|
51 |
-
|
52 |
-
private function get_table() {
|
53 |
-
$nc = ITSEC_Core::get_notification_center();
|
54 |
-
ob_start();
|
55 |
-
?>
|
56 |
-
<table class="widefat striped">
|
57 |
-
<thead>
|
58 |
-
<tr>
|
59 |
-
<th><?php esc_html_e( 'ID', 'better-wp-security' ) ?></th>
|
60 |
-
<th><?php esc_html_e( 'Last Sent', 'better-wp-security' ) ?></th>
|
61 |
-
<th><?php esc_html_e( 'Next Send', 'better-wp-security' ) ?></th>
|
62 |
-
<th><?php esc_html_e( 'Schedule', 'better-wp-security' ) ?></th>
|
63 |
-
<th></th>
|
64 |
-
</tr>
|
65 |
-
</thead>
|
66 |
-
<tbody>
|
67 |
-
<?php foreach ( $nc->get_notifications() as $slug => $notification ) : $scheduled = ITSEC_Notification_Center::S_NONE !== $notification['schedule']; ?>
|
68 |
-
<tr>
|
69 |
-
<td><?php echo esc_html( $slug ); ?></td>
|
70 |
-
<td><?php echo $scheduled ? date( 'Y-m-d H:i:s', $nc->get_last_sent( $slug ) ) : '–'; ?></td>
|
71 |
-
<td><?php echo $scheduled && ( $next = $nc->get_next_send_time( $slug ) ) ? date( 'Y-m-d H:i:s', $next ) : '–'; ?></td>
|
72 |
-
<td><?php echo $nc->get_schedule( $slug ); ?></td>
|
73 |
-
<td>
|
74 |
-
<?php if ( $scheduled && ( ! is_array( $notification['schedule'] ) || empty( $notification['schedule']['setting_only'] ) ) ): ?>
|
75 |
-
<button class="button itsec__send-notification itsec__send-notification--force" data-id="<?php echo esc_attr( $slug ); ?>">
|
76 |
-
<?php esc_html_e( 'Force', 'better-wp-security' ) ?>
|
77 |
-
</button>
|
78 |
-
<button class="button itsec__send-notification itsec__send-notification--silent" data-id="<?php echo esc_attr( $slug ); ?>">
|
79 |
-
<?php esc_html_e( 'Silent', 'better-wp-security' ) ?>
|
80 |
-
</button>
|
81 |
-
<?php endif; ?>
|
82 |
-
</td>
|
83 |
-
</tr>
|
84 |
-
<?php endforeach; ?>
|
85 |
-
</tbody>
|
86 |
-
</table>
|
87 |
-
<?php
|
88 |
-
return ob_get_clean();
|
89 |
-
}
|
90 |
-
}
|
91 |
-
|
92 |
-
new ITSEC_Notification_Center_Debug();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/notification-center/js/debug.js
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
(function ( $, itsecUtil ) {
|
2 |
-
"use strict";
|
3 |
-
|
4 |
-
$( function () {
|
5 |
-
$( '#itsec-notification-center-notifications' ).on( 'click', '.button', function () {
|
6 |
-
|
7 |
-
var $btn = $( this );
|
8 |
-
$btn.prop( 'disabled', true );
|
9 |
-
|
10 |
-
itsecUtil.sendModuleAJAXRequest( 'notification-center', { id: $btn.data( 'id' ), silent: $btn.hasClass( 'itsec__send-notification--silent' ) ? 1 : 0 }, function ( response ) {
|
11 |
-
|
12 |
-
$btn.prop( 'disabled', false );
|
13 |
-
|
14 |
-
if ( response.success ) {
|
15 |
-
$( 'table', '#itsec-notification-center-notifications' ).replaceWith( response.response );
|
16 |
-
}
|
17 |
-
|
18 |
-
itsecUtil.displayNotices( response, $( '#itsec-messages' ) );
|
19 |
-
} );
|
20 |
-
} );
|
21 |
-
} );
|
22 |
-
})( jQuery, window.itsecUtil );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/notification-center/js/settings-page.js
CHANGED
@@ -5,8 +5,10 @@ jQuery( function ( $ ) {
|
|
5 |
} );
|
6 |
|
7 |
$( document ).on( 'itsec-dismiss-notice', '.itsec-notification-center-mail-errors-container .notice.itsec-is-dismissible', function () {
|
8 |
-
|
9 |
-
|
|
|
|
|
10 |
jQuery( '#itsec-module-card-notification-center' ).removeClass( 'itsec-module-status--warning' );
|
11 |
}
|
12 |
} )
|
@@ -33,10 +35,6 @@ jQuery( function ( $ ) {
|
|
33 |
}
|
34 |
}
|
35 |
|
36 |
-
$( document ).on( 'change', '.itsec-notification-center-user-list-type', function ( e ) {
|
37 |
-
$( this ).next().toggleClass( 'hidden' );
|
38 |
-
} );
|
39 |
-
|
40 |
itsecSettingsPage.events.on( 'modulesReloaded', initializeHiding );
|
41 |
itsecSettingsPage.events.on( 'moduleReloaded', function ( _, module ) {
|
42 |
if ( 'notification-center' === module ) {
|
5 |
} );
|
6 |
|
7 |
$( document ).on( 'itsec-dismiss-notice', '.itsec-notification-center-mail-errors-container .notice.itsec-is-dismissible', function () {
|
8 |
+
var errorId = $( this ).data( 'id' );
|
9 |
+
|
10 |
+
itsecUtil.sendModuleAJAXRequest( 'notification-center', { method: 'dismiss-mail-error', mail_error: errorId }, function ( r ) {
|
11 |
+
if ( r.response && r.response.status === 'all-cleared' ) {
|
12 |
jQuery( '#itsec-module-card-notification-center' ).removeClass( 'itsec-module-status--warning' );
|
13 |
}
|
14 |
} )
|
35 |
}
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
38 |
itsecSettingsPage.events.on( 'modulesReloaded', initializeHiding );
|
39 |
itsecSettingsPage.events.on( 'moduleReloaded', function ( _, module ) {
|
40 |
if ( 'notification-center' === module ) {
|
core/modules/notification-center/logs.php
DELETED
@@ -1,94 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class ITSEC_Notification_Center_Logs {
|
4 |
-
|
5 |
-
public function __construct() {
|
6 |
-
add_filter( 'itsec_logs_prepare_notification_center_entry_for_list_display', array( $this, 'filter_entry_for_list_display' ), 10, 3 );
|
7 |
-
add_filter( 'itsec_logs_prepare_notification_center_entry_for_details_display', array( $this, 'filter_entry_for_details_display' ), 10, 4 );
|
8 |
-
}
|
9 |
-
|
10 |
-
public function filter_entry_for_list_display( $entry, $code, $data ) {
|
11 |
-
|
12 |
-
$entry['module_display'] = esc_html__( 'Notification Center', 'better-wp-security' );
|
13 |
-
|
14 |
-
switch ( $code ) {
|
15 |
-
case 'send':
|
16 |
-
list ( $notification ) = $data;
|
17 |
-
|
18 |
-
if ( $strings = ITSEC_Core::get_notification_center()->get_notification_strings( $notification ) ) {
|
19 |
-
$notification = $strings['label'];
|
20 |
-
}
|
21 |
-
|
22 |
-
$entry['description'] = sprintf( esc_html__( 'Sending %s', 'better-wp-security' ), $notification );
|
23 |
-
break;
|
24 |
-
case 'send_failed':
|
25 |
-
list ( $notification ) = $data;
|
26 |
-
|
27 |
-
if ( $strings = ITSEC_Core::get_notification_center()->get_notification_strings( $notification ) ) {
|
28 |
-
$notification = $strings['label'];
|
29 |
-
}
|
30 |
-
|
31 |
-
$entry['description'] = sprintf( esc_html__( 'Sending %s Failed', 'better-wp-security' ), $notification );
|
32 |
-
break;
|
33 |
-
case 'send_scheduled':
|
34 |
-
$entry['description'] = esc_html__( 'Sending scheduled notifications', 'better-wp-security' );
|
35 |
-
break;
|
36 |
-
}
|
37 |
-
|
38 |
-
return $entry;
|
39 |
-
}
|
40 |
-
|
41 |
-
public function filter_entry_for_details_display( $details, $entry, $code, $code_data ) {
|
42 |
-
|
43 |
-
$details['module']['content'] = esc_html__( 'Notification Center', 'better-wp-security' );
|
44 |
-
|
45 |
-
switch ( $code ) {
|
46 |
-
case 'send':
|
47 |
-
list ( $notification ) = $code_data;
|
48 |
-
|
49 |
-
if ( $strings = ITSEC_Core::get_notification_center()->get_notification_strings( $notification ) ) {
|
50 |
-
$notification = $strings['label'];
|
51 |
-
}
|
52 |
-
|
53 |
-
$details['description']['content'] = esc_html__( 'Sending Notification', 'better-wp-security' );
|
54 |
-
$details['notification'] = array(
|
55 |
-
'header' => esc_html__( 'Notification', 'better-wp-security' ),
|
56 |
-
'content' => $notification,
|
57 |
-
'order' => 21,
|
58 |
-
);
|
59 |
-
break;
|
60 |
-
case 'send_failed':
|
61 |
-
list ( $notification ) = $code_data;
|
62 |
-
|
63 |
-
if ( $strings = ITSEC_Core::get_notification_center()->get_notification_strings( $notification ) ) {
|
64 |
-
$notification = $strings['label'];
|
65 |
-
}
|
66 |
-
|
67 |
-
$details['description']['content'] = esc_html__( 'Sending Notification Failed', 'better-wp-security' );
|
68 |
-
$details['notification'] = array(
|
69 |
-
'header' => esc_html__( 'Notification', 'better-wp-security' ),
|
70 |
-
'content' => $notification,
|
71 |
-
'order' => 21,
|
72 |
-
);
|
73 |
-
$details['error_message'] = array(
|
74 |
-
'header' => esc_html__( 'Error', 'better-wp-security' ),
|
75 |
-
'content' => wp_sprintf( '%l', ITSEC_Response::get_error_strings( $entry['data']['error'] ) ),
|
76 |
-
'order' => 22,
|
77 |
-
);
|
78 |
-
break;
|
79 |
-
case 'send_scheduled':
|
80 |
-
$details['description']['content'] = esc_html__( 'Sending Scheduled Notification', 'better-wp-security' );
|
81 |
-
$details['notifications'] = array(
|
82 |
-
'header' => esc_html__( 'Notifications', 'better-wp-security' ),
|
83 |
-
'content' => wp_sprintf( '%l', $entry['data']['notifications'] ),
|
84 |
-
'order' => 21,
|
85 |
-
);
|
86 |
-
break;
|
87 |
-
break;
|
88 |
-
}
|
89 |
-
|
90 |
-
return $details;
|
91 |
-
}
|
92 |
-
}
|
93 |
-
|
94 |
-
new ITSEC_Notification_Center_Logs();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/notification-center/settings-page.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page {
|
4 |
|
5 |
-
private $version =
|
6 |
|
7 |
/** @var ITSEC_Notification_Center_Validator */
|
8 |
private $validator;
|
@@ -19,7 +19,7 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
19 |
|
20 |
$this->validator = ITSEC_Modules::get_validator( 'notification-center' );
|
21 |
|
22 |
-
if (
|
23 |
$this->status = 'warning';
|
24 |
}
|
25 |
|
@@ -39,8 +39,15 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
39 |
|
40 |
switch ( $data['method'] ) {
|
41 |
case 'dismiss-mail-error':
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
break;
|
45 |
}
|
46 |
}
|
@@ -65,31 +72,10 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
65 |
|
66 |
<table class="form-table itsec-settings-section">
|
67 |
<tbody>
|
68 |
-
<tr>
|
69 |
-
<th><label for="itsec-notification-center-from_email"><?php esc_html_e( 'From Email', 'better-wp-security' ); ?></label></th>
|
70 |
-
<td>
|
71 |
-
<?php $form->add_text( 'from_email' ); ?>
|
72 |
-
<p class="description">
|
73 |
-
<?php esc_html_e( 'iThemes Security will send notifications from this email address. Leave blank to use the WordPress default.', 'better-wp-security' ); ?>
|
74 |
-
</p>
|
75 |
-
</td>
|
76 |
-
</tr>
|
77 |
-
<tr class="itsec-email-contacts-setting">
|
78 |
-
<th><label for="itsec-notification-center-default_recipients"><?php esc_html_e( 'Default Recipients', 'better-wp-security' ); ?></label></th>
|
79 |
-
<td>
|
80 |
-
<?php
|
81 |
-
$form->add_input_group( 'default_recipients' );
|
82 |
-
$this->render_user_list_fieldset( $form, ITSEC_Notification_Center::R_USER_LIST );
|
83 |
-
$form->remove_input_group();
|
84 |
-
?>
|
85 |
-
<p class="description">
|
86 |
-
<?php esc_html_e( 'Set the default recipients for any admin-facing notifications.', 'better-wp-security' ); ?>
|
87 |
-
</p>
|
88 |
-
</td>
|
89 |
-
</tr>
|
90 |
</tbody>
|
91 |
</table>
|
92 |
|
|
|
93 |
<?php
|
94 |
|
95 |
$notifications = ITSEC_Core::get_notification_center()->get_notifications();
|
@@ -103,20 +89,30 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
103 |
}
|
104 |
|
105 |
protected function render_mail_errors() {
|
106 |
-
|
|
|
|
|
107 |
return;
|
108 |
}
|
109 |
|
110 |
-
$link = esc_url( ITSEC_Core::get_logs_page_url( 'notification_center', 'error' ) );
|
111 |
?>
|
112 |
<div class="itsec-notification-center-mail-errors-container">
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
</div>
|
121 |
<?php
|
122 |
}
|
@@ -249,34 +245,6 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
249 |
* @param string $type
|
250 |
*/
|
251 |
protected function render_user_list( $slug, $form, $type ) {
|
252 |
-
?>
|
253 |
-
|
254 |
-
<tr class="itsec-email-contacts-setting">
|
255 |
-
<th><?php esc_html_e( 'Recipient', 'better-wp-security' ); ?></th>
|
256 |
-
<td>
|
257 |
-
<?php $form->add_select( 'recipient_type', array(
|
258 |
-
'class' => 'itsec-notification-center-user-list-type',
|
259 |
-
'value' => array(
|
260 |
-
'default' => esc_html__( 'Default Recipients', 'better-wp-security' ),
|
261 |
-
'custom' => esc_html__( 'Custom', 'better-wp-security' )
|
262 |
-
),
|
263 |
-
)
|
264 |
-
); ?>
|
265 |
-
<div class="<?php 'default' === $form->get_option( 'recipient_type' ) ? print( 'hidden' ) : null; ?>">
|
266 |
-
<?php $this->render_user_list_fieldset( $form, $type ); ?>
|
267 |
-
</div>
|
268 |
-
</td>
|
269 |
-
</tr>
|
270 |
-
<?php
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Render the User List fieldset control.
|
275 |
-
*
|
276 |
-
* @param ITSEC_Form $form
|
277 |
-
* @param string $type
|
278 |
-
*/
|
279 |
-
private function render_user_list_fieldset( $form, $type ) {
|
280 |
|
281 |
$users_and_roles = $this->validator->get_available_admin_users_and_roles();
|
282 |
|
@@ -284,55 +252,59 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
284 |
$roles = $users_and_roles['roles'];
|
285 |
|
286 |
natcasesort( $users );
|
287 |
-
|
288 |
?>
|
289 |
-
|
290 |
-
|
291 |
-
<
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
<
|
296 |
-
|
297 |
-
<?php $form->add_multi_checkbox( 'user_list', $role ); ?>
|
298 |
-
<?php echo esc_html( sprintf( _x( 'All %s users', 'role', 'better-wp-security' ), $name ) ); ?>
|
299 |
-
</label>
|
300 |
-
</li>
|
301 |
-
<?php endforeach; ?>
|
302 |
-
</ul>
|
303 |
-
|
304 |
-
<ul>
|
305 |
-
<?php foreach ( $users as $id => $name ) : ?>
|
306 |
-
<li>
|
307 |
-
<label>
|
308 |
-
<?php $form->add_multi_checkbox( 'user_list', $id ); ?>
|
309 |
-
<?php echo esc_html( $name ); ?>
|
310 |
-
</label>
|
311 |
-
</li>
|
312 |
-
<?php endforeach; ?>
|
313 |
-
</ul>
|
314 |
-
|
315 |
-
<?php if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $type && $form->get_option( 'previous_emails' ) ): ?>
|
316 |
-
|
317 |
-
<div class="itsec-notification-center--deprecated-recipients">
|
318 |
-
<span><?php esc_html_e( 'Deprecated Recipients', 'better-wp-security' ); ?></span>
|
319 |
-
<p class="description">
|
320 |
-
<?php esc_html_e( 'The following email recipients are deprecated. Please create new users for these email addresses or remove them.', 'better-wp-security' ); ?>
|
321 |
-
</p>
|
322 |
<ul>
|
323 |
-
<?php foreach ( $
|
324 |
<li>
|
325 |
<label>
|
326 |
-
<?php $form->add_multi_checkbox( '
|
327 |
-
<?php echo esc_html( $
|
328 |
</label>
|
329 |
</li>
|
330 |
<?php endforeach; ?>
|
331 |
</ul>
|
332 |
-
</div>
|
333 |
-
<?php endif; ?>
|
334 |
-
</fieldset>
|
335 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
<?php
|
337 |
}
|
338 |
|
2 |
|
3 |
class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page {
|
4 |
|
5 |
+
private $version = 1;
|
6 |
|
7 |
/** @var ITSEC_Notification_Center_Validator */
|
8 |
private $validator;
|
19 |
|
20 |
$this->validator = ITSEC_Modules::get_validator( 'notification-center' );
|
21 |
|
22 |
+
if ( ITSEC_Core::get_notification_center()->get_mail_errors() ) {
|
23 |
$this->status = 'warning';
|
24 |
}
|
25 |
|
39 |
|
40 |
switch ( $data['method'] ) {
|
41 |
case 'dismiss-mail-error':
|
42 |
+
|
43 |
+
if ( ! empty( $data['mail_error'] ) ) {
|
44 |
+
ITSEC_Core::get_notification_center()->dismiss_mail_error( $data['mail_error'] );
|
45 |
+
|
46 |
+
if ( ! ITSEC_Core::get_notification_center()->get_mail_errors() ) {
|
47 |
+
ITSEC_Response::set_response( array( 'status' => 'all-cleared' ) );
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
break;
|
52 |
}
|
53 |
}
|
72 |
|
73 |
<table class="form-table itsec-settings-section">
|
74 |
<tbody>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
</tbody>
|
76 |
</table>
|
77 |
|
78 |
+
|
79 |
<?php
|
80 |
|
81 |
$notifications = ITSEC_Core::get_notification_center()->get_notifications();
|
89 |
}
|
90 |
|
91 |
protected function render_mail_errors() {
|
92 |
+
$errors = ITSEC_Core::get_notification_center()->get_mail_errors();
|
93 |
+
|
94 |
+
if ( ! $errors ) {
|
95 |
return;
|
96 |
}
|
97 |
|
|
|
98 |
?>
|
99 |
<div class="itsec-notification-center-mail-errors-container">
|
100 |
+
<?php foreach ( $errors as $id => $error ):
|
101 |
+
$strings = ITSEC_Core::get_notification_center()->get_notification_strings( $error['notification'] );
|
102 |
+
$details = $error['error'];
|
103 |
+
|
104 |
+
if ( is_wp_error( $details ) ) {
|
105 |
+
$message = $details->get_error_message();
|
106 |
+
} elseif ( is_array( $error ) && isset( $details['message'] ) && is_string( $details['message'] ) ) {
|
107 |
+
$message = $details['message'];
|
108 |
+
} else {
|
109 |
+
$message = __( 'Unknown error encountered while sending.', 'better-wp-security' );
|
110 |
+
}
|
111 |
+
?>
|
112 |
+
<div class="notice notice-alt notice-error below-h2 itsec-is-dismissible itsec-notification-center-mail-error" data-id="<?php echo esc_attr( $id ); ?>">
|
113 |
+
<p><?php printf( esc_html__( 'Error while sending %1$s notification at %2$s: %3$s', 'better-wp-security' ), '<b>' . $strings['label'] . '</b>', '<b>' . ITSEC_Lib::date_format_i18n_and_local_timezone( $error['time'] ) . '</b>', $message ); ?></p>
|
114 |
+
</div>
|
115 |
+
<?php endforeach; ?>
|
116 |
</div>
|
117 |
<?php
|
118 |
}
|
245 |
* @param string $type
|
246 |
*/
|
247 |
protected function render_user_list( $slug, $form, $type ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
|
249 |
$users_and_roles = $this->validator->get_available_admin_users_and_roles();
|
250 |
|
252 |
$roles = $users_and_roles['roles'];
|
253 |
|
254 |
natcasesort( $users );
|
|
|
255 |
?>
|
256 |
+
|
257 |
+
<tr class="itsec-email-contacts-setting">
|
258 |
+
<th><?php esc_html_e( 'Recipient', 'better-wp-security' ); ?></th>
|
259 |
+
<td>
|
260 |
+
<fieldset>
|
261 |
+
<legend class="screen-reader-text"><?php esc_html_e( 'Recipients for this email.', 'better-wp-security' ); ?></legend>
|
262 |
+
<p><?php esc_html_e( 'Select which users should be emailed.', 'better-wp-security' ); ?></p>
|
263 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
<ul>
|
265 |
+
<?php foreach ( $roles as $role => $name ) : ?>
|
266 |
<li>
|
267 |
<label>
|
268 |
+
<?php $form->add_multi_checkbox( 'user_list', $role ); ?>
|
269 |
+
<?php echo esc_html( sprintf( _x( 'All %s users', 'role', 'better-wp-security' ), $name ) ); ?>
|
270 |
</label>
|
271 |
</li>
|
272 |
<?php endforeach; ?>
|
273 |
</ul>
|
|
|
|
|
|
|
274 |
|
275 |
+
<ul>
|
276 |
+
<?php foreach ( $users as $id => $name ) : ?>
|
277 |
+
<li>
|
278 |
+
<label>
|
279 |
+
<?php $form->add_multi_checkbox( 'user_list', $id ); ?>
|
280 |
+
<?php echo esc_html( $name ); ?>
|
281 |
+
</label>
|
282 |
+
</li>
|
283 |
+
<?php endforeach; ?>
|
284 |
+
</ul>
|
285 |
+
|
286 |
+
<?php if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $type && $form->get_option( 'previous_emails' ) ): ?>
|
287 |
+
|
288 |
+
<div class="itsec-notification-center--deprecated-recipients">
|
289 |
+
<span><?php esc_html_e( 'Deprecated Recipients', 'better-wp-security' ); ?></span>
|
290 |
+
<p class="description">
|
291 |
+
<?php esc_html_e( 'The following email recipients are deprecated. Please create new users for these email addresses or remove them.', 'better-wp-security' ); ?>
|
292 |
+
</p>
|
293 |
+
<ul>
|
294 |
+
<?php foreach ( $form->get_option( 'previous_emails' ) as $email ): ?>
|
295 |
+
<li>
|
296 |
+
<label>
|
297 |
+
<?php $form->add_multi_checkbox( 'previous_emails', $email ); ?>
|
298 |
+
<?php echo esc_html( $email ); ?>
|
299 |
+
</label>
|
300 |
+
</li>
|
301 |
+
<?php endforeach; ?>
|
302 |
+
</ul>
|
303 |
+
</div>
|
304 |
+
<?php endif; ?>
|
305 |
+
</fieldset>
|
306 |
+
</td>
|
307 |
+
</tr>
|
308 |
<?php
|
309 |
}
|
310 |
|
core/modules/notification-center/settings.php
CHANGED
@@ -18,24 +18,16 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
18 |
|
19 |
public function get_defaults() {
|
20 |
return array(
|
21 |
-
'last_sent'
|
22 |
-
'resend_at'
|
23 |
-
'data'
|
24 |
-
'
|
25 |
-
'notifications'
|
26 |
-
'admin_emails'
|
27 |
-
'from_email' => '',
|
28 |
-
'default_recipients' => array(
|
29 |
-
'user_list' => array( 'role:administrator' )
|
30 |
-
),
|
31 |
);
|
32 |
}
|
33 |
|
34 |
public function load() {
|
35 |
-
if ( ! class_exists( 'ITSEC_Notification_Center' ) ) {
|
36 |
-
ITSEC_Modules::load_module_file( 'active.php', 'notification-center' );
|
37 |
-
}
|
38 |
-
|
39 |
$this->settings = ITSEC_Storage::get( $this->get_id() );
|
40 |
$defaults = $this->get_defaults();
|
41 |
|
@@ -56,8 +48,6 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
56 |
|
57 |
$this->settings['notifications'][ $slug ] = $value;
|
58 |
}
|
59 |
-
|
60 |
-
unset( $this->settings['mail_errors'] );
|
61 |
}
|
62 |
|
63 |
public function refresh_notification_settings( $save = true ) {
|
@@ -73,78 +63,39 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
73 |
}
|
74 |
}
|
75 |
|
76 |
-
public function continue_upgrade(
|
77 |
-
|
78 |
$nc = ITSEC_Core::get_notification_center();
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
$this->refresh_notification_settings( false );
|
83 |
|
84 |
-
|
85 |
-
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
if ( $user && $user->has_cap( 'manage_options' ) ) {
|
91 |
-
$admin_users[] = $user->ID;
|
92 |
-
} else {
|
93 |
-
$admin_emails[] = $admin_email;
|
94 |
-
}
|
95 |
-
}
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
$this->settings['notifications'][ $slug ]['user_list'] = $admin_users;
|
102 |
-
} elseif ( $admin_emails ) {
|
103 |
-
$this->settings['notifications'][ $slug ]['user_list'] = array();
|
104 |
-
}
|
105 |
-
|
106 |
-
$this->settings['notifications'][ $slug ]['previous_emails'] = $admin_emails;
|
107 |
-
}
|
108 |
}
|
109 |
-
|
110 |
-
$this->set_all( $this->settings );
|
111 |
}
|
112 |
|
113 |
-
|
114 |
|
115 |
-
$
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
$settings['notifications'][ $slug ]['recipient_type'] = 'custom';
|
121 |
-
|
122 |
-
continue;
|
123 |
-
}
|
124 |
-
|
125 |
-
if ( ITSEC_Notification_Center::R_USER_LIST !== $config['recipient'] && ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE !== $config['recipient'] ) {
|
126 |
-
continue;
|
127 |
}
|
128 |
|
129 |
-
$
|
130 |
}
|
131 |
-
|
132 |
-
$unique_lists = ITSEC_Lib::non_scalar_array_unique( $user_lists );
|
133 |
-
|
134 |
-
if ( 1 === count( $unique_lists ) ) {
|
135 |
-
$settings['default_recipients'] = array( 'user_list' => reset( $unique_lists ) );
|
136 |
-
|
137 |
-
foreach ( $user_lists as $notification_slug => $_ ) {
|
138 |
-
$settings['notifications'][ $notification_slug ]['recipient_type'] = 'default';
|
139 |
-
}
|
140 |
-
} else {
|
141 |
-
foreach ( $user_lists as $notification_slug => $_ ) {
|
142 |
-
$settings['notifications'][ $notification_slug ]['recipient_type'] = 'custom';
|
143 |
-
}
|
144 |
-
}
|
145 |
-
|
146 |
-
$this->set_all( $settings );
|
147 |
}
|
|
|
|
|
148 |
}
|
149 |
|
150 |
/**
|
@@ -178,13 +129,12 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
178 |
}
|
179 |
|
180 |
if ( ITSEC_Notification_Center::R_USER_LIST === $notification['recipient'] ) {
|
181 |
-
$defaults['user_list']
|
182 |
-
$defaults['recipient_type'] = 'default';
|
183 |
}
|
184 |
|
185 |
if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $notification['recipient'] ) {
|
186 |
-
$defaults['user_list']
|
187 |
-
$defaults['
|
188 |
}
|
189 |
|
190 |
if ( ITSEC_Notification_Center::R_EMAIL_LIST === $notification['recipient'] ) {
|
18 |
|
19 |
public function get_defaults() {
|
20 |
return array(
|
21 |
+
'last_sent' => array(),
|
22 |
+
'resend_at' => array(),
|
23 |
+
'data' => array(),
|
24 |
+
'mail_errors' => array(),
|
25 |
+
'notifications' => array(),
|
26 |
+
'admin_emails' => array(),
|
|
|
|
|
|
|
|
|
27 |
);
|
28 |
}
|
29 |
|
30 |
public function load() {
|
|
|
|
|
|
|
|
|
31 |
$this->settings = ITSEC_Storage::get( $this->get_id() );
|
32 |
$defaults = $this->get_defaults();
|
33 |
|
48 |
|
49 |
$this->settings['notifications'][ $slug ] = $value;
|
50 |
}
|
|
|
|
|
51 |
}
|
52 |
|
53 |
public function refresh_notification_settings( $save = true ) {
|
63 |
}
|
64 |
}
|
65 |
|
66 |
+
public function continue_upgrade() {
|
|
|
67 |
$nc = ITSEC_Core::get_notification_center();
|
68 |
|
69 |
+
$nc->clear_notifications_cache();
|
70 |
+
$this->refresh_notification_settings( false );
|
|
|
71 |
|
72 |
+
$admin_users = array();
|
73 |
+
$admin_emails = array();
|
74 |
|
75 |
+
foreach ( $this->settings['admin_emails'] as $admin_email ) {
|
76 |
+
$user = get_user_by( 'email', $admin_email );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
+
if ( $user && $user->has_cap( 'manage_options' ) ) {
|
79 |
+
$admin_users[] = $user->ID;
|
80 |
+
} else {
|
81 |
+
$admin_emails[] = $admin_email;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
}
|
|
|
|
|
83 |
}
|
84 |
|
85 |
+
foreach ( $nc->get_notifications() as $slug => $notification ) {
|
86 |
|
87 |
+
if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $notification['recipient'] ) {
|
88 |
+
if ( $admin_users ) {
|
89 |
+
$this->settings['notifications'][ $slug ]['user_list'] = $admin_users;
|
90 |
+
} elseif ( $admin_emails ) {
|
91 |
+
$this->settings['notifications'][ $slug ]['user_list'] = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
}
|
93 |
|
94 |
+
$this->settings['notifications'][ $slug ]['previous_emails'] = $admin_emails;
|
95 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
}
|
97 |
+
|
98 |
+
$this->set_all( $this->settings );
|
99 |
}
|
100 |
|
101 |
/**
|
129 |
}
|
130 |
|
131 |
if ( ITSEC_Notification_Center::R_USER_LIST === $notification['recipient'] ) {
|
132 |
+
$defaults['user_list'] = array( 'role:administrator' );
|
|
|
133 |
}
|
134 |
|
135 |
if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $notification['recipient'] ) {
|
136 |
+
$defaults['user_list'] = array( 'role:administrator' );
|
137 |
+
$defaults['previous_emails'] = array();
|
138 |
}
|
139 |
|
140 |
if ( ITSEC_Notification_Center::R_EMAIL_LIST === $notification['recipient'] ) {
|
core/modules/notification-center/setup.php
CHANGED
@@ -2,11 +2,9 @@
|
|
2 |
|
3 |
class ITSEC_Notification_Center_Setup {
|
4 |
|
5 |
-
private $old_version;
|
6 |
-
|
7 |
public function __construct() {
|
8 |
add_action( 'itsec_modules_do_plugin_uninstall', array( $this, 'execute_uninstall' ) );
|
9 |
-
add_action( 'itsec_modules_do_plugin_upgrade', array( $this, 'execute_upgrade' )
|
10 |
}
|
11 |
|
12 |
/**
|
@@ -73,7 +71,6 @@ class ITSEC_Notification_Center_Setup {
|
|
73 |
|
74 |
ITSEC_Modules::set_settings( 'notification-center', $settings );
|
75 |
|
76 |
-
$this->old_version = $itsec_old_version;
|
77 |
add_action( 'itsec_initialized', array( $this, 'fire_continue_upgrade' ) );
|
78 |
} elseif ( $itsec_old_version < 4077 ) { // Only run this if user is updating from 4076 -> 4077
|
79 |
ITSEC_Modules::load_module_file( 'active.php', 'notification-center' );
|
@@ -116,24 +113,10 @@ class ITSEC_Notification_Center_Setup {
|
|
116 |
ITSEC_Modules::set_settings( 'notification-center', $settings );
|
117 |
}
|
118 |
}
|
119 |
-
|
120 |
-
if ( $itsec_old_version < 4099 ) {
|
121 |
-
ITSEC_Modules::load_module_file( 'active.php', 'notification-center' );
|
122 |
-
|
123 |
-
$settings = ITSEC_Modules::get_settings( 'notification-center' );
|
124 |
-
unset( $settings['mail_errors'] );
|
125 |
-
ITSEC_Modules::set_settings( 'notification-center', $settings );
|
126 |
-
}
|
127 |
-
|
128 |
-
if ( $itsec_old_version < 4101 ) {
|
129 |
-
$this->old_version = $itsec_old_version;
|
130 |
-
add_action( 'itsec_initialized', array( $this, 'fire_continue_upgrade' ) );
|
131 |
-
}
|
132 |
}
|
133 |
|
134 |
public function fire_continue_upgrade() {
|
135 |
-
|
136 |
-
do_action( 'itsec_notification_center_continue_upgrade', $this->old_version );
|
137 |
}
|
138 |
}
|
139 |
|
2 |
|
3 |
class ITSEC_Notification_Center_Setup {
|
4 |
|
|
|
|
|
5 |
public function __construct() {
|
6 |
add_action( 'itsec_modules_do_plugin_uninstall', array( $this, 'execute_uninstall' ) );
|
7 |
+
add_action( 'itsec_modules_do_plugin_upgrade', array( $this, 'execute_upgrade' ) );
|
8 |
}
|
9 |
|
10 |
/**
|
71 |
|
72 |
ITSEC_Modules::set_settings( 'notification-center', $settings );
|
73 |
|
|
|
74 |
add_action( 'itsec_initialized', array( $this, 'fire_continue_upgrade' ) );
|
75 |
} elseif ( $itsec_old_version < 4077 ) { // Only run this if user is updating from 4076 -> 4077
|
76 |
ITSEC_Modules::load_module_file( 'active.php', 'notification-center' );
|
113 |
ITSEC_Modules::set_settings( 'notification-center', $settings );
|
114 |
}
|
115 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
}
|
117 |
|
118 |
public function fire_continue_upgrade() {
|
119 |
+
do_action( 'itsec_notification_center_continue_upgrade' );
|
|
|
120 |
}
|
121 |
}
|
122 |
|
core/modules/notification-center/validator.php
CHANGED
@@ -13,51 +13,11 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
13 |
}
|
14 |
|
15 |
protected function sanitize_settings() {
|
16 |
-
$this->vars_to_skip_validate_matching_fields = array( 'last_sent', 'data', 'resend_at', '
|
17 |
$this->set_previous_if_empty( array( 'last_sent', 'data', 'resend_at', 'admin_emails' ) );
|
18 |
|
19 |
-
if ( ! isset( $this->settings['
|
20 |
-
$this->settings['
|
21 |
-
}
|
22 |
-
|
23 |
-
// We allow an empty email string.
|
24 |
-
if ( ! empty( $this->settings['from_email'] ) ) {
|
25 |
-
$this->sanitize_setting( 'email', 'from_email', __( 'Admin Email', 'better-wp-security' ) );
|
26 |
-
}
|
27 |
-
|
28 |
-
if ( $this->sanitize_setting( 'array', 'default_recipients', esc_html__( 'Default Recipients', 'better-wp-security' ) ) ) {
|
29 |
-
if ( empty( $this->settings['default_recipients']['user_list'] ) ) {
|
30 |
-
$this->add_error( new WP_Error(
|
31 |
-
'itsec-validator-notification-center-invalid-type-default_recipients[user_list]-non-empty',
|
32 |
-
esc_html__( 'Selecting "Default Recipients" is required.', 'better-wp-security' )
|
33 |
-
) );
|
34 |
-
|
35 |
-
if ( ITSEC_Core::is_interactive() ) {
|
36 |
-
$this->set_can_save( false );
|
37 |
-
}
|
38 |
-
} else {
|
39 |
-
$users_and_roles = $this->get_available_admin_users_and_roles();
|
40 |
-
$valid_contacts = $users_and_roles['users'] + $users_and_roles['roles'];
|
41 |
-
|
42 |
-
$contact_errors = array();
|
43 |
-
|
44 |
-
foreach ( $this->settings['default_recipients']['user_list'] as $contact ) {
|
45 |
-
if ( ! isset( $valid_contacts[ $contact ] ) ) {
|
46 |
-
$contact_errors[] = $contact;
|
47 |
-
}
|
48 |
-
}
|
49 |
-
|
50 |
-
if ( $contact_errors ) {
|
51 |
-
$this->add_error( new WP_Error(
|
52 |
-
'itsec-validator-notification-center-invalid-type-default_recipients[user_list]-invalid-contacts',
|
53 |
-
wp_sprintf( esc_html__( 'Unknown Default Recipients contacts, %l.', 'better-wp-security' ), $contact_errors )
|
54 |
-
) );
|
55 |
-
|
56 |
-
if ( ITSEC_Core::is_interactive() ) {
|
57 |
-
$this->set_can_save( false );
|
58 |
-
}
|
59 |
-
}
|
60 |
-
}
|
61 |
}
|
62 |
|
63 |
if ( ! $this->sanitize_setting( 'array', 'notifications', esc_html__( 'Notifications', 'better-wp-security' ) ) ) {
|
@@ -76,7 +36,7 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
76 |
$strings = ITSEC_Core::get_notification_center()->get_notification_strings( $notification );
|
77 |
|
78 |
if ( ITSEC_Notification_Center::R_USER_LIST !== $config['recipient'] && ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE !== $config['recipient'] ) {
|
79 |
-
unset( $settings['user_list']
|
80 |
} else {
|
81 |
if ( ! is_array( $settings['user_list'] ) ) {
|
82 |
$settings['user_list'] = array();
|
@@ -111,19 +71,6 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
111 |
$this->set_can_save( false );
|
112 |
}
|
113 |
}
|
114 |
-
|
115 |
-
if ( ! isset( $settings['recipient_type'] ) ) {
|
116 |
-
$settings['recipient_type'] = 'default';
|
117 |
-
} elseif ( ! in_array( $settings['recipient_type'], array( 'default', 'custom' ), true ) ) {
|
118 |
-
$this->add_error( new WP_Error(
|
119 |
-
'itsec-validator-notification-center-invalid-type-notifications[recipient_type]-array',
|
120 |
-
wp_sprintf( esc_html__( 'Unknown recipient type for %s.', 'better-wp-security' ), $strings['label'] )
|
121 |
-
) );
|
122 |
-
|
123 |
-
if ( ITSEC_Core::is_interactive() ) {
|
124 |
-
$this->set_can_save( false );
|
125 |
-
}
|
126 |
-
}
|
127 |
}
|
128 |
|
129 |
if ( ITSEC_Notification_Center::R_EMAIL_LIST !== $config['recipient'] ) {
|
@@ -294,10 +241,8 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
294 |
$available_roles = array();
|
295 |
$available_users = array();
|
296 |
|
297 |
-
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
298 |
-
|
299 |
foreach ( $roles->roles as $role => $details ) {
|
300 |
-
if (
|
301 |
$available_roles["role:$role"] = translate_user_role( $details['name'] );
|
302 |
|
303 |
$users = get_users( array( 'role' => $role ) );
|
13 |
}
|
14 |
|
15 |
protected function sanitize_settings() {
|
16 |
+
$this->vars_to_skip_validate_matching_fields = array( 'last_sent', 'data', 'resend_at', 'mail_errors', 'admin_emails' );
|
17 |
$this->set_previous_if_empty( array( 'last_sent', 'data', 'resend_at', 'admin_emails' ) );
|
18 |
|
19 |
+
if ( ! isset( $this->settings['mail_errors'] ) ) {
|
20 |
+
$this->settings['mail_errors'] = $this->previous_settings['mail_errors'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
}
|
22 |
|
23 |
if ( ! $this->sanitize_setting( 'array', 'notifications', esc_html__( 'Notifications', 'better-wp-security' ) ) ) {
|
36 |
$strings = ITSEC_Core::get_notification_center()->get_notification_strings( $notification );
|
37 |
|
38 |
if ( ITSEC_Notification_Center::R_USER_LIST !== $config['recipient'] && ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE !== $config['recipient'] ) {
|
39 |
+
unset( $settings['user_list'] );
|
40 |
} else {
|
41 |
if ( ! is_array( $settings['user_list'] ) ) {
|
42 |
$settings['user_list'] = array();
|
71 |
$this->set_can_save( false );
|
72 |
}
|
73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
}
|
75 |
|
76 |
if ( ITSEC_Notification_Center::R_EMAIL_LIST !== $config['recipient'] ) {
|
241 |
$available_roles = array();
|
242 |
$available_users = array();
|
243 |
|
|
|
|
|
244 |
foreach ( $roles->roles as $role => $details ) {
|
245 |
+
if ( ! empty( $details['capabilities']['manage_options'] ) ) {
|
246 |
$available_roles["role:$role"] = translate_user_role( $details['name'] );
|
247 |
|
248 |
$users = get_users( array( 'role' => $role ) );
|
core/modules/password-requirements/active.php
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
require_once( dirname( __FILE__ ) . '/class-itsec-password-requirements.php' );
|
4 |
-
|
5 |
-
$requirements = new ITSEC_Password_Requirements();
|
6 |
-
$requirements->run();
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/password-requirements/class-itsec-password-requirements.php
DELETED
@@ -1,480 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class ITSEC_Password_Requirements
|
5 |
-
*/
|
6 |
-
class ITSEC_Password_Requirements {
|
7 |
-
|
8 |
-
const META_KEY = '_itsec_password_requirements';
|
9 |
-
|
10 |
-
public function run() {
|
11 |
-
|
12 |
-
add_action( 'user_profile_update_errors', array( $this, 'forward_profile_pass_update' ), 0, 3 );
|
13 |
-
add_action( 'validate_password_reset', array( $this, 'forward_reset_pass' ), 10, 2 );
|
14 |
-
|
15 |
-
add_action( 'profile_update', array( $this, 'handle_update_user' ), 10, 2 );
|
16 |
-
add_action( 'password_reset', array( $this, 'handle_password_reset' ), 10, 2 );
|
17 |
-
add_filter( 'wp_authenticate_user', array( $this, 'check_password_on_login' ), 999, 2 );
|
18 |
-
|
19 |
-
add_action( 'add_user_role', array( $this, 'handle_role_change' ) );
|
20 |
-
add_action( 'set_user_role', array( $this, 'handle_role_change' ) );
|
21 |
-
add_action( 'remove_user_role', array( $this, 'handle_role_change' ) );
|
22 |
-
|
23 |
-
add_action( 'itsec_validate_password', array( $this, 'validate_password' ), 10, 4 );
|
24 |
-
|
25 |
-
add_action( 'wp_login', array( $this, 'flag_check' ), 9, 2 );
|
26 |
-
|
27 |
-
add_action( 'itsec_login_interstitial_init', array( $this, 'register_interstitial' ) );
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* When a user's password is updated, or a new user created, verify that the new password is valid.
|
32 |
-
*
|
33 |
-
* @param WP_Error $errors
|
34 |
-
* @param bool $update
|
35 |
-
* @param WP_User|stdClass $user
|
36 |
-
*/
|
37 |
-
public function forward_profile_pass_update( $errors, $update, $user ) {
|
38 |
-
|
39 |
-
if ( $errors->get_error_message( 'pass' ) ) {
|
40 |
-
return;
|
41 |
-
}
|
42 |
-
|
43 |
-
if ( isset( $user->user_pass ) ) {
|
44 |
-
$this->handle_profile_update_password( $errors, $update, $user );
|
45 |
-
} elseif ( $update && isset( $user->role ) ) {
|
46 |
-
$this->handle_profile_update_role( $errors, $user );
|
47 |
-
}
|
48 |
-
}
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Handle the password being updated for a user.
|
52 |
-
*
|
53 |
-
* @param WP_Error $errors
|
54 |
-
* @param bool $update
|
55 |
-
* @param WP_User|stdClass $user
|
56 |
-
*/
|
57 |
-
private function handle_profile_update_password( $errors, $update, $user ) {
|
58 |
-
if ( ! $update ) {
|
59 |
-
$context = 'admin-user-create';
|
60 |
-
} elseif ( isset( $user->ID ) && $user->ID === get_current_user_id() ) {
|
61 |
-
$context = 'profile-update';
|
62 |
-
} else {
|
63 |
-
$context = 'admin-profile-update';
|
64 |
-
}
|
65 |
-
|
66 |
-
$args = array(
|
67 |
-
'error' => $errors,
|
68 |
-
'context' => $context
|
69 |
-
);
|
70 |
-
|
71 |
-
if ( isset( $user->role ) ) {
|
72 |
-
$args['role'] = $user->role;
|
73 |
-
}
|
74 |
-
|
75 |
-
ITSEC_Lib_Password_Requirements::validate_password( $user, $user->user_pass, $args );
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Handle the user's role being updated.
|
80 |
-
*
|
81 |
-
* @param WP_Error $errors
|
82 |
-
* @param WP_User|stdClass $user
|
83 |
-
*/
|
84 |
-
private function handle_profile_update_role( $errors, $user ) {
|
85 |
-
|
86 |
-
$settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
87 |
-
|
88 |
-
foreach ( ITSEC_Lib_Password_Requirements::get_registered() as $code => $requirement ) {
|
89 |
-
|
90 |
-
if ( ! $requirement['validate'] || ! ITSEC_Lib_Password_Requirements::is_requirement_enabled( $code ) ) {
|
91 |
-
continue;
|
92 |
-
}
|
93 |
-
|
94 |
-
$evaluation = get_user_meta( $user->ID, $requirement['meta'], true );
|
95 |
-
|
96 |
-
if ( '' === $evaluation ) {
|
97 |
-
continue;
|
98 |
-
}
|
99 |
-
|
100 |
-
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
101 |
-
|
102 |
-
$args = array(
|
103 |
-
'role' => $user->role,
|
104 |
-
'canonical' => ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $user->role, $user ),
|
105 |
-
);
|
106 |
-
|
107 |
-
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], $args );
|
108 |
-
|
109 |
-
if ( true === $validated ) {
|
110 |
-
continue;
|
111 |
-
}
|
112 |
-
|
113 |
-
$message = $validated ? $validated : esc_html__( "The provided password does not meet this site's requirements.", 'better-wp-security' );
|
114 |
-
$errors->add( 'pass', $message );
|
115 |
-
}
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* When a user attempts to reset their password, verify that the new password is valid.
|
120 |
-
*
|
121 |
-
* @param WP_Error $errors
|
122 |
-
* @param WP_User $user
|
123 |
-
*/
|
124 |
-
public function forward_reset_pass( $errors, $user ) {
|
125 |
-
|
126 |
-
if ( ! isset( $_POST['pass1'] ) || is_wp_error( $user ) ) {
|
127 |
-
// The validate_password_reset action fires when first rendering the reset page and when handling the form
|
128 |
-
// submissions. Since the pass1 data is missing, this must be the initial page render. So, we don't need to
|
129 |
-
// do anything yet.
|
130 |
-
return;
|
131 |
-
}
|
132 |
-
|
133 |
-
ITSEC_Lib_Password_Requirements::validate_password( $user, $_POST['pass1'], array(
|
134 |
-
'error' => $errors,
|
135 |
-
'context' => 'reset-password',
|
136 |
-
) );
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Whenever a user object is updated, set when their password was last updated.
|
141 |
-
*
|
142 |
-
* @param int $user_id
|
143 |
-
* @param object $old_user_data
|
144 |
-
*/
|
145 |
-
public function handle_update_user( $user_id, $old_user_data ) {
|
146 |
-
|
147 |
-
$user = get_userdata( $user_id );
|
148 |
-
|
149 |
-
if ( $user->user_pass === $old_user_data->user_pass ) {
|
150 |
-
return;
|
151 |
-
}
|
152 |
-
|
153 |
-
$this->handle_password_updated( $user );
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* When a user resets their password, update the last change time.
|
158 |
-
*
|
159 |
-
* For some unknown reason, the password reset routine uses {@see wp_set_password()} instead of {@see wp_update_user()}.
|
160 |
-
*
|
161 |
-
* @param WP_User $user
|
162 |
-
* @param string $new_password
|
163 |
-
*/
|
164 |
-
public function handle_password_reset( $user, $new_password ) {
|
165 |
-
$this->handle_password_updated( $user );
|
166 |
-
$this->handle_plain_text_password_available( $user, $new_password );
|
167 |
-
}
|
168 |
-
|
169 |
-
/**
|
170 |
-
* When a user logs in, if their password hasn't been validated yet,
|
171 |
-
* validate it.
|
172 |
-
*
|
173 |
-
* @param WP_User $user
|
174 |
-
* @param string $password
|
175 |
-
*
|
176 |
-
* @return WP_User
|
177 |
-
*/
|
178 |
-
public function check_password_on_login( $user, $password ) {
|
179 |
-
|
180 |
-
if ( ! $user instanceof WP_User ) {
|
181 |
-
return $user;
|
182 |
-
}
|
183 |
-
|
184 |
-
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
185 |
-
return $user;
|
186 |
-
}
|
187 |
-
|
188 |
-
$this->handle_plain_text_password_available( $user, $password );
|
189 |
-
|
190 |
-
return $user;
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* When a password is updated, set the last updated time and delete any pending required change.
|
195 |
-
*
|
196 |
-
* @param WP_User $user
|
197 |
-
*/
|
198 |
-
protected function handle_password_updated( $user ) {
|
199 |
-
delete_user_meta( $user->ID, 'itsec_password_change_required' );
|
200 |
-
update_user_meta( $user->ID, 'itsec_last_password_change', ITSEC_Core::get_current_time_gmt() );
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* When a plain text password is available, we perform any evaluations that have not yet been performed for this password.
|
205 |
-
*
|
206 |
-
* @param WP_User $user
|
207 |
-
* @param string $password
|
208 |
-
*/
|
209 |
-
protected function handle_plain_text_password_available( $user, $password ) {
|
210 |
-
|
211 |
-
$config = wp_parse_args( get_user_meta( $user->ID, self::META_KEY, true ), array(
|
212 |
-
'evaluation_times' => array(),
|
213 |
-
) );
|
214 |
-
|
215 |
-
$last_updated = ITSEC_Lib_Password_Requirements::password_last_changed( $user );
|
216 |
-
|
217 |
-
$settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
218 |
-
|
219 |
-
foreach ( ITSEC_Lib_Password_Requirements::get_registered() as $code => $requirement ) {
|
220 |
-
|
221 |
-
if ( ! $requirement['evaluate'] ) {
|
222 |
-
continue;
|
223 |
-
}
|
224 |
-
|
225 |
-
if ( ! $requirement['evaluate_if_not_enabled'] && ! ITSEC_Lib_Password_Requirements::is_requirement_enabled( $code ) ) {
|
226 |
-
continue;
|
227 |
-
}
|
228 |
-
|
229 |
-
if ( isset( $config['evaluation_times'][ $code ] ) && $config['evaluation_times'][ $code ] >= $last_updated ) {
|
230 |
-
continue;
|
231 |
-
}
|
232 |
-
|
233 |
-
$evaluation = call_user_func( $requirement['evaluate'], $password, $user );
|
234 |
-
|
235 |
-
if ( is_wp_error( $evaluation ) ) {
|
236 |
-
continue;
|
237 |
-
}
|
238 |
-
|
239 |
-
$config['evaluation_times'][ $code ] = ITSEC_Core::get_current_time_gmt();
|
240 |
-
update_user_meta( $user->ID, $requirement['meta'], $evaluation );
|
241 |
-
|
242 |
-
if ( ! ITSEC_Lib_Password_Requirements::is_requirement_enabled( $code ) ) {
|
243 |
-
continue;
|
244 |
-
}
|
245 |
-
|
246 |
-
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], array() );
|
247 |
-
|
248 |
-
if ( true === $validated ) {
|
249 |
-
continue;
|
250 |
-
}
|
251 |
-
|
252 |
-
ITSEC_Lib_Password_Requirements::flag_password_change_required( $user, $code );
|
253 |
-
}
|
254 |
-
|
255 |
-
update_user_meta( $user->ID, self::META_KEY, $config );
|
256 |
-
}
|
257 |
-
|
258 |
-
/**
|
259 |
-
* Validate password.
|
260 |
-
*
|
261 |
-
* @param \WP_Error $error
|
262 |
-
* @param \WP_User|stdClass $user
|
263 |
-
* @param string $new_password
|
264 |
-
* @param array $args
|
265 |
-
*/
|
266 |
-
public function validate_password( $error, $user, $new_password, $args ) {
|
267 |
-
|
268 |
-
$settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
269 |
-
|
270 |
-
foreach ( ITSEC_Lib_Password_Requirements::get_registered() as $code => $requirement ) {
|
271 |
-
|
272 |
-
if ( ! $requirement['evaluate'] || ! ITSEC_Lib_Password_Requirements::is_requirement_enabled( $code ) ) {
|
273 |
-
continue;
|
274 |
-
}
|
275 |
-
|
276 |
-
$evaluation = call_user_func( $requirement['evaluate'], $new_password, $user );
|
277 |
-
|
278 |
-
if ( is_wp_error( $evaluation ) ) {
|
279 |
-
continue;
|
280 |
-
}
|
281 |
-
|
282 |
-
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], $args );
|
283 |
-
|
284 |
-
if ( true === $validated ) {
|
285 |
-
continue;
|
286 |
-
}
|
287 |
-
|
288 |
-
// The default error message is a safeguard that should never occur.
|
289 |
-
$message = $validated ? $validated : esc_html__( "The provided password does not meet this site's requirements.", 'better-wp-security' );
|
290 |
-
|
291 |
-
switch ( $args['context'] ) {
|
292 |
-
case 'admin-user-create':
|
293 |
-
$message .= ' ' . __( 'The user has not been created.', 'better-wp-security' );
|
294 |
-
break;
|
295 |
-
case 'admin-profile-update':
|
296 |
-
$message .= ' ' . __( 'The user changes have not been saved.', 'better-wp-security' );
|
297 |
-
break;
|
298 |
-
case 'profile-update':
|
299 |
-
$message .= ' ' . __( 'Your profile has not been updated.', 'better-wp-security' );
|
300 |
-
break;
|
301 |
-
case 'reset-password':
|
302 |
-
$message .= ' ' . __( 'The password has not been updated.', 'better-wp-security' );
|
303 |
-
break;
|
304 |
-
}
|
305 |
-
|
306 |
-
$error->add( 'pass', $message );
|
307 |
-
}
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* When a user logs in, run any flag checks to see if a password change should be forced.
|
312 |
-
*
|
313 |
-
* @param string $username
|
314 |
-
* @param WP_User|null $user
|
315 |
-
*/
|
316 |
-
public function flag_check( $username, $user = null ) {
|
317 |
-
|
318 |
-
if ( ! $user && is_user_logged_in() ) {
|
319 |
-
$user = wp_get_current_user();
|
320 |
-
}
|
321 |
-
|
322 |
-
if ( ! $user instanceof WP_User || ! $user->exists() ) {
|
323 |
-
return;
|
324 |
-
}
|
325 |
-
|
326 |
-
foreach ( ITSEC_Lib_Password_Requirements::get_registered() as $code => $requirement ) {
|
327 |
-
if ( ! ITSEC_Lib_Password_Requirements::is_requirement_enabled( $code ) ) {
|
328 |
-
continue;
|
329 |
-
}
|
330 |
-
|
331 |
-
$settings = ITSEC_Lib_Password_Requirements::get_requirement_settings( $code );
|
332 |
-
|
333 |
-
if ( $requirement['flag_check'] && call_user_func( $requirement['flag_check'], $user, $settings ) ) {
|
334 |
-
ITSEC_Lib_Password_Requirements::flag_password_change_required( $user, $code );
|
335 |
-
|
336 |
-
return;
|
337 |
-
}
|
338 |
-
}
|
339 |
-
}
|
340 |
-
|
341 |
-
/**
|
342 |
-
* Is a given requirement enabled.
|
343 |
-
*
|
344 |
-
* @param string $requirement
|
345 |
-
*
|
346 |
-
* @return bool
|
347 |
-
*/
|
348 |
-
protected function is_requirement_enabled( $requirement ) {
|
349 |
-
|
350 |
-
$requirements = ITSEC_Lib_Password_Requirements::get_registered();
|
351 |
-
|
352 |
-
if ( ! isset( $requirements[ $requirement ] ) ) {
|
353 |
-
return false;
|
354 |
-
}
|
355 |
-
|
356 |
-
// If the requirement does not have any settings, than it is always enabled.
|
357 |
-
if ( null === $requirements[ $requirement ]['settings_config'] ) {
|
358 |
-
return true;
|
359 |
-
}
|
360 |
-
|
361 |
-
$enabled = ITSEC_Modules::get_setting( 'password-requirements', 'enabled_requirements' );
|
362 |
-
|
363 |
-
if ( ! empty( $enabled[ $requirement ] ) ) {
|
364 |
-
return true;
|
365 |
-
}
|
366 |
-
|
367 |
-
return false;
|
368 |
-
}
|
369 |
-
|
370 |
-
/**
|
371 |
-
* When a user's role changes, clear all the evaluation times as evaluat
|
372 |
-
*
|
373 |
-
* @param int $user_id
|
374 |
-
*/
|
375 |
-
public function handle_role_change( $user_id ) {
|
376 |
-
|
377 |
-
$config = get_user_meta( $user_id, self::META_KEY, true );
|
378 |
-
|
379 |
-
if ( ! $config || ! is_array( $config ) ) {
|
380 |
-
return;
|
381 |
-
}
|
382 |
-
|
383 |
-
$config['evaluation_times'] = array();
|
384 |
-
|
385 |
-
update_user_meta( $user_id, self::META_KEY, $config );
|
386 |
-
}
|
387 |
-
|
388 |
-
/**
|
389 |
-
* Register the password change interstitial.
|
390 |
-
*
|
391 |
-
* @param ITSEC_Lib_Login_Interstitial $lib
|
392 |
-
*/
|
393 |
-
public function register_interstitial( $lib ) {
|
394 |
-
$lib->register( 'update-password', array( $this, 'render_interstitial' ), array(
|
395 |
-
'show_to_user' => array( 'ITSEC_Lib_Password_Requirements', 'password_change_required' ),
|
396 |
-
'info_message' => array( 'ITSEC_Lib_Password_Requirements', 'get_message_for_password_change_reason' ),
|
397 |
-
'submit' => array( $this, 'submit' ),
|
398 |
-
) );
|
399 |
-
}
|
400 |
-
|
401 |
-
/**
|
402 |
-
* Render the interstitial.
|
403 |
-
*
|
404 |
-
* @param WP_User $user
|
405 |
-
*/
|
406 |
-
public function render_interstitial( $user ) {
|
407 |
-
do_action( 'itsec_password_requirements_change_form', $user );
|
408 |
-
?>
|
409 |
-
|
410 |
-
<div class="user-pass1-wrap">
|
411 |
-
<p><label for="pass1"><?php _e( 'New Password', 'better-wp-security' ); ?></label></p>
|
412 |
-
</div>
|
413 |
-
|
414 |
-
<div class="wp-pwd">
|
415 |
-
<span class="password-input-wrapper">
|
416 |
-
<input type="password" data-reveal="1"
|
417 |
-
data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" name="pass1" id="pass1"
|
418 |
-
class="input" size="20" value="" autocomplete="off" aria-describedby="pass-strength-result"/>
|
419 |
-
</span>
|
420 |
-
<div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator', 'better-wp-security' ); ?></div>
|
421 |
-
<div class="pw-weak">
|
422 |
-
<label>
|
423 |
-
<input type="checkbox" name="pw_weak" class="pw-checkbox" />
|
424 |
-
<?php _e( 'Confirm use of weak password' ); ?>
|
425 |
-
</label>
|
426 |
-
</div>
|
427 |
-
</div>
|
428 |
-
|
429 |
-
<p class="user-pass2-wrap">
|
430 |
-
<label for="pass2"><?php _e( 'Confirm new password' ) ?></label><br/>
|
431 |
-
<input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off"/>
|
432 |
-
</p>
|
433 |
-
|
434 |
-
<p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p>
|
435 |
-
<br class="clear"/>
|
436 |
-
|
437 |
-
<p class="submit">
|
438 |
-
<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Update Password', 'better-wp-security' ); ?>"/>
|
439 |
-
</p>
|
440 |
-
|
441 |
-
<?php
|
442 |
-
}
|
443 |
-
|
444 |
-
/**
|
445 |
-
* Handle the request to update the user's password.
|
446 |
-
*
|
447 |
-
* @param WP_User $user
|
448 |
-
* @param array $data POSTed data.
|
449 |
-
*
|
450 |
-
* @return WP_Error|null
|
451 |
-
*/
|
452 |
-
public function submit( $user, $data ) {
|
453 |
-
|
454 |
-
if ( empty( $data['pass1'] ) ) {
|
455 |
-
return new WP_Error(
|
456 |
-
'itsec-password-requirements-empty-password',
|
457 |
-
__( 'Please enter your new password.', 'better-wp-security' )
|
458 |
-
);
|
459 |
-
}
|
460 |
-
|
461 |
-
$error = ITSEC_Lib_Password_Requirements::validate_password( $user, $data['pass1'], array(
|
462 |
-
'context' => 'interstitial',
|
463 |
-
) );
|
464 |
-
|
465 |
-
if ( $error->get_error_message() ) {
|
466 |
-
return $error;
|
467 |
-
}
|
468 |
-
|
469 |
-
$error = wp_update_user( array(
|
470 |
-
'ID' => $user->ID,
|
471 |
-
'user_pass' => $data['pass1']
|
472 |
-
) );
|
473 |
-
|
474 |
-
if ( is_wp_error( $error ) ) {
|
475 |
-
return $error;
|
476 |
-
}
|
477 |
-
|
478 |
-
return null;
|
479 |
-
}
|
480 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/password-requirements/css/index.php
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
<?php // Silence is golden.
|
|
core/modules/password-requirements/css/settings-page.css
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
#itsec-module-card-password-requirements h4 {
|
2 |
-
margin: .25em 0;
|
3 |
-
}
|
|
|
|
|
|
core/modules/password-requirements/index.php
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
<?php //You don't belong here. ?>
|
|
core/modules/password-requirements/js/index.php
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
<?php // Silence is golden.
|
|
core/modules/password-requirements/js/settings-page.js
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
(function ( $ ) {
|
2 |
-
|
3 |
-
$( function () {
|
4 |
-
|
5 |
-
$( '.itsec-password-requirements-container' ).each( function () {
|
6 |
-
updateVisibility( $( this ).data( 'code' ) );
|
7 |
-
} );
|
8 |
-
|
9 |
-
$( '.itsec-password-requirements-container__enabled-wrap input[type="checkbox"]' ).on( 'change', function ( e ) {
|
10 |
-
updateVisibility( $( this ).parents( '.itsec-password-requirements-container' ).data( 'code' ) );
|
11 |
-
} )
|
12 |
-
} );
|
13 |
-
|
14 |
-
function updateVisibility( code ) {
|
15 |
-
var $checkbox = $( '.itsec-password-requirements-container__enabled-wrap--' + code + ' input[type="checkbox"]' ),
|
16 |
-
$details = $( '.itsec-password-requirements-container__settings-wrap--' + code );
|
17 |
-
|
18 |
-
if ( $checkbox.is( ':checked' ) ) {
|
19 |
-
$details.show();
|
20 |
-
} else {
|
21 |
-
$details.hide();
|
22 |
-
}
|
23 |
-
}
|
24 |
-
})( jQuery );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/password-requirements/settings-page.php
DELETED
@@ -1,115 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class ITSEC_Password_Requirements_Settings_Page
|
5 |
-
*/
|
6 |
-
class ITSEC_Password_Requirements_Settings_Page extends ITSEC_Module_Settings_Page {
|
7 |
-
|
8 |
-
/**
|
9 |
-
* ITSEC_Password_Requirements_Settings_Page constructor.
|
10 |
-
*/
|
11 |
-
public function __construct() {
|
12 |
-
$this->id = 'password-requirements';
|
13 |
-
$this->title = __( 'Password Requirements', 'better-wp-security' );
|
14 |
-
$this->description = __( 'Manage and configure Password Requirements for users.', 'better-wp-security' );
|
15 |
-
$this->can_save = true;
|
16 |
-
|
17 |
-
parent::__construct();
|
18 |
-
}
|
19 |
-
|
20 |
-
protected function render_description( $form ) {
|
21 |
-
?>
|
22 |
-
<p><?php esc_html_e( 'Manage and configure Password Requirements for users.', 'better-wp-security' ); ?></p>
|
23 |
-
<?php
|
24 |
-
}
|
25 |
-
|
26 |
-
public function enqueue_scripts_and_styles() {
|
27 |
-
wp_enqueue_script( 'itsec-password-requirements-settings-page', plugins_url( 'js/settings-page.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build() );
|
28 |
-
wp_enqueue_style( 'itsec-password-requirements-settings-page', plugins_url( 'css/settings-page.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
|
29 |
-
|
30 |
-
do_action( 'itsec_password_requirements_enqueue_scripts_and_styles' );
|
31 |
-
}
|
32 |
-
|
33 |
-
public function handle_ajax_request( $data ) {
|
34 |
-
if ( ! isset( $data['password_requirement'] ) ) {
|
35 |
-
return;
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Fires when Password Requirement ajax request is incoming.
|
40 |
-
*
|
41 |
-
* The dynamic portion of the hook, $data['password_requirement'] refers to the reason code of the requirement.
|
42 |
-
*
|
43 |
-
* @param array $data
|
44 |
-
*/
|
45 |
-
do_action( 'itsec_password_requirements_ajax_' . $data['password_requirement'], $data );
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Render settings.
|
50 |
-
*
|
51 |
-
* @param ITSEC_Form $form
|
52 |
-
*/
|
53 |
-
protected function render_settings( $form ) {
|
54 |
-
|
55 |
-
$requirements = ITSEC_Lib_Password_Requirements::get_registered();
|
56 |
-
?>
|
57 |
-
|
58 |
-
<?php do_action( 'itsec_password_requirements_settings_before', $form ); ?>
|
59 |
-
|
60 |
-
<div class="itsec-password-requirements-settings">
|
61 |
-
<?php do_action( 'itsec_password_requirements_settings_begin', $form ); ?>
|
62 |
-
<?php foreach ( $requirements as $code => $requirement ):
|
63 |
-
|
64 |
-
if ( null === $requirement['settings_config'] ) {
|
65 |
-
continue;
|
66 |
-
}
|
67 |
-
|
68 |
-
$config = call_user_func( $requirement['settings_config'] );
|
69 |
-
|
70 |
-
$form->add_input_group( 'enabled_requirements' );
|
71 |
-
?>
|
72 |
-
<div class="itsec-settings-section itsec-password-requirements-container itsec-password-requirements-container--<?php echo esc_attr( $code ); ?>"
|
73 |
-
data-code="<?php echo esc_attr( $code ) ?>">
|
74 |
-
<h4><?php echo esc_html( isset( $config['label'] ) ? $config['label'] : $code ); ?></h4>
|
75 |
-
|
76 |
-
<?php if ( ! empty( $config['description'] ) ): ?>
|
77 |
-
<p class="description"><?php echo $config['description']; ?></p>
|
78 |
-
<?php endif; ?>
|
79 |
-
|
80 |
-
<table class="form-table">
|
81 |
-
<thead class="itsec-password-requirements-container__enabled-wrap itsec-password-requirements-container__enabled-wrap--<?php echo esc_attr( $code ); ?>">
|
82 |
-
<tr>
|
83 |
-
<th scope="row">
|
84 |
-
<label for="itsec-password-requirements-enabled_requirements-<?php echo esc_attr( $code ); ?>">
|
85 |
-
<?php esc_html_e( 'Enabled', 'better-wp-security' ); ?>
|
86 |
-
</label>
|
87 |
-
</th>
|
88 |
-
<td><?php $form->add_checkbox( $code ); ?></td>
|
89 |
-
</tr>
|
90 |
-
</thead>
|
91 |
-
<?php
|
92 |
-
$form->remove_input_group();
|
93 |
-
|
94 |
-
if ( ! empty( $config['render'] ) ) :
|
95 |
-
$form->add_input_group( 'requirement_settings', $code );
|
96 |
-
?>
|
97 |
-
<tbody class="itsec-password-requirements-container__settings-wrap itsec-password-requirements-container__settings-wrap--<?php echo esc_attr( $code ); ?>">
|
98 |
-
<?php call_user_func( $config['render'], $form ) ?>
|
99 |
-
</tbody>
|
100 |
-
<?php
|
101 |
-
$form->remove_input_group();
|
102 |
-
$form->remove_input_group();
|
103 |
-
endif; ?>
|
104 |
-
</table>
|
105 |
-
</div>
|
106 |
-
<?php endforeach; ?>
|
107 |
-
<?php do_action( 'itsec_password_requirements_settings_end', $form ); ?>
|
108 |
-
</div>
|
109 |
-
<?php do_action( 'itsec_password_requirements_settings_after', $form ); ?>
|
110 |
-
<?php
|
111 |
-
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
new ITSEC_Password_Requirements_Settings_Page();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/password-requirements/settings.php
DELETED
@@ -1,51 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class ITSEC_Password_Requirements_Settings
|
5 |
-
*/
|
6 |
-
class ITSEC_Password_Requirements_Settings extends ITSEC_Settings {
|
7 |
-
|
8 |
-
public function get_id() {
|
9 |
-
return 'password-requirements';
|
10 |
-
}
|
11 |
-
|
12 |
-
public function get_defaults() {
|
13 |
-
return array(
|
14 |
-
'enabled_requirements' => array(),
|
15 |
-
'requirement_settings' => array(),
|
16 |
-
);
|
17 |
-
}
|
18 |
-
|
19 |
-
public function load() {
|
20 |
-
|
21 |
-
$this->settings = ITSEC_Storage::get( $this->get_id() );
|
22 |
-
$defaults = $this->get_defaults();
|
23 |
-
|
24 |
-
if ( ! is_array( $this->settings ) ) {
|
25 |
-
$this->settings = array();
|
26 |
-
}
|
27 |
-
|
28 |
-
$this->settings = array_merge( $defaults, $this->settings );
|
29 |
-
|
30 |
-
foreach ( ITSEC_Lib_Password_Requirements::get_registered() as $code => $requirement ) {
|
31 |
-
|
32 |
-
if ( ! isset( $this->settings['enabled_requirements'][ $code ] ) ) {
|
33 |
-
$this->settings['enabled_requirements'][ $code ] = false;
|
34 |
-
}
|
35 |
-
|
36 |
-
if ( null === $requirement['defaults'] ) {
|
37 |
-
continue;
|
38 |
-
}
|
39 |
-
|
40 |
-
if ( isset( $this->settings['requirement_settings'][ $code ] ) ) {
|
41 |
-
$current = $this->settings['requirement_settings'][ $code ];
|
42 |
-
} else {
|
43 |
-
$current = array();
|
44 |
-
}
|
45 |
-
|
46 |
-
$this->settings['requirement_settings'][ $code ] = wp_parse_args( $current, $requirement['defaults'] );
|
47 |
-
}
|
48 |
-
}
|
49 |
-
}
|
50 |
-
|
51 |
-
ITSEC_Modules::register_settings( new ITSEC_Password_Requirements_Settings() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/password-requirements/validator.php
DELETED
@@ -1,62 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class ITSEC_Password_Requirements_Validator
|
5 |
-
*/
|
6 |
-
class ITSEC_Password_Requirements_Validator extends ITSEC_Validator {
|
7 |
-
|
8 |
-
/** @var string */
|
9 |
-
private $current_requirement;
|
10 |
-
|
11 |
-
public function get_id() {
|
12 |
-
return 'password-requirements';
|
13 |
-
}
|
14 |
-
|
15 |
-
protected function sanitize_settings() {
|
16 |
-
$this->sanitize_setting( 'array', 'enabled_requirements', __( 'Enabled Requirements', 'better-wp-security' ) );
|
17 |
-
$this->sanitize_setting( 'array', 'requirement_settings', __( 'Requirement Settings', 'better-wp-security' ) );
|
18 |
-
|
19 |
-
$requirements = ITSEC_Lib_Password_Requirements::get_registered();
|
20 |
-
|
21 |
-
$settings = $this->settings;
|
22 |
-
|
23 |
-
foreach ( $requirements as $code => $requirement ) {
|
24 |
-
if ( null === $requirement['settings_config'] ) {
|
25 |
-
continue;
|
26 |
-
}
|
27 |
-
|
28 |
-
$config = call_user_func( $requirement['settings_config'] );
|
29 |
-
$sanitize = call_user_func( $config['sanitize'], $this->settings );
|
30 |
-
|
31 |
-
if ( is_wp_error( $sanitize ) ) {
|
32 |
-
$this->add_error( $sanitize );
|
33 |
-
|
34 |
-
if ( ITSEC_Core::is_interactive() ) {
|
35 |
-
$this->set_can_save( false );
|
36 |
-
}
|
37 |
-
} elseif ( is_array( $sanitize ) ) {
|
38 |
-
$this->settings = isset( $settings['requirement_settings'][ $code ] ) ? $settings['requirement_settings'][ $code ] : $requirement['defaults'];
|
39 |
-
$this->current_requirement = $code;
|
40 |
-
|
41 |
-
foreach ( $sanitize as $args ) {
|
42 |
-
call_user_func_array( array( $this, 'sanitize_setting' ), $args );
|
43 |
-
}
|
44 |
-
|
45 |
-
$settings['requirement_settings'][ $code ] = $this->settings;
|
46 |
-
$this->settings = $settings;
|
47 |
-
$this->current_requirement = null;
|
48 |
-
}
|
49 |
-
|
50 |
-
}
|
51 |
-
}
|
52 |
-
|
53 |
-
protected function generate_error( $id, $var, $type, $error ) {
|
54 |
-
if ( null === $this->current_requirement ) {
|
55 |
-
return parent::generate_error( $id, $var, $type, $error );
|
56 |
-
}
|
57 |
-
|
58 |
-
return new WP_Error( "itsec-validator-$id-invalid-type-enabled_requirements-{$this->current_requirement}-$var-$type", $error );
|
59 |
-
}
|
60 |
-
}
|
61 |
-
|
62 |
-
ITSEC_Modules::register_validator( new ITSEC_Password_Requirements_Validator() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/modules/pro/settings-page.php
CHANGED
@@ -36,6 +36,22 @@ final class ITSEC_Malware_Scheduling_Settings_Page extends ITSEC_Module_Settings
|
|
36 |
new ITSEC_Malware_Scheduling_Settings_Page();
|
37 |
|
38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
final class ITSEC_Privilege_Escalation_Settings_Page extends ITSEC_Module_Settings_Page {
|
40 |
public function __construct() {
|
41 |
$this->id = 'privilege';
|
36 |
new ITSEC_Malware_Scheduling_Settings_Page();
|
37 |
|
38 |
|
39 |
+
final class ITSEC_Password_Expiration_Settings_Page extends ITSEC_Module_Settings_Page {
|
40 |
+
public function __construct() {
|
41 |
+
$this->id = 'password-expiration';
|
42 |
+
$this->title = __( 'Password Expiration', 'better-wp-security' );
|
43 |
+
$this->description = __( 'Strengthen the passwords on the site with automated password expiration.', 'better-wp-security' );
|
44 |
+
$this->type = 'recommended';
|
45 |
+
$this->pro = true;
|
46 |
+
$this->upsell = true;
|
47 |
+
$this->upsell_url = 'https://ithemes.com/security/wordpress-password-security/?utm_source=wordpressadmin&utm_medium=widget&utm_campaign=itsecfreecta';
|
48 |
+
|
49 |
+
parent::__construct();
|
50 |
+
}
|
51 |
+
}
|
52 |
+
new ITSEC_Password_Expiration_Settings_Page();
|
53 |
+
|
54 |
+
|
55 |
final class ITSEC_Privilege_Escalation_Settings_Page extends ITSEC_Module_Settings_Page {
|
56 |
public function __construct() {
|
57 |
$this->id = 'privilege';
|
core/modules/security-check/scanner.php
CHANGED
@@ -48,27 +48,7 @@ final class ITSEC_Security_Check_Scanner {
|
|
48 |
self::enforce_activation( 'ban-users', __( 'Banned Users', 'better-wp-security' ) );
|
49 |
self::enforce_setting( 'ban-users', 'enable_ban_lists', true, __( 'Enabled the Enable Ban Lists setting in Banned Users.', 'better-wp-security' ) );
|
50 |
|
51 |
-
|
52 |
-
if ( ! function_exists( 'get_plugin_data' ) ) {
|
53 |
-
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
54 |
-
}
|
55 |
-
|
56 |
-
$name = "'{$backup}'";
|
57 |
-
|
58 |
-
if ( function_exists( 'get_plugin_data' ) ) {
|
59 |
-
$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $backup, false, true );
|
60 |
-
|
61 |
-
if ( isset( $data['Name'] ) ) {
|
62 |
-
$name = $data['Name'];
|
63 |
-
}
|
64 |
-
}
|
65 |
-
|
66 |
-
self::$feedback->add_section( 'backup-activation' );
|
67 |
-
self::$feedback->add_text( sprintf( __( 'A 3rd-party Backup Plugin, %s, is being used.', 'better-wp-security' ), $name ) );
|
68 |
-
} else {
|
69 |
-
self::enforce_activation( 'backup', __( 'Database Backups', 'better-wp-security' ) );
|
70 |
-
}
|
71 |
-
|
72 |
self::enforce_activation( 'brute-force', __( 'Local Brute Force Protection', 'better-wp-security' ) );
|
73 |
self::enforce_activation( 'magic-links', __( 'Magic Links', 'better-wp-security' ) );
|
74 |
self::enforce_activation( 'malware-scheduling', __( 'Malware Scan Scheduling', 'better-wp-security' ) );
|
@@ -76,10 +56,9 @@ final class ITSEC_Security_Check_Scanner {
|
|
76 |
|
77 |
self::add_network_brute_force_signup();
|
78 |
|
79 |
-
self::
|
80 |
self::enforce_activation( 'two-factor', __( 'Two-Factor Authentication', 'better-wp-security' ) );
|
81 |
self::enforce_setting( 'two-factor', 'available_methods', 'all', esc_html__( 'Changed the Authentication Methods Available to Users setting in Two-Factor Authentication to "All Methods".', 'better-wp-security' ) );
|
82 |
-
self::enforce_setting( 'two-factor', 'exclude_type', 'disabled', esc_html__( 'Changed the Disabled Force Two-Factor for Certain Users to "None".', 'better-wp-security' ) );
|
83 |
self::enforce_setting( 'two-factor', 'protect_user_type', 'privileged_users', esc_html__( 'Changed the User Type Protection setting in Two-Factor Authentication to "Privileged Users".', 'better-wp-security' ) );
|
84 |
self::enforce_setting( 'two-factor', 'protect_vulnerable_users', true, esc_html__( 'Enabled the Vulnerable User Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
85 |
self::enforce_setting( 'two-factor', 'protect_vulnerable_site', true, esc_html__( 'Enabled the Vulnerable Site Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
@@ -176,21 +155,6 @@ final class ITSEC_Security_Check_Scanner {
|
|
176 |
self::$feedback->add_text( sprintf( $text, $name ) );
|
177 |
}
|
178 |
|
179 |
-
private static function enforce_password_requirement_enabled( $requirement, $description ) {
|
180 |
-
|
181 |
-
$active = ITSEC_Modules::get_setting( 'password-requirements', 'enabled_requirements' );
|
182 |
-
|
183 |
-
if ( ! empty( $active[ $requirement ] ) ) {
|
184 |
-
return;
|
185 |
-
}
|
186 |
-
|
187 |
-
$active[ $requirement ] = true;
|
188 |
-
|
189 |
-
ITSEC_Modules::set_setting( 'password-requirements', 'enabled_requirements', $active );
|
190 |
-
self::$feedback->add_section( 'enforce-setting-password-requirements-enabled_requirements', array( 'status' => 'action-taken' ) );
|
191 |
-
self::$feedback->add_text( $description );
|
192 |
-
}
|
193 |
-
|
194 |
public static function activate_network_brute_force( $data ) {
|
195 |
if ( ! isset( $data['email'] ) ) {
|
196 |
ITSEC_Response::add_error( new WP_Error( 'itsec-security-check-missing-email', __( 'The email value is missing.', 'better-wp-security' ) ) );
|
48 |
self::enforce_activation( 'ban-users', __( 'Banned Users', 'better-wp-security' ) );
|
49 |
self::enforce_setting( 'ban-users', 'enable_ban_lists', true, __( 'Enabled the Enable Ban Lists setting in Banned Users.', 'better-wp-security' ) );
|
50 |
|
51 |
+
self::enforce_activation( 'backup', __( 'Database Backups', 'better-wp-security' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
self::enforce_activation( 'brute-force', __( 'Local Brute Force Protection', 'better-wp-security' ) );
|
53 |
self::enforce_activation( 'magic-links', __( 'Magic Links', 'better-wp-security' ) );
|
54 |
self::enforce_activation( 'malware-scheduling', __( 'Malware Scan Scheduling', 'better-wp-security' ) );
|
56 |
|
57 |
self::add_network_brute_force_signup();
|
58 |
|
59 |
+
self::enforce_activation( 'strong-passwords', __( 'Strong Password Enforcement', 'better-wp-security' ) );
|
60 |
self::enforce_activation( 'two-factor', __( 'Two-Factor Authentication', 'better-wp-security' ) );
|
61 |
self::enforce_setting( 'two-factor', 'available_methods', 'all', esc_html__( 'Changed the Authentication Methods Available to Users setting in Two-Factor Authentication to "All Methods".', 'better-wp-security' ) );
|
|
|
62 |
self::enforce_setting( 'two-factor', 'protect_user_type', 'privileged_users', esc_html__( 'Changed the User Type Protection setting in Two-Factor Authentication to "Privileged Users".', 'better-wp-security' ) );
|
63 |
self::enforce_setting( 'two-factor', 'protect_vulnerable_users', true, esc_html__( 'Enabled the Vulnerable User Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
64 |
self::enforce_setting( 'two-factor', 'protect_vulnerable_site', true, esc_html__( 'Enabled the Vulnerable Site Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
155 |
self::$feedback->add_text( sprintf( $text, $name ) );
|
156 |
}
|
157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
public static function activate_network_brute_force( $data ) {
|
159 |
if ( ! isset( $data['email'] ) ) {
|
160 |
ITSEC_Response::add_error( new WP_Error( 'itsec-security-check-missing-email', __( 'The email value is missing.', 'better-wp-security' ) ) );
|
core/modules/ssl/class-itsec-ssl.php
CHANGED
@@ -69,7 +69,7 @@ class ITSEC_SSL {
|
|
69 |
add_filter( 'script_loader_src', array( $this, 'script_loader_src' ) );
|
70 |
add_filter( 'style_loader_src', array( $this, 'style_loader_src' ) );
|
71 |
add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
|
72 |
-
} else if ( 'enabled' === $settings['require_ssl'] && '
|
73 |
$this->redirect_to_https();
|
74 |
}
|
75 |
}
|
@@ -87,7 +87,7 @@ class ITSEC_SSL {
|
|
87 |
*/
|
88 |
public function do_conditional_ssl_redirect() {
|
89 |
|
90 |
-
if ( '
|
91 |
return;
|
92 |
}
|
93 |
|
69 |
add_filter( 'script_loader_src', array( $this, 'script_loader_src' ) );
|
70 |
add_filter( 'style_loader_src', array( $this, 'style_loader_src' ) );
|
71 |
add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
|
72 |
+
} else if ( 'enabled' === $settings['require_ssl'] && ( ! defined( 'WP_CLI' ) || ! WP_CLI ) && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
|
73 |
$this->redirect_to_https();
|
74 |
}
|
75 |
}
|
87 |
*/
|
88 |
public function do_conditional_ssl_redirect() {
|
89 |
|
90 |
+
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
91 |
return;
|
92 |
}
|
93 |
|
core/modules/strong-passwords/class-itsec-strong-passwords.php
CHANGED
@@ -1,218 +1,247 @@
|
|
1 |
<?php
|
2 |
|
3 |
final class ITSEC_Strong_Passwords {
|
4 |
-
|
5 |
-
const STRENGTH_KEY = 'itsec-password-strength';
|
6 |
-
|
7 |
public function __construct() {
|
8 |
|
9 |
-
|
|
|
|
|
10 |
|
11 |
add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
|
12 |
-
add_action( '
|
13 |
-
add_action( 'itsec_password_requirements_change_form', array( $this, 'add_scripts_to_wp_login' ) );
|
14 |
}
|
15 |
|
16 |
/**
|
17 |
-
*
|
|
|
|
|
18 |
*/
|
19 |
-
public function
|
20 |
-
|
21 |
-
'evaluate' => array( $this, 'evaluate' ),
|
22 |
-
'validate' => array( $this, 'validate' ),
|
23 |
-
'reason' => array( $this, 'reason' ),
|
24 |
-
'meta' => self::STRENGTH_KEY,
|
25 |
-
'evaluate_if_not_enabled' => true,
|
26 |
-
'defaults' => array( 'role' => 'administrator' ),
|
27 |
-
'settings_config' => array( $this, 'get_settings_config' ),
|
28 |
-
) );
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
-
*
|
33 |
*
|
34 |
-
* @return
|
35 |
*/
|
36 |
-
public function
|
37 |
|
38 |
-
|
39 |
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
43 |
|
44 |
-
if (
|
45 |
-
return;
|
46 |
}
|
47 |
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
52 |
|
53 |
-
if (
|
54 |
-
|
|
|
|
|
55 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
}
|
57 |
|
58 |
/**
|
59 |
-
*
|
60 |
-
*
|
61 |
-
* We have to do this in these late actions so we have access to the correct user data.
|
62 |
*
|
63 |
-
* @param
|
|
|
|
|
|
|
64 |
*/
|
65 |
-
public function
|
66 |
|
67 |
-
if (
|
68 |
-
|
|
|
|
|
69 |
}
|
70 |
|
71 |
-
$
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
-
|
|
|
|
|
75 |
|
76 |
-
if (
|
77 |
-
|
78 |
}
|
79 |
-
}
|
80 |
|
81 |
-
|
82 |
-
* Provide the reason string displayed to users on the change password form.
|
83 |
-
*
|
84 |
-
* @param $evaluation
|
85 |
-
*
|
86 |
-
* @return string
|
87 |
-
*/
|
88 |
-
public function reason( $evaluation ) {
|
89 |
-
return esc_html__( 'Due to site rules, a strong password is required for your account. Please choose a new password that rates as strong on the meter.', 'better-wp-security' );
|
90 |
-
}
|
91 |
|
92 |
-
|
93 |
-
* Evaluate the strength of a password.
|
94 |
-
*
|
95 |
-
* @param string $password
|
96 |
-
* @param WP_User $user
|
97 |
-
*
|
98 |
-
* @return int
|
99 |
-
*/
|
100 |
-
public function evaluate( $password, $user ) {
|
101 |
-
return $this->get_password_strength( $user, $password );
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
-
*
|
106 |
*
|
107 |
-
* @param
|
108 |
-
* @param WP_User
|
109 |
-
* @param array $settings
|
110 |
-
* @param array $args
|
111 |
*
|
112 |
-
* @return
|
113 |
*/
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
|
|
118 |
}
|
119 |
|
120 |
-
|
121 |
|
122 |
-
|
|
|
123 |
|
124 |
-
|
125 |
-
|
|
|
|
|
|
|
126 |
}
|
127 |
|
128 |
-
|
129 |
-
}
|
130 |
|
131 |
-
|
132 |
-
return array(
|
133 |
-
'label' => esc_html__( 'Strong Passwords', 'better-wp-security' ),
|
134 |
-
'description' => esc_html__( 'Force users to use strong passwords as rated by the WordPress password meter.', 'better-wp-security' ),
|
135 |
-
'render' => array( $this, 'render_settings' ),
|
136 |
-
'sanitize' => array( $this, 'sanitize_settings' ),
|
137 |
-
);
|
138 |
}
|
139 |
|
140 |
/**
|
141 |
-
*
|
|
|
|
|
142 |
*
|
143 |
-
* @
|
144 |
*/
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
<label for="itsec-password-requirements-requirement_settings-strength-role"><?php _e( 'Minimum role at which a user must choose a strong password.', 'better-wp-security' ); ?></label>
|
160 |
-
<p class="description"><?php printf( __( 'For more information on WordPress roles and capabilities please see %s.', 'better-wp-security' ), $link ); ?></p>
|
161 |
-
<p class="warningtext description"><?php _e( 'Warning: If your site invites public registrations setting the role too low may annoy your members.', 'better-wp-security' ); ?></p>
|
162 |
-
</td>
|
163 |
-
</tr>
|
164 |
-
<?php
|
165 |
}
|
166 |
|
167 |
/**
|
168 |
-
*
|
169 |
*
|
170 |
-
* @param
|
171 |
*
|
172 |
-
* @return
|
173 |
*/
|
174 |
-
|
175 |
-
|
176 |
-
array( 'string', 'role', esc_html__( 'Minimum Role for Strong Passwords', 'better-wp-security' ) ),
|
177 |
-
array( 'canonical-roles', 'role', esc_html__( 'Minimum Role for Strong Passwords', 'better-wp-security' ) ),
|
178 |
-
);
|
179 |
-
}
|
180 |
|
181 |
-
|
182 |
-
* Get the strong password error message according to the given context.
|
183 |
-
*
|
184 |
-
* @return string
|
185 |
-
*/
|
186 |
-
private function make_error_message() {
|
187 |
-
$message = __( '<strong>Error</strong>: Due to site rules, a strong password is required. Please choose a new password that rates as <strong>Strong</strong> on the meter.', 'better-wp-security' );
|
188 |
|
189 |
-
return
|
190 |
}
|
191 |
|
192 |
/**
|
193 |
-
*
|
194 |
*
|
195 |
-
* @param WP_User $user
|
196 |
-
*
|
|
|
|
|
|
|
|
|
197 |
*
|
198 |
-
* @return
|
199 |
*/
|
200 |
-
private function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
|
207 |
-
|
208 |
-
|
209 |
-
|
|
|
210 |
}
|
211 |
-
}
|
212 |
|
213 |
-
|
|
|
|
|
214 |
|
215 |
-
return $
|
216 |
}
|
217 |
}
|
218 |
|
1 |
<?php
|
2 |
|
3 |
final class ITSEC_Strong_Passwords {
|
|
|
|
|
|
|
4 |
public function __construct() {
|
5 |
|
6 |
+
add_filter( 'itsec_password_change_requirement_description_for_strength', array( $this, 'strength_reason' ) );
|
7 |
+
add_action( 'user_profile_update_errors', array( $this, 'filter_user_profile_update_errors' ), 0, 3 );
|
8 |
+
add_action( 'itsec_validate_password', array( $this, 'validate_password' ), 10, 4 );
|
9 |
|
10 |
add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
|
11 |
+
add_action( 'login_enqueue_scripts', array( $this, 'add_scripts' ) );
|
|
|
12 |
}
|
13 |
|
14 |
/**
|
15 |
+
* Enqueue script to add measured password strength to the form submission data.
|
16 |
+
*
|
17 |
+
* @return void
|
18 |
*/
|
19 |
+
public function add_scripts() {
|
20 |
+
wp_enqueue_script( 'itsec_strong_passwords', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
}
|
22 |
|
23 |
/**
|
24 |
+
* Get the reason description for why a password change was set to 'strength'.
|
25 |
*
|
26 |
+
* @return string
|
27 |
*/
|
28 |
+
public function strength_reason() {
|
29 |
|
30 |
+
$message = __( 'Due to site rules, a strong password is required for your account. Please choose a new password that rates as <strong>Strong</strong> on the meter.', 'better-wp-security' );
|
31 |
|
32 |
+
return wp_kses( $message, array( 'strong' => '' ) );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Handle submission of a form to create or edit a user.
|
37 |
+
*
|
38 |
+
* @param WP_Error $errors WP_Error object.
|
39 |
+
* @param bool $update Whether this is a user update.
|
40 |
+
* @param stdClass $user User object.
|
41 |
+
*
|
42 |
+
* @return WP_Error
|
43 |
+
*/
|
44 |
+
public function filter_user_profile_update_errors( $errors, $update, $user ) {
|
45 |
+
|
46 |
+
// An error regarding the password was already found.
|
47 |
+
if ( $errors->get_error_data( 'pass' ) ) {
|
48 |
+
return $errors;
|
49 |
}
|
50 |
|
51 |
+
if ( isset( $user->user_pass ) || ! $update ) {
|
52 |
+
return $errors;
|
53 |
}
|
54 |
|
55 |
+
// The password was not changed, but an update is occurring. Test to see if we need to prompt for a password change.
|
56 |
+
// This also handles the case where a user's role is being changed to one that requires strong password enforcement.
|
57 |
+
|
58 |
+
$strength = get_user_meta( $user->ID, 'itsec-password-strength', true );
|
59 |
+
|
60 |
+
if ( ! is_numeric( $strength ) || $strength < 0 || $strength > 4 ) {
|
61 |
+
// Not enough data to determine whether a change of password is required.
|
62 |
+
return $errors;
|
63 |
+
}
|
64 |
|
65 |
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
66 |
|
67 |
+
if ( isset( $user->role ) ) {
|
68 |
+
$role = $this->get_canonical_role_from_role_and_user( $user->role, $user );
|
69 |
+
} else {
|
70 |
+
$role = ITSEC_Lib_Canonical_Roles::get_user_role( $user );
|
71 |
}
|
72 |
+
|
73 |
+
if ( ! $this->role_requires_strong_password( $role ) ) {
|
74 |
+
return $errors;
|
75 |
+
}
|
76 |
+
|
77 |
+
if ( 4 === (int) $strength ) {
|
78 |
+
return $errors;
|
79 |
+
}
|
80 |
+
|
81 |
+
if ( ! $update ) {
|
82 |
+
$context = 'admin-user-create';
|
83 |
+
} elseif ( $user->ID === get_current_user_id() ) {
|
84 |
+
$context = 'profile-update';
|
85 |
+
} else {
|
86 |
+
$context = 'admin-profile-update';
|
87 |
+
}
|
88 |
+
|
89 |
+
$errors->add( 'pass', $this->make_error_message( $context ) );
|
90 |
+
|
91 |
+
return $errors;
|
92 |
}
|
93 |
|
94 |
/**
|
95 |
+
* Validate a new password according to the configured strength rules.
|
|
|
|
|
96 |
*
|
97 |
+
* @param WP_Error $error
|
98 |
+
* @param WP_User $user
|
99 |
+
* @param string $new_password
|
100 |
+
* @param array $args
|
101 |
*/
|
102 |
+
public function validate_password( $error, $user, $new_password, $args = array() ) {
|
103 |
|
104 |
+
if ( isset( $args['strength'] ) ) {
|
105 |
+
$reported_strength = $args['strength'];
|
106 |
+
} else {
|
107 |
+
$reported_strength = false;
|
108 |
}
|
109 |
|
110 |
+
if ( empty( $user->ID ) || ! is_numeric( $user->ID ) ) {
|
111 |
+
$role = isset( $args['role'] ) ? $args['role'] : get_option( 'default_role', 'subscriber' );
|
112 |
+
} elseif ( isset( $args['role'] ) ) {
|
113 |
+
$role = $this->get_canonical_role_from_role_and_user( $args['role'], $user );
|
114 |
+
} else {
|
115 |
+
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
116 |
+
$role = ITSEC_Lib_Canonical_Roles::get_user_role( $user );
|
117 |
+
}
|
118 |
|
119 |
+
if ( ! $this->role_requires_strong_password( $role ) ) {
|
120 |
+
return;
|
121 |
+
}
|
122 |
|
123 |
+
if ( ! $this->fails_enforcement( $user, $new_password, $reported_strength ) ) {
|
124 |
+
return;
|
125 |
}
|
|
|
126 |
|
127 |
+
$message = $this->make_error_message( $args['context'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
$error->add( 'pass', $message );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
}
|
131 |
|
132 |
/**
|
133 |
+
* Retrieve a canonical role for a user and a role.
|
134 |
*
|
135 |
+
* @param string $role
|
136 |
+
* @param WP_User $user
|
|
|
|
|
137 |
*
|
138 |
+
* @return string
|
139 |
*/
|
140 |
+
private function get_canonical_role_from_role_and_user( $role, $user ) {
|
141 |
+
if ( empty( $role ) ) {
|
142 |
+
$role_caps = array();
|
143 |
+
} else {
|
144 |
+
$role_caps = array_keys( array_filter( wp_roles()->get_role( $role )->capabilities ) );
|
145 |
}
|
146 |
|
147 |
+
$user_caps = array();
|
148 |
|
149 |
+
if ( isset( $user->caps ) ) {
|
150 |
+
$wp_roles = wp_roles();
|
151 |
|
152 |
+
foreach ( $user->caps as $cap => $has ) {
|
153 |
+
if ( $has && ! $wp_roles->is_role( $cap ) ) {
|
154 |
+
$user_caps[] = $has;
|
155 |
+
}
|
156 |
+
}
|
157 |
}
|
158 |
|
159 |
+
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
|
|
160 |
|
161 |
+
return ITSEC_Lib_Canonical_Roles::get_role_from_caps( array_merge( $role_caps, $user_caps ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
|
164 |
/**
|
165 |
+
* Get the strong password error message according to the given context.
|
166 |
+
*
|
167 |
+
* @param string $context
|
168 |
*
|
169 |
+
* @return string
|
170 |
*/
|
171 |
+
private function make_error_message( $context ) {
|
172 |
+
$message = __( '<strong>Error</strong>: Due to site rules, a strong password is required. Please choose a new password that rates as <strong>Strong</strong> on the meter.', 'better-wp-security' );
|
173 |
+
|
174 |
+
if ( 'admin-user-create' === $context ) {
|
175 |
+
$message .= ' ' . __( 'The user has not been created.', 'better-wp-security' );
|
176 |
+
} elseif ( 'admin-profile-update' === $context ) {
|
177 |
+
$message .= ' ' . __( 'The user changes have not been saved.', 'better-wp-security' );
|
178 |
+
} elseif ( 'profile-update' === $context ) {
|
179 |
+
$message .= ' ' . __( 'Your profile has not been updated.', 'better-wp-security' );
|
180 |
+
} elseif ( 'reset-password' === $context ) {
|
181 |
+
$message .= ' ' . __( 'The password has not been updated.', 'better-wp-security' );
|
182 |
+
}
|
183 |
+
|
184 |
+
return wp_kses( $message, array( 'strong' => array() ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
}
|
186 |
|
187 |
/**
|
188 |
+
* Does the given role require a strong password.
|
189 |
*
|
190 |
+
* @param string $role The user's canonical role.
|
191 |
*
|
192 |
+
* @return bool
|
193 |
*/
|
194 |
+
private function role_requires_strong_password( $role ) {
|
195 |
+
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
|
|
|
|
|
|
|
|
196 |
|
197 |
+
$min_role = ITSEC_Modules::get_setting( 'strong-passwords', 'role' );
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
+
return ITSEC_Lib_Canonical_Roles::is_canonical_role_at_least( $min_role, $role );
|
200 |
}
|
201 |
|
202 |
/**
|
203 |
+
* Determine if the user requires enforcement and if it fails that enforcement.
|
204 |
*
|
205 |
+
* @param WP_User|stdClass $user Requires either a valid WP_User object or an object that has the following members:
|
206 |
+
* user_login, first_name, last_name, nickname, display_name, user_email, user_url, and
|
207 |
+
* description. A member of user_pass is required if $password_strength is false.
|
208 |
+
* @param string $new_password The user's new password.
|
209 |
+
* @param int|boolean $password_strength [optional] An integer value representing the password strength, if known, or false.
|
210 |
+
* Defaults to false.
|
211 |
*
|
212 |
+
* @return boolean True if the user requires enforcement and has a password weaker than strong. False otherwise.
|
213 |
*/
|
214 |
+
private function fails_enforcement( $user, $new_password, $password_strength = false ) {
|
215 |
+
|
216 |
+
if ( false !== $password_strength ) {
|
217 |
+
return $password_strength < 4;
|
218 |
+
}
|
219 |
+
|
220 |
+
if ( ! empty( $_POST['password_strength'] ) && 'strong' !== $_POST['password_strength'] ) {
|
221 |
+
// We want to validate the password strength if the form data says that the password is strong since we want
|
222 |
+
// to protect against spoofing. If the form data says that the password isn't strong, believe it.
|
223 |
+
|
224 |
+
$password_strength = 1;
|
225 |
+
} else {
|
226 |
+
// The form data does not indicate a password strength or the data claimed that the password is strong,
|
227 |
+
// which is a claim that must be validated. Use the zxcvbn library to find the password strength score.
|
228 |
|
229 |
+
$penalty_strings = array(
|
230 |
+
get_site_option( 'admin_email' )
|
231 |
+
);
|
232 |
+
$user_properties = array( 'user_login', 'first_name', 'last_name', 'nickname', 'display_name', 'user_email', 'user_url', 'description' );
|
233 |
|
234 |
+
foreach ( $user_properties as $user_property ) {
|
235 |
+
if ( isset( $user->$user_property ) ) {
|
236 |
+
$penalty_strings[] = $user->$user_property;
|
237 |
+
}
|
238 |
}
|
|
|
239 |
|
240 |
+
$results = ITSEC_Lib::get_password_strength_results( $new_password, $penalty_strings );
|
241 |
+
$password_strength = $results->score;
|
242 |
+
}
|
243 |
|
244 |
+
return $password_strength < 4;
|
245 |
}
|
246 |
}
|
247 |
|
core/modules/strong-passwords/js/script.js
CHANGED
@@ -1,3 +1,10 @@
|
|
1 |
jQuery( document ).ready( function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
jQuery( '.pw-weak' ).remove();
|
3 |
-
} );
|
1 |
jQuery( document ).ready( function () {
|
2 |
+
|
3 |
+
jQuery( '#resetpassform, #your-profile, #createuser' ).submit( function () {
|
4 |
+
|
5 |
+
jQuery( '#submit, #createusersub, #resetpassform' ).append( '<input type="hidden" name="password_strength" id="password_strength" value="' + jQuery( '#pass-strength-result' ).attr( 'class' ).replace( /hide-if-no-js /, '' ) + '">' );
|
6 |
+
|
7 |
+
} );
|
8 |
+
|
9 |
jQuery( '.pw-weak' ).remove();
|
10 |
+
} );
|
core/modules/strong-passwords/settings-page.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class ITSEC_Strong_Passwords_Settings_Page extends ITSEC_Module_Settings_Page {
|
4 |
+
private $script_version = 1;
|
5 |
+
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
$this->id = 'strong-passwords';
|
9 |
+
$this->title = __( 'Strong Password Enforcement', 'better-wp-security' );
|
10 |
+
$this->description = __( 'Force users to use strong passwords as rated by the WordPress password meter.', 'better-wp-security' );
|
11 |
+
$this->type = 'recommended';
|
12 |
+
|
13 |
+
parent::__construct();
|
14 |
+
}
|
15 |
+
|
16 |
+
protected function render_description( $form ) {
|
17 |
+
|
18 |
+
?>
|
19 |
+
<p><?php _e( 'Force users to use strong passwords as rated by the WordPress password meter.', 'better-wp-security' ); ?></p>
|
20 |
+
<?php
|
21 |
+
|
22 |
+
}
|
23 |
+
|
24 |
+
protected function render_settings( $form ) {
|
25 |
+
$roles = array(
|
26 |
+
'administrator' => translate_user_role( 'Administrator' ),
|
27 |
+
'editor' => translate_user_role( 'Editor' ),
|
28 |
+
'author' => translate_user_role( 'Author' ),
|
29 |
+
'contributor' => translate_user_role( 'Contributor' ),
|
30 |
+
'subscriber' => translate_user_role( 'Subscriber' ),
|
31 |
+
);
|
32 |
+
|
33 |
+
?>
|
34 |
+
<table class="form-table itsec-settings-section">
|
35 |
+
<tr>
|
36 |
+
<th scope="row"><label for="itsec-strong-passwords-role"><?php _e( 'Select Role for Strong Passwords', 'better-wp-security' ); ?></label></th>
|
37 |
+
<td>
|
38 |
+
<?php $form->add_select( 'role', $roles ); ?>
|
39 |
+
<br />
|
40 |
+
<label for="itsec-strong-passwords-role"><?php _e( 'Minimum role at which a user must choose a strong password.', 'better-wp-security' ); ?></label>
|
41 |
+
<p class="description"><?php printf( __( 'For more information on WordPress roles and capabilities please see <a href="%1$s" target="_blank" rel="noopener noreferrer">%1$s</a>.', 'better-wp-security' ), 'http://codex.wordpress.org/Roles_and_Capabilities' ); ?></p>
|
42 |
+
<p class="warningtext description"><?php _e( 'Warning: If your site invites public registrations setting the role too low may annoy your members.', 'better-wp-security' ); ?></p>
|
43 |
+
</td>
|
44 |
+
</tr>
|
45 |
+
</table>
|
46 |
+
<?php
|
47 |
+
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
new ITSEC_Strong_Passwords_Settings_Page();
|
core/modules/strong-passwords/setup.php
CHANGED
@@ -6,10 +6,10 @@ if ( ! class_exists( 'ITSEC_Strong_Passwords_Setup' ) ) {
|
|
6 |
|
7 |
public function __construct() {
|
8 |
|
9 |
-
add_action( 'itsec_modules_do_plugin_activation',
|
10 |
-
add_action( 'itsec_modules_do_plugin_deactivation', array( $this, 'execute_deactivate' )
|
11 |
-
add_action( 'itsec_modules_do_plugin_uninstall',
|
12 |
-
add_action( 'itsec_modules_do_plugin_upgrade',
|
13 |
|
14 |
}
|
15 |
|
@@ -86,28 +86,6 @@ if ( ! class_exists( 'ITSEC_Strong_Passwords_Setup' ) ) {
|
|
86 |
}
|
87 |
}
|
88 |
|
89 |
-
if ( $itsec_old_version < 4096 ) {
|
90 |
-
$active = get_site_option( 'itsec_active_modules', array() );
|
91 |
-
|
92 |
-
if ( ! empty( $active['strong-passwords'] ) ) {
|
93 |
-
$active_requirements = ITSEC_Modules::get_setting( 'password-requirements', 'enabled_requirements' );
|
94 |
-
$active_requirements['strength'] = true;
|
95 |
-
ITSEC_Modules::set_setting( 'password-requirements', 'enabled_requirements', $active_requirements );
|
96 |
-
}
|
97 |
-
|
98 |
-
$requirement_settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
99 |
-
$requirement_settings['strength']['role'] = ITSEC_Modules::get_setting( 'strong-passwords', 'role', 'administrator' );
|
100 |
-
ITSEC_Modules::set_setting( 'password-requirements', 'requirement_settings', $requirement_settings );
|
101 |
-
|
102 |
-
unset( $active['strong-passwords'] );
|
103 |
-
|
104 |
-
// Need to do this directly to be able to remove a module from the list entirely.
|
105 |
-
if ( is_multisite() ) {
|
106 |
-
update_site_option( 'itsec_active_modules', $active );
|
107 |
-
} else {
|
108 |
-
update_option( 'itsec_active_modules', $active );
|
109 |
-
}
|
110 |
-
}
|
111 |
}
|
112 |
|
113 |
}
|
6 |
|
7 |
public function __construct() {
|
8 |
|
9 |
+
add_action( 'itsec_modules_do_plugin_activation', array( $this, 'execute_activate' ) );
|
10 |
+
add_action( 'itsec_modules_do_plugin_deactivation', array( $this, 'execute_deactivate' ) );
|
11 |
+
add_action( 'itsec_modules_do_plugin_uninstall', array( $this, 'execute_uninstall' ) );
|
12 |
+
add_action( 'itsec_modules_do_plugin_upgrade', array( $this, 'execute_upgrade' ), null, 2 );
|
13 |
|
14 |
}
|
15 |
|
86 |
}
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}
|
90 |
|
91 |
}
|
core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php
CHANGED
@@ -128,68 +128,6 @@ final class ITSEC_WordPress_Tweaks {
|
|
128 |
}
|
129 |
}
|
130 |
|
131 |
-
public function deinit() {
|
132 |
-
$this->remove_config_hooks();
|
133 |
-
|
134 |
-
// Functional code for the valid_user_login_type setting.
|
135 |
-
if ( 'email' === $this->settings['valid_user_login_type'] ) {
|
136 |
-
remove_action( 'login_init', array( $this, 'add_gettext_filter' ) );
|
137 |
-
remove_filter( 'authenticate', array( $this, 'add_gettext_filter' ), 0 );
|
138 |
-
add_filter( 'authenticate', 'wp_authenticate_username_password', 20 );
|
139 |
-
} else if ( 'username' === $this->settings['valid_user_login_type'] ) {
|
140 |
-
remove_action( 'login_init', array( $this, 'add_gettext_filter' ) );
|
141 |
-
remove_filter( 'authenticate', array( $this, 'add_gettext_filter' ), 0 );
|
142 |
-
add_filter( 'authenticate', 'wp_authenticate_email_password', 20 );
|
143 |
-
}
|
144 |
-
|
145 |
-
// Functional code for the allow_xmlrpc_multiauth setting.
|
146 |
-
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && ! $this->settings['allow_xmlrpc_multiauth'] ) {
|
147 |
-
remove_filter( 'authenticate', array( $this, 'block_multiauth_attempts' ), 0 );
|
148 |
-
}
|
149 |
-
|
150 |
-
//remove wlmanifest link if turned on
|
151 |
-
if ( $this->settings['wlwmanifest_header'] ) {
|
152 |
-
add_action( 'wp_head', 'wlwmanifest_link' );
|
153 |
-
}
|
154 |
-
|
155 |
-
//remove rsd link from header if turned on
|
156 |
-
if ( $this->settings['edituri_header'] ) {
|
157 |
-
add_action( 'wp_head', 'rsd_link' );
|
158 |
-
}
|
159 |
-
|
160 |
-
//Disable XML-RPC
|
161 |
-
if ( 2 == $this->settings['disable_xmlrpc'] ) {
|
162 |
-
remove_filter( 'xmlrpc_enabled', '__return_null' );
|
163 |
-
remove_filter( 'bloginfo_url', array( $this, 'remove_pingback_url' ), 10 );
|
164 |
-
} else if ( 1 == $this->settings['disable_xmlrpc'] ) { // Disable pingbacks
|
165 |
-
remove_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
|
166 |
-
}
|
167 |
-
|
168 |
-
remove_filter( 'rest_dispatch_request', array( $this, 'filter_rest_dispatch_request' ), 10 );
|
169 |
-
|
170 |
-
//Process remove login errors
|
171 |
-
if ( $this->settings['login_errors'] ) {
|
172 |
-
remove_filter( 'login_errors', '__return_null' );
|
173 |
-
}
|
174 |
-
|
175 |
-
//Process require unique nicename
|
176 |
-
if ( $this->settings['force_unique_nicename'] ) {
|
177 |
-
remove_action( 'user_profile_update_errors', array( $this, 'force_unique_nicename' ), 10 );
|
178 |
-
}
|
179 |
-
|
180 |
-
//Process remove extra author archives
|
181 |
-
if ( $this->settings['disable_unused_author_pages'] ) {
|
182 |
-
remove_action( 'template_redirect', array( $this, 'disable_unused_author_pages' ) );
|
183 |
-
}
|
184 |
-
|
185 |
-
if ( $this->settings['block_tabnapping'] ) {
|
186 |
-
remove_action( 'wp_enqueue_scripts', array( $this, 'add_block_tabnapping_script' ) );
|
187 |
-
remove_action( 'admin_enqueue_scripts', array( $this, 'add_block_tabnapping_script' ) );
|
188 |
-
}
|
189 |
-
|
190 |
-
remove_filter( 'rest_request_after_callbacks', array( $this, 'filter_taxonomies_response' ), 10, 3 );
|
191 |
-
}
|
192 |
-
|
193 |
/**
|
194 |
* Add filter for gettext to change text for the valid_user_login_type setting changes.
|
195 |
*
|
@@ -265,44 +203,24 @@ final class ITSEC_WordPress_Tweaks {
|
|
265 |
return $result;
|
266 |
}
|
267 |
|
268 |
-
if ( function_exists( 'rest_authorization_required_code' ) ) {
|
269 |
-
$code = rest_authorization_required_code();
|
270 |
-
} else {
|
271 |
-
$code = is_user_logged_in() ? 403 : 401;
|
272 |
-
}
|
273 |
-
|
274 |
-
$error = new WP_Error( 'itsec_rest_api_access_restricted', __( 'You do not have sufficient permission to access this endpoint. Access to REST API requests is restricted by iThemes Security settings.', 'better-wp-security' ), array(
|
275 |
-
'status' => $code,
|
276 |
-
) );
|
277 |
-
|
278 |
// Each of the following endpoints can be restricted based on a simple capability check.
|
279 |
$endpoint_caps = array(
|
280 |
'comments' => 'moderate_comments',
|
281 |
'statuses' => 'edit_posts',
|
|
|
282 |
'types' => 'edit_posts',
|
283 |
);
|
284 |
|
285 |
-
if ( version_compare( $GLOBALS['wp_version'], '4.7.0', '<' ) ) {
|
286 |
-
// We need the request_after_callbacks filter to perform this blocking. So fallback to a more general edit_posts capability when this hook isn't available.
|
287 |
-
$endpoint_caps['taxonomies'] = 'edit_posts';
|
288 |
-
}
|
289 |
-
|
290 |
foreach ( $endpoint_caps as $endpoint => $cap ) {
|
291 |
if ( $endpoint === $route_parts[2] ) {
|
292 |
if ( current_user_can( $cap ) ) {
|
293 |
return $result;
|
294 |
}
|
295 |
|
296 |
-
return
|
297 |
}
|
298 |
}
|
299 |
|
300 |
-
if ( 'taxonomies' === $route_parts[2] ) {
|
301 |
-
add_filter( 'rest_request_after_callbacks', array( $this, 'filter_taxonomies_response' ), 10, 3 );
|
302 |
-
|
303 |
-
return $result;
|
304 |
-
}
|
305 |
-
|
306 |
if ( 'users' === $route_parts[2] ) {
|
307 |
if ( isset( $route_parts[3] ) && 'me' === $route_parts[3] ) {
|
308 |
// The users/me endpoint has its own permissions checks.
|
@@ -314,7 +232,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
314 |
return $result;
|
315 |
}
|
316 |
|
317 |
-
return
|
318 |
}
|
319 |
|
320 |
|
@@ -341,7 +259,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
341 |
if ( current_user_can( $taxonomy->cap->edit_terms ) ) {
|
342 |
return $result;
|
343 |
} else {
|
344 |
-
return
|
345 |
}
|
346 |
}
|
347 |
}
|
@@ -363,7 +281,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
363 |
if ( current_user_can( $post_type->cap->edit_posts ) ) {
|
364 |
return $result;
|
365 |
} else {
|
366 |
-
return
|
367 |
}
|
368 |
}
|
369 |
}
|
@@ -376,74 +294,6 @@ final class ITSEC_WordPress_Tweaks {
|
|
376 |
return $result;
|
377 |
}
|
378 |
|
379 |
-
/**
|
380 |
-
* Filter the taxonomies response to exclude taxonomies the user does not have edit permission for.
|
381 |
-
*
|
382 |
-
* @param WP_REST_Response|WP_Error $response
|
383 |
-
* @param array $handler
|
384 |
-
* @param WP_REST_Request $request
|
385 |
-
*
|
386 |
-
* @return WP_REST_Response|WP_Error
|
387 |
-
*/
|
388 |
-
public function filter_taxonomies_response( $response, $handler, $request ) {
|
389 |
-
|
390 |
-
if ( is_wp_error( $response ) ) {
|
391 |
-
return $response;
|
392 |
-
}
|
393 |
-
|
394 |
-
$route = strtolower( $request->get_route() );
|
395 |
-
$route_parts = explode( '/', trim( $route, '/' ) );
|
396 |
-
|
397 |
-
if ( 'wp' !== $route_parts[0] || ! isset( $route_parts[2] ) || 'taxonomies' !== $route_parts[2] ) {
|
398 |
-
return $response;
|
399 |
-
}
|
400 |
-
|
401 |
-
if ( function_exists( 'rest_authorization_required_code' ) ) {
|
402 |
-
$code = rest_authorization_required_code();
|
403 |
-
} else {
|
404 |
-
$code = is_user_logged_in() ? 403 : 401;
|
405 |
-
}
|
406 |
-
|
407 |
-
$error = new WP_Error( 'itsec_rest_api_access_restricted', __( 'You do not have sufficient permission to access this endpoint. Access to REST API requests is restricted by iThemes Security settings.', 'better-wp-security' ), array(
|
408 |
-
'status' => $code,
|
409 |
-
) );
|
410 |
-
|
411 |
-
$data = $response->get_data();
|
412 |
-
|
413 |
-
if ( isset( $route_parts[3] ) ) {
|
414 |
-
if ( ! $taxonomy = get_taxonomy( $route_parts[3] ) ) {
|
415 |
-
return $response;
|
416 |
-
}
|
417 |
-
|
418 |
-
if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) {
|
419 |
-
return $error;
|
420 |
-
}
|
421 |
-
|
422 |
-
return $response;
|
423 |
-
}
|
424 |
-
|
425 |
-
foreach ( $data as $i => $taxonomy_data ) {
|
426 |
-
if ( ! isset( $taxonomy_data['slug'] ) ) {
|
427 |
-
continue;
|
428 |
-
}
|
429 |
-
|
430 |
-
if ( ! $taxonomy = get_taxonomy( $taxonomy_data['slug'] ) ) {
|
431 |
-
continue;
|
432 |
-
}
|
433 |
-
|
434 |
-
if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) {
|
435 |
-
unset( $data[ $i ] );
|
436 |
-
}
|
437 |
-
}
|
438 |
-
|
439 |
-
if ( ! $data ) {
|
440 |
-
return $error;
|
441 |
-
}
|
442 |
-
|
443 |
-
$response->set_data( $data );
|
444 |
-
|
445 |
-
return $response;
|
446 |
-
}
|
447 |
|
448 |
public function add_block_tabnapping_script() {
|
449 |
wp_enqueue_script( 'blankshield', plugins_url( 'js/blankshield/blankshield.min.js', __FILE__ ), array(), ITSEC_Core::get_plugin_build(), true );
|
128 |
}
|
129 |
}
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
/**
|
132 |
* Add filter for gettext to change text for the valid_user_login_type setting changes.
|
133 |
*
|
203 |
return $result;
|
204 |
}
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
// Each of the following endpoints can be restricted based on a simple capability check.
|
207 |
$endpoint_caps = array(
|
208 |
'comments' => 'moderate_comments',
|
209 |
'statuses' => 'edit_posts',
|
210 |
+
'taxonomies' => 'edit_terms',
|
211 |
'types' => 'edit_posts',
|
212 |
);
|
213 |
|
|
|
|
|
|
|
|
|
|
|
214 |
foreach ( $endpoint_caps as $endpoint => $cap ) {
|
215 |
if ( $endpoint === $route_parts[2] ) {
|
216 |
if ( current_user_can( $cap ) ) {
|
217 |
return $result;
|
218 |
}
|
219 |
|
220 |
+
return new WP_Error( 'itsec_rest_api_access_restricted', __( 'You do not have sufficient permission to access this endpoint. Access to REST API requests is restricted by iThemes Security settings.', 'better-wp-security' ) );
|
221 |
}
|
222 |
}
|
223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
if ( 'users' === $route_parts[2] ) {
|
225 |
if ( isset( $route_parts[3] ) && 'me' === $route_parts[3] ) {
|
226 |
// The users/me endpoint has its own permissions checks.
|
232 |
return $result;
|
233 |
}
|
234 |
|
235 |
+
return new WP_Error( 'itsec_rest_api_access_restricted', __( 'You do not have sufficient permission to access this endpoint. Access to REST API requests is restricted by iThemes Security settings.', 'better-wp-security' ) );
|
236 |
}
|
237 |
|
238 |
|
259 |
if ( current_user_can( $taxonomy->cap->edit_terms ) ) {
|
260 |
return $result;
|
261 |
} else {
|
262 |
+
return new WP_Error( 'itsec_rest_api_access_restricted', __( 'You do not have sufficient permission to access this endpoint. Access to REST API requests is restricted by iThemes Security settings.', 'better-wp-security' ) );
|
263 |
}
|
264 |
}
|
265 |
}
|
281 |
if ( current_user_can( $post_type->cap->edit_posts ) ) {
|
282 |
return $result;
|
283 |
} else {
|
284 |
+
return new WP_Error( 'itsec_rest_api_access_restricted', __( 'You do not have sufficient permission to access this endpoint. Access to REST API requests is restricted by iThemes Security settings.', 'better-wp-security' ) );
|
285 |
}
|
286 |
}
|
287 |
}
|
294 |
return $result;
|
295 |
}
|
296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
|
298 |
public function add_block_tabnapping_script() {
|
299 |
wp_enqueue_script( 'blankshield', plugins_url( 'js/blankshield/blankshield.min.js', __FILE__ ), array(), ITSEC_Core::get_plugin_build(), true );
|
core/modules/wordpress-tweaks/settings-page.php
CHANGED
@@ -158,14 +158,6 @@ final class ITSEC_WordPress_Tweaks_Settings_Page extends ITSEC_Module_Settings_P
|
|
158 |
</ul>
|
159 |
</td>
|
160 |
</tr>
|
161 |
-
<tr>
|
162 |
-
<th scope="row"><label for="itsec-wordpress-tweaks-patch_thumb_file_traversal"><?php esc_html_e( 'Mitigate Attachment File Traversal Attack', 'better-wp-security' ); ?></label></th>
|
163 |
-
<td>
|
164 |
-
<?php $form->add_checkbox( 'patch_thumb_file_traversal' ); ?>
|
165 |
-
<label for="itsec-wordpress-tweaks-patch_thumb_file_traversal"><?php esc_html_e( 'Prevent attachment thumbnails from traversing to other files.', 'better-wp-security' ); ?></label>
|
166 |
-
<p class="description"><?php esc_html_e( 'Disabling this feature is not recommended. This helps mitigate an attack where users with the "author" role or higher could delete any file in your WordPress installation including sensitive files like wp-config.php.', 'better-wp-security' ); ?></p>
|
167 |
-
</td>
|
168 |
-
</tr>
|
169 |
</table>
|
170 |
<?php
|
171 |
|
158 |
</ul>
|
159 |
</td>
|
160 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
</table>
|
162 |
<?php
|
163 |
|
core/modules/wordpress-tweaks/settings.php
CHANGED
@@ -19,7 +19,6 @@ final class ITSEC_Wordpress_Tweaks_Settings extends ITSEC_Settings {
|
|
19 |
'disable_unused_author_pages' => false,
|
20 |
'block_tabnapping' => false,
|
21 |
'valid_user_login_type' => 'both',
|
22 |
-
'patch_thumb_file_traversal' => true,
|
23 |
);
|
24 |
}
|
25 |
}
|
19 |
'disable_unused_author_pages' => false,
|
20 |
'block_tabnapping' => false,
|
21 |
'valid_user_login_type' => 'both',
|
|
|
22 |
);
|
23 |
}
|
24 |
}
|
core/modules/wordpress-tweaks/validator.php
CHANGED
@@ -21,7 +21,6 @@ class ITSEC_WordPress_Tweaks_Validator extends ITSEC_Validator {
|
|
21 |
$this->sanitize_setting( 'bool', 'disable_unused_author_pages', __( 'Disable Extra User Archives', 'better-wp-security' ) );
|
22 |
$this->sanitize_setting( 'bool', 'block_tabnapping', __( 'Protect Against Tabnapping', 'better-wp-security' ) );
|
23 |
$this->sanitize_setting( array( 'both', 'email', 'username' ), 'valid_user_login_type', __( 'Login with Email Address or Username', 'better-wp-security' ) );
|
24 |
-
$this->sanitize_setting( 'bool', 'patch_thumb_file_traversal', __( 'Mitigate Attachment File Traversal Attack', 'better-wp-security' ) );
|
25 |
}
|
26 |
|
27 |
protected function validate_settings() {
|
21 |
$this->sanitize_setting( 'bool', 'disable_unused_author_pages', __( 'Disable Extra User Archives', 'better-wp-security' ) );
|
22 |
$this->sanitize_setting( 'bool', 'block_tabnapping', __( 'Protect Against Tabnapping', 'better-wp-security' ) );
|
23 |
$this->sanitize_setting( array( 'both', 'email', 'username' ), 'valid_user_login_type', __( 'Login with Email Address or Username', 'better-wp-security' ) );
|
|
|
24 |
}
|
25 |
|
26 |
protected function validate_settings() {
|
core/notify.php
CHANGED
@@ -124,11 +124,9 @@ class ITSEC_Notify {
|
|
124 |
|
125 |
$data_proxy = new ITSEC_Notify_Data_Proxy( $data );
|
126 |
|
127 |
-
$mail = $nc->mail(
|
128 |
$mail->add_header( $title, $banner_title );
|
129 |
-
$mail->start_group( 'intro' );
|
130 |
$mail->add_info_box( sprintf( esc_html__( 'The following is a summary of security related activity on your site: %s', 'better-wp-security' ), '<b>' . $mail->get_display_url() . '</b>' ) );
|
131 |
-
$mail->end_group();
|
132 |
|
133 |
$content = $mail->get_content();
|
134 |
|
@@ -205,13 +203,10 @@ class ITSEC_Notify {
|
|
205 |
'<a href="' . ITSEC_Mail::filter_admin_page_url( ITSEC_Core::get_logs_page_url() ) . '"><b>',
|
206 |
'</b></a>'
|
207 |
) );
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
$mail->add_text( esc_html__( 'Ensure your site is using recommended settings and features with a security check.', 'better-wp-security' ) );
|
213 |
-
$mail->add_button( esc_html__( 'Run a Security Check ✓', 'better-wp-security' ), ITSEC_Mail::filter_admin_page_url( ITSEC_Core::get_security_check_page_url() ) );
|
214 |
-
}
|
215 |
|
216 |
$mail->add_footer();
|
217 |
|
124 |
|
125 |
$data_proxy = new ITSEC_Notify_Data_Proxy( $data );
|
126 |
|
127 |
+
$mail = $nc->mail();
|
128 |
$mail->add_header( $title, $banner_title );
|
|
|
129 |
$mail->add_info_box( sprintf( esc_html__( 'The following is a summary of security related activity on your site: %s', 'better-wp-security' ), '<b>' . $mail->get_display_url() . '</b>' ) );
|
|
|
130 |
|
131 |
$content = $mail->get_content();
|
132 |
|
203 |
'<a href="' . ITSEC_Mail::filter_admin_page_url( ITSEC_Core::get_logs_page_url() ) . '"><b>',
|
204 |
'</b></a>'
|
205 |
) );
|
206 |
+
$mail->add_divider();
|
207 |
+
$mail->add_large_text( esc_html__( 'Is your site as secure as it could be?', 'better-wp-security' ) );
|
208 |
+
$mail->add_text( esc_html__( 'Ensure your site is using recommended settings and features with a security check.', 'better-wp-security' ) );
|
209 |
+
$mail->add_button( esc_html__( 'Run a Security Check ✓', 'better-wp-security' ), ITSEC_Mail::filter_admin_page_url( ITSEC_Core::get_security_check_page_url() ) );
|
|
|
|
|
|
|
210 |
|
211 |
$mail->add_footer();
|
212 |
|
core/response.php
CHANGED
@@ -72,7 +72,7 @@ final class ITSEC_Response {
|
|
72 |
|
73 |
return $self->errors;
|
74 |
}
|
75 |
-
|
76 |
public static function add_warnings( $warnings ) {
|
77 |
foreach ( $warnings as $warning ) {
|
78 |
self::add_warning( $warning );
|
@@ -199,10 +199,6 @@ final class ITSEC_Response {
|
|
199 |
self::get_instance()->add_js_function_call( 'reloadAllModules' );
|
200 |
}
|
201 |
|
202 |
-
public static function refresh_page() {
|
203 |
-
self::get_instance()->add_js_function_call( 'refreshPage' );
|
204 |
-
}
|
205 |
-
|
206 |
public static function regenerate_wp_config() {
|
207 |
$self = self::get_instance();
|
208 |
|
@@ -283,26 +279,16 @@ final class ITSEC_Response {
|
|
283 |
$added = array_diff( $new, $current );
|
284 |
|
285 |
if ( $added ) {
|
286 |
-
self::
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
}
|
288 |
}
|
289 |
|
290 |
-
public static function flag_new_notifications_available() {
|
291 |
-
static $run_count = 0;
|
292 |
-
|
293 |
-
if ( $run_count++ > 0 ) {
|
294 |
-
return;
|
295 |
-
}
|
296 |
-
|
297 |
-
self::reload_module( 'notification-center' );
|
298 |
-
self::get_instance()->has_new_notifications = true;
|
299 |
-
self::get_instance()->add_info( sprintf(
|
300 |
-
esc_html__( 'New notifications available in the %1$sNotification Center%2$s.', 'better-wp-security' ),
|
301 |
-
'<a href="#" data-module-link="notification-center">',
|
302 |
-
'</a>'
|
303 |
-
) );
|
304 |
-
}
|
305 |
-
|
306 |
public static function get_raw_data() {
|
307 |
$self = self::get_instance();
|
308 |
|
72 |
|
73 |
return $self->errors;
|
74 |
}
|
75 |
+
|
76 |
public static function add_warnings( $warnings ) {
|
77 |
foreach ( $warnings as $warning ) {
|
78 |
self::add_warning( $warning );
|
199 |
self::get_instance()->add_js_function_call( 'reloadAllModules' );
|
200 |
}
|
201 |
|
|
|
|
|
|
|
|
|
202 |
public static function regenerate_wp_config() {
|
203 |
$self = self::get_instance();
|
204 |
|
279 |
$added = array_diff( $new, $current );
|
280 |
|
281 |
if ( $added ) {
|
282 |
+
self::reload_module( 'notification-center' );
|
283 |
+
self::get_instance()->has_new_notifications = true;
|
284 |
+
self::get_instance()->add_info( sprintf(
|
285 |
+
esc_html__( 'New notifications available in the %1$sNotification Center%2$s.', 'better-wp-security' ),
|
286 |
+
'<a href="#" data-module-link="notification-center">',
|
287 |
+
'</a>'
|
288 |
+
) );
|
289 |
}
|
290 |
}
|
291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
public static function get_raw_data() {
|
293 |
$self = self::get_instance();
|
294 |
|
core/setup.php
CHANGED
@@ -9,6 +9,7 @@
|
|
9 |
final class ITSEC_Setup {
|
10 |
public static function handle_activation() {
|
11 |
self::setup_plugin_data();
|
|
|
12 |
}
|
13 |
|
14 |
public static function handle_deactivation() {
|
@@ -142,11 +143,13 @@ final class ITSEC_Setup {
|
|
142 |
ITSEC_Lib::schedule_cron_test();
|
143 |
}
|
144 |
|
145 |
-
if (
|
146 |
-
|
147 |
}
|
148 |
|
149 |
-
|
|
|
|
|
150 |
|
151 |
// Update stored build number.
|
152 |
ITSEC_Modules::set_setting( 'global', 'build', ITSEC_Core::get_plugin_build() );
|
@@ -199,7 +202,6 @@ final class ITSEC_Setup {
|
|
199 |
|
200 |
delete_site_option( 'itsec-storage' );
|
201 |
delete_site_option( 'itsec_active_modules' );
|
202 |
-
delete_site_option( 'itsec-enable-grade-report' );
|
203 |
|
204 |
ITSEC_Schema::remove_database_tables();
|
205 |
ITSEC_Lib_Directory::remove( ITSEC_Core::get_storage_dir() );
|
9 |
final class ITSEC_Setup {
|
10 |
public static function handle_activation() {
|
11 |
self::setup_plugin_data();
|
12 |
+
ITSEC_Core::get_scheduler()->register_events();
|
13 |
}
|
14 |
|
15 |
public static function handle_deactivation() {
|
143 |
ITSEC_Lib::schedule_cron_test();
|
144 |
}
|
145 |
|
146 |
+
if ( $build < 4087 ) {
|
147 |
+
ITSEC_Core::get_scheduler()->register_events();
|
148 |
}
|
149 |
|
150 |
+
if ( $build < 4094 ) {
|
151 |
+
ITSEC_Core::get_scheduler()->register_events();
|
152 |
+
}
|
153 |
|
154 |
// Update stored build number.
|
155 |
ITSEC_Modules::set_setting( 'global', 'build', ITSEC_Core::get_plugin_build() );
|
202 |
|
203 |
delete_site_option( 'itsec-storage' );
|
204 |
delete_site_option( 'itsec_active_modules' );
|
|
|
205 |
|
206 |
ITSEC_Schema::remove_database_tables();
|
207 |
ITSEC_Lib_Directory::remove( ITSEC_Core::get_storage_dir() );
|
history.txt
CHANGED
@@ -765,41 +765,3 @@
|
|
765 |
7.0.1 - 2018-05-25 - Chris Jean & Timothy Jacobs
|
766 |
Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
|
767 |
Bug Fix: Skip recovery if File Change storage is empty.
|
768 |
-
7.0.2 - 2018-06-14 - Chris Jean & Timothy Jacobs
|
769 |
-
Enhancement: Add UI to cancel in progress File Scan.
|
770 |
-
Enhancement: Add basic admin debug page to help diagnosing and resolving issues. Particularly with the events.
|
771 |
-
Enhancement: Add debug settings JSON editor.
|
772 |
-
Enhancement: Continually evaluate password strength for users instead of only during registration.
|
773 |
-
Enhancement: Introduce Password Requirements module for managing and enforcing password requirements.
|
774 |
-
Bug Fix: Accessing password requirement settings would not resolve properly in some instances.
|
775 |
-
Bug Fix: Away Mode would not lock out users who were already logged-in during the "away" period.
|
776 |
-
Bug Fix: Enforce the Strong Passwords requirement during Security Check.
|
777 |
-
Bug Fix: Ensure scheduling lock is cleared by the Cron Scheduler when not proceeding with running events.
|
778 |
-
Bug Fix: If a password requirement has been disabled or is no longer available, don't consider the password as needing a change.
|
779 |
-
Bug Fix: Only hide "Acknowledge Weak Password" checkbox if the user was not allowed to use a weak password.
|
780 |
-
Bug Fix: Password strength would not be evaluated if password was set using custom PHP or CLI commands.
|
781 |
-
Bug Fix: Prevent File Change from getting stuck in an infinite rescheduling loop on the first step.
|
782 |
-
Bug Fix: Remove distributed storage table on uninstall.
|
783 |
-
Tweak: Don't write to the tracked files setting if the file hash has not changed.
|
784 |
-
Tweak: If no last password change date is recorded for the user, treat their registration date as the last change date.
|
785 |
-
7.0.3 - 2018-06-18 - Chris Jean & Timothy Jacobs
|
786 |
-
Security Fix: Fixed SQL injection vulnerability in the logs page. Note: Admin privileges are required to exploit this vulnerability. Thanks to Çlirim Emini, Penetration Tester at sentry.co.com, for reporting this vulnerability.
|
787 |
-
Bug Fix: Provide default values for enabled requirements.
|
788 |
-
7.0.4 - 2018-06-27 - Chris Jean & Timothy Jacobs
|
789 |
-
Enhancement: Add mitigation for the WordPress Attachment File Traversal and Deletion vulnerability.
|
790 |
-
Tweak: Fire a WordPress action whenever settings are updated.
|
791 |
-
Bug Fix: Improved input sanitization on the logs page to prevent triggering warnings.
|
792 |
-
7.1.0 - 2018-08-15 - Chris Jean & Timothy Jacobs
|
793 |
-
New Feature: Allow for globally setting recipients for admin-targeted notifications. All new notifications will default to the recipients in this list. Notifications can be set to use the default list or switch to a custom list.
|
794 |
-
Enhancement: Added a setting to enable/disable the Grade Report feature of Pro.
|
795 |
-
Tweak: Check if an IP is blacklisted on page load for compatibility with servers that cannot process server configuration level bans immediately.
|
796 |
-
Tweak: Display a time diff until the next event on the Debug page.
|
797 |
-
Tweak: Use Logging API for tracking Notification Center errors.
|
798 |
-
Tweak: Register Scheduler Events whenever the plugin build changes.
|
799 |
-
Tweak: Allow for filtering logs by any module recorded.
|
800 |
-
Tweak: Account for 3rd-party Backup Plugin in Security Check.
|
801 |
-
Bug Fix: 404 detection for plugins that mark is_404 later in the hook sequence.
|
802 |
-
Bug Fix: REST API Protection blocked the Taxonomies route for all users.
|
803 |
-
Bug Fix: Account for any CLI PHP SAPI instead of just WP-CLI in the SSL Module.
|
804 |
-
Bug Fix: Fixed how the Grade Report enable/disable status is stored to fix admin page loading issues on some sites.
|
805 |
-
Bug Fix: Fix serialization of closure error when a plugin registering a hook with a closure is in the boot-up stack and the notification center is triggered too early in the cycle.
|
765 |
7.0.1 - 2018-05-25 - Chris Jean & Timothy Jacobs
|
766 |
Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
|
767 |
Bug Fix: Skip recovery if File Change storage is empty.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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: 7.1
|
7 |
Requires PHP: 5.2
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -189,48 +189,6 @@ Free support may be available with the help of the community in the <a href="htt
|
|
189 |
|
190 |
== Changelog ==
|
191 |
|
192 |
-
= 7.1.0 =
|
193 |
-
* New Feature: Allow for globally setting recipients for admin-targeted notifications. All new notifications will default to the recipients in this list. Notifications can be set to use the default list or switch to a custom list.
|
194 |
-
* Enhancement: Added a setting to enable/disable the Grade Report feature of Pro.
|
195 |
-
* Tweak: Check if an IP is blacklisted on page load for compatibility with servers that cannot process server configuration level bans immediately.
|
196 |
-
* Tweak: Display a time diff until the next event on the Debug page.
|
197 |
-
* Tweak: Use Logging API for tracking Notification Center errors.
|
198 |
-
* Tweak: Register Scheduler Events whenever the plugin build changes.
|
199 |
-
* Tweak: Allow for filtering logs by any module recorded.
|
200 |
-
* Tweak: Account for 3rd-party Backup Plugin in Security Check.
|
201 |
-
* Bug Fix: 404 detection for plugins that mark is_404 later in the hook sequence.
|
202 |
-
* Bug Fix: REST API Protection blocked the Taxonomies route for all users.
|
203 |
-
* Bug Fix: Account for any CLI PHP SAPI instead of just WP-CLI in the SSL Module.
|
204 |
-
* Bug Fix: Fixed how the Grade Report enable/disable status is stored to fix admin page loading issues on some sites.
|
205 |
-
* Bug Fix: Fix serialization of closure error when a plugin registering a hook with a closure is in the boot-up stack and the notification center is triggered too early in the cycle.
|
206 |
-
|
207 |
-
= 7.0.4 =
|
208 |
-
* Enhancement: Add mitigation for the WordPress Attachment File Traversal and Deletion vulnerability.
|
209 |
-
* Tweak: Fire a WordPress action whenever settings are updated.
|
210 |
-
* Bug Fix: Improved input sanitization on the logs page to prevent triggering warnings.
|
211 |
-
|
212 |
-
= 7.0.3 =
|
213 |
-
* Security Fix: Fixed SQL injection vulnerability in the logs page. Note: Admin privileges are required to exploit this vulnerability. Thanks to Çlirim Emini, Penetration Tester at sentry.co.com, for reporting this vulnerability.
|
214 |
-
* Bug Fix: Provide default values for enabled requirements.
|
215 |
-
|
216 |
-
= 7.0.2 =
|
217 |
-
* Enhancement: Add UI to cancel in progress File Scan.
|
218 |
-
* Enhancement: Add basic admin debug page to help diagnosing and resolving issues. Particularly with the events.
|
219 |
-
* Enhancement: Add debug settings JSON editor.
|
220 |
-
* Enhancement: Continually evaluate password strength for users instead of only during registration.
|
221 |
-
* Enhancement: Introduce Password Requirements module for managing and enforcing password requirements.
|
222 |
-
* Bug Fix: Accessing password requirement settings would not resolve properly in some instances.
|
223 |
-
* Bug Fix: Away Mode would not lock out users who were already logged-in during the "away" period.
|
224 |
-
* Bug Fix: Enforce the Strong Passwords requirement during Security Check.
|
225 |
-
* Bug Fix: Ensure scheduling lock is cleared by the Cron Scheduler when not proceeding with running events.
|
226 |
-
* Bug Fix: If a password requirement has been disabled or is no longer available, don't consider the password as needing a change.
|
227 |
-
* Bug Fix: Only hide "Acknowledge Weak Password" checkbox if the user was not allowed to use a weak password.
|
228 |
-
* Bug Fix: Password strength would not be evaluated if password was set using custom PHP or CLI commands.
|
229 |
-
* Bug Fix: Prevent File Change from getting stuck in an infinite rescheduling loop on the first step.
|
230 |
-
* Bug Fix: Remove distributed storage table on uninstall.
|
231 |
-
* Tweak: Don't write to the tracked files setting if the file hash has not changed.
|
232 |
-
* Tweak: If no last password change date is recorded for the user, treat their registration date as the last change date.
|
233 |
-
|
234 |
= 7.0.1 =
|
235 |
* Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
|
236 |
* Bug Fix: Skip recovery if File Change storage is empty.
|
@@ -496,5 +454,5 @@ Free support may be available with the help of the community in the <a href="htt
|
|
496 |
|
497 |
== Upgrade Notice ==
|
498 |
|
499 |
-
= 7.1
|
500 |
-
Version 7.
|
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
|
6 |
+
Stable tag: 7.0.1
|
7 |
Requires PHP: 5.2
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
189 |
|
190 |
== Changelog ==
|
191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
= 7.0.1 =
|
193 |
* Bug Fix: Fixed an "Uncaught Error: Call to undefined function esc_like()" error that could occur when exporting or erasing personal data.
|
194 |
* Bug Fix: Skip recovery if File Change storage is empty.
|
454 |
|
455 |
== Upgrade Notice ==
|
456 |
|
457 |
+
= 7.0.1 =
|
458 |
+
Version 7.0.0 contains important additions to support privacy controls, bug fixes, and various enhancements. It is recommended for all users.
|