Shield Security for WordPress - Version 7.0.4

Version Description

  • Current Release = Released: 12th February, 2018 - Release Notes

  • (v.4) IMPROVED: Refactored IP address blocking with improved audit trail messages.

  • (v.4) CHANGED: Expanded anonymous REST API whitelist to include 'wpstatistics' namespace.

  • (v.4) IMPROVED: Access protection for shield temp/caching dir.

  • (v.4) IMPROVED: Clarification on reCAPTCHA - v3 is not supported.

  • (v.4) IMPROVED: Clarification on user sessions timeout - Shield sets an absolutely session maximum.

  • (v.4) IMPROVED: Options form submission is adjusted to work around poorly restrictive webhosts.

  • (v.4) FIX: Various tweaks and fixes across the plugin.

  • (v.4) FIX: Error with ClassicPress.

Download this release

Release Info

Developer paultgoodchild
Plugin Icon 128x128 Shield Security for WordPress
Version 7.0.4
Comparing to
See all releases

Code changes from version 7.0.3 to 7.0.4

Files changed (44) hide show
  1. icwp-plugin-controller.php +58 -1
  2. icwp-wpsf.php +1 -1
  3. plugin-spec.php +3 -2
  4. readme.txt +15 -7
  5. resources/js/plugin.js +5 -1
  6. src/common/wp-widget.php +1 -1
  7. src/config/feature-firewall.php +2 -1
  8. src/config/feature-lockdown.php +13 -5
  9. src/config/feature-plugin.php +3 -3
  10. src/features/admin_access_restriction.php +23 -2
  11. src/features/base.php +47 -32
  12. src/features/base_wpsf.php +22 -24
  13. src/features/hack_protect.php +15 -9
  14. src/features/insights.php +1 -1
  15. src/features/ips.php +1 -1
  16. src/features/lockdown.php +5 -6
  17. src/features/plugin.php +5 -3
  18. src/features/user_management.php +32 -14
  19. src/lib/src/Modules/OptsConsumer.php +31 -0
  20. src/lib/src/Scans/Ufc/Scanner.php +15 -12
  21. src/lib/src/Scans/Wpv/Scanner.php +15 -9
  22. src/lib/src/Tables/Build/Sessions.php +24 -1
  23. src/lib/vendor/composer/autoload_classmap.php +2 -0
  24. src/lib/vendor/composer/autoload_static.php +2 -0
  25. src/lib/vendor/composer/installed.json +4 -4
  26. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/General.php +6 -5
  27. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Themes.php +12 -20
  28. src/lib/vendor/fernleafsystems/wordpress-services/src/Services.php +10 -0
  29. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php +558 -0
  30. src/processors/base_wpsf.php +6 -5
  31. src/processors/commentsfilter_antibotspam.php +2 -2
  32. src/processors/commentsfilter_googlerecaptcha.php +2 -2
  33. src/processors/commentsfilter_humanspam.php +2 -2
  34. src/processors/firewall.php +2 -2
  35. src/processors/ips.php +70 -52
  36. src/processors/lockdown.php +5 -9
  37. src/processors/loginprotect_base.php +12 -12
  38. src/processors/loginprotect_gasp.php +4 -4
  39. src/processors/plugin_badge.php +2 -1
  40. src/processors/plugin_badgewidget.php +10 -0
  41. src/processors/usermanagement_sessions.php +30 -24
  42. templates/twig/wpadmin_pages/insights_new/config/index.twig +1 -1
  43. templates/twig/wpadmin_pages/insights_new/config/module_summaries.twig +1 -1
  44. templates/twig/wpadmin_pages/insights_new/insights/index.twig +1 -1
icwp-plugin-controller.php CHANGED
@@ -272,6 +272,41 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
272
  $this->loadAllFeatures( true, true );
273
  }
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  /**
276
  */
277
  protected function doRegisterHooks() {
@@ -796,7 +831,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
796
  /**
797
  * @return array
798
  */
799
- public function getPluginLabels() {
800
 
801
  $aLabels = array_map( 'stripslashes', apply_filters( $this->prefix( 'plugin_labels' ), $this->getPluginSpec_Labels() ) );
802
 
@@ -1367,6 +1402,13 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1367
  return $this->getPath_SourceFile( $this->getPluginSpec_Path( 'autoload' ) );
1368
  }
1369
 
 
 
 
 
 
 
 
1370
  /**
1371
  * Get the directory for the plugin source files with the trailing slash
1372
  * @param string $sSourceFile
@@ -1716,6 +1758,13 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1716
  return $oModule;
1717
  }
1718
 
 
 
 
 
 
 
 
1719
  /**
1720
  * @return ICWP_WPSF_FeatureHandler_Base[]
1721
  */
@@ -1853,6 +1902,14 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1853
  return $aResult;
1854
  }
1855
 
 
 
 
 
 
 
 
 
1856
  /**
1857
  * v5.4.1: Nasty looping bug in here where this function was called within the 'user_has_cap' filter
1858
  * so we removed the "current_user_can()" or any such sub-call within this function
272
  $this->loadAllFeatures( true, true );
273
  }
274
 
275
+ /**
276
+ * @param string $sFilePath
277
+ * @return string
278
+ * @throws \Exception
279
+ */
280
+ public function getPluginCachePath( $sFilePath ) {
281
+ if ( !$this->buildPluginCacheDir() ) {
282
+ throw new \Exception( sprintf( 'Failed to create cache path: "%s"', $this->getPath_PluginCache() ) );
283
+ }
284
+ return path_join( $this->getPath_PluginCache(), $sFilePath );
285
+ }
286
+
287
+ /**
288
+ * @return bool
289
+ */
290
+ private function buildPluginCacheDir() {
291
+ $bSuccess = false;
292
+ $sBase = $this->getPath_PluginCache();
293
+ $oFs = Services::WpFs();
294
+ if ( $oFs->mkdir( $sBase ) ) {
295
+ $sHt = path_join( $sBase, '.htaccess' );
296
+ $sHtContent = "Options -Indexes\ndeny from all";
297
+ if ( !$oFs->exists( $sHt ) || ( md5_file( $sHt ) != md5( $sHtContent ) ) ) {
298
+ $oFs->putFileContent( $sHt, $sHtContent );
299
+ }
300
+ $sIndex = path_join( $sBase, 'index.php' );
301
+ $sIndexContent = "<?php\nhttp_response_code(404);";
302
+ if ( !$oFs->exists( $sIndex ) || ( md5_file( $sIndex ) != md5( $sIndexContent ) ) ) {
303
+ $oFs->putFileContent( $sIndex, $sIndexContent );
304
+ }
305
+ $bSuccess = true;
306
+ }
307
+ return $bSuccess;
308
+ }
309
+
310
  /**
311
  */
312
  protected function doRegisterHooks() {
831
  /**
832
  * @return array
833
  */
834
+ public function getLabels() {
835
 
836
  $aLabels = array_map( 'stripslashes', apply_filters( $this->prefix( 'plugin_labels' ), $this->getPluginSpec_Labels() ) );
837
 
1402
  return $this->getPath_SourceFile( $this->getPluginSpec_Path( 'autoload' ) );
1403
  }
1404
 
1405
+ /**
1406
+ * @return string
1407
+ */
1408
+ public function getPath_PluginCache() {
1409
+ return path_join( WP_CONTENT_DIR, $this->getPluginSpec_Path( 'cache' ) );
1410
+ }
1411
+
1412
  /**
1413
  * Get the directory for the plugin source files with the trailing slash
1414
  * @param string $sSourceFile
1758
  return $oModule;
1759
  }
1760
 
1761
+ /**
1762
+ * @return ICWP_WPSF_FeatureHandler_AdminAccessRestriction|mixed
1763
+ */
1764
+ public function getModule_SecAdmin() {
1765
+ return $this->getModule( 'admin_access_restriction' );
1766
+ }
1767
+
1768
  /**
1769
  * @return ICWP_WPSF_FeatureHandler_Base[]
1770
  */
1902
  return $aResult;
1903
  }
1904
 
1905
+ /**
1906
+ * @deprecated 7.0.4
1907
+ * @return array
1908
+ */
1909
+ public function getPluginLabels() {
1910
+ return $this->getLabels();
1911
+ }
1912
+
1913
  /**
1914
  * v5.4.1: Nasty looping bug in here where this function was called within the 'user_has_cap' filter
1915
  * so we removed the "current_user_can()" or any such sub-call within this function
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://icwp.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 7.0.3
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: One Dollar Plugin
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://icwp.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 7.0.4
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: One Dollar Plugin
plugin-spec.php CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "properties": {
3
- "version": "7.0.3",
4
  "release_timestamp": 1549527670,
5
  "slug_parent": "icwp",
6
  "slug_plugin": "wpsf",
@@ -26,7 +26,8 @@
26
  "assets": "resources",
27
  "languages": "languages",
28
  "templates": "templates",
29
- "flags": "flags"
 
30
  },
31
  "includes": {
32
  "admin": {
1
  {
2
  "properties": {
3
+ "version": "7.0.4",
4
  "release_timestamp": 1549527670,
5
  "slug_parent": "icwp",
6
  "slug_plugin": "wpsf",
26
  "assets": "resources",
27
  "languages": "languages",
28
  "templates": "templates",
29
+ "flags": "flags",
30
+ "cache": "shield"
31
  },
32
  "includes": {
33
  "admin": {
readme.txt CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.5.0
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
  Tested up to: 5.1
11
- Stable tag: 7.0.3
12
 
13
  Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
14
 
@@ -352,8 +352,20 @@ You will always be able to use Shield Security and its free features in-full.
352
 
353
  [Go Pro for just $1/month](https://icwp.io/aa).
354
 
355
- = 7.0.3 - Current Release =
356
- *Released: 7th February, 2018* - [Release Notes](https://icwp.io/ef)
 
 
 
 
 
 
 
 
 
 
 
 
357
 
358
  * **(v.3)** NEW: Automatically whitelist anonymous REST API Access for 3 plugins: Contact Form 7, WooCommerce, JetPack.
359
  * **(v.3)** IMPROVED: Security admin login failure messages are clearer.
@@ -362,10 +374,6 @@ You will always be able to use Shield Security and its free features in-full.
362
  * **(v.3)** IMPROVED: Attempt to also capture B/CC email addresses included in outgoing emails in Audit logs.
363
  * **(v.3)** FIX: Allow use of IPv4 ranges in whitelist again.
364
  * **(v.3)** CHANGED: Numerous code refactoring and improvements building upon the major v7 release and prepping for v7.1.
365
-
366
- = 7.0 - Series =
367
- *Released: 28th January, 2018* - [Release Notes](https://icwp.io/ef)
368
-
369
  * **(v.1-2)** FIXED: Some JS fixes.
370
  * **(v.0)** NEW: New primary UI for Shield site security management. Easy access to scans, audit trail, user sessions etc.
371
  * **(v.0)** NEW: Supports only PHP 5.4 or higher
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
  Tested up to: 5.1
11
+ Stable tag: 7.0.4
12
 
13
  Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
14
 
352
 
353
  [Go Pro for just $1/month](https://icwp.io/aa).
354
 
355
+ = 7.0.4 - Current Release =
356
+ *Released: 12th February, 2018* - [Release Notes](https://icwp.io/ef)
357
+
358
+ * **(v.4)** IMPROVED: Refactored IP address blocking with improved audit trail messages.
359
+ * **(v.4)** CHANGED: Expanded anonymous REST API whitelist to include 'wpstatistics' namespace.
360
+ * **(v.4)** IMPROVED: Access protection for shield temp/caching dir.
361
+ * **(v.4)** IMPROVED: Clarification on reCAPTCHA - v3 is **not** supported.
362
+ * **(v.4)** IMPROVED: Clarification on user sessions timeout - Shield sets an absolutely session maximum.
363
+ * **(v.4)** IMPROVED: Options form submission is adjusted to work around poorly restrictive webhosts.
364
+ * **(v.4)** FIX: Various tweaks and fixes across the plugin.
365
+ * **(v.4)** FIX: Error with ClassicPress.
366
+
367
+ = 7.0 - Series =
368
+ *Released: 28th January, 2018* - [Release Notes](https://icwp.io/ef)
369
 
370
  * **(v.3)** NEW: Automatically whitelist anonymous REST API Access for 3 plugins: Contact Form 7, WooCommerce, JetPack.
371
  * **(v.3)** IMPROVED: Security admin login failure messages are clearer.
374
  * **(v.3)** IMPROVED: Attempt to also capture B/CC email addresses included in outgoing emails in Audit logs.
375
  * **(v.3)** FIX: Allow use of IPv4 ranges in whitelist again.
376
  * **(v.3)** CHANGED: Numerous code refactoring and improvements building upon the major v7 release and prepping for v7.1.
 
 
 
 
377
  * **(v.1-2)** FIXED: Some JS fixes.
378
  * **(v.0)** NEW: New primary UI for Shield site security management. Easy access to scans, audit trail, user sessions etc.
379
  * **(v.0)** NEW: Supports only PHP 5.4 or higher
resources/js/plugin.js CHANGED
@@ -111,7 +111,11 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
111
  } );
112
 
113
  if ( $bPasswordsReady ) {
114
- jQuery.post( ajaxurl, $oForm.serialize(),
 
 
 
 
115
  function ( oResponse ) {
116
  var sMessage;
117
  if ( oResponse === null || typeof oResponse.data === 'undefined'
111
  } );
112
 
113
  if ( $bPasswordsReady ) {
114
+ var aReq = jQuery.extend(
115
+ icwp_wpsf_vars_base.ajax.mod_options,
116
+ { 'form_params': btoa( $oForm.serialize() ) }
117
+ );
118
+ jQuery.post( ajaxurl, aReq,
119
  function ( oResponse ) {
120
  var sMessage;
121
  if ( oResponse === null || typeof oResponse.data === 'undefined'
src/common/wp-widget.php CHANGED
@@ -3,7 +3,7 @@
3
  /**
4
  * Class ICWP_WPSF_WpWidget
5
  */
6
- abstract class ICWP_WPSF_WpWidget extends WP_Widget {
7
 
8
  /**
9
  * @param array $aWidgetArguments
3
  /**
4
  * Class ICWP_WPSF_WpWidget
5
  */
6
+ abstract class ICWP_WPSF_WpWidget extends \WP_Widget {
7
 
8
  /**
9
  * @param array $aWidgetArguments
src/config/feature-firewall.php CHANGED
@@ -302,7 +302,8 @@
302
  "jetpack_sso_redirect_to",
303
  "/^wordpress_logged_in_[0-9a-f]+$/",
304
  "edd_action",
305
- "edd_redirect"
 
306
  ]
307
  },
308
  "firewall_patterns": {
302
  "jetpack_sso_redirect_to",
303
  "/^wordpress_logged_in_[0-9a-f]+$/",
304
  "edd_action",
305
+ "edd_redirect",
306
+ "wpcf7-form"
307
  ]
308
  },
309
  "firewall_patterns": {
src/config/feature-lockdown.php CHANGED
@@ -1,6 +1,6 @@
1
  {
2
- "slug": "lockdown",
3
- "properties": {
4
  "slug": "lockdown",
5
  "name": "Lockdown",
6
  "show_module_menu_item": false,
@@ -14,7 +14,7 @@
14
  "run_if_verified_bot": false,
15
  "order": 90
16
  },
17
- "sections": [
18
  {
19
  "slug": "section_apixml",
20
  "primary": true,
@@ -57,7 +57,7 @@
57
  "hidden": true
58
  }
59
  ],
60
- "options": [
61
  {
62
  "key": "enable_lockdown",
63
  "section": "section_enable_plugin_feature_wordpress_lockdown",
@@ -173,5 +173,13 @@
173
  "section": "section_non_ui",
174
  "default": 0
175
  }
176
- ]
 
 
 
 
 
 
 
 
177
  }
1
  {
2
+ "slug": "lockdown",
3
+ "properties": {
4
  "slug": "lockdown",
5
  "name": "Lockdown",
6
  "show_module_menu_item": false,
14
  "run_if_verified_bot": false,
15
  "order": 90
16
  },
17
+ "sections": [
18
  {
19
  "slug": "section_apixml",
20
  "primary": true,
57
  "hidden": true
58
  }
59
  ],
60
+ "options": [
61
  {
62
  "key": "enable_lockdown",
63
  "section": "section_enable_plugin_feature_wordpress_lockdown",
173
  "section": "section_non_ui",
174
  "default": 0
175
  }
176
+ ],
177
+ "definitions": {
178
+ "default_restapi_exclusions": [
179
+ "contact-form-7",
180
+ "jetpack",
181
+ "wpstatistics",
182
+ "woocommerce"
183
+ ]
184
+ }
185
  }
src/config/feature-plugin.php CHANGED
@@ -323,7 +323,7 @@
323
  "link_info": "https://icwp.io/shld5",
324
  "link_blog": "",
325
  "name": "reCAPTCHA Site Key",
326
- "summary": "Google reCAPTCHA Site Key",
327
  "description": "Enter your Google reCAPTCHA site key for use throughout the plugin."
328
  },
329
  {
@@ -335,7 +335,7 @@
335
  "link_info": "https://icwp.io/shld5",
336
  "link_blog": "",
337
  "name": "reCAPTCHA Secret",
338
- "summary": "Google reCAPTCHA Secret Key",
339
  "description": "Enter your Google reCAPTCHA secret key for use throughout the plugin."
340
  },
341
  {
@@ -426,7 +426,7 @@
426
  {
427
  "slug": "admin_access_restriction",
428
  "storage_key": "admin_access_restriction",
429
- "load_priority": 20
430
  },
431
  {
432
  "slug": "hack_protect",
323
  "link_info": "https://icwp.io/shld5",
324
  "link_blog": "",
325
  "name": "reCAPTCHA Site Key",
326
+ "summary": "Google reCAPTCHA Site Key - Only v2 or Invisible. v3 NOT supported.",
327
  "description": "Enter your Google reCAPTCHA site key for use throughout the plugin."
328
  },
329
  {
335
  "link_info": "https://icwp.io/shld5",
336
  "link_blog": "",
337
  "name": "reCAPTCHA Secret",
338
+ "summary": "Google reCAPTCHA Secret Key - Only v2 or Invisible. v3 NOT supported.",
339
  "description": "Enter your Google reCAPTCHA secret key for use throughout the plugin."
340
  },
341
  {
426
  {
427
  "slug": "admin_access_restriction",
428
  "storage_key": "admin_access_restriction",
429
+ "load_priority": 11
430
  },
431
  {
432
  "slug": "hack_protect",
src/features/admin_access_restriction.php CHANGED
@@ -386,7 +386,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
386
  $sAccessKeyRequest = $this->loadRequest()->post( 'admin_access_key_request', '' );
387
  $bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
388
  if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
389
- add_filter( $this->prefix( 'ip_black_mark' ), '__return_true' );
390
  }
391
  return $bSuccess;
392
  }
@@ -496,6 +496,27 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
496
  return $this->setOpt( 'admin_access_key', '' );
497
  }
498
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  /**
500
  * @param array $aAllData
501
  * @return array
@@ -504,7 +525,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
504
  $aThis = array(
505
  'strings' => array(
506
  'title' => _wpsf__( 'Security Admin' ),
507
- 'sub' => _wpsf__( 'Prevent Shield Security Tampering' ),
508
  ),
509
  'key_opts' => array(),
510
  'href_options' => $this->getUrl_AdminPage()
386
  $sAccessKeyRequest = $this->loadRequest()->post( 'admin_access_key_request', '' );
387
  $bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
388
  if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
389
+ $this->setIpTransgressed();
390
  }
391
  return $bSuccess;
392
  }
496
  return $this->setOpt( 'admin_access_key', '' );
497
  }
498
 
499
+ public function insertCustomJsVars_Admin() {
500
+ parent::insertCustomJsVars_Admin();
501
+
502
+ if ( $this->getSecAdminTimeLeft() < 1 ) {
503
+ wp_localize_script(
504
+ $this->prefix( 'plugin' ),
505
+ 'icwp_wpsf_vars_secadmin',
506
+ array(
507
+ 'reqajax' => $this->getSecAdminCheckAjaxData(),
508
+ 'is_sec_admin' => true, // if $nSecTimeLeft > 0
509
+ 'timeleft' => $this->getSecAdminTimeLeft(), // JS uses milliseconds
510
+ 'strings' => array(
511
+ 'confirm' => _wpsf__( 'Security Admin session has timed-out.' ).' '._wpsf__( 'Reload now?' ),
512
+ 'nearly' => _wpsf__( 'Security Admin session has nearly timed-out.' ),
513
+ 'expired' => _wpsf__( 'Security Admin session has timed-out.' )
514
+ )
515
+ )
516
+ );
517
+ }
518
+ }
519
+
520
  /**
521
  * @param array $aAllData
522
  * @return array
525
  $aThis = array(
526
  'strings' => array(
527
  'title' => _wpsf__( 'Security Admin' ),
528
+ 'sub' => sprintf( _wpsf__( 'Prevent Tampering With %s Settings' ), $this->getCon()->getHumanName() ),
529
  ),
530
  'key_opts' => array(),
531
  'href_options' => $this->getUrl_AdminPage()
src/features/base.php CHANGED
@@ -1,10 +1,11 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Services\Services;
 
4
 
5
  abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
6
 
7
- use \FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
8
 
9
  /**
10
  * @var boolean
@@ -210,11 +211,13 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
210
  }
211
 
212
  /**
 
213
  * @return array
214
  */
215
- protected function getAjaxFormParams() {
216
- parse_str( $this->loadRequest()->post( 'form_params', '' ), $aFormParams );
217
- return is_array( $aFormParams ) ? $aFormParams : array();
 
218
  }
219
 
220
  /**
@@ -1185,13 +1188,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1185
  && check_admin_referer( $this->getCon()->getPluginPrefix() );
1186
  }
1187
 
1188
- /**
1189
- * @throws \Exception
1190
- */
1191
- protected function doSaveStandardOptions() {
1192
- $this->updatePluginOptionsFromSubmit();
1193
- }
1194
-
1195
  protected function doExtraSubmitProcessing() {
1196
  }
1197
 
@@ -1248,65 +1244,64 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1248
  /**
1249
  * @throws \Exception
1250
  */
1251
- protected function updatePluginOptionsFromSubmit() {
1252
- $oReq = $this->loadRequest();
1253
-
1254
- if ( $oReq->post( 'plugin_form_submit' ) !== 'Y' ) {
1255
- return;
1256
  }
1257
 
1258
- foreach ( $this->getAllFormOptionsAndTypes() as $sOptionKey => $sOptionType ) {
1259
 
1260
- $sOptionValue = $oReq->post( $sOptionKey );
1261
  if ( is_null( $sOptionValue ) ) {
1262
 
1263
- if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
1264
  continue;
1265
  }
1266
- else if ( $sOptionType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
1267
  $sOptionValue = 'N';
1268
  }
1269
- else if ( $sOptionType == 'integer' ) { //if it was a integer, and it's null, it means '0'
1270
  $sOptionValue = 0;
1271
  }
1272
- else if ( $sOptionType == 'multiple_select' ) {
1273
- $sOptionValue = array();
1274
  }
1275
  }
1276
  else { //handle any pre-processing we need to.
1277
 
1278
- if ( $sOptionType == 'text' || $sOptionType == 'email' ) {
1279
  $sOptionValue = trim( $sOptionValue );
1280
  }
1281
- if ( $sOptionType == 'integer' ) {
1282
  $sOptionValue = intval( $sOptionValue );
1283
  }
1284
- else if ( $sOptionType == 'password' && $this->hasEncryptOption() ) { //md5 any password fields
1285
  $sTempValue = trim( $sOptionValue );
1286
  if ( empty( $sTempValue ) ) {
1287
  continue;
1288
  }
1289
 
1290
- $sConfirm = $oReq->post( $sOptionKey.'_confirm', '' );
1291
  if ( $sTempValue !== $sConfirm ) {
1292
  throw new \Exception( _wpsf__( 'Password values do not match.' ) );
1293
  }
1294
 
1295
  $sOptionValue = md5( $sTempValue );
1296
  }
1297
- else if ( $sOptionType == 'array' ) { //arrays are textareas, where each is separated by newline
1298
  $sOptionValue = array_filter( explode( "\n", esc_textarea( $sOptionValue ) ), 'trim' );
1299
  }
1300
- else if ( $sOptionType == 'comma_separated_lists' ) {
1301
  $sOptionValue = $this->loadDP()->extractCommaSeparatedList( $sOptionValue );
1302
  }
1303
- else if ( $sOptionType == 'multiple_select' ) {
1304
  }
1305
  }
1306
 
1307
  // Prevent overwriting of non-editable fields
1308
- if ( !in_array( $sOptionType, array( 'noneditable_text' ) ) ) {
1309
- $this->setOpt( $sOptionKey, $sOptionValue );
1310
  }
1311
  }
1312
 
@@ -1690,6 +1685,18 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1690
  * Override this with custom JS vars for your particular module.
1691
  */
1692
  public function insertCustomJsVars_Admin() {
 
 
 
 
 
 
 
 
 
 
 
 
1693
  }
1694
 
1695
  /**
@@ -2001,4 +2008,12 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
2001
  public function isPluginDeleting() {
2002
  return $this->getCon()->isPluginDeleting();
2003
  }
 
 
 
 
 
 
 
 
2004
  }
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Services\Services;
4
+ use FernleafSystems\Wordpress\Plugin\Shield;
5
 
6
  abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
7
 
8
+ use Shield\Modules\PluginControllerConsumer;
9
 
10
  /**
11
  * @var boolean
211
  }
212
 
213
  /**
214
+ * @param bool $bBase64Encoded
215
  * @return array
216
  */
217
+ protected function getAjaxFormParams( $bBase64Encoded = false ) {
218
+ $sRaw = $this->loadRequest()->post( 'form_params', '' );
219
+ parse_str( ( $bBase64Encoded ? base64_decode( $sRaw ) : $sRaw ), $aFormParams );
220
+ return is_array( $aFormParams ) ? $aFormParams : [];
221
  }
222
 
223
  /**
1188
  && check_admin_referer( $this->getCon()->getPluginPrefix() );
1189
  }
1190
 
 
 
 
 
 
 
 
1191
  protected function doExtraSubmitProcessing() {
1192
  }
1193
 
1244
  /**
1245
  * @throws \Exception
1246
  */
1247
+ private function doSaveStandardOptions() {
1248
+ $aForm = $this->getAjaxFormParams( true );
1249
+ if ( empty( $aForm[ 'plugin_form_submit' ] ) || $aForm[ 'plugin_form_submit' ] !== 'Y' ) {
1250
+ throw new \Exception( 'Not a standard plugin options form submission' );
 
1251
  }
1252
 
1253
+ foreach ( $this->getAllFormOptionsAndTypes() as $sKey => $sOptType ) {
1254
 
1255
+ $sOptionValue = isset( $aForm[ $sKey ] ) ? $aForm[ $sKey ] : null;
1256
  if ( is_null( $sOptionValue ) ) {
1257
 
1258
+ if ( in_array( $sOptType, [ 'text', 'email' ] ) ) { //text box, and it's null, don't update
1259
  continue;
1260
  }
1261
+ else if ( $sOptType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
1262
  $sOptionValue = 'N';
1263
  }
1264
+ else if ( $sOptType == 'integer' ) { //if it was a integer, and it's null, it means '0'
1265
  $sOptionValue = 0;
1266
  }
1267
+ else if ( $sOptType == 'multiple_select' ) {
1268
+ $sOptionValue = [];
1269
  }
1270
  }
1271
  else { //handle any pre-processing we need to.
1272
 
1273
+ if ( $sOptType == 'text' || $sOptType == 'email' ) {
1274
  $sOptionValue = trim( $sOptionValue );
1275
  }
1276
+ if ( $sOptType == 'integer' ) {
1277
  $sOptionValue = intval( $sOptionValue );
1278
  }
1279
+ else if ( $sOptType == 'password' && $this->hasEncryptOption() ) { //md5 any password fields
1280
  $sTempValue = trim( $sOptionValue );
1281
  if ( empty( $sTempValue ) ) {
1282
  continue;
1283
  }
1284
 
1285
+ $sConfirm = isset( $aForm[ $sKey.'_confirm' ] ) ? $aForm[ $sKey.'_confirm' ] : null;
1286
  if ( $sTempValue !== $sConfirm ) {
1287
  throw new \Exception( _wpsf__( 'Password values do not match.' ) );
1288
  }
1289
 
1290
  $sOptionValue = md5( $sTempValue );
1291
  }
1292
+ else if ( $sOptType == 'array' ) { //arrays are textareas, where each is separated by newline
1293
  $sOptionValue = array_filter( explode( "\n", esc_textarea( $sOptionValue ) ), 'trim' );
1294
  }
1295
+ else if ( $sOptType == 'comma_separated_lists' ) {
1296
  $sOptionValue = $this->loadDP()->extractCommaSeparatedList( $sOptionValue );
1297
  }
1298
+ else if ( $sOptType == 'multiple_select' ) {
1299
  }
1300
  }
1301
 
1302
  // Prevent overwriting of non-editable fields
1303
+ if ( !in_array( $sOptType, array( 'noneditable_text' ) ) ) {
1304
+ $this->setOpt( $sKey, $sOptionValue );
1305
  }
1306
  }
1307
 
1685
  * Override this with custom JS vars for your particular module.
1686
  */
1687
  public function insertCustomJsVars_Admin() {
1688
+
1689
+ if ( $this->isThisModulePage() ) {
1690
+ wp_localize_script(
1691
+ $this->prefix( 'plugin' ),
1692
+ 'icwp_wpsf_vars_base',
1693
+ [
1694
+ 'ajax' => [
1695
+ 'mod_options' => $this->getAjaxActionData( 'mod_options' ),
1696
+ ]
1697
+ ]
1698
+ );
1699
+ }
1700
  }
1701
 
1702
  /**
2008
  public function isPluginDeleting() {
2009
  return $this->getCon()->isPluginDeleting();
2010
  }
2011
+
2012
+ /**
2013
+ * @deprecated
2014
+ * @throws \Exception
2015
+ */
2016
+ protected function updatePluginOptionsFromSubmit() {
2017
+ $this->doSaveStandardOptions();
2018
+ }
2019
  }
src/features/base_wpsf.php CHANGED
@@ -36,25 +36,6 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
36
  return ( $this->getSession() instanceof \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO );
37
  }
38
 
39
- public function insertCustomJsVars_Admin() {
40
- parent::insertCustomJsVars_Admin();
41
-
42
- wp_localize_script(
43
- $this->prefix( 'plugin' ),
44
- 'icwp_wpsf_vars_secadmin',
45
- array(
46
- 'reqajax' => $this->getSecAdminCheckAjaxData(),
47
- 'is_sec_admin' => true, // if $nSecTimeLeft > 0
48
- 'timeleft' => $this->getSecAdminTimeLeft(), // JS uses milliseconds
49
- 'strings' => array(
50
- 'confirm' => _wpsf__( 'Security Admin session has timed-out.' ).' '._wpsf__( 'Reload now?' ),
51
- 'nearly' => _wpsf__( 'Security Admin session has nearly timed-out.' ),
52
- 'expired' => _wpsf__( 'Security Admin session has timed-out.' )
53
- )
54
- )
55
- );
56
- }
57
-
58
  /**
59
  * @return int
60
  */
@@ -127,10 +108,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
127
  * @return bool
128
  */
129
  public function isWlEnabled() {
130
- /** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
131
- $oFO = $this->getCon()
132
- ->getModule( 'admin_access_restriction' );
133
- return $oFO->isWlEnabled();
134
  }
135
 
136
  /**
@@ -165,6 +143,8 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
165
  * @return array
166
  */
167
  protected function getBaseDisplayData( $bRenderEmbeddedContent = true ) {
 
 
168
  return $this->loadDP()->mergeArraysRecursive(
169
  parent::getBaseDisplayData( $bRenderEmbeddedContent ),
170
  array(
@@ -199,7 +179,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
199
  'has_session' => $this->hasSession()
200
  ),
201
  'hrefs' => array(
202
- 'aar_forget_key' => 'https://icwp.io/b5',
203
  )
204
  )
205
  );
@@ -388,4 +368,22 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
388
 
389
  return array( $sTitle, $sTitleShort, $aSummary );
390
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  }
36
  return ( $this->getSession() instanceof \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO );
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  /**
40
  * @return int
41
  */
108
  * @return bool
109
  */
110
  public function isWlEnabled() {
111
+ return $this->getCon()->getModule_SecAdmin()->isWlEnabled();
 
 
 
112
  }
113
 
114
  /**
143
  * @return array
144
  */
145
  protected function getBaseDisplayData( $bRenderEmbeddedContent = true ) {
146
+ $sHelpUrl = $this->isWlEnabled() ? $this->getCon()->getLabels()[ 'AuthorURI' ] : 'https://icwp.io/b5';
147
+
148
  return $this->loadDP()->mergeArraysRecursive(
149
  parent::getBaseDisplayData( $bRenderEmbeddedContent ),
150
  array(
179
  'has_session' => $this->hasSession()
180
  ),
181
  'hrefs' => array(
182
+ 'aar_forget_key' => $sHelpUrl
183
  )
184
  )
185
  );
368
 
369
  return array( $sTitle, $sTitleShort, $aSummary );
370
  }
371
+
372
+ /**
373
+ * Used to mark an IP address for immediate block
374
+ * @return $this
375
+ */
376
+ public function setIpBlocked() {
377
+ add_filter( $this->prefix( 'ip_block_it' ), '__return_true' );
378
+ return $this;
379
+ }
380
+
381
+ /**
382
+ * Used to mark an IP address for transgression/black-mark
383
+ * @return $this
384
+ */
385
+ public function setIpTransgressed() {
386
+ add_filter( $this->prefix( 'ip_black_mark' ), '__return_true' );
387
+ return $this;
388
+ }
389
  }
src/features/hack_protect.php CHANGED
@@ -458,15 +458,15 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
458
  * @return bool
459
  */
460
  public function canPtgWriteToDisk() {
461
- $bCan = (bool)$this->getOpt( 'ptg_candiskwrite' );
462
  $nNow = $this->loadRequest()->ts();
463
-
464
  $bLastCheckExpired = ( $nNow - $this->getOpt( 'ptg_candiskwrite_at', 0 ) ) > DAY_IN_SECONDS;
465
- if ( !$bCan && $bLastCheckExpired ) {
 
 
466
  $oFS = $this->loadFS();
467
  $sDir = $this->getPtgSnapsBaseDir();
468
 
469
- if ( $oFS->mkdir( $sDir ) ) {
470
  $sTestFile = path_join( $sDir, 'test.txt' );
471
  $oFS->putFileContent( $sTestFile, 'test-'.$nNow );
472
  $sContents = $oFS->exists( $sTestFile ) ? $oFS->getFileContent( $sTestFile ) : '';
@@ -474,11 +474,11 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
474
  $oFS->deleteFile( $sTestFile );
475
  $this->setOpt( 'ptg_candiskwrite', !$oFS->exists( $sTestFile ) );
476
  }
 
477
  }
478
- $this->setOpt( 'ptg_candiskwrite_at', $nNow );
479
  }
480
 
481
- return $bCan;
482
  }
483
 
484
  /**
@@ -527,10 +527,16 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
527
  }
528
 
529
  /**
530
- * @return string
531
  */
532
  public function getPtgSnapsBaseDir() {
533
- return path_join( WP_CONTENT_DIR, 'shield/ptguard' );
 
 
 
 
 
 
534
  }
535
 
536
  /**
@@ -1007,7 +1013,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
1007
  'summary' => $bGoodFrequency ?
1008
  _wpsf__( 'Automatic scanners run more than once per day' )
1009
  : _wpsf__( "Automatic scanners only run once per day" ),
1010
- 'weight' => 2,
1011
  'href' => $this->getUrl_DirectLinkToSection( 'section_scan_options' ),
1012
  );
1013
 
458
  * @return bool
459
  */
460
  public function canPtgWriteToDisk() {
 
461
  $nNow = $this->loadRequest()->ts();
 
462
  $bLastCheckExpired = ( $nNow - $this->getOpt( 'ptg_candiskwrite_at', 0 ) ) > DAY_IN_SECONDS;
463
+
464
+ $bCanWrite = (bool)$this->getOpt( 'ptg_candiskwrite' ) && !$bLastCheckExpired;
465
+ if ( !$bCanWrite ) {
466
  $oFS = $this->loadFS();
467
  $sDir = $this->getPtgSnapsBaseDir();
468
 
469
+ if ( $sDir && $oFS->mkdir( $sDir ) ) {
470
  $sTestFile = path_join( $sDir, 'test.txt' );
471
  $oFS->putFileContent( $sTestFile, 'test-'.$nNow );
472
  $sContents = $oFS->exists( $sTestFile ) ? $oFS->getFileContent( $sTestFile ) : '';
474
  $oFS->deleteFile( $sTestFile );
475
  $this->setOpt( 'ptg_candiskwrite', !$oFS->exists( $sTestFile ) );
476
  }
477
+ $this->setOpt( 'ptg_candiskwrite_at', $nNow );
478
  }
 
479
  }
480
 
481
+ return $bCanWrite;
482
  }
483
 
484
  /**
527
  }
528
 
529
  /**
530
+ * @return string|false
531
  */
532
  public function getPtgSnapsBaseDir() {
533
+ try {
534
+ $sPath = $this->getCon()->getPluginCachePath( 'ptguard/' );
535
+ }
536
+ catch ( \Exception $oE ) {
537
+ $sPath = false;
538
+ }
539
+ return $sPath;
540
  }
541
 
542
  /**
1013
  'summary' => $bGoodFrequency ?
1014
  _wpsf__( 'Automatic scanners run more than once per day' )
1015
  : _wpsf__( "Automatic scanners only run once per day" ),
1016
+ 'weight' => 1,
1017
  'href' => $this->getUrl_DirectLinkToSection( 'section_scan_options' ),
1018
  );
1019
 
src/features/insights.php CHANGED
@@ -605,7 +605,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
605
  ),
606
  // 'sessions' => array(
607
  // 'title' => _wpsf__( 'Active Sessions' ),
608
- // 'val' => $oProUsers->getProcessorSessions()->getCountActiveSessions(),
609
  // 'tooltip' => _wpsf__( 'Currently active user sessions.' )
610
  // ),
611
  'transgressions' => array(
605
  ),
606
  // 'sessions' => array(
607
  // 'title' => _wpsf__( 'Active Sessions' ),
608
+ // 'val' => $oProUsers->getProcessorSessions()->countActiveSessions(),
609
  // 'tooltip' => _wpsf__( 'Currently active user sessions.' )
610
  // ),
611
  'transgressions' => array(
src/features/ips.php CHANGED
@@ -240,7 +240,7 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
240
  case 'text_remainingtrans':
241
  $sText = sprintf( '%s: %s',
242
  _wpsf__( 'Warning' ),
243
- _wpsf__( 'You have %s remaining transgression(s) against this site and then you will be black listed.' )
244
  .'<br/><strong>'._wpsf__( 'Seriously, stop repeating what you are doing or you will be locked out.' ).'</strong>'
245
  );
246
  break;
240
  case 'text_remainingtrans':
241
  $sText = sprintf( '%s: %s',
242
  _wpsf__( 'Warning' ),
243
+ _wpsf__( 'You have %s remaining transgression(s) against this site and then your IP address will be completely blocked.' )
244
  .'<br/><strong>'._wpsf__( 'Seriously, stop repeating what you are doing or you will be locked out.' ).'</strong>'
245
  );
246
  break;
src/features/lockdown.php CHANGED
@@ -9,11 +9,10 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
9
  */
10
  private function getRestApiAnonymousExclusions() {
11
  $aExcl = $this->getOpt( 'api_namespace_exclusions' );
12
- if ( empty( $aExcl ) || !is_array( $aExcl ) ) {
13
- $this->getOptionsVo()->resetOptToDefault( 'api_namespace_exclusions' );
14
- $aExcl = $this->getOpt( 'api_namespace_exclusions' );
15
  }
16
- return is_array( $aExcl ) ? $aExcl : [];
17
  }
18
 
19
  /**
@@ -27,7 +26,7 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
27
  /**
28
  * @return bool
29
  */
30
- public function isFileEditingDisabled() {
31
  return $this->isOpt( 'disable_file_editing', 'Y' );
32
  }
33
 
@@ -107,7 +106,7 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
107
  $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
108
  }
109
  else {
110
- $bEditing = $this->isFileEditingDisabled();
111
  $aThis[ 'key_opts' ][ 'editing' ] = array(
112
  'name' => _wpsf__( 'WP File Editing' ),
113
  'enabled' => $bEditing,
9
  */
10
  private function getRestApiAnonymousExclusions() {
11
  $aExcl = $this->getOpt( 'api_namespace_exclusions' );
12
+ if ( !is_array( $aExcl ) ) {
13
+ $aExcl = [];
 
14
  }
15
+ return array_merge( $this->getDef( 'default_restapi_exclusions' ), $aExcl );
16
  }
17
 
18
  /**
26
  /**
27
  * @return bool
28
  */
29
+ public function isOptFileEditingDisabled() {
30
  return $this->isOpt( 'disable_file_editing', 'Y' );
31
  }
32
 
106
  $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
107
  }
108
  else {
109
+ $bEditing = current_user_can( 'edit_plugins' );
110
  $aThis[ 'key_opts' ][ 'editing' ] = array(
111
  'name' => _wpsf__( 'WP File Editing' ),
112
  'enabled' => $bEditing,
src/features/plugin.php CHANGED
@@ -896,7 +896,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
896
  $aThis = array(
897
  'strings' => array(
898
  'title' => _wpsf__( 'General Settings' ),
899
- 'sub' => _wpsf__( 'General Shield Security Settings' ),
900
  ),
901
  'key_opts' => array(),
902
  'href_options' => $this->getUrl_AdminPage()
@@ -1130,13 +1130,15 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
1130
  case 'google_recaptcha_secret_key' :
1131
  $sName = _wpsf__( 'reCAPTCHA Secret' );
1132
  $sSummary = _wpsf__( 'Google reCAPTCHA Secret Key' );
1133
- $sDescription = _wpsf__( 'Enter your Google reCAPTCHA secret key for use throughout the plugin.' );
 
1134
  break;
1135
 
1136
  case 'google_recaptcha_site_key' :
1137
  $sName = _wpsf__( 'reCAPTCHA Site Key' );
1138
  $sSummary = _wpsf__( 'Google reCAPTCHA Site Key' );
1139
- $sDescription = _wpsf__( 'Enter your Google reCAPTCHA site key for use throughout the plugin' );
 
1140
  break;
1141
 
1142
  case 'google_recaptcha_style' :
896
  $aThis = array(
897
  'strings' => array(
898
  'title' => _wpsf__( 'General Settings' ),
899
+ 'sub' => sprintf( _wpsf__( 'General %s Settings' ), $this->getCon()->getHumanName() ),
900
  ),
901
  'key_opts' => array(),
902
  'href_options' => $this->getUrl_AdminPage()
1130
  case 'google_recaptcha_secret_key' :
1131
  $sName = _wpsf__( 'reCAPTCHA Secret' );
1132
  $sSummary = _wpsf__( 'Google reCAPTCHA Secret Key' );
1133
+ $sDescription = _wpsf__( 'Enter your Google reCAPTCHA secret key for use throughout the plugin.' )
1134
+ .'<br />'.sprintf( '<strong>%s</strong>: %s', _wpsf__( 'Important' ), 'reCAPTCHA v3 not supported.' );
1135
  break;
1136
 
1137
  case 'google_recaptcha_site_key' :
1138
  $sName = _wpsf__( 'reCAPTCHA Site Key' );
1139
  $sSummary = _wpsf__( 'Google reCAPTCHA Site Key' );
1140
+ $sDescription = _wpsf__( 'Enter your Google reCAPTCHA site key for use throughout the plugin' )
1141
+ .'<br />'.sprintf( '<strong>%s</strong>: %s', _wpsf__( 'Important' ), 'reCAPTCHA v3 not supported.' );
1142
  break;
1143
 
1144
  case 'google_recaptcha_style' :
src/features/user_management.php CHANGED
@@ -72,7 +72,6 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
72
  $sMessage .= ' *'._wpsf__( 'Your session was retained' );
73
  }
74
  }
75
-
76
  }
77
 
78
  return array(
@@ -117,9 +116,13 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
117
  // first clean out the expired sessions before display
118
  $oPro->getProcessorSessions()->cleanExpiredSessions();
119
 
 
 
 
120
  $oTableBuilder = ( new Shield\Tables\Build\Sessions() )
121
  ->setMod( $this )
122
- ->setDbHandler( $this->getSessionsProcessor()->getDbHandler() );
 
123
 
124
  return array(
125
  'success' => true,
@@ -145,7 +148,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
145
  /**
146
  * @return int
147
  */
148
- public function getSessionTimeoutInterval() {
149
  return $this->getOpt( 'session_timeout_interval' )*DAY_IN_SECONDS;
150
  }
151
 
@@ -159,14 +162,8 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
159
  /**
160
  * @return bool
161
  */
162
- public function hasSessionTimeoutInterval() {
163
- return $this->isModuleEnabled() && ( $this->getSessionTimeoutInterval() > 0 );
164
- }
165
-
166
- protected function doPrePluginOptionsSave() {
167
- if ( $this->getIdleTimeoutInterval() > $this->getSessionTimeoutInterval() ) {
168
- $this->setOpt( 'session_idle_timeout_interval', $this->getOpt( 'session_timeout_interval' )*24 );
169
- }
170
  }
171
 
172
  protected function doExtraSubmitProcessing() {
@@ -182,6 +179,10 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
182
  if ( $this->getOpt( 'session_timeout_interval' ) < 1 ) {
183
  $this->getOptionsVo()->resetOptToDefault( 'session_timeout_interval' );
184
  }
 
 
 
 
185
  }
186
 
187
  /**
@@ -523,9 +524,10 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
523
  $sName = _wpsf__( 'Session Timeout' );
524
  $sSummary = _wpsf__( 'Specify How Many Days After Login To Automatically Force Re-Login' );
525
  $sDescription = _wpsf__( 'WordPress default is 2 days, or 14 days if you check the "Remember Me" box.' )
526
- .'<br />'.sprintf( _wpsf__( 'This cannot be less than %s.' ), '"<strong>1</strong>"' )
527
- .'<br />'.sprintf( '%s: %s', _wpsf__( 'Default' ), '"<strong>'.$this->getOptionsVo()
528
- ->getOptDefault( 'session_timeout_interval' ).'</strong>"' );
 
529
  break;
530
 
531
  case 'session_idle_timeout_interval' :
@@ -605,4 +607,20 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
605
  public function getSessionIdleTimeoutInterval() {
606
  return $this->getIdleTimeoutInterval();
607
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  }
72
  $sMessage .= ' *'._wpsf__( 'Your session was retained' );
73
  }
74
  }
 
75
  }
76
 
77
  return array(
116
  // first clean out the expired sessions before display
117
  $oPro->getProcessorSessions()->cleanExpiredSessions();
118
 
119
+ /** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oSecAdminMod */
120
+ $oSecAdminMod = $this->getCon()->getModule( 'admin_access_restriction' );
121
+
122
  $oTableBuilder = ( new Shield\Tables\Build\Sessions() )
123
  ->setMod( $this )
124
+ ->setDbHandler( $this->getSessionsProcessor()->getDbHandler() )
125
+ ->setSecAdminUsers( $oSecAdminMod->getSecurityAdminUsers() );
126
 
127
  return array(
128
  'success' => true,
148
  /**
149
  * @return int
150
  */
151
+ public function getMaxSessionTime() {
152
  return $this->getOpt( 'session_timeout_interval' )*DAY_IN_SECONDS;
153
  }
154
 
162
  /**
163
  * @return bool
164
  */
165
+ public function hasMaxSessionTimeout() {
166
+ return $this->isModuleEnabled() && ( $this->getMaxSessionTime() > 0 );
 
 
 
 
 
 
167
  }
168
 
169
  protected function doExtraSubmitProcessing() {
179
  if ( $this->getOpt( 'session_timeout_interval' ) < 1 ) {
180
  $this->getOptionsVo()->resetOptToDefault( 'session_timeout_interval' );
181
  }
182
+
183
+ if ( $this->getIdleTimeoutInterval() > $this->getMaxSessionTime() ) {
184
+ $this->setOpt( 'session_idle_timeout_interval', $this->getOpt( 'session_timeout_interval' )*24 );
185
+ }
186
  }
187
 
188
  /**
524
  $sName = _wpsf__( 'Session Timeout' );
525
  $sSummary = _wpsf__( 'Specify How Many Days After Login To Automatically Force Re-Login' );
526
  $sDescription = _wpsf__( 'WordPress default is 2 days, or 14 days if you check the "Remember Me" box.' )
527
+ .'<br />'._wpsf__( 'Think of this as an absolute maximum possible session length.' )
528
+ .'<br />'.sprintf( _wpsf__( 'This cannot be less than %s.' ), '<strong>1</strong>' )
529
+ .' '.sprintf( '%s: %s', _wpsf__( 'Default' ), '<strong>'.$this->getOptionsVo()
530
+ ->getOptDefault( 'session_timeout_interval' ).'</strong>' );
531
  break;
532
 
533
  case 'session_idle_timeout_interval' :
607
  public function getSessionIdleTimeoutInterval() {
608
  return $this->getIdleTimeoutInterval();
609
  }
610
+
611
+ /**
612
+ * @deprecated 7.0.4
613
+ * @return int
614
+ */
615
+ public function getSessionTimeoutInterval() {
616
+ return $this->getMaxSessionTime();
617
+ }
618
+
619
+ /**
620
+ * @deprecated 7.0.4
621
+ * @return bool
622
+ */
623
+ public function hasSessionTimeoutInterval() {
624
+ return $this->hasMaxSessionTimeout();
625
+ }
626
  }
src/lib/src/Modules/OptsConsumer.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
+
5
+ /**
6
+ * Trait OptsConsumer
7
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules
8
+ */
9
+ trait OptsConsumer {
10
+
11
+ /**
12
+ * @var \ICWP_WPSF_OptionsVO
13
+ */
14
+ private $oOpts;
15
+
16
+ /**
17
+ * @return \ICWP_WPSF_OptionsVO
18
+ */
19
+ public function getOpts() {
20
+ return $this->oOpts;
21
+ }
22
+
23
+ /**
24
+ * @param \ICWP_WPSF_OptionsVO $oOpts
25
+ * @return $this
26
+ */
27
+ public function setOpts( $oOpts ) {
28
+ $this->oOpts = $oOpts;
29
+ return $this;
30
+ }
31
+ }
src/lib/src/Scans/Ufc/Scanner.php CHANGED
@@ -48,22 +48,25 @@ class Scanner {
48
  * WP Core files from the collection of files to be assessed
49
  */
50
  $oDirIt = StandardDirectoryIterator::create( $sDir, 0, $this->getFileTypesForDir( $sDir ), true );
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
  catch ( \Exception $oE ) {
 
 
 
53
  continue;
54
  }
55
-
56
- foreach ( $oDirIt as $oFsItem ) {
57
- /** @var \SplFileInfo $oFsItem */
58
- $sFullPath = $oFsItem->getPathname();
59
-
60
- $oResultItem = new ResultItem();
61
- $oResultItem->path_full = wp_normalize_path( $sFullPath );
62
- $oResultItem->path_fragment = $oHashes->getFileFragment( $sFullPath );
63
- if ( !$this->isExcluded( $sFullPath ) ) {
64
- $oResultSet->addItem( $oResultItem );
65
- };
66
- }
67
  }
68
 
69
  return $oResultSet;
48
  * WP Core files from the collection of files to be assessed
49
  */
50
  $oDirIt = StandardDirectoryIterator::create( $sDir, 0, $this->getFileTypesForDir( $sDir ), true );
51
+
52
+ foreach ( $oDirIt as $oFsItem ) {
53
+ /** @var \SplFileInfo $oFsItem */
54
+ $sFullPath = $oFsItem->getPathname();
55
+
56
+ $oResultItem = new ResultItem();
57
+ $oResultItem->path_full = wp_normalize_path( $sFullPath );
58
+ $oResultItem->path_fragment = $oHashes->getFileFragment( $sFullPath );
59
+ if ( !$this->isExcluded( $sFullPath ) ) {
60
+ $oResultSet->addItem( $oResultItem );
61
+ };
62
+ }
63
  }
64
  catch ( \Exception $oE ) {
65
+ error_log(
66
+ sprintf( 'Shield file scanner attempted to read directory but there was error: "%s".', $oE->getMessage() )
67
+ );
68
  continue;
69
  }
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
 
72
  return $oResultSet;
src/lib/src/Scans/Wpv/Scanner.php CHANGED
@@ -62,16 +62,22 @@ class Scanner {
62
  $oWpThemes = Services::WpThemes();
63
 
64
  $oActiveTheme = $oWpThemes->getCurrent();
65
- $aThemes = array(
66
- $oActiveTheme->get_stylesheet() => $oActiveTheme->get_stylesheet()
67
- );
68
- if ( $oWpThemes->isActiveThemeAChild() ) { // is child theme
69
- $oParent = $oWpThemes->getCurrentParent();
70
- $aThemes[ $oParent->get_stylesheet() ] = $oParent->get_stylesheet();
71
- }
72
 
73
- foreach ( $aThemes as $sBaseFile => $sSlug ) {
74
- $aVulns[ $sBaseFile ] = $this->getThemeVulnerabilities( $sBaseFile );
 
 
 
 
 
 
 
 
75
  }
76
  return array_filter( $aVulns );
77
  }
62
  $oWpThemes = Services::WpThemes();
63
 
64
  $oActiveTheme = $oWpThemes->getCurrent();
65
+ if ( $oActiveTheme instanceof \WP_Theme ) {
66
+
67
+ $aThemes = array(
68
+ $oActiveTheme->get_stylesheet() => $oActiveTheme->get_stylesheet()
69
+ );
 
 
70
 
71
+ if ( $oWpThemes->isActiveThemeAChild() ) { // is child theme
72
+ $oParent = $oWpThemes->getCurrentParent();
73
+ if ( $oParent instanceof \WP_Theme ) {
74
+ $aThemes[ $oParent->get_stylesheet() ] = $oParent->get_stylesheet();
75
+ }
76
+ }
77
+
78
+ foreach ( $aThemes as $sBaseFile => $sSlug ) {
79
+ $aVulns[ $sBaseFile ] = $this->getThemeVulnerabilities( $sBaseFile );
80
+ }
81
  }
82
  return array_filter( $aVulns );
83
  }
src/lib/src/Tables/Build/Sessions.php CHANGED
@@ -12,6 +12,11 @@ use FernleafSystems\Wordpress\Services\Services;
12
  */
13
  class Sessions extends BaseBuild {
14
 
 
 
 
 
 
15
  /**
16
  * Override this to apply table-specific query filters.
17
  * @return $this
@@ -60,7 +65,7 @@ class Sessions extends BaseBuild {
60
  foreach ( $this->getEntriesRaw() as $nKey => $oEntry ) {
61
  /** @var Session\EntryVO $oEntry */
62
  $aE = $oEntry->getRawDataAsArray();
63
- $aE[ 'is_secadmin' ] = ( $oEntry->getSecAdminAt() > 0 ) ? __( 'Yes' ) : __( 'No' );
64
  $aE[ 'last_activity_at' ] = $this->formatTimestampField( $oEntry->last_activity_at );
65
  $aE[ 'logged_in_at' ] = $this->formatTimestampField( $oEntry->logged_in_at );
66
  if ( $oEntry->ip == $sYou ) {
@@ -80,4 +85,22 @@ class Sessions extends BaseBuild {
80
  protected function getTableRenderer() {
81
  return new Tables\Render\Sessions();
82
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
12
  */
13
  class Sessions extends BaseBuild {
14
 
15
+ /**
16
+ * @var []
17
+ */
18
+ private $aSecAdminUsers;
19
+
20
  /**
21
  * Override this to apply table-specific query filters.
22
  * @return $this
65
  foreach ( $this->getEntriesRaw() as $nKey => $oEntry ) {
66
  /** @var Session\EntryVO $oEntry */
67
  $aE = $oEntry->getRawDataAsArray();
68
+ $aE[ 'is_secadmin' ] = $this->isSecAdminSession( $oEntry ) ? __( 'Yes' ) : __( 'No' );
69
  $aE[ 'last_activity_at' ] = $this->formatTimestampField( $oEntry->last_activity_at );
70
  $aE[ 'logged_in_at' ] = $this->formatTimestampField( $oEntry->logged_in_at );
71
  if ( $oEntry->ip == $sYou ) {
85
  protected function getTableRenderer() {
86
  return new Tables\Render\Sessions();
87
  }
88
+
89
+ /**
90
+ * @param Session\EntryVO $oEntry
91
+ * @return bool
92
+ */
93
+ private function isSecAdminSession( $oEntry ) {
94
+ return ( $oEntry->getSecAdminAt() > 0 ) ||
95
+ ( is_array( $this->aSecAdminUsers ) && in_array( $oEntry->wp_username, $this->aSecAdminUsers ) );
96
+ }
97
+
98
+ /**
99
+ * @param array $aSecAdminUsernames
100
+ * @return $this
101
+ */
102
+ public function setSecAdminUsers( $aSecAdminUsernames ) {
103
+ $this->aSecAdminUsers = $aSecAdminUsernames;
104
+ return $this;
105
+ }
106
  }
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -74,6 +74,7 @@ return array(
74
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => $baseDir . '/src/Databases/Traffic/Select.php',
75
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => $baseDir . '/src/License/EddLicenseVO.php',
76
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => $baseDir . '/src/Modules/ModConsumer.php',
 
77
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => $baseDir . '/src/Modules/PluginControllerConsumer.php',
78
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertResultsToVos' => $baseDir . '/src/Scans/Base/BaseConvertResultsToVos.php',
79
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertVosToResults' => $baseDir . '/src/Scans/Base/BaseConvertVosToResults.php',
@@ -183,6 +184,7 @@ return array(
183
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
184
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
185
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
 
186
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Core' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Core.php',
187
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Plugins' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Plugins.php',
188
  'GeoIp2\\Database\\Reader' => $vendorDir . '/geoip2/geoip2/src/Database/Reader.php',
74
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => $baseDir . '/src/Databases/Traffic/Select.php',
75
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => $baseDir . '/src/License/EddLicenseVO.php',
76
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => $baseDir . '/src/Modules/ModConsumer.php',
77
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\OptsConsumer' => $baseDir . '/src/Modules/OptsConsumer.php',
78
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => $baseDir . '/src/Modules/PluginControllerConsumer.php',
79
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertResultsToVos' => $baseDir . '/src/Scans/Base/BaseConvertResultsToVos.php',
80
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertVosToResults' => $baseDir . '/src/Scans/Base/BaseConvertVosToResults.php',
184
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
185
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
186
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
187
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
188
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Core' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Core.php',
189
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Plugins' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Plugins.php',
190
  'GeoIp2\\Database\\Reader' => $vendorDir . '/geoip2/geoip2/src/Database/Reader.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -222,6 +222,7 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
222
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => __DIR__ . '/../..' . '/src/Databases/Traffic/Select.php',
223
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => __DIR__ . '/../..' . '/src/License/EddLicenseVO.php',
224
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => __DIR__ . '/../..' . '/src/Modules/ModConsumer.php',
 
225
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/PluginControllerConsumer.php',
226
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertResultsToVos' => __DIR__ . '/../..' . '/src/Scans/Base/BaseConvertResultsToVos.php',
227
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertVosToResults' => __DIR__ . '/../..' . '/src/Scans/Base/BaseConvertVosToResults.php',
@@ -331,6 +332,7 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
331
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
332
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
333
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
 
334
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Core' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Core.php',
335
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Plugins' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Plugins.php',
336
  'GeoIp2\\Database\\Reader' => __DIR__ . '/..' . '/geoip2/geoip2/src/Database/Reader.php',
222
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => __DIR__ . '/../..' . '/src/Databases/Traffic/Select.php',
223
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => __DIR__ . '/../..' . '/src/License/EddLicenseVO.php',
224
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => __DIR__ . '/../..' . '/src/Modules/ModConsumer.php',
225
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\OptsConsumer' => __DIR__ . '/../..' . '/src/Modules/OptsConsumer.php',
226
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/PluginControllerConsumer.php',
227
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertResultsToVos' => __DIR__ . '/../..' . '/src/Scans/Base/BaseConvertResultsToVos.php',
228
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseConvertVosToResults' => __DIR__ . '/../..' . '/src/Scans/Base/BaseConvertVosToResults.php',
332
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
333
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
334
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
335
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
336
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Core' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Core.php',
337
  'FernleafSystems\\Wordpress\\Services\\Utilities\\WpOrg\\Plugins' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Plugins.php',
338
  'GeoIp2\\Database\\Reader' => __DIR__ . '/..' . '/geoip2/geoip2/src/Database/Reader.php',
src/lib/vendor/composer/installed.json CHANGED
@@ -876,12 +876,12 @@
876
  "source": {
877
  "type": "git",
878
  "url": "https://bitbucket.org/FernleafSystems/wordpress-services.git",
879
- "reference": "66ec4f8e00cb487b7db77fd4984ec99903ff13eb"
880
  },
881
  "dist": {
882
  "type": "zip",
883
- "url": "https://bitbucket.org/FernleafSystems/wordpress-services/get/66ec4f8e00cb487b7db77fd4984ec99903ff13eb.zip",
884
- "reference": "66ec4f8e00cb487b7db77fd4984ec99903ff13eb",
885
  "shasum": ""
886
  },
887
  "require": {
@@ -894,7 +894,7 @@
894
  "symfony/yaml": "~2.0||~3.0",
895
  "twig/twig": "^1.0"
896
  },
897
- "time": "2019-02-04T11:29:39+00:00",
898
  "type": "library",
899
  "installation-source": "source",
900
  "autoload": {
876
  "source": {
877
  "type": "git",
878
  "url": "https://bitbucket.org/FernleafSystems/wordpress-services.git",
879
+ "reference": "db0fd10355afe2f9d28bb12b8eae3aa628916c98"
880
  },
881
  "dist": {
882
  "type": "zip",
883
+ "url": "https://bitbucket.org/FernleafSystems/wordpress-services/get/db0fd10355afe2f9d28bb12b8eae3aa628916c98.zip",
884
+ "reference": "db0fd10355afe2f9d28bb12b8eae3aa628916c98",
885
  "shasum": ""
886
  },
887
  "require": {
894
  "symfony/yaml": "~2.0||~3.0",
895
  "twig/twig": "^1.0"
896
  },
897
+ "time": "2019-02-08T13:06:53+00:00",
898
  "type": "library",
899
  "installation-source": "source",
900
  "autoload": {
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/General.php CHANGED
@@ -349,10 +349,10 @@ class General {
349
 
350
  /**
351
  * TODO: Create ClassicPress override class for this stuff
352
- * @param bool $bAlwaysWp if true returns the $wp_version regardless of ClassicPress or not
353
  * @return string
354
  */
355
- public function getVersion( $bAlwaysWp = false ) {
356
 
357
  if ( empty( $this->sWpVersion ) ) {
358
  $sVersionContents = file_get_contents( ABSPATH.WPINC.'/version.php' );
@@ -365,15 +365,16 @@ class General {
365
  $this->sWpVersion = $wp_version;
366
  }
367
  }
368
- return ( $bAlwaysWp || !$this->isClassicPress() ) ? $this->sWpVersion : classicpress_version();
369
  }
370
 
371
  /**
372
  * @param string $sVersionToMeet
 
373
  * @return boolean
374
  */
375
- public function getWordpressIsAtLeastVersion( $sVersionToMeet ) {
376
- return version_compare( $this->getVersion(), $sVersionToMeet, '>=' );
377
  }
378
 
379
  /**
349
 
350
  /**
351
  * TODO: Create ClassicPress override class for this stuff
352
+ * @param bool $bIgnoreClassicpress if true returns the $wp_version regardless of ClassicPress or not
353
  * @return string
354
  */
355
+ public function getVersion( $bIgnoreClassicpress = false ) {
356
 
357
  if ( empty( $this->sWpVersion ) ) {
358
  $sVersionContents = file_get_contents( ABSPATH.WPINC.'/version.php' );
365
  $this->sWpVersion = $wp_version;
366
  }
367
  }
368
+ return ( $bIgnoreClassicpress || !$this->isClassicPress() ) ? $this->sWpVersion : classicpress_version();
369
  }
370
 
371
  /**
372
  * @param string $sVersionToMeet
373
+ * @param bool $bIgnoreClassicPress - set true to compare WP version. False to compare CP version
374
  * @return boolean
375
  */
376
+ public function getWordpressIsAtLeastVersion( $sVersionToMeet, $bIgnoreClassicPress = true ) {
377
+ return version_compare( $this->getVersion( $bIgnoreClassicPress ), $sVersionToMeet, '>=' );
378
  }
379
 
380
  /**
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Themes.php CHANGED
@@ -30,7 +30,7 @@ class Themes {
30
  // Now test currently active theme
31
  $oCurrentTheme = $this->getCurrent();
32
 
33
- return ( !is_null( $oCurrentTheme ) && ( $sThemeStylesheet == $oCurrentTheme->get_stylesheet() ) );
34
  }
35
 
36
  /**
@@ -193,8 +193,7 @@ class Themes {
193
  * @return bool
194
  */
195
  public function getExists( $sStylesheet ) {
196
- $oTheme = $this->getTheme( $sStylesheet );
197
- return ( !is_null( $oTheme ) && ( $oTheme instanceof \WP_Theme ) && $oTheme->exists() );
198
  }
199
 
200
  /**
@@ -206,29 +205,23 @@ class Themes {
206
  }
207
 
208
  /**
 
209
  * @param string $sStylesheet
210
  * @return null|\WP_Theme
211
  */
212
  public function getTheme( $sStylesheet = null ) {
213
- if ( Services::WpGeneral()->getWordpressIsAtLeastVersion( '3.4.0' ) ) {
214
- if ( !function_exists( 'wp_get_theme' ) ) {
215
- require_once( ABSPATH.'wp-admin/includes/theme.php' );
216
- }
217
- return function_exists( 'wp_get_theme' ) ? wp_get_theme( $sStylesheet ) : null;
218
- }
219
- $aThemes = $this->getThemes();
220
- return array_key_exists( $sStylesheet, $aThemes ) ? $aThemes[ $sStylesheet ] : null;
221
  }
222
 
223
  /**
 
224
  * Abstracts the WordPress wp_get_themes()
225
- * @return array|\WP_Theme[]
226
  */
227
  public function getThemes() {
228
- if ( !function_exists( 'wp_get_themes' ) ) {
229
- require_once( ABSPATH.'wp-admin/includes/theme.php' );
230
- }
231
- return function_exists( 'wp_get_themes' ) ? wp_get_themes() : get_themes();
232
  }
233
 
234
  /**
@@ -257,8 +250,7 @@ class Themes {
257
  * @return null|\WP_Theme
258
  */
259
  public function getCurrentParent() {
260
- $oTheme = $this->getCurrent();
261
- return $this->isActiveThemeAChild() ? $this->getTheme( $oTheme->get_template() ) : null;
262
  }
263
 
264
  /**
@@ -308,7 +300,7 @@ class Themes {
308
  * @return bool
309
  */
310
  public function isInstalled( $sSlug ) {
311
- return !empty( $sSlug ) && !is_null( $this->getTheme( $sSlug ) );
312
  }
313
 
314
  /**
@@ -338,7 +330,7 @@ class Themes {
338
  protected function checkForUpdates() {
339
 
340
  if ( class_exists( 'WPRC_Installer' ) && method_exists( 'WPRC_Installer', 'wprc_update_themes' ) ) {
341
- WPRC_Installer::wprc_update_themes();
342
  return true;
343
  }
344
  else if ( function_exists( 'wp_update_themes' ) ) {
30
  // Now test currently active theme
31
  $oCurrentTheme = $this->getCurrent();
32
 
33
+ return ( $sThemeStylesheet == $oCurrentTheme->get_stylesheet() );
34
  }
35
 
36
  /**
193
  * @return bool
194
  */
195
  public function getExists( $sStylesheet ) {
196
+ return $this->getTheme( $sStylesheet )->exists();
 
197
  }
198
 
199
  /**
205
  }
206
 
207
  /**
208
+ * Supports only WP > 3.4.0
209
  * @param string $sStylesheet
210
  * @return null|\WP_Theme
211
  */
212
  public function getTheme( $sStylesheet = null ) {
213
+ require_once( ABSPATH.'wp-admin/includes/theme.php' );
214
+ return function_exists( 'wp_get_theme' ) ? wp_get_theme( $sStylesheet ) : null;
 
 
 
 
 
 
215
  }
216
 
217
  /**
218
+ * Supports only WP > 3.4.0
219
  * Abstracts the WordPress wp_get_themes()
220
+ * @return \WP_Theme[]
221
  */
222
  public function getThemes() {
223
+ require_once( ABSPATH.'wp-admin/includes/theme.php' );
224
+ return function_exists( 'wp_get_themes' ) ? wp_get_themes() : [];
 
 
225
  }
226
 
227
  /**
250
  * @return null|\WP_Theme
251
  */
252
  public function getCurrentParent() {
253
+ return $this->isActiveThemeAChild() ? $this->getTheme( get_template() ) : null;
 
254
  }
255
 
256
  /**
300
  * @return bool
301
  */
302
  public function isInstalled( $sSlug ) {
303
+ return ( !empty( $sSlug ) && $this->getExists( $sSlug ) );
304
  }
305
 
306
  /**
330
  protected function checkForUpdates() {
331
 
332
  if ( class_exists( 'WPRC_Installer' ) && method_exists( 'WPRC_Installer', 'wprc_update_themes' ) ) {
333
+ \WPRC_Installer::wprc_update_themes();
334
  return true;
335
  }
336
  else if ( function_exists( 'wp_update_themes' ) ) {
src/lib/vendor/fernleafsystems/wordpress-services/src/Services.php CHANGED
@@ -73,6 +73,9 @@ class Services {
73
  self::$oDic[ 'service_respond' ] = function () {
74
  return new Core\Respond();
75
  };
 
 
 
76
  self::$oDic[ 'service_includes' ] = function () {
77
  return new Core\Includes();
78
  };
@@ -214,6 +217,13 @@ class Services {
214
  return self::getObj( __FUNCTION__ );
215
  }
216
 
 
 
 
 
 
 
 
217
  /**
218
  * @return Core\AdminNotices
219
  */
73
  self::$oDic[ 'service_respond' ] = function () {
74
  return new Core\Respond();
75
  };
76
+ self::$oDic[ 'service_serviceproviders' ] = function () {
77
+ return new Utilities\ServiceProviders();
78
+ };
79
  self::$oDic[ 'service_includes' ] = function () {
80
  return new Core\Includes();
81
  };
217
  return self::getObj( __FUNCTION__ );
218
  }
219
 
220
+ /**
221
+ * @return Utilities\ServiceProviders
222
+ */
223
+ static public function ServiceProviders() {
224
+ return self::getObj( __FUNCTION__ );
225
+ }
226
+
227
  /**
228
  * @return Core\AdminNotices
229
  */
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php ADDED
@@ -0,0 +1,558 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class ServiceProviders
9
+ * @package FernleafSystems\Wordpress\Services\Utilities
10
+ */
11
+ class ServiceProviders {
12
+
13
+ const URL_IPS_STATUSCAKE = 'https://app.statuscake.com/Workfloor/Locations.php?format=json';
14
+ const URL_IPS_CLOUDFLARE = 'https://www.cloudflare.com/ips-v%s';
15
+ const URL_IPS_ICONTROLWP = 'https://www.icontrolwp.com/?icwp_ips';
16
+ const URL_IPS_MANAGEWP = 'https://managewp.com/wp-content/uploads/2016/11/managewp-ips.txt';
17
+ const URL_IPS_PINGDOM = 'https://my.pingdom.com/probes/ipv%s';
18
+ const URL_IPS_UPTIMEROBOT = 'https://uptimerobot.com/inc/files/ips/IPv%s.txt';
19
+
20
+ /**
21
+ * @return string[]
22
+ */
23
+ public function getAllCrawlerUseragents() {
24
+ return [
25
+ 'Applebot/',
26
+ 'baidu',
27
+ 'bingbot',
28
+ 'Googlebot',
29
+ 'APIs-Google',
30
+ 'AdsBot-Google',
31
+ 'Mediapartners-Google',
32
+ 'yandex.com/bots',
33
+ 'yahoo!'
34
+ ];
35
+ }
36
+
37
+ /**
38
+ * @return string[][]
39
+ */
40
+ public function getIps_CloudFlare() {
41
+ $oWp = Services::WpGeneral();
42
+
43
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_cloudflare' );
44
+ $aIps = $oWp->getTransient( $sStoreKey );
45
+ if ( empty( $aIps ) ) {
46
+ $aIps = array(
47
+ 4 => $this->downloadServiceIps_Cloudflare( 4 ),
48
+ 6 => $this->downloadServiceIps_Cloudflare( 6 )
49
+ );
50
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
51
+ }
52
+ return $aIps;
53
+ }
54
+
55
+ /**
56
+ * @return string[]
57
+ */
58
+ public function getIps_CloudFlareV4() {
59
+ $aIps = $this->getIps_CloudFlare();
60
+ return $aIps[ 4 ];
61
+ }
62
+
63
+ /**
64
+ * @return string[]
65
+ */
66
+ public function getIps_CloudFlareV6() {
67
+ $aIps = $this->getIps_CloudFlare();
68
+ return $aIps[ 6 ];
69
+ }
70
+
71
+ /**
72
+ * @return string[]
73
+ */
74
+ public function getIps_DuckDuckGo() {
75
+ return array( '107.20.237.51', '23.21.226.191', '107.21.1.8', '54.208.102.37' );
76
+ }
77
+
78
+ /**
79
+ * @param bool $bFlat
80
+ * @return array[]|string[]
81
+ */
82
+ public function getIps_iControlWP( $bFlat = false ) {
83
+ $oWp = Services::WpGeneral();
84
+
85
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_icontrolwp' );
86
+ $aIps = $oWp->getTransient( $sStoreKey );
87
+ if ( empty( $aIps ) ) {
88
+ $aIps = $this->downloadServiceIps_iControlWP();
89
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*2 );
90
+ }
91
+
92
+ return $bFlat ? array_merge( $aIps[ 4 ], $aIps[ 6 ] ) : $aIps;
93
+ }
94
+
95
+ /**
96
+ * @return array[]
97
+ */
98
+ public function getIps_ManageWp() {
99
+ $oWp = Services::WpGeneral();
100
+
101
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_managewp' );
102
+ $aIps = $oWp->getTransient( $sStoreKey );
103
+ if ( empty( $aIps ) ) {
104
+ $aIps = $this->downloadServiceIps_ManageWp();
105
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
106
+ }
107
+ return $aIps;
108
+ }
109
+
110
+ /**
111
+ * @return string[][]
112
+ */
113
+ public function getIps_Pingdom() {
114
+ $oWp = Services::WpGeneral();
115
+
116
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_pingdom' );
117
+ $aIps = $oWp->getTransient( $sStoreKey );
118
+ if ( empty( $aIps ) ) {
119
+ $aIps = array(
120
+ 4 => $this->downloadServiceIps_Pingdom( 4 ),
121
+ 6 => $this->downloadServiceIps_Pingdom( 6 )
122
+ );
123
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
124
+ }
125
+ return $aIps;
126
+ }
127
+
128
+ /**
129
+ * @return string[]
130
+ */
131
+ public function getIps_Statuscake() {
132
+ $oWp = Services::WpGeneral();
133
+
134
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_statuscake' );
135
+ $aIps = $oWp->getTransient( $sStoreKey );
136
+ if ( empty( $aIps ) || !is_array( $aIps ) ) {
137
+ $aIps = $this->downloadServiceIps_StatusCake();
138
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
139
+ }
140
+ return $aIps;
141
+ }
142
+
143
+ /**
144
+ * @return array[]
145
+ */
146
+ public function getIps_UptimeRobot() {
147
+ $oWp = Services::WpGeneral();
148
+
149
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_uptimerobot' );
150
+ $aIps = $oWp->getTransient( $sStoreKey );
151
+ if ( empty( $aIps ) ) {
152
+ $aIps = array(
153
+ 4 => $this->downloadServiceIps_UptimeRobot( 4 ),
154
+ 6 => $this->downloadServiceIps_UptimeRobot( 6 )
155
+ );
156
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
157
+ }
158
+ return $aIps;
159
+ }
160
+
161
+ /**
162
+ * @param string $sIp
163
+ * @param string $sUserAgent
164
+ * @return bool
165
+ */
166
+ public function isIp_AppleBot( $sIp, $sUserAgent ) {
167
+ $oWp = Services::WpGeneral();
168
+
169
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_applebot' );
170
+ $aIps = $oWp->getTransient( $sStoreKey );
171
+ if ( !is_array( $aIps ) ) {
172
+ $aIps = array();
173
+ }
174
+
175
+ if ( !in_array( $sIp, $aIps ) && $this->verifyIp_AppleBot( $sIp, $sUserAgent ) ) {
176
+ $aIps[] = $sIp;
177
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
178
+ }
179
+
180
+ return in_array( $sIp, $aIps );
181
+ }
182
+
183
+ /**
184
+ * @param string $sIp
185
+ * @param string $sUserAgent
186
+ * @return bool
187
+ */
188
+ public function isIp_BaiduBot( $sIp, $sUserAgent ) {
189
+ $oWp = Services::WpGeneral();
190
+
191
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_baidubot' );
192
+ $aIps = $oWp->getTransient( $sStoreKey );
193
+ if ( !is_array( $aIps ) ) {
194
+ $aIps = array();
195
+ }
196
+
197
+ if ( !in_array( $sIp, $aIps ) && $this->verifyIp_BaiduBot( $sIp, $sUserAgent ) ) {
198
+ $aIps[] = $sIp;
199
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
200
+ }
201
+
202
+ return in_array( $sIp, $aIps );
203
+ }
204
+
205
+ /**
206
+ * @param string $sIp
207
+ * @param string $sUserAgent
208
+ * @return bool
209
+ */
210
+ public function isIp_BingBot( $sIp, $sUserAgent ) {
211
+ $oWp = Services::WpGeneral();
212
+
213
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_bingbot' );
214
+ $aIps = $oWp->getTransient( $sStoreKey );
215
+ if ( !is_array( $aIps ) ) {
216
+ $aIps = array();
217
+ }
218
+
219
+ if ( !in_array( $sIp, $aIps ) && $this->verifyIp_BingBot( $sIp, $sUserAgent ) ) {
220
+ $aIps[] = $sIp;
221
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
222
+ }
223
+
224
+ return in_array( $sIp, $aIps );
225
+ }
226
+
227
+ /**
228
+ * @param string $sIp
229
+ * @return bool
230
+ */
231
+ public function isIp_Cloudflare( $sIp ) {
232
+ $bIs = false;
233
+ try {
234
+ $oIp = Services::IP();
235
+ if ( $oIp->getIpVersion( $sIp ) == 4 ) {
236
+ $bIs = $oIp->checkIp( $sIp, $this->getIps_CloudFlareV4() );
237
+ }
238
+ else {
239
+ $bIs = $oIp->checkIp( $sIp, $this->getIps_CloudFlareV6() );
240
+ }
241
+ }
242
+ catch ( \Exception $oE ) {
243
+ }
244
+ return $bIs;
245
+ }
246
+
247
+ /**
248
+ * https://duckduckgo.com/duckduckbot
249
+ * @param string $sIp
250
+ * @param string $sUserAgent
251
+ * @return bool
252
+ */
253
+ public function isIp_DuckDuckGoBot( $sIp, $sUserAgent ) {
254
+ $bIsBot = false;
255
+ // We check the useragent if available
256
+ if ( is_null( $sUserAgent ) || stripos( $sUserAgent, 'DuckDuckBot' ) !== false ) {
257
+ $bIsBot = in_array( $sIp, $this->getIps_DuckDuckGo() );
258
+ }
259
+ return $bIsBot;
260
+ }
261
+
262
+ /**
263
+ * @param string $sIp
264
+ * @param string $sAgent
265
+ * @return bool
266
+ */
267
+ public function isIp_iControlWP( $sIp, $sAgent = null ) { //TODO: Agent
268
+ $bIsBot = false;
269
+ if ( is_null( $sAgent ) || stripos( $sAgent, 'iControlWPApp' ) !== false ) {
270
+ $bIsBot = in_array( $sIp, $this->getIps_iControlWP( true ) );
271
+ }
272
+ return $bIsBot;
273
+ }
274
+
275
+ /**
276
+ * https://support.google.com/webmasters/answer/80553?hl=en
277
+ * @param string $sIp
278
+ * @param string $sUserAgent
279
+ * @return bool
280
+ */
281
+ public function isIp_GoogleBot( $sIp, $sUserAgent ) {
282
+ $oWp = Services::WpGeneral();
283
+
284
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_googlebot' );
285
+ $aIps = $oWp->getTransient( $sStoreKey );
286
+ if ( !is_array( $aIps ) ) {
287
+ $aIps = array();
288
+ }
289
+
290
+ if ( !in_array( $sIp, $aIps ) && $this->verifyIp_GoogleBot( $sIp, $sUserAgent ) ) {
291
+ $aIps[] = $sIp;
292
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
293
+ }
294
+
295
+ return in_array( $sIp, $aIps );
296
+ }
297
+
298
+ /**
299
+ * @param string $sIp
300
+ * @param string $sAgent
301
+ * @return bool
302
+ */
303
+ public function isIp_Statuscake( $sIp, $sAgent ) {
304
+ $bIsIp = false;
305
+ if ( stripos( $sAgent, 'StatusCake' ) !== false ) {
306
+ $aIps = $this->getIps_Statuscake();
307
+ $bIsIp = in_array( $sIp, $aIps );
308
+ }
309
+ return $bIsIp;
310
+ }
311
+
312
+ /**
313
+ * @param string $sIp
314
+ * @param string $sAgent
315
+ * @return bool
316
+ */
317
+ public function isIp_Pingdom( $sIp, $sAgent ) {
318
+ $bIsIp = false;
319
+ if ( stripos( $sAgent, 'pingdom.com' ) !== false ) {
320
+ $aIps = $this->getIps_Pingdom();
321
+ $bIsIp = in_array( $sIp, $aIps[ Services::IP()->getIpVersion( $sIp ) ] );
322
+ }
323
+ return $bIsIp;
324
+ }
325
+
326
+ /**
327
+ * @param string $sIp
328
+ * @param string $sAgent
329
+ * @return bool
330
+ */
331
+ public function isIp_UptimeRobot( $sIp, $sAgent ) {
332
+ $bIsIp = false;
333
+ if ( stripos( $sAgent, 'UptimeRobot' ) !== false ) {
334
+ $aIps = $this->getIps_UptimeRobot();
335
+ $bIsIp = in_array( $sIp, $aIps[ Services::IP()->getIpVersion( $sIp ) ] );
336
+ }
337
+ return $bIsIp;
338
+ }
339
+
340
+ /**
341
+ * https://yandex.com/support/webmaster/robot-workings/check-yandex-robots.html
342
+ * @param string $sIp
343
+ * @param string $sUserAgent
344
+ * @return bool
345
+ */
346
+ public function isIp_YandexBot( $sIp, $sUserAgent ) {
347
+ $oWp = Services::WpGeneral();
348
+
349
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_yandexbot' );
350
+ $aIps = $oWp->getTransient( $sStoreKey );
351
+ if ( !is_array( $aIps ) ) {
352
+ $aIps = array();
353
+ }
354
+
355
+ if ( !in_array( $sIp, $aIps ) && $this->verifyIp_YandexBot( $sIp, $sUserAgent ) ) {
356
+ $aIps[] = $sIp;
357
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
358
+ }
359
+
360
+ return in_array( $sIp, $aIps );
361
+ }
362
+
363
+ /**
364
+ * https://yandex.com/support/webmaster/robot-workings/check-yandex-robots.html
365
+ * @param string $sIp
366
+ * @param string $sUserAgent
367
+ * @return bool
368
+ */
369
+ public function isIp_YahooBot( $sIp, $sUserAgent ) {
370
+ $oWp = Services::WpGeneral();
371
+
372
+ $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_yahoobot' );
373
+ $aIps = $oWp->getTransient( $sStoreKey );
374
+ if ( !is_array( $aIps ) ) {
375
+ $aIps = array();
376
+ }
377
+
378
+ if ( !in_array( $sIp, $aIps ) && $this->verifyIp_YahooBot( $sIp, $sUserAgent ) ) {
379
+ $aIps[] = $sIp;
380
+ $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
381
+ }
382
+
383
+ return in_array( $sIp, $aIps );
384
+ }
385
+
386
+ /**
387
+ * https://support.apple.com/en-gb/HT204683
388
+ * https://discussions.apple.com/thread/7090135
389
+ * Apple IPs start with '17.'
390
+ * @param string $sIp
391
+ * @param string $sUserAgent
392
+ * @return bool
393
+ */
394
+ private function verifyIp_AppleBot( $sIp, $sUserAgent = '' ) {
395
+ return ( Services::IP()->getIpVersion( $sIp ) != 4 || strpos( $sIp, '17.' ) === 0 )
396
+ && $this->isIpOfBot( [ 'Applebot/' ], '#.*\.applebot.apple.com\.?$#i', $sIp, $sUserAgent );
397
+ }
398
+
399
+ /**
400
+ * @param string $sIp
401
+ * @param string $sUserAgent
402
+ * @return bool
403
+ */
404
+ private function verifyIp_BaiduBot( $sIp, $sUserAgent = '' ) {
405
+ return $this->isIpOfBot( [ 'baidu' ], '#.*\.crawl\.baidu\.(com|jp)\.?$#i', $sIp, $sUserAgent );
406
+ }
407
+
408
+ /**
409
+ * @param string $sIp
410
+ * @param string $sUserAgent
411
+ * @return bool
412
+ */
413
+ private function verifyIp_BingBot( $sIp, $sUserAgent = '' ) {
414
+ return $this->isIpOfBot( [ 'bingbot' ], '#.*\.search\.msn\.com\.?$#i', $sIp, $sUserAgent );
415
+ }
416
+
417
+ /**
418
+ * @param string $sIp
419
+ * @param string $sUserAgent
420
+ * @return bool
421
+ */
422
+ private function verifyIp_GoogleBot( $sIp, $sUserAgent = '' ) {
423
+ return $this->isIpOfBot(
424
+ [ 'Googlebot', 'APIs-Google', 'AdsBot-Google', 'Mediapartners-Google' ],
425
+ '#.*\.google(bot)?\.com\.?$#i', $sIp, $sUserAgent
426
+ );
427
+ }
428
+
429
+ /**
430
+ * @param string $sIp
431
+ * @param string $sUserAgent
432
+ * @return bool
433
+ */
434
+ private function verifyIp_YandexBot( $sIp, $sUserAgent = '' ) {
435
+ return $this->isIpOfBot( [ 'yandex.com/bots' ], '#.*\.yandex?\.(com|ru|net)\.?$#i', $sIp, $sUserAgent );
436
+ }
437
+
438
+ /**
439
+ * @param string $sIp
440
+ * @param string $sUserAgent
441
+ * @return bool
442
+ */
443
+ private function verifyIp_YahooBot( $sIp, $sUserAgent = '' ) {
444
+ return $this->isIpOfBot( [ 'yahoo!' ], '#.*\.crawl\.yahoo\.net\.?$#i', $sIp, $sUserAgent );
445
+ }
446
+
447
+ /**
448
+ * Will test useragent, then attempt to resolve to hostname and back again
449
+ * https://www.elephate.com/detect-verify-crawlers/
450
+ * @param array $aBotUserAgents
451
+ * @param string $sBotHostPattern
452
+ * @param string $sReqIp
453
+ * @param string $sReqUserAgent
454
+ * @return bool
455
+ */
456
+ private function isIpOfBot( $aBotUserAgents, $sBotHostPattern, $sReqIp, $sReqUserAgent = '' ) {
457
+ $bIsBot = false;
458
+
459
+ $bCheckIpHost = is_null( $sReqUserAgent );
460
+ if ( !$bCheckIpHost ) {
461
+ $aBotUserAgents = array_map(
462
+ function ( $sAgent ) {
463
+ preg_quote( $sAgent, '#' );
464
+ },
465
+ $aBotUserAgents
466
+ );
467
+ $bCheckIpHost = (bool)preg_match( sprintf( '#%s#i', implode( '|', $aBotUserAgents ) ), $sReqUserAgent );
468
+ }
469
+
470
+ if ( $bCheckIpHost ) {
471
+ $sHost = @gethostbyaddr( $sReqIp ); // returns the ip on failure
472
+ $bIsBot = !empty( $sHost ) && ( $sHost != $sReqIp )
473
+ && preg_match( $sBotHostPattern, $sHost )
474
+ && gethostbyname( $sHost ) === $sReqIp;
475
+ }
476
+ return $bIsBot;
477
+ }
478
+
479
+ /**
480
+ * @param int $sIpVersion
481
+ * @return string[]
482
+ */
483
+ private function downloadServiceIps_Cloudflare( $sIpVersion = 4 ) {
484
+ return $this->downloadServiceIps_Standard( self::URL_IPS_CLOUDFLARE, $sIpVersion );
485
+ }
486
+
487
+ /**
488
+ * @return string[]
489
+ */
490
+ private function downloadServiceIps_ManageWp() {
491
+ return $this->downloadServiceIps_Standard( self::URL_IPS_MANAGEWP );
492
+ }
493
+
494
+ /**
495
+ * @return array[]
496
+ */
497
+ private function downloadServiceIps_iControlWP() {
498
+ $aIps = @json_decode( Services::HttpRequest()->getContent( self::URL_IPS_ICONTROLWP ), true );
499
+ return is_array( $aIps ) ? $aIps : [];
500
+ }
501
+
502
+ /**
503
+ * @param int $sIpVersion
504
+ * @return string[]
505
+ */
506
+ private function downloadServiceIps_Pingdom( $sIpVersion = 4 ) {
507
+ return $this->downloadServiceIps_Standard( self::URL_IPS_PINGDOM, $sIpVersion );
508
+ }
509
+
510
+ /**
511
+ * @return string[]
512
+ */
513
+ private function downloadServiceIps_StatusCake() {
514
+ $aIps = array();
515
+ $aData = @json_decode( Services::HttpRequest()->getContent( self::URL_IPS_STATUSCAKE ), true );
516
+ if ( is_array( $aData ) ) {
517
+ foreach ( $aData as $aItem ) {
518
+ if ( !empty( $aItem[ 'ip' ] ) ) {
519
+ $aIps[] = $aItem[ 'ip' ];
520
+ }
521
+ }
522
+ }
523
+ return $aIps;
524
+ }
525
+
526
+ /**
527
+ * @param int $sIpVersion
528
+ * @return string[]
529
+ */
530
+ private function downloadServiceIps_UptimeRobot( $sIpVersion = 4 ) {
531
+ return $this->downloadServiceIps_Standard( self::URL_IPS_UPTIMEROBOT, $sIpVersion );
532
+ }
533
+
534
+ /**
535
+ * @param string $sSourceUrl must have an sprintf %s placeholder
536
+ * @param int $sIpVersion
537
+ * @return string[]
538
+ */
539
+ private function downloadServiceIps_Standard( $sSourceUrl, $sIpVersion = null ) {
540
+ if ( !is_null( $sIpVersion ) ) {
541
+ if ( !in_array( (int)$sIpVersion, array( 4, 6 ) ) ) {
542
+ $sIpVersion = 4;
543
+ }
544
+ $sSourceUrl = Services::HttpRequest()->getContent( sprintf( $sSourceUrl, $sIpVersion ) );
545
+ }
546
+ $sRaw = Services::HttpRequest()->getContent( $sSourceUrl );
547
+ $aIps = empty( $sRaw ) ? array() : explode( "\n", $sRaw );
548
+ return array_filter( array_map( 'trim', $aIps ) );
549
+ }
550
+
551
+ /**
552
+ * @param string $sKey
553
+ * @return string
554
+ */
555
+ private function getPrefixedStoreKey( $sKey ) {
556
+ return 'odp_'.$sKey;
557
+ }
558
+ }
src/processors/base_wpsf.php CHANGED
@@ -106,7 +106,8 @@ abstract class ICWP_WPSF_Processor_BaseWpsf extends ICWP_WPSF_Processor_Base {
106
  * @return bool
107
  */
108
  protected function getIfIpTransgressed() {
109
- return apply_filters( $this->getMod()->prefix( 'ip_black_mark' ), false );
 
110
  }
111
 
112
  /**
@@ -160,13 +161,13 @@ abstract class ICWP_WPSF_Processor_BaseWpsf extends ICWP_WPSF_Processor_Base {
160
  }
161
 
162
  /**
163
- * Used to mark an IP address for transgression/black-mark
164
- *
165
  * @return $this
166
  */
167
  public function setIpTransgressed() {
168
- add_filter( $this->getMod()->prefix( 'ip_black_mark' ), '__return_true' );
169
- return $this;
 
170
  }
171
 
172
  /**
106
  * @return bool
107
  */
108
  protected function getIfIpTransgressed() {
109
+ return apply_filters( $this->getMod()->prefix( 'ip_black_mark' ), false )
110
+ || apply_filters( $this->getMod()->prefix( 'ip_block_it' ), false );
111
  }
112
 
113
  /**
161
  }
162
 
163
  /**
164
+ * @deprecated
 
165
  * @return $this
166
  */
167
  public function setIpTransgressed() {
168
+ /** @var ICWP_WPSF_FeatureHandler_BaseWpsf $oFO */
169
+ $oFO = $this->getMod();
170
+ return $oFO->setIpTransgressed();
171
  }
172
 
173
  /**
src/processors/commentsfilter_antibotspam.php CHANGED
@@ -133,8 +133,8 @@ class ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam extends ICWP_WPSF_BaseDbPro
133
  $this->doStatIncrement( sprintf( 'spam.gasp.%s', $sStatKey ) );
134
  $this->sCommentStatus = $this->getOption( 'comments_default_action_spam_bot' );
135
  $this->setCommentStatusExplanation( $sExplanation );
136
- $this->setIpTransgressed(); // black mark this IP
137
- $oFO->setOptInsightsAt( 'last_comment_block_at' );
138
  }
139
  }
140
 
133
  $this->doStatIncrement( sprintf( 'spam.gasp.%s', $sStatKey ) );
134
  $this->sCommentStatus = $this->getOption( 'comments_default_action_spam_bot' );
135
  $this->setCommentStatusExplanation( $sExplanation );
136
+ $oFO->setOptInsightsAt( 'last_comment_block_at' )
137
+ ->setIpTransgressed();
138
  }
139
  }
140
 
src/processors/commentsfilter_googlerecaptcha.php CHANGED
@@ -62,8 +62,8 @@ class ICWP_WPSF_Processor_CommentsFilter_GoogleRecaptcha extends ICWP_WPSF_Proce
62
  self::$sCommentStatus = $this->getOption( 'comments_default_action_spam_bot' );
63
  $this->setCommentStatusExplanation( $sExplanation );
64
 
65
- $oFO->setOptInsightsAt( 'last_comment_block_at' );
66
- $this->setIpTransgressed(); // black mark this IP
67
 
68
  if ( self::$sCommentStatus == 'reject' ) {
69
  $oWp = $this->loadWp();
62
  self::$sCommentStatus = $this->getOption( 'comments_default_action_spam_bot' );
63
  $this->setCommentStatusExplanation( $sExplanation );
64
 
65
+ $oFO->setOptInsightsAt( 'last_comment_block_at' )
66
+ ->setIpTransgressed();
67
 
68
  if ( self::$sCommentStatus == 'reject' ) {
69
  $oWp = $this->loadWp();
src/processors/commentsfilter_humanspam.php CHANGED
@@ -116,8 +116,8 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_C
116
  $this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
117
  $this->setCommentStatus( $this->getOption( 'comments_default_action_human_spam' ) );
118
  $this->setCommentStatusExplanation( sprintf( _wpsf__( 'Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
119
- $this->setIpTransgressed(); // black mark this IP
120
- $oFO->setOptInsightsAt( 'last_comment_block_at' );
121
  break 2;
122
  }
123
  }
116
  $this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
117
  $this->setCommentStatus( $this->getOption( 'comments_default_action_human_spam' ) );
118
  $this->setCommentStatusExplanation( sprintf( _wpsf__( 'Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
119
+ $oFO->setOptInsightsAt( 'last_comment_block_at' )
120
+ ->setIpTransgressed();
121
  break 2;
122
  }
123
  }
src/processors/firewall.php CHANGED
@@ -277,9 +277,9 @@ class ICWP_WPSF_Processor_Firewall extends ICWP_WPSF_Processor_BaseWpsf {
277
  }
278
  }
279
 
280
- $oFO->setOptInsightsAt( 'last_firewall_block_at' );
 
281
  $this->addToAuditEntry( sprintf( _wpsf__( 'Firewall Block Response: %s.' ), $sMessage ) );
282
- $this->setIpTransgressed(); // black mark this IP
283
  }
284
  }
285
 
277
  }
278
  }
279
 
280
+ $oFO->setOptInsightsAt( 'last_firewall_block_at' )
281
+ ->setIpTransgressed();
282
  $this->addToAuditEntry( sprintf( _wpsf__( 'Firewall Block Response: %s.' ), $sMessage ) );
 
283
  }
284
  }
285
 
src/processors/ips.php CHANGED
@@ -35,8 +35,8 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
35
  $oFO = $this->getMod();
36
  if ( $oFO->isAutoBlackListFeatureEnabled() ) {
37
  add_filter( $oFO->prefix( 'firewall_die_message' ), array( $this, 'fAugmentFirewallDieMessage' ) );
38
- add_action( $oFO->prefix( 'pre_plugin_shutdown' ), array( $this, 'action_blackMarkIp' ) );
39
- add_action( 'wp_login_failed', array( $this, 'setIpTransgressed' ), 10, 0 );
40
  }
41
 
42
  add_filter( 'authenticate', array( $this, 'addLoginFailedWarningMessage' ), 10000, 1 );
@@ -48,7 +48,7 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
48
  $oFO = $this->getMod();
49
  if ( $oFO->is404Tracking() && is_404() && !$oFO->isVerifiedBot() ) {
50
  if ( $oFO->getOptTracking404() == 'assign-transgression' ) {
51
- $this->setIpTransgressed(); // We now black mark this IP
52
  }
53
  $this->addToAuditEntry(
54
  sprintf( _wpsf__( '404 detected at "%s"' ), $this->loadRequest()->getPath() ),
@@ -153,7 +153,9 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
153
  }
154
 
155
  if ( $bBlackMark ) {
156
- $this->setIpTransgressed(); // We now black mark this IP
 
 
157
 
158
  if ( !is_wp_error( $oUserOrError ) ) {
159
  $oUserOrError = new WP_Error();
@@ -215,7 +217,7 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
215
  }
216
 
217
  if ( $bKill ) {
218
- $sAuditMessage = sprintf( _wpsf__( 'Visitor was found to be on the Black List with IP address "%s" and their connection was killed.' ), $sIp );
219
  $this->setIfLogRequest( false )// don't log traffic from killed requests
220
  ->doStatIncrement( 'ip.connection.killed' )
221
  ->addToAuditEntry( $sAuditMessage, 3, 'black_list_connection_killed' );
@@ -261,59 +263,59 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
261
 
262
  /**
263
  */
264
- public function action_blackMarkIp() {
265
- $this->blackMarkCurrentVisitor();
266
- }
267
-
268
- /**
269
- */
270
- protected function blackMarkCurrentVisitor() {
271
  /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
272
  $oFO = $this->getMod();
273
 
274
- if ( $this->getIfIpTransgressed() && !$oFO->isVerifiedBot() && !$this->isCurrentIpWhitelisted() ) {
275
-
276
- // Never black mark IPs that are on the whitelist
277
- $bCanBlackMark = $oFO->isAutoBlackListFeatureEnabled()
278
- && !$this->getCon()->isPluginDeleting();
279
 
280
- if ( $bCanBlackMark ) {
281
- $this->processIpBlackMark( $this->ip() );
282
- }
283
  }
284
  }
285
 
286
  /**
287
- * @param string $sIp
288
  */
289
- private function processIpBlackMark( $sIp ) {
290
  /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
291
  $oFO = $this->getMod();
292
- $oFO->setOptInsightsAt( 'last_transgression_at' );
293
- $this->doStatIncrement( 'ip.transgression.incremented' );
294
 
295
- $oBlackIp = $this->getAutoBlackListIp( $sIp );
 
 
 
 
296
  if ( $oBlackIp instanceof IPs\EntryVO ) {
 
 
 
 
 
297
 
298
  /** @var IPs\Update $oUp */
299
  $oUp = $this->getDbHandler()->getQueryUpdater();
300
- $oUp->incrementTransgressions( $oBlackIp );
301
-
302
- $sAuditMessage = sprintf(
303
- _wpsf__( 'Auto Black List transgression counter was incremented from %s to %s.' ),
304
- $oBlackIp->getTransgressions() - 1,
305
- $oBlackIp->getTransgressions()
306
- );
307
- $this->addToAuditEntry( $sAuditMessage, 2, 'transgression_counter_increment' );
308
- }
309
- else {
310
- $this->addIpToAutoBlackList( $sIp );
311
-
312
- $sAuditMessage = sprintf(
313
- _wpsf__( 'Auto Black List transgression counter was started for visitor.' ),
314
- $sIp
315
- );
316
- $this->addToAuditEntry( $sAuditMessage, 2, 'transgression_counter_started' );
 
 
 
 
 
317
  }
318
  }
319
 
@@ -472,16 +474,6 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
472
  return $oIp;
473
  }
474
 
475
- /**
476
- * @param string $sIp
477
- */
478
- private function addIpToAutoBlackList( $sIp ) {
479
- $oIp = $this->addIpToList( $sIp, ICWP_WPSF_FeatureHandler_Ips::LIST_AUTO_BLACK, 'auto' );
480
- /** @var IPs\Update $oUp */
481
- $oUp = $this->getDbHandler()->getQueryUpdater();
482
- ( $oIp instanceof IPs\EntryVO ) && $oUp->incrementTransgressions( $oIp );
483
- }
484
-
485
  /**
486
  * ADDITION OF ANY IP TO ANY LIST SHOULD GO THROUGH HERE.
487
  * @param string $sIp
@@ -668,4 +660,30 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
668
  public function getQueryUpdater() {
669
  return parent::getQueryUpdater();
670
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
  }
35
  $oFO = $this->getMod();
36
  if ( $oFO->isAutoBlackListFeatureEnabled() ) {
37
  add_filter( $oFO->prefix( 'firewall_die_message' ), array( $this, 'fAugmentFirewallDieMessage' ) );
38
+ add_action( $oFO->prefix( 'pre_plugin_shutdown' ), array( $this, 'doBlackMarkCurrentVisitor' ) );
39
+ add_action( 'wp_login_failed', array( $oFO, 'setIpTransgressed' ), 10, 0 );
40
  }
41
 
42
  add_filter( 'authenticate', array( $this, 'addLoginFailedWarningMessage' ), 10000, 1 );
48
  $oFO = $this->getMod();
49
  if ( $oFO->is404Tracking() && is_404() && !$oFO->isVerifiedBot() ) {
50
  if ( $oFO->getOptTracking404() == 'assign-transgression' ) {
51
+ $oFO->setIpTransgressed(); // We now black mark this IP
52
  }
53
  $this->addToAuditEntry(
54
  sprintf( _wpsf__( '404 detected at "%s"' ), $this->loadRequest()->getPath() ),
153
  }
154
 
155
  if ( $bBlackMark ) {
156
+ /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
157
+ $oFO = $this->getMod();
158
+ $oFO->setIpTransgressed(); // We now black mark this IP
159
 
160
  if ( !is_wp_error( $oUserOrError ) ) {
161
  $oUserOrError = new WP_Error();
217
  }
218
 
219
  if ( $bKill ) {
220
+ $sAuditMessage = sprintf( _wpsf__( 'Visitor found on the Black List and their connection was killed.' ), $sIp );
221
  $this->setIfLogRequest( false )// don't log traffic from killed requests
222
  ->doStatIncrement( 'ip.connection.killed' )
223
  ->addToAuditEntry( $sAuditMessage, 3, 'black_list_connection_killed' );
263
 
264
  /**
265
  */
266
+ public function doBlackMarkCurrentVisitor() {
 
 
 
 
 
 
267
  /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
268
  $oFO = $this->getMod();
269
 
270
+ if ( $oFO->isAutoBlackListFeatureEnabled() && !$this->getCon()->isPluginDeleting()
271
+ && $this->getIfIpTransgressed() && !$oFO->isVerifiedBot() && !$this->isCurrentIpWhitelisted() ) {
 
 
 
272
 
273
+ $this->processTransgression();
 
 
274
  }
275
  }
276
 
277
  /**
 
278
  */
279
+ private function processTransgression() {
280
  /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
281
  $oFO = $this->getMod();
 
 
282
 
283
+ $oBlackIp = $this->getAutoBlackListIp( $this->ip() );
284
+ if ( !$oBlackIp instanceof IPs\EntryVO ) {
285
+ $oBlackIp = $this->addIpToList( $this->ip(), ICWP_WPSF_FeatureHandler_Ips::LIST_AUTO_BLACK, 'auto' );
286
+ }
287
+
288
  if ( $oBlackIp instanceof IPs\EntryVO ) {
289
+ $nLimit = $oFO->getOptTransgressionLimit();
290
+ $nCurrentTrans = $oBlackIp->transgressions;
291
+ // At this stage we know it's a transgression. But is it an outright block?
292
+ $bBlock = apply_filters( $oFO->prefix( 'ip_block_it' ), false ) || ( $nLimit - $nCurrentTrans == 1 );
293
+ $nToIncrement = $bBlock ? ( $nLimit - $nCurrentTrans ) : 1;
294
 
295
  /** @var IPs\Update $oUp */
296
  $oUp = $this->getDbHandler()->getQueryUpdater();
297
+ $oUp->incrementTransgressions( $oBlackIp, $nToIncrement );
298
+
299
+ $oFO->setOptInsightsAt( 'last_transgression_at' );
300
+ $this->doStatIncrement( 'ip.transgression.incremented' );
301
+
302
+ if ( $bBlock ) {
303
+ $oFO->setOptInsightsAt( 'last_ip_block_at' );
304
+ $sAuditMessage = sprintf(
305
+ _wpsf__( 'IP blocked after incrementing transgressions from %s to %s.' ),
306
+ $nCurrentTrans,
307
+ $oBlackIp->transgressions
308
+ );
309
+ $this->addToAuditEntry( $sAuditMessage, 2, 'ip_transgression_blocked' );
310
+ }
311
+ else {
312
+ $sAuditMessage = sprintf(
313
+ _wpsf__( 'Auto Black List transgression counter was incremented from %s to %s.' ),
314
+ $nCurrentTrans,
315
+ $oBlackIp->transgressions
316
+ );
317
+ $this->addToAuditEntry( $sAuditMessage, 2, 'ip_transgression_increment' );
318
+ }
319
  }
320
  }
321
 
474
  return $oIp;
475
  }
476
 
 
 
 
 
 
 
 
 
 
 
477
  /**
478
  * ADDITION OF ANY IP TO ANY LIST SHOULD GO THROUGH HERE.
479
  * @param string $sIp
660
  public function getQueryUpdater() {
661
  return parent::getQueryUpdater();
662
  }
663
+
664
+ /**
665
+ * @deprecated
666
+ */
667
+ public function action_blackMarkIp() {
668
+ $this->doBlackMarkCurrentVisitor();
669
+ }
670
+
671
+ /**
672
+ * @deprecated
673
+ * @param string $sIp
674
+ */
675
+ private function addIpToAutoBlackList( $sIp ) {
676
+ $oIp = $this->addIpToList( $sIp, ICWP_WPSF_FeatureHandler_Ips::LIST_AUTO_BLACK, 'auto' );
677
+ /** @var IPs\Update $oUp */
678
+ $oUp = $this->getDbHandler()->getQueryUpdater();
679
+ ( $oIp instanceof IPs\EntryVO ) && $oUp->incrementTransgressions( $oIp );
680
+ }
681
+
682
+ /**
683
+ * @deprecated
684
+ * @param string $sIp
685
+ */
686
+ private function processIpBlackMark( $sIp ) {
687
+ $this->processTransgression();
688
+ }
689
  }
src/processors/lockdown.php CHANGED
@@ -10,7 +10,7 @@ class ICWP_WPSF_Processor_Lockdown extends ICWP_WPSF_Processor_BaseWpsf {
10
  /** @var ICWP_WPSF_FeatureHandler_Lockdown $oFO */
11
  $oFO = $this->getMod();
12
 
13
- if ( $oFO->isFileEditingDisabled() ) {
14
  if ( !defined( 'DISALLOW_FILE_EDIT' ) ) {
15
  define( 'DISALLOW_FILE_EDIT', true );
16
  }
@@ -65,8 +65,8 @@ class ICWP_WPSF_Processor_Lockdown extends ICWP_WPSF_Processor_BaseWpsf {
65
  public function disableXmlrpc() {
66
  /** @var ICWP_WPSF_FeatureHandler_Lockdown $oFO */
67
  $oFO = $this->getMod();
68
- $oFO->setOptInsightsAt( 'xml_block_at' );
69
- $this->setIpTransgressed();
70
  return ( current_filter() == 'xmlrpc_enabled' ) ? false : array();
71
  }
72
 
@@ -153,14 +153,10 @@ class ICWP_WPSF_Processor_Lockdown extends ICWP_WPSF_Processor_BaseWpsf {
153
  * @return array
154
  */
155
  public function disableFileEditing( $aAllCaps, $cap, $aArgs ) {
156
-
157
- $aEditCapabilities = array( 'edit_themes', 'edit_plugins', 'edit_files' );
158
  $sRequestedCapability = $aArgs[ 0 ];
159
-
160
- if ( !in_array( $sRequestedCapability, $aEditCapabilities ) ) {
161
- return $aAllCaps;
162
  }
163
- $aAllCaps[ $sRequestedCapability ] = false;
164
  return $aAllCaps;
165
  }
166
 
10
  /** @var ICWP_WPSF_FeatureHandler_Lockdown $oFO */
11
  $oFO = $this->getMod();
12
 
13
+ if ( $oFO->isOptFileEditingDisabled() ) {
14
  if ( !defined( 'DISALLOW_FILE_EDIT' ) ) {
15
  define( 'DISALLOW_FILE_EDIT', true );
16
  }
65
  public function disableXmlrpc() {
66
  /** @var ICWP_WPSF_FeatureHandler_Lockdown $oFO */
67
  $oFO = $this->getMod();
68
+ $oFO->setOptInsightsAt( 'xml_block_at' )
69
+ ->setIpTransgressed();
70
  return ( current_filter() == 'xmlrpc_enabled' ) ? false : array();
71
  }
72
 
153
  * @return array
154
  */
155
  public function disableFileEditing( $aAllCaps, $cap, $aArgs ) {
 
 
156
  $sRequestedCapability = $aArgs[ 0 ];
157
+ if ( in_array( $sRequestedCapability, [ 'edit_themes', 'edit_plugins', 'edit_files' ] ) ) {
158
+ $aAllCaps[ $sRequestedCapability ] = false;
 
159
  }
 
160
  return $aAllCaps;
161
  }
162
 
src/processors/loginprotect_base.php CHANGED
@@ -72,7 +72,7 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends ICWP_WPSF_Processor
72
 
73
  // LearnPress
74
  add_action( 'learn-press/after-form-login-fields', array( $this, 'printFormItems_LearnPress' ), 100 );
75
- add_action( 'learn-press/before-checkout-form-login-button', array( $this, 'printFormItems_LearnPress' ), 100 );
76
  add_filter( 'learn-press/login-validate-field', array( $this, 'checkReqLogin_LearnPress' ), 100 );
77
  }
78
  }
@@ -115,8 +115,8 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends ICWP_WPSF_Processor
115
  add_action( 'edd_process_register_form', array( $this, 'checkReqRegistration_Edd' ), 10 );
116
 
117
  add_action( 'woocommerce_register_form', array( $this, 'printRegisterFormItems_Woo' ), 10 );
118
- add_action( 'woocommerce_after_checkout_registration_form', array( $this, 'printRegistrationFormItems_Woo' ), 10 );
119
- add_filter( 'woocommerce_process_registration_errors', array( $this, 'checkReqRegistration_Woo' ), 10, 2 );
120
 
121
  // MemberPress - Checkout == Registration
122
  add_action( 'mepr-checkout-before-submit', array( $this, 'printRegisterFormItems_MePr' ), 10 );
@@ -125,14 +125,14 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends ICWP_WPSF_Processor
125
  add_action( 'um_after_register_fields', array( $this, 'printFormItems_UltMem' ), 100 );
126
  add_action( 'um_submit_form_register', array( $this, 'checkReqRegistration_UltMem' ), 5, 0 );
127
  // LearnPress
128
- add_action( 'learn-press/after-form-register-fields', array( $this, 'printFormItems_LearnPress' ), 100 );
129
- add_filter( 'learn-press/register-validate-field', array( $this, 'checkReqRegistration_LearnPress' ), 100, 1 );
130
  }
131
  }
132
 
133
  if ( $b3rdParty && $oFO->isProtect( 'checkout_woo' ) ) {
134
- add_action( 'woocommerce_after_checkout_registration_form', array( $this, 'printRegistrationFormItems_Woo' ), 10 );
135
- add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkReqCheckout_Woo' ), 10, 2 );
136
  }
137
  }
138
 
@@ -535,11 +535,11 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends ICWP_WPSF_Processor
535
 
536
  /**
537
  * see form-billing.php
538
- * @param WC_Checkout $oCheckout
539
  * @return void
540
  */
541
  public function printRegistrationFormItems_Woo( $oCheckout ) {
542
- if ( $oCheckout instanceof WC_Checkout && $oCheckout->is_registration_enabled() ) {
543
  $this->printFormItems();
544
  }
545
  }
@@ -565,13 +565,13 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends ICWP_WPSF_Processor
565
  protected function setLoginAsFailed( $sStatToIncrement ) {
566
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
567
  $oFO = $this->getMod();
568
- $oFO->setOptInsightsAt( 'last_login_block_at' );
 
569
 
570
  remove_filter( 'authenticate', 'wp_authenticate_username_password', 20 ); // wp-includes/user.php
571
  remove_filter( 'authenticate', 'wp_authenticate_email_password', 20 ); // wp-includes/user.php
572
 
573
- $this->doStatIncrement( $sStatToIncrement );
574
- return $this->setIpTransgressed(); // We now black mark this IP
575
  }
576
 
577
  /**
72
 
73
  // LearnPress
74
  add_action( 'learn-press/after-form-login-fields', array( $this, 'printFormItems_LearnPress' ), 100 );
75
+ add_action( 'learn-press/before-checkout-form-login-button', [ $this,'printFormItems_LearnPress' ], 100 );
76
  add_filter( 'learn-press/login-validate-field', array( $this, 'checkReqLogin_LearnPress' ), 100 );
77
  }
78
  }
115
  add_action( 'edd_process_register_form', array( $this, 'checkReqRegistration_Edd' ), 10 );
116
 
117
  add_action( 'woocommerce_register_form', array( $this, 'printRegisterFormItems_Woo' ), 10 );
118
+ add_action( 'woocommerce_after_checkout_registration_form', [ $this,'printRegistrationFormItems_Woo' ], 10 );
119
+ add_filter( 'woocommerce_process_registration_errors', [ $this, 'checkReqRegistration_Woo' ], 10, 2 );
120
 
121
  // MemberPress - Checkout == Registration
122
  add_action( 'mepr-checkout-before-submit', array( $this, 'printRegisterFormItems_MePr' ), 10 );
125
  add_action( 'um_after_register_fields', array( $this, 'printFormItems_UltMem' ), 100 );
126
  add_action( 'um_submit_form_register', array( $this, 'checkReqRegistration_UltMem' ), 5, 0 );
127
  // LearnPress
128
+ add_action( 'learn-press/after-form-register-fields', [ $this, 'printFormItems_LearnPress' ], 100 );
129
+ add_filter( 'learn-press/register-validate-field', [ $this,'checkReqRegistration_LearnPress' ], 100, 1 );
130
  }
131
  }
132
 
133
  if ( $b3rdParty && $oFO->isProtect( 'checkout_woo' ) ) {
134
+ add_action( 'woocommerce_after_checkout_registration_form', [ $this,'printRegistrationFormItems_Woo' ], 10 );
135
+ add_action( 'woocommerce_after_checkout_validation', [ $this, 'checkReqCheckout_Woo' ], 10, 2 );
136
  }
137
  }
138
 
535
 
536
  /**
537
  * see form-billing.php
538
+ * @param \WC_Checkout $oCheckout
539
  * @return void
540
  */
541
  public function printRegistrationFormItems_Woo( $oCheckout ) {
542
+ if ( $oCheckout instanceof \WC_Checkout && $oCheckout->is_registration_enabled() ) {
543
  $this->printFormItems();
544
  }
545
  }
565
  protected function setLoginAsFailed( $sStatToIncrement ) {
566
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
567
  $oFO = $this->getMod();
568
+ $oFO->setOptInsightsAt( 'last_login_block_at' )
569
+ ->setIpTransgressed();
570
 
571
  remove_filter( 'authenticate', 'wp_authenticate_username_password', 20 ); // wp-includes/user.php
572
  remove_filter( 'authenticate', 'wp_authenticate_email_password', 20 ); // wp-includes/user.php
573
 
574
+ return $this->doStatIncrement( $sStatToIncrement );
 
575
  }
576
 
577
  /**
src/processors/loginprotect_gasp.php CHANGED
@@ -77,8 +77,8 @@ class ICWP_WPSF_Processor_LoginProtect_Gasp extends ICWP_WPSF_Processor_LoginPro
77
  if ( !$bValid ) {
78
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
79
  $oFO = $this->getMod();
80
- $oFO->setOptInsightsAt( sprintf( 'last_%s_block_at', $sActionAttempted ) );
81
- $this->setIpTransgressed(); // We now black mark this IP
82
  throw new \Exception( $sError );
83
  }
84
  }
@@ -123,8 +123,8 @@ class ICWP_WPSF_Processor_LoginProtect_Gasp extends ICWP_WPSF_Processor_LoginPro
123
  if ( !$bValid ) {
124
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
125
  $oFO = $this->getMod();
126
- $oFO->setOptInsightsAt( sprintf( 'last_%s_block_at', $sActionAttempted ) );
127
- $this->setIpTransgressed(); // We now black mark this IP
128
  throw new \Exception( $sDieMessage );
129
  }
130
 
77
  if ( !$bValid ) {
78
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
79
  $oFO = $this->getMod();
80
+ $oFO->setOptInsightsAt( sprintf( 'last_%s_block_at', $sActionAttempted ) )
81
+ ->setIpTransgressed();
82
  throw new \Exception( $sError );
83
  }
84
  }
123
  if ( !$bValid ) {
124
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
125
  $oFO = $this->getMod();
126
+ $oFO->setOptInsightsAt( sprintf( 'last_%s_block_at', $sActionAttempted ) )
127
+ ->setIpTransgressed(); // We now black mark this IP
128
  throw new \Exception( $sDieMessage );
129
  }
130
 
src/processors/plugin_badge.php CHANGED
@@ -54,7 +54,8 @@ class ICWP_WPSF_Processor_Plugin_Badge extends ICWP_WPSF_Processor_BaseWpsf {
54
  public function addPluginBadgeWidget() {
55
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
56
  $oFO = $this->getMod();
57
- if ( !empty( $oFO ) && $this->loadWp()->getWordpressIsAtLeastVersion( '4.6.0' ) ) {
 
58
  $oWidget = new ICWP_WPSF_Processor_Plugin_BadgeWidget( $oFO );
59
  register_widget( $oWidget );
60
  }
54
  public function addPluginBadgeWidget() {
55
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
56
  $oFO = $this->getMod();
57
+ if ( !empty( $oFO ) && $this->loadWp()->getWordpressIsAtLeastVersion( '4.6.0' )
58
+ && !class_exists( 'Tribe_WP_Widget_Factory' ) ) {
59
  $oWidget = new ICWP_WPSF_Processor_Plugin_BadgeWidget( $oFO );
60
  register_widget( $oWidget );
61
  }
src/processors/plugin_badgewidget.php CHANGED
@@ -9,6 +9,16 @@ class ICWP_WPSF_Processor_Plugin_BadgeWidget extends ICWP_WPSF_WpWidget {
9
  * @param ICWP_WPSF_FeatureHandler_Base $oMod
10
  */
11
  public function __construct( $oMod ) {
 
 
 
 
 
 
 
 
 
 
12
  $this->setMod( $oMod );
13
  parent::__construct(
14
  $oMod->prefixOptionKey( 'plugin_badge' ),
9
  * @param ICWP_WPSF_FeatureHandler_Base $oMod
10
  */
11
  public function __construct( $oMod ) {
12
+ if ( empty( $oMod ) ) {
13
+ try {
14
+ $oMod = ICWP_WPSF_Shield_Security::GetInstance()
15
+ ->getController()
16
+ ->getModule( 'plugin' );
17
+ }
18
+ catch ( \Exception $oE ) {
19
+ return;
20
+ }
21
+ }
22
  $this->setMod( $oMod );
23
  parent::__construct(
24
  $oMod->prefixOptionKey( 'plugin_badge' ),
src/processors/usermanagement_sessions.php CHANGED
@@ -8,7 +8,7 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_Processor_Ba
8
  if ( $this->isReadyToRun() ) {
9
  parent::run();
10
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
11
- add_filter( 'auth_cookie_expiration', array( $this, 'setTimeoutCookieExpiration_Filter' ), 100, 1 );
12
  }
13
  }
14
 
@@ -161,44 +161,50 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_Processor_Ba
161
  }
162
 
163
  /**
164
- * @return \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO[]
 
 
 
 
 
 
 
165
  */
166
  public function getActiveSessions() {
 
 
 
 
 
 
 
167
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
168
  $oFO = $this->getMod();
169
  /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Select $oSel */
170
  $oSel = $oFO->getSessionsProcessor()->getDbHandler()->getQuerySelector();
171
 
172
- if ( $oFO->hasSessionTimeoutInterval() ) {
173
  $oSel->filterByLoginNotExpired( $this->getLoginExpiredBoundary() );
174
  }
175
  if ( $oFO->hasSessionIdleTimeout() ) {
176
  $oSel->filterByLoginNotIdleExpired( $this->getLoginIdleExpiredBoundary() );
177
  }
178
-
179
- /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO[] $aS */
180
- $aS = $oSel->query();
181
- return $aS;
182
  }
183
 
184
  /**
185
  * @return int
186
  */
187
- public function getCountActiveSessions() {
188
- return count( $this->getActiveSessions() );
189
- }
190
-
191
- /**
192
- * @return int
193
- */
194
- public function getLoginExpiredBoundary() {
195
- return $this->time() - $this->loadWp()->getAuthCookieExpiration();
196
  }
197
 
198
  /**
199
  * @return int
200
  */
201
- public function getLoginIdleExpiredBoundary() {
202
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
203
  $oFO = $this->getMod();
204
  return $this->time() - $oFO->getIdleTimeoutInterval();
@@ -220,8 +226,8 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_Processor_Ba
220
  $nTime = $this->time();
221
 
222
  // timeout interval
223
- if ( $oFO->hasSessionTimeoutInterval() && ( $nTime - $oSess->logged_in_at > $oFO->getSessionTimeoutInterval() ) ) {
224
- $nDays = (int)( $oFO->getSessionTimeoutInterval()/DAY_IN_SECONDS );
225
  throw new \Exception(
226
  sprintf(
227
  _wpsf__( 'User session has expired after %s' ),
@@ -268,17 +274,17 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_Processor_Ba
268
  }
269
 
270
  /**
271
- * @param integer $nTimeout
272
- * @return integer
273
  */
274
- public function setTimeoutCookieExpiration_Filter( $nTimeout ) {
275
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
276
  $oFO = $this->getMod();
277
- return $oFO->hasSessionTimeoutInterval() ? $oFO->getSessionTimeoutInterval() : $nTimeout;
278
  }
279
 
280
  /**
281
- * @param WP_User $oUser
282
  */
283
  protected function enforceSessionLimits( $oUser ) {
284
 
8
  if ( $this->isReadyToRun() ) {
9
  parent::run();
10
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
11
+ add_filter( 'auth_cookie_expiration', array( $this, 'setMaxAuthCookieExpiration' ), 100, 1 );
12
  }
13
  }
14
 
161
  }
162
 
163
  /**
164
+ * @return int
165
+ */
166
+ public function countActiveSessions() {
167
+ return $this->getActiveSessionsQuerySelector()->count();
168
+ }
169
+
170
+ /**
171
+ * @return \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO[]|mixed
172
  */
173
  public function getActiveSessions() {
174
+ return $this->getActiveSessionsQuerySelector()->query();
175
+ }
176
+
177
+ /**
178
+ * @return \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Select
179
+ */
180
+ private function getActiveSessionsQuerySelector() {
181
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
182
  $oFO = $this->getMod();
183
  /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Select $oSel */
184
  $oSel = $oFO->getSessionsProcessor()->getDbHandler()->getQuerySelector();
185
 
186
+ if ( $oFO->hasMaxSessionTimeout() ) {
187
  $oSel->filterByLoginNotExpired( $this->getLoginExpiredBoundary() );
188
  }
189
  if ( $oFO->hasSessionIdleTimeout() ) {
190
  $oSel->filterByLoginNotIdleExpired( $this->getLoginIdleExpiredBoundary() );
191
  }
192
+ return $oSel;
 
 
 
193
  }
194
 
195
  /**
196
  * @return int
197
  */
198
+ private function getLoginExpiredBoundary() {
199
+ /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
200
+ $oFO = $this->getMod();
201
+ return $this->time() - $oFO->getMaxSessionTime();
 
 
 
 
 
202
  }
203
 
204
  /**
205
  * @return int
206
  */
207
+ private function getLoginIdleExpiredBoundary() {
208
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
209
  $oFO = $this->getMod();
210
  return $this->time() - $oFO->getIdleTimeoutInterval();
226
  $nTime = $this->time();
227
 
228
  // timeout interval
229
+ if ( $oFO->hasMaxSessionTimeout() && ( $nTime - $oSess->logged_in_at > $oFO->getMaxSessionTime() ) ) {
230
+ $nDays = (int)( $oFO->getMaxSessionTime()/DAY_IN_SECONDS );
231
  throw new \Exception(
232
  sprintf(
233
  _wpsf__( 'User session has expired after %s' ),
274
  }
275
 
276
  /**
277
+ * @param int $nTimeout
278
+ * @return int
279
  */
280
+ public function setMaxAuthCookieExpiration( $nTimeout ) {
281
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
282
  $oFO = $this->getMod();
283
+ return $oFO->hasMaxSessionTimeout() ? min( $nTimeout, $oFO->getMaxSessionTime() ) : $nTimeout;
284
  }
285
 
286
  /**
287
+ * @param \WP_User $oUser
288
  */
289
  protected function enforceSessionLimits( $oUser ) {
290
 
templates/twig/wpadmin_pages/insights_new/config/index.twig CHANGED
@@ -15,7 +15,7 @@
15
  <div class="alert alert-danger">Potential danger</div>
16
  </div>
17
  <div class="col-sm-2">
18
- <div class="alert alert-info">Information</div>
19
  </div>
20
  </div>
21
  <div class="row">
15
  <div class="alert alert-danger">Potential danger</div>
16
  </div>
17
  <div class="col-sm-2">
18
+ <div class="alert alert-primary">Information</div>
19
  </div>
20
  </div>
21
  <div class="row">
templates/twig/wpadmin_pages/insights_new/config/module_summaries.twig CHANGED
@@ -14,7 +14,7 @@
14
  <tr class="row-{{ opt_key }} row-key_opt
15
 
16
  {% if opt.weight|default( 2 ) == 0 %}
17
- table-info
18
  {% else %}
19
  {% if opt.enabled %}
20
  {% if opt.weight|default( 2 ) == 1 %}
14
  <tr class="row-{{ opt_key }} row-key_opt
15
 
16
  {% if opt.weight|default( 2 ) == 0 %}
17
+ table-secondary
18
  {% else %}
19
  {% if opt.enabled %}
20
  {% if opt.weight|default( 2 ) == 1 %}
templates/twig/wpadmin_pages/insights_new/insights/index.twig CHANGED
@@ -40,7 +40,7 @@
40
  <div class="alert alert-danger">Potential danger</div>
41
  </div>
42
  <div class="col-sm-2">
43
- <div class="alert alert-info">Information</div>
44
  </div>
45
  </div>
46
  <div class="row">
40
  <div class="alert alert-danger">Potential danger</div>
41
  </div>
42
  <div class="col-sm-2">
43
+ <div class="alert alert-secondary">Information</div>
44
  </div>
45
  </div>
46
  <div class="row">