Shield Security for WordPress - Version 11.1.1

Version Description

Download this release

Release Info

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

Code changes from version 11.1.0 to 11.1.1

Files changed (52) hide show
  1. .htaccess +0 -4
  2. cl.json +36 -0
  3. icwp-wpsf.php +1 -1
  4. plugin-spec.php +3 -3
  5. readme.txt +1 -1
  6. resources/css/plugin.css +1 -1
  7. resources/images/shield/banner-2FA.png +0 -0
  8. src/config/feature-admin_access_restriction.php +4 -4
  9. src/config/feature-sessions.php +1 -1
  10. src/lib/src/Controller/Controller.php +10 -5
  11. src/lib/src/Modules/Base/Options.php +0 -7
  12. src/lib/src/Modules/Base/Options/OptValueSanitize.php +7 -7
  13. src/lib/src/Modules/BaseShield/ModCon.php +12 -4
  14. src/lib/src/Modules/Email/Processor.php +3 -1
  15. src/lib/src/Modules/Events/Lib/UI/BuildDataForStats.php +125 -0
  16. src/lib/src/Modules/Events/UI.php +9 -95
  17. src/lib/src/Modules/HackGuard/Debug.php +7 -1
  18. src/lib/src/Modules/HackGuard/Lib/FileLocker/FileLockerController.php +7 -3
  19. src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Load.php +5 -5
  20. src/lib/src/Modules/Headers/Insights/OverviewCards.php +3 -4
  21. src/lib/src/Modules/Headers/ModCon.php +4 -0
  22. src/lib/src/Modules/Headers/Strings.php +27 -24
  23. src/lib/src/Modules/IPs/BotTrack/TrackFakeWebCrawler.php +1 -1
  24. src/lib/src/Modules/IPs/Components/QueryIpBlock.php +1 -1
  25. src/lib/src/Modules/IPs/Components/QueryRemainingOffenses.php +1 -1
  26. src/lib/src/Modules/IPs/Lib/BlacklistHandler.php +1 -1
  27. src/lib/src/Modules/IPs/Lib/Bots/BotEventListener.php +1 -3
  28. src/lib/src/Modules/IPs/Lib/Bots/EventListener.php +0 -80
  29. src/lib/src/Modules/IPs/Lib/IpAnalyse/BuildDisplay.php +3 -3
  30. src/lib/src/Modules/IPs/Lib/Ops/AddIp.php +2 -2
  31. src/lib/src/Modules/IPs/Lib/Ops/LookupIpOnList.php +2 -2
  32. src/lib/src/Modules/IPs/Lib/ProcessOffenses.php +1 -1
  33. src/lib/src/Modules/Insights/UI.php +12 -1
  34. src/lib/src/Modules/Integrations/Lib/Spam/Handlers/Helpers/NinjaForms_ShieldSpamAction.php +1 -1
  35. src/lib/src/Modules/Integrations/Lib/Spam/Handlers/WpForo.php +2 -2
  36. src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php +8 -11
  37. src/lib/src/Modules/Plugin/Components/PluginBadge.php +3 -3
  38. src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/BaseCapabilitiesRestrict.php +1 -1
  39. src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php +8 -2
  40. src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php +3 -4
  41. src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php +58 -0
  42. src/lib/src/Modules/SecurityAdmin/ModCon.php +9 -9
  43. src/lib/src/Modules/SecurityAdmin/Strings.php +6 -6
  44. src/lib/src/Utilities/Htaccess/RootHtaccess.php +64 -0
  45. src/lib/vendor/composer/autoload_classmap.php +4 -0
  46. src/lib/vendor/composer/autoload_static.php +4 -0
  47. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Request.php +14 -1
  48. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Platform/Detection.php +31 -0
  49. templates/twig/components/events/stats/stat_box.twig +3 -3
  50. templates/twig/components/events/stats/stats_collection.twig +8 -4
  51. templates/twig/pages/login_intent/index.twig +3 -4
  52. templates/twig/wpadmin_pages/insights/base.twig +1 -1
.htaccess DELETED
@@ -1,4 +0,0 @@
1
- Order Allow,Deny
2
- <FilesMatch "^.*\.(css|js|png|jpg|svg)$">
3
- Allow from all
4
- </FilesMatch>
 
 
 
 
cl.json CHANGED
@@ -68,6 +68,42 @@
68
  "type": "fixed",
69
  "title": "Exclusions for unrecognised file scanner weren't stored correctly in the case of regular expressions.",
70
  "description": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
  ]
73
  },
68
  "type": "fixed",
69
  "title": "Exclusions for unrecognised file scanner weren't stored correctly in the case of regular expressions.",
70
  "description": []
71
+ },
72
+ {
73
+ "type": "fixed",
74
+ "title": "In some rare scenarios, user sessions wouldn't be properly created and user automatically logged-out.",
75
+ "description": [],
76
+ "patch": "11.1.1"
77
+ },
78
+ {
79
+ "type": "fixed",
80
+ "title": "WP Config FileLocker bug not correctly maintaining its state and resulting in locks not being created.",
81
+ "description": [],
82
+ "patch": "11.1.1"
83
+ },
84
+ {
85
+ "type": "fixed",
86
+ "title": "The .htaccess file in the root of the Shield plugin directory is only created if its supported.",
87
+ "description": [],
88
+ "patch": "11.1.1"
89
+ },
90
+ {
91
+ "type": "fixed",
92
+ "title": "Whitelabel settings were misleading and didn't properly update the dashboard log.",
93
+ "description": [],
94
+ "patch": "11.1.1"
95
+ },
96
+ {
97
+ "type": "fixed",
98
+ "title": "SPAM detection for Ninja Forms would report as SPAM when not SPAM.",
99
+ "description": [],
100
+ "patch": "11.1.1"
101
+ },
102
+ {
103
+ "type": "fixed",
104
+ "title": "wpForo integration produced a PHP Warning in certain circumstances.",
105
+ "description": [],
106
+ "patch": "11.1.1"
107
  }
108
  ]
109
  },
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 11.1.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 11.1.1
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
plugin-spec.php CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "11.1.0",
4
- "release_timestamp": 1617870687,
5
- "build": "202104.0801",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
1
  {
2
  "properties": {
3
+ "version": "11.1.1",
4
+ "release_timestamp": 1618305000,
5
+ "build": "202104.1301",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
readme.txt CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.5.2
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.7
11
- Stable tag: 11.1.0
12
  Security against hackers and brute force bots with firewall, login security hiding and hardening, Antispam, Audit Trail, Live Traffic, and much more...
13
 
14
  == Description ==
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.7
11
+ Stable tag: 11.1.1
12
  Security against hackers and brute force bots with firewall, login security hiding and hardening, Antispam, Audit Trail, Live Traffic, and much more...
13
 
14
  == Description ==
resources/css/plugin.css CHANGED
@@ -1583,7 +1583,7 @@ body.folded #FooterBannerGoPro {
1583
  text-align: center;
1584
  }
1585
  .stat_box .card-body {
1586
- background-color: #c3c3d6;
1587
  }
1588
  .stat_box .stat_count {
1589
  font-size: 3rem;
1583
  text-align: center;
1584
  }
1585
  .stat_box .card-body {
1586
+ background-color: #ffffff;
1587
  }
1588
  .stat_box .stat_count {
1589
  font-size: 3rem;
resources/images/shield/banner-2FA.png ADDED
Binary file
src/config/feature-admin_access_restriction.php CHANGED
@@ -368,8 +368,8 @@
368
  "type": "text",
369
  "link_info": "",
370
  "link_blog": "",
371
- "name": "Dashboard Logo",
372
- "summary": "Dashboard Logo URL",
373
  "description": "The URL of the logo displayed in the main dashboard. Should be 128x128px"
374
  },
375
  {
@@ -380,8 +380,8 @@
380
  "type": "text",
381
  "link_info": "https://shsec.io/dt",
382
  "link_blog": "",
383
- "name": "Dashboard Logo",
384
- "summary": "Dashboard Logo URL",
385
  "description": "The URL of the logo displayed in the main dashboard. Should be 128x128px"
386
  }
387
  ],
368
  "type": "text",
369
  "link_info": "",
370
  "link_blog": "",
371
+ "name": "Plugin Badge Logo",
372
+ "summary": "Plugin Badge Logo URL",
373
  "description": "The URL of the logo displayed in the main dashboard. Should be 128x128px"
374
  },
375
  {
380
  "type": "text",
381
  "link_info": "https://shsec.io/dt",
382
  "link_blog": "",
383
+ "name": "Dashboard and 2FA Logo",
384
+ "summary": "Dashboard and 2FA Logo URL",
385
  "description": "The URL of the logo displayed in the main dashboard. Should be 128x128px"
386
  }
387
  ],
src/config/feature-sessions.php CHANGED
@@ -64,7 +64,7 @@
64
  "cols_custom": {
65
  "session_id": "varchar(32) NOT NULL DEFAULT ''",
66
  "wp_username": "varchar(255) NOT NULL DEFAULT ''",
67
- "ip": "varchar(60) NOT NULL DEFAULT '0'",
68
  "browser": "varchar(32) NOT NULL DEFAULT ''",
69
  "last_activity_uri": "text NOT NULL DEFAULT ''"
70
  },
64
  "cols_custom": {
65
  "session_id": "varchar(32) NOT NULL DEFAULT ''",
66
  "wp_username": "varchar(255) NOT NULL DEFAULT ''",
67
+ "ip": "varchar(60) NOT NULL DEFAULT ''",
68
  "browser": "varchar(32) NOT NULL DEFAULT ''",
69
  "last_activity_uri": "text NOT NULL DEFAULT ''"
70
  },
src/lib/src/Controller/Controller.php CHANGED
@@ -545,6 +545,11 @@ class Controller extends DynPropertiesClass {
545
  ( new Shield\Crons\DailyCron() )
546
  ->setCon( $this )
547
  ->run();
 
 
 
 
 
548
  }
549
 
550
  /**
@@ -1233,14 +1238,14 @@ class Controller extends DynPropertiesClass {
1233
  }
1234
 
1235
  /**
1236
- * @param bool $bSetIfNeeded
1237
  * @return string
1238
  */
1239
- public function getSessionId( $bSetIfNeeded = true ) {
1240
  if ( empty( self::$sSessionId ) ) {
1241
  $req = Services::Request();
1242
  self::$sSessionId = $req->cookie( $this->getSessionCookieID(), '' );
1243
- if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1244
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1245
  $this->setSessionCookie();
1246
  }
@@ -1248,10 +1253,10 @@ class Controller extends DynPropertiesClass {
1248
  return self::$sSessionId;
1249
  }
1250
 
1251
- public function getUniqueRequestId( bool $bSetIfNeeded = false ) :string {
1252
  if ( !isset( self::$sRequestId ) ) {
1253
  self::$sRequestId = md5(
1254
- $this->getSessionId( $bSetIfNeeded ).Services::IP()->getRequestIp().Services::Request()->ts().wp_rand()
1255
  );
1256
  }
1257
  return self::$sRequestId;
545
  ( new Shield\Crons\DailyCron() )
546
  ->setCon( $this )
547
  ->run();
548
+ if ( Services::WpGeneral()->isCron() ) {
549
+ ( new Shield\Utilities\Htaccess\RootHtaccess() )
550
+ ->setCon( $this )
551
+ ->execute();
552
+ }
553
  }
554
 
555
  /**
1238
  }
1239
 
1240
  /**
1241
+ * @param bool $setIfNeeded
1242
  * @return string
1243
  */
1244
+ public function getSessionId( $setIfNeeded = true ) {
1245
  if ( empty( self::$sSessionId ) ) {
1246
  $req = Services::Request();
1247
  self::$sSessionId = $req->cookie( $this->getSessionCookieID(), '' );
1248
+ if ( empty( self::$sSessionId ) && $setIfNeeded ) {
1249
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1250
  $this->setSessionCookie();
1251
  }
1253
  return self::$sSessionId;
1254
  }
1255
 
1256
+ public function getUniqueRequestId( bool $setIfNeeded = false ) :string {
1257
  if ( !isset( self::$sRequestId ) ) {
1258
  self::$sRequestId = md5(
1259
+ $this->getSessionId( $setIfNeeded ).Services::IP()->getRequestIp().Services::Request()->ts().wp_rand()
1260
  );
1261
  }
1262
  return self::$sRequestId;
src/lib/src/Modules/Base/Options.php CHANGED
@@ -585,13 +585,6 @@ class Options {
585
  return $raw[ 'requirements' ] ?? [];
586
  }
587
 
588
- /**
589
- * @deprecated 11.0
590
- */
591
- protected function getRawData_MenuItems() :array {
592
- return $this->getRawData_FullFeatureConfig()[ 'menu_items' ] ?? [];
593
- }
594
-
595
  public function getRawData_SingleOption( string $key ) :array {
596
  foreach ( $this->getRawData_AllOptions() as $opt ) {
597
  if ( isset( $opt[ 'key' ] ) && ( $key == $opt[ 'key' ] ) ) {
585
  return $raw[ 'requirements' ] ?? [];
586
  }
587
 
 
 
 
 
 
 
 
588
  public function getRawData_SingleOption( string $key ) :array {
589
  foreach ( $this->getRawData_AllOptions() as $opt ) {
590
  if ( isset( $opt[ 'key' ] ) && ( $key == $opt[ 'key' ] ) ) {
src/lib/src/Modules/Base/Options/OptValueSanitize.php CHANGED
@@ -16,15 +16,15 @@ class OptValueSanitize {
16
  * @throws \Exception
17
  */
18
  public function run( $sKey, $mVal ) {
19
- $oOpts = $this->getOptions();
20
- $aRawOption = $oOpts->getRawData_SingleOption( $sKey );
21
 
22
- if ( !in_array( $sKey, $oOpts->getOptionsKeys() ) ) {
23
  throw new \Exception( sprintf( 'Not a valid option key for module: %s', $sKey ) );
24
  }
25
 
26
  $validValue = false;
27
- switch ( $oOpts->getOptionType( $sKey ) ) {
28
 
29
  case 'boolean':
30
  $validValue = is_bool( $mVal );
@@ -47,8 +47,8 @@ class OptValueSanitize {
47
  break;
48
 
49
  case 'text':
50
- if ( is_scalar( $mVal ) ) {
51
- $validValue = is_null( $mVal ) || is_scalar( $mVal );
52
  $mVal = (string)$mVal;
53
  }
54
  break;
@@ -65,7 +65,7 @@ class OptValueSanitize {
65
  function ( $aValueOption ) {
66
  return $aValueOption[ 'value_key' ];
67
  },
68
- $aRawOption[ 'value_options' ]
69
  )
70
  ) ) === 0;
71
  }
16
  * @throws \Exception
17
  */
18
  public function run( $sKey, $mVal ) {
19
+ $opts = $this->getOptions();
20
+ $raw = $opts->getRawData_SingleOption( $sKey );
21
 
22
+ if ( !in_array( $sKey, $opts->getOptionsKeys() ) ) {
23
  throw new \Exception( sprintf( 'Not a valid option key for module: %s', $sKey ) );
24
  }
25
 
26
  $validValue = false;
27
+ switch ( $opts->getOptionType( $sKey ) ) {
28
 
29
  case 'boolean':
30
  $validValue = is_bool( $mVal );
47
  break;
48
 
49
  case 'text':
50
+ if ( is_null( $mVal ) || is_scalar( $mVal ) ) {
51
+ $validValue = true;
52
  $mVal = (string)$mVal;
53
  }
54
  break;
65
  function ( $aValueOption ) {
66
  return $aValueOption[ 'value_key' ];
67
  },
68
+ $raw[ 'value_options' ]
69
  )
70
  ) ) === 0;
71
  }
src/lib/src/Modules/BaseShield/ModCon.php CHANGED
@@ -176,9 +176,7 @@ class ModCon extends Base\ModCon {
176
 
177
  $ipID = Services::IP()->getIpDetector()->getIPIdentity();
178
 
179
- $untrustedProviders = apply_filters( 'shield/untrusted_service_providers', [] );
180
-
181
- if ( is_array( $untrustedProviders ) && in_array( $ipID, $untrustedProviders ) ) {
182
  self::$bVisitorIsWhitelisted = false;
183
  }
184
  elseif ( in_array( $ipID, Services::ServiceProviders()->getWpSiteManagementProviders() ) ) {
@@ -189,13 +187,23 @@ class ModCon extends Base\ModCon {
189
  ( new Shield\Modules\IPs\Lib\Ops\LookupIpOnList() )
190
  ->setDbHandler( $this->getCon()->getModule_IPs()->getDbHandler_IPs() )
191
  ->setIP( Services::IP()->getRequestIp() )
192
- ->setListTypeWhite()
193
  ->lookup() instanceof Shield\Databases\IPs\EntryVO;
194
  }
195
  }
196
  return self::$bVisitorIsWhitelisted;
197
  }
198
 
 
 
 
 
 
 
 
 
 
 
199
  public function isVerifiedBot() :bool {
200
  if ( !isset( self::$bIsVerifiedBot ) ) {
201
  $ipID = Services::IP()->getIpDetector()->getIPIdentity();
176
 
177
  $ipID = Services::IP()->getIpDetector()->getIPIdentity();
178
 
179
+ if ( in_array( $ipID, $this->getUntrustedProviders() ) ) {
 
 
180
  self::$bVisitorIsWhitelisted = false;
181
  }
182
  elseif ( in_array( $ipID, Services::ServiceProviders()->getWpSiteManagementProviders() ) ) {
187
  ( new Shield\Modules\IPs\Lib\Ops\LookupIpOnList() )
188
  ->setDbHandler( $this->getCon()->getModule_IPs()->getDbHandler_IPs() )
189
  ->setIP( Services::IP()->getRequestIp() )
190
+ ->setListTypeBypass()
191
  ->lookup() instanceof Shield\Databases\IPs\EntryVO;
192
  }
193
  }
194
  return self::$bVisitorIsWhitelisted;
195
  }
196
 
197
+ public function isTrustedVerifiedBot() :bool {
198
+ return $this->isVerifiedBot()
199
+ && !in_array( Services::IP()->getIpDetector()->getIPIdentity(), $this->getUntrustedProviders() );
200
+ }
201
+
202
+ protected function getUntrustedProviders() :array {
203
+ $untrustedProviders = apply_filters( 'shield/untrusted_service_providers', [] );
204
+ return is_array( $untrustedProviders ) ? $untrustedProviders : [];
205
+ }
206
+
207
  public function isVerifiedBot() :bool {
208
  if ( !isset( self::$bIsVerifiedBot ) ) {
209
  $ipID = Services::IP()->getIpDetector()->getIPIdentity();
src/lib/src/Modules/Email/Processor.php CHANGED
@@ -40,6 +40,8 @@ class Processor extends BaseShield\Processor {
40
  shuffle( $benefits );
41
  }
42
 
 
 
43
  $footer = [
44
  $this->getMod()
45
  ->renderTemplate( '/email/footer.twig', [
@@ -61,7 +63,7 @@ class Processor extends BaseShield\Processor {
61
  ],
62
  'flags' => [
63
  'is_pro' => $con->isPremiumActive(),
64
- 'is_whitelabelled' => $con->getModule_SecAdmin()->isWlEnabled()
65
  ]
66
  ] ),
67
  ];
40
  shuffle( $benefits );
41
  }
42
 
43
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Options $secAdminOpts */
44
+ $secAdminOpts = $con->getModule_SecAdmin()->getOptions();
45
  $footer = [
46
  $this->getMod()
47
  ->renderTemplate( '/email/footer.twig', [
63
  ],
64
  'flags' => [
65
  'is_pro' => $con->isPremiumActive(),
66
+ 'is_whitelabelled' => $secAdminOpts->isEnabledWhitelabel()
67
  ]
68
  ] ),
69
  ];
src/lib/src/Modules/Events/Lib/UI/BuildDataForStats.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Events\Lib\UI;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Events\Select;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Events\ModCon;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Events\Strings;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
+ use FernleafSystems\Wordpress\Services\Services;
10
+
11
+ class BuildDataForStats {
12
+
13
+ use ModConsumer;
14
+
15
+ public function build() :array {
16
+ return [
17
+ 'stats' => $this->buildStats(),
18
+ 'stat_intervals' => [
19
+ 'days_1' => '24 Hours',
20
+ 'days_7' => '7 Days',
21
+ 'months_1' => '1 Month',
22
+ 'lifetime' => 'Lifetime',
23
+ ]
24
+ ];
25
+ }
26
+
27
+ private function buildStats() :array {
28
+ $allStats = [];
29
+
30
+ /** @var ModCon $mod */
31
+ $mod = $this->getMod();
32
+ /** @var Strings $strings */
33
+ $strings = $mod->getStrings();
34
+ foreach ( $this->getAllEvents() as $eventSection ) {
35
+ $stats = [];
36
+ foreach ( $eventSection[ 'events' ] as $event ) {
37
+ $sums = $this->buildSums( $event );
38
+ if ( !empty( array_filter( $sums ) ) ) {
39
+ $stats[ $event ] = [
40
+ 'key' => $event,
41
+ 'name' => $strings->getEventName( $event ),
42
+ 'counts' => $this->buildSums( $event ),
43
+ ];
44
+ }
45
+ }
46
+
47
+ if ( !empty( $stats ) ) {
48
+ $eventSection[ 'events' ] = $stats;
49
+ $allStats[] = $eventSection;
50
+ }
51
+ }
52
+
53
+ return $allStats;
54
+ }
55
+
56
+ private function buildSums( $event ) :array {
57
+ /** @var ModCon $mod */
58
+ $mod = $this->getMod();
59
+ /** @var Select $selector */
60
+ $selector = $mod->getDbHandler_Events()->getQuerySelector();
61
+ $carbon = Services::Request()->carbon( true );
62
+ return array_map(
63
+ 'number_format',
64
+ [
65
+ 'lifetime' => $selector->sumEvent( $event ),
66
+ 'months_1' => $selector
67
+ ->filterByCreatedAt( ( clone $carbon )->subDays( 30 )->startOfDay()->timestamp, '>' )
68
+ ->sumEvent( $event ),
69
+ 'days_7' => $selector
70
+ ->filterByCreatedAt( ( clone $carbon )->subDays( 7 )->startOfDay()->timestamp, '>' )
71
+ ->sumEvent( $event ),
72
+ 'days_1' => $selector
73
+ ->filterByCreatedAt( ( clone $carbon )->subHours( 24 )->timestamp, '>' )
74
+ ->sumEvent( $event ),
75
+ ]
76
+ );
77
+ }
78
+
79
+ private function getAllEvents() :array {
80
+ return [
81
+ [
82
+ 'title' => __( 'IP Offenses' ),
83
+ 'events' => [
84
+ 'ip_offense',
85
+ 'conn_kill',
86
+ 'ip_blocked',
87
+ ]
88
+ ],
89
+ [
90
+ 'title' => __( 'Bot Tracking' ),
91
+ 'events' => [
92
+ 'antibot_fail',
93
+ 'antibot_pass',
94
+ 'bottrack_404',
95
+ 'bottrack_fakewebcrawler',
96
+ 'bottrack_linkcheese',
97
+ 'bottrack_loginfailed',
98
+ 'bottrack_logininvalid',
99
+ 'bottrack_useragent',
100
+ 'bottrack_xmlrpc',
101
+ 'bottrack_invalidscript',
102
+ ]
103
+ ],
104
+ [
105
+ 'title' => __( 'Comment SPAM' ),
106
+ 'events' => [
107
+ 'spam_block_antibot',
108
+ 'spam_block_bot',
109
+ 'spam_block_recaptcha',
110
+ 'spam_block_human',
111
+ ]
112
+ ],
113
+ [
114
+ 'title' => __( 'Login Guard' ),
115
+ 'events' => [
116
+ 'cooldown_fail',
117
+ 'honeypot_fail',
118
+ 'botbox_fail',
119
+ 'login_block',
120
+ '2fa_success',
121
+ ]
122
+ ],
123
+ ];
124
+ }
125
+ }
src/lib/src/Modules/Events/UI.php CHANGED
@@ -4,110 +4,24 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Events;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
7
- use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class UI extends BaseShield\UI {
10
 
11
  public function buildInsightsVars() :array {
12
- $stats = $this->buildStats();
13
- return [
14
- 'flags' => [
15
- 'has_stats' => !empty( $stats )
16
- ],
17
- 'strings' => [
18
- 'no_stats' => __('No stats yet. It wont take long though, so check back here soon.')
19
- ],
20
- 'vars' => [
21
- 'stats' => $stats,
22
- 'stat_intervals' => [
23
- 'days_1' => '24 Hours',
24
- 'days_7' => '7 Days',
25
- 'months_1' => '1 Month',
26
- 'lifetime' => 'Lifetime',
27
- ]
28
- ],
29
- ];
30
- }
31
 
32
- private function buildStats() :array {
33
- $allStats = [];
 
34
 
35
- /** @var ModCon $mod */
36
- $mod = $this->getMod();
37
- /** @var Strings $strings */
38
- $strings = $mod->getStrings();
39
- foreach ( $this->getAllEvents() as $eventSection ) {
40
- $stats = [];
41
- foreach ( $eventSection as $event ) {
42
- $sums = $this->buildSums( $event );
43
- if ( !empty( array_filter( $sums ) ) ) {
44
- $stats[ $event ] = [
45
- 'key' => $event,
46
- 'name' => $strings->getEventName( $event ),
47
- 'counts' => $this->buildSums( $event ),
48
- ];
49
- }
50
- }
51
- if ( !empty( $stats ) ) {
52
- $allStats[] = $stats;
53
- }
54
- }
55
-
56
- return $allStats;
57
- }
58
-
59
- private function buildSums( $event ) :array {
60
- /** @var ModCon $mod */
61
- $mod = $this->getMod();
62
- /** @var Databases\Events\Select $selector */
63
- $selector = $mod->getDbHandler_Events()->getQuerySelector();
64
- $carbon = Services::Request()->carbon( true );
65
- return [
66
- 'lifetime' => $selector->sumEvent( $event ),
67
- 'months_1' => $selector
68
- ->filterByCreatedAt( ( clone $carbon )->subDays( 30 )->startOfDay()->timestamp, '>' )
69
- ->sumEvent( $event ),
70
- 'days_7' => $selector
71
- ->filterByCreatedAt( ( clone $carbon )->subDays( 7 )->startOfDay()->timestamp, '>' )
72
- ->sumEvent( $event ),
73
- 'days_1' => $selector
74
- ->filterByCreatedAt( ( clone $carbon )->subHours( 24 )->timestamp, '>' )
75
- ->sumEvent( $event ),
76
- ];
77
- }
78
-
79
- private function getAllEvents() :array {
80
  return [
81
- [
82
- 'ip_offense',
83
- 'conn_kill',
84
- 'ip_blocked',
85
- ],
86
- [
87
- 'antibot_fail',
88
- 'antibot_pass',
89
- 'bottrack_404',
90
- 'bottrack_fakewebcrawler',
91
- 'bottrack_linkcheese',
92
- 'bottrack_loginfailed',
93
- 'bottrack_logininvalid',
94
- 'bottrack_useragent',
95
- 'bottrack_xmlrpc',
96
- 'bottrack_invalidscript',
97
- ],
98
- [
99
- 'spam_block_antibot',
100
- 'spam_block_bot',
101
- 'spam_block_recaptcha',
102
- 'spam_block_human',
103
  ],
104
- [
105
- 'cooldown_fail',
106
- 'honeypot_fail',
107
- 'botbox_fail',
108
- 'login_block',
109
- '2fa_success',
110
  ],
 
111
  ];
112
  }
113
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Events\Lib\UI\BuildDataForStats;
8
 
9
  class UI extends BaseShield\UI {
10
 
11
  public function buildInsightsVars() :array {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ $statsVars = ( new BuildDataForStats() )
14
+ ->setMod( $this->getMod() )
15
+ ->build();
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  return [
18
+ 'flags' => [
19
+ 'has_stats' => !empty( $statsVars[ 'stats' ] )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  ],
21
+ 'strings' => [
22
+ 'no_stats' => __( 'No stats yet. It wont take long though, so check back here soon.' )
 
 
 
 
23
  ],
24
+ 'vars' => $statsVars,
25
  ];
26
  }
27
  }
src/lib/src/Modules/HackGuard/Debug.php CHANGED
@@ -7,6 +7,12 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules;
7
  class Debug extends Modules\Base\Debug {
8
 
9
  public function run() {
10
- die();
 
 
 
 
 
 
11
  }
12
  }
7
  class Debug extends Modules\Base\Debug {
8
 
9
  public function run() {
10
+ die('finish');
11
+ }
12
+
13
+ private function filelocker() {
14
+ /** @var ModCon $mod */
15
+ $mod = $this->getMod();
16
+ $mod->getFileLocker()->processFileLocks();
17
  }
18
  }
src/lib/src/Modules/HackGuard/Lib/FileLocker/FileLockerController.php CHANGED
@@ -38,7 +38,13 @@ class FileLockerController {
38
 
39
  public function processFileLocks() {
40
  if ( !$this->getCon()->plugin_deactivating && !$this->getCon()->is_my_upgrade ) {
41
- $this->isFileLockerStateChanged() ? $this->deleteAllLocks() : $this->runAnalysis();
 
 
 
 
 
 
42
  }
43
  }
44
 
@@ -189,8 +195,6 @@ class FileLockerController {
189
  * @throws \Exception
190
  */
191
  private function getFile( string $fileKey ) :File {
192
- $file = null;
193
-
194
  $isSplitWpUrl = false; // TODO: is split URL?
195
  $maxPaths = 1;
196
  switch ( $fileKey ) {
38
 
39
  public function processFileLocks() {
40
  if ( !$this->getCon()->plugin_deactivating && !$this->getCon()->is_my_upgrade ) {
41
+ if ( $this->isFileLockerStateChanged() ) {
42
+ $this->deleteAllLocks();
43
+ $this->setState( [] );
44
+ }
45
+ else {
46
+ $this->runAnalysis();
47
+ }
48
  }
49
  }
50
 
195
  * @throws \Exception
196
  */
197
  private function getFile( string $fileKey ) :File {
 
 
198
  $isSplitWpUrl = false; // TODO: is split URL?
199
  $maxPaths = 1;
200
  switch ( $fileKey ) {
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Load.php CHANGED
@@ -12,13 +12,13 @@ class Load extends BaseAction {
12
  * @throws \Exception
13
  */
14
  public function run() {
15
- $oStore = $this->getNewStore();
16
 
17
- foreach ( [ $oStore->getSnapStorePath(), $oStore->getSnapStoreMetaPath() ] as $sPath ) {
18
- if ( !Services::WpFs()->exists( $sPath ) ) {
19
- throw new \Exception( 'Critical store file does not exist: '.$sPath );
20
  }
21
  }
22
- return $oStore;
23
  }
24
  }
12
  * @throws \Exception
13
  */
14
  public function run() {
15
+ $store = $this->getNewStore();
16
 
17
+ foreach ( [ $store->getSnapStorePath(), $store->getSnapStoreMetaPath() ] as $path ) {
18
+ if ( !Services::WpFs()->exists( $path ) ) {
19
+ throw new \Exception( 'Critical store file does not exist: '.$path );
20
  }
21
  }
22
+ return $store;
23
  }
24
  }
src/lib/src/Modules/Headers/Insights/OverviewCards.php CHANGED
@@ -36,13 +36,12 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
36
  'href' => $mod->getUrl_DirectLinkToSection( 'section_security_headers' ),
37
  ];
38
 
39
- $bCsp = $opts->isEnabledContentSecurityPolicy();
40
  $cards[ 'csp' ] = [
41
  'name' => __( 'Content Security Policies', 'wp-simple-firewall' ),
42
- 'state' => $bCsp ? 1 : 0,
43
- 'summary' => $bCsp ?
44
  __( 'Content Security Policy is turned on', 'wp-simple-firewall' )
45
- : __( "Content Security Policies aren't active", 'wp-simple-firewall' ),
46
  'href' => $mod->getUrl_DirectLinkToSection( 'section_content_security_policy' ),
47
  ];
48
  }
36
  'href' => $mod->getUrl_DirectLinkToSection( 'section_security_headers' ),
37
  ];
38
 
 
39
  $cards[ 'csp' ] = [
40
  'name' => __( 'Content Security Policies', 'wp-simple-firewall' ),
41
+ 'state' => $opts->isEnabledContentSecurityPolicy() ? 1 : 0,
42
+ 'summary' => $opts->isEnabledContentSecurityPolicy() ?
43
  __( 'Content Security Policy is turned on', 'wp-simple-firewall' )
44
+ : __( "Content Security Policies aren't active or there are no rules provided", 'wp-simple-firewall' ),
45
  'href' => $mod->getUrl_DirectLinkToSection( 'section_content_security_policy' ),
46
  ];
47
  }
src/lib/src/Modules/Headers/ModCon.php CHANGED
@@ -23,5 +23,9 @@ class ModCon extends BaseShield\ModCon {
23
  },
24
  $opts->getOpt( 'xcsp_custom', [] )
25
  ) ) ) );
 
 
 
 
26
  }
27
  }
23
  },
24
  $opts->getOpt( 'xcsp_custom', [] )
25
  ) ) ) );
26
+
27
+ if ( empty( $opts->getOpt( 'xcsp_custom', [] ) ) ) {
28
+ $opts->setOpt( 'enable_x_content_security_policy', 'N' );
29
+ }
30
  }
31
  }
src/lib/src/Modules/Headers/Strings.php CHANGED
@@ -65,46 +65,49 @@ class Strings extends Base\Strings {
65
  switch ( $key ) {
66
 
67
  case 'enable_headers' :
68
- $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
69
- $sSummary = sprintf( __( 'Enable (or Disable) The %s Module', 'wp-simple-firewall' ), $sModName );
70
- $sDescription = sprintf( __( 'Un-Checking this option will completely disable the %s module.', 'wp-simple-firewall' ), $sModName );
71
  break;
72
 
73
  case 'x_frame' :
74
- $sName = __( 'Block iFrames', 'wp-simple-firewall' );
75
- $sSummary = __( 'Block Remote iFrames Of This Site', 'wp-simple-firewall' );
76
- $sDescription = __( 'The setting prevents any external website from embedding your site in an iFrame.', 'wp-simple-firewall' )
77
  .__( 'This is useful for preventing so-called "ClickJack attacks".', 'wp-simple-firewall' );
78
  break;
79
 
80
  case 'x_referrer_policy' :
81
- $sName = __( 'Referrer Policy', 'wp-simple-firewall' );
82
- $sSummary = __( 'Referrer Policy Header', 'wp-simple-firewall' );
83
- $sDescription = __( 'The Referrer Policy Header allows you to control when and what referral information a browser may pass along with links clicked on your site.', 'wp-simple-firewall' );
84
  break;
85
 
86
  case 'x_xss_protect' :
87
- $sName = __( 'XSS Protection', 'wp-simple-firewall' );
88
- $sSummary = __( 'Employ Built-In Browser XSS Protection', 'wp-simple-firewall' );
89
- $sDescription = __( 'Directs compatible browsers to block what they detect as Reflective XSS attacks.', 'wp-simple-firewall' );
90
  break;
91
 
92
  case 'x_content_type' :
93
- $sName = __( 'Prevent Mime-Sniff', 'wp-simple-firewall' );
94
- $sSummary = __( 'Turn-Off Browser Mime-Sniff', 'wp-simple-firewall' );
95
- $sDescription = __( 'Reduces visitor exposure to malicious user-uploaded content.', 'wp-simple-firewall' );
96
  break;
97
 
98
  case 'enable_x_content_security_policy' :
99
- $sName = sprintf( __( 'Enable %s', 'wp-simple-firewall' ), 'CSP' );
100
- $sSummary = sprintf( __( 'Enable %s', 'wp-simple-firewall' ), __( 'Content Security Policy', 'wp-simple-firewall' ) );
101
- $sDescription = __( 'Allows for permission and restriction of all resources loaded on your site.', 'wp-simple-firewall' );
 
 
 
102
  break;
103
 
104
  case 'xcsp_custom' :
105
- $sName = __( 'Manual Rules', 'wp-simple-firewall' );
106
- $sSummary = __( 'Manual CSP Rules', 'wp-simple-firewall' );
107
- $sDescription = [
108
  '- '.__( 'Take a new line per rule.', 'wp-simple-firewall' ),
109
  '- '.__( 'We provide this feature as-is: to allow you to add custom CSP rules to your site.', 'wp-simple-firewall' ),
110
  '- '.__( "We don't provide support for creating CSP rules and whether they're correct for your site.", 'wp-simple-firewall' ),
@@ -117,9 +120,9 @@ class Strings extends Base\Strings {
117
  }
118
 
119
  return [
120
- 'name' => $sName,
121
- 'summary' => $sSummary,
122
- 'description' => $sDescription,
123
  ];
124
  }
125
  }
65
  switch ( $key ) {
66
 
67
  case 'enable_headers' :
68
+ $name = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
69
+ $summary = sprintf( __( 'Enable (or Disable) The %s Module', 'wp-simple-firewall' ), $sModName );
70
+ $description = sprintf( __( 'Un-Checking this option will completely disable the %s module.', 'wp-simple-firewall' ), $sModName );
71
  break;
72
 
73
  case 'x_frame' :
74
+ $name = __( 'Block iFrames', 'wp-simple-firewall' );
75
+ $summary = __( 'Block Remote iFrames Of This Site', 'wp-simple-firewall' );
76
+ $description = __( 'The setting prevents any external website from embedding your site in an iFrame.', 'wp-simple-firewall' )
77
  .__( 'This is useful for preventing so-called "ClickJack attacks".', 'wp-simple-firewall' );
78
  break;
79
 
80
  case 'x_referrer_policy' :
81
+ $name = __( 'Referrer Policy', 'wp-simple-firewall' );
82
+ $summary = __( 'Referrer Policy Header', 'wp-simple-firewall' );
83
+ $description = __( 'The Referrer Policy Header allows you to control when and what referral information a browser may pass along with links clicked on your site.', 'wp-simple-firewall' );
84
  break;
85
 
86
  case 'x_xss_protect' :
87
+ $name = __( 'XSS Protection', 'wp-simple-firewall' );
88
+ $summary = __( 'Employ Built-In Browser XSS Protection', 'wp-simple-firewall' );
89
+ $description = __( 'Directs compatible browsers to block what they detect as Reflective XSS attacks.', 'wp-simple-firewall' );
90
  break;
91
 
92
  case 'x_content_type' :
93
+ $name = __( 'Prevent Mime-Sniff', 'wp-simple-firewall' );
94
+ $summary = __( 'Turn-Off Browser Mime-Sniff', 'wp-simple-firewall' );
95
+ $description = __( 'Reduces visitor exposure to malicious user-uploaded content.', 'wp-simple-firewall' );
96
  break;
97
 
98
  case 'enable_x_content_security_policy' :
99
+ $name = sprintf( __( 'Enable %s', 'wp-simple-firewall' ), 'CSP' );
100
+ $summary = sprintf( __( 'Enable %s', 'wp-simple-firewall' ), __( 'Content Security Policy', 'wp-simple-firewall' ) );
101
+ $description = [
102
+ __( 'Allows for permission and restriction of all resources loaded on your site.', 'wp-simple-firewall' ),
103
+ __( 'Use this in conjunction with the Manual Rules section - you must supply your own CSP rules.', 'wp-simple-firewall' ),
104
+ ];
105
  break;
106
 
107
  case 'xcsp_custom' :
108
+ $name = __( 'Manual Rules', 'wp-simple-firewall' );
109
+ $summary = __( 'Manual CSP Rules', 'wp-simple-firewall' );
110
+ $description = [
111
  '- '.__( 'Take a new line per rule.', 'wp-simple-firewall' ),
112
  '- '.__( 'We provide this feature as-is: to allow you to add custom CSP rules to your site.', 'wp-simple-firewall' ),
113
  '- '.__( "We don't provide support for creating CSP rules and whether they're correct for your site.", 'wp-simple-firewall' ),
120
  }
121
 
122
  return [
123
+ 'name' => $name,
124
+ 'summary' => $summary,
125
+ 'description' => $description,
126
  ];
127
  }
128
  }
src/lib/src/Modules/IPs/BotTrack/TrackFakeWebCrawler.php CHANGED
@@ -18,7 +18,7 @@ class TrackFakeWebCrawler extends Base {
18
  protected function process() {
19
  /** @var ModCon $mod */
20
  $mod = $this->getMod();
21
- if ( $this->identifiesAsCrawler() && !$mod->isVerifiedBot() ) {
22
  $this->doTransgression();
23
  }
24
  }
18
  protected function process() {
19
  /** @var ModCon $mod */
20
  $mod = $this->getMod();
21
+ if ( $this->identifiesAsCrawler() && !$mod->isTrustedVerifiedBot() ) {
22
  $this->doTransgression();
23
  }
24
  }
src/lib/src/Modules/IPs/Components/QueryIpBlock.php CHANGED
@@ -44,7 +44,7 @@ class QueryIpBlock {
44
  $oIP = ( new IPs\Lib\Ops\LookupIpOnList() )
45
  ->setDbHandler( $mod->getDbHandler_IPs() )
46
  ->setIP( $this->getIP() )
47
- ->setListTypeBlack()
48
  ->setIsIpBlocked( true )
49
  ->lookup();
50
 
44
  $oIP = ( new IPs\Lib\Ops\LookupIpOnList() )
45
  ->setDbHandler( $mod->getDbHandler_IPs() )
46
  ->setIP( $this->getIP() )
47
+ ->setListTypeBlock()
48
  ->setIsIpBlocked( true )
49
  ->lookup();
50
 
src/lib/src/Modules/IPs/Components/QueryRemainingOffenses.php CHANGED
@@ -23,7 +23,7 @@ class QueryRemainingOffenses {
23
  $mod = $this->getMod();
24
  $oBlackIp = ( new IPs\Lib\Ops\LookupIpOnList() )
25
  ->setDbHandler( $mod->getDbHandler_IPs() )
26
- ->setListTypeBlack()
27
  ->setIP( $this->getIP() )
28
  ->lookup( false );
29
 
23
  $mod = $this->getMod();
24
  $oBlackIp = ( new IPs\Lib\Ops\LookupIpOnList() )
25
  ->setDbHandler( $mod->getDbHandler_IPs() )
26
+ ->setListTypeBlock()
27
  ->setIP( $this->getIP() )
28
  ->lookup( false );
29
 
src/lib/src/Modules/IPs/Lib/BlacklistHandler.php CHANGED
@@ -57,7 +57,7 @@ class BlacklistHandler {
57
 
58
  if ( !Services::WpUsers()->isUserLoggedIn() ) {
59
 
60
- if ( !$mod->isVerifiedBot() ) {
61
  if ( $opts->isEnabledTrackXmlRpc() ) {
62
  ( new IPs\BotTrack\TrackXmlRpc() )
63
  ->setMod( $mod )
57
 
58
  if ( !Services::WpUsers()->isUserLoggedIn() ) {
59
 
60
+ if ( !$mod->isTrustedVerifiedBot() ) {
61
  if ( $opts->isEnabledTrackXmlRpc() ) {
62
  ( new IPs\BotTrack\TrackXmlRpc() )
63
  ->setMod( $mod )
src/lib/src/Modules/IPs/Lib/Bots/BotEventListener.php CHANGED
@@ -31,9 +31,7 @@ class BotEventListener {
31
  }
32
 
33
  protected function canRun() :bool {
34
- /** @var ModCon $mod */
35
- $mod = $this->getMod();
36
- return !$mod->isVerifiedBot();
37
  }
38
 
39
  protected function run() {
31
  }
32
 
33
  protected function canRun() :bool {
34
+ return !$this->getMod()->isTrustedVerifiedBot();
 
 
35
  }
36
 
37
  protected function run() {
src/lib/src/Modules/IPs/Lib/Bots/EventListener.php DELETED
@@ -1,80 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots;
4
-
5
- use FernleafSystems\Utilities\Logic\ExecOnce;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
- use FernleafSystems\Wordpress\Services\Services;
9
-
10
- class EventListener {
11
-
12
- use ModConsumer;
13
- use ExecOnce;
14
-
15
- public function fireEventForIP( $ip, $event ) {
16
- $events = $this->getEventsToColumn();
17
-
18
- foreach ( $events as $eventTrigger => $column ) {
19
- if ( $eventTrigger === $event || preg_match( sprintf( '#^%s$#', $eventTrigger ), $event ) ) {
20
- try {
21
- ( new BotSignalsRecord() )
22
- ->setMod( $this->getMod() )
23
- ->setIP( $ip )
24
- ->updateSignalField( $column );
25
- }
26
- catch ( \LogicException $e ) {
27
- error_log( 'Error updating bot signal: '.$e->getMessage() );
28
- }
29
- }
30
- }
31
- }
32
-
33
- protected function canRun() :bool {
34
- /** @var ModCon $mod */
35
- $mod = $this->getMod();
36
- return !$mod->isVerifiedBot();
37
- }
38
-
39
- protected function run() {
40
- add_action( $this->getCon()->prefix( 'event' ), function ( $event ) {
41
- $this->fireEventForIP( Services::IP()->getRequestIp(), $event );
42
- } );
43
- }
44
-
45
- /**
46
- * @return string[]
47
- */
48
- private function getEventsToColumn() :array {
49
- return array_map(
50
- function ( $column ) {
51
- return str_replace( '_at', '', $column ).'_at';
52
- },
53
- [
54
- 'bottrack_notbot' => 'notbot',
55
- 'frontpage_load' => 'frontpage',
56
- 'bottrack_404' => 'bt404',
57
- 'bottrack_fakewebcrawler' => 'btfake',
58
- 'bottrack_linkcheese' => 'btcheese',
59
- 'bottrack_loginfailed' => 'btloginfail',
60
- 'bottrack_useragent' => 'btua',
61
- 'bottrack_xmlrpc' => 'btxml',
62
- 'bottrack_logininvalid' => 'btlogininvalid',
63
- 'bottrack_invalidscript' => 'btinvalidscript',
64
- 'cooldown_fail' => 'cooldown',
65
- 'recaptcha_success' => 'captchapass',
66
- 'request_limit_exceeded' => 'ratelimit',
67
- 'recaptcha_fail' => 'captchafail',
68
- 'spam_block_human' => 'humanspam',
69
- 'comment_markspam' => 'markspam',
70
- 'comment_unmarkspam' => 'unmarkspam',
71
- 'blockparam_.*' => 'firewall',
72
- 'ip_offense' => 'offense',
73
- 'ip_blocked' => 'blocked',
74
- 'ip_unblock' => 'unblocked',
75
- 'ip_bypass' => 'bypass',
76
- 'login_success' => 'auth',
77
- ]
78
- );
79
- }
80
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/IPs/Lib/IpAnalyse/BuildDisplay.php CHANGED
@@ -68,13 +68,13 @@ class BuildDisplay {
68
 
69
  $blockIP = ( new LookupIpOnList() )
70
  ->setDbHandler( $mod->getDbHandler_IPs() )
71
- ->setListTypeBlack()
72
  ->setIP( $ip )
73
  ->lookup( true );
74
 
75
  $bypassIP = ( new LookupIpOnList() )
76
  ->setDbHandler( $mod->getDbHandler_IPs() )
77
- ->setListTypeWhite()
78
  ->setIP( $ip )
79
  ->lookup( true );
80
 
@@ -109,7 +109,7 @@ class BuildDisplay {
109
  $ipEntry = ( new LookupIpOnList() )
110
  ->setDbHandler( $mod->getDbHandler_IPs() )
111
  ->setIP( $ip )
112
- ->setListTypeWhite()
113
  ->lookup();
114
  if ( $ipEntry instanceof Databases\IPs\EntryVO ) {
115
  $ipName = $ipEntry->label;
68
 
69
  $blockIP = ( new LookupIpOnList() )
70
  ->setDbHandler( $mod->getDbHandler_IPs() )
71
+ ->setListTypeBlock()
72
  ->setIP( $ip )
73
  ->lookup( true );
74
 
75
  $bypassIP = ( new LookupIpOnList() )
76
  ->setDbHandler( $mod->getDbHandler_IPs() )
77
+ ->setListTypeBypass()
78
  ->setIP( $ip )
79
  ->lookup( true );
80
 
109
  $ipEntry = ( new LookupIpOnList() )
110
  ->setDbHandler( $mod->getDbHandler_IPs() )
111
  ->setIP( $ip )
112
+ ->setListTypeBypass()
113
  ->lookup();
114
  if ( $ipEntry instanceof Databases\IPs\EntryVO ) {
115
  $ipName = $ipEntry->label;
src/lib/src/Modules/IPs/Lib/Ops/AddIp.php CHANGED
@@ -35,7 +35,7 @@ class AddIp {
35
 
36
  $IP = ( new LookupIpOnList() )
37
  ->setDbHandler( $mod->getDbHandler_IPs() )
38
- ->setListTypeBlack()
39
  ->setIP( $ip )
40
  ->lookup( false );
41
  if ( !$IP instanceof Databases\IPs\EntryVO ) {
@@ -85,7 +85,7 @@ class AddIp {
85
 
86
  $IP = ( new LookupIpOnList() )
87
  ->setDbHandler( $mod->getDbHandler_IPs() )
88
- ->setListTypeBlack()
89
  ->setIP( $sIP )
90
  ->lookup( false );
91
 
35
 
36
  $IP = ( new LookupIpOnList() )
37
  ->setDbHandler( $mod->getDbHandler_IPs() )
38
+ ->setListTypeBlock()
39
  ->setIP( $ip )
40
  ->lookup( false );
41
  if ( !$IP instanceof Databases\IPs\EntryVO ) {
85
 
86
  $IP = ( new LookupIpOnList() )
87
  ->setDbHandler( $mod->getDbHandler_IPs() )
88
+ ->setListTypeBlock()
89
  ->setIP( $sIP )
90
  ->lookup( false );
91
 
src/lib/src/Modules/IPs/Lib/Ops/LookupIpOnList.php CHANGED
@@ -132,7 +132,7 @@ class LookupIpOnList {
132
 
133
  /**
134
  * @return $this
135
- * @deprecated 11.0
136
  */
137
  public function setListTypeBlack() {
138
  $this->listType = 'black';
@@ -141,7 +141,7 @@ class LookupIpOnList {
141
 
142
  /**
143
  * @return $this
144
- * @deprecated 11.0
145
  */
146
  public function setListTypeWhite() {
147
  $this->listType = 'white';
132
 
133
  /**
134
  * @return $this
135
+ * @deprecated 11.1
136
  */
137
  public function setListTypeBlack() {
138
  $this->listType = 'black';
141
 
142
  /**
143
  * @return $this
144
+ * @deprecated 11.1
145
  */
146
  public function setListTypeWhite() {
147
  $this->listType = 'white';
src/lib/src/Modules/IPs/Lib/ProcessOffenses.php CHANGED
@@ -13,7 +13,7 @@ class ProcessOffenses {
13
  use ExecOnce;
14
 
15
  protected function canRun() :bool {
16
- return !$this->getMod()->isVerifiedBot();
17
  }
18
 
19
  protected function run() {
13
  use ExecOnce;
14
 
15
  protected function canRun() :bool {
16
+ return !$this->getMod()->isTrustedVerifiedBot();
17
  }
18
 
19
  protected function run() {
src/lib/src/Modules/Insights/UI.php CHANGED
@@ -201,6 +201,17 @@ class UI extends BaseShield\UI {
201
  __( 'Settings', 'wp-simple-firewall' ), $modsToSearch[ $subNavSection ][ 'name' ] );
202
  }
203
 
 
 
 
 
 
 
 
 
 
 
 
204
  $DP = Services::DataManipulation();
205
  $data = $DP->mergeArraysRecursive(
206
  $this->getBaseDisplayData(),
@@ -214,7 +225,7 @@ class UI extends BaseShield\UI {
214
  'hrefs' => [
215
  'go_pro' => 'https://shsec.io/shieldgoprofeature',
216
  'nav_home' => $mod->getUrl_AdminPage(),
217
- 'img_banner' => $con->urls->forImage( 'pluginlogo_banner-170x40.png' )
218
  ],
219
  'strings' => [
220
  'page_title' => $pageTitle
201
  __( 'Settings', 'wp-simple-firewall' ), $modsToSearch[ $subNavSection ][ 'name' ] );
202
  }
203
 
204
+ /** @var Shield\Modules\SecurityAdmin\Options $secAdminOpts */
205
+ $secAdminOpts = $this->getCon()->getModule_SecAdmin()->getOptions();
206
+ if ( $secAdminOpts->isEnabledWhitelabel() ) {
207
+ $dashboardLogo = ( new Shield\Modules\SecurityAdmin\Lib\WhiteLabel\BuildOptions() )
208
+ ->setMod( $this->getCon()->getModule_SecAdmin() )
209
+ ->build()[ 'url_login2fa_logourl' ];
210
+ }
211
+ else {
212
+ $dashboardLogo = $con->urls->forImage( 'pluginlogo_banner-170x40.png' );
213
+ }
214
+
215
  $DP = Services::DataManipulation();
216
  $data = $DP->mergeArraysRecursive(
217
  $this->getBaseDisplayData(),
225
  'hrefs' => [
226
  'go_pro' => 'https://shsec.io/shieldgoprofeature',
227
  'nav_home' => $mod->getUrl_AdminPage(),
228
+ 'img_banner' => $dashboardLogo
229
  ],
230
  'strings' => [
231
  'page_title' => $pageTitle
src/lib/src/Modules/Integrations/Lib/Spam/Handlers/Helpers/NinjaForms_ShieldSpamAction.php CHANGED
@@ -39,7 +39,7 @@ final class NinjaForms_ShieldSpamAction extends \NF_Abstracts_Action {
39
  * @inheritDoc
40
  */
41
  public function process( $action_settings, $form_id, $data ) {
42
- if ( !$this->shieldNinjaFormsHandler->isSpam() ) {
43
  $data[ 'errors' ][ 'form' ][ 'spam' ] = esc_html__( 'There was an error trying to send your message. Please try again later', 'ninja-forms' );
44
  }
45
  return $data;
39
  * @inheritDoc
40
  */
41
  public function process( $action_settings, $form_id, $data ) {
42
+ if ( $this->shieldNinjaFormsHandler->isSpam() ) {
43
  $data[ 'errors' ][ 'form' ][ 'spam' ] = esc_html__( 'There was an error trying to send your message. Please try again later', 'ninja-forms' );
44
  }
45
  return $data;
src/lib/src/Modules/Integrations/Lib/Spam/Handlers/WpForo.php CHANGED
@@ -6,7 +6,7 @@ class WpForo extends Base {
6
 
7
  protected function run() {
8
  foreach ( $this->getFiltersToMonitor() as $filter ) {
9
- add_filter( $filter, function ( array $args, $forum ) {
10
 
11
  $status = $args[ 'status' ] ?? null;
12
  if ( $status !== 1 && $this->isSpam() ) {
@@ -17,7 +17,7 @@ class WpForo extends Base {
17
  }
18
 
19
  return $args;
20
- }, 1000, 2 );
21
  }
22
  }
23
 
6
 
7
  protected function run() {
8
  foreach ( $this->getFiltersToMonitor() as $filter ) {
9
+ add_filter( $filter, function ( array $args = [] ) {
10
 
11
  $status = $args[ 'status' ] ?? null;
12
  if ( $status !== 1 && $this->isSpam() ) {
17
  }
18
 
19
  return $args;
20
+ }, 1000 );
21
  }
22
  }
23
 
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php CHANGED
@@ -108,20 +108,17 @@ class LoginIntentPage {
108
  );
109
  }
110
 
111
- /**
112
- * @return string
113
- */
114
- private function renderPage() {
115
  $oIC = $this->getMfaCon();
116
  /** @var LoginGuard\ModCon $mod */
117
  $mod = $oIC->getMod();
118
  $con = $oIC->getCon();
119
  $req = Services::Request();
120
 
121
- $aLabels = $con->getLabels();
122
- $sBannerUrl = empty( $aLabels[ 'url_login2fa_logourl' ] ) ? $con->urls->forImage( 'pluginlogo_banner-772x250.png' ) : $aLabels[ 'url_login2fa_logourl' ];
123
  $nTimeRemaining = $mod->getSession()->login_intent_expires_at - $req->ts();
124
- $aDisplayData = [
125
  'strings' => [
126
  'what_is_this' => __( 'What is this?', 'wp-simple-firewall' ),
127
  'page_title' => sprintf( __( '%s Login Verification', 'wp-simple-firewall' ), $con->getHumanName() ),
@@ -136,7 +133,7 @@ class LoginIntentPage {
136
  'what_is_this' => 'https://support.getshieldsecurity.com/support/solutions/articles/3000064840',
137
  ],
138
  'imgs' => [
139
- 'banner' => $sBannerUrl,
140
  'favicon' => $con->urls->forImage( 'pluginlogo_24x24.png' ),
141
  ],
142
  'flags' => [
@@ -150,8 +147,8 @@ class LoginIntentPage {
150
  ];
151
 
152
  // Provide the U2F scripts if required.
153
- if ( $aDisplayData[ 'flags' ][ 'has_u2f' ] ) {
154
- $aDisplayData[ 'head' ] = [
155
  'scripts' => [
156
  [
157
  'src' => $con->urls->forJs( 'u2f-bundle.js' ),
@@ -165,6 +162,6 @@ class LoginIntentPage {
165
 
166
  return $mod->renderTemplate( '/pages/login_intent/index.twig',
167
  Services::DataManipulation()->mergeArraysRecursive(
168
- $mod->getUIHandler()->getBaseDisplayData(), $aDisplayData ), true );
169
  }
170
  }
108
  );
109
  }
110
 
111
+ private function renderPage() :string {
 
 
 
112
  $oIC = $this->getMfaCon();
113
  /** @var LoginGuard\ModCon $mod */
114
  $mod = $oIC->getMod();
115
  $con = $oIC->getCon();
116
  $req = Services::Request();
117
 
118
+ $labels = $con->getLabels();
119
+ $bannerURL = empty( $labels[ 'url_login2fa_logourl' ] ) ? $con->urls->forImage( 'shield/banner-2FA.png' ) : $labels[ 'url_login2fa_logourl' ];
120
  $nTimeRemaining = $mod->getSession()->login_intent_expires_at - $req->ts();
121
+ $data = [
122
  'strings' => [
123
  'what_is_this' => __( 'What is this?', 'wp-simple-firewall' ),
124
  'page_title' => sprintf( __( '%s Login Verification', 'wp-simple-firewall' ), $con->getHumanName() ),
133
  'what_is_this' => 'https://support.getshieldsecurity.com/support/solutions/articles/3000064840',
134
  ],
135
  'imgs' => [
136
+ 'banner' => $bannerURL,
137
  'favicon' => $con->urls->forImage( 'pluginlogo_24x24.png' ),
138
  ],
139
  'flags' => [
147
  ];
148
 
149
  // Provide the U2F scripts if required.
150
+ if ( $data[ 'flags' ][ 'has_u2f' ] ) {
151
+ $data[ 'head' ] = [
152
  'scripts' => [
153
  [
154
  'src' => $con->urls->forJs( 'u2f-bundle.js' ),
162
 
163
  return $mod->renderTemplate( '/pages/login_intent/index.twig',
164
  Services::DataManipulation()->mergeArraysRecursive(
165
+ $mod->getUIHandler()->getBaseDisplayData(), $data ), true );
166
  }
167
  }
src/lib/src/Modules/Plugin/Components/PluginBadge.php CHANGED
@@ -17,9 +17,9 @@ class PluginBadge {
17
  public function run() {
18
  /** @var Plugin\Options $opts */
19
  $opts = $this->getOptions();
20
- $bDisplay = $opts->isOpt( 'display_plugin_badge', 'Y' )
21
- && ( Services::Request()->cookie( $this->getCookieIdBadgeState() ) != 'closed' );
22
- if ( $bDisplay ) {
23
  add_action( 'wp_enqueue_scripts', [ $this, 'includeJquery' ] );
24
  add_action( 'login_enqueue_scripts', [ $this, 'includeJquery' ] );
25
  add_action( 'wp_footer', [ $this, 'printPluginBadge' ], 100 );
17
  public function run() {
18
  /** @var Plugin\Options $opts */
19
  $opts = $this->getOptions();
20
+ $display = $opts->isOpt( 'display_plugin_badge', 'Y' )
21
+ && ( Services::Request()->cookie( $this->getCookieIdBadgeState() ) != 'closed' );
22
+ if ( $display ) {
23
  add_action( 'wp_enqueue_scripts', [ $this, 'includeJquery' ] );
24
  add_action( 'login_enqueue_scripts', [ $this, 'includeJquery' ] );
25
  add_action( 'wp_footer', [ $this, 'printPluginBadge' ], 100 );
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/BaseCapabilitiesRestrict.php CHANGED
@@ -38,7 +38,7 @@ class BaseCapabilitiesRestrict extends Base {
38
  }
39
 
40
  protected function getRestrictedCapabilities() :array {
41
- /** @var WpOptions $opts */
42
  $opts = $this->getOptions();
43
  return $opts->getSecAdminAreaCaps( static::AREA_SLUG );
44
  }
38
  }
39
 
40
  protected function getRestrictedCapabilities() :array {
41
+ /** @var Options $opts */
42
  $opts = $this->getOptions();
43
  return $opts->getSecAdminAreaCaps( static::AREA_SLUG );
44
  }
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php CHANGED
@@ -55,7 +55,7 @@ class SecurityAdminController {
55
  /** @var Options $opts */
56
  $opts = $this->getOptions();
57
  return $this->getMod()->isModOptEnabled() &&
58
- $opts->hasSecurityPIN() && $this->getSecAdminTimeout() > 0;
59
  }
60
 
61
  private function enqueueJS() {
@@ -80,7 +80,8 @@ class SecurityAdminController {
80
  ],
81
  'flags' => [
82
  'restrict_options' => !$isCurrentlySecAdmin && $opts->getAdminAccessArea_Options(),
83
- 'run_checks' => $this->getCon()->getIsPage_PluginAdmin() && $isCurrentlySecAdmin,
 
84
  ],
85
  'strings' => [
86
  'confirm' => __( 'Security Admin session has timed-out.', 'wp-simple-firewall' ).' '.__( 'Click OK to reload and re-authenticate.', 'wp-simple-firewall' ),
@@ -130,6 +131,10 @@ class SecurityAdminController {
130
  return (int)max( 0, $remaining );
131
  }
132
 
 
 
 
 
133
  /**
134
  * @param \WP_User|null $user
135
  * @return bool
@@ -144,6 +149,7 @@ class SecurityAdminController {
144
  }
145
 
146
  public function isCurrentlySecAdmin() :bool {
 
147
  return $this->isRegisteredSecAdminUser( Services::WpUsers()->getCurrentWpUser() )
148
  || $this->getSecAdminTimeRemaining() > 0;
149
  }
55
  /** @var Options $opts */
56
  $opts = $this->getOptions();
57
  return $this->getMod()->isModOptEnabled() &&
58
+ $opts->hasSecurityPIN() && $this->getSecAdminTimeout() > 2;
59
  }
60
 
61
  private function enqueueJS() {
80
  ],
81
  'flags' => [
82
  'restrict_options' => !$isCurrentlySecAdmin && $opts->getAdminAccessArea_Options(),
83
+ 'run_checks' => $this->getCon()->getIsPage_PluginAdmin() && $isCurrentlySecAdmin
84
+ && !$this->isCurrentUserRegisteredSecAdmin(),
85
  ],
86
  'strings' => [
87
  'confirm' => __( 'Security Admin session has timed-out.', 'wp-simple-firewall' ).' '.__( 'Click OK to reload and re-authenticate.', 'wp-simple-firewall' ),
131
  return (int)max( 0, $remaining );
132
  }
133
 
134
+ public function isCurrentUserRegisteredSecAdmin() :bool {
135
+ return $this->isRegisteredSecAdminUser( Services::WpUsers()->getCurrentWpUser() );
136
+ }
137
+
138
  /**
139
  * @param \WP_User|null $user
140
  * @return bool
149
  }
150
 
151
  public function isCurrentlySecAdmin() :bool {
152
+ // TODO: replace with isCurrentUserRegisteredSecAdmin()
153
  return $this->isRegisteredSecAdminUser( Services::WpUsers()->getCurrentWpUser() )
154
  || $this->getSecAdminTimeRemaining() > 0;
155
  }
src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php CHANGED
@@ -73,10 +73,9 @@ class ApplyLabels {
73
  * @return array
74
  */
75
  public function applyPluginLabels( $pluginLabels ) {
76
- /** @var SecurityAdmin\ModCon $mod */
77
- $mod = $this->getMod();
78
-
79
- $labels = $mod->getWhitelabelOptions();
80
 
81
  // these are the old white labelling keys which will be replaced upon final release of white labelling.
82
  $serviceName = $labels[ 'name_main' ];
73
  * @return array
74
  */
75
  public function applyPluginLabels( $pluginLabels ) {
76
+ $labels = ( new BuildOptions() )
77
+ ->setMod( $this->getMod() )
78
+ ->build();
 
79
 
80
  // these are the old white labelling keys which will be replaced upon final release of white labelling.
81
  $serviceName = $labels[ 'name_main' ];
src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\WhiteLabel;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class BuildOptions {
9
+
10
+ use ModConsumer;
11
+
12
+ public function build() :array {
13
+ $opts = $this->getOptions();
14
+ $main = $opts->getOpt( 'wl_pluginnamemain' );
15
+ $menu = $opts->getOpt( 'wl_namemenu' );
16
+ if ( empty( $menu ) ) {
17
+ $menu = $main;
18
+ }
19
+
20
+ return [
21
+ 'name_main' => $main,
22
+ 'name_menu' => $menu,
23
+ 'name_company' => $opts->getOpt( 'wl_companyname' ),
24
+ 'description' => $opts->getOpt( 'wl_description' ),
25
+ 'url_home' => $opts->getOpt( 'wl_homeurl' ),
26
+ 'url_icon' => $this->buildWlImageUrl( 'wl_menuiconurl' ),
27
+ 'url_dashboardlogourl' => $this->buildWlImageUrl( 'wl_dashboardlogourl' ),
28
+ 'url_login2fa_logourl' => $this->buildWlImageUrl( 'wl_login2fa_logourl' ),
29
+ ];
30
+ }
31
+
32
+ /**
33
+ * We cater for 3 options:
34
+ * Full URL
35
+ * Relative path URL: i.e. starts with /
36
+ * Or Plugin image URL i.e. doesn't start with HTTP or /
37
+ * @param string $key
38
+ * @return string
39
+ */
40
+ private function buildWlImageUrl( string $key ) {
41
+ $opts = $this->getOptions();
42
+
43
+ $url = $opts->getOpt( $key );
44
+ if ( empty( $url ) ) {
45
+ $opts->resetOptToDefault( $key );
46
+ $url = $opts->getOpt( $key );
47
+ }
48
+ if ( !empty( $url ) && !Services::Data()->isValidWebUrl( $url ) && strpos( $url, '/' ) !== 0 ) {
49
+ $url = $this->getCon()->urls->forImage( $url );
50
+ if ( empty( $url ) ) {
51
+ $opts->resetOptToDefault( $key );
52
+ $url = $this->getCon()->urls->forImage( $opts->getOpt( $key ) );
53
+ }
54
+ }
55
+
56
+ return $url;
57
+ }
58
+ }
src/lib/src/Modules/SecurityAdmin/ModCon.php CHANGED
@@ -54,7 +54,7 @@ class ModCon extends BaseShield\ModCon {
54
  $opts = $this->getOptions();
55
 
56
  // Verify whitelabel images
57
- if ( $this->isWlEnabled() ) {
58
  foreach ( [ 'wl_menuiconurl', 'wl_dashboardlogourl', 'wl_login2fa_logourl' ] as $key ) {
59
  if ( !Services::Data()->isValidWebUrl( $this->buildWlImageUrl( $key ) ) ) {
60
  $opts->resetOptToDefault( $key );
@@ -126,20 +126,20 @@ class ModCon extends BaseShield\ModCon {
126
  private function buildWlImageUrl( $key ) {
127
  $opts = $this->getOptions();
128
 
129
- $sLogoUrl = $opts->getOpt( $key );
130
- if ( empty( $sLogoUrl ) ) {
131
  $opts->resetOptToDefault( $key );
132
- $sLogoUrl = $opts->getOpt( $key );
133
  }
134
- if ( !empty( $sLogoUrl ) && !Services::Data()->isValidWebUrl( $sLogoUrl ) && strpos( $sLogoUrl, '/' ) !== 0 ) {
135
- $sLogoUrl = $this->getCon()->urls->forImage( $sLogoUrl );
136
- if ( empty( $sLogoUrl ) ) {
137
  $opts->resetOptToDefault( $key );
138
- $sLogoUrl = $this->getCon()->urls->forImage( $opts->getOpt( $key ) );
139
  }
140
  }
141
 
142
- return $sLogoUrl;
143
  }
144
 
145
  /**
54
  $opts = $this->getOptions();
55
 
56
  // Verify whitelabel images
57
+ if ( $opts->isEnabledWhitelabel() ) {
58
  foreach ( [ 'wl_menuiconurl', 'wl_dashboardlogourl', 'wl_login2fa_logourl' ] as $key ) {
59
  if ( !Services::Data()->isValidWebUrl( $this->buildWlImageUrl( $key ) ) ) {
60
  $opts->resetOptToDefault( $key );
126
  private function buildWlImageUrl( $key ) {
127
  $opts = $this->getOptions();
128
 
129
+ $url = $opts->getOpt( $key );
130
+ if ( empty( $url ) ) {
131
  $opts->resetOptToDefault( $key );
132
+ $url = $opts->getOpt( $key );
133
  }
134
+ if ( !empty( $url ) && !Services::Data()->isValidWebUrl( $url ) && strpos( $url, '/' ) !== 0 ) {
135
+ $url = $this->getCon()->urls->forImage( $url );
136
+ if ( empty( $url ) ) {
137
  $opts->resetOptToDefault( $key );
138
+ $url = $this->getCon()->urls->forImage( $opts->getOpt( $key ) );
139
  }
140
  }
141
 
142
+ return $url;
143
  }
144
 
145
  /**
src/lib/src/Modules/SecurityAdmin/Strings.php CHANGED
@@ -240,15 +240,15 @@ class Strings extends Base\Strings {
240
  .' '.sprintf( __( 'The %s should measure %s.', 'wp-simple-firewall' ), __( 'icon', 'wp-simple-firewall' ), '16px x 16px' );
241
  break;
242
  case 'wl_dashboardlogourl' :
243
- $name = __( 'Dashboard Logo', 'wp-simple-firewall' );
244
- $summary = __( 'Dashboard Logo URL', 'wp-simple-firewall' );
245
- $description = __( 'The URL of the logo to display in the admin pages.', 'wp-simple-firewall' )
246
  .' '.sprintf( __( 'The %s should measure %s.', 'wp-simple-firewall' ), __( 'logo', 'wp-simple-firewall' ), '128px x 128px' );
247
  break;
248
  case 'wl_login2fa_logourl' :
249
- $name = __( '2FA Login Logo URL', 'wp-simple-firewall' );
250
- $summary = __( '2FA Login Logo URL', 'wp-simple-firewall' );
251
- $description = __( 'The URL of the logo to display on the Two-Factor Authentication login page.', 'wp-simple-firewall' );
252
  break;
253
 
254
  default:
240
  .' '.sprintf( __( 'The %s should measure %s.', 'wp-simple-firewall' ), __( 'icon', 'wp-simple-firewall' ), '16px x 16px' );
241
  break;
242
  case 'wl_dashboardlogourl' :
243
+ $name = __( 'Plugin Badge Logo', 'wp-simple-firewall' );
244
+ $summary = __( 'Plugin Badge Logo URL', 'wp-simple-firewall' );
245
+ $description = __( 'The URL of the logo to display in the plugin badge.', 'wp-simple-firewall' )
246
  .' '.sprintf( __( 'The %s should measure %s.', 'wp-simple-firewall' ), __( 'logo', 'wp-simple-firewall' ), '128px x 128px' );
247
  break;
248
  case 'wl_login2fa_logourl' :
249
+ $name = __( 'Dashboard and 2FA Login Logo URL', 'wp-simple-firewall' );
250
+ $summary = __( 'Dashboard and 2FA Login Logo URL', 'wp-simple-firewall' );
251
+ $description = __( 'The URL of the logo to display on the Dashboard and the Two-Factor Authentication login page.', 'wp-simple-firewall' );
252
  break;
253
 
254
  default:
src/lib/src/Utilities/Htaccess/RootHtaccess.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Utilities\Htaccess;
4
+
5
+ use FernleafSystems\Utilities\Logic\ExecOnce;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
8
+ use FernleafSystems\Wordpress\Services\Services;
9
+
10
+ class RootHtaccess {
11
+
12
+ use ExecOnce;
13
+ use PluginControllerConsumer;
14
+ use PluginCronsConsumer;
15
+
16
+ protected function run() {
17
+ $this->setupCronHooks();
18
+ }
19
+
20
+ public function runDailyCron() {
21
+ $hadFile = (bool)Services::WpFs()->exists( $this->getPathToHtaccess() );
22
+ $couldAccess = $this->testCanAccessURL();
23
+
24
+ if ( $hadFile && !$couldAccess ) {
25
+ $this->deleteHtaccess();
26
+ }
27
+ elseif ( !$hadFile && $couldAccess ) {
28
+ // Create the file and test you can access it. If not, delete it again.
29
+ if ( $this->createHtaccess() && !$this->testCanAccessURL() ) {
30
+ $this->deleteHtaccess();
31
+ }
32
+ }
33
+ }
34
+
35
+ private function testCanAccessURL() :bool {
36
+ $httpReq = Services::HttpRequest();
37
+ return $httpReq->get( $this->getTestURL() ) && $httpReq->lastResponse->getCode() < 400;
38
+ }
39
+
40
+ private function getTestURL() :string {
41
+ return add_query_arg( [ 'rand' => rand( 1000, 9999 ) ], $this->getCon()->urls->forJs( 'plugin.js' ) );
42
+ }
43
+
44
+ private function getPathToHtaccess() :string {
45
+ return path_join( $this->getCon()->getRootDir(), '.htaccess' );
46
+ }
47
+
48
+ private function deleteHtaccess() {
49
+ Services::WpFs()->deleteFile( $this->getPathToHtaccess() );
50
+ }
51
+
52
+ private function createHtaccess() :bool {
53
+ return Services::WpFs()->putFileContent(
54
+ $this->getPathToHtaccess(),
55
+ implode( "\n", [
56
+ 'Order Allow,Deny',
57
+ '<FilesMatch "^.*\.(css|js|png|jpg|svg)$" >',
58
+ ' Allow from all',
59
+ '</FilesMatch>',
60
+ ] )
61
+ );
62
+ }
63
+ }
64
+
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -260,6 +260,7 @@ return array(
260
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\KeyStats' => $baseDir . '/src/Modules/Events/Lib/Reports/KeyStats.php',
261
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\ScanRepairs' => $baseDir . '/src/Modules/Events/Lib/Reports/ScanRepairs.php',
262
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\StatsWriter' => $baseDir . '/src/Modules/Events/Lib/StatsWriter.php',
 
263
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\ModCon' => $baseDir . '/src/Modules/Events/ModCon.php',
264
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Options' => $baseDir . '/src/Modules/Events/Options.php',
265
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Processor' => $baseDir . '/src/Modules/Events/Processor.php',
@@ -604,6 +605,7 @@ return array(
604
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
605
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
606
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\ApplyLabels' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php',
 
607
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => $baseDir . '/src/Modules/SecurityAdmin/ModCon.php',
608
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => $baseDir . '/src/Modules/SecurityAdmin/Options.php',
609
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => $baseDir . '/src/Modules/SecurityAdmin/Processor.php',
@@ -800,6 +802,7 @@ return array(
800
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpUserConsumer' => $baseDir . '/src/Utilities/Consumer/WpUserConsumer.php',
801
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Github\\ListTags' => $baseDir . '/src/Utilities/Github/ListTags.php',
802
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HCaptcha\\TestRequest' => $baseDir . '/src/Utilities/HCaptcha/TestRequest.php',
 
803
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HumanSpam\\TestContent' => $baseDir . '/src/Utilities/HumanSpam/TestContent.php',
804
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Nonce\\Handler' => $baseDir . '/src/Utilities/Nonce/Handler.php',
805
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Options\\CleanStorage' => $baseDir . '/src/Utilities/Options/CleanStorage.php',
@@ -927,6 +930,7 @@ return array(
927
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
928
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
929
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\Transient' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Options/Transient.php',
 
930
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
931
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
932
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
260
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\KeyStats' => $baseDir . '/src/Modules/Events/Lib/Reports/KeyStats.php',
261
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\ScanRepairs' => $baseDir . '/src/Modules/Events/Lib/Reports/ScanRepairs.php',
262
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\StatsWriter' => $baseDir . '/src/Modules/Events/Lib/StatsWriter.php',
263
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\UI\\BuildDataForStats' => $baseDir . '/src/Modules/Events/Lib/UI/BuildDataForStats.php',
264
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\ModCon' => $baseDir . '/src/Modules/Events/ModCon.php',
265
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Options' => $baseDir . '/src/Modules/Events/Options.php',
266
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Processor' => $baseDir . '/src/Modules/Events/Processor.php',
605
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
606
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
607
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\ApplyLabels' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php',
608
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\BuildOptions' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php',
609
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => $baseDir . '/src/Modules/SecurityAdmin/ModCon.php',
610
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => $baseDir . '/src/Modules/SecurityAdmin/Options.php',
611
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => $baseDir . '/src/Modules/SecurityAdmin/Processor.php',
802
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpUserConsumer' => $baseDir . '/src/Utilities/Consumer/WpUserConsumer.php',
803
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Github\\ListTags' => $baseDir . '/src/Utilities/Github/ListTags.php',
804
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HCaptcha\\TestRequest' => $baseDir . '/src/Utilities/HCaptcha/TestRequest.php',
805
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Htaccess\\RootHtaccess' => $baseDir . '/src/Utilities/Htaccess/RootHtaccess.php',
806
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HumanSpam\\TestContent' => $baseDir . '/src/Utilities/HumanSpam/TestContent.php',
807
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Nonce\\Handler' => $baseDir . '/src/Utilities/Nonce/Handler.php',
808
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Options\\CleanStorage' => $baseDir . '/src/Utilities/Options/CleanStorage.php',
930
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
931
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
932
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\Transient' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Options/Transient.php',
933
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Platform\\Detection' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Platform/Detection.php',
934
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
935
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
936
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -428,6 +428,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
428
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\KeyStats' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/Reports/KeyStats.php',
429
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\ScanRepairs' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/Reports/ScanRepairs.php',
430
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\StatsWriter' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/StatsWriter.php',
 
431
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Events/ModCon.php',
432
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Options' => __DIR__ . '/../..' . '/src/Modules/Events/Options.php',
433
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Processor' => __DIR__ . '/../..' . '/src/Modules/Events/Processor.php',
@@ -772,6 +773,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
772
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
773
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
774
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\ApplyLabels' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php',
 
775
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/ModCon.php',
776
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Options.php',
777
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Processor.php',
@@ -968,6 +970,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
968
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpUserConsumer' => __DIR__ . '/../..' . '/src/Utilities/Consumer/WpUserConsumer.php',
969
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Github\\ListTags' => __DIR__ . '/../..' . '/src/Utilities/Github/ListTags.php',
970
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HCaptcha\\TestRequest' => __DIR__ . '/../..' . '/src/Utilities/HCaptcha/TestRequest.php',
 
971
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HumanSpam\\TestContent' => __DIR__ . '/../..' . '/src/Utilities/HumanSpam/TestContent.php',
972
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Nonce\\Handler' => __DIR__ . '/../..' . '/src/Utilities/Nonce/Handler.php',
973
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Options\\CleanStorage' => __DIR__ . '/../..' . '/src/Utilities/Options/CleanStorage.php',
@@ -1095,6 +1098,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1095
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
1096
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
1097
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\Transient' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Options/Transient.php',
 
1098
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
1099
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
1100
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
428
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\KeyStats' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/Reports/KeyStats.php',
429
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\Reports\\ScanRepairs' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/Reports/ScanRepairs.php',
430
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\StatsWriter' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/StatsWriter.php',
431
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Lib\\UI\\BuildDataForStats' => __DIR__ . '/../..' . '/src/Modules/Events/Lib/UI/BuildDataForStats.php',
432
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Events/ModCon.php',
433
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Options' => __DIR__ . '/../..' . '/src/Modules/Events/Options.php',
434
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Events\\Processor' => __DIR__ . '/../..' . '/src/Modules/Events/Processor.php',
773
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
774
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
775
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\ApplyLabels' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php',
776
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\BuildOptions' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php',
777
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/ModCon.php',
778
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Options.php',
779
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Processor.php',
970
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpUserConsumer' => __DIR__ . '/../..' . '/src/Utilities/Consumer/WpUserConsumer.php',
971
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Github\\ListTags' => __DIR__ . '/../..' . '/src/Utilities/Github/ListTags.php',
972
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HCaptcha\\TestRequest' => __DIR__ . '/../..' . '/src/Utilities/HCaptcha/TestRequest.php',
973
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Htaccess\\RootHtaccess' => __DIR__ . '/../..' . '/src/Utilities/Htaccess/RootHtaccess.php',
974
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\HumanSpam\\TestContent' => __DIR__ . '/../..' . '/src/Utilities/HumanSpam/TestContent.php',
975
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Nonce\\Handler' => __DIR__ . '/../..' . '/src/Utilities/Nonce/Handler.php',
976
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Options\\CleanStorage' => __DIR__ . '/../..' . '/src/Utilities/Options/CleanStorage.php',
1098
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
1099
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
1100
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\Transient' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Options/Transient.php',
1101
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Platform\\Detection' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Platform/Detection.php',
1102
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
1103
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
1104
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Request.php CHANGED
@@ -12,6 +12,7 @@ use FernleafSystems\Wordpress\Services\Services;
12
  * @property array $post
13
  * @property array $query
14
  * @property array $cookie
 
15
  * @property array $server
16
  * @property array $env
17
  */
@@ -38,12 +39,24 @@ class Request extends DynPropertiesClass {
38
  public function __construct() {
39
  $this->post = is_array( $_POST ) ? $_POST : [];
40
  $this->query = is_array( $_GET ) ? $_GET : [];
41
- $this->cookie = is_array( $_COOKIE ) ? $_COOKIE : [];
42
  $this->server = is_array( $_SERVER ) ? $_SERVER : [];
43
  $this->env = is_array( $_ENV ) ? $_ENV : [];
44
  $this->ts();
45
  }
46
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  public function getContent() :string {
48
  if ( !isset( $this->content ) ) {
49
  $this->content = file_get_contents( 'php://input' );
12
  * @property array $post
13
  * @property array $query
14
  * @property array $cookie
15
+ * @property array $cookie_copy
16
  * @property array $server
17
  * @property array $env
18
  */
39
  public function __construct() {
40
  $this->post = is_array( $_POST ) ? $_POST : [];
41
  $this->query = is_array( $_GET ) ? $_GET : [];
42
+ $this->cookie_copy = is_array( $_COOKIE ) ? $_COOKIE : [];
43
  $this->server = is_array( $_SERVER ) ? $_SERVER : [];
44
  $this->env = is_array( $_ENV ) ? $_ENV : [];
45
  $this->ts();
46
  }
47
 
48
+ public function __get( string $key ) {
49
+ switch ( $key ) {
50
+ case 'cookie':
51
+ $value = is_array( $_COOKIE ) ? $_COOKIE : [];
52
+ break;
53
+ default:
54
+ $value = parent::__get( $key );
55
+ break;
56
+ }
57
+ return $value;
58
+ }
59
+
60
  public function getContent() :string {
61
  if ( !isset( $this->content ) ) {
62
  $this->content = file_get_contents( 'php://input' );
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Platform/Detection.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\Platform;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Detection {
8
+
9
+ public static function Apache() :string {
10
+ $version = '';
11
+ $raw = function_exists( 'apache_get_version' ) ? apache_get_version() : false;
12
+ if ( empty( $raw ) ) {
13
+ $raw = (string)Services::Request()->env( 'SERVER_SOFTWARE' );
14
+ }
15
+ if ( !empty( $raw ) && preg_match( '#Apache/([\d.]+)\s+#i', $raw, $matches ) ) {
16
+ $version = $matches[ 1 ];
17
+ }
18
+ return $version;
19
+ }
20
+
21
+ public static function PHP( bool $cleaned = true, bool $includeMinor = true ) :string {
22
+ $version = (string)( defined( 'PHP_VERSION' ) ? PHP_VERSION : phpversion() );
23
+ if ( $cleaned && !empty( $version ) && preg_match( '#^[0-9]+\.[0-9]+(\.[0-9]+)?#', $version, $matches ) ) {
24
+ $version = $matches[ 0 ];
25
+ if ( !$includeMinor && substr_count( $version, '.' ) === 3 ) {
26
+ $version = substr( $version, 0, strrpos( $version, '.' ) );
27
+ }
28
+ }
29
+ return (string)$version;
30
+ }
31
+ }
templates/twig/components/events/stats/stat_box.twig CHANGED
@@ -1,8 +1,8 @@
1
  <div class="card h-100 stat_box">
2
- <div class="card-header">
3
- {{ stat.name }}
4
- </div>
5
  <div class="card-body d-flex flex-row text-center justify-content-center">
6
  <div class="stat_count">{{ attribute(stat.counts, stat_to_show|default('lifetime')) }}</div>
7
  </div>
 
 
 
8
  </div>
1
  <div class="card h-100 stat_box">
 
 
 
2
  <div class="card-body d-flex flex-row text-center justify-content-center">
3
  <div class="stat_count">{{ attribute(stat.counts, stat_to_show|default('lifetime')) }}</div>
4
  </div>
5
+ <div class="card-footer text-center">
6
+ {{ stat.name }}
7
+ </div>
8
  </div>
templates/twig/components/events/stats/stats_collection.twig CHANGED
@@ -1,8 +1,12 @@
1
-
2
  {% for stats_section in vars.stats %}
3
- <div class="row row-cols-md-3 row-cols-lg-4 row-cols-xl-6 ">
4
- {% for stat in stats_section %}
5
- <div class=" col mb-4">
 
 
 
 
 
6
  {% include '/components/events/stats/stat_box.twig' %}
7
  </div>
8
  {% endfor %}
 
1
  {% for stats_section in vars.stats %}
2
+ <div class="row">
3
+ <div class="col">
4
+ <h6 class="mt-2 mb-3">{{ stats_section.title }}</h6>
5
+ </div>
6
+ </div>
7
+ <div class="row row-cols-sm-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-5">
8
+ {% for stat in stats_section.events %}
9
+ <div class="col mb-4">
10
  {% include '/components/events/stats/stat_box.twig' %}
11
  </div>
12
  {% endfor %}
templates/twig/pages/login_intent/index.twig CHANGED
@@ -26,14 +26,13 @@
26
 
27
  {% block body_content_header %}
28
  <div class="row justify-content-center">
29
- <div class="col-8 col-md-6 text-center">
30
- <img id="ShieldLogo" class="img-fluid" src="{{ imgs.banner }}" alt="logo" />
31
  </div>
32
  </div>
33
  {% endblock %}
34
  {% block body_content_main %}
35
-
36
- <div class="row">
37
  <div class="col-12 col-md-8 offset-md-2 col-lg-6 offset-lg-3">
38
  {{ content.form|raw }}
39
  </div>
26
 
27
  {% block body_content_header %}
28
  <div class="row justify-content-center">
29
+ <div class="col-8 col-md-4 text-center">
30
+ <img id="ShieldLogo" class="img-fluid my-6" src="{{ imgs.banner }}" alt="logo" />
31
  </div>
32
  </div>
33
  {% endblock %}
34
  {% block body_content_main %}
35
+ <div class="row mt-4">
 
36
  <div class="col-12 col-md-8 offset-md-2 col-lg-6 offset-lg-3">
37
  {{ content.form|raw }}
38
  </div>
templates/twig/wpadmin_pages/insights/base.twig CHANGED
@@ -17,7 +17,7 @@
17
  <a class="navbar-brand float-right my-2"
18
  href="{{ hrefs.nav_home }}"
19
  id="navbar-bannerlogo"
20
- style="background-image: url('{{ hrefs.img_banner }}');"
21
  >&nbsp;</a>
22
  </div>
23
  </div>
17
  <a class="navbar-brand float-right my-2"
18
  href="{{ hrefs.nav_home }}"
19
  id="navbar-bannerlogo"
20
+ style="background-image: url('{{ hrefs.img_banner }}');background-size: auto 40px;"
21
  >&nbsp;</a>
22
  </div>
23
  </div>