iThemes Security (formerly Better WP Security) - Version 8.0.1

Version Description

  • Bug Fix: Sites that did not support HTTPS, but had the SSL module active, but not configured, on upgrade would get redirected to the HTTPS version of the site.
  • Bug Fix: Unregister the iThemes Security Two-Factor module when the Two-Factor Feature Plugin is enabled.
  • Bug Fix: Allow activation on WordPress 5.7.0.
  • Bug Fix: Add missing textdomains.
Download this release

Release Info

Developer TimothyBlynJacobs
Plugin Icon 128x128 iThemes Security (formerly Better WP Security)
Version 8.0.1
Comparing to
See all releases

Code changes from version 8.0.0 to 8.0.1

Files changed (42) hide show
  1. better-wp-security.php +3 -3
  2. core/admin-pages/init.php +1 -1
  3. core/admin-pages/logs-list-table.php +2 -2
  4. core/admin-pages/page-logs.php +4 -4
  5. core/core.php +17 -3
  6. core/lib.php +1 -1
  7. core/lib/Legacy_Password_Requirement.php +1 -1
  8. core/lib/class-itsec-lib-feature-flags.php +5 -5
  9. core/lib/class-itsec-lib-jwt.php +19 -19
  10. core/lib/class-itsec-lib-login-interstitial.php +1 -1
  11. core/lib/class-itsec-lib-rest.php +1 -1
  12. core/lib/class-itsec-wp-list-table.php +27 -27
  13. core/lib/includes/function.login-header.php +2 -2
  14. core/lib/rest/Modules_Controller.php +19 -19
  15. core/modules.php +5 -1
  16. core/modules/backup/privacy.php +1 -1
  17. core/modules/ban-users/REST.php +1 -1
  18. core/modules/brute-force/logs.php +1 -1
  19. core/modules/dashboard/cards/class-itsec-dashboard-card-banned-users.php +1 -1
  20. core/modules/dashboard/class-itsec-dashboard-rest.php +2 -2
  21. core/modules/global/privacy.php +2 -2
  22. core/modules/hide-backend/privacy.php +1 -1
  23. core/modules/network-brute-force/logs.php +1 -1
  24. core/modules/network-brute-force/privacy.php +1 -1
  25. core/modules/password-requirements/class-itsec-password-requirements.php +2 -2
  26. core/modules/privacy/util.php +17 -17
  27. core/modules/site-scanner/api.php +1 -1
  28. core/modules/site-scanner/privacy.php +1 -1
  29. core/modules/ssl/activate.php +0 -1
  30. core/modules/ssl/active.php +2 -1
  31. core/modules/ssl/class-itsec-ssl.php +10 -12
  32. core/modules/ssl/deactivate.php +1 -2
  33. core/modules/two-factor/class-itsec-two-factor-helper.php +0 -2
  34. core/modules/two-factor/class-itsec-two-factor-on-board.php +3 -3
  35. core/modules/two-factor/class-itsec-two-factor.php +2 -2
  36. core/modules/two-factor/privacy.php +1 -1
  37. core/modules/two-factor/providers/class.two-factor-backup-codes.php +3 -3
  38. core/modules/user-groups/REST/User_Groups.php +1 -1
  39. core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php +1 -1
  40. core/notify.php +2 -2
  41. history.txt +5 -0
  42. readme.txt +8 -2
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: 8.0.0
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
@@ -24,9 +24,9 @@ if ( version_compare( phpversion(), '7.0.0', '<' ) ) {
24
  return;
25
  }
26
 
27
- if ( version_compare( $GLOBALS['wp_version'], '5.7.0', '<' ) ) {
28
  function itsec_minimum_wp_version_notice() {
29
- echo '<div class="notice notice-error"><p>' . esc_html__( 'iThemes Security Pro requires WordPress 5.7 or later.', 'better-wp-security' ) . '</p></div>';
30
  }
31
 
32
  add_action( 'admin_notices', 'itsec_minimum_wp_version_notice' );
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: 8.0.1
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
24
  return;
25
  }
26
 
27
+ if ( version_compare( $GLOBALS['wp_version'], '5.7', '<' ) ) {
28
  function itsec_minimum_wp_version_notice() {
29
+ echo '<div class="notice notice-error"><p>' . esc_html__( 'iThemes Security requires WordPress 5.7 or later.', 'better-wp-security' ) . '</p></div>';
30
  }
31
 
32
  add_action( 'admin_notices', 'itsec_minimum_wp_version_notice' );
core/admin-pages/init.php CHANGED
@@ -47,7 +47,7 @@ final class ITSEC_Admin_Page_Loader {
47
  }
48
 
49
  if ( defined( 'ITSEC_DEBUG' ) && ITSEC_DEBUG ) {
50
- $page_refs[] = add_submenu_page( $parent, __( 'iThemes Security Debug', 'better-wp-security' ), __( 'Debug' ), $capability, 'itsec-debug', array( $this, 'show_page' ) );
51
  }
52
 
53
  foreach ( $page_refs as $page_ref ) {
47
  }
48
 
49
  if ( defined( 'ITSEC_DEBUG' ) && ITSEC_DEBUG ) {
50
+ $page_refs[] = add_submenu_page( $parent, __( 'iThemes Security Debug', 'better-wp-security' ), __( 'Debug', 'better-wp-security' ), $capability, 'itsec-debug', array( $this, 'show_page' ) );
51
  }
52
 
53
  foreach ( $page_refs as $page_ref ) {
core/admin-pages/logs-list-table.php CHANGED
@@ -124,7 +124,7 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
124
  $out = '&nbsp;<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 ) ) . '">&nbsp;</a>';
125
 
126
  if ( 'module' === $column_name ) {
127
- $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
128
  }
129
 
130
  return $out;
@@ -433,7 +433,7 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
433
  <?php endforeach; ?>
434
  </select>
435
 
436
- <?php submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'itsec-logs-query-submit' ) ); ?>
437
 
438
  <?php if ( isset( $filters['type'] ) ): ?>
439
  <input type="hidden" name="filters[]" value="type|<?php echo esc_attr( $filters['type'] ); ?>">
124
  $out = '&nbsp;<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 ) ) . '">&nbsp;</a>';
125
 
126
  if ( 'module' === $column_name ) {
127
+ $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details', 'better-wp-security' ) . '</span></button>';
128
  }
129
 
130
  return $out;
433
  <?php endforeach; ?>
434
  </select>
435
 
436
+ <?php submit_button( __( 'Filter', 'better-wp-security' ), '', 'filter_action', false, array( 'id' => 'itsec-logs-query-submit' ) ); ?>
437
 
438
  <?php if ( isset( $filters['type'] ) ): ?>
439
  <input type="hidden" name="filters[]" value="type|<?php echo esc_attr( $filters['type'] ); ?>">
core/admin-pages/page-logs.php CHANGED
@@ -357,13 +357,13 @@ final class ITSEC_Logs_Page {
357
 
358
  ?>
359
  <fieldset class="screen-options">
360
- <legend><?php esc_html_e( 'Pagination' ); ?></legend>
361
- <label for="itsec_logs_page_entries_per_page"><?php esc_html_e( 'Number of items per page:' ); ?></label>
362
  <?php $form->add_number( 'per_page', array( 'step' => 1, 'min' => 1, 'max' => 999, 'maxlength' => 3 ) ); ?>
363
  </fieldset>
364
 
365
  <fieldset>
366
- <legend><?php esc_html_e( 'View Mode' ); ?></legend>
367
 
368
  <label for="itsec-default_view-important">
369
  <?php $form->add_radio( 'default_view', 'important' ); ?>
@@ -401,7 +401,7 @@ final class ITSEC_Logs_Page {
401
  </fieldset>
402
 
403
  <p class="submit">
404
- <?php $form->add_submit( 'apply', __( 'Apply' ) ); ?>
405
  </p>
406
 
407
  <p class="submit">
357
 
358
  ?>
359
  <fieldset class="screen-options">
360
+ <legend><?php esc_html_e( 'Pagination', 'better-wp-security' ); ?></legend>
361
+ <label for="itsec_logs_page_entries_per_page"><?php esc_html_e( 'Number of items per page:', 'better-wp-security' ); ?></label>
362
  <?php $form->add_number( 'per_page', array( 'step' => 1, 'min' => 1, 'max' => 999, 'maxlength' => 3 ) ); ?>
363
  </fieldset>
364
 
365
  <fieldset>
366
+ <legend><?php esc_html_e( 'View Mode', 'better-wp-security' ); ?></legend>
367
 
368
  <label for="itsec-default_view-important">
369
  <?php $form->add_radio( 'default_view', 'important' ); ?>
401
  </fieldset>
402
 
403
  <p class="submit">
404
+ <?php $form->add_submit( 'apply', __( 'Apply', 'better-wp-security' ) ); ?>
405
  </p>
406
 
407
  <p class="submit">
core/core.php CHANGED
@@ -147,6 +147,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
147
  $itsec_lockout = new ITSEC_Lockout();
148
 
149
  // Handle upgrade if needed.
 
150
  add_action( 'plugins_loaded', array( $this, 'handle_upgrade' ), - 100, 0 );
151
  add_action( 'plugins_loaded', array( $this, 'continue_init' ), - 90 );
152
 
@@ -551,6 +552,18 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
551
  return $meta;
552
  }
553
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  /**
555
  * Dispatch a request to upgrade the data schema to another version.
556
  *
@@ -574,6 +587,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
574
 
575
  public static function handle_activation() {
576
  self::load_setup();
 
577
  self::get_instance()->setup_error = ITSEC_Setup::handle_activation();
578
  }
579
 
@@ -865,9 +879,9 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
865
  /**
866
  * Gets the URL for the Security Check page.
867
  *
 
868
  * @deprecated 7.0.0
869
  *
870
- * @return string
871
  */
872
  public static function get_security_check_page_url() {
873
  _deprecated_function( __METHOD__, '7.0.0' );
@@ -899,8 +913,8 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
899
  /**
900
  * Runs a callback with the given interactivity settings.
901
  *
902
- * @param bool $interactive Whether to process the callback in interactive mode.
903
- * @param callable $callback The callback to execute.
904
  *
905
  * @return mixed The return value from callback.
906
  */
147
  $itsec_lockout = new ITSEC_Lockout();
148
 
149
  // Handle upgrade if needed.
150
+ add_action( 'plugins_loaded', array( $this, 'compat_checks' ), - 150 );
151
  add_action( 'plugins_loaded', array( $this, 'handle_upgrade' ), - 100, 0 );
152
  add_action( 'plugins_loaded', array( $this, 'continue_init' ), - 90 );
153
 
552
  return $meta;
553
  }
554
 
555
+ /**
556
+ * Checks for compatibility with existing plugins,
557
+ * and disables the respective ITSEC modules if needed.
558
+ */
559
+ public function compat_checks() {
560
+ // The Two-Factor feature plugin and ITSEC Two-Factor cannot be used at the same time.
561
+ if ( defined( 'TWO_FACTOR_VERSION' ) ) {
562
+ ITSEC_Modules::deregister_module( 'two-factor' );
563
+ ITSEC_Modules::deregister_module( 'pro-two-factor' );
564
+ }
565
+ }
566
+
567
  /**
568
  * Dispatch a request to upgrade the data schema to another version.
569
  *
587
 
588
  public static function handle_activation() {
589
  self::load_setup();
590
+ self::get_instance()->compat_checks();
591
  self::get_instance()->setup_error = ITSEC_Setup::handle_activation();
592
  }
593
 
879
  /**
880
  * Gets the URL for the Security Check page.
881
  *
882
+ * @return string
883
  * @deprecated 7.0.0
884
  *
 
885
  */
886
  public static function get_security_check_page_url() {
887
  _deprecated_function( __METHOD__, '7.0.0' );
913
  /**
914
  * Runs a callback with the given interactivity settings.
915
  *
916
+ * @param bool $interactive Whether to process the callback in interactive mode.
917
+ * @param callable $callback The callback to execute.
918
  *
919
  * @return mixed The return value from callback.
920
  */
core/lib.php CHANGED
@@ -1022,7 +1022,7 @@ final class ITSEC_Lib {
1022
  $diff = abs( $to - $from );
1023
 
1024
  if ( $diff < DAY_IN_SECONDS ) {
1025
- return sprintf( __( '%s ago' ), human_time_diff( $from, $to ) ); // Uses core translation
1026
  }
1027
 
1028
  $format = $format ?: get_option( 'date_format' );
1022
  $diff = abs( $to - $from );
1023
 
1024
  if ( $diff < DAY_IN_SECONDS ) {
1025
+ return sprintf( __( '%s ago', 'default' ), human_time_diff( $from, $to ) );
1026
  }
1027
 
1028
  $format = $format ?: get_option( 'date_format' );
core/lib/Legacy_Password_Requirement.php CHANGED
@@ -55,7 +55,7 @@ final class Legacy_Password_Requirement implements Password_Requirement, \ArrayA
55
 
56
  public function evaluate( string $password, $user ) {
57
  if ( ! $this->config['evaluate'] ) {
58
- return new \WP_Error( 'not_implemented', __( 'This password requirement does not evaluate passwords.' ) );
59
  }
60
 
61
  return call_user_func( $this->config['evaluate'], $password, $user );
55
 
56
  public function evaluate( string $password, $user ) {
57
  if ( ! $this->config['evaluate'] ) {
58
+ return new \WP_Error( 'not_implemented', __( 'This password requirement does not evaluate passwords.', 'better-wp-security' ) );
59
  }
60
 
61
  return call_user_func( $this->config['evaluate'], $password, $user );
core/lib/class-itsec-lib-feature-flags.php CHANGED
@@ -183,7 +183,7 @@ class ITSEC_Lib_Feature_Flags {
183
  */
184
  public static function get_reason( $flag ) {
185
  if ( ! $config = self::get_flag_config( $flag ) ) {
186
- return [ 'unknown', __( 'Unknown flag' ) ];
187
  }
188
 
189
  if ( ! self::is_available( $flag ) ) {
@@ -193,20 +193,20 @@ class ITSEC_Lib_Feature_Flags {
193
  }
194
 
195
  if ( defined( 'ITSEC_FF_' . $flag ) ) {
196
- return [ 'constant', __( 'Manually configured with a constant.' ) ];
197
  }
198
 
199
  if ( ! empty( $config['disabled'] ) ) {
200
- return [ 'remote', __( 'Remotely disabled by iThemes.' ) ];
201
  }
202
 
203
  $flags = ITSEC_Modules::get_setting( 'global', 'feature_flags' );
204
 
205
  if ( isset( $flags[ $flag ]['rate'] ) ) {
206
- return [ 'rollout', __( 'Gradually rolling out.' ) ];
207
  }
208
 
209
- return [ 'setting', __( 'Configured in the Feature Flags settings page.' ) ];
210
  }
211
 
212
  /**
183
  */
184
  public static function get_reason( $flag ) {
185
  if ( ! $config = self::get_flag_config( $flag ) ) {
186
+ return [ 'unknown', __( 'Unknown flag', 'better-wp-security' ) ];
187
  }
188
 
189
  if ( ! self::is_available( $flag ) ) {
193
  }
194
 
195
  if ( defined( 'ITSEC_FF_' . $flag ) ) {
196
+ return [ 'constant', __( 'Manually configured with a constant.', 'better-wp-security' ) ];
197
  }
198
 
199
  if ( ! empty( $config['disabled'] ) ) {
200
+ return [ 'remote', __( 'Remotely disabled by iThemes.', 'better-wp-security' ) ];
201
  }
202
 
203
  $flags = ITSEC_Modules::get_setting( 'global', 'feature_flags' );
204
 
205
  if ( isset( $flags[ $flag ]['rate'] ) ) {
206
+ return [ 'rollout', __( 'Gradually rolling out.', 'better-wp-security' ) ];
207
  }
208
 
209
+ return [ 'setting', __( 'Configured in the Feature Flags settings page.', 'better-wp-security' ) ];
210
  }
211
 
212
  /**
core/lib/class-itsec-lib-jwt.php CHANGED
@@ -60,11 +60,11 @@ final class ITSEC_Lib_JWT {
60
  $allow_unsecured = in_array( 'none', $allowed_algs, true );
61
 
62
  if ( $allow_unsecured && 'unsecure' !== $confirm_unsecure ) {
63
- return new \WP_Error( 'jwt_unsecure_not_confirmed', __( 'Did not confirm that "none" is an allowed algorithm.', 'oauth2' ) );
64
  }
65
 
66
  if ( empty( $key ) && ! $allow_unsecured ) {
67
- return new \WP_Error( 'jwt_empty_key', __( 'Key may not be empty', 'oauth2' ) );
68
  }
69
 
70
  $parsed = self::parse_jwt( $jwt );
@@ -76,27 +76,27 @@ final class ITSEC_Lib_JWT {
76
  list( $header, $payload, $sig, $headb64, $bodyb64 ) = $parsed;
77
 
78
  if ( empty( $header->alg ) ) {
79
- return new \WP_Error( 'jwt_invalid_format', __( 'Empty algorithm', 'oauth2' ) );
80
  }
81
 
82
  if ( 'none' !== $header->alg || ! $allow_unsecured ) {
83
  if ( empty( static::$supported_algs[ $header->alg ] ) ) {
84
- return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'oauth2' ) );
85
  }
86
 
87
  if ( ! in_array( $header->alg, $allowed_algs, true ) ) {
88
- return new \WP_Error( 'jwt_disallowed_algorithm', __( 'Algorithm not allowed', 'oauth2' ) );
89
  }
90
 
91
  if ( is_array( $key ) || $key instanceof \ArrayAccess ) {
92
  if ( isset( $header->kid ) ) {
93
  if ( ! isset( $key[ $header->kid ] ) ) {
94
- return new \WP_Error( 'jwt_invalid_key', __( '"kid" invalid, unable to lookup correct key', 'oauth2' ) );
95
  }
96
 
97
  $key = $key[ $header->kid ];
98
  } else {
99
- return new \WP_Error( 'jwt_invalid_key', __( '"kid" empty, unable to lookup correct key', 'oauth2' ) );
100
  }
101
  }
102
 
@@ -108,7 +108,7 @@ final class ITSEC_Lib_JWT {
108
  }
109
 
110
  if ( true !== $verified ) {
111
- return new \WP_Error( 'jwt_invalid_signature', __( 'Signature verification failed', 'oauth2' ) );
112
  }
113
  }
114
 
@@ -119,7 +119,7 @@ final class ITSEC_Lib_JWT {
119
  'jwt_before_valid',
120
  sprintf(
121
  /* translators: %s Date/Time the JWT is valid. */
122
- __( 'Cannot handle token prior to %s.', 'oauth2' ),
123
  wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $payload->nbf )
124
  ),
125
  array( 'nbf' => $payload->nbf )
@@ -134,7 +134,7 @@ final class ITSEC_Lib_JWT {
134
  'jwt_before_valid',
135
  sprintf(
136
  /* translators: %s Date/Time the JWT is valid. */
137
- __( 'Cannot handle token prior to %s.', 'oauth2' ),
138
  wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $payload->iat )
139
  ),
140
  array( 'iat' => $payload->iat )
@@ -143,7 +143,7 @@ final class ITSEC_Lib_JWT {
143
 
144
  // Check if this token has expired.
145
  if ( isset( $payload->exp ) && ( $timestamp - static::$leeway ) >= $payload->exp ) {
146
- return new \WP_Error( 'jwt_expired', __( 'Expired token', 'oauth2' ), array( 'exp' => $payload->exp ) );
147
  }
148
 
149
  return $payload;
@@ -160,21 +160,21 @@ final class ITSEC_Lib_JWT {
160
  $tks = explode( '.', $jwt );
161
 
162
  if ( 3 !== count( $tks ) ) {
163
- return new \WP_Error( 'jwt_invalid_format', __( 'Wrong number of segments', 'oauth2' ) );
164
  }
165
 
166
  list( $headb64, $bodyb64, $cryptob64 ) = $tks;
167
 
168
  if ( null === ( $header = static::json_decode( static::url_safe_b64_decode( $headb64 ) ) ) ) {
169
- return new \WP_Error( 'jwt_invalid_format', __( 'Invalid header encoding', 'oauth2' ) );
170
  }
171
 
172
  if ( null === $payload = static::json_decode( static::url_safe_b64_decode( $bodyb64 ) ) ) {
173
- return new \WP_Error( 'jwt_invalid_format', __( 'Invalid claims encoding', 'oauth2' ) );
174
  }
175
 
176
  if ( false === ( $sig = static::url_safe_b64_decode( $cryptob64 ) ) ) {
177
- return new \WP_Error( 'jwt_invalid_format', __( 'Invalid signature encoding', 'oauth2' ) );
178
  }
179
 
180
  return array( $header, $payload, $sig, $headb64, $bodyb64, $cryptob64 );
@@ -245,7 +245,7 @@ final class ITSEC_Lib_JWT {
245
  */
246
  protected static function sign( $msg, $key, $alg = 'HS256' ) {
247
  if ( empty( static::$supported_algs[ $alg ] ) ) {
248
- return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'oauth2' ) );
249
  }
250
 
251
  list( $function, $algorithm ) = static::$supported_algs[ $alg ];
@@ -258,13 +258,13 @@ final class ITSEC_Lib_JWT {
258
  $success = openssl_sign( $msg, $signature, $key, $algorithm );
259
 
260
  if ( ! $success ) {
261
- return new \WP_Error( 'jwt_openssl_error', __( 'OpenSSL unable to sign data', 'oauth2' ) );
262
  }
263
 
264
  return $signature;
265
  }
266
 
267
- return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'oauth2' ) );
268
  }
269
 
270
  /**
@@ -280,7 +280,7 @@ final class ITSEC_Lib_JWT {
280
  */
281
  protected static function verify( $msg, $signature, $key, $alg ) {
282
  if ( empty( static::$supported_algs[ $alg ] ) ) {
283
- return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'oauth2' ) );
284
  }
285
 
286
  list( $function, $algorithm ) = static::$supported_algs[ $alg ];
60
  $allow_unsecured = in_array( 'none', $allowed_algs, true );
61
 
62
  if ( $allow_unsecured && 'unsecure' !== $confirm_unsecure ) {
63
+ return new \WP_Error( 'jwt_unsecure_not_confirmed', __( 'Did not confirm that "none" is an allowed algorithm.', 'better-wp-security' ) );
64
  }
65
 
66
  if ( empty( $key ) && ! $allow_unsecured ) {
67
+ return new \WP_Error( 'jwt_empty_key', __( 'Key may not be empty', 'better-wp-security' ) );
68
  }
69
 
70
  $parsed = self::parse_jwt( $jwt );
76
  list( $header, $payload, $sig, $headb64, $bodyb64 ) = $parsed;
77
 
78
  if ( empty( $header->alg ) ) {
79
+ return new \WP_Error( 'jwt_invalid_format', __( 'Empty algorithm', 'better-wp-security' ) );
80
  }
81
 
82
  if ( 'none' !== $header->alg || ! $allow_unsecured ) {
83
  if ( empty( static::$supported_algs[ $header->alg ] ) ) {
84
+ return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'better-wp-security' ) );
85
  }
86
 
87
  if ( ! in_array( $header->alg, $allowed_algs, true ) ) {
88
+ return new \WP_Error( 'jwt_disallowed_algorithm', __( 'Algorithm not allowed', 'better-wp-security' ) );
89
  }
90
 
91
  if ( is_array( $key ) || $key instanceof \ArrayAccess ) {
92
  if ( isset( $header->kid ) ) {
93
  if ( ! isset( $key[ $header->kid ] ) ) {
94
+ return new \WP_Error( 'jwt_invalid_key', __( '"kid" invalid, unable to lookup correct key', 'better-wp-security' ) );
95
  }
96
 
97
  $key = $key[ $header->kid ];
98
  } else {
99
+ return new \WP_Error( 'jwt_invalid_key', __( '"kid" empty, unable to lookup correct key', 'better-wp-security' ) );
100
  }
101
  }
102
 
108
  }
109
 
110
  if ( true !== $verified ) {
111
+ return new \WP_Error( 'jwt_invalid_signature', __( 'Signature verification failed', 'better-wp-security' ) );
112
  }
113
  }
114
 
119
  'jwt_before_valid',
120
  sprintf(
121
  /* translators: %s Date/Time the JWT is valid. */
122
+ __( 'Cannot handle token prior to %s.', 'better-wp-security' ),
123
  wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $payload->nbf )
124
  ),
125
  array( 'nbf' => $payload->nbf )
134
  'jwt_before_valid',
135
  sprintf(
136
  /* translators: %s Date/Time the JWT is valid. */
137
+ __( 'Cannot handle token prior to %s.', 'better-wp-security' ),
138
  wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $payload->iat )
139
  ),
140
  array( 'iat' => $payload->iat )
143
 
144
  // Check if this token has expired.
145
  if ( isset( $payload->exp ) && ( $timestamp - static::$leeway ) >= $payload->exp ) {
146
+ return new \WP_Error( 'jwt_expired', __( 'Expired token', 'better-wp-security' ), array( 'exp' => $payload->exp ) );
147
  }
148
 
149
  return $payload;
160
  $tks = explode( '.', $jwt );
161
 
162
  if ( 3 !== count( $tks ) ) {
163
+ return new \WP_Error( 'jwt_invalid_format', __( 'Wrong number of segments', 'better-wp-security' ) );
164
  }
165
 
166
  list( $headb64, $bodyb64, $cryptob64 ) = $tks;
167
 
168
  if ( null === ( $header = static::json_decode( static::url_safe_b64_decode( $headb64 ) ) ) ) {
169
+ return new \WP_Error( 'jwt_invalid_format', __( 'Invalid header encoding', 'better-wp-security' ) );
170
  }
171
 
172
  if ( null === $payload = static::json_decode( static::url_safe_b64_decode( $bodyb64 ) ) ) {
173
+ return new \WP_Error( 'jwt_invalid_format', __( 'Invalid claims encoding', 'better-wp-security' ) );
174
  }
175
 
176
  if ( false === ( $sig = static::url_safe_b64_decode( $cryptob64 ) ) ) {
177
+ return new \WP_Error( 'jwt_invalid_format', __( 'Invalid signature encoding', 'better-wp-security' ) );
178
  }
179
 
180
  return array( $header, $payload, $sig, $headb64, $bodyb64, $cryptob64 );
245
  */
246
  protected static function sign( $msg, $key, $alg = 'HS256' ) {
247
  if ( empty( static::$supported_algs[ $alg ] ) ) {
248
+ return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'better-wp-security' ) );
249
  }
250
 
251
  list( $function, $algorithm ) = static::$supported_algs[ $alg ];
258
  $success = openssl_sign( $msg, $signature, $key, $algorithm );
259
 
260
  if ( ! $success ) {
261
+ return new \WP_Error( 'jwt_openssl_error', __( 'OpenSSL unable to sign data', 'better-wp-security' ) );
262
  }
263
 
264
  return $signature;
265
  }
266
 
267
+ return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'better-wp-security' ) );
268
  }
269
 
270
  /**
280
  */
281
  protected static function verify( $msg, $signature, $key, $alg ) {
282
  if ( empty( static::$supported_algs[ $alg ] ) ) {
283
+ return new \WP_Error( 'jwt_unsupported_algorithm', __( 'Algorithm not supported', 'better-wp-security' ) );
284
  }
285
 
286
  list( $function, $algorithm ) = static::$supported_algs[ $alg ];
core/lib/class-itsec-lib-login-interstitial.php CHANGED
@@ -659,7 +659,7 @@ class ITSEC_Lib_Login_Interstitial {
659
  wp_enqueue_script( 'customize-base' );
660
  }
661
 
662
- login_header( '', '<p class="message">' . __( 'You have logged in successfully.' ) . '</p>' );
663
  ?>
664
  </div>
665
  <?php
659
  wp_enqueue_script( 'customize-base' );
660
  }
661
 
662
+ login_header( '', '<p class="message">' . __( 'You have logged in successfully.', 'better-wp-security' ) . '</p>' );
663
  ?>
664
  </div>
665
  <?php
core/lib/class-itsec-lib-rest.php CHANGED
@@ -141,7 +141,7 @@ class ITSEC_Lib_REST {
141
  public static function validate_ip( $ip, $request, $param ) {
142
  if ( ! is_string( $ip ) || ! ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $ip ) ) {
143
  /* translators: %s: Parameter name. */
144
- return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $param ) );
145
  }
146
 
147
  return true;
141
  public static function validate_ip( $ip, $request, $param ) {
142
  if ( ! is_string( $ip ) || ! ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $ip ) ) {
143
  /* translators: %s: Parameter name. */
144
+ return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.', 'better-wp-security' ), $param ) );
145
  }
146
 
147
  return true;
core/lib/class-itsec-wp-list-table.php CHANGED
@@ -148,8 +148,8 @@ class ITSEC_WP_List_Table {
148
 
149
  if ( empty( $this->modes ) ) {
150
  $this->modes = array(
151
- 'list' => __( 'List View' ),
152
- 'excerpt' => __( 'Excerpt View' )
153
  );
154
  }
155
  }
@@ -309,7 +309,7 @@ class ITSEC_WP_List_Table {
309
  * @since 3.1.0
310
  */
311
  public function no_items() {
312
- _e( 'No items found.' );
313
  }
314
 
315
  /**
@@ -431,9 +431,9 @@ class ITSEC_WP_List_Table {
431
  if ( empty( $this->_actions ) )
432
  return;
433
 
434
- echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action' ) . '</label>';
435
  echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
436
- echo '<option value="-1">' . __( 'Bulk Actions' ) . "</option>\n";
437
 
438
  foreach ( $this->_actions as $name => $title ) {
439
  $class = 'edit' === $name ? ' class="hide-if-no-js"' : '';
@@ -443,7 +443,7 @@ class ITSEC_WP_List_Table {
443
 
444
  echo "</select>\n";
445
 
446
- submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) );
447
  echo "\n";
448
  }
449
 
@@ -491,7 +491,7 @@ class ITSEC_WP_List_Table {
491
  }
492
  $out .= '</div>';
493
 
494
- $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
495
 
496
  return $out;
497
  }
@@ -553,9 +553,9 @@ class ITSEC_WP_List_Table {
553
 
554
  $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
555
  ?>
556
- <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date' ); ?></label>
557
  <select name="m" id="filter-by-date">
558
- <option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option>
559
  <?php
560
  foreach ( $months as $arc_row ) {
561
  if ( 0 == $arc_row->year )
@@ -568,7 +568,7 @@ class ITSEC_WP_List_Table {
568
  selected( $m, $year . $month, false ),
569
  esc_attr( $arc_row->year . $month ),
570
  /* translators: 1: month name, 2: 4-digit year */
571
- sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
572
  );
573
  }
574
  ?>
@@ -618,14 +618,14 @@ class ITSEC_WP_List_Table {
618
  $approved_comments_number = number_format_i18n( $approved_comments );
619
  $pending_comments_number = number_format_i18n( $pending_comments );
620
 
621
- $approved_only_phrase = sprintf( _n( '%s comment', '%s comments', $approved_comments ), $approved_comments_number );
622
- $approved_phrase = sprintf( _n( '%s approved comment', '%s approved comments', $approved_comments ), $approved_comments_number );
623
- $pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments ), $pending_comments_number );
624
 
625
  // No comments at all.
626
  if ( ! $approved_comments && ! $pending_comments ) {
627
  printf( '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">%s</span>',
628
- __( 'No comments' )
629
  );
630
  // Approved comments have different display depending on some conditions.
631
  } elseif ( $approved_comments ) {
@@ -637,7 +637,7 @@ class ITSEC_WP_List_Table {
637
  } else {
638
  printf( '<span class="post-com-count post-com-count-no-comments"><span class="comment-count comment-count-no-comments" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
639
  $approved_comments_number,
640
- $pending_comments ? __( 'No approved comments' ) : __( 'No comments' )
641
  );
642
  }
643
 
@@ -650,7 +650,7 @@ class ITSEC_WP_List_Table {
650
  } else {
651
  printf( '<span class="post-com-count post-com-count-pending post-com-count-no-pending"><span class="comment-count comment-count-no-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
652
  $pending_comments_number,
653
- $approved_comments ? __( 'No pending comments' ) : __( 'No comments' )
654
  );
655
  }
656
  }
@@ -724,7 +724,7 @@ class ITSEC_WP_List_Table {
724
  $this->screen->render_screen_reader_content( 'heading_pagination' );
725
  }
726
 
727
- $output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
728
 
729
  $current = $this->get_pagenum();
730
  $removable_query_args = wp_removable_query_args();
@@ -761,7 +761,7 @@ class ITSEC_WP_List_Table {
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
  '&laquo;'
766
  );
767
  }
@@ -771,30 +771,30 @@ class ITSEC_WP_List_Table {
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
  '&lsaquo;'
776
  );
777
  }
778
 
779
  if ( 'bottom' === $which ) {
780
  $html_current_page = $current;
781
- $total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
782
  } else {
783
  $html_current_page = sprintf( "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
784
- '<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
785
  $current,
786
  strlen( $total_pages )
787
  );
788
  }
789
  $html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
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">&rsaquo;</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
  '&rsaquo;'
799
  );
800
  }
@@ -804,7 +804,7 @@ class ITSEC_WP_List_Table {
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
  '&raquo;'
809
  );
810
  }
@@ -1024,7 +1024,7 @@ class ITSEC_WP_List_Table {
1024
 
1025
  if ( ! empty( $columns['cb'] ) ) {
1026
  static $cb_counter = 1;
1027
- $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
1028
  . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
1029
  $cb_counter++;
1030
  }
@@ -1268,7 +1268,7 @@ class ITSEC_WP_List_Table {
1268
  * @return string The row actions HTML, or an empty string if the current column is the primary column.
1269
  */
1270
  protected function handle_row_actions( $item, $column_name, $primary ) {
1271
- return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : '';
1272
  }
1273
 
1274
  /**
@@ -1292,7 +1292,7 @@ class ITSEC_WP_List_Table {
1292
 
1293
  if ( isset( $this->_pagination_args['total_items'] ) ) {
1294
  $response['total_items_i18n'] = sprintf(
1295
- _n( '%s item', '%s items', $this->_pagination_args['total_items'] ),
1296
  number_format_i18n( $this->_pagination_args['total_items'] )
1297
  );
1298
  }
148
 
149
  if ( empty( $this->modes ) ) {
150
  $this->modes = array(
151
+ 'list' => __( 'List View', 'better-wp-security' ),
152
+ 'excerpt' => __( 'Excerpt View', 'better-wp-security' )
153
  );
154
  }
155
  }
309
  * @since 3.1.0
310
  */
311
  public function no_items() {
312
+ _e( 'No items found.', 'better-wp-security' );
313
  }
314
 
315
  /**
431
  if ( empty( $this->_actions ) )
432
  return;
433
 
434
+ echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action', 'better-wp-security' ) . '</label>';
435
  echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
436
+ echo '<option value="-1">' . __( 'Bulk Actions', 'better-wp-security' ) . "</option>\n";
437
 
438
  foreach ( $this->_actions as $name => $title ) {
439
  $class = 'edit' === $name ? ' class="hide-if-no-js"' : '';
443
 
444
  echo "</select>\n";
445
 
446
+ submit_button( __( 'Apply', 'better-wp-security' ), 'action', '', false, array( 'id' => "doaction$two" ) );
447
  echo "\n";
448
  }
449
 
491
  }
492
  $out .= '</div>';
493
 
494
+ $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details', 'better-wp-security' ) . '</span></button>';
495
 
496
  return $out;
497
  }
553
 
554
  $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
555
  ?>
556
+ <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date', 'better-wp-security' ); ?></label>
557
  <select name="m" id="filter-by-date">
558
+ <option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates', 'better-wp-security' ); ?></option>
559
  <?php
560
  foreach ( $months as $arc_row ) {
561
  if ( 0 == $arc_row->year )
568
  selected( $m, $year . $month, false ),
569
  esc_attr( $arc_row->year . $month ),
570
  /* translators: 1: month name, 2: 4-digit year */
571
+ sprintf( __( '%1$s %2$d', 'better-wp-security' ), $wp_locale->get_month( $month ), $year )
572
  );
573
  }
574
  ?>
618
  $approved_comments_number = number_format_i18n( $approved_comments );
619
  $pending_comments_number = number_format_i18n( $pending_comments );
620
 
621
+ $approved_only_phrase = sprintf( _n( '%s comment', '%s comments', $approved_comments, 'better-wp-security' ), $approved_comments_number );
622
+ $approved_phrase = sprintf( _n( '%s approved comment', '%s approved comments', $approved_comments, 'better-wp-security' ), $approved_comments_number );
623
+ $pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments, 'better-wp-security' ), $pending_comments_number );
624
 
625
  // No comments at all.
626
  if ( ! $approved_comments && ! $pending_comments ) {
627
  printf( '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">%s</span>',
628
+ __( 'No comments', 'better-wp-security' )
629
  );
630
  // Approved comments have different display depending on some conditions.
631
  } elseif ( $approved_comments ) {
637
  } else {
638
  printf( '<span class="post-com-count post-com-count-no-comments"><span class="comment-count comment-count-no-comments" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
639
  $approved_comments_number,
640
+ $pending_comments ? __( 'No approved comments', 'better-wp-security' ) : __( 'No comments', 'better-wp-security' )
641
  );
642
  }
643
 
650
  } else {
651
  printf( '<span class="post-com-count post-com-count-pending post-com-count-no-pending"><span class="comment-count comment-count-no-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
652
  $pending_comments_number,
653
+ $approved_comments ? __( 'No pending comments', 'better-wp-security' ) : __( 'No comments', 'better-wp-security' )
654
  );
655
  }
656
  }
724
  $this->screen->render_screen_reader_content( 'heading_pagination' );
725
  }
726
 
727
+ $output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items, 'better-wp-security' ), number_format_i18n( $total_items ) ) . '</span>';
728
 
729
  $current = $this->get_pagenum();
730
  $removable_query_args = wp_removable_query_args();
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', 'better-wp-security' ),
765
  '&laquo;'
766
  );
767
  }
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', 'better-wp-security' ),
775
  '&lsaquo;'
776
  );
777
  }
778
 
779
  if ( 'bottom' === $which ) {
780
  $html_current_page = $current;
781
+ $total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page', 'better-wp-security' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
782
  } else {
783
  $html_current_page = sprintf( "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
784
+ '<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page', 'better-wp-security' ) . '</label>',
785
  $current,
786
  strlen( $total_pages )
787
  );
788
  }
789
  $html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
790
+ $page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging', 'better-wp-security' ), $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">&rsaquo;</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', 'better-wp-security' ),
798
  '&rsaquo;'
799
  );
800
  }
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', 'better-wp-security' ),
808
  '&raquo;'
809
  );
810
  }
1024
 
1025
  if ( ! empty( $columns['cb'] ) ) {
1026
  static $cb_counter = 1;
1027
+ $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All', 'better-wp-security' ) . '</label>'
1028
  . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
1029
  $cb_counter++;
1030
  }
1268
  * @return string The row actions HTML, or an empty string if the current column is the primary column.
1269
  */
1270
  protected function handle_row_actions( $item, $column_name, $primary ) {
1271
+ return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details', 'better-wp-security' ) . '</span></button>' : '';
1272
  }
1273
 
1274
  /**
1292
 
1293
  if ( isset( $this->_pagination_args['total_items'] ) ) {
1294
  $response['total_items_i18n'] = sprintf(
1295
+ _n( '%s item', '%s items', $this->_pagination_args['total_items'], 'better-wp-security' ),
1296
  number_format_i18n( $this->_pagination_args['total_items'] )
1297
  );
1298
  }
core/lib/includes/function.login-header.php CHANGED
@@ -82,8 +82,8 @@ function login_header( $title = 'Log In', $message = '', $wp_error = '' ) {
82
  $login_header_url = network_home_url();
83
  $login_header_title = get_network()->site_name;
84
  } else {
85
- $login_header_url = __( 'https://wordpress.org/' );
86
- $login_header_title = __( 'Powered by WordPress' );
87
  }
88
 
89
  /**
82
  $login_header_url = network_home_url();
83
  $login_header_title = get_network()->site_name;
84
  } else {
85
+ $login_header_url = __( 'https://wordpress.org/', 'default' );
86
+ $login_header_title = __( 'Powered by WordPress', 'default' );
87
  }
88
 
89
  /**
core/lib/rest/Modules_Controller.php CHANGED
@@ -241,13 +241,13 @@ final class Modules_Controller extends \WP_REST_Controller {
241
  'type' => 'object',
242
  'properties' => [
243
  'id' => [
244
- 'title' => __( 'Module ID' ),
245
  'type' => 'string',
246
  'context' => [ 'view', 'edit', 'embed' ],
247
  'readonly' => true,
248
  ],
249
  'status' => [
250
- 'title' => __( 'Module Status' ),
251
  'type' => 'object',
252
  'properties' => [
253
  'selected' => [
@@ -265,20 +265,20 @@ final class Modules_Controller extends \WP_REST_Controller {
265
  'context' => [ 'view', 'edit', 'embed' ],
266
  ],
267
  'type' => [
268
- 'title' => __( 'The Module Type' ),
269
  'type' => 'string',
270
  'enum' => [ 'recommended', 'advanced', 'tool' ],
271
  'context' => [ 'view', 'edit', 'embed' ],
272
  'readonly' => true,
273
  ],
274
  'onboard' => [
275
- 'title' => __( 'Show in Onboard' ),
276
  'type' => 'boolean',
277
  'context' => [ 'view', 'edit', 'embed' ],
278
  'readonly' => true,
279
  ],
280
  'side_effects' => [
281
- 'title' => __( 'Has Side-Effects' ),
282
  'type' => 'boolean',
283
  'context' => [ 'edit' ],
284
  'readonly' => true,
@@ -293,83 +293,83 @@ final class Modules_Controller extends \WP_REST_Controller {
293
  'readonly' => true,
294
  ],
295
  'title' => [
296
- 'title' => __( 'Module Title' ),
297
  'type' => 'string',
298
  'context' => [ 'view', 'edit', 'embed' ],
299
  'readonly' => true,
300
  ],
301
  'description' => [
302
- 'title' => __( 'Module Description' ),
303
  'type' => 'string',
304
  'context' => [ 'view', 'edit', 'embed' ],
305
  'readonly' => true,
306
  ],
307
  'help' => [
308
- 'title' => __( 'Module Help' ),
309
  'type' => 'string',
310
  'context' => [ 'view', 'edit', 'embed' ],
311
  'readonly' => true,
312
  ],
313
  'user_groups' => [
314
- 'title' => __( 'User Groups' ),
315
  'type' => 'object',
316
  'context' => [ 'edit' ],
317
  'readonly' => true,
318
  ],
319
  'password_requirements' => [
320
- 'title' => __( 'Password Requirements' ),
321
  'type' => 'object',
322
  'context' => [ 'edit' ],
323
  'readonly' => true,
324
  ],
325
  'requirements' => [
326
- 'title' => __( 'Requirements' ),
327
  'type' => 'object',
328
  'context' => [ 'edit' ],
329
  'readonly' => true,
330
  ],
331
  'tools' => [
332
- 'title' => __( 'Module Tools', 'better-wp-security' ),
333
  'type' => 'object',
334
  'additionalProperties' => [
335
  'type' => 'object',
336
  ],
337
  ],
338
  'settings' => [
339
- 'title' => __( 'Module Settings Configuration' ),
340
  'type' => 'object',
341
  'properties' => [
342
  'schema' => [
343
- 'description' => __( 'The schema describing the settings.' ),
344
  'type' => 'object',
345
  ],
346
  'conditional' => [
347
- 'description' => __( 'Map of setting names to conditional setting definitions.' ),
348
  'type' => 'object',
349
  ],
350
  'interactive' => [
351
- 'description' => __( 'List of interactive setting names.' ),
352
  'type' => 'array',
353
  'items' => [
354
  'type' => 'string',
355
  ],
356
  ],
357
  'removed' => [
358
- 'description' => __( 'List of removed setting names.' ),
359
  'type' => 'array',
360
  'items' => [
361
  'type' => 'string',
362
  ],
363
  ],
364
  'deprecated' => [
365
- 'description' => __( 'List of deprecated setting names.' ),
366
  'type' => 'array',
367
  'items' => [
368
  'type' => 'string',
369
  ],
370
  ],
371
  'onboard' => [
372
- 'description' => __( 'List of settings to onboard.' ),
373
  'type' => 'array',
374
  'items' => [
375
  'type' => 'string',
241
  'type' => 'object',
242
  'properties' => [
243
  'id' => [
244
+ 'title' => __( 'Module ID', 'better-wp-security' ),
245
  'type' => 'string',
246
  'context' => [ 'view', 'edit', 'embed' ],
247
  'readonly' => true,
248
  ],
249
  'status' => [
250
+ 'title' => __( 'Module Status', 'better-wp-security' ),
251
  'type' => 'object',
252
  'properties' => [
253
  'selected' => [
265
  'context' => [ 'view', 'edit', 'embed' ],
266
  ],
267
  'type' => [
268
+ 'title' => __( 'The Module Type', 'better-wp-security' ),
269
  'type' => 'string',
270
  'enum' => [ 'recommended', 'advanced', 'tool' ],
271
  'context' => [ 'view', 'edit', 'embed' ],
272
  'readonly' => true,
273
  ],
274
  'onboard' => [
275
+ 'title' => __( 'Show in Onboard', 'better-wp-security' ),
276
  'type' => 'boolean',
277
  'context' => [ 'view', 'edit', 'embed' ],
278
  'readonly' => true,
279
  ],
280
  'side_effects' => [
281
+ 'title' => __( 'Has Side-Effects', 'better-wp-security' ),
282
  'type' => 'boolean',
283
  'context' => [ 'edit' ],
284
  'readonly' => true,
293
  'readonly' => true,
294
  ],
295
  'title' => [
296
+ 'title' => __( 'Module Title', 'better-wp-security' ),
297
  'type' => 'string',
298
  'context' => [ 'view', 'edit', 'embed' ],
299
  'readonly' => true,
300
  ],
301
  'description' => [
302
+ 'title' => __( 'Module Description', 'better-wp-security' ),
303
  'type' => 'string',
304
  'context' => [ 'view', 'edit', 'embed' ],
305
  'readonly' => true,
306
  ],
307
  'help' => [
308
+ 'title' => __( 'Module Help', 'better-wp-security' ),
309
  'type' => 'string',
310
  'context' => [ 'view', 'edit', 'embed' ],
311
  'readonly' => true,
312
  ],
313
  'user_groups' => [
314
+ 'title' => __( 'User Groups', 'better-wp-security' ),
315
  'type' => 'object',
316
  'context' => [ 'edit' ],
317
  'readonly' => true,
318
  ],
319
  'password_requirements' => [
320
+ 'title' => __( 'Password Requirements', 'better-wp-security' ),
321
  'type' => 'object',
322
  'context' => [ 'edit' ],
323
  'readonly' => true,
324
  ],
325
  'requirements' => [
326
+ 'title' => __( 'Requirements', 'better-wp-security' ),
327
  'type' => 'object',
328
  'context' => [ 'edit' ],
329
  'readonly' => true,
330
  ],
331
  'tools' => [
332
+ 'title' => __( 'Module Tools', 'LION', 'better-wp-security' ),
333
  'type' => 'object',
334
  'additionalProperties' => [
335
  'type' => 'object',
336
  ],
337
  ],
338
  'settings' => [
339
+ 'title' => __( 'Module Settings Configuration', 'better-wp-security' ),
340
  'type' => 'object',
341
  'properties' => [
342
  'schema' => [
343
+ 'description' => __( 'The schema describing the settings.', 'better-wp-security' ),
344
  'type' => 'object',
345
  ],
346
  'conditional' => [
347
+ 'description' => __( 'Map of setting names to conditional setting definitions.', 'better-wp-security' ),
348
  'type' => 'object',
349
  ],
350
  'interactive' => [
351
+ 'description' => __( 'List of interactive setting names.', 'better-wp-security' ),
352
  'type' => 'array',
353
  'items' => [
354
  'type' => 'string',
355
  ],
356
  ],
357
  'removed' => [
358
+ 'description' => __( 'List of removed setting names.', 'better-wp-security' ),
359
  'type' => 'array',
360
  'items' => [
361
  'type' => 'string',
362
  ],
363
  ],
364
  'deprecated' => [
365
+ 'description' => __( 'List of deprecated setting names.', 'better-wp-security' ),
366
  'type' => 'array',
367
  'items' => [
368
  'type' => 'string',
369
  ],
370
  ],
371
  'onboard' => [
372
+ 'description' => __( 'List of settings to onboard.', 'better-wp-security' ),
373
  'type' => 'array',
374
  'items' => [
375
  'type' => 'string',
core/modules.php CHANGED
@@ -156,7 +156,11 @@ final class ITSEC_Modules {
156
  $slug = sanitize_title_with_dashes( $slug );
157
 
158
  if ( isset( $self->_module_paths[ $slug ] ) ) {
159
- unset( $self->_module_paths[ $slug ] );
 
 
 
 
160
  $self->_available_modules = array_keys( $self->_module_paths );
161
 
162
  unset( $self->_always_active_modules[ $slug ], $self->_default_active_modules[ $slug ] );
156
  $slug = sanitize_title_with_dashes( $slug );
157
 
158
  if ( isset( $self->_module_paths[ $slug ] ) ) {
159
+ unset(
160
+ $self->_module_paths[ $slug ],
161
+ $self->module_config[ $slug ],
162
+ $self->inherited_modules[ $slug ]
163
+ );
164
  $self->_available_modules = array_keys( $self->_module_paths );
165
 
166
  unset( $self->_always_active_modules[ $slug ], $self->_default_active_modules[ $slug ] );
core/modules/backup/privacy.php CHANGED
@@ -11,7 +11,7 @@ final class ITSEC_Backup_Privacy {
11
  }
12
 
13
  public function get_privacy_policy_for_retention( $policy ) {
14
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
15
 
16
  if ( $this->settings['enabled'] ) {
17
  if ( 1 !== $this->settings['method'] ) {
11
  }
12
 
13
  public function get_privacy_policy_for_retention( $policy ) {
14
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
15
 
16
  if ( $this->settings['enabled'] ) {
17
  if ( 1 !== $this->settings['method'] ) {
core/modules/ban-users/REST.php CHANGED
@@ -34,7 +34,7 @@ final class REST implements Runnable {
34
  'properties' => [
35
  'bans' => [
36
  'title' => __( 'IPs to Ban', 'better-wp-security' ),
37
- 'description' => __( 'Enter one IP address per-line. Optionally, include a note by ending the line with a # sign.' ),
38
  'type' => 'array',
39
  'items' => [
40
  'type' => 'string',
34
  'properties' => [
35
  'bans' => [
36
  'title' => __( 'IPs to Ban', 'better-wp-security' ),
37
+ 'description' => __( 'Enter one IP address per-line. Optionally, include a note by ending the line with a # sign.', 'better-wp-security' ),
38
  'type' => 'array',
39
  'items' => [
40
  'type' => 'string',
core/modules/brute-force/logs.php CHANGED
@@ -38,7 +38,7 @@ final class ITSEC_Brute_Force_Logs {
38
  }
39
 
40
  $details['source'] = array(
41
- 'header' => esc_html__( 'Login Source' ),
42
  'content' => $source,
43
  );
44
 
38
  }
39
 
40
  $details['source'] = array(
41
+ 'header' => esc_html__( 'Login Source', 'better-wp-security' ),
42
  'content' => $source,
43
  );
44
 
core/modules/dashboard/cards/class-itsec-dashboard-card-banned-users.php CHANGED
@@ -6,7 +6,7 @@ class ITSEC_Dashboard_Card_Banned_Users extends ITSEC_Dashboard_Card {
6
  }
7
 
8
  public function get_label() {
9
- return __( 'Banned Users' );
10
  }
11
 
12
  public function get_size() {
6
  }
7
 
8
  public function get_label() {
9
+ return __( 'Banned Users', 'better-wp-security' );
10
  }
11
 
12
  public function get_size() {
core/modules/dashboard/class-itsec-dashboard-rest.php CHANGED
@@ -105,7 +105,7 @@ class ITSEC_Dashboard_REST {
105
  if ( is_wp_error( $permission ) ) {
106
  $response = $permission;
107
  } elseif ( false === $permission || null === $permission ) {
108
- $response = new WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to do that.' ), array( 'status' => rest_authorization_required_code() ) );
109
  }
110
  }
111
 
@@ -124,7 +124,7 @@ class ITSEC_Dashboard_REST {
124
  return $error;
125
  }
126
 
127
- return new WP_Error( 'rest_no_route', __( 'No route was found matching the URL and request method' ), array( 'status' => 404 ) );
128
  }
129
 
130
  /**
105
  if ( is_wp_error( $permission ) ) {
106
  $response = $permission;
107
  } elseif ( false === $permission || null === $permission ) {
108
+ $response = new WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to do that.', 'better-wp-security' ), array( 'status' => rest_authorization_required_code() ) );
109
  }
110
  }
111
 
124
  return $error;
125
  }
126
 
127
+ return new WP_Error( 'rest_no_route', __( 'No route was found matching the URL and request method', 'better-wp-security' ), array( 'status' => 404 ) );
128
  }
129
 
130
  /**
core/modules/global/privacy.php CHANGED
@@ -11,7 +11,7 @@ final class ITSEC_Global_Privacy {
11
  }
12
 
13
  public function get_privacy_policy_for_security_logs( $policy ) {
14
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
15
 
16
  $retention_days = $this->get_retention_days();
17
 
@@ -22,7 +22,7 @@ final class ITSEC_Global_Privacy {
22
  }
23
 
24
  public function get_privacy_policy_for_retention( $policy ) {
25
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
26
 
27
  $retention_days = $this->get_retention_days();
28
 
11
  }
12
 
13
  public function get_privacy_policy_for_security_logs( $policy ) {
14
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
15
 
16
  $retention_days = $this->get_retention_days();
17
 
22
  }
23
 
24
  public function get_privacy_policy_for_retention( $policy ) {
25
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
26
 
27
  $retention_days = $this->get_retention_days();
28
 
core/modules/hide-backend/privacy.php CHANGED
@@ -14,7 +14,7 @@ final class ITSEC_Hide_Backend_Privacy {
14
  }
15
 
16
  public function get_privacy_policy_for_cookies( $policy ) {
17
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
18
 
19
  $policy .= "<p>$suggested_text " . esc_html__( 'Visiting the login page sets a temporary cookie that aids compatibility with some alternate login methods. This cookie contains no personal data and expires after 1 hour.', 'better-wp-security' ) . "</p>\n";
20
 
14
  }
15
 
16
  public function get_privacy_policy_for_cookies( $policy ) {
17
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
18
 
19
  $policy .= "<p>$suggested_text " . esc_html__( 'Visiting the login page sets a temporary cookie that aids compatibility with some alternate login methods. This cookie contains no personal data and expires after 1 hour.', 'better-wp-security' ) . "</p>\n";
20
 
core/modules/network-brute-force/logs.php CHANGED
@@ -46,7 +46,7 @@ final class ITSEC_IPCheck_Logs {
46
  }
47
 
48
  $details['source'] = array(
49
- 'header' => esc_html__( 'Login Source' ),
50
  'content' => $source,
51
  );
52
  }
46
  }
47
 
48
  $details['source'] = array(
49
+ 'header' => esc_html__( 'Login Source', 'better-wp-security' ),
50
  'content' => $source,
51
  );
52
  }
core/modules/network-brute-force/privacy.php CHANGED
@@ -14,7 +14,7 @@ final class ITSEC_Network_Bruteforce_Privacy {
14
  }
15
 
16
  public function get_privacy_policy_for_sending( $policy ) {
17
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
18
 
19
  /* Translators: 1: URL to the iThemes privacy policy */
20
  $policy .= "<p>$suggested_text " . sprintf( wp_kses( __( 'This site is part of a network of sites that protect against distributed brute force attacks. To enable this protection, the IP address of visitors attempting to log into the site is shared with a service provided by ithemes.com. For privacy policy details, please see the <a href="%1$s">iThemes Privacy Policy</a>.', 'better-wp-security' ), array( 'a' => array( 'href' => array() ) ) ), 'https://ithemes.com/privacy-policy' ) . "</p>\n";
14
  }
15
 
16
  public function get_privacy_policy_for_sending( $policy ) {
17
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
18
 
19
  /* Translators: 1: URL to the iThemes privacy policy */
20
  $policy .= "<p>$suggested_text " . sprintf( wp_kses( __( 'This site is part of a network of sites that protect against distributed brute force attacks. To enable this protection, the IP address of visitors attempting to log into the site is shared with a service provided by ithemes.com. For privacy policy details, please see the <a href="%1$s">iThemes Privacy Policy</a>.', 'better-wp-security' ), array( 'a' => array( 'href' => array() ) ) ), 'https://ithemes.com/privacy-policy' ) . "</p>\n";
core/modules/password-requirements/class-itsec-password-requirements.php CHANGED
@@ -437,13 +437,13 @@ class ITSEC_Password_Requirements {
437
  <div class="pw-weak">
438
  <label>
439
  <input type="checkbox" name="pw_weak" class="pw-checkbox"/>
440
- <?php _e( 'Confirm use of weak password' ); ?>
441
  </label>
442
  </div>
443
  </div>
444
 
445
  <p class="user-pass2-wrap">
446
- <label for="pass2"><?php _e( 'Confirm new password' ) ?></label><br/>
447
  <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off"/>
448
  </p>
449
 
437
  <div class="pw-weak">
438
  <label>
439
  <input type="checkbox" name="pw_weak" class="pw-checkbox"/>
440
+ <?php _e( 'Confirm use of weak password', 'better-wp-security' ); ?>
441
  </label>
442
  </div>
443
  </div>
444
 
445
  <p class="user-pass2-wrap">
446
+ <label for="pass2"><?php _e( 'Confirm new password', 'better-wp-security' ) ?></label><br/>
447
  <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off"/>
448
  </p>
449
 
core/modules/privacy/util.php CHANGED
@@ -7,26 +7,26 @@ final class ITSEC_Privacy_Util {
7
 
8
  $sections = array(
9
  'collection' => array(
10
- 'heading' => __( 'What personal data we collect and why we collect it' ),
11
  'subheadings' => array(
12
- 'comments' => __( 'Comments' ),
13
- 'media' => __( 'Media' ),
14
- 'contact_forms' => __( 'Contact Forms' ),
15
- 'cookies' => __( 'Cookies' ),
16
- 'embeds' => __( 'Embedded content from other websites' ),
17
- 'analytics' => __( 'Analytics' ),
18
- 'security_logs' => __( 'Security Logs' ),
19
  ),
20
  ),
21
- 'sharing' => __( 'Who we share your data with' ),
22
- 'retention' => __( 'How long we retain your data' ),
23
- 'rights' => __( 'What rights you have over your data' ),
24
- 'sending' => __( 'Where we send your data' ),
25
- 'additional' => __( 'Additional information' ),
26
- 'protection' => __( 'How we protect your data' ),
27
- 'breach_procedures' => __( 'What data breach procedures we have in place' ),
28
- 'third_parties' => __( 'What third parties we receive data from' ),
29
- 'profiling' => __( 'What automated decision making and/or profiling we do with user data' ),
30
  );
31
 
32
  $sections = apply_filters( 'itsec_get_privacy_policy_sections', $sections );
7
 
8
  $sections = array(
9
  'collection' => array(
10
+ 'heading' => __( 'What personal data we collect and why we collect it', 'better-wp-security' ),
11
  'subheadings' => array(
12
+ 'comments' => __( 'Comments', 'better-wp-security' ),
13
+ 'media' => __( 'Media', 'better-wp-security' ),
14
+ 'contact_forms' => __( 'Contact Forms', 'better-wp-security' ),
15
+ 'cookies' => __( 'Cookies', 'better-wp-security' ),
16
+ 'embeds' => __( 'Embedded content from other websites', 'better-wp-security' ),
17
+ 'analytics' => __( 'Analytics', 'better-wp-security' ),
18
+ 'security_logs' => __( 'Security Logs', 'better-wp-security' ),
19
  ),
20
  ),
21
+ 'sharing' => __( 'Who we share your data with', 'better-wp-security' ),
22
+ 'retention' => __( 'How long we retain your data', 'better-wp-security' ),
23
+ 'rights' => __( 'What rights you have over your data', 'better-wp-security' ),
24
+ 'sending' => __( 'Where we send your data', 'better-wp-security' ),
25
+ 'additional' => __( 'Additional information', 'better-wp-security' ),
26
+ 'protection' => __( 'How we protect your data', 'better-wp-security' ),
27
+ 'breach_procedures' => __( 'What data breach procedures we have in place', 'better-wp-security' ),
28
+ 'third_parties' => __( 'What third parties we receive data from', 'better-wp-security' ),
29
+ 'profiling' => __( 'What automated decision making and/or profiling we do with user data', 'better-wp-security' ),
30
  );
31
 
32
  $sections = apply_filters( 'itsec_get_privacy_policy_sections', $sections );
core/modules/site-scanner/api.php CHANGED
@@ -48,7 +48,7 @@ class ITSEC_Site_Scanner_API {
48
  }
49
 
50
  if ( self::is_temporary_server_error( $response ) ) {
51
- $response->add( 'itsec-temporary-server-error', __( 'Site Scanning is temporarily unavailable, please try again later.' ) );
52
  }
53
 
54
  $log_data = [ 'results' => $response, 'cached' => $cached ];
48
  }
49
 
50
  if ( self::is_temporary_server_error( $response ) ) {
51
+ $response->add( 'itsec-temporary-server-error', __( 'Site Scanning is temporarily unavailable, please try again later.', 'better-wp-security' ) );
52
  }
53
 
54
  $log_data = [ 'results' => $response, 'cached' => $cached ];
core/modules/site-scanner/privacy.php CHANGED
@@ -6,7 +6,7 @@ final class ITSEC_Site_Scanner_Privacy {
6
  }
7
 
8
  public function get_privacy_policy_for_sharing( $policy ) {
9
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
10
 
11
  /* Translators: 1: Link to Sucuri's privacy policy */
12
  $policy .= "<p>$suggested_text " . __( 'This site is scanned for potential malware and vulnerabilities by the iThemes Site Scanner. We do not send personal information to the scanner; however, the scanner could find personal information posted publicly (such as in comments) during the scan.', 'better-wp-security' ) . "</p>\n";
6
  }
7
 
8
  public function get_privacy_policy_for_sharing( $policy ) {
9
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
10
 
11
  /* Translators: 1: Link to Sucuri's privacy policy */
12
  $policy .= "<p>$suggested_text " . __( 'This site is scanned for potential malware and vulnerabilities by the iThemes Site Scanner. We do not send personal information to the scanner; however, the scanner could find personal information posted publicly (such as in comments) during the scan.', 'better-wp-security' ) . "</p>\n";
core/modules/ssl/activate.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
 
3
  require_once( __DIR__ . '/class-itsec-ssl.php' );
4
-
5
  ITSEC_SSL::activate();
1
  <?php
2
 
3
  require_once( __DIR__ . '/class-itsec-ssl.php' );
 
4
  ITSEC_SSL::activate();
core/modules/ssl/active.php CHANGED
@@ -1,3 +1,4 @@
1
  <?php
2
 
3
- require_once( dirname( __FILE__ ) . '/class-itsec-ssl.php' );
 
1
  <?php
2
 
3
+ require_once( __DIR__ . '/class-itsec-ssl.php' );
4
+ ITSEC_SSL::get_instance();
core/modules/ssl/class-itsec-ssl.php CHANGED
@@ -7,13 +7,15 @@ class ITSEC_SSL {
7
  private $http_site_url;
8
  private $https_site_url;
9
 
10
- private function __construct() {
11
- $this->init();
 
 
12
  }
13
 
14
- public static function get_instance() {
15
  if ( ! self::$instance ) {
16
- self::$instance = new self;
17
  }
18
 
19
  return self::$instance;
@@ -27,8 +29,7 @@ class ITSEC_SSL {
27
  }
28
 
29
  public static function deactivate() {
30
- $self = self::get_instance();
31
-
32
  $self->remove_config_hooks();
33
  ITSEC_Response::regenerate_wp_config();
34
  }
@@ -56,14 +57,14 @@ class ITSEC_SSL {
56
  add_filter( 'option_home', array( $this, 'get_https_url' ), 5 );
57
 
58
  if ( is_ssl() ) {
59
- $this->http_site_url = site_url( '', 'http' );
60
  $this->https_site_url = site_url( '', 'https' );
61
 
62
  add_filter( 'the_content', array( $this, 'replace_content_urls' ) );
63
  add_filter( 'script_loader_src', array( $this, 'script_loader_src' ) );
64
  add_filter( 'style_loader_src', array( $this, 'style_loader_src' ) );
65
  add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
66
- } else if ( 'cli' !== php_sapi_name() && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
67
  $this->redirect_to_https();
68
  }
69
  }
@@ -127,7 +128,7 @@ class ITSEC_SSL {
127
  * @return array
128
  */
129
  public function upload_dir( $upload_dir ) {
130
- $upload_dir['url'] = str_replace( $this->http_site_url, $this->https_site_url, $upload_dir['url'] );
131
  $upload_dir['baseurl'] = str_replace( $this->http_site_url, $this->https_site_url, $upload_dir['baseurl'] );
132
 
133
  return $upload_dir;
@@ -139,6 +140,3 @@ class ITSEC_SSL {
139
  return $modification;
140
  }
141
  }
142
-
143
-
144
- ITSEC_SSL::get_instance();
7
  private $http_site_url;
8
  private $https_site_url;
9
 
10
+ private function __construct( $run ) {
11
+ if ( $run ) {
12
+ $this->init();
13
+ }
14
  }
15
 
16
+ public static function get_instance( $run = true ) {
17
  if ( ! self::$instance ) {
18
+ self::$instance = new self( $run );
19
  }
20
 
21
  return self::$instance;
29
  }
30
 
31
  public static function deactivate() {
32
+ $self = self::get_instance( false );
 
33
  $self->remove_config_hooks();
34
  ITSEC_Response::regenerate_wp_config();
35
  }
57
  add_filter( 'option_home', array( $this, 'get_https_url' ), 5 );
58
 
59
  if ( is_ssl() ) {
60
+ $this->http_site_url = site_url( '', 'http' );
61
  $this->https_site_url = site_url( '', 'https' );
62
 
63
  add_filter( 'the_content', array( $this, 'replace_content_urls' ) );
64
  add_filter( 'script_loader_src', array( $this, 'script_loader_src' ) );
65
  add_filter( 'style_loader_src', array( $this, 'style_loader_src' ) );
66
  add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
67
+ } elseif ( 'cli' !== php_sapi_name() && ! ITSEC_Core::doing_data_upgrade() && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
68
  $this->redirect_to_https();
69
  }
70
  }
128
  * @return array
129
  */
130
  public function upload_dir( $upload_dir ) {
131
+ $upload_dir['url'] = str_replace( $this->http_site_url, $this->https_site_url, $upload_dir['url'] );
132
  $upload_dir['baseurl'] = str_replace( $this->http_site_url, $this->https_site_url, $upload_dir['baseurl'] );
133
 
134
  return $upload_dir;
140
  return $modification;
141
  }
142
  }
 
 
 
core/modules/ssl/deactivate.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
 
3
- require_once( 'class-itsec-ssl.php' );
4
-
5
  ITSEC_SSL::deactivate();
1
  <?php
2
 
3
+ require_once( __DIR__ . '/class-itsec-ssl.php' );
 
4
  ITSEC_SSL::deactivate();
core/modules/two-factor/class-itsec-two-factor-helper.php CHANGED
@@ -1,7 +1,5 @@
1
  <?php
2
 
3
- use iThemesSecurity\TwoFactor\Application_Passwords_Core;
4
-
5
  /**
6
  * Two-Factor Helper Class
7
  *
1
  <?php
2
 
 
 
3
  /**
4
  * Two-Factor Helper Class
5
  *
core/modules/two-factor/class-itsec-two-factor-on-board.php CHANGED
@@ -222,11 +222,11 @@ class ITSEC_Two_Factor_On_Board extends ITSEC_Login_Interstitial {
222
 
223
  $list = apply_filters( 'wp_sprintf_l', array(
224
  /* translators: used to join items in a list with more than 2 items */
225
- 'between' => sprintf( __( '%1$s, %2$s' ), '', '' ),
226
  /* translators: used to join last two items in a list with more than 2 times */
227
- 'between_last_two' => sprintf( __( '%1$s, and %2$s' ), '', '' ),
228
  /* translators: used to join items in a list with only 2 items */
229
- 'between_only_two' => sprintf( __( '%1$s and %2$s' ), '', '' ),
230
  ) );
231
 
232
  /* translators: 1. List of enabled Two-Factor methods. */
222
 
223
  $list = apply_filters( 'wp_sprintf_l', array(
224
  /* translators: used to join items in a list with more than 2 items */
225
+ 'between' => sprintf( __( '%1$s, %2$s', 'better-wp-security' ), '', '' ),
226
  /* translators: used to join last two items in a list with more than 2 times */
227
+ 'between_last_two' => sprintf( __( '%1$s, and %2$s', 'better-wp-security' ), '', '' ),
228
  /* translators: used to join items in a list with only 2 items */
229
+ 'between_only_two' => sprintf( __( '%1$s and %2$s', 'better-wp-security' ), '', '' ),
230
  ) );
231
 
232
  /* translators: 1. List of enabled Two-Factor methods. */
core/modules/two-factor/class-itsec-two-factor.php CHANGED
@@ -139,8 +139,8 @@ class ITSEC_Two_Factor {
139
  wp_nonce_field( 'user_two_factor_options', '_nonce_user_two_factor_options', false );
140
  ?>
141
  <h3 id="two-factor-user-options"><?php esc_html_e( 'Two-Factor Authentication Options', 'better-wp-security' ); ?></h3>
142
- <p><?php esc_html_e( 'Enabling two-factor authentication greatly increases the security of your user account on this site. With two-factor authentication enabled, after you login with your username and password, you will be asked for an authentication code before you can successfully log in.' ); ?>
143
- <strong> <?php esc_html_e( 'Two-factor authentication codes can come from an app that runs on your mobile device, an email that is sent to you after you login with your username and password, or from a pre-generated list of codes.' ); ?></strong> <?php esc_html_e( 'The settings below allow you to configure which of these authentication code providers are enabled for your user.', 'better-wp-security' ); ?>
144
  </p>
145
 
146
  <table class="two-factor-methods-table widefat wp-list-table striped">
139
  wp_nonce_field( 'user_two_factor_options', '_nonce_user_two_factor_options', false );
140
  ?>
141
  <h3 id="two-factor-user-options"><?php esc_html_e( 'Two-Factor Authentication Options', 'better-wp-security' ); ?></h3>
142
+ <p><?php esc_html_e( 'Enabling two-factor authentication greatly increases the security of your user account on this site. With two-factor authentication enabled, after you login with your username and password, you will be asked for an authentication code before you can successfully log in.', 'better-wp-security' ); ?>
143
+ <strong> <?php esc_html_e( 'Two-factor authentication codes can come from an app that runs on your mobile device, an email that is sent to you after you login with your username and password, or from a pre-generated list of codes.', 'better-wp-security' ); ?></strong> <?php esc_html_e( 'The settings below allow you to configure which of these authentication code providers are enabled for your user.', 'better-wp-security' ); ?>
144
  </p>
145
 
146
  <table class="two-factor-methods-table widefat wp-list-table striped">
core/modules/two-factor/privacy.php CHANGED
@@ -6,7 +6,7 @@ final class ITSEC_Two_Factor_Privacy {
6
  }
7
 
8
  public function get_privacy_policy_for_sharing( $policy ) {
9
- $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
10
 
11
  /* Translators: 1: Link to WordPress's privacy policy, 2: Link to iThemes' privacy policy, 3: Link to Amazon AWS's privacy policy */
12
  $policy .= "<p>$suggested_text " . sprintf( wp_kses( __( 'A QR code image is generated for users that set up two-factor authentication for this site. This image is generated using an iThemes hosted API. As part of generating this image, your username is sent to the API. This data is not logged. For privacy policy details, please see the <a href="%1$s">iThemes Privacy Policy</a>.', 'better-wp-security' ), array( 'a' => array( 'href' => array() ) ) ), 'https://ithemes.com/privacy-policy' ) . "</p>\n";
6
  }
7
 
8
  public function get_privacy_policy_for_sharing( $policy ) {
9
+ $suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'better-wp-security' ) . ' </strong>';
10
 
11
  /* Translators: 1: Link to WordPress's privacy policy, 2: Link to iThemes' privacy policy, 3: Link to Amazon AWS's privacy policy */
12
  $policy .= "<p>$suggested_text " . sprintf( wp_kses( __( 'A QR code image is generated for users that set up two-factor authentication for this site. This image is generated using an iThemes hosted API. As part of generating this image, your username is sent to the API. This data is not logged. For privacy policy details, please see the <a href="%1$s">iThemes Privacy Policy</a>.', 'better-wp-security' ), array( 'a' => array( 'href' => array() ) ) ), 'https://ithemes.com/privacy-policy' ) . "</p>\n";
core/modules/two-factor/providers/class.two-factor-backup-codes.php CHANGED
@@ -58,7 +58,7 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider implements ITSEC_Two_F
58
  $user = wp_get_current_user();
59
 
60
  // Return if the provider is not enabled.
61
- if ( ! in_array( __CLASS__, Two_Factor_Core::get_enabled_providers_for_user( $user->ID ) ) ) {
62
  return;
63
  }
64
 
@@ -119,7 +119,7 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider implements ITSEC_Two_F
119
  <button type="button" class="button button-two-factor-backup-codes-generate button-secondary hide-if-no-js">
120
  <?php esc_html_e( 'Generate Authentication Codes', 'better-wp-security' ); ?>
121
  </button>
122
- <span class="two-factor-backup-codes-count"><?php echo esc_html( sprintf( _n( '%s unused code remaining.', '%s unused codes remaining.', $count ), $count ) ); ?></span>
123
  </p>
124
  <div class="two-factor-backup-codes-wrapper" style="display:none;">
125
  <ol class="two-factor-backup-codes-unused-codes"></ol>
@@ -207,7 +207,7 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider implements ITSEC_Two_F
207
  // Setup the return data.
208
  $codes = $this->generate_codes( $user );
209
  $count = self::codes_remaining_for_user( $user );
210
- $i18n = esc_html( sprintf( _n( '%s unused code remaining.', '%s unused codes remaining.', $count ), $count ) );
211
 
212
  // Send the response.
213
  wp_send_json_success( array( 'codes' => $codes, 'i18n' => $i18n ) );
58
  $user = wp_get_current_user();
59
 
60
  // Return if the provider is not enabled.
61
+ if ( ! in_array( __CLASS__, ITSEC_Two_Factor::get_instance()->get_enabled_providers_for_user( $user->ID ) ) ) {
62
  return;
63
  }
64
 
119
  <button type="button" class="button button-two-factor-backup-codes-generate button-secondary hide-if-no-js">
120
  <?php esc_html_e( 'Generate Authentication Codes', 'better-wp-security' ); ?>
121
  </button>
122
+ <span class="two-factor-backup-codes-count"><?php echo esc_html( sprintf( _n( '%s unused code remaining.', '%s unused codes remaining.', $count, 'better-wp-security' ), $count ) ); ?></span>
123
  </p>
124
  <div class="two-factor-backup-codes-wrapper" style="display:none;">
125
  <ol class="two-factor-backup-codes-unused-codes"></ol>
207
  // Setup the return data.
208
  $codes = $this->generate_codes( $user );
209
  $count = self::codes_remaining_for_user( $user );
210
+ $i18n = esc_html( sprintf( _n( '%s unused code remaining.', '%s unused codes remaining.', $count, 'better-wp-security' ), $count ) );
211
 
212
  // Send the response.
213
  wp_send_json_success( array( 'codes' => $codes, 'i18n' => $i18n ) );
core/modules/user-groups/REST/User_Groups.php CHANGED
@@ -297,7 +297,7 @@ class User_Groups extends \WP_REST_Controller {
297
  if ( ! $user_group->is_configured() ) {
298
  return new \WP_Error(
299
  'rest_user_group_not_configured',
300
- __( 'A user group must have a minimum role, list of roles, or list of users to be created.' ),
301
  [ 'status' => \WP_Http::BAD_REQUEST ]
302
  );
303
  }
297
  if ( ! $user_group->is_configured() ) {
298
  return new \WP_Error(
299
  'rest_user_group_not_configured',
300
+ __( 'A user group must have a minimum role, list of roles, or list of users to be created.', 'better-wp-security' ),
301
  [ 'status' => \WP_Http::BAD_REQUEST ]
302
  );
303
  }
core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php CHANGED
@@ -430,7 +430,7 @@ final class ITSEC_WordPress_Tweaks {
430
 
431
  status_header( 405 );
432
  header( 'Content-Type: text/plain' );
433
- die( __( 'XML-RPC services are disabled on this site.' ) );
434
  }
435
 
436
  /**
430
 
431
  status_header( 405 );
432
  header( 'Content-Type: text/plain' );
433
+ die( __( 'XML-RPC services are disabled on this site.', 'better-wp-security' ) );
434
  }
435
 
436
  /**
core/notify.php CHANGED
@@ -45,9 +45,9 @@ class ITSEC_Notify {
45
  $description = esc_html__( 'During periods of heavy attack, iThemes Security can generate a LOT of email.', 'better-wp-security' );
46
 
47
  if ( ITSEC_Core::is_pro() ) {
48
- $features = esc_html__( 'The Security Digest reduces the number of emails sent so you can receive a summary of lockouts, file change detection scans, and privilege escalations.' );
49
  } else {
50
- $features = esc_html__( 'The Security Digest reduces the number of emails sent so you can receive a summary of lockouts and file change detection scans.' );
51
  }
52
 
53
  return array(
45
  $description = esc_html__( 'During periods of heavy attack, iThemes Security can generate a LOT of email.', 'better-wp-security' );
46
 
47
  if ( ITSEC_Core::is_pro() ) {
48
+ $features = esc_html__( 'The Security Digest reduces the number of emails sent so you can receive a summary of lockouts, file change detection scans, and privilege escalations.', 'better-wp-security' );
49
  } else {
50
+ $features = esc_html__( 'The Security Digest reduces the number of emails sent so you can receive a summary of lockouts and file change detection scans.', 'better-wp-security' );
51
  }
52
 
53
  return array(
history.txt CHANGED
@@ -953,3 +953,8 @@
953
  Dev Note: New Object Oriented API for creating Password Requirements.
954
  Dev Note: New Settings and Modules REST API endpoints.
955
  Dev Note: New RPC REST API namespace. There is no backward compatibility promise for these API endpoints.
 
 
 
 
 
953
  Dev Note: New Object Oriented API for creating Password Requirements.
954
  Dev Note: New Settings and Modules REST API endpoints.
955
  Dev Note: New RPC REST API namespace. There is no backward compatibility promise for these API endpoints.
956
+ 8.0.1 - 2021-07-29 - Timothy Jacobs
957
+ Bug Fix: Sites that did not support HTTPS, but had the SSL module active, but not configured, on upgrade would get redirected to the HTTPS version of the site.
958
+ Bug Fix: Unregister the iThemes Security Two-Factor module when the Two-Factor Feature Plugin is enabled.
959
+ Bug Fix: Allow activation on WordPress 5.7.0.
960
+ Bug Fix: Add missing textdomains.
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: ithemes, chrisjean, mattdanner, timothyblynjacobs
3
  Tags: security plugin, malware scanner, login security, malware prevention, hack prevention, brute force protection, anti-virus, secure, password protection, ban, bad bots, audit log
4
  Requires at least: 5.7
5
  Tested up to: 5.8
6
- Stable tag: 8.0.0
7
  Requires PHP: 7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -189,6 +189,12 @@ Free support may be available with the help of the community in the <a href="htt
189
 
190
  == Changelog ==
191
 
 
 
 
 
 
 
192
  = 8.0.0 =
193
 
194
  * Important: iThemes Security now requires WordPress 5.7 and PHP 7.0 or later.
@@ -665,5 +671,5 @@ Free support may be available with the help of the community in the <a href="htt
665
 
666
  == Upgrade Notice ==
667
 
668
- = 8.0.0 =
669
  Version 8.0.0 is a major new release for iThemes Security with a brand new user interface and new features like Two-Factor.
3
  Tags: security plugin, malware scanner, login security, malware prevention, hack prevention, brute force protection, anti-virus, secure, password protection, ban, bad bots, audit log
4
  Requires at least: 5.7
5
  Tested up to: 5.8
6
+ Stable tag: 8.0.1
7
  Requires PHP: 7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
189
 
190
  == Changelog ==
191
 
192
+ = 8.0.1 =
193
+ * Bug Fix: Sites that did not support HTTPS, but had the SSL module active, but not configured, on upgrade would get redirected to the HTTPS version of the site.
194
+ * Bug Fix: Unregister the iThemes Security Two-Factor module when the Two-Factor Feature Plugin is enabled.
195
+ * Bug Fix: Allow activation on WordPress 5.7.0.
196
+ * Bug Fix: Add missing textdomains.
197
+
198
  = 8.0.0 =
199
 
200
  * Important: iThemes Security now requires WordPress 5.7 and PHP 7.0 or later.
671
 
672
  == Upgrade Notice ==
673
 
674
+ = 8.0.1 =
675
  Version 8.0.0 is a major new release for iThemes Security with a brand new user interface and new features like Two-Factor.