Version Description
- 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.
- Enhancement: Added a setting to enable/disable the Grade Report feature of Pro.
- Tweak: Check if an IP is blacklisted on page load for compatibility with servers that cannot process server configuration level bans immediately.
- Tweak: Display a time diff until the next event on the Debug page.
- Tweak: Use Logging API for tracking Notification Center errors.
- Tweak: Register Scheduler Events whenever the plugin build changes.
- Tweak: Allow for filtering logs by any module recorded.
- Tweak: Account for 3rd-party Backup Plugin in Security Check.
- Bug Fix: 404 detection for plugins that mark is_404 later in the hook sequence.
- Bug Fix: REST API Protection blocked the Taxonomies route for all users.
- Bug Fix: Account for any CLI PHP SAPI instead of just WP-CLI in the SSL Module.
- Bug Fix: Fixed how the Grade Report enable/disable status is stored to fix admin page loading issues on some sites.
- 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.
Download this release
Release Info
Developer | TimothyBlynJacobs |
Plugin | iThemes Security (formerly Better WP Security) |
Version | 7.1.0 |
Comparing to | |
See all releases |
Code changes from version 7.0.4 to 7.1.0
- better-wp-security.php +1 -1
- core/admin-pages/css/style.css +3 -0
- core/admin-pages/js/debug.js +4 -0
- core/admin-pages/js/script.js +25 -21
- core/admin-pages/js/settings.js +25 -21
- core/admin-pages/logs-list-table.php +76 -20
- core/admin-pages/page-debug.php +8 -8
- core/admin-pages/page-logs.php +20 -0
- core/core.php +14 -4
- core/history.txt +22 -1
- core/lib.php +110 -29
- core/lib/class-itsec-job.php +4 -3
- core/lib/class-itsec-lib-canonical-roles.php +27 -0
- core/lib/class-itsec-mail.php +41 -5
- core/lib/class-itsec-scheduler-cron.php +15 -12
- core/lib/class-itsec-scheduler-page-load.php +17 -2
- core/lib/class-itsec-scheduler.php +14 -0
- core/lib/class-itsec-wp-list-table.php +9 -11
- core/lib/form.php +21 -0
- core/lib/validator.php +44 -0
- core/lockout.php +1 -1
- core/modules/404-detection/class-itsec-four-oh-four.php +4 -8
- core/modules/404-detection/logs.php +5 -0
- core/modules/global/settings-page.php +14 -0
- core/modules/global/settings.php +12 -0
- core/modules/global/validator.php +2 -1
- core/modules/notification-center/class-notification-center.php +68 -24
- core/modules/notification-center/debug.php +2 -2
- core/modules/notification-center/js/settings-page.js +6 -4
- core/modules/notification-center/logs.php +94 -0
- core/modules/notification-center/settings-page.php +103 -75
- core/modules/notification-center/settings.php +79 -29
- core/modules/notification-center/setup.php +19 -2
- core/modules/notification-center/validator.php +60 -5
- core/modules/security-check/scanner.php +22 -1
- core/modules/ssl/class-itsec-ssl.php +2 -2
- core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php +155 -5
- core/response.php +22 -8
- core/setup.php +4 -6
- history.txt +15 -1
- readme.txt +19 -4
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.0
|
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.1.0
|
10 |
* Text Domain: better-wp-security
|
11 |
* Network: True
|
12 |
* License: GPLv2
|
core/admin-pages/css/style.css
CHANGED
@@ -866,4 +866,7 @@ body.security_page_itsec-logs #old-logs-migration-status p {
|
|
866 |
|
867 |
#itsec-settings-editor:empty {
|
868 |
display: none;
|
|
|
|
|
|
|
869 |
}
|
866 |
|
867 |
#itsec-settings-editor:empty {
|
868 |
display: none;
|
869 |
+
}
|
870 |
+
.itsec-module-cards-container .bulkactions:empty {
|
871 |
+
display: none;
|
872 |
}
|
core/admin-pages/js/debug.js
CHANGED
@@ -20,6 +20,10 @@
|
|
20 |
} );
|
21 |
} );
|
22 |
|
|
|
|
|
|
|
|
|
23 |
$( '#itsec-scheduler-reset' ).on( 'click', function () {
|
24 |
|
25 |
var $btn = $( this );
|
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 );
|
core/admin-pages/js/script.js
CHANGED
@@ -980,34 +980,38 @@ 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 |
-
|
1009 |
-
|
1010 |
-
}
|
1011 |
};
|
1012 |
|
1013 |
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 |
+
refreshPage: function() {
|
1013 |
+
location.reload( true );
|
1014 |
+
}
|
1015 |
};
|
1016 |
|
1017 |
jQuery(document).ready(function( $ ) {
|
core/admin-pages/js/settings.js
CHANGED
@@ -824,34 +824,38 @@ 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 |
-
|
853 |
-
|
854 |
-
}
|
855 |
};
|
856 |
|
857 |
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 |
+
refreshPage: function() {
|
857 |
+
location.reload( true );
|
858 |
+
}
|
859 |
};
|
860 |
|
861 |
jQuery(document).ready(function( $ ) {
|
core/admin-pages/logs-list-table.php
CHANGED
@@ -110,12 +110,17 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
110 |
return;
|
111 |
}
|
112 |
|
113 |
-
if (
|
114 |
-
$
|
|
|
115 |
} else {
|
116 |
-
$
|
|
|
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 ) {
|
@@ -372,7 +377,7 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
372 |
$current = $this->get_current_view();
|
373 |
|
374 |
foreach ( $views as $type => $description ) {
|
375 |
-
$url =
|
376 |
|
377 |
if ( $current === $type ) {
|
378 |
$description = '<a href="' . esc_url( $url ) . '" class="current" aria-current="page">' . $description . '</a>';
|
@@ -409,28 +414,79 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
409 |
}
|
410 |
|
411 |
protected function extra_tablenav( $which ) {
|
412 |
-
echo '<div class="alignleft actions">';
|
413 |
|
414 |
-
|
415 |
-
|
416 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
|
418 |
-
|
419 |
|
420 |
-
|
421 |
-
|
422 |
-
submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
|
423 |
-
}*/
|
424 |
}
|
425 |
|
426 |
-
|
427 |
-
submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false );
|
428 |
-
}*/
|
429 |
|
430 |
-
|
431 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
432 |
|
433 |
-
|
434 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
435 |
}
|
436 |
}
|
110 |
return;
|
111 |
}
|
112 |
|
113 |
+
if ( false === strpos( $item['code'], '::' ) ) {
|
114 |
+
$code = $item['code'];
|
115 |
+
$data = array();
|
116 |
} else {
|
117 |
+
list( $code, $data ) = explode( '::', $item['code'], 2 );
|
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 ) {
|
377 |
$current = $this->get_current_view();
|
378 |
|
379 |
foreach ( $views as $type => $description ) {
|
380 |
+
$url = $this->get_self_link( array( 'filters' => "type|$type" ), array() );
|
381 |
|
382 |
if ( $current === $type ) {
|
383 |
$description = '<a href="' . esc_url( $url ) . '" class="current" aria-current="page">' . $description . '</a>';
|
414 |
}
|
415 |
|
416 |
protected function extra_tablenav( $which ) {
|
|
|
417 |
|
418 |
+
$filters = $this->get_raw_filters();
|
419 |
+
$current = isset( $filters['module'] ) ? $filters['module'] : '';
|
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 |
+
$items = $wpdb->get_results( "SELECT {$columns} FROM {$wpdb->prefix}itsec_logs GROUP BY `module`", ARRAY_A );
|
467 |
|
468 |
+
if ( ! is_array( $items ) ) {
|
469 |
+
return array();
|
|
|
|
|
470 |
}
|
471 |
|
472 |
+
$modules = array();
|
|
|
|
|
473 |
|
474 |
+
foreach ( $items as $item ) {
|
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 |
+
$item['description'] = $item['code'];
|
484 |
+
$item['module_display'] = $item['module'];
|
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 |
+
return $modules;
|
491 |
}
|
492 |
}
|
core/admin-pages/page-debug.php
CHANGED
@@ -89,12 +89,12 @@ final class ITSEC_Debug_Page {
|
|
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 |
-
$
|
93 |
|
94 |
-
if ( !
|
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 invalid
|
96 |
} else {
|
97 |
-
ITSEC_Core::get_scheduler()->
|
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' ) );
|
@@ -225,7 +225,7 @@ final class ITSEC_Debug_Page {
|
|
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><?php esc_html_e( 'Data', 'better-wp-security' ) ?></th>
|
229 |
<th></th>
|
230 |
</tr>
|
231 |
</thead>
|
@@ -233,12 +233,12 @@ final class ITSEC_Debug_Page {
|
|
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'] );
|
237 |
<td><?php echo isset( $event['schedule'] ) ? $event['schedule'] : '–'; ?></td>
|
238 |
-
<td><?php $event['data'] ? ITSEC_Lib::print_r( $event['data'] ) : print( '–' ); ?></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(
|
242 |
<?php esc_html_e( 'Run', 'better-wp-security' ) ?>
|
243 |
</button>
|
244 |
</td>
|
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' ) );
|
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>
|
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>
|
core/admin-pages/page-logs.php
CHANGED
@@ -274,34 +274,42 @@ final class ITSEC_Logs_Page {
|
|
274 |
'module' => array(
|
275 |
'header' => esc_html__( 'Module', 'better-wp-security' ),
|
276 |
'content' => esc_html( $entry['module'] ),
|
|
|
277 |
),
|
278 |
'type' => array(
|
279 |
'header' => esc_html__( 'Type', 'better-wp-security' ),
|
280 |
'content' => $type,
|
|
|
281 |
),
|
282 |
'description' => array(
|
283 |
'header' => esc_html__( 'Description', 'better-wp-security' ),
|
284 |
'content' => esc_html( $code ),
|
|
|
285 |
),
|
286 |
'timestamp' => array(
|
287 |
'header' => esc_html__( 'Timestamp', 'better-wp-security' ),
|
288 |
'content' => esc_html( $datetime ),
|
|
|
289 |
),
|
290 |
'host' => array(
|
291 |
'header' => esc_html__( 'Host', 'better-wp-security' ),
|
292 |
'content' => '<code>' . esc_html( $entry['remote_ip'] ) . '</code>',
|
|
|
293 |
),
|
294 |
'user' => array(
|
295 |
'header' => esc_html__( 'User', 'better-wp-security' ),
|
296 |
'content' => esc_html( $username ),
|
|
|
297 |
),
|
298 |
'url' => array(
|
299 |
'header' => esc_html__( 'URL', 'better-wp-security' ),
|
300 |
'content' => '<code>' . $url . '</code>',
|
|
|
301 |
),
|
302 |
'raw-details' => array(
|
303 |
'header' => esc_html__( 'Raw Details', 'better-wp-security' ),
|
304 |
'content' => true,
|
|
|
305 |
),
|
306 |
);
|
307 |
|
@@ -329,6 +337,17 @@ final class ITSEC_Logs_Page {
|
|
329 |
|
330 |
$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>';
|
331 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
}
|
333 |
|
334 |
ob_start();
|
@@ -468,6 +487,7 @@ final class ITSEC_Logs_Page {
|
|
468 |
$list->prepare_items();
|
469 |
$list->views();
|
470 |
$form->start_form( array( 'method' => 'GET' ) );
|
|
|
471 |
$list->display();
|
472 |
$form->end_form();
|
473 |
?>
|
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 |
|
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 |
$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 |
?>
|
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
|
@@ -604,11 +604,21 @@ 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 |
}
|
613 |
|
614 |
return $url;
|
24 |
*
|
25 |
* @access private
|
26 |
*/
|
27 |
+
private $plugin_build = 4106;
|
28 |
|
29 |
/**
|
30 |
* Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
|
604 |
return $url;
|
605 |
}
|
606 |
|
607 |
+
public static function get_logs_page_url( $module = false, $type = false ) {
|
608 |
$url = network_admin_url( 'admin.php?page=itsec-logs' );
|
609 |
|
610 |
+
$filters = array();
|
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;
|
core/history.txt
CHANGED
@@ -725,4 +725,25 @@
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
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, -2, 2 );
|
110 |
}
|
111 |
|
112 |
return implode( '.', $host_parts );
|
@@ -175,6 +175,7 @@ final class ITSEC_Lib {
|
|
175 |
|
176 |
if ( ! empty( $ip ) ) {
|
177 |
$GLOBALS['__itsec_remote_ip'] = $ip;
|
|
|
178 |
return $ip;
|
179 |
}
|
180 |
}
|
@@ -184,6 +185,7 @@ final class ITSEC_Lib {
|
|
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,19 +205,19 @@ final class ITSEC_Lib {
|
|
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,21 +408,21 @@ final class ITSEC_Lib {
|
|
406 |
|
407 |
if ( - 1 < $memory_limit ) {
|
408 |
|
409 |
-
$unit
|
410 |
$memory_limit = (int) $memory_limit;
|
411 |
|
412 |
-
$new_unit
|
413 |
$new_memory_limit = (int) $new_memory_limit;
|
414 |
|
415 |
if ( 'm' == $unit ) {
|
416 |
|
417 |
$memory_limit *= 1048576;
|
418 |
|
419 |
-
}
|
420 |
|
421 |
$memory_limit *= 1073741824;
|
422 |
|
423 |
-
}
|
424 |
|
425 |
$memory_limit *= 1024;
|
426 |
|
@@ -430,11 +432,11 @@ final class ITSEC_Lib {
|
|
430 |
|
431 |
$new_memory_limit *= 1048576;
|
432 |
|
433 |
-
}
|
434 |
|
435 |
$new_memory_limit *= 1073741824;
|
436 |
|
437 |
-
}
|
438 |
|
439 |
$new_memory_limit *= 1024;
|
440 |
|
@@ -531,11 +533,11 @@ final class ITSEC_Lib {
|
|
531 |
|
532 |
if ( false === $user ) {
|
533 |
$user = wp_get_current_user();
|
534 |
-
}
|
535 |
$user = get_user_by( 'id', $user );
|
536 |
-
}
|
537 |
$user = get_user_by( 'login', $user );
|
538 |
-
}
|
539 |
$user = get_user_by( 'id', $user->ID );
|
540 |
} else {
|
541 |
if ( is_object( $user ) ) {
|
@@ -607,7 +609,7 @@ final class ITSEC_Lib {
|
|
607 |
|
608 |
if ( 'Basic ' === $http_auth_type ) {
|
609 |
$authentication_types[] = 'header_http_basic_auth';
|
610 |
-
}
|
611 |
$authentication_types[] = 'header_http_oauth';
|
612 |
}
|
613 |
}
|
@@ -624,14 +626,14 @@ final class ITSEC_Lib {
|
|
624 |
$authentication_types[] = 'post_oauth';
|
625 |
}
|
626 |
|
627 |
-
if ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST ) {
|
628 |
-
$source
|
629 |
$authentication_types = array( 'username_and_password' );
|
630 |
-
}
|
631 |
-
$source
|
632 |
$authentication_types[] = 'cookie';
|
633 |
} else {
|
634 |
-
$source
|
635 |
$authentication_types = array( 'username_and_password' );
|
636 |
}
|
637 |
|
@@ -673,7 +675,7 @@ final class ITSEC_Lib {
|
|
673 |
*/
|
674 |
public static function get_request_path() {
|
675 |
if ( ! isset( $GLOBALS['__itsec_lib_get_request_path'] ) ) {
|
676 |
-
$request_uri
|
677 |
$GLOBALS['__itsec_lib_get_request_path'] = self::get_url_path( $request_uri, self::get_home_root() );
|
678 |
}
|
679 |
|
@@ -696,8 +698,8 @@ final class ITSEC_Lib {
|
|
696 |
global $wpdb;
|
697 |
$main_options = $wpdb->base_prefix . 'options';
|
698 |
|
699 |
-
$lock
|
700 |
-
$now
|
701 |
$release_at = $now + $expires_in;
|
702 |
|
703 |
if ( is_multisite() ) {
|
@@ -780,7 +782,7 @@ final class ITSEC_Lib {
|
|
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,13 +847,13 @@ final class ITSEC_Lib {
|
|
845 |
wp_cache_switch_to_blog( 1 );
|
846 |
|
847 |
$alloptions = wp_cache_get( 'alloptions' );
|
848 |
-
$set_all
|
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,7 +920,7 @@ final class ITSEC_Lib {
|
|
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 |
-
|
922 |
} else {
|
923 |
$probability = 0;
|
924 |
}
|
@@ -1183,4 +1185,83 @@ final class ITSEC_Lib {
|
|
1183 |
|
1184 |
return $array;
|
1185 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1186 |
}
|
39 |
w3tc_dbcache_flush();
|
40 |
w3tc_objectcache_flush();
|
41 |
|
42 |
+
} elseif ( 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 |
+
|
179 |
return $ip;
|
180 |
}
|
181 |
}
|
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 |
|
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[ $header ] ) ) {
|
211 |
continue;
|
212 |
}
|
213 |
|
214 |
+
$ip = trim( $_SERVER[ $header ] );
|
215 |
|
216 |
if ( empty( $ip ) ) {
|
217 |
continue;
|
218 |
}
|
219 |
|
220 |
+
if ( false !== ( $comma_index = strpos( $_SERVER[ $header ], ',' ) ) ) {
|
221 |
$ip = substr( $ip, 0, $comma_index );
|
222 |
}
|
223 |
|
408 |
|
409 |
if ( - 1 < $memory_limit ) {
|
410 |
|
411 |
+
$unit = strtolower( substr( $memory_limit, - 1 ) );
|
412 |
$memory_limit = (int) $memory_limit;
|
413 |
|
414 |
+
$new_unit = strtolower( substr( $new_memory_limit, - 1 ) );
|
415 |
$new_memory_limit = (int) $new_memory_limit;
|
416 |
|
417 |
if ( 'm' == $unit ) {
|
418 |
|
419 |
$memory_limit *= 1048576;
|
420 |
|
421 |
+
} elseif ( 'g' == $unit ) {
|
422 |
|
423 |
$memory_limit *= 1073741824;
|
424 |
|
425 |
+
} elseif ( 'k' == $unit ) {
|
426 |
|
427 |
$memory_limit *= 1024;
|
428 |
|
432 |
|
433 |
$new_memory_limit *= 1048576;
|
434 |
|
435 |
+
} elseif ( 'g' == $new_unit ) {
|
436 |
|
437 |
$new_memory_limit *= 1073741824;
|
438 |
|
439 |
+
} elseif ( 'k' == $new_unit ) {
|
440 |
|
441 |
$new_memory_limit *= 1024;
|
442 |
|
533 |
|
534 |
if ( false === $user ) {
|
535 |
$user = wp_get_current_user();
|
536 |
+
} elseif ( is_int( $user ) ) {
|
537 |
$user = get_user_by( 'id', $user );
|
538 |
+
} elseif ( is_string( $user ) ) {
|
539 |
$user = get_user_by( 'login', $user );
|
540 |
+
} elseif ( is_object( $user ) && isset( $user->ID ) ) {
|
541 |
$user = get_user_by( 'id', $user->ID );
|
542 |
} else {
|
543 |
if ( is_object( $user ) ) {
|
609 |
|
610 |
if ( 'Basic ' === $http_auth_type ) {
|
611 |
$authentication_types[] = 'header_http_basic_auth';
|
612 |
+
} elseif ( 'OAuth ' === $http_auth_type ) {
|
613 |
$authentication_types[] = 'header_http_oauth';
|
614 |
}
|
615 |
}
|
626 |
$authentication_types[] = 'post_oauth';
|
627 |
}
|
628 |
|
629 |
+
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
|
630 |
+
$source = 'xmlrpc';
|
631 |
$authentication_types = array( 'username_and_password' );
|
632 |
+
} elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
633 |
+
$source = 'rest_api';
|
634 |
$authentication_types[] = 'cookie';
|
635 |
} else {
|
636 |
+
$source = 'wp-login.php';
|
637 |
$authentication_types = array( 'username_and_password' );
|
638 |
}
|
639 |
|
675 |
*/
|
676 |
public static function get_request_path() {
|
677 |
if ( ! isset( $GLOBALS['__itsec_lib_get_request_path'] ) ) {
|
678 |
+
$request_uri = preg_replace( '|//+|', '/', $_SERVER['REQUEST_URI'] );
|
679 |
$GLOBALS['__itsec_lib_get_request_path'] = self::get_url_path( $request_uri, self::get_home_root() );
|
680 |
}
|
681 |
|
698 |
global $wpdb;
|
699 |
$main_options = $wpdb->base_prefix . 'options';
|
700 |
|
701 |
+
$lock = "itsec-lock-{$name}";
|
702 |
+
$now = ITSEC_Core::get_current_time_gmt();
|
703 |
$release_at = $now + $expires_in;
|
704 |
|
705 |
if ( is_multisite() ) {
|
782 |
$alloptions = wp_cache_get( 'alloptions' );
|
783 |
|
784 |
if ( is_array( $alloptions ) && isset( $alloptions[ $lock ] ) ) {
|
785 |
+
unset( $alloptions[ $lock ] );
|
786 |
wp_cache_set( 'alloptions', $alloptions, 'options' );
|
787 |
} else {
|
788 |
wp_cache_delete( $lock, 'options' );
|
847 |
wp_cache_switch_to_blog( 1 );
|
848 |
|
849 |
$alloptions = wp_cache_get( 'alloptions' );
|
850 |
+
$set_all = false;
|
851 |
|
852 |
foreach ( $rows as $row ) {
|
853 |
$lock = $row->option_name;
|
854 |
|
855 |
if ( is_array( $alloptions ) && isset( $alloptions[ $lock ] ) ) {
|
856 |
+
unset( $alloptions[ $lock ] );
|
857 |
$set_all = true;
|
858 |
} else {
|
859 |
wp_cache_delete( $lock, 'options' );
|
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 |
+
// not valid to a visitor.
|
924 |
} else {
|
925 |
$probability = 0;
|
926 |
}
|
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 |
}
|
core/lib/class-itsec-job.php
CHANGED
@@ -34,10 +34,11 @@ class ITSEC_Job {
|
|
34 |
*
|
35 |
* The original event will not fire while a reschedule is pending.
|
36 |
*
|
37 |
-
* @param int
|
|
|
38 |
*/
|
39 |
-
public function reschedule_in( $seconds ) {
|
40 |
-
$data = $this->
|
41 |
|
42 |
if ( isset( $data['retry_count'] ) ) {
|
43 |
$data['retry_count'] ++;
|
34 |
*
|
35 |
* The original event will not fire while a reschedule is pending.
|
36 |
*
|
37 |
+
* @param int $seconds
|
38 |
+
* @param array $data Additional data to attach to the rescheduled event.
|
39 |
*/
|
40 |
+
public function reschedule_in( $seconds, $data = array() ) {
|
41 |
+
$data = array_merge( $this->data, $data );
|
42 |
|
43 |
if ( isset( $data['retry_count'] ) ) {
|
44 |
$data['retry_count'] ++;
|
core/lib/class-itsec-lib-canonical-roles.php
CHANGED
@@ -165,6 +165,33 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
165 |
return self::get_role_from_caps( array_merge( $role_caps, $user_caps ) );
|
166 |
}
|
167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
/**
|
169 |
* Get a list of all of the capabilities that are unique to each role.
|
170 |
*
|
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 |
*
|
core/lib/class-itsec-mail.php
CHANGED
@@ -369,7 +369,13 @@ final class ITSEC_Mail {
|
|
369 |
return "<li style=\"margin: 0; padding: 5px 10px;{$bold_tag}\">{$item}</li>";
|
370 |
}
|
371 |
|
372 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
373 |
|
374 |
if ( null !== $this->current_group ) {
|
375 |
$this->deferred .= $html;
|
@@ -400,7 +406,18 @@ final class ITSEC_Mail {
|
|
400 |
* This is automatically included in non-user emails if ITSEC_DEBUG is turned on.
|
401 |
*/
|
402 |
public function include_debug_info() {
|
403 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
}
|
405 |
|
406 |
/**
|
@@ -429,7 +446,7 @@ final class ITSEC_Mail {
|
|
429 |
$this->content = $content;
|
430 |
}
|
431 |
|
432 |
-
public function get_content() {
|
433 |
|
434 |
$groups = $this->groups;
|
435 |
|
@@ -439,8 +456,9 @@ final class ITSEC_Mail {
|
|
439 |
*
|
440 |
* @param array $groups
|
441 |
* @param ITSEC_Mail $this
|
|
|
442 |
*/
|
443 |
-
$groups = apply_filters( "itsec_mail_{$this->name}", $groups, $this );
|
444 |
}
|
445 |
|
446 |
return implode( '', $groups );
|
@@ -505,7 +523,25 @@ final class ITSEC_Mail {
|
|
505 |
$this->set_default_subject();
|
506 |
}
|
507 |
|
508 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
509 |
}
|
510 |
|
511 |
/**
|
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;
|
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 |
$this->content = $content;
|
447 |
}
|
448 |
|
449 |
+
public function get_content( $recipient = '' ) {
|
450 |
|
451 |
$groups = $this->groups;
|
452 |
|
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 );
|
523 |
$this->set_default_subject();
|
524 |
}
|
525 |
|
526 |
+
$headers = array(
|
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 |
/**
|
core/lib/class-itsec-scheduler-cron.php
CHANGED
@@ -12,15 +12,19 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
12 |
|
13 |
public function register_cron_schedules( $schedules ) {
|
14 |
|
15 |
-
$schedules[ 'itsec-' . self::
|
|
|
|
|
|
|
|
|
16 |
'display' => esc_html__( 'Four Times per Day', 'better-wp-security' ),
|
17 |
'interval' => DAY_IN_SECONDS / 4,
|
18 |
);
|
19 |
-
$schedules[ 'itsec-' . self::S_WEEKLY ]
|
20 |
'display' => esc_html__( 'Weekly', 'better-wp-security' ),
|
21 |
'interval' => WEEK_IN_SECONDS,
|
22 |
);
|
23 |
-
$schedules[ 'itsec-' . self::S_MONTHLY ]
|
24 |
'display' => esc_html__( 'Monthly', 'better-wp-security' ),
|
25 |
'interval' => MONTH_IN_SECONDS,
|
26 |
);
|
@@ -62,20 +66,18 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
$this->unschedule_single( $id, $data );
|
81 |
$this->call_action( $job );
|
@@ -351,6 +353,7 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
|
|
351 |
'id' => $id,
|
352 |
'data' => $options['single'][ $id ][ $hash ]['data'],
|
353 |
'fire_at' => $timestamp,
|
|
|
354 |
);
|
355 |
}
|
356 |
}
|
12 |
|
13 |
public function register_cron_schedules( $schedules ) {
|
14 |
|
15 |
+
$schedules[ 'itsec-' . self::S_TWICE_HOURLY ] = array(
|
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 ] = array(
|
24 |
'display' => esc_html__( 'Weekly', 'better-wp-security' ),
|
25 |
'interval' => WEEK_IN_SECONDS,
|
26 |
);
|
27 |
+
$schedules[ 'itsec-' . self::S_MONTHLY ] = array(
|
28 |
'display' => esc_html__( 'Monthly', 'better-wp-security' ),
|
29 |
'interval' => MONTH_IN_SECONDS,
|
30 |
);
|
66 |
$this->run_single_event_by_hash( $id, $this->hash_data( $data ) );
|
67 |
}
|
68 |
|
69 |
+
public function run_single_event_by_hash( $id, $hash ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
$opts = array( 'single' => true );
|
72 |
|
73 |
$storage = $this->get_options();
|
|
|
74 |
|
75 |
+
if ( ! isset( $storage['single'][ $id ][ $hash ] ) ) {
|
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 );
|
353 |
'id' => $id,
|
354 |
'data' => $options['single'][ $id ][ $hash ]['data'],
|
355 |
'fire_at' => $timestamp,
|
356 |
+
'hash' => $hash,
|
357 |
);
|
358 |
}
|
359 |
}
|
core/lib/class-itsec-scheduler-page-load.php
CHANGED
@@ -159,6 +159,7 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
|
|
159 |
'id' => $id,
|
160 |
'data' => $event['data'],
|
161 |
'fire_at' => $event['fire_at'],
|
|
|
162 |
);
|
163 |
}
|
164 |
}
|
@@ -265,6 +266,13 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
|
|
265 |
}
|
266 |
|
267 |
public function run_single_event( $id, $data = array() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
|
269 |
if ( $this->operating_data ) {
|
270 |
$clear_operating_data = false;
|
@@ -274,12 +282,19 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
|
|
274 |
$storage = $this->operating_data = $this->get_options();
|
275 |
}
|
276 |
|
277 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 ) {
|
159 |
'id' => $id,
|
160 |
'data' => $event['data'],
|
161 |
'fire_at' => $event['fire_at'],
|
162 |
+
'hash' => $hash,
|
163 |
);
|
164 |
}
|
165 |
}
|
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 |
$storage = $this->operating_data = $this->get_options();
|
283 |
}
|
284 |
|
285 |
+
if ( ! isset( $storage['single'][ $id ][ $hash ] ) ) {
|
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, $event['data'] );
|
298 |
$this->call_action( $job );
|
299 |
|
300 |
if ( $clear_operating_data ) {
|
core/lib/class-itsec-scheduler.php
CHANGED
@@ -2,6 +2,7 @@
|
|
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,6 +141,7 @@ abstract class ITSEC_Scheduler {
|
|
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,6 +170,16 @@ abstract class ITSEC_Scheduler {
|
|
168 |
*/
|
169 |
abstract public function run_single_event( $id, $data = array() );
|
170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
/**
|
172 |
* Run any events that are due now.
|
173 |
*
|
@@ -326,6 +338,8 @@ abstract class ITSEC_Scheduler {
|
|
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:
|
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 |
* - 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 |
*/
|
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 |
*/
|
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:
|
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" 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,9 +767,9 @@ class ITSEC_WP_List_Table {
|
|
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,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" 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,9 +800,9 @@ class ITSEC_WP_List_Table {
|
|
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,9 +1134,7 @@ 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 $this->bulk_actions( $which ); ?>
|
1139 |
-
</div>
|
1140 |
<?php endif;
|
1141 |
$this->extra_tablenav( $which );
|
1142 |
$this->pagination( $which );
|
757 |
}
|
758 |
|
759 |
if ( $disable_first ) {
|
760 |
+
$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">«</span>';
|
761 |
} else {
|
762 |
+
$page_links[] = sprintf( "<a class='first-page button' 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 button disabled" aria-hidden="true">‹</span>';
|
771 |
} else {
|
772 |
+
$page_links[] = sprintf( "<a class='prev-page button' 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 button disabled" aria-hidden="true">›</span>';
|
794 |
} else {
|
795 |
+
$page_links[] = sprintf( "<a class='next-page button' 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 button disabled" aria-hidden="true">»</span>';
|
804 |
} else {
|
805 |
+
$page_links[] = sprintf( "<a class='last-page button' 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"><?php $this->bulk_actions( $which ); ?></div>
|
|
|
|
|
1138 |
<?php endif;
|
1139 |
$this->extra_tablenav( $which );
|
1140 |
$this->pagination( $which );
|
core/lib/form.php
CHANGED
@@ -27,6 +27,9 @@ final class ITSEC_Form {
|
|
27 |
parse_str( $data['data']['--itsec-form-serialized-data'], $data );
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
|
31 |
$defaults = array(
|
32 |
'booleans' => false,
|
@@ -480,6 +483,24 @@ final class ITSEC_Form {
|
|
480 |
$this->add_select( $var, $options );
|
481 |
}
|
482 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
483 |
private function add_custom_input( $var, $options ) {
|
484 |
if ( empty( $options['type'] ) ) {
|
485 |
trigger_error( 'add_custom_input called without a type option set' );
|
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,
|
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' );
|
core/lib/validator.php
CHANGED
@@ -142,6 +142,19 @@ 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 |
} else if ( 'array' === $type ) {
|
146 |
if ( ! is_array( $this->settings[$var] ) ) {
|
147 |
if ( empty( $this->settings[$var] ) ) {
|
@@ -414,6 +427,37 @@ abstract class ITSEC_Validator {
|
|
414 |
$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 );
|
415 |
}
|
416 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
} else {
|
418 |
/* translators: 1: sanitize type, 2: input name */
|
419 |
$error = sprintf( __( 'An invalid sanitize type of "%1$s" was received for the %2$s input.', 'better-wp-security' ), $type, $name );
|
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] ) ) {
|
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 );
|
core/lockout.php
CHANGED
@@ -129,7 +129,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 |
}
|
129 |
|
130 |
$host = ITSEC_Lib::get_ip();
|
131 |
|
132 |
+
if ( $this->is_host_locked_out( $host ) || ITSEC_Lib::is_ip_blacklisted() ) {
|
133 |
$this->execute_lock();
|
134 |
}
|
135 |
}
|
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,19 +29,15 @@ 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 |
-
// 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 |
/**
|
10 |
|
11 |
add_filter( 'itsec_lockout_modules', array( $this, 'register_lockout' ) );
|
12 |
|
13 |
+
add_action( 'template_redirect', 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'], true ) ) {
|
33 |
+
return; // white listed page.
|
|
|
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'], true ) ) {
|
|
|
39 |
$itsec_lockout->do_lockout( 'four_oh_four' );
|
|
|
40 |
}
|
|
|
41 |
}
|
42 |
|
43 |
/**
|
core/modules/404-detection/logs.php
CHANGED
@@ -4,6 +4,7 @@ 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 |
}
|
8 |
|
9 |
public function filter_entry_for_list_display( $entry ) {
|
@@ -24,5 +25,9 @@ final class ITSEC_Four_Oh_Four_Logs {
|
|
24 |
|
25 |
return $details;
|
26 |
}
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
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 |
+
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 |
|
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();
|
core/modules/global/settings-page.php
CHANGED
@@ -73,6 +73,11 @@ final class ITSEC_Global_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
73 |
true => __( 'Yes' ),
|
74 |
);
|
75 |
|
|
|
|
|
|
|
|
|
|
|
76 |
?>
|
77 |
<table class="form-table itsec-settings-section">
|
78 |
<tr>
|
@@ -242,6 +247,15 @@ final class ITSEC_Global_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
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 |
|
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 |
<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 |
|
core/modules/global/settings.php
CHANGED
@@ -35,6 +35,7 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
|
|
35 |
'cron_status' => - 1,
|
36 |
'use_cron' => true,
|
37 |
'cron_test_time' => 0,
|
|
|
38 |
);
|
39 |
}
|
40 |
|
@@ -47,6 +48,17 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
|
|
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 ) {
|
35 |
'cron_status' => - 1,
|
36 |
'use_cron' => true,
|
37 |
'cron_test_time' => 0,
|
38 |
+
'enable_grade_report' => false,
|
39 |
);
|
40 |
}
|
41 |
|
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 ) {
|
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,6 +31,7 @@ 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 |
|
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' ) );
|
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', 'enable_grade_report' ) );
|
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 |
+
$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' ) );
|
core/modules/notification-center/class-notification-center.php
CHANGED
@@ -71,6 +71,14 @@ final class ITSEC_Notification_Center {
|
|
71 |
public function get_notifications() {
|
72 |
|
73 |
if ( null === $this->notifications ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
/**
|
75 |
* Filter the registered notifications.
|
76 |
*
|
@@ -163,9 +171,10 @@ final class ITSEC_Notification_Center {
|
|
163 |
|
164 |
$schedules = self::get_schedule_order();
|
165 |
$schedule = array(
|
166 |
-
'min'
|
167 |
-
'max'
|
168 |
-
'default'
|
|
|
169 |
);
|
170 |
|
171 |
if ( $args['schedule'] === self::S_CONFIGURABLE ) {
|
@@ -317,27 +326,39 @@ final class ITSEC_Notification_Center {
|
|
317 |
}
|
318 |
|
319 |
$settings = $this->get_notification_settings( $notification );
|
320 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
|
322 |
$addresses = array();
|
323 |
|
|
|
|
|
|
|
324 |
foreach ( $contacts as $contact ) {
|
325 |
if ( (string) $contact === (string) intval( $contact ) ) {
|
326 |
-
$users =
|
327 |
} else {
|
328 |
-
list(
|
329 |
|
330 |
if ( empty( $role ) ) {
|
331 |
continue;
|
332 |
}
|
333 |
|
334 |
-
$
|
335 |
}
|
|
|
336 |
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
|
|
|
|
341 |
}
|
342 |
}
|
343 |
|
@@ -361,6 +382,18 @@ final class ITSEC_Notification_Center {
|
|
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,7 +419,7 @@ final class ITSEC_Notification_Center {
|
|
386 |
$notification_data[] = $data;
|
387 |
|
388 |
if ( $enforce_unique ) {
|
389 |
-
$notification_data =
|
390 |
}
|
391 |
|
392 |
$all_data[ $notification ] = $notification_data;
|
@@ -445,6 +478,11 @@ final class ITSEC_Notification_Center {
|
|
445 |
|
446 |
add_action( 'wp_mail_failed', array( $this, 'capture_mail_fail' ) );
|
447 |
|
|
|
|
|
|
|
|
|
|
|
448 |
$this->_sending_notification = $notification;
|
449 |
$result = $mail->send();
|
450 |
$this->_sending_notification = '';
|
@@ -460,9 +498,7 @@ final class ITSEC_Notification_Center {
|
|
460 |
* @param string $error_id
|
461 |
*/
|
462 |
public function dismiss_mail_error( $error_id ) {
|
463 |
-
|
464 |
-
unset( $errors[ $error_id ] );
|
465 |
-
ITSEC_Modules::set_setting( 'notification-center', 'mail_errors', $errors );
|
466 |
}
|
467 |
|
468 |
/**
|
@@ -471,7 +507,10 @@ final class ITSEC_Notification_Center {
|
|
471 |
* @return array
|
472 |
*/
|
473 |
public function get_mail_errors() {
|
474 |
-
|
|
|
|
|
|
|
475 |
}
|
476 |
|
477 |
/**
|
@@ -490,15 +529,9 @@ final class ITSEC_Notification_Center {
|
|
490 |
*/
|
491 |
public function capture_mail_fail( $error ) {
|
492 |
|
493 |
-
|
494 |
|
495 |
-
|
496 |
-
'error' => array( 'message' => $error->get_error_message(), 'code' => $error->get_error_code() ),
|
497 |
-
'time' => ITSEC_Core::get_current_time_gmt(),
|
498 |
-
'notification' => $this->_sending_notification,
|
499 |
-
);
|
500 |
-
|
501 |
-
ITSEC_Modules::set_setting( 'notification-center', 'mail_errors', $errors );
|
502 |
|
503 |
if ( ITSEC_Core::is_interactive() ) {
|
504 |
ITSEC_Response::reload_module( 'notification-center' );
|
@@ -660,6 +693,13 @@ final class ITSEC_Notification_Center {
|
|
660 |
*/
|
661 |
public function send_scheduled_notifications( $notification_slugs, $silent = false ) {
|
662 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
663 |
@set_time_limit( 120 );
|
664 |
$sent = array();
|
665 |
|
@@ -881,6 +921,10 @@ final class ITSEC_Notification_Center {
|
|
881 |
return false; // This is an on-demand
|
882 |
}
|
883 |
|
|
|
|
|
|
|
|
|
884 |
switch ( $schedule ) {
|
885 |
case self::S_DAILY:
|
886 |
$period = DAY_IN_SECONDS;
|
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 |
|
172 |
$schedules = self::get_schedule_order();
|
173 |
$schedule = array(
|
174 |
+
'min' => $schedules[0],
|
175 |
+
'max' => $schedules[ count( $schedules ) - 1 ],
|
176 |
+
'default' => self::S_DAILY,
|
177 |
+
'setting_only' => false,
|
178 |
);
|
179 |
|
180 |
if ( $args['schedule'] === self::S_CONFIGURABLE ) {
|
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[] = get_userdata( $contact );
|
345 |
} else {
|
346 |
+
list( , $role ) = explode( ':', $contact, 2 );
|
347 |
|
348 |
if ( empty( $role ) ) {
|
349 |
continue;
|
350 |
}
|
351 |
|
352 |
+
$roles[] = $role;
|
353 |
}
|
354 |
+
}
|
355 |
|
356 |
+
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
357 |
+
$users = array_merge( $users, ITSEC_Lib_Canonical_Roles::get_users_with_canonical_role( $roles ) );
|
358 |
+
|
359 |
+
foreach ( $users as $user ) {
|
360 |
+
if ( is_object( $user ) && ! empty( $user->user_email ) ) {
|
361 |
+
$addresses[] = $user->user_email;
|
362 |
}
|
363 |
}
|
364 |
|
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 |
$notification_data[] = $data;
|
420 |
|
421 |
if ( $enforce_unique ) {
|
422 |
+
$notification_data = ITSEC_Lib::non_scalar_array_unique( $notification_data );
|
423 |
}
|
424 |
|
425 |
$all_data[ $notification ] = $notification_data;
|
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 |
* @param string $error_id
|
499 |
*/
|
500 |
public function dismiss_mail_error( $error_id ) {
|
501 |
+
_deprecated_function( __METHOD__, '4.7.1' );
|
|
|
|
|
502 |
}
|
503 |
|
504 |
/**
|
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 |
*/
|
530 |
public function capture_mail_fail( $error ) {
|
531 |
|
532 |
+
ITSEC_Log::add_error( 'notification_center', "send_failed::{$this->_sending_notification}", compact( 'error' ) );
|
533 |
|
534 |
+
ITSEC_Modules::set_setting( 'notification-center', 'last_mail_error', $error->get_error_message() );
|
|
|
|
|
|
|
|
|
|
|
|
|
535 |
|
536 |
if ( ITSEC_Core::is_interactive() ) {
|
537 |
ITSEC_Response::reload_module( '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 |
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;
|
core/modules/notification-center/debug.php
CHANGED
@@ -68,10 +68,10 @@ class ITSEC_Notification_Center_Debug {
|
|
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 ? date( 'Y-m-d H:i:s', $
|
72 |
<td><?php echo $nc->get_schedule( $slug ); ?></td>
|
73 |
<td>
|
74 |
-
<?php if ( $scheduled ): ?>
|
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>
|
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>
|
core/modules/notification-center/js/settings-page.js
CHANGED
@@ -5,10 +5,8 @@ jQuery( function ( $ ) {
|
|
5 |
} );
|
6 |
|
7 |
$( document ).on( 'itsec-dismiss-notice', '.itsec-notification-center-mail-errors-container .notice.itsec-is-dismissible', function () {
|
8 |
-
|
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,6 +33,10 @@ jQuery( function ( $ ) {
|
|
35 |
}
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
38 |
itsecSettingsPage.events.on( 'modulesReloaded', initializeHiding );
|
39 |
itsecSettingsPage.events.on( 'moduleReloaded', function ( _, module ) {
|
40 |
if ( 'notification-center' === module ) {
|
5 |
} );
|
6 |
|
7 |
$( document ).on( 'itsec-dismiss-notice', '.itsec-notification-center-mail-errors-container .notice.itsec-is-dismissible', function () {
|
8 |
+
itsecUtil.sendModuleAJAXRequest( 'notification-center', { method: 'dismiss-mail-error' }, function ( r ) {
|
9 |
+
if ( r.success ) {
|
|
|
|
|
10 |
jQuery( '#itsec-module-card-notification-center' ).removeClass( 'itsec-module-status--warning' );
|
11 |
}
|
12 |
} )
|
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 ) {
|
core/modules/notification-center/logs.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,15 +39,8 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
39 |
|
40 |
switch ( $data['method'] ) {
|
41 |
case 'dismiss-mail-error':
|
42 |
-
|
43 |
-
|
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,10 +65,31 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
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,30 +103,20 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
89 |
}
|
90 |
|
91 |
protected function render_mail_errors() {
|
92 |
-
$
|
93 |
-
|
94 |
-
if ( ! $errors ) {
|
95 |
return;
|
96 |
}
|
97 |
|
|
|
98 |
?>
|
99 |
<div class="itsec-notification-center-mail-errors-container">
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
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,6 +249,34 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
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,59 +284,55 @@ class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page
|
|
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 ( $
|
277 |
<li>
|
278 |
<label>
|
279 |
-
<?php $form->add_multi_checkbox( '
|
280 |
-
<?php echo esc_html( $
|
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 |
|
2 |
|
3 |
class ITSEC_Notification_Center_Settings_Page extends ITSEC_Module_Settings_Page {
|
4 |
|
5 |
+
private $version = 3;
|
6 |
|
7 |
/** @var ITSEC_Notification_Center_Validator */
|
8 |
private $validator;
|
19 |
|
20 |
$this->validator = ITSEC_Modules::get_validator( 'notification-center' );
|
21 |
|
22 |
+
if ( ITSEC_Modules::get_setting( 'notification-center', 'last_mail_error' ) ) {
|
23 |
$this->status = 'warning';
|
24 |
}
|
25 |
|
39 |
|
40 |
switch ( $data['method'] ) {
|
41 |
case 'dismiss-mail-error':
|
42 |
+
ITSEC_Modules::set_setting( 'notification-center', 'last_mail_error', '' );
|
43 |
+
ITSEC_Response::set_success( true );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
break;
|
45 |
}
|
46 |
}
|
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 |
}
|
104 |
|
105 |
protected function render_mail_errors() {
|
106 |
+
if ( ! $message = ITSEC_Modules::get_setting( 'notification-center', 'last_mail_error' ) ) {
|
|
|
|
|
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 |
+
<div class="notice notice-alt notice-error below-h2 itsec-is-dismissible itsec-notification-center-mail-error">
|
114 |
+
<?php if ( 'file' !== ITSEC_Modules::get_setting( 'global', 'log_type' ) ): ?>
|
115 |
+
<p><?php printf( esc_html__( 'Error while sending notification: %1$s. %2$sView All%3$s.', 'better-wp-security' ), $message, "<a href=\"{$link}\">", '</a>' ); ?></p>
|
116 |
+
<?php else: ?>
|
117 |
+
<p><?php printf( esc_html__( 'Error while sending notification: %1$s.', 'better-wp-security' ), $message ); ?></p>
|
118 |
+
<?php endif; ?>
|
119 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
</div>
|
121 |
<?php
|
122 |
}
|
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 |
$roles = $users_and_roles['roles'];
|
285 |
|
286 |
natcasesort( $users );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
+
?>
|
289 |
+
<fieldset>
|
290 |
+
<legend class="screen-reader-text"><?php esc_html_e( 'Recipients for this email.', 'better-wp-security' ); ?></legend>
|
291 |
+
<p><?php esc_html_e( 'Select which users should be emailed.', 'better-wp-security' ); ?></p>
|
292 |
+
|
293 |
+
<ul>
|
294 |
+
<?php foreach ( $roles as $role => $name ) : ?>
|
295 |
+
<li>
|
296 |
+
<label>
|
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 ( $form->get_option( 'previous_emails' ) as $email ): ?>
|
324 |
<li>
|
325 |
<label>
|
326 |
+
<?php $form->add_multi_checkbox( 'previous_emails', $email ); ?>
|
327 |
+
<?php echo esc_html( $email ); ?>
|
328 |
</label>
|
329 |
</li>
|
330 |
<?php endforeach; ?>
|
331 |
</ul>
|
332 |
+
</div>
|
333 |
+
<?php endif; ?>
|
334 |
+
</fieldset>
|
335 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
<?php
|
337 |
}
|
338 |
|
core/modules/notification-center/settings.php
CHANGED
@@ -18,16 +18,24 @@ 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 |
);
|
28 |
}
|
29 |
|
30 |
public function load() {
|
|
|
|
|
|
|
|
|
31 |
$this->settings = ITSEC_Storage::get( $this->get_id() );
|
32 |
$defaults = $this->get_defaults();
|
33 |
|
@@ -48,6 +56,8 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
48 |
|
49 |
$this->settings['notifications'][ $slug ] = $value;
|
50 |
}
|
|
|
|
|
51 |
}
|
52 |
|
53 |
public function refresh_notification_settings( $save = true ) {
|
@@ -63,39 +73,78 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
63 |
}
|
64 |
}
|
65 |
|
66 |
-
public function continue_upgrade() {
|
|
|
67 |
$nc = ITSEC_Core::get_notification_center();
|
68 |
|
69 |
-
$
|
70 |
-
|
|
|
71 |
|
72 |
-
|
73 |
-
|
74 |
|
75 |
-
|
76 |
-
|
77 |
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
82 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
}
|
84 |
|
85 |
-
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
}
|
93 |
|
94 |
-
$
|
95 |
}
|
96 |
-
}
|
97 |
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
}
|
100 |
|
101 |
/**
|
@@ -129,12 +178,13 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
129 |
}
|
130 |
|
131 |
if ( ITSEC_Notification_Center::R_USER_LIST === $notification['recipient'] ) {
|
132 |
-
$defaults['user_list']
|
|
|
133 |
}
|
134 |
|
135 |
if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $notification['recipient'] ) {
|
136 |
-
$defaults['user_list']
|
137 |
-
$defaults['
|
138 |
}
|
139 |
|
140 |
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 |
+
'last_mail_error' => '',
|
25 |
+
'notifications' => array(),
|
26 |
+
'admin_emails' => array(),
|
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 |
|
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 |
}
|
74 |
}
|
75 |
|
76 |
+
public function continue_upgrade( $old_version ) {
|
77 |
+
|
78 |
$nc = ITSEC_Core::get_notification_center();
|
79 |
|
80 |
+
if ( $old_version < 4076 ) {
|
81 |
+
$nc->clear_notifications_cache();
|
82 |
+
$this->refresh_notification_settings( false );
|
83 |
|
84 |
+
$admin_users = array();
|
85 |
+
$admin_emails = array();
|
86 |
|
87 |
+
foreach ( $this->settings['admin_emails'] as $admin_email ) {
|
88 |
+
$user = get_user_by( 'email', $admin_email );
|
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 |
+
foreach ( $nc->get_notifications() as $slug => $notification ) {
|
98 |
+
|
99 |
+
if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $notification['recipient'] ) {
|
100 |
+
if ( $admin_users ) {
|
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 |
+
if ( $old_version < 4101 ) {
|
114 |
|
115 |
+
$settings = $this->get_all();
|
116 |
+
$user_lists = array();
|
117 |
+
|
118 |
+
foreach ( $settings['notifications'] as $slug => $setting ) {
|
119 |
+
if ( ! $config = $nc->get_notification( $slug ) ) {
|
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 |
+
$user_lists[ $slug ] = $setting['user_list'];
|
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 |
}
|
179 |
|
180 |
if ( ITSEC_Notification_Center::R_USER_LIST === $notification['recipient'] ) {
|
181 |
+
$defaults['user_list'] = array( 'role:administrator' );
|
182 |
+
$defaults['recipient_type'] = 'default';
|
183 |
}
|
184 |
|
185 |
if ( ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE === $notification['recipient'] ) {
|
186 |
+
$defaults['user_list'] = array( 'role:administrator' );
|
187 |
+
$defaults['recipient_type'] = 'default';
|
188 |
}
|
189 |
|
190 |
if ( ITSEC_Notification_Center::R_EMAIL_LIST === $notification['recipient'] ) {
|
core/modules/notification-center/setup.php
CHANGED
@@ -2,9 +2,11 @@
|
|
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,6 +73,7 @@ class ITSEC_Notification_Center_Setup {
|
|
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,10 +116,24 @@ class ITSEC_Notification_Center_Setup {
|
|
113 |
ITSEC_Modules::set_settings( 'notification-center', $settings );
|
114 |
}
|
115 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
}
|
117 |
|
118 |
public function fire_continue_upgrade() {
|
119 |
-
|
|
|
120 |
}
|
121 |
}
|
122 |
|
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' ), -100 );
|
10 |
}
|
11 |
|
12 |
/**
|
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 |
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 |
+
ITSEC_Modules::load_module_file( 'settings.php', 'notification-center' );
|
136 |
+
do_action( 'itsec_notification_center_continue_upgrade', $this->old_version );
|
137 |
}
|
138 |
}
|
139 |
|
core/modules/notification-center/validator.php
CHANGED
@@ -13,11 +13,51 @@ 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 |
if ( ! $this->sanitize_setting( 'array', 'notifications', esc_html__( 'Notifications', 'better-wp-security' ) ) ) {
|
@@ -36,7 +76,7 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
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,6 +111,19 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
71 |
$this->set_can_save( false );
|
72 |
}
|
73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
}
|
75 |
|
76 |
if ( ITSEC_Notification_Center::R_EMAIL_LIST !== $config['recipient'] ) {
|
@@ -241,8 +294,10 @@ class ITSEC_Notification_Center_Validator extends ITSEC_Validator {
|
|
241 |
$available_roles = array();
|
242 |
$available_users = array();
|
243 |
|
|
|
|
|
244 |
foreach ( $roles->roles as $role => $details ) {
|
245 |
-
if (
|
246 |
$available_roles["role:$role"] = translate_user_role( $details['name'] );
|
247 |
|
248 |
$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', 'admin_emails', 'last_mail_error' );
|
17 |
$this->set_previous_if_empty( array( 'last_sent', 'data', 'resend_at', 'admin_emails' ) );
|
18 |
|
19 |
+
if ( ! isset( $this->settings['last_mail_error'] ) ) {
|
20 |
+
$this->settings['last_mail_error'] = $this->previous_settings['last_mail_error'];
|
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 |
$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'], $settings['recipient_type'] );
|
80 |
} else {
|
81 |
if ( ! is_array( $settings['user_list'] ) ) {
|
82 |
$settings['user_list'] = array();
|
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 |
$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 ( 'administrator' === ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $role ) ) {
|
301 |
$available_roles["role:$role"] = translate_user_role( $details['name'] );
|
302 |
|
303 |
$users = get_users( array( 'role' => $role ) );
|
core/modules/security-check/scanner.php
CHANGED
@@ -48,7 +48,27 @@ 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 |
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' ) );
|
@@ -59,6 +79,7 @@ final class ITSEC_Security_Check_Scanner {
|
|
59 |
self::enforce_password_requirement_enabled( 'strength', __( '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' ) );
|
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 |
+
if ( $backup = ITSEC_Lib::get_backup_plugin() ) {
|
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' ) );
|
79 |
self::enforce_password_requirement_enabled( 'strength', __( 'Strong Password Enforcement', 'better-wp-security' ) );
|
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' ) );
|
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'] && 'cli' !== php_sapi_name() && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
|
73 |
$this->redirect_to_https();
|
74 |
}
|
75 |
}
|
87 |
*/
|
88 |
public function do_conditional_ssl_redirect() {
|
89 |
|
90 |
+
if ( 'cli' === php_sapi_name() ) {
|
91 |
return;
|
92 |
}
|
93 |
|
core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php
CHANGED
@@ -128,6 +128,68 @@ final class ITSEC_WordPress_Tweaks {
|
|
128 |
}
|
129 |
}
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
/**
|
132 |
* Add filter for gettext to change text for the valid_user_login_type setting changes.
|
133 |
*
|
@@ -203,24 +265,44 @@ final class ITSEC_WordPress_Tweaks {
|
|
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
|
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,7 +314,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
232 |
return $result;
|
233 |
}
|
234 |
|
235 |
-
return
|
236 |
}
|
237 |
|
238 |
|
@@ -259,7 +341,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
259 |
if ( current_user_can( $taxonomy->cap->edit_terms ) ) {
|
260 |
return $result;
|
261 |
} else {
|
262 |
-
return
|
263 |
}
|
264 |
}
|
265 |
}
|
@@ -281,7 +363,7 @@ final class ITSEC_WordPress_Tweaks {
|
|
281 |
if ( current_user_can( $post_type->cap->edit_posts ) ) {
|
282 |
return $result;
|
283 |
} else {
|
284 |
-
return
|
285 |
}
|
286 |
}
|
287 |
}
|
@@ -294,6 +376,74 @@ final class ITSEC_WordPress_Tweaks {
|
|
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 );
|
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 |
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 $error;
|
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 |
return $result;
|
315 |
}
|
316 |
|
317 |
+
return $error;
|
318 |
}
|
319 |
|
320 |
|
341 |
if ( current_user_can( $taxonomy->cap->edit_terms ) ) {
|
342 |
return $result;
|
343 |
} else {
|
344 |
+
return $error;
|
345 |
}
|
346 |
}
|
347 |
}
|
363 |
if ( current_user_can( $post_type->cap->edit_posts ) ) {
|
364 |
return $result;
|
365 |
} else {
|
366 |
+
return $error;
|
367 |
}
|
368 |
}
|
369 |
}
|
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 );
|
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,6 +199,10 @@ final class ITSEC_Response {
|
|
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,16 +283,26 @@ final class ITSEC_Response {
|
|
279 |
$added = array_diff( $new, $current );
|
280 |
|
281 |
if ( $added ) {
|
282 |
-
self::
|
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 |
|
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 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 |
$added = array_diff( $new, $current );
|
284 |
|
285 |
if ( $added ) {
|
286 |
+
self::flag_new_notifications_available();
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
core/setup.php
CHANGED
@@ -9,7 +9,6 @@
|
|
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,13 +142,11 @@ final class ITSEC_Setup {
|
|
143 |
ITSEC_Lib::schedule_cron_test();
|
144 |
}
|
145 |
|
146 |
-
if (
|
147 |
-
|
148 |
}
|
149 |
|
150 |
-
|
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,6 +199,7 @@ final class ITSEC_Setup {
|
|
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() );
|
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 |
ITSEC_Lib::schedule_cron_test();
|
143 |
}
|
144 |
|
145 |
+
if ( null === get_site_option( 'itsec-enable-grade-report', null ) ) {
|
146 |
+
update_site_option( 'itsec-enable-grade-report', ITSEC_Modules::get_setting( 'global', 'enable_grade_report' ) );
|
147 |
}
|
148 |
|
149 |
+
ITSEC_Core::get_scheduler()->register_events();
|
|
|
|
|
150 |
|
151 |
// Update stored build number.
|
152 |
ITSEC_Modules::set_setting( 'global', 'build', ITSEC_Core::get_plugin_build() );
|
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() );
|
history.txt
CHANGED
@@ -788,4 +788,18 @@
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
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.0
|
7 |
Requires PHP: 5.2
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -189,6 +189,21 @@ Free support may be available with the help of the community in the <a href="htt
|
|
189 |
|
190 |
== Changelog ==
|
191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
= 7.0.4 =
|
193 |
* Enhancement: Add mitigation for the WordPress Attachment File Traversal and Deletion vulnerability.
|
194 |
* Tweak: Fire a WordPress action whenever settings are updated.
|
@@ -481,5 +496,5 @@ Free support may be available with the help of the community in the <a href="htt
|
|
481 |
|
482 |
== Upgrade Notice ==
|
483 |
|
484 |
-
= 7.0
|
485 |
-
Version 7.0
|
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.8
|
6 |
+
Stable tag: 7.1.0
|
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.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.
|
496 |
|
497 |
== Upgrade Notice ==
|
498 |
|
499 |
+
= 7.1.0 =
|
500 |
+
Version 7.1.0 contains important bug fixes and improvements. It is recommended for all users.
|