Shield Security for WordPress - Version 8.7.0

Version Description

  • Current Release = Released: 16th March, 2020 - Release Notes

  • (v.0) NEW: [PRO] Traffic Rate Limiting Feature.

  • (v.0) ADDED: Support for registration forms in plugins: Profile Builder and Paid Member Subscriptions

  • (v.0) IMPROVED: Tweaks and changes to UI.

  • (v.0) FIXED: Minor issues with the MFA page.

Full Shield Security Changelog

Download this release

Release Info

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

Code changes from version 8.6.3 to 8.7.0

Files changed (125) hide show
  1. icwp-wpsf.php +1 -1
  2. plugin-spec.php +3 -3
  3. readme.txt +9 -21
  4. resources/css/global-plugin.css +2 -6
  5. resources/css/plugin.css +218 -173
  6. resources/js/ip_detect.js +15 -0
  7. resources/js/plugin.js +12 -2
  8. src/config/feature-admin_access_restriction.php +1 -0
  9. src/config/feature-audit_trail.php +1 -0
  10. src/config/feature-autoupdates.php +1 -0
  11. src/config/feature-comments_filter.php +1 -0
  12. src/config/feature-email.php +2 -1
  13. src/config/feature-events.php +2 -1
  14. src/config/feature-firewall.php +1 -0
  15. src/config/feature-hack_protect.php +43 -35
  16. src/config/feature-headers.php +1 -0
  17. src/config/feature-insights.php +2 -1
  18. src/config/feature-ips.php +1 -0
  19. src/config/feature-lockdown.php +1 -0
  20. src/config/feature-login_protect.php +1 -0
  21. src/config/feature-plugin.php +27 -25
  22. src/config/feature-sessions.php +2 -1
  23. src/config/feature-traffic.php +32 -6
  24. src/config/feature-user_management.php +1 -0
  25. src/features/admin_access_restriction.php +1 -2
  26. src/features/base.php +28 -28
  27. src/features/base_wpsf.php +4 -7
  28. src/features/comments_filter.php +0 -8
  29. src/features/hack_protect.php +5 -15
  30. src/features/insights.php +26 -3
  31. src/features/license.php +0 -233
  32. src/features/login_protect.php +10 -178
  33. src/features/plugin.php +5 -6
  34. src/features/traffic.php +25 -8
  35. src/lib/src/Controller/Controller.php +9 -16
  36. src/lib/src/Modules/Base/BaseModCon.php +1 -8
  37. src/lib/src/Modules/Base/BaseProcessor.php +0 -10
  38. src/lib/src/Modules/Base/Options.php +29 -6
  39. src/lib/src/Modules/Base/Strings.php +19 -1
  40. src/lib/src/Modules/BaseShield/ShieldProcessor.php +5 -2
  41. src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/StoreFormatUpgrade.php +0 -80
  42. src/lib/src/Modules/HackGuard/Scan/Results/Clean.php +0 -27
  43. src/lib/src/Modules/IPs/Lib/BlockRequest.php +2 -1
  44. src/lib/src/Modules/License/AdminNotices.php +2 -4
  45. src/lib/src/Modules/License/Lib/WpHashes/ApiTokenManager.php +9 -2
  46. src/lib/src/Modules/LoginGuard/AdminNotices.php +4 -2
  47. src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php +5 -5
  48. src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php +2 -2
  49. src/lib/src/Modules/LoginGuard/Strings.php +2 -2
  50. src/lib/src/Modules/Plugin/AdminNotices.php +1 -0
  51. src/lib/src/Modules/Plugin/AjaxHandler.php +21 -0
  52. src/lib/src/Modules/Plugin/Lib/WpHashesTokenManager.php +0 -129
  53. src/lib/src/Modules/Plugin/Options.php +8 -0
  54. src/lib/src/Modules/Plugin/Strings.php +6 -4
  55. src/lib/src/Modules/Traffic/Lib/Limit/Limiter.php +45 -0
  56. src/lib/src/Modules/Traffic/{Limiter → Lib/Limit}/TestIp.php +4 -4
  57. src/lib/src/Modules/Traffic/Lib/Logger.php +136 -0
  58. src/lib/src/Modules/Traffic/Limiter/Limiter.php +0 -38
  59. src/lib/src/Modules/Traffic/Options.php +18 -1
  60. src/lib/src/Modules/Traffic/Strings.php +22 -8
  61. src/lib/src/Tables/Build/BaseBuild.php +1 -1
  62. src/lib/src/Tables/Build/Sessions.php +7 -0
  63. src/lib/src/Tables/Render/Base.php +1 -1
  64. src/lib/src/Tests/VerifyUniqueEvents.php +1 -1
  65. src/lib/vendor/composer/autoload_classmap.php +6 -18
  66. src/lib/vendor/composer/autoload_static.php +6 -18
  67. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php +37 -0
  68. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheConsumer.php +31 -0
  69. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Retrieve.php +0 -19
  70. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Retrieve.php +0 -19
  71. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/WhitelistRetrieve.php +0 -19
  72. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php +5 -25
  73. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Base.php +14 -7
  74. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php +46 -0
  75. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php +31 -0
  76. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php +1 -35
  77. src/processors/adminaccess_whitelabel.php +0 -141
  78. src/processors/autoupdates.php +0 -17
  79. src/processors/email.php +0 -62
  80. src/processors/ips.php +0 -8
  81. src/processors/login_protect.php +0 -42
  82. src/processors/loginprotect_base.php +58 -1
  83. src/processors/loginprotect_intent.php +0 -128
  84. src/processors/loginprotect_intent_tracker.php +0 -166
  85. src/processors/loginprotect_intentprovider_backup.php +0 -118
  86. src/processors/loginprotect_intentprovider_base.php +0 -316
  87. src/processors/loginprotect_intentprovider_email.php +0 -149
  88. src/processors/loginprotect_intentprovider_ga.php +0 -325
  89. src/processors/loginprotect_intentprovider_yubikey.php +0 -248
  90. src/processors/loginprotect_wplogin.php +8 -8
  91. src/processors/plugin.php +0 -12
  92. src/processors/plugin_crondaily.php +0 -30
  93. src/processors/plugin_cronhourly.php +0 -33
  94. src/processors/traffic.php +6 -25
  95. src/processors/traffic_logger.php +8 -84
  96. src/wizards/login_protect.php +8 -5
  97. src/wizards/plugin.php +5 -2
  98. templates/php/admin_bootstrap.php +0 -6
  99. templates/php/feature-default.php +0 -29
  100. templates/php/index.php +0 -29
  101. templates/php/index_body.php +0 -26
  102. templates/php/index_footer.php +0 -26
  103. templates/php/index_header.php +0 -3
  104. templates/php/snippets/module-actions-template.php +0 -30
  105. templates/php/snippets/options_form.php +0 -293
  106. templates/php/snippets/summary_single.php +0 -7
  107. templates/php/snippets/widget_iframe_side.php +0 -7
  108. templates/php/subfeature-statistics_data_viewer.php +0 -18
  109. templates/php/widgets/icwp_widgets.php +0 -26
  110. templates/twig/common/macros.twig +4 -0
  111. templates/twig/components/options_form/main.twig +87 -0
  112. templates/twig/components/options_form/option.twig +177 -0
  113. templates/twig/features/feature-default.twig +1 -1
  114. templates/twig/snippets/options_form.twig +0 -255
  115. templates/twig/wpadmin_pages/insights/license/license.twig +15 -4
  116. templates/twig/wpadmin_pages/insights/scans/results/apc.twig +1 -1
  117. templates/twig/wpadmin_pages/insights/scans/results/common_disabled.twig +1 -1
  118. templates/twig/wpadmin_pages/insights/scans/results/mal.twig +1 -1
  119. templates/twig/wpadmin_pages/insights/scans/results/mal_disabled.twig +1 -1
  120. templates/twig/wpadmin_pages/insights/scans/results/ptg.twig +1 -1
  121. templates/twig/wpadmin_pages/insights/scans/results/wpv.twig +1 -1
  122. templates/twig/wpadmin_pages/insights/settings/index.twig +15 -8
  123. templates/twig/wpadmin_pages/insights/traffic/index.twig +1 -1
  124. templates/twig/wpadmin_pages/insights/traffic/traffic_disabled.twig +1 -1
  125. templates/twig/wpadmin_pages/security_admin/index.twig +4 -3
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: 8.6.3
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: 8.7.0
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": "8.6.3",
4
- "release_timestamp": 1582635039,
5
- "build": "202002.2505",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield",
1
  {
2
  "properties": {
3
+ "version": "8.7.0",
4
+ "release_timestamp": 1584347026,
5
+ "build": "202003.1601",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield",
readme.txt CHANGED
@@ -7,8 +7,8 @@ Tags: scan, malware, firewall, two factor authentication, login protection
7
  Requires at least: 3.5.2
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
- Tested up to: 5.3
11
- Stable tag: 8.6.3
12
 
13
  Smarter security protection from hackers through automation. Powerful scanners, 2-Factor Auth, limit logins, auto IP blocks & more.
14
 
@@ -370,24 +370,12 @@ You will always be able to use Shield Security and its free features in-full.
370
 
371
  [Go Pro for just $1/month](https://shsec.io/aa).
372
 
373
- = 8.6.3 - Current Release =
374
- *Released: 25th February, 2020* - [Release Notes](https://shsec.io/gl)
375
-
376
- * **(v.3)** IMPROVED: AJAX handling and general plugin requests have been refined to be less prone to errors.
377
- * **(v.3)** IMPROVED: The Traffic Log Viewer will now be displayed even if it's disabled.
378
- * **(v.3)** REMOVED: 2 options from the Automatic Updates module have been removed, that influenced translations and version control.
379
- * **(v.3)** IMPROVED: Some minor improvements and optimisations.
380
- * **(v.3)** IMPROVED: Adjusted how Shield stores temporary WP options to prevent duplicates.
381
- * **(v.3)** FIXED: Login backup-code wasn't always reset after it was used.
382
- * **(v.3)** FIXED: IP address wasn't blocked even after committing an offense in 1 particular scenario.
383
-
384
- = 8.6 - Series =
385
- *Released: 19th February, 2020* - [Release Notes](https://shsec.io/gl)
386
-
387
- * **(v.1)** NEW: [**PRO**] Deep scanning for valid email addresses when user registers with site.
388
- * **(v.1)** ADDED: [**PRO**] New option allows users to turn on email-based two-factor authentication from their profile.
389
- * **(v.1)** ADDED: Support for manually blocking IP Ranges (not just single IPs).
390
- * **(v.1)** IMPROVED: Two-Factor Authentication system has been rewritten and improved.
391
- * **(v.1)** IMPROVED: Table ordering and descriptions for the IP Black List.
392
 
393
  #### [Full Shield Security Changelog](https://shsec.io/shieldwporgfullchangelog)
7
  Requires at least: 3.5.2
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
+ Tested up to: 5.4
11
+ Stable tag: 8.7.0
12
 
13
  Smarter security protection from hackers through automation. Powerful scanners, 2-Factor Auth, limit logins, auto IP blocks & more.
14
 
370
 
371
  [Go Pro for just $1/month](https://shsec.io/aa).
372
 
373
+ = 8.7.0 - Current Release =
374
+ *Released: 16th March, 2020* - [Release Notes](https://shsec.io/gy)
375
+
376
+ * **(v.0)** NEW: [**PRO**] [Traffic Rate Limiting Feature](https://shsec.io/gv).
377
+ * **(v.0)** ADDED: Support for registration forms in plugins: Profile Builder and Paid Member Subscriptions
378
+ * **(v.0)** IMPROVED: Tweaks and changes to UI.
379
+ * **(v.0)** FIXED: Minor issues with the MFA page.
 
 
 
 
 
 
 
 
 
 
 
 
380
 
381
  #### [Full Shield Security Changelog](https://shsec.io/shieldwporgfullchangelog)
resources/css/global-plugin.css CHANGED
@@ -86,7 +86,7 @@
86
  font-weight: bold;
87
  }
88
  ul.nav-tabs li a {
89
- color: rgba(69, 119, 0, 1);
90
  }
91
  ul.nav-tabs li.active a {
92
  color: #000000;
@@ -168,7 +168,7 @@ tr.icwp-plugin-vulnerability dd {
168
  background-color: whitesmoke;
169
  }
170
  .wp-submenu-wrap a .icwp_highlighted {
171
- color: #09b740;
172
  }
173
  #icwp-wpsf-dashboard_widget {
174
  }
@@ -232,9 +232,7 @@ tr.icwp-plugin-vulnerability dd {
232
  transition: width 1.5s;
233
  transition-timing-function: ease;
234
  -webkit-transition-timing-function: ease;
235
-
236
  visibility: hidden;
237
-
238
  width: 0;
239
  font-size: 18px;
240
  color: #ffffff;
@@ -341,8 +339,6 @@ tr.icwp-plugin-vulnerability dd {
341
  .icwpAjaxTableContainer table th.column-ip {
342
  white-space: pre;
343
  }
344
- .icwpAjaxTableContainer table th.column-wp_username {
345
- }
346
  .icwpAjaxTableContainer table th.column-event {
347
  width: 110px;
348
  }
86
  font-weight: bold;
87
  }
88
  ul.nav-tabs li a {
89
+ color: #008000;
90
  }
91
  ul.nav-tabs li.active a {
92
  color: #000000;
168
  background-color: whitesmoke;
169
  }
170
  .wp-submenu-wrap a .icwp_highlighted {
171
+ color: #008000;
172
  }
173
  #icwp-wpsf-dashboard_widget {
174
  }
232
  transition: width 1.5s;
233
  transition-timing-function: ease;
234
  -webkit-transition-timing-function: ease;
 
235
  visibility: hidden;
 
236
  width: 0;
237
  font-size: 18px;
238
  color: #ffffff;
339
  .icwpAjaxTableContainer table th.column-ip {
340
  white-space: pre;
341
  }
 
 
342
  .icwpAjaxTableContainer table th.column-event {
343
  width: 110px;
344
  }
resources/css/plugin.css CHANGED
@@ -1,5 +1,4 @@
1
  @CHARSET "ISO-8859-1";
2
-
3
  /* GENERAL STYLES */
4
  body {
5
  overflow-y: scroll;
@@ -14,7 +13,6 @@ body.rtl {
14
  margin: 0;
15
  padding: 0;
16
  }
17
-
18
  /** Hide WordPress update nag **/
19
  .update-nag {
20
  display: none;
@@ -22,7 +20,6 @@ body.rtl {
22
  #wpbody-content .odp-admin-notice.notice {
23
  margin: 5px 15px;
24
  }
25
-
26
  .pluginlogo_16 {
27
  background: url("../images/pluginlogo_16x16.png?ver=1.0.0") no-repeat 0 3px transparent;
28
  }
@@ -49,17 +46,29 @@ body.rtl {
49
  line-height: 10px;
50
  letter-spacing: -0.5px;
51
  }
52
- #ColumnOptions .form-actions {
 
53
  position: fixed;
54
- bottom: 50px;
 
 
 
 
 
55
  }
56
- #ColumnOptions .form-actions .row > div {
57
  background-color: transparent; /*#d8d8d8;*/
58
- z-index: 1000;
 
 
59
  }
60
  #ColumnOptions form {
61
  margin-bottom: 50px;
62
  }
 
 
 
 
63
  #ColumnOptions .form-actions .btn {
64
  box-shadow: -1px 2px 2px rgba(0, 0, 0, 0.3);
65
  opacity: 0.85;
@@ -124,9 +133,8 @@ p.code-description {
124
  padding: 5px 30px 30px;
125
  }
126
  .row.option_section_row.non_primary_section > div {
127
- margin-left: 0px;
128
  }*/
129
-
130
  .well.admin_access_restriction_form {
131
  background-color: #fbfbfb;
132
  border: 1px solid #cccccc;
@@ -143,7 +151,6 @@ p.code-description {
143
  opacity: 0.5;
144
  }
145
  /* BOOSTRAP SETTINGS PAGE STYLES */
146
-
147
  .bootstrap-wpadmin .form-horizontal .form-actions {
148
  padding-left: 200px;
149
  }
@@ -154,11 +161,10 @@ a.section-help-video {
154
  }
155
  a.section-help-video > span {
156
  font-size: 28px;
157
- margin-left: 6px;
158
- color: rgba(69, 119, 0, 1);
159
  }
160
  /** End-Section summaries **/
161
-
162
  .wrap .icon32 {
163
  width: 32px;
164
  }
@@ -298,93 +304,13 @@ label input[type=checkbox] {
298
  border: 1px solid #cccccc;
299
  background: #f9f9f9;
300
  }
301
- .module-icon:before {
302
- -webkit-font-smoothing: antialiased;
303
- display: inline-block;
304
- font: 32px/1 'dashicons';
305
- vertical-align: top;
306
  }
307
- .feature-summary-blocks .module-icon:before {
308
  -webkit-font-smoothing: antialiased;
309
- display: inline-block;
310
- font: 32px/1 'dashicons';
311
- vertical-align: top;
312
- }
313
- .feature-summary-blocks a {
314
- display: block;
315
- text-shadow: 1px 0 0 rgba(0, 0, 0, 0.4);
316
- width: 100%;
317
- }
318
- .feature-summary-blocks .summary-state {
319
- border: 1px solid transparent;
320
- overflow: hidden;
321
- text-align: center;
322
- margin-bottom: -1px;
323
- }
324
- .feature-summary-blocks .summary-state.active-feature {
325
- background-color: rgba(69, 119, 0, 1);
326
- }
327
- .feature-summary-blocks .summary-state.active-feature a {
328
- color: rgba(255, 255, 255, 1);
329
- }
330
- .feature-summary-blocks .summary-state.active-feature.state-off {
331
- background-color: rgba(173, 84, 0, 0.85);
332
- }
333
- .feature-summary-blocks .summary-state .popover {
334
- box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
335
- padding: 0;
336
- border-radius: 1px;
337
- text-align: left;
338
- width: 200px;
339
- }
340
- .feature-summary-blocks .summary-state .popover .arrow {
341
- display: none;
342
- }
343
- .feature-summary-blocks .summary-state.active-feature.state-off:hover,
344
- .feature-summary-blocks .summary-state:hover {
345
- border: 1px solid rgba(0, 0, 0, 0.1);
346
- border-left: 1px solid transparent;
347
- background-color: rgba(255, 255, 255, 0.8);
348
- }
349
- .feature-summary-blocks .summary-state:hover {
350
- }
351
- .feature-summary-blocks .summary-state a p {
352
- text-shadow: 0 0 0 rgba(0, 0, 0, 0.6);
353
- font-size: 12px;
354
- margin: 0;
355
- }
356
- .feature-summary-blocks .summary-state a:hover {
357
- text-decoration: none;
358
- }
359
- .feature-summary-blocks .summary-state a {
360
- padding: 8px 0;
361
- }
362
- @media (max-width: 800px) {
363
- .feature-summary-blocks .summary-state p {
364
- font-size: 8px;
365
- }
366
-
367
- .feature-summary-blocks .module-icon:before {
368
- font-size: 16px;
369
- }
370
- }
371
- .feature-summary-blocks .state-on a {
372
- color: rgba(69, 119, 0, 1);
373
- }
374
- .feature-summary-blocks .state-off a {
375
- color: rgba(173, 84, 0, 0.85);
376
- }
377
- .feature-summary-blocks .state-on a:hover {
378
- color: rgb(99, 150, 0);
379
- }
380
- .feature-summary-blocks .state-off a:hover {
381
- color: rgba(207, 90, 0, 0.85);
382
- }
383
- .feature-summary-blocks .feature-summary-block.state-on {
384
- background-color: rgba(102, 216, 45, 0.2);
385
- }
386
- .feature-summary-blocks .feature-summary-block.state-off {
387
- background-color: rgba(239, 141, 49, 0.2);
388
  }
389
  .module-icon-insights:before {
390
  content: "\f179";
@@ -533,7 +459,6 @@ input[type="email"] {
533
  .content-help {
534
  background-color: #f1f1f1; /** == #ColumnOptions */
535
  padding: 20px;
536
-
537
  }
538
  .content-help h2 {
539
  margin-bottom: 8px;
@@ -620,7 +545,6 @@ input:checked + .icwp-slider:before {
620
  border-radius: 10%;
621
  }
622
  /** NEW FORMS **/
623
-
624
  #wpwrap {
625
  background-color: #f1f1f1;
626
  }
@@ -643,16 +567,14 @@ input:checked + .icwp-slider:before {
643
  height: 76px;
644
  width: 76px;
645
  background-size: 76px 76px;
646
-
647
  margin-bottom: 7px;
648
  position: relative;
649
  left: 1px;
650
  }
651
  #ColumnModules {
652
- text-align: center;
653
- border-left: 1px solid rgba(0, 0, 0, 0.05);
654
- max-width: 85px;
655
- margin-top: 10px;
656
  }
657
  #ColumnOptions {
658
  min-width: 590px; /** prevents col breaking **/
@@ -670,19 +592,40 @@ input:checked + .icwp-slider:before {
670
  display: block;
671
  }
672
  .modules a.module {
673
- height: 54px;
674
- width: 66px;
675
  margin: auto;
676
- padding: 0.6rem 0.9rem;
 
 
 
 
677
  }
678
  .modules a.module:first-child {
679
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
680
  .modules a#tab-license {
681
  color: #1d00ff;
682
  }
683
  .modules a.module .module-name {
684
- line-height: 19px;
685
- position: relative;
686
  }
687
  .modules .module-name .dashicons {
688
  position: absolute;
@@ -699,22 +642,8 @@ input:checked + .icwp-slider:before {
699
  .modules a.module .dashicons-warning:before {
700
  font-size: 16px !important;
701
  }
702
- .modules a.module:hover,
703
- .modules a.module:focus {
704
- background-color: #eeeeee;
705
- color: #222222;
706
- box-shadow: none;
707
- }
708
- .modules a.module.active {
709
- border: 1px solid rgba(0, 0, 0, 0.3);
710
- border-radius: 0.25rem;
711
- background-color: rgba(255, 255, 255, 0.6);
712
- }
713
  .modules a.module.active .module-icon {
714
  }
715
- .modules a.module.active .module-icon:before {
716
- color: #222222;
717
- }
718
  .icwp-options-page .tab-content {
719
  background-color: #f1f1f1;
720
  border: 1px solid #dddddd;
@@ -733,7 +662,6 @@ input:checked + .icwp-slider:before {
733
  .option_container {
734
  }
735
  .carousel-item {
736
-
737
  transition: -webkit-transform 0.3s ease;
738
  transition: transform 0.2s ease;
739
  transition: transform 0.2s ease, -webkit-transform 0.2s ease;
@@ -764,10 +692,10 @@ input:checked + .icwp-slider:before {
764
  }
765
 
766
  .modules a.module {
 
767
  font-size: 0.7rem;
768
  font-weight: normal;
769
  letter-spacing: -1px;
770
- padding: 0.4rem 0.6rem 0.4rem 0.8rem;
771
  }
772
 
773
  .modules .module-name .dashicons {
@@ -782,6 +710,12 @@ input:checked + .icwp-slider:before {
782
  width: 100%;
783
  z-index: 5;
784
  }
 
 
 
 
 
 
785
  #WizardTop {
786
  height: 40px;
787
  background-color: #fafafa;
@@ -791,7 +725,7 @@ input:checked + .icwp-slider:before {
791
  height: 66px;
792
  background-color: #eaffea;
793
  border-top: 1px solid #bbbbbb;
794
- padding-top: 10px;
795
  text-align: center;
796
  word-break: keep-all;
797
  white-space: nowrap;
@@ -812,12 +746,10 @@ td.column-message textarea {
812
  box-shadow: none;
813
  border-color: rgba(0, 0, 0, 0.05);
814
  }
815
-
816
  .table-side-filter {
817
  position: sticky;
818
  top: 120px;
819
  }
820
-
821
  #SectionNotices tr.title_row th {
822
  padding: 0.25rem 1.0rem;
823
  border-bottom: 0 none;
@@ -826,7 +758,6 @@ td.column-message textarea {
826
  #SectionNotices tr.title_row th h6 {
827
  font-size: 0.85rem;
828
  }
829
-
830
  /** TABLE: TRAFFIC **/
831
  th.column-visitor {
832
  }
@@ -849,13 +780,10 @@ th.column-request_info {
849
  width: 100px;
850
  }
851
  /** INSIGHTS **/
852
-
853
  /* TABLES */
854
  .tablenav-pages-navspan {
855
  box-sizing: content-box;
856
  }
857
- #odp-PageContainer {
858
- }
859
  #odp-PageContainer .card {
860
  box-shadow: none;
861
  margin-top: 0;
@@ -865,7 +793,6 @@ th.column-request_info {
865
  #odp-PageHead {
866
  }
867
  .page-insights #odp-PageHead {
868
- position: sticky;
869
  top: 40px;
870
  z-index: 3;
871
  }
@@ -879,8 +806,10 @@ th.column-request_info {
879
  font-weight: bold;
880
  border: 1px solid rgba(0, 0, 0, 0.1);
881
  border-radius: 3px;
882
- background-color: rgba(0, 0, 0, 0.04);
883
- color: green;
 
 
884
  }
885
  .nav-link.module.notenabled .module-icon:before {
886
  color: rgba(0, 0, 0, 0.4);
@@ -897,8 +826,6 @@ th.column-request_info {
897
  font-size: 13px;
898
  }
899
  .odp-outercontainer.icwp-wpsf-insights.settings #odp-PageMain {
900
- position: relative;
901
- top: 20px;
902
  }
903
  .insights_section {
904
  margin-top: 20px;
@@ -932,11 +859,9 @@ td.cell_delete_note {
932
  .icon-sign {
933
  font-size: 14px;
934
  }
935
-
936
  #collapseConfigSummaryTitle:hover {
937
  cursor: pointer;
938
  }
939
-
940
  #SectionStats {
941
  overflow: auto;
942
  }
@@ -975,7 +900,6 @@ th.column-last_activity_at {
975
  td .timestamp-small {
976
  font-size: smaller;
977
  }
978
-
979
  .odp-table td.check-column input[type=checkbox],
980
  .odp-table th.check-column input[type=checkbox] {
981
  margin: 0 4px;
@@ -984,7 +908,6 @@ a.ip-whois {
984
  color: #739e31;
985
  }
986
  /** END TABLES **/
987
-
988
  /** Sessions Table **/
989
  th.column-is_secadmin {
990
  width: 120px;
@@ -996,7 +919,7 @@ form.add-ip button.add {
996
  vertical-align: text-bottom;
997
  }
998
  form.add-ip button.add .dashicons {
999
- vertical-align: inherit;
1000
  }
1001
  .odp-table .actions-block {
1002
  font-size: 0.75rem;
@@ -1026,8 +949,6 @@ td.column-actions button > span {
1026
  font-size: 20px;
1027
  } */
1028
  /** END IPS Insights **/
1029
-
1030
-
1031
  .scan-select .form-text {
1032
  white-space: normal;
1033
  }
@@ -1040,7 +961,6 @@ td.column-actions button > span {
1040
  table.scan-table.wp-list-table button.toggle-row {
1041
  display: none;
1042
  }
1043
-
1044
  #ScanResultsTabs {
1045
  }
1046
  #ScanResultsTabs ul.nav.nav-tabs a.nav-link {
@@ -1056,7 +976,6 @@ table.scan-table.wp-list-table button.toggle-row {
1056
  #ScanResultsTabs nav > a.nav-link .badge {
1057
  font-size: 12px;
1058
  }
1059
-
1060
  /**
1061
  PTG SCAN TABLES
1062
  */
@@ -1066,7 +985,6 @@ PTG SCAN TABLES
1066
  .scan-table-for-slug .tablenav.top {
1067
  display: none;
1068
  }
1069
-
1070
  .card.card-scan_results {
1071
  background-color: transparent;
1072
  border: 0 none;
@@ -1098,7 +1016,6 @@ table.odp-table.scan-table td.column-path code {
1098
  .container-scantable .tablenav.top {
1099
  /*display: none;*/
1100
  }
1101
-
1102
  #TableAdminNotes .tablenav.bottom,
1103
  #TableSessions .tablenav.bottom,
1104
  .container-scantable .tablenav.bottom {
@@ -1115,7 +1032,6 @@ table.odp-table.scan-table td.column-path code {
1115
  border-radius: 0;
1116
  border-width: 2px 0;
1117
  }
1118
-
1119
  #navbar-bannerlogo {
1120
  min-width: 170px;
1121
  width: 170px;
@@ -1150,47 +1066,60 @@ input[type=checkbox].form-check-input {
1150
  margin: 0;
1151
  border-width: 10px 20px;
1152
  }
1153
-
1154
  /** copied from bootstrap to override WP admin styles */
1155
  .content-options {
1156
  font-size: 14px;
1157
  padding-top: 10px;
1158
  }
1159
- #ModuleOptionsNav.nav-tabs {
1160
  border: 0 none;
1161
  margin: 0;
1162
  }
1163
- #ModuleOptionsNav.nav-tabs a.nav-link {
1164
- padding: 0.5rem 0.7rem;
1165
- background-color: rgba(0, 0, 0, 0.06);
1166
- border: 1px solid rgba(0, 0, 0, 0.06);
1167
- border-bottom: 0 none;
1168
- margin-left: 6px;
1169
  font-size: 14px;
 
 
 
 
 
 
 
 
 
1170
  }
1171
  #ModuleOptionsNav.nav-tabs a.nav-link.active,
1172
  #ModuleOptionsNav.nav-tabs a.nav-link.active:hover {
1173
- background-color: transparent;
1174
- border-color: rgba(0, 0, 0, 0.1);
 
 
 
 
1175
  }
1176
  #ModuleOptionsNav.nav-tabs a.nav-link:hover {
1177
- background-color: #dddddd;
1178
- border-color: #999999;
 
 
 
 
 
1179
  }
1180
  .content-options .tab-content {
1181
  border-top: 0 none;
1182
  padding-top: 14px;
1183
  }
1184
  .content-options .form-group.row {
1185
- margin-bottom: 20px;
1186
- padding-bottom: 15px;
1187
  border-bottom: 1px dashed rgba(0, 0, 0, 0.08);
1188
  }
1189
  .content-options .option-section-summary,
1190
  .content-options .option-description {
1191
  font-size: 12px;
1192
  border: 1px solid rgba(0, 0, 0, 0.06);
1193
- margin-top: 4px;
1194
  padding: 5px 9px;
1195
  background-color: rgba(255, 255, 255, 0.4);
1196
  }
@@ -1198,17 +1127,24 @@ input[type=checkbox].form-check-input {
1198
  margin-bottom: 12px;
1199
  padding-top: 8px;
1200
  }
1201
- .content-options .option-links {
1202
- font-size: 12px;
 
1203
  }
1204
- .content-options .option-links a {
1205
- color: rgba(69, 119, 0, 1);
 
 
 
 
 
 
 
 
1206
  }
1207
-
1208
  .tooltip .arrow {
1209
  display: none !important;
1210
  }
1211
-
1212
  table.odp-table tr.audit-cat-1 td {
1213
  background-color: #f8fbff;
1214
  }
@@ -1218,7 +1154,6 @@ table.odp-table tr.audit-cat-2 td {
1218
  table.odp-table tr.audit-cat-3 td {
1219
  background-color: #fffdfd;
1220
  }
1221
-
1222
  .row-sticky td {
1223
  background-color: #5a5a5a;
1224
  position: sticky;
@@ -1229,7 +1164,117 @@ table.odp-table tr.audit-cat-3 td {
1229
  margin: 0;
1230
  color: #ffffff;
1231
  }
1232
-
1233
  .introjs-helperLayer {
1234
  background-color: rgba(91, 228, 56, 0.34);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1235
  }
1
  @CHARSET "ISO-8859-1";
 
2
  /* GENERAL STYLES */
3
  body {
4
  overflow-y: scroll;
13
  margin: 0;
14
  padding: 0;
15
  }
 
16
  /** Hide WordPress update nag **/
17
  .update-nag {
18
  display: none;
20
  #wpbody-content .odp-admin-notice.notice {
21
  margin: 5px 15px;
22
  }
 
23
  .pluginlogo_16 {
24
  background: url("../images/pluginlogo_16x16.png?ver=1.0.0") no-repeat 0 3px transparent;
25
  }
46
  line-height: 10px;
47
  letter-spacing: -0.5px;
48
  }
49
+ #OptionsFormActions.form-actions {
50
+ background: rgba(0, 0, 0, 0.1);
51
  position: fixed;
52
+ bottom: 0;
53
+ left: 0;
54
+ height: 70px;
55
+ width: 100%;
56
+ z-index: 100;
57
+ text-align: center;
58
  }
59
+ #OptionsFormActions.form-actions .row > div {
60
  background-color: transparent; /*#d8d8d8;*/
61
+ }
62
+ #OptionsFormActions.form-actions button {
63
+ margin-top: 10px;
64
  }
65
  #ColumnOptions form {
66
  margin-bottom: 50px;
67
  }
68
+ #ColumnOptions form .form-group.row .form-check-null {
69
+ display: flex;
70
+ align-items: center;
71
+ }
72
  #ColumnOptions .form-actions .btn {
73
  box-shadow: -1px 2px 2px rgba(0, 0, 0, 0.3);
74
  opacity: 0.85;
133
  padding: 5px 30px 30px;
134
  }
135
  .row.option_section_row.non_primary_section > div {
136
+ margin-left: 0;
137
  }*/
 
138
  .well.admin_access_restriction_form {
139
  background-color: #fbfbfb;
140
  border: 1px solid #cccccc;
151
  opacity: 0.5;
152
  }
153
  /* BOOSTRAP SETTINGS PAGE STYLES */
 
154
  .bootstrap-wpadmin .form-horizontal .form-actions {
155
  padding-left: 200px;
156
  }
161
  }
162
  a.section-help-video > span {
163
  font-size: 28px;
164
+ color: #008000;
165
+ margin-top: -2px;
166
  }
167
  /** End-Section summaries **/
 
168
  .wrap .icon32 {
169
  width: 32px;
170
  }
304
  border: 1px solid #cccccc;
305
  background: #f9f9f9;
306
  }
307
+ .module-icon {
308
+ position: relative;
309
+ top: 2px;
 
 
310
  }
311
+ .module-icon:before {
312
  -webkit-font-smoothing: antialiased;
313
+ font: 16px/1 'dashicons';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  }
315
  .module-icon-insights:before {
316
  content: "\f179";
459
  .content-help {
460
  background-color: #f1f1f1; /** == #ColumnOptions */
461
  padding: 20px;
 
462
  }
463
  .content-help h2 {
464
  margin-bottom: 8px;
545
  border-radius: 10%;
546
  }
547
  /** NEW FORMS **/
 
548
  #wpwrap {
549
  background-color: #f1f1f1;
550
  }
567
  height: 76px;
568
  width: 76px;
569
  background-size: 76px 76px;
 
570
  margin-bottom: 7px;
571
  position: relative;
572
  left: 1px;
573
  }
574
  #ColumnModules {
575
+ width: 200px;
576
+ margin-left: 15px;
577
+ margin-top: 8px;
 
578
  }
579
  #ColumnOptions {
580
  min-width: 590px; /** prevents col breaking **/
592
  display: block;
593
  }
594
  .modules a.module {
595
+ height: 45px;
596
+ width: 100%;
597
  margin: auto;
598
+ text-align: left;
599
+ display: block;
600
+ padding: 10px 0 0 0;
601
+ color: #222222;
602
+ font-size: 16px;
603
  }
604
  .modules a.module:first-child {
605
  }
606
+ .modules a.module:hover,
607
+ .modules a.module:focus {
608
+ /*background-color: #eeeeee;*/
609
+ color: rgba(0, 128, 0, 1);
610
+ box-shadow: none;
611
+ }
612
+ .modules a.module.active {
613
+ font-weight: bold;
614
+ color: rgba(0, 128, 0, 1);
615
+ padding-left: 5px;
616
+ }
617
+ .modules a.module.active > div {
618
+ }
619
+ .modules a.module .module-icon::before {
620
+ color: #222222;
621
+ }
622
+ .modules a.module.active .module-icon::before {
623
+ color: rgba(0, 128, 0, 1);
624
+ }
625
  .modules a#tab-license {
626
  color: #1d00ff;
627
  }
628
  .modules a.module .module-name {
 
 
629
  }
630
  .modules .module-name .dashicons {
631
  position: absolute;
642
  .modules a.module .dashicons-warning:before {
643
  font-size: 16px !important;
644
  }
 
 
 
 
 
 
 
 
 
 
 
645
  .modules a.module.active .module-icon {
646
  }
 
 
 
647
  .icwp-options-page .tab-content {
648
  background-color: #f1f1f1;
649
  border: 1px solid #dddddd;
662
  .option_container {
663
  }
664
  .carousel-item {
 
665
  transition: -webkit-transform 0.3s ease;
666
  transition: transform 0.2s ease;
667
  transition: transform 0.2s ease, -webkit-transform 0.2s ease;
692
  }
693
 
694
  .modules a.module {
695
+ width: 81px;
696
  font-size: 0.7rem;
697
  font-weight: normal;
698
  letter-spacing: -1px;
 
699
  }
700
 
701
  .modules .module-name .dashicons {
710
  width: 100%;
711
  z-index: 5;
712
  }
713
+ #FooterWizardBanner .text-left {
714
+ margin-bottom: 0;
715
+ }
716
+ #FooterWizardBanner .offset-1 {
717
+ margin-left: 12%;
718
+ }
719
  #WizardTop {
720
  height: 40px;
721
  background-color: #fafafa;
725
  height: 66px;
726
  background-color: #eaffea;
727
  border-top: 1px solid #bbbbbb;
728
+ padding-top: 15px;
729
  text-align: center;
730
  word-break: keep-all;
731
  white-space: nowrap;
746
  box-shadow: none;
747
  border-color: rgba(0, 0, 0, 0.05);
748
  }
 
749
  .table-side-filter {
750
  position: sticky;
751
  top: 120px;
752
  }
 
753
  #SectionNotices tr.title_row th {
754
  padding: 0.25rem 1.0rem;
755
  border-bottom: 0 none;
758
  #SectionNotices tr.title_row th h6 {
759
  font-size: 0.85rem;
760
  }
 
761
  /** TABLE: TRAFFIC **/
762
  th.column-visitor {
763
  }
780
  width: 100px;
781
  }
782
  /** INSIGHTS **/
 
783
  /* TABLES */
784
  .tablenav-pages-navspan {
785
  box-sizing: content-box;
786
  }
 
 
787
  #odp-PageContainer .card {
788
  box-shadow: none;
789
  margin-top: 0;
793
  #odp-PageHead {
794
  }
795
  .page-insights #odp-PageHead {
 
796
  top: 40px;
797
  z-index: 3;
798
  }
806
  font-weight: bold;
807
  border: 1px solid rgba(0, 0, 0, 0.1);
808
  border-radius: 3px;
809
+ color: #008000;
810
+ }
811
+ .nav-link.module.notenabled span.module-name {
812
+ text-decoration: line-through;
813
  }
814
  .nav-link.module.notenabled .module-icon:before {
815
  color: rgba(0, 0, 0, 0.4);
826
  font-size: 13px;
827
  }
828
  .odp-outercontainer.icwp-wpsf-insights.settings #odp-PageMain {
 
 
829
  }
830
  .insights_section {
831
  margin-top: 20px;
859
  .icon-sign {
860
  font-size: 14px;
861
  }
 
862
  #collapseConfigSummaryTitle:hover {
863
  cursor: pointer;
864
  }
 
865
  #SectionStats {
866
  overflow: auto;
867
  }
900
  td .timestamp-small {
901
  font-size: smaller;
902
  }
 
903
  .odp-table td.check-column input[type=checkbox],
904
  .odp-table th.check-column input[type=checkbox] {
905
  margin: 0 4px;
908
  color: #739e31;
909
  }
910
  /** END TABLES **/
 
911
  /** Sessions Table **/
912
  th.column-is_secadmin {
913
  width: 120px;
919
  vertical-align: text-bottom;
920
  }
921
  form.add-ip button.add .dashicons {
922
+ vertical-align: middle;
923
  }
924
  .odp-table .actions-block {
925
  font-size: 0.75rem;
949
  font-size: 20px;
950
  } */
951
  /** END IPS Insights **/
 
 
952
  .scan-select .form-text {
953
  white-space: normal;
954
  }
961
  table.scan-table.wp-list-table button.toggle-row {
962
  display: none;
963
  }
 
964
  #ScanResultsTabs {
965
  }
966
  #ScanResultsTabs ul.nav.nav-tabs a.nav-link {
976
  #ScanResultsTabs nav > a.nav-link .badge {
977
  font-size: 12px;
978
  }
 
979
  /**
980
  PTG SCAN TABLES
981
  */
985
  .scan-table-for-slug .tablenav.top {
986
  display: none;
987
  }
 
988
  .card.card-scan_results {
989
  background-color: transparent;
990
  border: 0 none;
1016
  .container-scantable .tablenav.top {
1017
  /*display: none;*/
1018
  }
 
1019
  #TableAdminNotes .tablenav.bottom,
1020
  #TableSessions .tablenav.bottom,
1021
  .container-scantable .tablenav.bottom {
1032
  border-radius: 0;
1033
  border-width: 2px 0;
1034
  }
 
1035
  #navbar-bannerlogo {
1036
  min-width: 170px;
1037
  width: 170px;
1066
  margin: 0;
1067
  border-width: 10px 20px;
1068
  }
 
1069
  /** copied from bootstrap to override WP admin styles */
1070
  .content-options {
1071
  font-size: 14px;
1072
  padding-top: 10px;
1073
  }
1074
+ #ModuleOptionsNav.list-group {
1075
  border: 0 none;
1076
  margin: 0;
1077
  }
1078
+ #ModuleOptionsNav.list-group a {
1079
+ /*display: inline-block;*/
1080
+ padding: 0.5rem 1rem;
 
 
 
1081
  font-size: 14px;
1082
+ /*border: 1px solid transparent;*/
1083
+ /*border-radius: 2px;*/
1084
+ }
1085
+ #ModuleOptionsNav.list-group a.active {
1086
+ background-color: rgba(0, 128, 0, 0.75);
1087
+ border-color: transparent;
1088
+ }
1089
+ #ModuleOptionsNav.nav-tabs a.nav-link > span {
1090
+ border-bottom: 1px dashed rgba(0, 0, 0, 0.2);
1091
  }
1092
  #ModuleOptionsNav.nav-tabs a.nav-link.active,
1093
  #ModuleOptionsNav.nav-tabs a.nav-link.active:hover {
1094
+ background-color: rgba(255, 255, 255, 0.6);
1095
+ border-color: rgba(190, 190, 190, 0.4);
1096
+ color: rgba(0, 128, 0, 1);
1097
+ }
1098
+ #ModuleOptionsNav.nav-tabs a.nav-link.active > span {
1099
+ border-bottom: 0 none;
1100
  }
1101
  #ModuleOptionsNav.nav-tabs a.nav-link:hover {
1102
+ background-color: rgba(238, 238, 238, 0.76);
1103
+ border-color: transparent;
1104
+ }
1105
+ .options-summary {
1106
+ margin-top: 10px;
1107
+ font-style: italic;
1108
+ font-size: 12px;
1109
  }
1110
  .content-options .tab-content {
1111
  border-top: 0 none;
1112
  padding-top: 14px;
1113
  }
1114
  .content-options .form-group.row {
1115
+ /*margin-bottom: 20px;*/
1116
+ padding: 15px 0 25px;
1117
  border-bottom: 1px dashed rgba(0, 0, 0, 0.08);
1118
  }
1119
  .content-options .option-section-summary,
1120
  .content-options .option-description {
1121
  font-size: 12px;
1122
  border: 1px solid rgba(0, 0, 0, 0.06);
 
1123
  padding: 5px 9px;
1124
  background-color: rgba(255, 255, 255, 0.4);
1125
  }
1127
  margin-bottom: 12px;
1128
  padding-top: 8px;
1129
  }
1130
+ .content-options .option_label_name {
1131
+ position: relative;
1132
+ /*display: block;*/
1133
  }
1134
+ .content-options .option_link_info {
1135
+ /*position: absolute;*/
1136
+ /*right: -18px;*/
1137
+ /*top: -5px;*/
1138
+ }
1139
+ .content-options .option_link_info > .dashicons {
1140
+ font-size: 16px;
1141
+ text-decoration: none;
1142
+ width: 1px;
1143
+ margin-left: -3px;
1144
  }
 
1145
  .tooltip .arrow {
1146
  display: none !important;
1147
  }
 
1148
  table.odp-table tr.audit-cat-1 td {
1149
  background-color: #f8fbff;
1150
  }
1154
  table.odp-table tr.audit-cat-3 td {
1155
  background-color: #fffdfd;
1156
  }
 
1157
  .row-sticky td {
1158
  background-color: #5a5a5a;
1159
  position: sticky;
1164
  margin: 0;
1165
  color: #ffffff;
1166
  }
 
1167
  .introjs-helperLayer {
1168
  background-color: rgba(91, 228, 56, 0.34);
1169
+ }
1170
+ /* New css changes */
1171
+ .btn-primary {
1172
+ background-color: #008000;
1173
+ border-color: #008000;
1174
+ }
1175
+ .btn-primary:hover {
1176
+ color: #008000;
1177
+ background-color: #ffffff;
1178
+ border-color: #008000;
1179
+ }
1180
+ input:checked + .icwp-slider {
1181
+ background-color: #008000;
1182
+ }
1183
+ dd, li {
1184
+ margin-bottom: 0;
1185
+ }
1186
+ a {
1187
+ color: #008000;
1188
+ }
1189
+ a:hover {
1190
+ color: #008000;
1191
+ }
1192
+ a:focus .gravatar, a:focus, a:focus .media-icon img {
1193
+ box-shadow: none !important;
1194
+ }
1195
+ .wp-core-ui select {
1196
+ min-height: 38px;
1197
+ }
1198
+ .col-form-label {
1199
+ font-weight: bold;
1200
+ padding-top: 0;
1201
+ }
1202
+ #SectionScanResultsAggregate .card-footer a:hover {
1203
+ color: #ffffff;
1204
+ background-color: #008000;
1205
+ border-color: #008000;
1206
+ }
1207
+ #ScanPageTabsNav > li a {
1208
+ color: #ffffff !important;
1209
+ background-color: #008000;
1210
+ border-color: #008000 !important;
1211
+ }
1212
+ #SessionsFilter .btn-info {
1213
+ color: #ffffff;
1214
+ background-color: #008000;
1215
+ border-color: #008000;
1216
+ }
1217
+ #SessionsFilter .btn-link {
1218
+ color: #008000;
1219
+ }
1220
+ #FilterIpBlack #SubmitForm {
1221
+ color: #ffffff;
1222
+ background-color: #008000;
1223
+ border-color: #008000;
1224
+ }
1225
+ #SectionIpsWhite #SubmitForm {
1226
+ color: #ffffff;
1227
+ background-color: #008000;
1228
+ border-color: #008000;
1229
+ }
1230
+ #NewWhiteIp button {
1231
+ color: #ffffff;
1232
+ background-color: #008000;
1233
+ border-color: #008000;
1234
+ }
1235
+ .btn-outline-dark:hover {
1236
+ color: #ffffff;
1237
+ background-color: #008000;
1238
+ border-color: #008000;
1239
+ }
1240
+ .table-success, .table-success > td, .table-success > th {
1241
+ background-color: rgba(0, 128, 0, 0.20);
1242
+ }
1243
+ #SectionIpsBlack .alert {
1244
+ border-radius: 0;
1245
+ }
1246
+ #SectionIpsWhite .alert {
1247
+ border-radius: 0;
1248
+ }
1249
+ #SectionIpsBlack .form-inline {
1250
+ margin: 10px 0 !important;
1251
+ }
1252
+ #SectionIpsWhite .form-inline {
1253
+ margin: 10px 0 !important;
1254
+ }
1255
+ #SectionIpsBlack .input-group-text {
1256
+ background-color: transparent !important;
1257
+ }
1258
+ #SectionIpsWhite .form-inline {
1259
+ background-color: transparent !important;
1260
+ }
1261
+ a[target="_blank"]:not(.option_link_info)::after,
1262
+ a.new-window-link::after {
1263
+ content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==);
1264
+ margin: 0 3px;
1265
+ }
1266
+ #footer-thankyou {
1267
+ display: none;
1268
+ }
1269
+ a.section_title_info .dashicons {
1270
+ color: rgba(0, 128, 0, 1);
1271
+ }
1272
+ dl.pro-features dt{
1273
+ margin-left:2px;
1274
+ }
1275
+ dl.pro-features dt:before {
1276
+ content: "\1f44d";
1277
+ }
1278
+ dl.pro-features dd {
1279
+ margin-bottom: 10px;
1280
  }
resources/js/ip_detect.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ if ( typeof icwp_wpsf_vars_ipdetect !== 'undefined' ) {
2
+ let iCWP_WPSF_IP_Detect = new function () {
3
+ this.runIpDetect = function () {
4
+ jQuery.get( "https://ipinfo.io", function ( response ) {
5
+ if ( typeof response !== 'undefined' && typeof response[ 'ip' ] !== 'undefined' ) {
6
+ icwp_wpsf_vars_ipdetect.ajax[ 'ip' ] = response[ 'ip' ];
7
+ jQuery.post( ajaxurl, icwp_wpsf_vars_ipdetect.ajax ).always();
8
+ }
9
+ }, "jsonp" );
10
+ };
11
+ }();
12
+ jQuery( document ).ready( function () {
13
+ iCWP_WPSF_IP_Detect.runIpDetect();
14
+ } );
15
+ }
resources/js/plugin.js CHANGED
@@ -21,15 +21,25 @@ var iCWP_WPSF_OptionsPages = new function () {
21
  window.location.hash = jQuery( e.target ).attr( "href" ).substr( 1 );
22
  } );
23
 
24
- jQuery( document ).on( "odp-optsrender", focusTab );
25
  } );
26
  };
27
 
28
- var focusTab = function ( evt ) {
29
  var sActiveTabHash = window.location.hash;
30
  if ( typeof sActiveTabHash !== 'undefined' ) {
31
  jQuery( '#ModuleOptionsNav a[href="' + sActiveTabHash + '"]' ).tab( 'show' );
 
32
  }
 
 
 
 
 
 
 
 
 
33
  };
34
 
35
  }();
21
  window.location.hash = jQuery( e.target ).attr( "href" ).substr( 1 );
22
  } );
23
 
24
+ jQuery( document ).on( "odp-optsrender", onOptsTabRender );
25
  } );
26
  };
27
 
28
+ var onOptsTabRender = function ( evt ) {
29
  var sActiveTabHash = window.location.hash;
30
  if ( typeof sActiveTabHash !== 'undefined' ) {
31
  jQuery( '#ModuleOptionsNav a[href="' + sActiveTabHash + '"]' ).tab( 'show' );
32
+ jQuery( 'html,body' ).scrollTop( 0 );
33
  }
34
+
35
+ jQuery( function () {
36
+ jQuery( 'a.section_title_info' ).popover( {
37
+ placement: 'bottom',
38
+ trigger: 'hover',
39
+ delay: 200,
40
+ html: true
41
+ } )
42
+ } )
43
  };
44
 
45
  }();
src/config/feature-admin_access_restriction.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "admin_access_restriction",
5
  "name": "Security Admin",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "admin_access_restriction",
3
  "properties": {
4
  "slug": "admin_access_restriction",
5
  "name": "Security Admin",
6
+ "sidebar_name": "Security Admin",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "admin_access_restriction",
src/config/feature-audit_trail.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "audit_trail",
5
  "name": "Audit Trail",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "audit_trail",
3
  "properties": {
4
  "slug": "audit_trail",
5
  "name": "Audit Trail",
6
+ "sidebar_name": "Audit Trail",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "audit_trail",
src/config/feature-autoupdates.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "autoupdates",
5
  "name": "Automatic Updates",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "autoupdates",
3
  "properties": {
4
  "slug": "autoupdates",
5
  "name": "Automatic Updates",
6
+ "sidebar_name": "Auto Updates",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "autoupdates",
src/config/feature-comments_filter.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "comments_filter",
5
  "name": "Comments SPAM",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "commentsfilter",
3
  "properties": {
4
  "slug": "comments_filter",
5
  "name": "Comments SPAM",
6
+ "sidebar_name": "SPAM",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "commentsfilter",
src/config/feature-email.php CHANGED
@@ -10,7 +10,8 @@
10
  "premium": false,
11
  "access_restricted": true,
12
  "run_if_whitelisted": true,
13
- "run_if_wpcli": true
 
14
  },
15
  "sections": [
16
  {
10
  "premium": false,
11
  "access_restricted": true,
12
  "run_if_whitelisted": true,
13
+ "run_if_wpcli": true,
14
+ "tracking_exclude": true
15
  },
16
  "sections": [
17
  {
src/config/feature-events.php CHANGED
@@ -10,7 +10,8 @@
10
  "access_restricted": true,
11
  "run_if_whitelisted": true,
12
  "run_if_verified_bot": true,
13
- "run_if_wpcli": true
 
14
  },
15
  "sections": [
16
  {
10
  "access_restricted": true,
11
  "run_if_whitelisted": true,
12
  "run_if_verified_bot": true,
13
+ "run_if_wpcli": true,
14
+ "tracking_exclude": true
15
  },
16
  "sections": [
17
  {
src/config/feature-firewall.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "firewall",
5
  "name": "Firewall",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "firewall",
3
  "properties": {
4
  "slug": "firewall",
5
  "name": "Firewall",
6
+ "sidebar_name": "Firewall",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "firewall",
src/config/feature-hack_protect.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "hack_protect",
5
  "name": "Hack Guard",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "hack_protect",
@@ -572,11 +573,12 @@
572
  "default": false
573
  },
574
  {
575
- "key": "ptg_candiskwrite_at",
576
- "section": "section_non_ui",
577
- "transferable": false,
578
- "type": "integer",
579
- "default": false
 
580
  },
581
  {
582
  "key": "snapshot_users",
@@ -587,46 +589,52 @@
587
  "default": []
588
  },
589
  {
590
- "key": "rt_file_hashes",
591
- "section": "section_non_ui",
592
- "transferable": false,
593
- "type": "array",
594
- "default": []
 
595
  },
596
  {
597
- "key": "rt_file_backup_names",
598
- "section": "section_non_ui",
599
- "transferable": false,
600
- "type": "array",
601
- "default": []
 
602
  },
603
  {
604
- "key": "rt_can_write_files",
605
- "section": "section_non_ui",
606
- "transferable": false,
607
- "type": "array",
608
- "default": []
 
609
  },
610
  {
611
- "key": "scans_to_build",
612
- "section": "section_non_ui",
613
- "transferable": false,
614
- "type": "array",
615
- "default": []
 
616
  },
617
  {
618
- "key": "is_scan_cron",
619
- "section": "section_non_ui",
620
- "transferable": false,
621
- "type": "boolean",
622
- "default": false
 
623
  },
624
  {
625
- "key": "mal_fp_reports",
626
- "section": "section_non_ui",
627
- "transferable": false,
628
- "type": "array",
629
- "default": []
 
630
  }
631
  ],
632
  "definitions": {
3
  "properties": {
4
  "slug": "hack_protect",
5
  "name": "Hack Guard",
6
+ "sidebar_name": "Scanners",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "hack_protect",
573
  "default": false
574
  },
575
  {
576
+ "key": "ptg_candiskwrite_at",
577
+ "section": "section_non_ui",
578
+ "transferable": false,
579
+ "tracking_exclude": true,
580
+ "type": "integer",
581
+ "default": false
582
  },
583
  {
584
  "key": "snapshot_users",
589
  "default": []
590
  },
591
  {
592
+ "key": "rt_file_hashes",
593
+ "section": "section_non_ui",
594
+ "transferable": false,
595
+ "tracking_exclude": true,
596
+ "type": "array",
597
+ "default": []
598
  },
599
  {
600
+ "key": "rt_file_backup_names",
601
+ "section": "section_non_ui",
602
+ "transferable": false,
603
+ "tracking_exclude": true,
604
+ "type": "array",
605
+ "default": []
606
  },
607
  {
608
+ "key": "rt_can_write_files",
609
+ "section": "section_non_ui",
610
+ "transferable": false,
611
+ "tracking_exclude": true,
612
+ "type": "array",
613
+ "default": []
614
  },
615
  {
616
+ "key": "scans_to_build",
617
+ "section": "section_non_ui",
618
+ "transferable": false,
619
+ "tracking_exclude": true,
620
+ "type": "array",
621
+ "default": []
622
  },
623
  {
624
+ "key": "is_scan_cron",
625
+ "section": "section_non_ui",
626
+ "transferable": false,
627
+ "tracking_exclude": true,
628
+ "type": "boolean",
629
+ "default": false
630
  },
631
  {
632
+ "key": "mal_fp_reports",
633
+ "section": "section_non_ui",
634
+ "transferable": false,
635
+ "tracking_exclude": true,
636
+ "type": "array",
637
+ "default": []
638
  }
639
  ],
640
  "definitions": {
src/config/feature-headers.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "headers",
5
  "name": "HTTP Headers",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "headers",
3
  "properties": {
4
  "slug": "headers",
5
  "name": "HTTP Headers",
6
+ "sidebar_name": "HTTP Headers",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "headers",
src/config/feature-insights.php CHANGED
@@ -14,7 +14,8 @@
14
  "access_restricted": true,
15
  "run_if_whitelisted": true,
16
  "run_if_verified_bot": false,
17
- "run_if_wpcli": false
 
18
  },
19
  "requirements": {
20
  "php": {
14
  "access_restricted": true,
15
  "run_if_whitelisted": true,
16
  "run_if_verified_bot": false,
17
+ "run_if_wpcli": false,
18
+ "tracking_exclude": true
19
  },
20
  "requirements": {
21
  "php": {
src/config/feature-ips.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "ips",
5
  "name": "Block Bad IPs/Visitors",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "ips",
3
  "properties": {
4
  "slug": "ips",
5
  "name": "Block Bad IPs/Visitors",
6
+ "sidebar_name": "IP Blocking",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "ips",
src/config/feature-lockdown.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "lockdown",
5
  "name": "WP Lockdown",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "lockdown",
3
  "properties": {
4
  "slug": "lockdown",
5
  "name": "WP Lockdown",
6
+ "sidebar_name": "Lockdown",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "lockdown",
src/config/feature-login_protect.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "login_protect",
5
  "name": "Login Guard",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "loginprotect",
3
  "properties": {
4
  "slug": "login_protect",
5
  "name": "Login Guard",
6
+ "sidebar_name": "Login Protection",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "loginprotect",
src/config/feature-plugin.php CHANGED
@@ -2,6 +2,7 @@
2
  "properties": {
3
  "slug": "plugin",
4
  "name": "General Settings",
 
5
  "menu_title": "Settings",
6
  "show_module_menu_item": true,
7
  "show_module_options": true,
@@ -418,6 +419,7 @@
418
  {
419
  "key": "openssl_private_key",
420
  "transferable": false,
 
421
  "section": "section_non_ui",
422
  "type": "text",
423
  "default": ""
@@ -469,19 +471,31 @@
469
  "storage_key": "ips",
470
  "load_priority": 15
471
  },
 
 
 
 
 
 
472
  {
473
  "slug": "hack_protect",
474
  "storage_key": "hack_protect"
475
  },
476
  {
477
- "slug": "login_protect",
478
- "storage_key": "loginprotect"
 
 
479
  },
480
  {
481
  "slug": "firewall",
482
  "storage_key": "firewall",
483
  "load_priority": 1000
484
  },
 
 
 
 
485
  {
486
  "slug": "user_management",
487
  "storage_key": "user_management"
@@ -490,18 +504,6 @@
490
  "slug": "comments_filter",
491
  "storage_key": "commentsfilter"
492
  },
493
- {
494
- "slug": "autoupdates",
495
- "storage_key": "autoupdates"
496
- },
497
- {
498
- "slug": "headers",
499
- "storage_key": "headers"
500
- },
501
- {
502
- "slug": "lockdown",
503
- "storage_key": "lockdown"
504
- },
505
  {
506
  "slug": "events",
507
  "storage_key": "events",
@@ -513,21 +515,21 @@
513
  "load_priority": 5
514
  },
515
  {
516
- "slug": "audit_trail",
517
- "storage_key": "audit_trail",
518
- "load_priority": 11,
519
- "hidden": false
520
  },
521
  {
522
- "slug": "traffic",
523
- "storage_key": "traffic",
524
- "load_priority": 12,
525
- "min_php": "5.4"
526
  },
527
  {
528
- "slug": "license",
529
- "storage_key": "license",
530
- "load_priority": 10
 
 
 
531
  },
532
  {
533
  "slug": "email",
2
  "properties": {
3
  "slug": "plugin",
4
  "name": "General Settings",
5
+ "sidebar_name": "General",
6
  "menu_title": "Settings",
7
  "show_module_menu_item": true,
8
  "show_module_options": true,
419
  {
420
  "key": "openssl_private_key",
421
  "transferable": false,
422
+ "sensitive": true,
423
  "section": "section_non_ui",
424
  "type": "text",
425
  "default": ""
471
  "storage_key": "ips",
472
  "load_priority": 15
473
  },
474
+ {
475
+ "slug": "audit_trail",
476
+ "storage_key": "audit_trail",
477
+ "load_priority": 11,
478
+ "hidden": false
479
+ },
480
  {
481
  "slug": "hack_protect",
482
  "storage_key": "hack_protect"
483
  },
484
  {
485
+ "slug": "traffic",
486
+ "storage_key": "traffic",
487
+ "load_priority": 12,
488
+ "min_php": "5.4"
489
  },
490
  {
491
  "slug": "firewall",
492
  "storage_key": "firewall",
493
  "load_priority": 1000
494
  },
495
+ {
496
+ "slug": "login_protect",
497
+ "storage_key": "loginprotect"
498
+ },
499
  {
500
  "slug": "user_management",
501
  "storage_key": "user_management"
504
  "slug": "comments_filter",
505
  "storage_key": "commentsfilter"
506
  },
 
 
 
 
 
 
 
 
 
 
 
 
507
  {
508
  "slug": "events",
509
  "storage_key": "events",
515
  "load_priority": 5
516
  },
517
  {
518
+ "slug": "license",
519
+ "storage_key": "license",
520
+ "load_priority": 10
 
521
  },
522
  {
523
+ "slug": "autoupdates",
524
+ "storage_key": "autoupdates"
 
 
525
  },
526
  {
527
+ "slug": "headers",
528
+ "storage_key": "headers"
529
+ },
530
+ {
531
+ "slug": "lockdown",
532
+ "storage_key": "lockdown"
533
  },
534
  {
535
  "slug": "email",
src/config/feature-sessions.php CHANGED
@@ -12,7 +12,8 @@
12
  "auto_load_processor": true,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": true,
15
- "run_if_wpcli": false
 
16
  },
17
  "sections": [
18
  {
12
  "auto_load_processor": true,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": true,
15
+ "run_if_wpcli": false,
16
+ "tracking_exclude": true
17
  },
18
  "sections": [
19
  {
src/config/feature-traffic.php CHANGED
@@ -3,6 +3,7 @@
3
  "properties": {
4
  "slug": "traffic",
5
  "name": "Traffic Watch",
 
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "traffic",
@@ -33,8 +34,8 @@
33
  },
34
  {
35
  "slug": "section_traffic_limiter",
36
- "title": "Traffic Limiter",
37
- "title_short": "Options",
38
  "summary": [
39
  "Purpose - Provides ability to restrict excessive requests from a single visitor.",
40
  "Recommendation - These settings are dependent on your requirements."
@@ -66,6 +67,17 @@
66
  "summary": "Enable (or Disable) The Traffic Watch Module",
67
  "description": "Un-Checking this option will completely disable the Traffic Watch module."
68
  },
 
 
 
 
 
 
 
 
 
 
 
69
  {
70
  "key": "type_exclusions",
71
  "section": "section_traffic_options",
@@ -115,6 +127,7 @@
115
  {
116
  "key": "custom_exclusions",
117
  "section": "section_traffic_options",
 
118
  "default": [],
119
  "type": "array",
120
  "link_info": "https://shsec.io/ec",
@@ -138,6 +151,7 @@
138
  {
139
  "key": "max_entries",
140
  "section": "section_traffic_options",
 
141
  "default": 1000,
142
  "min": 0,
143
  "type": "integer",
@@ -158,10 +172,22 @@
158
  "summary": "Auto Disable Traffic Logging After 1 Week",
159
  "description": "Turn on to prevent unnecessary long-term traffic logging. Timer resets each time you save."
160
  },
 
 
 
 
 
 
 
 
 
 
 
 
161
  {
162
  "key": "limit_requests",
163
- "section": "section_non_ui",
164
- "default": "20",
165
  "min": 0,
166
  "type": "integer",
167
  "link_info": "",
@@ -172,8 +198,8 @@
172
  },
173
  {
174
  "key": "limit_time_span",
175
- "section": "section_non_ui",
176
- "default": "20",
177
  "min": 0,
178
  "type": "integer",
179
  "link_info": "",
3
  "properties": {
4
  "slug": "traffic",
5
  "name": "Traffic Watch",
6
+ "sidebar_name": "Traffic",
7
  "show_module_menu_item": false,
8
  "show_module_options": true,
9
  "storage_key": "traffic",
34
  },
35
  {
36
  "slug": "section_traffic_limiter",
37
+ "title": "Traffic Rate Limiting",
38
+ "title_short": "Rate Limiting",
39
  "summary": [
40
  "Purpose - Provides ability to restrict excessive requests from a single visitor.",
41
  "Recommendation - These settings are dependent on your requirements."
67
  "summary": "Enable (or Disable) The Traffic Watch Module",
68
  "description": "Un-Checking this option will completely disable the Traffic Watch module."
69
  },
70
+ {
71
+ "key": "enable_logger",
72
+ "section": "section_traffic_options",
73
+ "default": "N",
74
+ "type": "checkbox",
75
+ "link_info": "",
76
+ "link_blog": "",
77
+ "name": "Enable Traffic Logger",
78
+ "summary": "Turn On The Traffic Logging Feature",
79
+ "description": "Enable or disable the ability to log and monitor requests to your site."
80
+ },
81
  {
82
  "key": "type_exclusions",
83
  "section": "section_traffic_options",
127
  {
128
  "key": "custom_exclusions",
129
  "section": "section_traffic_options",
130
+ "premium": true,
131
  "default": [],
132
  "type": "array",
133
  "link_info": "https://shsec.io/ec",
151
  {
152
  "key": "max_entries",
153
  "section": "section_traffic_options",
154
+ "premium": true,
155
  "default": 1000,
156
  "min": 0,
157
  "type": "integer",
172
  "summary": "Auto Disable Traffic Logging After 1 Week",
173
  "description": "Turn on to prevent unnecessary long-term traffic logging. Timer resets each time you save."
174
  },
175
+ {
176
+ "key": "enable_limiter",
177
+ "section": "section_traffic_limiter",
178
+ "premium": true,
179
+ "default": "N",
180
+ "type": "checkbox",
181
+ "link_info": "https://shsec.io/gw",
182
+ "link_blog": "https://shsec.io/gx",
183
+ "name": "Enable Rate Limiting",
184
+ "summary": "Turn On The Rate Limiting Feature",
185
+ "description": "Enable or disable the rate limiting feature according to your rate limiting parameters."
186
+ },
187
  {
188
  "key": "limit_requests",
189
+ "section": "section_traffic_limiter",
190
+ "default": "60",
191
  "min": 0,
192
  "type": "integer",
193
  "link_info": "",
198
  },
199
  {
200
  "key": "limit_time_span",
201
+ "section": "section_traffic_limiter",
202
+ "default": "60",
203
  "min": 0,
204
  "type": "integer",
205
  "link_info": "",
src/config/feature-user_management.php CHANGED
@@ -2,6 +2,7 @@
2
  "slug": "user_management",
3
  "properties": {
4
  "name": "User Management",
 
5
  "show_module_menu_item": false,
6
  "show_module_options": true,
7
  "storage_key": "user_management",
2
  "slug": "user_management",
3
  "properties": {
4
  "name": "User Management",
5
+ "sidebar_name": "Users",
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "user_management",
src/features/admin_access_restriction.php CHANGED
@@ -40,8 +40,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
40
  * @return bool
41
  */
42
  public function hasSecAdminUsers() {
43
- $aUsers = $this->getSecurityAdminUsers();
44
- return !empty( $aUsers );
45
  }
46
 
47
  /**
40
  * @return bool
41
  */
42
  public function hasSecAdminUsers() {
43
+ return count( $this->getSecurityAdminUsers() ) > 0;
 
44
  }
45
 
46
  /**
src/features/base.php CHANGED
@@ -84,6 +84,9 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
84
  */
85
  protected function setupHooks( $aModProps ) {
86
  $nRunPriority = isset( $aModProps[ 'load_priority' ] ) ? $aModProps[ 'load_priority' ] : 100;
 
 
 
87
  add_action( $this->prefix( 'run_processors' ), [ $this, 'onRunProcessors' ], $nRunPriority );
88
  add_action( 'init', [ $this, 'onWpInit' ], 1 );
89
  add_action( $this->prefix( 'import_options' ), [ $this, 'processImportOptions' ] );
@@ -288,6 +291,9 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
288
  return $bMeetsReqs;
289
  }
290
 
 
 
 
291
  /**
292
  */
293
  public function onRunProcessors() {
@@ -693,10 +699,10 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
693
  * @return array
694
  */
695
  protected function buildSummaryData() {
696
- $oOptsVo = $this->getOptions();
697
- $sMenuTitle = $oOptsVo->getFeatureProperty( 'menu_title' );
698
 
699
- $aSections = $oOptsVo->getSections();
700
  foreach ( $aSections as $sSlug => $aSection ) {
701
  try {
702
  $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
@@ -710,17 +716,18 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
710
  }
711
 
712
  $aSum = [
713
- 'enabled' => $this->isEnabledForUiSummary(),
714
- 'active' => $this->isThisModulePage() || $this->isPage_InsightsThisModule(),
715
- 'slug' => $this->getSlug(),
716
- 'name' => $this->getMainFeatureName(),
717
- 'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : __( $sMenuTitle, 'wp-simple-firewall' ),
718
- 'href' => network_admin_url( 'admin.php?page='.$this->getModSlug() ),
719
- 'sections' => $aSections,
720
- 'options' => [],
 
721
  ];
722
 
723
- foreach ( $oOptsVo->getVisibleOptionsKeys() as $sOptKey ) {
724
  try {
725
  $aOptData = $this->getStrings()->getOptionStrings( $sOptKey );
726
  $aOptData[ 'href' ] = $this->getUrl_DirectLinkToOption( $sOptKey );
@@ -730,11 +737,9 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
730
  }
731
  }
732
 
733
- // $aSum[ 'content' ] = $this->renderTemplate( 'snippets/summary_single', $aSum );
734
  $aSum[ 'tooltip' ] = sprintf(
735
- '%s%s',
736
- $aSum[ 'name' ],
737
- ( $aSum[ 'enabled' ] ? '' : ' ('.strtolower( __( 'Disabled', 'wp-simple-firewall' ) ).')' )
738
  );
739
  return $aSum;
740
  }
@@ -1132,10 +1137,11 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
1132
 
1133
  // add strings
1134
  try {
1135
- $aOptParams = Services::DataManipulation()->mergeArraysRecursive(
1136
- $aOptParams,
1137
- $this->getStrings()->getOptionStrings( $aOptParams[ 'key' ] )
1138
- );
 
1139
  }
1140
  catch ( \Exception $oE ) {
1141
  }
@@ -1185,12 +1191,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
1185
  protected function handleModAction( $sAction ) {
1186
  }
1187
 
1188
- /**
1189
- * @deprecated 8.6.2
1190
- */
1191
- protected function handleModRequest() {
1192
- }
1193
-
1194
  /**
1195
  * @throws \Exception
1196
  */
@@ -1617,7 +1617,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
1617
  public function renderOptionsForm() {
1618
 
1619
  if ( $this->canDisplayOptionsForm() ) {
1620
- $sTemplate = 'snippets/options_form.twig';
1621
  }
1622
  else {
1623
  $sTemplate = 'subfeature-access_restricted';
@@ -1754,7 +1754,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends Shield\Deprecated\Foundatio
1754
  */
1755
  public function collectOptionsForTracking() {
1756
  $oVO = $this->getOptions();
1757
- $aOptionsData = $this->getOptions()->getOptionsMaskSensitive();
1758
  foreach ( $aOptionsData as $sOption => $mValue ) {
1759
  unset( $aOptionsData[ $sOption ] );
1760
  // some cleaning to ensure we don't have disallowed characters
84
  */
85
  protected function setupHooks( $aModProps ) {
86
  $nRunPriority = isset( $aModProps[ 'load_priority' ] ) ? $aModProps[ 'load_priority' ] : 100;
87
+ add_action( $this->prefix( 'modules_loaded' ), function () {
88
+ $this->onModulesLoaded();
89
+ }, $nRunPriority );
90
  add_action( $this->prefix( 'run_processors' ), [ $this, 'onRunProcessors' ], $nRunPriority );
91
  add_action( 'init', [ $this, 'onWpInit' ], 1 );
92
  add_action( $this->prefix( 'import_options' ), [ $this, 'processImportOptions' ] );
291
  return $bMeetsReqs;
292
  }
293
 
294
+ protected function onModulesLoaded() {
295
+ }
296
+
297
  /**
298
  */
299
  public function onRunProcessors() {
699
  * @return array
700
  */
701
  protected function buildSummaryData() {
702
+ $oOpts = $this->getOptions();
703
+ $sMenuTitle = $oOpts->getFeatureProperty( 'menu_title' );
704
 
705
+ $aSections = $oOpts->getSections();
706
  foreach ( $aSections as $sSlug => $aSection ) {
707
  try {
708
  $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
716
  }
717
 
718
  $aSum = [
719
+ 'enabled' => $this->isEnabledForUiSummary(),
720
+ 'active' => $this->isThisModulePage() || $this->isPage_InsightsThisModule(),
721
+ 'slug' => $this->getSlug(),
722
+ 'name' => $this->getMainFeatureName(),
723
+ 'sidebar_name' => $oOpts->getFeatureProperty( 'sidebar_name' ),
724
+ 'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : __( $sMenuTitle, 'wp-simple-firewall' ),
725
+ 'href' => network_admin_url( 'admin.php?page='.$this->getModSlug() ),
726
+ 'sections' => $aSections,
727
+ 'options' => [],
728
  ];
729
 
730
+ foreach ( $oOpts->getVisibleOptionsKeys() as $sOptKey ) {
731
  try {
732
  $aOptData = $this->getStrings()->getOptionStrings( $sOptKey );
733
  $aOptData[ 'href' ] = $this->getUrl_DirectLinkToOption( $sOptKey );
737
  }
738
  }
739
 
 
740
  $aSum[ 'tooltip' ] = sprintf(
741
+ '%s',
742
+ empty( $aSum[ 'sidebar_name' ] ) ? $aSum[ 'name' ] : __( $aSum[ 'sidebar_name' ], 'wp-simple-firewall' )
 
743
  );
744
  return $aSum;
745
  }
1137
 
1138
  // add strings
1139
  try {
1140
+ $aOptStrings = $this->getStrings()->getOptionStrings( $aOptParams[ 'key' ] );
1141
+ if ( is_array( $aOptStrings[ 'description' ] ) ) {
1142
+ $aOptStrings[ 'description' ] = implode( "<br/>", $aOptStrings[ 'description' ] );
1143
+ }
1144
+ $aOptParams = Services::DataManipulation()->mergeArraysRecursive( $aOptParams, $aOptStrings );
1145
  }
1146
  catch ( \Exception $oE ) {
1147
  }
1191
  protected function handleModAction( $sAction ) {
1192
  }
1193
 
 
 
 
 
 
 
1194
  /**
1195
  * @throws \Exception
1196
  */
1617
  public function renderOptionsForm() {
1618
 
1619
  if ( $this->canDisplayOptionsForm() ) {
1620
+ $sTemplate = 'components/options_form/main.twig';
1621
  }
1622
  else {
1623
  $sTemplate = 'subfeature-access_restricted';
1754
  */
1755
  public function collectOptionsForTracking() {
1756
  $oVO = $this->getOptions();
1757
+ $aOptionsData = $this->getOptions()->getOptionsForTracking();
1758
  foreach ( $aOptionsData as $sOption => $mValue ) {
1759
  unset( $aOptionsData[ $sOption ] );
1760
  // some cleaning to ensure we don't have disallowed characters
src/features/base_wpsf.php CHANGED
@@ -11,11 +11,6 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
11
  */
12
  protected static $bIsVerifiedBot;
13
 
14
- /**
15
- * @var int
16
- */
17
- private static $nIpOffenceCount = 0;
18
-
19
  /**
20
  * @var bool
21
  */
@@ -368,15 +363,17 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
368
 
369
  /**
370
  * @return bool
 
371
  */
372
  public function getIfIpTransgressed() {
373
- return $this->getIpOffenceCount() > 0;
374
  }
375
 
376
  /**
377
  * @return int
 
378
  */
379
  public function getIpOffenceCount() {
380
- return isset( self::$nIpOffenceCount ) ? self::$nIpOffenceCount : 0;
381
  }
382
  }
11
  */
12
  protected static $bIsVerifiedBot;
13
 
 
 
 
 
 
14
  /**
15
  * @var bool
16
  */
363
 
364
  /**
365
  * @return bool
366
+ * @deprecated 8.7.0
367
  */
368
  public function getIfIpTransgressed() {
369
+ return false;
370
  }
371
 
372
  /**
373
  * @return int
374
+ * @deprecated 8.7.0
375
  */
376
  public function getIpOffenceCount() {
377
+ return 0;
378
  }
379
  }
src/features/comments_filter.php CHANGED
@@ -207,12 +207,4 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
207
  public function getSpamBlacklistFile() {
208
  return $this->getCon()->getPluginCachePath( 'spamblacklist.txt' );
209
  }
210
-
211
- /**
212
- * @return int
213
- * @deprecated 8.6.0
214
- */
215
- public function getTokenCooldown() {
216
- return (int)$this->getOpt( 'comments_cooldown_interval' );
217
- }
218
  }
207
  public function getSpamBlacklistFile() {
208
  return $this->getCon()->getPluginCachePath( 'spamblacklist.txt' );
209
  }
 
 
 
 
 
 
 
 
210
  }
src/features/hack_protect.php CHANGED
@@ -17,7 +17,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
17
  private $aScanCons;
18
 
19
  protected function doPostConstruction() {
20
- parent::doPostConstruction();
21
  $this->setCustomCronSchedules();
22
  }
23
 
@@ -137,15 +136,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
137
  return ( $oEntry instanceof Shield\Databases\Events\EntryVO ) ? $oEntry->created_at : 0;
138
  }
139
 
140
- /**
141
- * @param string $sScan ptg, wcf, ufc, wpv
142
- * @return bool
143
- * @deprecated 8.5.5
144
- */
145
- public function getScanHasProblem( $sScan ) {
146
- return $this->getScanCon( $sScan )->getScanHasProblem();
147
- }
148
-
149
  /**
150
  * @return int
151
  */
@@ -625,7 +615,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
625
  'rec' => __( 'Automatic WordPress Core File scanner should be turned-on.', 'wp-simple-firewall' )
626
  ];
627
  }
628
- elseif ( $this->getScanHasProblem( 'wcf' ) ) {
629
  $aNotices[ 'messages' ][ 'wcf' ] = [
630
  'title' => $aScanNames[ 'wcf' ],
631
  'message' => __( 'Modified WordPress core files found.', 'wp-simple-firewall' ),
@@ -646,7 +636,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
646
  'rec' => __( 'Automatic scanning for non-WordPress core files is recommended.', 'wp-simple-firewall' )
647
  ];
648
  }
649
- elseif ( $this->getScanHasProblem( 'ufc' ) ) {
650
  $aNotices[ 'messages' ][ 'ufc' ] = [
651
  'title' => $aScanNames[ 'ufc' ],
652
  'message' => __( 'Unrecognised files found in WordPress Core directory.', 'wp-simple-firewall' ),
@@ -689,7 +679,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
689
  'rec' => __( 'Automatic detection of vulnerabilities is recommended.', 'wp-simple-firewall' )
690
  ];
691
  }
692
- elseif ( $this->getScanHasProblem( 'wpv' ) ) {
693
  $aNotices[ 'messages' ][ 'wpv' ] = [
694
  'title' => $aScanNames[ 'wpv' ],
695
  'message' => __( 'At least 1 item has known vulnerabilities.', 'wp-simple-firewall' ),
@@ -710,7 +700,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
710
  'rec' => __( 'Automatic detection of abandoned plugins is recommended.', 'wp-simple-firewall' )
711
  ];
712
  }
713
- elseif ( $this->getScanHasProblem( 'apc' ) ) {
714
  $aNotices[ 'messages' ][ 'apc' ] = [
715
  'title' => $aScanNames[ 'apc' ],
716
  'message' => __( 'At least 1 plugin on your site is abandoned.', 'wp-simple-firewall' ),
@@ -731,7 +721,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
731
  'rec' => __( 'Automatic detection of Malware is recommended.', 'wp-simple-firewall' )
732
  ];
733
  }
734
- elseif ( $this->getScanHasProblem( 'mal' ) ) {
735
  $aNotices[ 'messages' ][ 'mal' ] = [
736
  'title' => $aScanNames[ 'mal' ],
737
  'message' => __( 'At least 1 file with potential Malware has been discovered.', 'wp-simple-firewall' ),
17
  private $aScanCons;
18
 
19
  protected function doPostConstruction() {
 
20
  $this->setCustomCronSchedules();
21
  }
22
 
136
  return ( $oEntry instanceof Shield\Databases\Events\EntryVO ) ? $oEntry->created_at : 0;
137
  }
138
 
 
 
 
 
 
 
 
 
 
139
  /**
140
  * @return int
141
  */
615
  'rec' => __( 'Automatic WordPress Core File scanner should be turned-on.', 'wp-simple-firewall' )
616
  ];
617
  }
618
+ elseif ( $this->getScanCon( 'wcf' )->getScanHasProblem() ) {
619
  $aNotices[ 'messages' ][ 'wcf' ] = [
620
  'title' => $aScanNames[ 'wcf' ],
621
  'message' => __( 'Modified WordPress core files found.', 'wp-simple-firewall' ),
636
  'rec' => __( 'Automatic scanning for non-WordPress core files is recommended.', 'wp-simple-firewall' )
637
  ];
638
  }
639
+ elseif ( $this->getScanCon( 'ufc' )->getScanHasProblem() ) {
640
  $aNotices[ 'messages' ][ 'ufc' ] = [
641
  'title' => $aScanNames[ 'ufc' ],
642
  'message' => __( 'Unrecognised files found in WordPress Core directory.', 'wp-simple-firewall' ),
679
  'rec' => __( 'Automatic detection of vulnerabilities is recommended.', 'wp-simple-firewall' )
680
  ];
681
  }
682
+ elseif ( $this->getScanCon( 'wpv' )->getScanHasProblem() ) {
683
  $aNotices[ 'messages' ][ 'wpv' ] = [
684
  'title' => $aScanNames[ 'wpv' ],
685
  'message' => __( 'At least 1 item has known vulnerabilities.', 'wp-simple-firewall' ),
700
  'rec' => __( 'Automatic detection of abandoned plugins is recommended.', 'wp-simple-firewall' )
701
  ];
702
  }
703
+ elseif ( $this->getScanCon( 'apc' )->getScanHasProblem() ) {
704
  $aNotices[ 'messages' ][ 'apc' ] = [
705
  'title' => $aScanNames[ 'apc' ],
706
  'message' => __( 'At least 1 plugin on your site is abandoned.', 'wp-simple-firewall' ),
721
  'rec' => __( 'Automatic detection of Malware is recommended.', 'wp-simple-firewall' )
722
  ];
723
  }
724
+ elseif ( $this->getScanCon( 'mal' )->getScanHasProblem() ) {
725
  $aNotices[ 'messages' ][ 'mal' ] = [
726
  'title' => $aScanNames[ 'mal' ],
727
  'message' => __( 'At least 1 file with potential Malware has been discovered.', 'wp-simple-firewall' ),
src/features/insights.php CHANGED
@@ -5,8 +5,7 @@ use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWpsf {
7
 
8
- protected function doPostConstruction() {
9
- parent::doPostConstruction();
10
  $this->maybeRedirectToAdmin();
11
  }
12
 
@@ -35,7 +34,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
35
  $sNavSection = $oReq->query( 'inav', 'overview' );
36
  $sSubNavSection = $oReq->query( 'subnav' );
37
 
38
- /** @var ICWP_WPSF_FeatureHandler_Traffic $oTrafficMod */
39
  $oTrafficMod = $oCon->getModule( 'traffic' );
40
  /** @var Shield\Databases\Traffic\Select $oTrafficSelector */
41
  $oTrafficSelector = $oTrafficMod->getDbHandler_Traffic()->getQuerySelector();
@@ -445,6 +444,8 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
445
  wp_enqueue_style( $sUnique );
446
  $aDeps[] = $sUnique;
447
  }
 
 
448
  break;
449
 
450
  case 'scans':
@@ -518,6 +519,28 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
518
  }
519
  }
520
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
  private function buildVars_Reports() {
522
  $oEvtsMod = $this->getCon()->getModule_Events();
523
  /** @var Shield\Modules\Events\Strings $oStrs */
5
 
6
  class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWpsf {
7
 
8
+ protected function onModulesLoaded() {
 
9
  $this->maybeRedirectToAdmin();
10
  }
11
 
34
  $sNavSection = $oReq->query( 'inav', 'overview' );
35
  $sSubNavSection = $oReq->query( 'subnav' );
36
 
37
+ /** @var \ICWP_WPSF_FeatureHandler_Traffic $oTrafficMod */
38
  $oTrafficMod = $oCon->getModule( 'traffic' );
39
  /** @var Shield\Databases\Traffic\Select $oTrafficSelector */
40
  $oTrafficSelector = $oTrafficMod->getDbHandler_Traffic()->getQuerySelector();
444
  wp_enqueue_style( $sUnique );
445
  $aDeps[] = $sUnique;
446
  }
447
+
448
+ $this->includeScriptIpDetect();
449
  break;
450
 
451
  case 'scans':
519
  }
520
  }
521
 
522
+ private function includeScriptIpDetect() {
523
+ $oCon = $this->getCon();
524
+ /** @var Shield\Modules\Plugin\Options $oOpts */
525
+ $oOpts = $oCon->getModule_Plugin()->getOptions();
526
+ if ( $oOpts->isIpSourceAutoDetect() ) {
527
+ wp_register_script(
528
+ $oCon->prefix( 'ip_detect' ),
529
+ $oCon->getPluginUrl_Js( 'ip_detect.js' ),
530
+ [],
531
+ $oCon->getVersion(),
532
+ true
533
+ );
534
+ wp_enqueue_script( $oCon->prefix( 'ip_detect' ) );
535
+
536
+ wp_localize_script(
537
+ $oCon->prefix( 'ip_detect' ),
538
+ 'icwp_wpsf_vars_ipdetect',
539
+ [ 'ajax' => $oCon->getModule_Plugin()->getAjaxActionData( 'ipdetect' ) ]
540
+ );
541
+ }
542
+ }
543
+
544
  private function buildVars_Reports() {
545
  $oEvtsMod = $this->getCon()->getModule_Events();
546
  /** @var Shield\Modules\Events\Strings $oStrs */
src/features/license.php CHANGED
@@ -3,7 +3,6 @@
3
  use FernleafSystems\Wordpress\Plugin\Shield;
4
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\License;
5
  use FernleafSystems\Wordpress\Services\Services;
6
- use FernleafSystems\Wordpress\Services\Utilities;
7
 
8
  class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf {
9
 
@@ -131,13 +130,6 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
131
  add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] );
132
  }
133
 
134
- /**
135
- * @deprecated 8.6.2
136
- */
137
- protected function updateHandler() {
138
- $this->getWpHashesTokenManager()->getToken();
139
- }
140
-
141
  public function onWpLoaded() {
142
  $this->getWpHashesTokenManager()->run();
143
  }
@@ -158,231 +150,6 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
158
  parent::onPluginShutdown();
159
  }
160
 
161
- /**
162
- * @return Shield\License\EddLicenseVO
163
- * @deprecated 8.6.2
164
- */
165
- protected function loadLicense() {
166
- return $this->getLicenseHandler()->getLicense();
167
- }
168
-
169
- /**
170
- * @return array
171
- * @deprecated 8.6.2
172
- */
173
- protected function getLicenseData() {
174
- $aData = $this->getOpt( 'license_data', [] );
175
- return is_array( $aData ) ? $aData : [];
176
- }
177
-
178
- /**
179
- * @return $this
180
- * @deprecated 8.6.2
181
- */
182
- public function clearLicenseData() {
183
- return $this->setOpt( 'license_data', [] );
184
- }
185
-
186
- /**
187
- * @param Utilities\Licenses\EddLicenseVO $oLic
188
- * @return $this
189
- * @deprecated 8.6.2
190
- */
191
- protected function setLicenseData( $oLic ) {
192
- return $this->setOpt( 'license_data', $oLic->getRawDataAsArray() );
193
- }
194
-
195
- /**
196
- * @param string $sDeactivatedReason
197
- * @deprecated 8.6.2
198
- */
199
- public function deactivate( $sDeactivatedReason = '' ) {
200
- }
201
-
202
- /**
203
- * License check normally only happens when the verification_at expires (~3 days)
204
- * for a currently valid license.
205
- * @param bool $bForceCheck
206
- * @return $this
207
- * @deprecated 8.6.2
208
- */
209
- public function verifyLicense( $bForceCheck = true ) {
210
- try {
211
- $this->getLicenseHandler()->verify( $bForceCheck );
212
- }
213
- catch ( Exception $oE ) {
214
- }
215
- return $this;
216
- }
217
-
218
- /**
219
- * @return bool
220
- * @deprecated 8.6.2
221
- */
222
- private function isLicenseCheckRequired() {
223
- return false;
224
- }
225
-
226
- /**
227
- * @return bool
228
- * @deprecated 8.6.2
229
- */
230
- private function canLicenseCheck() {
231
- return false;
232
- }
233
-
234
- /**
235
- * @return bool
236
- * @deprecated 8.6.2
237
- */
238
- private function canLicenseCheck_FileFlag() {
239
- return false;
240
- }
241
-
242
- /**
243
- * @return $this
244
- * @deprecated 8.6.2
245
- */
246
- private function touchLicenseCheckFileFlag() {
247
- Services::WpFs()->touch( $this->getCon()->getPath_Flags( 'license_check' ) );
248
- return $this;
249
- }
250
-
251
- /**
252
- * @return bool
253
- * @deprecated 8.6.2
254
- */
255
- protected function isLicenseMaybeExpiring() {
256
- return false;
257
- }
258
-
259
- /**
260
- * @return $this
261
- * @deprecated 8.6.2
262
- */
263
- protected function activateLicense() {
264
- return $this;
265
- }
266
-
267
- /**
268
- * @deprecated 8.6.2
269
- */
270
- protected function sendLicenseWarningEmail() {
271
- }
272
-
273
- /**
274
- * @deprecated 8.6.2
275
- */
276
- private function sendLicenseDeactivatedEmail() {
277
- }
278
-
279
- /**
280
- * @return int
281
- * @deprecated 8.6.2
282
- */
283
- protected function getLicenseActivatedAt() {
284
- return $this->getOpt( 'license_activated_at' );
285
- }
286
-
287
- /**
288
- * @return int
289
- * @deprecated 8.6.2
290
- */
291
- protected function getLicenseDeactivatedAt() {
292
- return $this->getOpt( 'license_deactivated_at' );
293
- }
294
-
295
- /**
296
- * @return string
297
- * @deprecated 8.6.2
298
- */
299
- public function getLicenseItemName() {
300
- return $this->getLicenseHandler()->getLicense()->is_central ?
301
- $this->getDef( 'license_item_name_sc' ) :
302
- $this->getDef( 'license_item_name' );
303
- }
304
-
305
- /**
306
- * @return int
307
- * @deprecated 8.6.2
308
- */
309
- protected function getLicenseLastCheckedAt() {
310
- return $this->getOpt( 'license_last_checked_at' );
311
- }
312
-
313
- /**
314
- * @param int $nTimePeriod
315
- * @return bool
316
- * @deprecated 8.6.2
317
- */
318
- private function getIsLicenseNotCheckedFor( $nTimePeriod ) {
319
- return false;
320
- }
321
-
322
- /**
323
- * @return int
324
- * @deprecated 8.6.2
325
- */
326
- public function getLicenseNotCheckedForInterval() {
327
- return 0;
328
- }
329
-
330
- /**
331
- * @return bool
332
- * @deprecated 8.6.2
333
- */
334
- public function isLicenseActive() {
335
- return $this->getLicenseHandler()->isActive();
336
- }
337
-
338
- /**
339
- * IMPORTANT: Method used by Shield Central. Modify with care.
340
- * We test various data points:
341
- * 1) the key is valid format
342
- * 2) the official license status is 'valid'
343
- * 3) the license is marked as "active"
344
- * 4) the license hasn't expired
345
- * 5) the time since the last check hasn't expired
346
- * @return bool
347
- * @deprecated 8.6.2
348
- */
349
- public function hasValidWorkingLicense() {
350
- return $this->getLicenseHandler()->hasValidWorkingLicense();
351
- }
352
-
353
- /**
354
- * @return bool
355
- * @deprecated 8.6.2
356
- */
357
- protected function isLastVerifiedExpired() {
358
- return false;
359
- }
360
-
361
- /**
362
- * @return bool
363
- * @deprecated 8.6.2
364
- */
365
- protected function isLastVerifiedGraceExpired() {
366
- return false;
367
- }
368
-
369
- /**
370
- * @return bool
371
- * @deprecated 8.6.2
372
- */
373
- protected function isWithinVerifiedGraceExpired() {
374
- return false;
375
- }
376
-
377
- /**
378
- * @param int $nAt
379
- * @return $this
380
- * @deprecated 8.6.2
381
- */
382
- protected function setLicenseLastCheckedAt( $nAt = null ) {
383
- return $this;
384
- }
385
-
386
  /**
387
  * @return string
388
  */
3
  use FernleafSystems\Wordpress\Plugin\Shield;
4
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\License;
5
  use FernleafSystems\Wordpress\Services\Services;
 
6
 
7
  class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf {
8
 
130
  add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] );
131
  }
132
 
 
 
 
 
 
 
 
133
  public function onWpLoaded() {
134
  $this->getWpHashesTokenManager()->run();
135
  }
150
  parent::onPluginShutdown();
151
  }
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  /**
154
  * @return string
155
  */
src/features/login_protect.php CHANGED
@@ -11,15 +11,9 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
11
  */
12
  private $oLoginIntentController;
13
 
14
- /**
15
- * @return bool
16
- * @deprecated 8.6.0
17
- */
18
- public function getIfUseLoginIntentPage() {
19
- return $this->isOpt( 'use_login_intent_page', true );
20
- }
21
-
22
  protected function doExtraSubmitProcessing() {
 
 
23
  /**
24
  * $oWp = $this->loadWpFunctionsProcessor();
25
  * $sCustomLoginPath = $this->cleanLoginUrlPath();
@@ -27,7 +21,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
27
  * $oWp->resavePermalinks();
28
  * }
29
  */
30
- if ( $this->isModuleOptionsRequest() && $this->isEmailAuthenticationOptionOn() && !$this->getIfCanSendEmailVerified() ) {
31
  $this->setIfCanSendEmail( false )
32
  ->sendEmailVerifyCanSend();
33
  }
@@ -64,10 +58,12 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
64
  * @uses wp_redirect()
65
  */
66
  private function processEmailSendVerify() {
 
 
67
  $this->setIfCanSendEmail( true );
68
  $this->saveModOptions();
69
 
70
- if ( $this->getIfCanSendEmailVerified() ) {
71
  $bSuccess = true;
72
  $sMessage = __( 'Email verification completed successfully.', 'wp-simple-firewall' );
73
  }
@@ -150,21 +146,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
150
  return in_array( $sLocationKey, $this->getBotProtectionLocations() );
151
  }
152
 
153
- /**
154
- * @return array
155
- */
156
- public function getEmail2FaRoles() {
157
- $aRoles = $this->getOpt( 'two_factor_auth_user_roles', [] );
158
- if ( empty( $aRoles ) || !is_array( $aRoles ) ) {
159
- $aRoles = $this->getOptEmailTwoFactorRolesDefaults();
160
- $this->setOpt( 'two_factor_auth_user_roles', $aRoles );
161
- }
162
- if ( $this->isPremium() ) {
163
- $aRoles = apply_filters( 'odp-shield-2fa_email_user_roles', $aRoles );
164
- }
165
- return is_array( $aRoles ) ? $aRoles : $this->getOptEmailTwoFactorRolesDefaults();
166
- }
167
-
168
  /**
169
  * @param bool $bAsOptDefaults
170
  * @return array
@@ -234,82 +215,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
234
  return strtoupper( substr( $this->getTwoAuthSecretKey(), 10, 6 ) );
235
  }
236
 
237
- /**
238
- * @param \WP_User $oUser
239
- * @return bool
240
- */
241
- public function canUserMfaSkip( $oUser ) {
242
- $oReq = Services::Request();
243
- if ( $this->getMfaSkipEnabled() ) {
244
- $aHashes = $this->getMfaLoginHashes( $oUser );
245
- $nSkipTime = $this->getMfaSkip()*DAY_IN_SECONDS;
246
-
247
- $sHash = md5( $oReq->getUserAgent() );
248
- $bCanSkip = isset( $aHashes[ $sHash ] )
249
- && ( (int)$aHashes[ $sHash ] + $nSkipTime ) > $oReq->ts();
250
- }
251
- elseif ( $this->getIfSupport3rdParty() && class_exists( 'WC_Social_Login' ) ) {
252
- // custom support for WooCommerce Social login
253
- $oMeta = $this->getCon()->getUserMeta( $oUser );
254
- $bCanSkip = isset( $oMeta->wc_social_login_valid ) ? $oMeta->wc_social_login_valid : false;
255
- }
256
- else {
257
- /**
258
- * TODO: remove the HTTP_REFERER bit once iCWP plugin is updated.
259
- * We want logins from iCWP to skip 2FA. To achieve this, iCWP plugin needs
260
- * to add a TRUE filter on 'odp-shield-2fa_skip' at the point of login.
261
- * Until then, we'll use the HTTP referrer as an indicator
262
- */
263
- $bCanSkip = apply_filters(
264
- 'odp-shield-2fa_skip',
265
- strpos( $oReq->server( 'HTTP_REFERER' ), 'https://app.icontrolwp.com/' ) === 0
266
- );
267
- }
268
- return $bCanSkip;
269
- }
270
-
271
- /**
272
- * @param \WP_User $oUser
273
- * @return $this
274
- */
275
- public function addMfaLoginHash( $oUser ) {
276
- $oReq = Services::Request();
277
- $aHashes = $this->getMfaLoginHashes( $oUser );
278
- $aHashes[ md5( $oReq->getUserAgent() ) ] = $oReq->ts();
279
- $this->getCon()->getCurrentUserMeta()->hash_loginmfa = $aHashes;
280
- return $this;
281
- }
282
-
283
- /**
284
- * @param WP_User $oUser
285
- * @return array
286
- */
287
- public function getMfaLoginHashes( $oUser ) {
288
- $oMeta = $this->getCon()->getUserMeta( $oUser );
289
- $aHashes = $oMeta->hash_loginmfa;
290
- if ( !is_array( $aHashes ) ) {
291
- $aHashes = [];
292
- $oMeta->hash_loginmfa = $aHashes;
293
- }
294
- return $aHashes;
295
- }
296
-
297
- /**
298
- * @return bool
299
- */
300
- public function getMfaSkipEnabled() {
301
- return $this->getMfaSkip() > 0;
302
- }
303
-
304
- /**
305
- * NOTE: DO NOT REPLACE WITH OPTIONS USE AS THIS RETURNS DAYS
306
- * @return int - days
307
- * @deprecated 8.6.0
308
- */
309
- public function getMfaSkip() {
310
- return (int)$this->getOpt( 'mfa_skip', 0 );
311
- }
312
-
313
  /**
314
  * @return string
315
  */
@@ -322,39 +227,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
322
  return $sKey;
323
  }
324
 
325
- /**
326
- * @return bool
327
- * @deprecated 8.6.0
328
- */
329
- public function isEmailAuthenticationOptionOn() {
330
- return $this->isOpt( 'enable_email_authentication', 'Y' );
331
- }
332
-
333
- /**
334
- * Also considers whether email sending ability has been verified
335
- * @return bool
336
- * @deprecated 8.6.0
337
- */
338
- public function isEmailAuthenticationActive() {
339
- return $this->getIfCanSendEmailVerified() && $this->isEmailAuthenticationOptionOn();
340
- }
341
-
342
- /**
343
- * @return bool
344
- * @deprecated 8.6.0
345
- */
346
- public function isEnabledBackupCodes() {
347
- return $this->isPremium() && $this->isOpt( 'allow_backupcodes', 'Y' );
348
- }
349
-
350
- /**
351
- * @return bool
352
- * @deprecated 8.6.0
353
- */
354
- public function isEnabledGoogleAuthenticator() {
355
- return $this->isOpt( 'enable_google_authenticator', 'Y' );
356
- }
357
-
358
  /**
359
  * @return bool
360
  */
@@ -362,22 +234,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
362
  return ( !$this->isOpt( 'enable_google_recaptcha_login', 'disabled' ) && $this->isGoogleRecaptchaReady() );
363
  }
364
 
365
- /**
366
- * @return int
367
- * @deprecated 8.6.0
368
- */
369
- public function getCanSendEmailVerifiedAt() {
370
- return $this->getOpt( 'email_can_send_verified_at' );
371
- }
372
-
373
- /**
374
- * @return bool
375
- * @deprecated 8.6.0
376
- */
377
- public function getIfCanSendEmailVerified() {
378
- return $this->getCanSendEmailVerifiedAt() > 0;
379
- }
380
-
381
  /**
382
  * @return string
383
  */
@@ -409,14 +265,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
409
  return $this->oLoginIntentController;
410
  }
411
 
412
- /**
413
- * @return bool
414
- * @deprecated 8.6.0
415
- */
416
- public function isChainedAuth() {
417
- return $this->isOpt( 'enable_chained_authentication', 'Y' );
418
- }
419
-
420
  /**
421
  * @param bool $bIsChained
422
  * @return $this
@@ -537,24 +385,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
537
  return $sIntegration;
538
  }
539
 
540
- /**
541
- * @return bool
542
- * @deprecated 8.6.0
543
- */
544
- public function isYubikeyActive() {
545
- return $this->isOpt( 'enable_yubikey', 'Y' ) && $this->isYubikeyConfigReady();
546
- }
547
-
548
- /**
549
- * @return bool
550
- * @deprecated 8.6.0
551
- */
552
- private function isYubikeyConfigReady() {
553
- $sAppId = $this->getOpt( 'yubikey_app_id' );
554
- $sApiKey = $this->getOpt( 'yubikey_api_key' );
555
- return !empty( $sAppId ) && !empty( $sApiKey );
556
- }
557
-
558
  /**
559
  * @return bool
560
  */
@@ -592,6 +422,8 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
592
  * @return array
593
  */
594
  public function addInsightsConfigData( $aAllData ) {
 
 
595
  $aThis = [
596
  'strings' => [
597
  'title' => __( 'Login Guard', 'wp-simple-firewall' ),
@@ -638,8 +470,8 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
638
  'href' => $this->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
639
  ];
640
 
641
- $bHas2Fa = $this->isEmailAuthenticationActive()
642
- || $this->isEnabledGoogleAuthenticator() || $this->isYubikeyActive();
643
  $aThis[ 'key_opts' ][ '2fa' ] = [
644
  'name' => __( 'Identity Verification', 'wp-simple-firewall' ),
645
  'enabled' => $bHas2Fa,
11
  */
12
  private $oLoginIntentController;
13
 
 
 
 
 
 
 
 
 
14
  protected function doExtraSubmitProcessing() {
15
+ /** @var LoginGuard\Options $oOpts */
16
+ $oOpts = $this->getOptions();
17
  /**
18
  * $oWp = $this->loadWpFunctionsProcessor();
19
  * $sCustomLoginPath = $this->cleanLoginUrlPath();
21
  * $oWp->resavePermalinks();
22
  * }
23
  */
24
+ if ( $this->isModuleOptionsRequest() && $oOpts->isEnabledEmailAuth() && !$oOpts->getIfCanSendEmailVerified() ) {
25
  $this->setIfCanSendEmail( false )
26
  ->sendEmailVerifyCanSend();
27
  }
58
  * @uses wp_redirect()
59
  */
60
  private function processEmailSendVerify() {
61
+ /** @var LoginGuard\Options $oOpts */
62
+ $oOpts = $this->getOptions();
63
  $this->setIfCanSendEmail( true );
64
  $this->saveModOptions();
65
 
66
+ if ( $oOpts->getIfCanSendEmailVerified() ) {
67
  $bSuccess = true;
68
  $sMessage = __( 'Email verification completed successfully.', 'wp-simple-firewall' );
69
  }
146
  return in_array( $sLocationKey, $this->getBotProtectionLocations() );
147
  }
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  /**
150
  * @param bool $bAsOptDefaults
151
  * @return array
215
  return strtoupper( substr( $this->getTwoAuthSecretKey(), 10, 6 ) );
216
  }
217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  /**
219
  * @return string
220
  */
227
  return $sKey;
228
  }
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  /**
231
  * @return bool
232
  */
234
  return ( !$this->isOpt( 'enable_google_recaptcha_login', 'disabled' ) && $this->isGoogleRecaptchaReady() );
235
  }
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  /**
238
  * @return string
239
  */
265
  return $this->oLoginIntentController;
266
  }
267
 
 
 
 
 
 
 
 
 
268
  /**
269
  * @param bool $bIsChained
270
  * @return $this
385
  return $sIntegration;
386
  }
387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  /**
389
  * @return bool
390
  */
422
  * @return array
423
  */
424
  public function addInsightsConfigData( $aAllData ) {
425
+ /** @var LoginGuard\Options $oOpts */
426
+ $oOpts = $this->getOptions();
427
  $aThis = [
428
  'strings' => [
429
  'title' => __( 'Login Guard', 'wp-simple-firewall' ),
470
  'href' => $this->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
471
  ];
472
 
473
+ $bHas2Fa = $oOpts->isEmailAuthenticationActive()
474
+ || $oOpts->isEnabledGoogleAuthenticator() || $oOpts->isEnabledYubikey();
475
  $aThis[ 'key_opts' ][ '2fa' ] = [
476
  'name' => __( 'Identity Verification', 'wp-simple-firewall' ),
477
  'enabled' => $bHas2Fa,
src/features/plugin.php CHANGED
@@ -8,7 +8,6 @@ use FernleafSystems\Wordpress\Services\Utilities;
8
  class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf {
9
 
10
  protected function doPostConstruction() {
11
- parent::doPostConstruction();
12
  $this->setVisitorIpSource();
13
  }
14
 
@@ -49,11 +48,10 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
49
  * Hooked to the plugin's main plugin_shutdown action
50
  */
51
  public function onPluginShutdown() {
52
- /* TODO: uncomment on any version 8.6+
53
  $sPreferredSource = Services::IP()->getIpDetector()->getLastSuccessfulSource();
54
  if ( !empty( $sPreferredSource ) ) {
55
- $this->setOpt( 'last_ip_detect_source', $sPreferredSource );
56
- } */
57
  parent::onPluginShutdown();
58
  }
59
 
@@ -586,8 +584,9 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
586
  public function insertCustomJsVars_Admin() {
587
  parent::insertCustomJsVars_Admin();
588
 
 
589
  if ( Services::WpPost()->isCurrentPage( 'plugins.php' ) ) {
590
- $sFile = $this->getCon()->getPluginBaseFile();
591
  wp_localize_script(
592
  $this->prefix( 'global-plugin' ),
593
  'icwp_wpsf_vars_plugin',
@@ -606,7 +605,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
606
  }
607
 
608
  wp_localize_script(
609
- $this->prefix( 'plugin' ),
610
  'icwp_wpsf_vars_tourmanager',
611
  [ 'ajax' => $this->getAjaxActionData( 'mark_tour_finished' ) ]
612
  );
8
  class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf {
9
 
10
  protected function doPostConstruction() {
 
11
  $this->setVisitorIpSource();
12
  }
13
 
48
  * Hooked to the plugin's main plugin_shutdown action
49
  */
50
  public function onPluginShutdown() {
 
51
  $sPreferredSource = Services::IP()->getIpDetector()->getLastSuccessfulSource();
52
  if ( !empty( $sPreferredSource ) ) {
53
+ $this->setOpt( 'last_ip_detect_source', $sPreferredSource );
54
+ }
55
  parent::onPluginShutdown();
56
  }
57
 
584
  public function insertCustomJsVars_Admin() {
585
  parent::insertCustomJsVars_Admin();
586
 
587
+ $oCon = $this->getCon();
588
  if ( Services::WpPost()->isCurrentPage( 'plugins.php' ) ) {
589
+ $sFile = $oCon->getPluginBaseFile();
590
  wp_localize_script(
591
  $this->prefix( 'global-plugin' ),
592
  'icwp_wpsf_vars_plugin',
605
  }
606
 
607
  wp_localize_script(
608
+ $oCon->prefix( 'plugin' ),
609
  'icwp_wpsf_vars_tourmanager',
610
  [ 'ajax' => $this->getAjaxActionData( 'mark_tour_finished' ) ]
611
  );
src/features/traffic.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
 
4
  use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf {
@@ -12,9 +13,14 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
12
  return $this->getDbH( 'traffic' );
13
  }
14
 
15
- /**
16
- * Hooked to the plugin's main plugin_shutdown action
17
- */
 
 
 
 
 
18
  public function onPluginShutdown() {
19
  if ( $this->isAutoDisable() && Services::Request()->ts() - $this->getAutoDisableAt() > 0 ) {
20
  $this->setOpt( 'auto_disable', 'N' )
@@ -28,13 +34,16 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
28
  * We clean the database after saving.
29
  */
30
  protected function doExtraSubmitProcessing() {
31
- $this->setOpt( 'autodisable_at', $this->isAutoDisable() ? Services::Request()->ts() + WEEK_IN_SECONDS : 0 );
 
 
 
32
 
33
- $aExcls = $this->getCustomExclusions();
34
  foreach ( $aExcls as &$sExcl ) {
35
  $sExcl = trim( esc_js( $sExcl ) );
36
  }
37
- $this->setOpt( 'custom_exclusions', array_filter( $aExcls ) );
38
  }
39
 
40
  /**
@@ -54,6 +63,9 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
54
  * @return array
55
  */
56
  protected function getSectionWarnings( $sSection ) {
 
 
 
57
  $aWarnings = [];
58
 
59
  $oIp = Services::IP();
@@ -63,8 +75,13 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
63
 
64
  switch ( $sSection ) {
65
  case 'section_traffic_limiter':
66
- if ( !$this->isPremium() ) {
67
- $aWarnings[] = sprintf( __( '%s is a Pro-only feature.', 'wp-simple-firewall' ), __( 'Traffic Limiting', 'wp-simple-firewall' ) );
 
 
 
 
 
68
  }
69
  break;
70
  }
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
4
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
5
  use FernleafSystems\Wordpress\Services\Services;
6
 
7
  class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf {
13
  return $this->getDbH( 'traffic' );
14
  }
15
 
16
+ protected function updateHandler() {
17
+ /** @var Traffic\Options $oOpts */
18
+ $oOpts = $this->getOptions();
19
+ if ( $this->isModOptEnabled() ) {
20
+ $oOpts->setOpt( 'enable_logger', 'Y' );
21
+ }
22
+ }
23
+
24
  public function onPluginShutdown() {
25
  if ( $this->isAutoDisable() && Services::Request()->ts() - $this->getAutoDisableAt() > 0 ) {
26
  $this->setOpt( 'auto_disable', 'N' )
34
  * We clean the database after saving.
35
  */
36
  protected function doExtraSubmitProcessing() {
37
+ /** @var Traffic\Options $oOpts */
38
+ $oOpts = $this->getOptions();
39
+
40
+ $oOpts->setOpt( 'autodisable_at', $this->isAutoDisable() ? Services::Request()->ts() + WEEK_IN_SECONDS : 0 );
41
 
42
+ $aExcls = $oOpts->getCustomExclusions();
43
  foreach ( $aExcls as &$sExcl ) {
44
  $sExcl = trim( esc_js( $sExcl ) );
45
  }
46
+ $oOpts->setOpt( 'custom_exclusions', array_filter( $aExcls ) );
47
  }
48
 
49
  /**
63
  * @return array
64
  */
65
  protected function getSectionWarnings( $sSection ) {
66
+ /** @var Traffic\Options $oOpts */
67
+ $oOpts = $this->getOptions();
68
+
69
  $aWarnings = [];
70
 
71
  $oIp = Services::IP();
75
 
76
  switch ( $sSection ) {
77
  case 'section_traffic_limiter':
78
+ if ( $this->isPremium() ) {
79
+ if ( !$oOpts->isTrafficLoggerEnabled() ) {
80
+ $aWarnings[] = sprintf( __( '%s may only be enabled if the Traffic Logger feature is also turned on.', 'wp-simple-firewall' ), __( 'Traffic Rate Limiter', 'wp-simple-firewall' ) );
81
+ }
82
+ }
83
+ else {
84
+ $aWarnings[] = sprintf( __( '%s is a Pro-only feature.', 'wp-simple-firewall' ), __( 'Traffic Rate Limiter', 'wp-simple-firewall' ) );
85
  }
86
  break;
87
  }
src/lib/src/Controller/Controller.php CHANGED
@@ -1646,14 +1646,6 @@ class Controller extends Shield\Deprecated\Foundation {
1646
  return $this->getModule_License()->getLicenseHandler()->hasValidWorkingLicense();
1647
  }
1648
 
1649
- /**
1650
- * @return string
1651
- * @deprecated 8.6.2
1652
- */
1653
- public function getPremiumLicenseFilterName() {
1654
- return $this->prefix( 'license_is_valid'.$this->getUniqueRequestId( false ) );
1655
- }
1656
-
1657
  /**
1658
  * @return bool
1659
  */
@@ -1845,9 +1837,8 @@ class Controller extends Shield\Deprecated\Foundation {
1845
  }
1846
 
1847
  $this->modules_loaded = true;
1848
-
1849
  do_action( $this->prefix( 'run_processors' ) );
1850
-
1851
  return $bSuccess;
1852
  }
1853
 
@@ -1858,9 +1849,9 @@ class Controller extends Shield\Deprecated\Foundation {
1858
  public function getModule( $sSlug ) {
1859
  if ( !is_array( $this->aModules ) ) {
1860
  $this->aModules = [];
1861
- $this->modules = $this->aModules;
1862
  }
1863
- $oModule = isset( $this->aModules[ $sSlug ] ) ? $this->aModules[ $sSlug ] : null;
1864
  if ( !is_null( $oModule ) && !( $oModule instanceof \ICWP_WPSF_FeatureHandler_Base ) ) {
1865
  $oModule = null;
1866
  }
@@ -1953,9 +1944,10 @@ class Controller extends Shield\Deprecated\Foundation {
1953
 
1954
  /**
1955
  * @return \ICWP_WPSF_FeatureHandler_Base[]
 
1956
  */
1957
  public function getModules() {
1958
- return is_array( $this->aModules ) ? $this->aModules : [];
1959
  }
1960
 
1961
  /**
@@ -1999,8 +1991,9 @@ class Controller extends Shield\Deprecated\Foundation {
1999
  throw new \Exception( $sMessage );
2000
  }
2001
 
2002
- $this->aModules[ $sModSlug ] = $this->{$sOptionsVarName};
2003
- $this->modules = $this->aModules;
 
2004
  return $this->{$sOptionsVarName};
2005
  }
2006
 
@@ -2194,7 +2187,7 @@ class Controller extends Shield\Deprecated\Foundation {
2194
  private function runTests() {
2195
  die();
2196
  ( new Shield\Tests\VerifyUniqueEvents() )->setCon( $this )->run();
2197
- foreach ( $this->getModules() as $oModule ) {
2198
  ( new \FernleafSystems\Wordpress\Plugin\Shield\Tests\VerifyConfig() )
2199
  ->setOpts( $oModule->getOptions() )
2200
  ->run();
1646
  return $this->getModule_License()->getLicenseHandler()->hasValidWorkingLicense();
1647
  }
1648
 
 
 
 
 
 
 
 
 
1649
  /**
1650
  * @return bool
1651
  */
1837
  }
1838
 
1839
  $this->modules_loaded = true;
1840
+ do_action( $this->prefix( 'modules_loaded' ) );
1841
  do_action( $this->prefix( 'run_processors' ) );
 
1842
  return $bSuccess;
1843
  }
1844
 
1849
  public function getModule( $sSlug ) {
1850
  if ( !is_array( $this->aModules ) ) {
1851
  $this->aModules = [];
1852
+ $this->modules = [];
1853
  }
1854
+ $oModule = isset( $this->modules[ $sSlug ] ) ? $this->modules[ $sSlug ] : null;
1855
  if ( !is_null( $oModule ) && !( $oModule instanceof \ICWP_WPSF_FeatureHandler_Base ) ) {
1856
  $oModule = null;
1857
  }
1944
 
1945
  /**
1946
  * @return \ICWP_WPSF_FeatureHandler_Base[]
1947
+ * @deprecated 8.7.0
1948
  */
1949
  public function getModules() {
1950
+ return is_array( $this->modules ) ? $this->modules : [];
1951
  }
1952
 
1953
  /**
1991
  throw new \Exception( $sMessage );
1992
  }
1993
 
1994
+ $aMs = $this->modules;
1995
+ $aMs[ $sModSlug ] = $this->{$sOptionsVarName};
1996
+ $this->modules = $aMs;
1997
  return $this->{$sOptionsVarName};
1998
  }
1999
 
2187
  private function runTests() {
2188
  die();
2189
  ( new Shield\Tests\VerifyUniqueEvents() )->setCon( $this )->run();
2190
+ foreach ( $this->modules as $oModule ) {
2191
  ( new \FernleafSystems\Wordpress\Plugin\Shield\Tests\VerifyConfig() )
2192
  ->setOpts( $oModule->getOptions() )
2193
  ->run();
src/lib/src/Modules/Base/BaseModCon.php CHANGED
@@ -709,7 +709,6 @@ class BaseModCon extends Deprecated\Foundation {
709
  }
710
  }
711
 
712
- // $aSum[ 'content' ] = $this->renderTemplate( 'snippets/summary_single', $aSum );
713
  $aSum[ 'tooltip' ] = sprintf(
714
  '%s%s',
715
  $aSum[ 'name' ],
@@ -1133,10 +1132,6 @@ class BaseModCon extends Deprecated\Foundation {
1133
  }
1134
 
1135
  public function onPluginDelete() {
1136
- $oDbh = $this->getDbHandler();
1137
- if ( !empty( $oDbh ) ) {
1138
- $oDbh->deleteTable();
1139
- }
1140
  $this->getOptions()->deleteStorage();
1141
  }
1142
 
@@ -1589,7 +1584,7 @@ class BaseModCon extends Deprecated\Foundation {
1589
  public function renderOptionsForm() {
1590
 
1591
  if ( $this->canDisplayOptionsForm() ) {
1592
- $sTemplate = 'snippets/options_form.twig';
1593
  }
1594
  else {
1595
  $sTemplate = 'subfeature-access_restricted';
@@ -1833,9 +1828,7 @@ class BaseModCon extends Deprecated\Foundation {
1833
  * @return bool
1834
  */
1835
  protected function isHelpVideoDisplayable() {
1836
- $sId = $this->getHelpVideoId();
1837
  return false;
1838
- return !empty( $sId );
1839
  }
1840
 
1841
  /**
709
  }
710
  }
711
 
 
712
  $aSum[ 'tooltip' ] = sprintf(
713
  '%s%s',
714
  $aSum[ 'name' ],
1132
  }
1133
 
1134
  public function onPluginDelete() {
 
 
 
 
1135
  $this->getOptions()->deleteStorage();
1136
  }
1137
 
1584
  public function renderOptionsForm() {
1585
 
1586
  if ( $this->canDisplayOptionsForm() ) {
1587
+ $sTemplate = 'components/options_form/main.twig';
1588
  }
1589
  else {
1590
  $sTemplate = 'subfeature-access_restricted';
1828
  * @return bool
1829
  */
1830
  protected function isHelpVideoDisplayable() {
 
1831
  return false;
 
1832
  }
1833
 
1834
  /**
src/lib/src/Modules/Base/BaseProcessor.php CHANGED
@@ -137,16 +137,6 @@ class BaseProcessor extends Deprecated\Foundation {
137
  public function run() {
138
  }
139
 
140
- /**
141
- * @param $sOptionKey
142
- * @param mixed $mDefault
143
- * @return mixed
144
- * @deprecated 8.6.2 - leave for a while JIC.
145
- */
146
- public function getOption( $sOptionKey, $mDefault = false ) {
147
- return $this->getMod()->getOpt( $sOptionKey, $mDefault );
148
- }
149
-
150
  /**
151
  * We don't handle locale derivatives (yet)
152
  * @return string
137
  public function run() {
138
  }
139
 
 
 
 
 
 
 
 
 
 
 
140
  /**
141
  * We don't handle locale derivatives (yet)
142
  * @return string
src/lib/src/Modules/Base/Options.php CHANGED
@@ -130,14 +130,38 @@ class Options {
130
  $aOptions[ $sKey ] = $this->getOptDefault( $sKey );
131
  }
132
  }
133
- foreach ( $this->getRawData_AllOptions() as $nKey => $aOptionData ) {
134
- if ( isset( $aOptionData[ 'sensitive' ] ) && $aOptionData[ 'sensitive' ] === true ) {
135
- unset( $aOptions[ $aOptionData[ 'key' ] ] );
136
  }
137
  }
138
  return array_diff_key( $aOptions, array_flip( $this->getVirtualCommonOptions() ) );
139
  }
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  /**
142
  * @param $sProperty
143
  * @return null|mixed
@@ -288,9 +312,8 @@ class Options {
288
  */
289
  public function isSectionReqsMet( $sSectionSlug ) {
290
  $aReqs = $this->getSection_Requirements( $sSectionSlug );
291
- $bMet = Services::Data()->getPhpVersionIsAtLeast( $aReqs[ 'php_min' ] )
292
- && Services::WpGeneral()->getWordpressIsAtLeastVersion( $aReqs[ 'wp_min' ] );
293
- return $bMet;
294
  }
295
 
296
  /**
130
  $aOptions[ $sKey ] = $this->getOptDefault( $sKey );
131
  }
132
  }
133
+ foreach ( $this->getRawData_AllOptions() as $nKey => $aOptDef ) {
134
+ if ( isset( $aOptDef[ 'sensitive' ] ) && $aOptDef[ 'sensitive' ] === true ) {
135
+ unset( $aOptions[ $aOptDef[ 'key' ] ] );
136
  }
137
  }
138
  return array_diff_key( $aOptions, array_flip( $this->getVirtualCommonOptions() ) );
139
  }
140
 
141
+ /**
142
+ * Returns an array of all the options with the values for "sensitive" options masked out.
143
+ * @return array
144
+ */
145
+ public function getOptionsForTracking() {
146
+ $aOpts = [];
147
+ if ( (bool)$this->getFeatureProperty( 'tracking_exclude' ) === false ) {
148
+
149
+ $aOptions = $this->getAllOptionsValues();
150
+ foreach ( $this->getOptionsKeys() as $sKey ) {
151
+ if ( !isset( $aOptions[ $sKey ] ) ) {
152
+ $aOptions[ $sKey ] = $this->getOptDefault( $sKey );
153
+ }
154
+ }
155
+ foreach ( $this->getRawData_AllOptions() as $nKey => $aOptDef ) {
156
+ if ( !empty( $aOptDef[ 'sensitive' ] ) || !empty( $aOptDef[ 'tracking_exclude' ] ) ) {
157
+ unset( $aOptions[ $aOptDef[ 'key' ] ] );
158
+ }
159
+ }
160
+ $aOpts = array_diff_key( $aOptions, array_flip( $this->getVirtualCommonOptions() ) );
161
+ }
162
+ return $aOpts;
163
+ }
164
+
165
  /**
166
  * @param $sProperty
167
  * @return null|mixed
312
  */
313
  public function isSectionReqsMet( $sSectionSlug ) {
314
  $aReqs = $this->getSection_Requirements( $sSectionSlug );
315
+ return Services::Data()->getPhpVersionIsAtLeast( $aReqs[ 'php_min' ] )
316
+ && Services::WpGeneral()->getWordpressIsAtLeastVersion( $aReqs[ 'wp_min' ] );
 
317
  }
318
 
319
  /**
src/lib/src/Modules/Base/Strings.php CHANGED
@@ -45,6 +45,8 @@ class Strings {
45
  'time_until' => __( 'Until', 'wp-simple-firewall' ),
46
  'time_since' => __( 'Since', 'wp-simple-firewall' ),
47
  'more_info' => __( 'Info', 'wp-simple-firewall' ),
 
 
48
  'logged_in' => __( 'Logged-In', 'wp-simple-firewall' ),
49
  'username' => __( 'Username' ),
50
  'blog' => __( 'Blog', 'wp-simple-firewall' ),
@@ -133,6 +135,14 @@ class Strings {
133
  * @throws \Exception
134
  */
135
  public function getOptionStrings( $sOptKey ) {
 
 
 
 
 
 
 
 
136
  throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sOptKey ) );
137
  }
138
 
@@ -156,7 +166,15 @@ class Strings {
156
  break;
157
 
158
  default:
159
- throw new \Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
 
 
 
 
 
 
 
 
160
  }
161
 
162
  return [
45
  'time_until' => __( 'Until', 'wp-simple-firewall' ),
46
  'time_since' => __( 'Since', 'wp-simple-firewall' ),
47
  'more_info' => __( 'Info', 'wp-simple-firewall' ),
48
+ 'opt_info_helpdesk' => __( 'Read the HelpDesk article for this option', 'wp-simple-firewall' ),
49
+ 'opt_info_blog' => __( 'Read our Blog article for this option', 'wp-simple-firewall' ),
50
  'logged_in' => __( 'Logged-In', 'wp-simple-firewall' ),
51
  'username' => __( 'Username' ),
52
  'blog' => __( 'Blog', 'wp-simple-firewall' ),
135
  * @throws \Exception
136
  */
137
  public function getOptionStrings( $sOptKey ) {
138
+ $aOpt = $this->getOptions()->getOptDefinition( $sOptKey );
139
+ if ( is_array( $aOpt ) && !empty( $aOpt[ 'name' ] ) && !empty( $aOpt[ 'summary' ] ) && !empty( $aOpt[ 'description' ] ) ) {
140
+ return [
141
+ 'name' => __( $aOpt[ 'name' ], 'wp-simple-firewall' ),
142
+ 'summary' => __( $aOpt[ 'summary' ], 'wp-simple-firewall' ),
143
+ 'description' => __( $aOpt[ 'description' ], 'wp-simple-firewall' ),
144
+ ];
145
+ }
146
  throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sOptKey ) );
147
  }
148
 
166
  break;
167
 
168
  default:
169
+ $aSect = $this->getOptions()->getSection( $sSectionSlug );
170
+ if ( is_array( $aSect ) && !empty( $aSect[ 'title' ] ) && !empty( $aSect[ 'title_short' ] ) ) {
171
+ $sTitle = __( $aSect[ 'title' ], 'wp-simple-firewall' );
172
+ $sTitleShort = __( $aSect[ 'title_short' ], 'wp-simple-firewall' );
173
+ $aSummary = empty( $aSect[ 'summary' ] ) ? [] : $aSect[ 'summary' ];
174
+ }
175
+ else {
176
+ throw new \Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
177
+ }
178
  }
179
 
180
  return [
src/lib/src/Modules/BaseShield/ShieldProcessor.php CHANGED
@@ -117,8 +117,11 @@ class ShieldProcessor extends Base\BaseProcessor {
117
  if ( !is_array( $aData ) ) {
118
  $aData = [];
119
  }
120
- $oFO = $this->getMod();
121
- $aData[ $oFO->getSlug() ] = [ 'options' => $oFO->collectOptionsForTracking() ];
 
 
 
122
  return $aData;
123
  }
124
 
117
  if ( !is_array( $aData ) ) {
118
  $aData = [];
119
  }
120
+ $oMod = $this->getMod();
121
+ $aOptions = $oMod->collectOptionsForTracking();
122
+ if ( !empty( $aOptions ) ) {
123
+ $aData[ $oMod->getSlug() ] = [ 'options' => $oMod->collectOptionsForTracking() ];
124
+ }
125
  return $aData;
126
  }
127
 
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/StoreFormatUpgrade.php DELETED
@@ -1,80 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\Store;
6
-
7
- /**
8
- * Class StoreFormatUpgrade
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg\Snapshots
10
- * @needs updating if required
11
- */
12
- class StoreFormatUpgrade {
13
-
14
- /**
15
- * @var Store
16
- */
17
- private $oStore;
18
-
19
- /**
20
- * @return $this
21
- */
22
- public function run() {
23
- $aSnapData = $this->getStore()->getSnapData();
24
-
25
- $bStoreRequired = false;
26
- foreach ( $aSnapData as $sSlug => $aSnap ) {
27
- $sSnapVersion = isset( $aSnap[ 'meta' ][ 'snap_version' ] ) ? isset( $aSnap[ 'meta' ][ 'snap_version' ] ) : '0.0';
28
-
29
- if ( version_compare( $sSnapVersion, '7.0.0', '<' ) ) {
30
- $aSnapData[ $sSlug ] = $this->upgradeSnap_Pre700( $aSnap );
31
- $bStoreRequired = true;
32
- }
33
- }
34
-
35
- if ( $bStoreRequired ) {
36
- try {
37
- $this->getStore()
38
- ->deleteSnapshots()
39
- ->setSnapData( $aSnapData )
40
- ->save();
41
- }
42
- catch ( \Exception $oE ) {
43
- }
44
- }
45
-
46
- return $this;
47
- }
48
-
49
- /**
50
- * Will replace older absolute file paths with ABSPATH-relative paths.
51
- * @param array $aSnap
52
- * @return array
53
- */
54
- private function upgradeSnap_Pre700( $aSnap ) {
55
- $sNormAbs = wp_normalize_path( ABSPATH );
56
- $aNew = [];
57
- foreach ( $aSnap[ 'hashes' ] as $sOldPath => $sHash ) {
58
- $aNew[ str_replace( $sNormAbs, '', wp_normalize_path( $sOldPath ) ) ] = $sHash;
59
- }
60
- $aSnap[ 'hashes' ] = $aNew;
61
- $aSnap[ 'meta' ][ 'snap_version' ] = '7.0.0';
62
- return $aSnap;
63
- }
64
-
65
- /**
66
- * @return Store
67
- */
68
- private function getStore() {
69
- return $this->oStore;
70
- }
71
-
72
- /**
73
- * @param Store $oStore
74
- * @return $this
75
- */
76
- public function setStore( $oStore ) {
77
- $this->oStore = $oStore;
78
- return $this;
79
- }
80
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/Clean.php DELETED
@@ -1,27 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- /**
8
- * Class Clean
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ScanResults
10
- */
11
- class Clean {
12
-
13
- use Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
14
-
15
- /**
16
- * @return $this
17
- */
18
- public function removeStaleResults() {
19
- $sScan = $this->getScanController()->getSlug();
20
- if ( !empty( $sScan ) ) {
21
- /** @var Shield\Databases\Scanner\Delete $oDel */
22
- $oDel = $this->getDbHandler()->getQueryDeleter();
23
- $oDel->forScan( $sScan );
24
- }
25
- return $this;
26
- }
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/IPs/Lib/BlockRequest.php CHANGED
@@ -20,7 +20,8 @@ class BlockRequest {
20
  ->run();
21
 
22
  if ( $bIpBlocked ) {
23
- // $this->setIfLogRequest( false ); // TODO don't log traffic from killed requests
 
24
  try {
25
  if ( $this->processAutoUnblockRequest() ) {
26
  return;
20
  ->run();
21
 
22
  if ( $bIpBlocked ) {
23
+ // don't log killed requests
24
+ add_filter( $this->getCon()->prefix( 'is_log_traffic' ), '__return_false' );
25
  try {
26
  if ( $this->processAutoUnblockRequest() ) {
27
  return;
src/lib/src/Modules/License/AdminNotices.php CHANGED
@@ -3,7 +3,6 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\License;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
 
8
  class AdminNotices extends Shield\Modules\Base\AdminNotices {
9
 
@@ -52,15 +51,14 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
52
  * @return bool
53
  */
54
  protected function isDisplayNeeded( $oNotice ) {
55
- $oCon = $this->getCon();
56
  /** @var \ICWP_WPSF_FeatureHandler_License $oMod */
57
  $oMod = $this->getMod();
58
 
59
  switch ( $oNotice->id ) {
60
 
61
  case 'wphashes-token-fail':
62
- $bNeeded = $oCon->isPremiumActive() && !$oMod->getWpHashesTokenManager()->hasToken()
63
- && ( Services::Request()->ts() > 1583712000 ); // @deprecated 8.6.3 i.e. remove it
64
  break;
65
 
66
  default:
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\License;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
 
6
 
7
  class AdminNotices extends Shield\Modules\Base\AdminNotices {
8
 
51
  * @return bool
52
  */
53
  protected function isDisplayNeeded( $oNotice ) {
 
54
  /** @var \ICWP_WPSF_FeatureHandler_License $oMod */
55
  $oMod = $this->getMod();
56
 
57
  switch ( $oNotice->id ) {
58
 
59
  case 'wphashes-token-fail':
60
+ $bNeeded = $this->getCon()->isPremiumActive()
61
+ && !$oMod->getWpHashesTokenManager()->hasToken();
62
  break;
63
 
64
  default:
src/lib/src/Modules/License/Lib/WpHashes/ApiTokenManager.php CHANGED
@@ -45,7 +45,7 @@ class ApiTokenManager {
45
 
46
  if ( $this->getCon()->getModule_License()->getLicenseHandler()->getLicense()->isValid() ) {
47
  $aT = $this->loadToken();
48
- if ( $this->isExpired() && $this->canRequestNewToken() ) {
49
  $aT = $this->loadToken();
50
  try {
51
  $aT = array_merge( $aT, $this->solicitApiToken() );
@@ -91,7 +91,7 @@ class ApiTokenManager {
91
  private function canRequestNewToken() {
92
  return $this->getCanRequestOverride() ||
93
  (
94
- Services::Request()->carbon()->subHours( 6 )->timestamp > $this->loadToken()[ 'attempt_at' ]
95
  && $this->getCon()->getModule_License()->getLicenseHandler()->getLicense()->isValid()
96
  );
97
  }
@@ -110,6 +110,13 @@ class ApiTokenManager {
110
  return Services::Request()->ts() > $this->loadToken()[ 'expires_at' ];
111
  }
112
 
 
 
 
 
 
 
 
113
  /**
114
  * @param array $aToken
115
  * @return $this
45
 
46
  if ( $this->getCon()->getModule_License()->getLicenseHandler()->getLicense()->isValid() ) {
47
  $aT = $this->loadToken();
48
+ if ( $this->isNearlyExpired() && $this->canRequestNewToken() ) {
49
  $aT = $this->loadToken();
50
  try {
51
  $aT = array_merge( $aT, $this->solicitApiToken() );
91
  private function canRequestNewToken() {
92
  return $this->getCanRequestOverride() ||
93
  (
94
+ Services::Request()->carbon()->subHour( 1 )->timestamp > $this->loadToken()[ 'attempt_at' ]
95
  && $this->getCon()->getModule_License()->getLicenseHandler()->getLicense()->isValid()
96
  );
97
  }
110
  return Services::Request()->ts() > $this->loadToken()[ 'expires_at' ];
111
  }
112
 
113
+ /**
114
+ * @return bool
115
+ */
116
+ public function isNearlyExpired() {
117
+ return Services::Request()->carbon()->addHours( 2 )->timestamp > $this->loadToken()[ 'expires_at' ];
118
+ }
119
+
120
  /**
121
  * @param array $aToken
122
  * @return $this
src/lib/src/Modules/LoginGuard/AdminNotices.php CHANGED
@@ -59,12 +59,14 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
59
  protected function isDisplayNeeded( $oNotice ) {
60
  /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
61
  $oMod = $this->getMod();
 
 
62
 
63
  switch ( $oNotice->id ) {
64
 
65
  case 'email-verification-sent':
66
- $bNeeded = $oMod->isEmailAuthenticationOptionOn()
67
- && !$oMod->isEmailAuthenticationActive() && !$oMod->getIfCanSendEmailVerified();
68
  break;
69
 
70
  default:
59
  protected function isDisplayNeeded( $oNotice ) {
60
  /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
61
  $oMod = $this->getMod();
62
+ /** @var Options $oOpts */
63
+ $oOpts = $this->getOptions();
64
 
65
  switch ( $oNotice->id ) {
66
 
67
  case 'email-verification-sent':
68
+ $bNeeded = $oOpts->isEnabledEmailAuth()
69
+ && !$oOpts->isEmailAuthenticationActive() && !$oOpts->getIfCanSendEmailVerified();
70
  break;
71
 
72
  default:
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php CHANGED
@@ -70,10 +70,10 @@ class LoginIntentPage {
70
 
71
  $sCancelHref = $oReq->post( 'cancel_href', '' );
72
  if ( empty( $sCancelHref ) && Services::Data()->isValidWebUrl( $sReferUrl ) ) {
73
- $sCancelHref = rawurlencode( parse_url( $sReferUrl, PHP_URL_PATH ) );
74
  }
75
 
76
- $nMfaSkip = $oOpts->getMfaSkip();
77
  $nTimeRemaining = $oMod->getSession()->login_intent_expires_at - $oReq->ts();
78
  $aDisplayData = [
79
  'strings' => [
@@ -101,7 +101,7 @@ class LoginIntentPage {
101
  'cancel_href' => $sCancelHref
102
  ],
103
  'flags' => [
104
- 'can_skip_mfa' => $oMod->getMfaSkipEnabled(),
105
  'show_branded_links' => !$oMod->isWlEnabled(), // white label mitigation
106
  ]
107
  ];
@@ -125,8 +125,8 @@ class LoginIntentPage {
125
  $nTimeRemaining = $oMod->getSession()->login_intent_expires_at - $oReq->ts();
126
  $aDisplayData = [
127
  'strings' => [
128
- 'what_is_this' => __( 'What is this?', 'wp-simple-firewall' ),
129
- 'page_title' => sprintf( __( '%s Login Verification', 'wp-simple-firewall' ), $oCon->getHumanName() ),
130
  ],
131
  'data' => [
132
  'time_remaining' => $nTimeRemaining,
70
 
71
  $sCancelHref = $oReq->post( 'cancel_href', '' );
72
  if ( empty( $sCancelHref ) && Services::Data()->isValidWebUrl( $sReferUrl ) ) {
73
+ $sCancelHref = parse_url( $sReferUrl, PHP_URL_PATH );
74
  }
75
 
76
+ $nMfaSkip = (int)( $oOpts->getMfaSkip()/DAY_IN_SECONDS );
77
  $nTimeRemaining = $oMod->getSession()->login_intent_expires_at - $oReq->ts();
78
  $aDisplayData = [
79
  'strings' => [
101
  'cancel_href' => $sCancelHref
102
  ],
103
  'flags' => [
104
+ 'can_skip_mfa' => $oOpts->isMfaSkip(),
105
  'show_branded_links' => !$oMod->isWlEnabled(), // white label mitigation
106
  ]
107
  ];
125
  $nTimeRemaining = $oMod->getSession()->login_intent_expires_at - $oReq->ts();
126
  $aDisplayData = [
127
  'strings' => [
128
+ 'what_is_this' => __( 'What is this?', 'wp-simple-firewall' ),
129
+ 'page_title' => sprintf( __( '%s Login Verification', 'wp-simple-firewall' ), $oCon->getHumanName() ),
130
  ],
131
  'data' => [
132
  'time_remaining' => $nTimeRemaining,
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php CHANGED
@@ -127,7 +127,7 @@ class MfaController {
127
  */
128
  private function getLoginIntentPageHandler() {
129
  if ( !isset( $this->oLoginIntentPageHandler ) ) {
130
- $this->oLoginIntentPageHandler =( new LoginIntentPage() )->setMfaController( $this );
131
  }
132
  return $this->oLoginIntentPageHandler;
133
  }
@@ -185,7 +185,7 @@ class MfaController {
185
  if ( $oReq->post( 'cancel' ) == 1 ) {
186
  Services::WpUsers()->logoutUser(); // clears the login and login intent
187
  $sRedirectHref = $oReq->post( 'cancel_href' );
188
- empty( $sRedirectHref ) ? $oWpResp->redirectToLogin() : $oWpResp->redirect( rawurldecode( $sRedirectHref ) );
189
  }
190
  elseif ( $this->validateLoginIntentRequest() ) {
191
 
127
  */
128
  private function getLoginIntentPageHandler() {
129
  if ( !isset( $this->oLoginIntentPageHandler ) ) {
130
+ $this->oLoginIntentPageHandler = ( new LoginIntentPage() )->setMfaController( $this );
131
  }
132
  return $this->oLoginIntentPageHandler;
133
  }
185
  if ( $oReq->post( 'cancel' ) == 1 ) {
186
  Services::WpUsers()->logoutUser(); // clears the login and login intent
187
  $sRedirectHref = $oReq->post( 'cancel_href' );
188
+ empty( $sRedirectHref ) ? $oWpResp->redirectToLogin() : $oWpResp->redirect( $sRedirectHref );
189
  }
190
  elseif ( $this->validateLoginIntentRequest() ) {
191
 
src/lib/src/Modules/LoginGuard/Strings.php CHANGED
@@ -288,14 +288,14 @@ class Strings extends Base\Strings {
288
  $sName = __( 'Yubikey App ID', 'wp-simple-firewall' );
289
  $sSummary = __( 'Your Unique Yubikey App ID', 'wp-simple-firewall' );
290
  $sDescription = __( 'Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication', 'wp-simple-firewall' )
291
- .__( 'Please review the info link on how to obtain your own Yubikey App ID and API Key.', 'wp-simple-firewall' );
292
  break;
293
 
294
  case 'yubikey_api_key' :
295
  $sName = __( 'Yubikey API Key', 'wp-simple-firewall' );
296
  $sSummary = __( 'Your Unique Yubikey App API Key', 'wp-simple-firewall' );
297
  $sDescription = __( 'Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication.', 'wp-simple-firewall' )
298
- .__( 'Please review the info link on how to get your own Yubikey App ID and API Key.', 'wp-simple-firewall' );
299
  break;
300
 
301
  case 'yubikey_unique_keys' :
288
  $sName = __( 'Yubikey App ID', 'wp-simple-firewall' );
289
  $sSummary = __( 'Your Unique Yubikey App ID', 'wp-simple-firewall' );
290
  $sDescription = __( 'Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication', 'wp-simple-firewall' )
291
+ .'<br />'.__( 'Please review the info link on how to obtain your own Yubikey App ID and API Key.', 'wp-simple-firewall' );
292
  break;
293
 
294
  case 'yubikey_api_key' :
295
  $sName = __( 'Yubikey API Key', 'wp-simple-firewall' );
296
  $sSummary = __( 'Your Unique Yubikey App API Key', 'wp-simple-firewall' );
297
  $sDescription = __( 'Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication.', 'wp-simple-firewall' )
298
+ .'<br />'.__( 'Please review the info link on how to get your own Yubikey App ID and API Key.', 'wp-simple-firewall' );
299
  break;
300
 
301
  case 'yubikey_unique_keys' :
src/lib/src/Modules/Plugin/AdminNotices.php CHANGED
@@ -159,6 +159,7 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
159
  * @param Shield\Utilities\AdminNotices\NoticeVO $oNotice
160
  */
161
  private function buildNotice_PluginMailingListSignup( $oNotice ) {
 
162
  $oOpts = $this->getOptions();
163
 
164
  $sName = $this->getCon()->getHumanName();
159
  * @param Shield\Utilities\AdminNotices\NoticeVO $oNotice
160
  */
161
  private function buildNotice_PluginMailingListSignup( $oNotice ) {
162
+ /** @var Options $oOpts */
163
  $oOpts = $this->getOptions();
164
 
165
  $sName = $this->getCon()->getHumanName();
src/lib/src/Modules/Plugin/AjaxHandler.php CHANGED
@@ -5,6 +5,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
7
  use FernleafSystems\Wordpress\Services\Services;
 
8
 
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
@@ -54,6 +55,10 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
54
  $aResponse = $this->ajaxExec_TurnOffSiteGroundOptions();
55
  break;
56
 
 
 
 
 
57
  case 'mark_tour_finished':
58
  $aResponse = $this->ajaxExec_MarkTourFinished();
59
  break;
@@ -296,6 +301,22 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
296
  ];
297
  }
298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  /**
300
  * @return array
301
  */
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
7
  use FernleafSystems\Wordpress\Services\Services;
8
+ use FernleafSystems\Wordpress\Services\Utilities\Net\FindSourceFromIp;
9
 
10
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
11
 
55
  $aResponse = $this->ajaxExec_TurnOffSiteGroundOptions();
56
  break;
57
 
58
+ case 'ipdetect':
59
+ $aResponse = $this->ajaxExec_IpDetect();
60
+ break;
61
+
62
  case 'mark_tour_finished':
63
  $aResponse = $this->ajaxExec_MarkTourFinished();
64
  break;
301
  ];
302
  }
303
 
304
+ /**
305
+ * @return array
306
+ */
307
+ private function ajaxExec_IpDetect() {
308
+ /** @var Options $oOpts */
309
+ $oOpts = $this->getOptions();
310
+ $sSource = ( new FindSourceFromIp() )->run( Services::Request()->post( 'ip' ) );
311
+ if ( !empty( $sSource ) ) {
312
+ $oOpts->setVisitorAddressSource( $sSource );
313
+ }
314
+ return [
315
+ 'success' => !empty( $sSource ),
316
+ 'message' => empty( $sSource ) ? 'Could not find source' : 'IP Source Found: '.$sSource
317
+ ];
318
+ }
319
+
320
  /**
321
  * @return array
322
  */
src/lib/src/Modules/Plugin/Lib/WpHashesTokenManager.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
- use FernleafSystems\Wordpress\Services\Services;
7
- use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Token;
8
-
9
- /**
10
- * Class WpHashesTokenManager
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib
12
- * @deprecated 8.6.2
13
- */
14
- class WpHashesTokenManager {
15
-
16
- use ModConsumer;
17
-
18
- /**
19
- * @var bool
20
- */
21
- private $bCanRequestOverride = false;
22
-
23
- public function run() {
24
- add_action( $this->getCon()->prefix( 'event' ), function ( $sEventTag ) {
25
- if ( $sEventTag === 'lic_check_success' ) {
26
- $this->setCanRequestOverride( true )
27
- ->getToken();
28
- }
29
- } );
30
- }
31
-
32
- /**
33
- * @return string
34
- */
35
- public function getToken() {
36
-
37
- if ( $this->getCon()->getModule_License()->getLicenseHandler()->getLicense()->isValid() ) {
38
- $aT = $this->loadToken();
39
- if ( $this->isExpired() && $this->canRequestNewToken() ) {
40
- $aT = $this->loadToken();
41
- try {
42
- $aT = array_merge( $aT, $this->solicitApiToken() );
43
- }
44
- catch ( \Exception $oE ) {
45
- }
46
- $aT[ 'attempt_at' ] = Services::Request()->ts();
47
- $this->storeToken( $aT );
48
- }
49
- }
50
- else {
51
- $this->storeToken( [] );
52
- }
53
-
54
- return empty( $aT[ 'token' ] ) ? '' : $aT[ 'token' ];
55
- }
56
-
57
- /**
58
- * @return array - return Token exactly as it's saved currently
59
- */
60
- private function loadToken() {
61
- return array_merge(
62
- [
63
- 'token' => '',
64
- 'expires_at' => 0,
65
- 'attempt_at' => 0,
66
- 'valid_license' => false,
67
- ],
68
- $this->getOptions()->getOpt( 'wphashes_api_token', [] )
69
- );
70
- }
71
-
72
- /**
73
- * @return bool
74
- */
75
- private function canRequestNewToken() {
76
- return $this->getCanRequestOverride() ||
77
- (
78
- Services::Request()->carbon()->subHours( 6 )->timestamp > $this->loadToken()[ 'attempt_at' ]
79
- && $this->getCon()->getModule_License()->getLicenseHandler()->getLicense()->isValid()
80
- );
81
- }
82
-
83
- /**
84
- * @return bool
85
- */
86
- public function getCanRequestOverride() {
87
- return (bool)$this->bCanRequestOverride;
88
- }
89
-
90
- /**
91
- * @return bool
92
- */
93
- public function isExpired() {
94
- return Services::Request()->ts() > $this->loadToken()[ 'expires_at' ];
95
- }
96
-
97
- /**
98
- * @param array $aToken
99
- * @return $this
100
- */
101
- private function storeToken( array $aToken = [] ) {
102
- $this->getOptions()->setOpt( 'wphashes_api_token', $aToken );
103
- return $this;
104
- }
105
-
106
- /**
107
- * @param bool $bCanRequest
108
- * @return $this
109
- */
110
- public function setCanRequestOverride( $bCanRequest ) {
111
- $this->bCanRequestOverride = (bool)$bCanRequest;
112
- return $this;
113
- }
114
-
115
- /**
116
- * @return array
117
- * @throws \Exception
118
- */
119
- private function solicitApiToken() {
120
- $aResp = ( new Token\Solicit() )->retrieve(
121
- Services::WpGeneral()->getHomeUrl(),
122
- $this->getCon()->getSiteInstallationId()
123
- );
124
- if ( !is_array( $aResp ) || empty( $aResp[ 'token' ] ) || strlen( $aResp[ 'token' ] ) != 40 ) {
125
- throw new \Exception( 'Could not retrieve token' );
126
- }
127
- return $aResp;
128
- }
129
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/Plugin/Options.php CHANGED
@@ -130,4 +130,12 @@ class Options extends Base\ShieldOptions {
130
  return $this->setOpt( 'enable_tracking', $bOnOrOff ? 'Y' : 'N' )
131
  ->setOpt( 'tracking_permission_set_at', Services::Request()->ts() );
132
  }
 
 
 
 
 
 
 
 
133
  }
130
  return $this->setOpt( 'enable_tracking', $bOnOrOff ? 'Y' : 'N' )
131
  ->setOpt( 'tracking_permission_set_at', Services::Request()->ts() );
132
  }
133
+
134
+ /**
135
+ * @param string $sSource
136
+ * @return $this
137
+ */
138
+ public function setVisitorAddressSource( $sSource ) {
139
+ return $this->setOpt( 'visitor_address_source', $sSource );
140
+ }
141
  }
src/lib/src/Modules/Plugin/Strings.php CHANGED
@@ -145,9 +145,11 @@ class Strings extends Base\Strings {
145
  case 'enable_tracking' :
146
  $sName = __( 'Anonymous Usage Statistics', 'wp-simple-firewall' );
147
  $sSummary = __( 'Permit Anonymous Usage Information Gathering', 'wp-simple-firewall' );
148
- $sDescription = __( 'Allows us to gather information on statistics and features in-use across our client installations.', 'wp-simple-firewall' )
149
- .' '.__( 'This information is strictly anonymous and contains no personally, or otherwise, identifiable data.', 'wp-simple-firewall' )
150
- .'<br />'.sprintf( '<a href="%s" target="_blank">%s</a>', $oMod->getLinkToTrackingDataDump(), __( 'Click to see the exact data that would be sent.', 'wp-simple-firewall' ) );
 
 
151
  break;
152
 
153
  case 'visitor_address_source' :
@@ -158,7 +160,7 @@ class Strings extends Base\Strings {
158
  .'<br />'.sprintf(
159
  __( 'Current source is: %s (%s)', 'wp-simple-firewall' ),
160
  '<strong>'.$oOpts->getIpSource().'</strong>',
161
- $oOpts->getOpt( 'last_ip_detect_source' )
162
  )
163
  .'<br />'
164
  .'<br />'.implode( '<br />', $this->buildIpAddressMap() );
145
  case 'enable_tracking' :
146
  $sName = __( 'Anonymous Usage Statistics', 'wp-simple-firewall' );
147
  $sSummary = __( 'Permit Anonymous Usage Information Gathering', 'wp-simple-firewall' );
148
+ $sDescription = [
149
+ __( 'Allows us to gather information on statistics and features in-use across our client installations.', 'wp-simple-firewall' )
150
+ .' '.__( 'This information is strictly anonymous and contains no personally, or otherwise, identifiable data.', 'wp-simple-firewall' ),
151
+ sprintf( '<a href="%s" target="_blank" class="new-window-link">%s</a>', $oMod->getLinkToTrackingDataDump(), __( 'Click to see the exact data that would be sent.', 'wp-simple-firewall' ) )
152
+ ];
153
  break;
154
 
155
  case 'visitor_address_source' :
160
  .'<br />'.sprintf(
161
  __( 'Current source is: %s (%s)', 'wp-simple-firewall' ),
162
  '<strong>'.$oOpts->getIpSource().'</strong>',
163
+ Services::IP()->getRequestIp()
164
  )
165
  .'<br />'
166
  .'<br />'.implode( '<br />', $this->buildIpAddressMap() );
src/lib/src/Modules/Traffic/Lib/Limit/Limiter.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\Limit;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ /**
10
+ * Class Limiter
11
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\Limit
12
+ */
13
+ class Limiter {
14
+
15
+ use ModConsumer;
16
+
17
+ public function run() {
18
+ /** @var Traffic\Options $oOpts */
19
+ $oOpts = $this->getOptions();
20
+ if ( $oOpts->isTrafficLimitEnabled() ) {
21
+ add_action( 'init', [ $this, 'limit' ] );
22
+ }
23
+ }
24
+
25
+ public function limit() {
26
+ try {
27
+ ( new TestIp() )
28
+ ->setMod( $this->getMod() )
29
+ ->runTest( Services::IP()->getRequestIp() );
30
+ }
31
+ catch ( \Exception $oE ) {
32
+ /** @var Traffic\Options $oOpts */
33
+ $oOpts = $this->getOptions();
34
+ $this->getCon()->fireEvent(
35
+ 'request_limit_exceeded',
36
+ [
37
+ 'audit' => [
38
+ 'count' => $oOpts->getLimitRequestCount(),
39
+ 'span' => $oOpts->getLimitTimeSpan(),
40
+ ]
41
+ ]
42
+ );
43
+ }
44
+ }
45
+ }
src/lib/src/Modules/Traffic/{Limiter → Lib/Limit}/TestIp.php RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Limiter;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
@@ -8,7 +8,7 @@ use FernleafSystems\Wordpress\Services\Services;
8
 
9
  /**
10
  * Class TestIp
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Limiter
12
  */
13
  class TestIp {
14
 
@@ -24,11 +24,11 @@ class TestIp {
24
  $oMod = $this->getMod();
25
  /** @var Shield\Modules\Traffic\Options $oOpts */
26
  $oOpts = $oMod->getOptions();
27
- /** @var Traffic\Select $oSel */
28
- $oSel = $oMod->getDbHandler_Traffic()->getQuerySelector();
29
 
30
  $oNow = Services::Request()->carbon();
31
 
 
 
32
  $nCount = $oSel->filterByIp( inet_pton( $sHumanIp ) )
33
  ->filterByCreatedAt( $oNow->subSeconds( $oOpts->getLimitTimeSpan() )->timestamp, '>' )
34
  ->count();
1
  <?php
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\Limit;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
8
 
9
  /**
10
  * Class TestIp
11
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\Limit
12
  */
13
  class TestIp {
14
 
24
  $oMod = $this->getMod();
25
  /** @var Shield\Modules\Traffic\Options $oOpts */
26
  $oOpts = $oMod->getOptions();
 
 
27
 
28
  $oNow = Services::Request()->carbon();
29
 
30
+ /** @var Traffic\Select $oSel */
31
+ $oSel = $oMod->getDbHandler_Traffic()->getQuerySelector();
32
  $nCount = $oSel->filterByIp( inet_pton( $sHumanIp ) )
33
  ->filterByCreatedAt( $oNow->subSeconds( $oOpts->getLimitTimeSpan() )->timestamp, '>' )
34
  ->count();
src/lib/src/Modules/Traffic/Lib/Logger.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic\EntryVO;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
8
+ use FernleafSystems\Wordpress\Services\Services;
9
+
10
+ class Logger {
11
+
12
+ use ModConsumer;
13
+
14
+ public function run() {
15
+ /** @var Traffic\Options $oOpts */
16
+ $oOpts = $this->getOptions();
17
+ if ( $oOpts->isTrafficLoggerEnabled() ) {
18
+ add_action( $this->getCon()->prefix( 'plugin_shutdown' ), function () {
19
+ if ( $this->isRequestToBeLogged() ) {
20
+ $this->logTraffic();
21
+ }
22
+ } );
23
+ }
24
+ }
25
+
26
+ /**
27
+ * @return bool
28
+ */
29
+ private function isRequestToBeLogged() {
30
+ return apply_filters( $this->getCon()->prefix( 'is_log_traffic' ), true )
31
+ && !$this->getCon()->isPluginDeleting()
32
+ && ( !$this->isCustomExcluded() )
33
+ && ( !$this->isRequestTypeExcluded() );
34
+ }
35
+
36
+ /**
37
+ * @return bool
38
+ */
39
+ private function isRequestTypeExcluded() {
40
+ /** @var Traffic\Options $oOpts */
41
+ $oOpts = $this->getOptions();
42
+ $aEx = $oOpts->getReqTypeExclusions();
43
+ $bLoggedIn = Services::WpUsers()->isUserLoggedIn();
44
+
45
+ $bExcluded = ( in_array( 'simple', $aEx ) && count( Services::Request()->getRawRequestParams( false ) ) == 0 )
46
+ || ( in_array( 'logged_in', $aEx ) && $bLoggedIn )
47
+ || ( in_array( 'ajax', $aEx ) && Services::WpGeneral()->isAjax() )
48
+ || ( in_array( 'cron', $aEx ) && Services::WpGeneral()->isCron() );
49
+
50
+ if ( !$bExcluded && !$bLoggedIn ) {
51
+ $bExcluded = ( in_array( 'search', $aEx ) && $this->isServiceIp_Search() )
52
+ || ( in_array( 'uptime', $aEx ) && $this->isServiceIp_Uptime() );
53
+ }
54
+
55
+ return $bExcluded;
56
+ }
57
+
58
+ /**
59
+ * @return bool
60
+ */
61
+ private function isCustomExcluded() {
62
+ /** @var Traffic\Options $oOpts */
63
+ $oOpts = $this->getOptions();
64
+ $oReq = Services::Request();
65
+
66
+ $sAgent = $oReq->getUserAgent();
67
+ $sPath = $oReq->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) );
68
+
69
+ $bExcluded = false;
70
+ foreach ( $oOpts->getCustomExclusions() as $sExcl ) {
71
+ if ( stripos( $sAgent, $sExcl ) !== false || stripos( $sPath, $sExcl ) !== false ) {
72
+ $bExcluded = true;
73
+ }
74
+ }
75
+ return $bExcluded;
76
+ }
77
+
78
+ /**
79
+ * @return bool
80
+ */
81
+ private function isServiceIp_Search() {
82
+ $oSP = Services::ServiceProviders();
83
+ $sIp = Services::IP()->getRequestIp();
84
+ $sAgent = (string)Services::Request()->getUserAgent();
85
+
86
+ return $oSP->isIp_GoogleBot( $sIp, $sAgent )
87
+ || $oSP->isIp_BingBot( $sIp, $sAgent )
88
+ || $oSP->isIp_DuckDuckGoBot( $sIp, $sAgent )
89
+ || $oSP->isIp_YandexBot( $sIp, $sAgent )
90
+ || $oSP->isIp_BaiduBot( $sIp, $sAgent )
91
+ || $oSP->isIp_YahooBot( $sIp, $sAgent )
92
+ || $oSP->isIp_AppleBot( $sIp, $sAgent );
93
+ }
94
+
95
+ /**
96
+ * @return bool
97
+ */
98
+ private function isServiceIp_Uptime() {
99
+ $oSP = Services::ServiceProviders();
100
+ $sIp = Services::IP()->getRequestIp();
101
+ $sAgent = (string)Services::Request()->getUserAgent();
102
+
103
+ return $oSP->isIp_Statuscake( $sIp, $sAgent )
104
+ || $oSP->isIp_UptimeRobot( $sIp, $sAgent )
105
+ || $oSP->isIp_Pingdom( $sIp, $sAgent )
106
+ || $oSP->isIpInCollection( $sIp, $oSP->getIps_NodePing() );
107
+ }
108
+
109
+ private function logTraffic() {
110
+ /** @var \ICWP_WPSF_FeatureHandler_Traffic $oMod */
111
+ $oMod = $this->getMod();
112
+ $oReq = Services::Request();
113
+ $oDbh = $oMod->getDbHandler_Traffic();
114
+
115
+ // For multisites that are separated by sub-domains we also show the host.
116
+ $sLeadingPath = Services::WpGeneral()->isMultisite_SubdomainInstall() ? $oReq->getHost() : '';
117
+
118
+ /** @var EntryVO $oEntry */
119
+ $oEntry = $oDbh->getVo();
120
+
121
+ $oEntry->rid = $this->getCon()->getShortRequestId();
122
+ $oEntry->uid = Services::WpUsers()->getCurrentWpUserId();
123
+ $oEntry->ip = inet_pton( Services::IP()->getRequestIp() );
124
+ $oEntry->verb = $oReq->getMethod();
125
+ $oEntry->path = $sLeadingPath.$oReq->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) );
126
+ $oEntry->code = http_response_code();
127
+ $oEntry->ua = $oReq->getUserAgent();
128
+ $oEntry->trans = $this->getCon()
129
+ ->getModule_IPs()
130
+ ->loadOffenseTracker()
131
+ ->getOffenseCount() > 0 ? 1 : 0;
132
+
133
+ $oDbh->getQueryInserter()
134
+ ->insert( $oEntry );
135
+ }
136
+ }
src/lib/src/Modules/Traffic/Limiter/Limiter.php DELETED
@@ -1,38 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Limiter;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
-
8
- class Limiter {
9
-
10
- use Shield\Modules\ModConsumer;
11
-
12
- public function run() {
13
- /** @var \ICWP_WPSF_FeatureHandler_Traffic $oMod */
14
- $oMod = $this->getMod();
15
-
16
- try {
17
- $bAllowed = ( new TestIp() )
18
- ->setMod( $oMod )
19
- ->runTest( Services::IP()->getRequestIp() );
20
- }
21
- catch ( \Exception $oE ) {
22
- $bAllowed = false;
23
- /** @var Shield\Modules\Traffic\Options $oOpts */
24
- $oOpts = $oMod->getOptions();
25
- $this->getCon()->fireEvent(
26
- 'request_limit_exceeded',
27
- [
28
- 'audit' => [
29
- 'count' => $oOpts->getLimitRequestCount(),
30
- 'span' => $oOpts->getLimitTimeSpan(),
31
- ]
32
- ]
33
- );
34
- }
35
-
36
- return $bAllowed;
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/Traffic/Options.php CHANGED
@@ -56,10 +56,27 @@ class Options extends Base\ShieldOptions {
56
  return (int)$this->getOpt( 'max_entries' );
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  * @return bool
61
  */
62
  public function isTrafficLimitEnabled() {
63
- return ( $this->getLimitTimeSpan() > 0 ) && ( $this->getLimitRequestCount() > 0 );
 
64
  }
65
  }
56
  return (int)$this->getOpt( 'max_entries' );
57
  }
58
 
59
+ /**
60
+ * @return string[]
61
+ */
62
+ public function getReqTypeExclusions() {
63
+ $aEx = $this->getOpt( 'type_exclusions' );
64
+ return is_array( $aEx ) ? $aEx : [];
65
+ }
66
+
67
+ /**
68
+ * @return bool
69
+ */
70
+ public function isTrafficLoggerEnabled() {
71
+ return $this->isOpt( 'enable_traffic', 'Y' ) && $this->isOpt( 'enable_logger', 'Y' )
72
+ && $this->getMaxEntries() > 0 && $this->getAutoCleanDays() > 0;
73
+ }
74
+
75
  /**
76
  * @return bool
77
  */
78
  public function isTrafficLimitEnabled() {
79
+ return $this->isTrafficLoggerEnabled() && $this->isOpt( 'enable_limiter', 'Y' )
80
+ && ( $this->getLimitTimeSpan() > 0 ) && ( $this->getLimitRequestCount() > 0 );
81
  }
82
  }
src/lib/src/Modules/Traffic/Strings.php CHANGED
@@ -46,13 +46,13 @@ class Strings extends Base\Strings {
46
  break;
47
 
48
  case 'section_traffic_limiter' :
49
- $sTitle = __( 'Traffic Limiter', 'wp-simple-firewall' );
50
- $sTitleShort = __( 'Brute Force Traffic Limiter', 'wp-simple-firewall' );
51
  $aSummary = [
52
- sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Provides ability to restrict excessive requests from a single visitor.', 'wp-simple-firewall' ) ),
53
- sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'These settings are dependent on your requirements.', 'wp-simple-firewall' ), __( 'User Management', 'wp-simple-firewall' ) ) ),
54
  sprintf( '%s - %s', __( 'Warning', 'wp-simple-firewall' ), __( 'Use this feature with care.', 'wp-simple-firewall' ) )
55
- .' '.sprintf( __( 'You could block legitimate visitors who load many pages in quick succession on your site.', 'wp-simple-firewall' ) )
56
  ];
57
  break;
58
 
@@ -85,6 +85,12 @@ class Strings extends Base\Strings {
85
  $sDescription = sprintf( __( 'Un-Checking this option will completely disable the %s module.', 'wp-simple-firewall' ), $sModName );
86
  break;
87
 
 
 
 
 
 
 
88
  case 'type_exclusions' :
89
  $sName = __( 'Traffic Log Exclusions', 'wp-simple-firewall' );
90
  $sSummary = __( 'Select Which Types Of Requests To Exclude', 'wp-simple-firewall' );
@@ -112,12 +118,19 @@ class Strings extends Base\Strings {
112
  $sDescription = __( 'DB cleanup will delete logs to maintain this maximum number of records.', 'wp-simple-firewall' );
113
  break;
114
 
 
 
 
 
 
 
115
  case 'limit_requests' :
116
  $sName = __( 'Max Request Limit', 'wp-simple-firewall' );
117
  $sSummary = __( 'Maximum Number Of Requests Allowed In Time Limit', 'wp-simple-firewall' );
118
- $sDescription = __( 'The maximum number of requests that are allowed in the given request time limit.', 'wp-simple-firewall' )
119
  .'<br/>'.__( 'Any visitor that exceeds this number of requests in the given time period will register an offense against their IP address.', 'wp-simple-firewall' )
120
- .'<br/>'.__( 'Enough offenses will result in a ban of the IP address.', 'wp-simple-firewall' );
 
121
  break;
122
 
123
  case 'limit_time_span' :
@@ -128,7 +141,8 @@ class Strings extends Base\Strings {
128
  .'<br/>'.sprintf( '%s: %s', __( 'Example', 'wp-simple-firewall' ),
129
  sprintf( __( 'Use %s to test for excessive requests within a %s minutes interval.', 'wp-simple-firewall' ), '<code>300</code>', 5 ) )
130
  .'<br/>'.sprintf( '%s: %s', __( 'Example', 'wp-simple-firewall' ),
131
- sprintf( __( 'Use %s to test for excessive requests within a %s minutes interval.', 'wp-simple-firewall' ), '<code>3600</code>', 60 ) );
 
132
  break;
133
 
134
  case 'auto_disable' :
46
  break;
47
 
48
  case 'section_traffic_limiter' :
49
+ $sTitle = __( 'Brute Force Traffic Rate Limiting', 'wp-simple-firewall' );
50
+ $sTitleShort = __( 'Traffic Rate Limiting', 'wp-simple-firewall' );
51
  $aSummary = [
52
+ sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Prevents excessive requests from a single visitor.', 'wp-simple-firewall' ) ),
53
+ sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ), sprintf( __( 'This feature is only available while the Traffic Logger is active.', 'wp-simple-firewall' ), __( 'User Management', 'wp-simple-firewall' ) ) ),
54
  sprintf( '%s - %s', __( 'Warning', 'wp-simple-firewall' ), __( 'Use this feature with care.', 'wp-simple-firewall' ) )
55
+ .' '.sprintf( __( 'You could block legitimate visitors who load too many pages in quick succession on your site.', 'wp-simple-firewall' ) )
56
  ];
57
  break;
58
 
85
  $sDescription = sprintf( __( 'Un-Checking this option will completely disable the %s module.', 'wp-simple-firewall' ), $sModName );
86
  break;
87
 
88
+ case 'enable_logger' :
89
+ $sName = __( 'Enable Traffic Logger', 'wp-simple-firewall' );
90
+ $sSummary = __( 'Turn On The Traffic Logging Feature', 'wp-simple-firewall' );
91
+ $sDescription = __( 'Enable or disable the ability to log and monitor requests to your site', 'wp-simple-firewall' );
92
+ break;
93
+
94
  case 'type_exclusions' :
95
  $sName = __( 'Traffic Log Exclusions', 'wp-simple-firewall' );
96
  $sSummary = __( 'Select Which Types Of Requests To Exclude', 'wp-simple-firewall' );
118
  $sDescription = __( 'DB cleanup will delete logs to maintain this maximum number of records.', 'wp-simple-firewall' );
119
  break;
120
 
121
+ case 'enable_limiter' :
122
+ $sName = __( 'Enable Rate Limiting', 'wp-simple-firewall' );
123
+ $sSummary = __( 'Turn On The Rate Limiting Feature', 'wp-simple-firewall' );
124
+ $sDescription = __( 'Enable or disable the rate limiting feature according to your rate limiting parameters.', 'wp-simple-firewall' );
125
+ break;
126
+
127
  case 'limit_requests' :
128
  $sName = __( 'Max Request Limit', 'wp-simple-firewall' );
129
  $sSummary = __( 'Maximum Number Of Requests Allowed In Time Limit', 'wp-simple-firewall' );
130
+ $sDescription = __( 'The maximum number of requests that are allowed within the given request time limit.', 'wp-simple-firewall' )
131
  .'<br/>'.__( 'Any visitor that exceeds this number of requests in the given time period will register an offense against their IP address.', 'wp-simple-firewall' )
132
+ .'<br/>'.__( 'Enough offenses will result in a ban of the IP address.', 'wp-simple-firewall' )
133
+ .'<br/>'.__( 'Use a larger maximum request limit to reduce the risk of blocking legitimate visitors.', 'wp-simple-firewall' );
134
  break;
135
 
136
  case 'limit_time_span' :
141
  .'<br/>'.sprintf( '%s: %s', __( 'Example', 'wp-simple-firewall' ),
142
  sprintf( __( 'Use %s to test for excessive requests within a %s minutes interval.', 'wp-simple-firewall' ), '<code>300</code>', 5 ) )
143
  .'<br/>'.sprintf( '%s: %s', __( 'Example', 'wp-simple-firewall' ),
144
+ sprintf( __( 'Use %s to test for excessive requests within a %s minutes interval.', 'wp-simple-firewall' ), '<code>3600</code>', 60 ) )
145
+ .'<br/>'.__( 'Use a smaller interval to reduce the risk of blocking legitimate visitors.', 'wp-simple-firewall' );
146
  break;
147
 
148
  case 'auto_disable' :
src/lib/src/Tables/Build/BaseBuild.php CHANGED
@@ -62,7 +62,7 @@ class BaseBuild {
62
  * @return string
63
  */
64
  protected function buildEmpty() {
65
- return sprintf( '<div class="alert alert-info m-0">%s</div>', __( 'No entries to display.', 'wp-simple-firewall' ) );
66
  }
67
 
68
  /**
62
  * @return string
63
  */
64
  protected function buildEmpty() {
65
+ return sprintf( '<div class="alert alert-success m-0">%s</div>', __( 'No entries to display.', 'wp-simple-firewall' ) );
66
  }
67
 
68
  /**
src/lib/src/Tables/Build/Sessions.php CHANGED
@@ -74,6 +74,13 @@ class Sessions extends BaseBuild {
74
  else {
75
  $aE[ 'your_ip' ] = '';
76
  }
 
 
 
 
 
 
 
77
  $aEntries[ $nKey ] = $aE;
78
  }
79
  return $aEntries;
74
  else {
75
  $aE[ 'your_ip' ] = '';
76
  }
77
+
78
+ $oWpUsers = Services::WpUsers();
79
+ $aE[ 'wp_username' ] = sprintf(
80
+ '<a href="%s">%s</a>',
81
+ $oWpUsers->getAdminUrl_ProfileEdit( $oWpUsers->getUserByUsername( $aE[ 'wp_username' ] ) ),
82
+ $aE[ 'wp_username' ]
83
+ );
84
  $aEntries[ $nKey ] = $aE;
85
  }
86
  return $aEntries;
src/lib/src/Tables/Render/Base.php CHANGED
@@ -265,7 +265,7 @@ class Base extends \WP_List_Table {
265
  */
266
  protected function getIpWhoisLookupLink( $sIp ) {
267
  $oIp = Services::IP();
268
- return sprintf( '<a href="%s" target="_blank" class="ip-whois">%s</a>',
269
  $oIp->isValidIpRange( $sIp ) ? $oIp->getIpWhoisLookup( $sIp ) : $oIp->getIpInfo( $sIp ),
270
  $sIp
271
  );
265
  */
266
  protected function getIpWhoisLookupLink( $sIp ) {
267
  $oIp = Services::IP();
268
+ return sprintf( '<a href="%s" target="_blank" class="ip-whois new-window-link">%s</a>',
269
  $oIp->isValidIpRange( $sIp ) ? $oIp->getIpWhoisLookup( $sIp ) : $oIp->getIpInfo( $sIp ),
270
  $sIp
271
  );
src/lib/src/Tests/VerifyUniqueEvents.php CHANGED
@@ -17,7 +17,7 @@ class VerifyUniqueEvents {
17
  $oCon = $this->getCon();
18
 
19
  $aAllKeys = [];
20
- foreach ( $oCon->getModules() as $oMod ) {
21
  $aKeys = array_map(
22
  function ( $aEvt ) {
23
  return $aEvt[ 'key' ];
17
  $oCon = $this->getCon();
18
 
19
  $aAllKeys = [];
20
+ foreach ( $oCon->modules as $oMod ) {
21
  $aKeys = array_map(
22
  function ( $aEvt ) {
23
  return $aEvt[ 'key' ];
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -204,7 +204,6 @@ return array(
204
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\DeleteAll' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/DeleteAll.php',
205
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Load' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Load.php',
206
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\ScheduleBuildAll' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/ScheduleBuildAll.php',
207
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\StoreFormatUpgrade' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/StoreFormatUpgrade.php',
208
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\TouchAll' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/TouchAll.php',
209
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Utility\\FileDownloadHandler' => $baseDir . '/src/Modules/HackGuard/Lib/Utility/FileDownloadHandler.php',
210
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => $baseDir . '/src/Modules/HackGuard/Options.php',
@@ -230,7 +229,6 @@ return array(
230
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanEnqueue' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php',
231
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanExecute' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanExecute.php',
232
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanInitiate' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php',
233
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Clean' => $baseDir . '/src/Modules/HackGuard/Scan/Results/Clean.php',
234
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ConvertBetweenTypes' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php',
235
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsDelete' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsDelete.php',
236
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsRetrieve' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php',
@@ -303,7 +301,6 @@ return array(
303
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\PluginBadge' => $baseDir . '/src/Modules/Plugin/Components/PluginBadge.php',
304
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\SiteGroundPluginCompatibility' => $baseDir . '/src/Modules/Plugin/Components/SiteGroundPluginCompatibility.php',
305
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Lib\\TourManager' => $baseDir . '/src/Modules/Plugin/Lib/TourManager.php',
306
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Lib\\WpHashesTokenManager' => $baseDir . '/src/Modules/Plugin/Lib/WpHashesTokenManager.php',
307
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Options' => $baseDir . '/src/Modules/Plugin/Options.php',
308
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Strings' => $baseDir . '/src/Modules/Plugin/Strings.php',
309
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\AdminNotices' => $baseDir . '/src/Modules/SecurityAdmin/AdminNotices.php',
@@ -318,8 +315,9 @@ return array(
318
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Options' => $baseDir . '/src/Modules/Statistics/Options.php',
319
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Strings' => $baseDir . '/src/Modules/Statistics/Strings.php',
320
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\AjaxHandler' => $baseDir . '/src/Modules/Traffic/AjaxHandler.php',
321
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Limiter\\Limiter' => $baseDir . '/src/Modules/Traffic/Limiter/Limiter.php',
322
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Limiter\\TestIp' => $baseDir . '/src/Modules/Traffic/Limiter/TestIp.php',
 
323
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Options' => $baseDir . '/src/Modules/Traffic/Options.php',
324
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Strings' => $baseDir . '/src/Modules/Traffic/Strings.php',
325
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\AjaxHandler' => $baseDir . '/src/Modules/UserManagement/AjaxHandler.php',
@@ -506,6 +504,7 @@ return array(
506
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncrypt' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php',
507
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncryptVo' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php',
508
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/Base.php',
 
509
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\CacheDefVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheDefVO.php',
510
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\LoadFromCache' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/LoadFromCache.php',
511
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\StoreToCache' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/StoreToCache.php',
@@ -543,12 +542,9 @@ return array(
543
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Base.php',
544
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\ReportFalsePositive' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/ReportFalsePositive.php',
545
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\RequestVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/RequestVO.php',
546
- 'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\Retrieve' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Retrieve.php',
547
- 'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\WhitelistRetrieve' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/WhitelistRetrieve.php',
548
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Base.php',
549
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\ReportFalsePositive' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/ReportFalsePositive.php',
550
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\RequestVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/RequestVO.php',
551
- 'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\Retrieve' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Retrieve.php',
552
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/Base.php',
553
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\IPs' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/IPs.php',
554
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\RequestVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/RequestVO.php',
@@ -572,6 +568,8 @@ return array(
572
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
573
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
574
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Lookup.php',
 
 
575
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\VisitorIpDetection' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php',
576
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
577
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
@@ -632,7 +630,6 @@ return array(
632
  'ICWP_WPSF_FeatureHandler_Traffic' => $baseDir . '/../features/traffic.php',
633
  'ICWP_WPSF_FeatureHandler_UserManagement' => $baseDir . '/../features/user_management.php',
634
  'ICWP_WPSF_Processor_AdminAccessRestriction' => $baseDir . '/../processors/admin_access_restriction.php',
635
- 'ICWP_WPSF_Processor_AdminAccess_Whitelabel' => $baseDir . '/../processors/adminaccess_whitelabel.php',
636
  'ICWP_WPSF_Processor_AuditTrail' => $baseDir . '/../processors/audit_trail.php',
637
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => $baseDir . '/../processors/audit_trail_auditor.php',
638
  'ICWP_WPSF_Processor_AuditTrail_ChangeTracking' => $baseDir . '/../processors/audit_trail_changetracking.php',
@@ -659,21 +656,12 @@ return array(
659
  'ICWP_WPSF_Processor_License' => $baseDir . '/../processors/license.php',
660
  'ICWP_WPSF_Processor_Lockdown' => $baseDir . '/../processors/lockdown.php',
661
  'ICWP_WPSF_Processor_LoginProtect' => $baseDir . '/../processors/login_protect.php',
662
- 'ICWP_WPSF_Processor_LoginProtect_BackupCodes' => $baseDir . '/../processors/loginprotect_intentprovider_backup.php',
663
  'ICWP_WPSF_Processor_LoginProtect_Base' => $baseDir . '/../processors/loginprotect_base.php',
664
  'ICWP_WPSF_Processor_LoginProtect_Cooldown' => $baseDir . '/../processors/loginprotect_cooldown.php',
665
  'ICWP_WPSF_Processor_LoginProtect_Gasp' => $baseDir . '/../processors/loginprotect_gasp.php',
666
- 'ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator' => $baseDir . '/../processors/loginprotect_intentprovider_ga.php',
667
  'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha' => $baseDir . '/../processors/loginprotect_googlerecaptcha.php',
668
- 'ICWP_WPSF_Processor_LoginProtect_Intent' => $baseDir . '/../processors/loginprotect_intent.php',
669
- 'ICWP_WPSF_Processor_LoginProtect_IntentProviderBase' => $baseDir . '/../processors/loginprotect_intentprovider_base.php',
670
- 'ICWP_WPSF_Processor_LoginProtect_Track' => $baseDir . '/../processors/loginprotect_intent_tracker.php',
671
- 'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth' => $baseDir . '/../processors/loginprotect_intentprovider_email.php',
672
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => $baseDir . '/../processors/loginprotect_wplogin.php',
673
- 'ICWP_WPSF_Processor_LoginProtect_Yubikey' => $baseDir . '/../processors/loginprotect_intentprovider_yubikey.php',
674
  'ICWP_WPSF_Processor_Plugin' => $baseDir . '/../processors/plugin.php',
675
- 'ICWP_WPSF_Processor_Plugin_CronDaily' => $baseDir . '/../processors/plugin_crondaily.php',
676
- 'ICWP_WPSF_Processor_Plugin_CronHourly' => $baseDir . '/../processors/plugin_cronhourly.php',
677
  'ICWP_WPSF_Processor_Plugin_ImportExport' => $baseDir . '/../processors/plugin_importexport.php',
678
  'ICWP_WPSF_Processor_Plugin_Tracking' => $baseDir . '/../processors/plugin_tracking.php',
679
  'ICWP_WPSF_Processor_ScanBase' => $baseDir . '/../processors/hackprotect_scan_base.php',
204
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\DeleteAll' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/DeleteAll.php',
205
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Load' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Load.php',
206
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\ScheduleBuildAll' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/ScheduleBuildAll.php',
 
207
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\TouchAll' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/TouchAll.php',
208
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Utility\\FileDownloadHandler' => $baseDir . '/src/Modules/HackGuard/Lib/Utility/FileDownloadHandler.php',
209
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => $baseDir . '/src/Modules/HackGuard/Options.php',
229
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanEnqueue' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php',
230
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanExecute' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanExecute.php',
231
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanInitiate' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php',
 
232
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ConvertBetweenTypes' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php',
233
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsDelete' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsDelete.php',
234
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsRetrieve' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php',
301
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\PluginBadge' => $baseDir . '/src/Modules/Plugin/Components/PluginBadge.php',
302
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\SiteGroundPluginCompatibility' => $baseDir . '/src/Modules/Plugin/Components/SiteGroundPluginCompatibility.php',
303
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Lib\\TourManager' => $baseDir . '/src/Modules/Plugin/Lib/TourManager.php',
 
304
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Options' => $baseDir . '/src/Modules/Plugin/Options.php',
305
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Strings' => $baseDir . '/src/Modules/Plugin/Strings.php',
306
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\AdminNotices' => $baseDir . '/src/Modules/SecurityAdmin/AdminNotices.php',
315
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Options' => $baseDir . '/src/Modules/Statistics/Options.php',
316
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Strings' => $baseDir . '/src/Modules/Statistics/Strings.php',
317
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\AjaxHandler' => $baseDir . '/src/Modules/Traffic/AjaxHandler.php',
318
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\Limiter' => $baseDir . '/src/Modules/Traffic/Lib/Limit/Limiter.php',
319
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\TestIp' => $baseDir . '/src/Modules/Traffic/Lib/Limit/TestIp.php',
320
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Logger' => $baseDir . '/src/Modules/Traffic/Lib/Logger.php',
321
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Options' => $baseDir . '/src/Modules/Traffic/Options.php',
322
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Strings' => $baseDir . '/src/Modules/Traffic/Strings.php',
323
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\AjaxHandler' => $baseDir . '/src/Modules/UserManagement/AjaxHandler.php',
504
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncrypt' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php',
505
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncryptVo' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php',
506
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/Base.php',
507
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\CacheConsumer' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheConsumer.php',
508
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\CacheDefVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheDefVO.php',
509
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\LoadFromCache' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/LoadFromCache.php',
510
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\StoreToCache' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/StoreToCache.php',
542
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Base.php',
543
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\ReportFalsePositive' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/ReportFalsePositive.php',
544
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\RequestVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/RequestVO.php',
 
 
545
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Base.php',
546
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\ReportFalsePositive' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/ReportFalsePositive.php',
547
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\RequestVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/RequestVO.php',
 
548
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/Base.php',
549
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\IPs' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/IPs.php',
550
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\RequestVO' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/RequestVO.php',
568
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
569
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
570
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Lookup.php',
571
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\BaseIP' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php',
572
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\FindSourceFromIp' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php',
573
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\VisitorIpDetection' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php',
574
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
575
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
630
  'ICWP_WPSF_FeatureHandler_Traffic' => $baseDir . '/../features/traffic.php',
631
  'ICWP_WPSF_FeatureHandler_UserManagement' => $baseDir . '/../features/user_management.php',
632
  'ICWP_WPSF_Processor_AdminAccessRestriction' => $baseDir . '/../processors/admin_access_restriction.php',
 
633
  'ICWP_WPSF_Processor_AuditTrail' => $baseDir . '/../processors/audit_trail.php',
634
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => $baseDir . '/../processors/audit_trail_auditor.php',
635
  'ICWP_WPSF_Processor_AuditTrail_ChangeTracking' => $baseDir . '/../processors/audit_trail_changetracking.php',
656
  'ICWP_WPSF_Processor_License' => $baseDir . '/../processors/license.php',
657
  'ICWP_WPSF_Processor_Lockdown' => $baseDir . '/../processors/lockdown.php',
658
  'ICWP_WPSF_Processor_LoginProtect' => $baseDir . '/../processors/login_protect.php',
 
659
  'ICWP_WPSF_Processor_LoginProtect_Base' => $baseDir . '/../processors/loginprotect_base.php',
660
  'ICWP_WPSF_Processor_LoginProtect_Cooldown' => $baseDir . '/../processors/loginprotect_cooldown.php',
661
  'ICWP_WPSF_Processor_LoginProtect_Gasp' => $baseDir . '/../processors/loginprotect_gasp.php',
 
662
  'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha' => $baseDir . '/../processors/loginprotect_googlerecaptcha.php',
 
 
 
 
663
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => $baseDir . '/../processors/loginprotect_wplogin.php',
 
664
  'ICWP_WPSF_Processor_Plugin' => $baseDir . '/../processors/plugin.php',
 
 
665
  'ICWP_WPSF_Processor_Plugin_ImportExport' => $baseDir . '/../processors/plugin_importexport.php',
666
  'ICWP_WPSF_Processor_Plugin_Tracking' => $baseDir . '/../processors/plugin_tracking.php',
667
  'ICWP_WPSF_Processor_ScanBase' => $baseDir . '/../processors/hackprotect_scan_base.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -353,7 +353,6 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
353
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\DeleteAll' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/DeleteAll.php',
354
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Load' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Load.php',
355
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\ScheduleBuildAll' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/ScheduleBuildAll.php',
356
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\StoreFormatUpgrade' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/StoreFormatUpgrade.php',
357
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\TouchAll' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/TouchAll.php',
358
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Utility\\FileDownloadHandler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Utility/FileDownloadHandler.php',
359
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Options.php',
@@ -379,7 +378,6 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
379
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanEnqueue' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php',
380
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanExecute' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanExecute.php',
381
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanInitiate' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php',
382
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Clean' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/Clean.php',
383
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ConvertBetweenTypes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php',
384
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsDelete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsDelete.php',
385
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsRetrieve' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php',
@@ -452,7 +450,6 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
452
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\PluginBadge' => __DIR__ . '/../..' . '/src/Modules/Plugin/Components/PluginBadge.php',
453
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\SiteGroundPluginCompatibility' => __DIR__ . '/../..' . '/src/Modules/Plugin/Components/SiteGroundPluginCompatibility.php',
454
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Lib\\TourManager' => __DIR__ . '/../..' . '/src/Modules/Plugin/Lib/TourManager.php',
455
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Lib\\WpHashesTokenManager' => __DIR__ . '/../..' . '/src/Modules/Plugin/Lib/WpHashesTokenManager.php',
456
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Options' => __DIR__ . '/../..' . '/src/Modules/Plugin/Options.php',
457
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Strings' => __DIR__ . '/../..' . '/src/Modules/Plugin/Strings.php',
458
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\AdminNotices' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/AdminNotices.php',
@@ -467,8 +464,9 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
467
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Options' => __DIR__ . '/../..' . '/src/Modules/Statistics/Options.php',
468
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Strings' => __DIR__ . '/../..' . '/src/Modules/Statistics/Strings.php',
469
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Traffic/AjaxHandler.php',
470
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Limiter\\Limiter' => __DIR__ . '/../..' . '/src/Modules/Traffic/Limiter/Limiter.php',
471
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Limiter\\TestIp' => __DIR__ . '/../..' . '/src/Modules/Traffic/Limiter/TestIp.php',
 
472
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Options' => __DIR__ . '/../..' . '/src/Modules/Traffic/Options.php',
473
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Strings' => __DIR__ . '/../..' . '/src/Modules/Traffic/Strings.php',
474
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/UserManagement/AjaxHandler.php',
@@ -655,6 +653,7 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
655
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncrypt' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php',
656
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncryptVo' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php',
657
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/Base.php',
 
658
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\CacheDefVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheDefVO.php',
659
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\LoadFromCache' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/LoadFromCache.php',
660
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\StoreToCache' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/StoreToCache.php',
@@ -692,12 +691,9 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
692
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Base.php',
693
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\ReportFalsePositive' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/ReportFalsePositive.php',
694
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\RequestVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/RequestVO.php',
695
- 'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\Retrieve' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Retrieve.php',
696
- 'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\WhitelistRetrieve' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/WhitelistRetrieve.php',
697
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Base.php',
698
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\ReportFalsePositive' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/ReportFalsePositive.php',
699
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\RequestVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/RequestVO.php',
700
- 'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\Retrieve' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Retrieve.php',
701
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/Base.php',
702
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\IPs' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/IPs.php',
703
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\RequestVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/RequestVO.php',
@@ -721,6 +717,8 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
721
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
722
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
723
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Lookup.php',
 
 
724
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\VisitorIpDetection' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php',
725
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
726
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
@@ -781,7 +779,6 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
781
  'ICWP_WPSF_FeatureHandler_Traffic' => __DIR__ . '/../..' . '/../features/traffic.php',
782
  'ICWP_WPSF_FeatureHandler_UserManagement' => __DIR__ . '/../..' . '/../features/user_management.php',
783
  'ICWP_WPSF_Processor_AdminAccessRestriction' => __DIR__ . '/../..' . '/../processors/admin_access_restriction.php',
784
- 'ICWP_WPSF_Processor_AdminAccess_Whitelabel' => __DIR__ . '/../..' . '/../processors/adminaccess_whitelabel.php',
785
  'ICWP_WPSF_Processor_AuditTrail' => __DIR__ . '/../..' . '/../processors/audit_trail.php',
786
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => __DIR__ . '/../..' . '/../processors/audit_trail_auditor.php',
787
  'ICWP_WPSF_Processor_AuditTrail_ChangeTracking' => __DIR__ . '/../..' . '/../processors/audit_trail_changetracking.php',
@@ -808,21 +805,12 @@ class ComposerStaticInitfcf2fe1888f1f5fc092770cdc8ef3cf4
808
  'ICWP_WPSF_Processor_License' => __DIR__ . '/../..' . '/../processors/license.php',
809
  'ICWP_WPSF_Processor_Lockdown' => __DIR__ . '/../..' . '/../processors/lockdown.php',
810
  'ICWP_WPSF_Processor_LoginProtect' => __DIR__ . '/../..' . '/../processors/login_protect.php',
811
- 'ICWP_WPSF_Processor_LoginProtect_BackupCodes' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_backup.php',
812
  'ICWP_WPSF_Processor_LoginProtect_Base' => __DIR__ . '/../..' . '/../processors/loginprotect_base.php',
813
  'ICWP_WPSF_Processor_LoginProtect_Cooldown' => __DIR__ . '/../..' . '/../processors/loginprotect_cooldown.php',
814
  'ICWP_WPSF_Processor_LoginProtect_Gasp' => __DIR__ . '/../..' . '/../processors/loginprotect_gasp.php',
815
- 'ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_ga.php',
816
  'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha' => __DIR__ . '/../..' . '/../processors/loginprotect_googlerecaptcha.php',
817
- 'ICWP_WPSF_Processor_LoginProtect_Intent' => __DIR__ . '/../..' . '/../processors/loginprotect_intent.php',
818
- 'ICWP_WPSF_Processor_LoginProtect_IntentProviderBase' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_base.php',
819
- 'ICWP_WPSF_Processor_LoginProtect_Track' => __DIR__ . '/../..' . '/../processors/loginprotect_intent_tracker.php',
820
- 'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_email.php',
821
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => __DIR__ . '/../..' . '/../processors/loginprotect_wplogin.php',
822
- 'ICWP_WPSF_Processor_LoginProtect_Yubikey' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_yubikey.php',
823
  'ICWP_WPSF_Processor_Plugin' => __DIR__ . '/../..' . '/../processors/plugin.php',
824
- 'ICWP_WPSF_Processor_Plugin_CronDaily' => __DIR__ . '/../..' . '/../processors/plugin_crondaily.php',
825
- 'ICWP_WPSF_Processor_Plugin_CronHourly' => __DIR__ . '/../..' . '/../processors/plugin_cronhourly.php',
826
  'ICWP_WPSF_Processor_Plugin_ImportExport' => __DIR__ . '/../..' . '/../processors/plugin_importexport.php',
827
  'ICWP_WPSF_Processor_Plugin_Tracking' => __DIR__ . '/../..' . '/../processors/plugin_tracking.php',
828
  'ICWP_WPSF_Processor_ScanBase' => __DIR__ . '/../..' . '/../processors/hackprotect_scan_base.php',
353
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\DeleteAll' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/DeleteAll.php',
354
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Load' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Load.php',
355
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\ScheduleBuildAll' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/ScheduleBuildAll.php',
 
356
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\TouchAll' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/TouchAll.php',
357
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Utility\\FileDownloadHandler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Utility/FileDownloadHandler.php',
358
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Options.php',
378
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanEnqueue' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php',
379
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanExecute' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanExecute.php',
380
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanInitiate' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php',
 
381
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ConvertBetweenTypes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php',
382
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsDelete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsDelete.php',
383
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsRetrieve' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php',
450
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\PluginBadge' => __DIR__ . '/../..' . '/src/Modules/Plugin/Components/PluginBadge.php',
451
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Components\\SiteGroundPluginCompatibility' => __DIR__ . '/../..' . '/src/Modules/Plugin/Components/SiteGroundPluginCompatibility.php',
452
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Lib\\TourManager' => __DIR__ . '/../..' . '/src/Modules/Plugin/Lib/TourManager.php',
 
453
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Options' => __DIR__ . '/../..' . '/src/Modules/Plugin/Options.php',
454
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Plugin\\Strings' => __DIR__ . '/../..' . '/src/Modules/Plugin/Strings.php',
455
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\AdminNotices' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/AdminNotices.php',
464
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Options' => __DIR__ . '/../..' . '/src/Modules/Statistics/Options.php',
465
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Statistics\\Strings' => __DIR__ . '/../..' . '/src/Modules/Statistics/Strings.php',
466
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Traffic/AjaxHandler.php',
467
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\Limiter' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Limit/Limiter.php',
468
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\TestIp' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Limit/TestIp.php',
469
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Logger' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Logger.php',
470
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Options' => __DIR__ . '/../..' . '/src/Modules/Traffic/Options.php',
471
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Strings' => __DIR__ . '/../..' . '/src/Modules/Traffic/Strings.php',
472
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/UserManagement/AjaxHandler.php',
653
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncrypt' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php',
654
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncryptVo' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php',
655
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/Base.php',
656
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\CacheConsumer' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheConsumer.php',
657
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\CacheDefVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheDefVO.php',
658
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\LoadFromCache' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/LoadFromCache.php',
659
  'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\Cache\\StoreToCache' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/Cache/StoreToCache.php',
691
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Base.php',
692
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\ReportFalsePositive' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/ReportFalsePositive.php',
693
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Signatures\\RequestVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/RequestVO.php',
 
 
694
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Base.php',
695
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\ReportFalsePositive' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/ReportFalsePositive.php',
696
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Malware\\Whitelist\\RequestVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/RequestVO.php',
 
697
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/Base.php',
698
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\IPs' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/IPs.php',
699
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Integrations\\WpHashes\\Services\\RequestVO' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Services/RequestVO.php',
717
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
718
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
719
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Lookup.php',
720
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\BaseIP' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php',
721
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\FindSourceFromIp' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php',
722
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\VisitorIpDetection' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php',
723
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Obfuscate' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Obfuscate.php',
724
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Options\\TestCanUseTransients' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Options/TestCanUseTransients.php',
779
  'ICWP_WPSF_FeatureHandler_Traffic' => __DIR__ . '/../..' . '/../features/traffic.php',
780
  'ICWP_WPSF_FeatureHandler_UserManagement' => __DIR__ . '/../..' . '/../features/user_management.php',
781
  'ICWP_WPSF_Processor_AdminAccessRestriction' => __DIR__ . '/../..' . '/../processors/admin_access_restriction.php',
 
782
  'ICWP_WPSF_Processor_AuditTrail' => __DIR__ . '/../..' . '/../processors/audit_trail.php',
783
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => __DIR__ . '/../..' . '/../processors/audit_trail_auditor.php',
784
  'ICWP_WPSF_Processor_AuditTrail_ChangeTracking' => __DIR__ . '/../..' . '/../processors/audit_trail_changetracking.php',
805
  'ICWP_WPSF_Processor_License' => __DIR__ . '/../..' . '/../processors/license.php',
806
  'ICWP_WPSF_Processor_Lockdown' => __DIR__ . '/../..' . '/../processors/lockdown.php',
807
  'ICWP_WPSF_Processor_LoginProtect' => __DIR__ . '/../..' . '/../processors/login_protect.php',
 
808
  'ICWP_WPSF_Processor_LoginProtect_Base' => __DIR__ . '/../..' . '/../processors/loginprotect_base.php',
809
  'ICWP_WPSF_Processor_LoginProtect_Cooldown' => __DIR__ . '/../..' . '/../processors/loginprotect_cooldown.php',
810
  'ICWP_WPSF_Processor_LoginProtect_Gasp' => __DIR__ . '/../..' . '/../processors/loginprotect_gasp.php',
 
811
  'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha' => __DIR__ . '/../..' . '/../processors/loginprotect_googlerecaptcha.php',
 
 
 
 
812
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => __DIR__ . '/../..' . '/../processors/loginprotect_wplogin.php',
 
813
  'ICWP_WPSF_Processor_Plugin' => __DIR__ . '/../..' . '/../processors/plugin.php',
 
 
814
  'ICWP_WPSF_Processor_Plugin_ImportExport' => __DIR__ . '/../..' . '/../processors/plugin_importexport.php',
815
  'ICWP_WPSF_Processor_Plugin_Tracking' => __DIR__ . '/../..' . '/../processors/plugin_tracking.php',
816
  'ICWP_WPSF_Processor_ScanBase' => __DIR__ . '/../..' . '/../processors/hackprotect_scan_base.php',
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php CHANGED
@@ -24,6 +24,43 @@ class Fs {
24
  return rtrim( $sBase, DIRECTORY_SEPARATOR ).DIRECTORY_SEPARATOR.ltrim( $sPath, DIRECTORY_SEPARATOR );
25
  }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  /**
28
  * @param $sFilePath
29
  * @return bool|null true/false whether file/directory exists
24
  return rtrim( $sBase, DIRECTORY_SEPARATOR ).DIRECTORY_SEPARATOR.ltrim( $sPath, DIRECTORY_SEPARATOR );
25
  }
26
 
27
+ /**
28
+ * @param string $sDir
29
+ * @param array $aExclude
30
+ */
31
+ public function emptyDir( $sDir, $aExclude = [] ) {
32
+ if ( $this->exists( $sDir ) ) {
33
+ foreach ( new \DirectoryIterator( $sDir ) as $oFile ) {
34
+ /** @var $oFile \DirectoryIterator */
35
+ if ( !$oFile->isDot() && !in_array( $oFile->getBasename(), $aExclude ) ) {
36
+ $oFile->isDir() ? $this->deleteDir( $oFile->getPathname() ) : $this->deleteFile( $oFile->getPathname() );
37
+ }
38
+ }
39
+ }
40
+ else {
41
+ $this->mkdir( $sDir );
42
+ }
43
+ }
44
+
45
+ /**
46
+ * @param string $sSource
47
+ * @param string $sTarget
48
+ */
49
+ public function moveDirContents( $sSource, $sTarget ) {
50
+
51
+ if ( !$this->exists( $sTarget ) ) {
52
+ $this->mkdir( $sTarget );
53
+ }
54
+
55
+ $oDirIt = new \DirectoryIterator( $sSource );
56
+ foreach ( $oDirIt as $oFile ) {
57
+ /** @var $oFile \DirectoryIterator */
58
+ if ( !$oFile->isDot() ) {
59
+ $this->move( $oFile->getPathname(), path_join( $sTarget, $oFile->getBasename() ) );
60
+ }
61
+ }
62
+ }
63
+
64
  /**
65
  * @param $sFilePath
66
  * @return bool|null true/false whether file/directory exists
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/Cache/CacheConsumer.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\File\Cache;
4
+
5
+ /**
6
+ * Trait CacheConsumer
7
+ * @package FernleafSystems\Wordpress\Services\Utilities\File\Cache
8
+ */
9
+ trait CacheConsumer {
10
+
11
+ /**
12
+ * @var CacheDefVO
13
+ */
14
+ private $oCacheDef;
15
+
16
+ /**
17
+ * @return CacheDefVO
18
+ */
19
+ public function getCacheDef() {
20
+ return $this->oCacheDef;
21
+ }
22
+
23
+ /**
24
+ * @param CacheDefVO $oDef
25
+ * @return $this
26
+ */
27
+ public function setCacheDef( $oDef ) {
28
+ $this->oCacheDef = $oDef;
29
+ return $this;
30
+ }
31
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Signatures/Retrieve.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware\Signatures;
4
-
5
- /**
6
- * Class Retrieve
7
- * @package FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware\Signatures
8
- */
9
- class Retrieve extends Base {
10
-
11
- const RESPONSE_DATA_KEY = 'hashes';
12
-
13
- /**
14
- * @return int[][]
15
- */
16
- public function getSignatures() {
17
- return $this->query();
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Whitelist/Retrieve.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware\Whitelist;
4
-
5
- /**
6
- * Class Retrieve
7
- * @package FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware\Whitelist
8
- */
9
- class Retrieve extends Base {
10
-
11
- const RESPONSE_DATA_KEY = 'hashes';
12
-
13
- /**
14
- * @return array[][]
15
- */
16
- public function getWhitelist() {
17
- return $this->query();
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/WhitelistRetrieve.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
4
-
5
- /**
6
- * Class WhitelistRetrieve
7
- * @package FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware
8
- * @deprecated 0.1.13
9
- */
10
- class WhitelistRetrieve extends Whitelist\Retrieve {
11
-
12
- /**
13
- * @return array[]|null
14
- * @deprecated
15
- */
16
- public function getFiles() {
17
- return $this->query();
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php CHANGED
@@ -5,6 +5,7 @@ namespace FernleafSystems\Wordpress\Services\Utilities;
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\Ipify;
 
8
 
9
  /**
10
  * Class IpUtils
@@ -333,32 +334,11 @@ class IpUtils {
333
  }
334
 
335
  /**
336
- * @param string $sVisitorIp
337
- * @return string
338
  */
339
- public function determineSourceFromIp( $sVisitorIp ) {
340
- $oReq = Services::Request();
341
-
342
- $sBestSource = null;
343
- foreach ( $this->getIpDetector()->getIpSourceOptions() as $sSource ) {
344
-
345
- $sIpToTest = $oReq->server( $sSource );
346
- if ( empty( $sIpToTest ) ) {
347
- continue;
348
- }
349
-
350
- // sometimes a comma-separated list is returned
351
- $aIpAddresses = array_map( 'trim', explode( ',', $sIpToTest ) );
352
- foreach ( $aIpAddresses as $sIp ) {
353
-
354
- if ( $sVisitorIp == $sIp ) {
355
- $sBestSource = $sSource;
356
- break( 2 );
357
- }
358
- }
359
- }
360
-
361
- return $sBestSource;
362
  }
363
 
364
  /**
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\Ipify;
8
+ use FernleafSystems\Wordpress\Services\Utilities\Net\FindSourceFromIp;
9
 
10
  /**
11
  * Class IpUtils
334
  }
335
 
336
  /**
337
+ * @param $sIP
338
+ * @return string|null
339
  */
340
+ public function determineSourceFromIp( $sIP ) {
341
+ return ( new FindSourceFromIp() )->run( $sIP );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  }
343
 
344
  /**
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Base.php CHANGED
@@ -28,21 +28,28 @@ abstract class Base {
28
  protected function sendReq() {
29
  $oHttpReq = Services::HttpRequest();
30
 
31
- $aParams = [
 
 
 
 
 
32
  'timeout' => $this->timeout,
33
- 'body' => array_intersect_key(
34
- $this->getRawDataAsArray(),
35
- array_flip( $this->getRequestBodyParamKeys() )
36
- )
37
  ];
38
 
39
  switch ( $this->request_method ) {
40
  case 'post':
41
- $bReqSuccess = $oHttpReq->post( $this->getApiRequestUrl(), $aParams );
 
42
  break;
43
  case 'get':
44
  default:
45
- $bReqSuccess = $oHttpReq->get( $this->getApiRequestUrl(), $aParams );
 
 
 
 
 
46
  break;
47
  }
48
 
28
  protected function sendReq() {
29
  $oHttpReq = Services::HttpRequest();
30
 
31
+ $aBodyParams = array_intersect_key(
32
+ $this->getRawDataAsArray(),
33
+ array_flip( $this->getRequestBodyParamKeys() )
34
+ );
35
+
36
+ $aReqParams = [
37
  'timeout' => $this->timeout,
 
 
 
 
38
  ];
39
 
40
  switch ( $this->request_method ) {
41
  case 'post':
42
+ $aReqParams[ 'body' ] = $aBodyParams;
43
+ $bReqSuccess = $oHttpReq->post( $this->getApiRequestUrl(), $aReqParams );
44
  break;
45
  case 'get':
46
  default:
47
+ // Doing it in the ['body'] on some sites fails with the params not passed through to query string.
48
+ // if they're not using the newer WP Request() class. WP 4.6+
49
+ $bReqSuccess = $oHttpReq->get(
50
+ add_query_arg( $aBodyParams, $this->getApiRequestUrl() ),
51
+ $aReqParams
52
+ );
53
  break;
54
  }
55
 
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\Net;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class BaseIP
9
+ * @package FernleafSystems\Wordpress\Services\Utilities\Net
10
+ */
11
+ class BaseIP {
12
+
13
+ /**
14
+ * @param string $sSource
15
+ * @return string[]
16
+ */
17
+ protected function getIpsFromSource( $sSource ) {
18
+ return array_filter(
19
+ array_map( 'trim', explode( ',', (string)Services::Request()->server( $sSource ) ) ),
20
+ function ( $sIp ) {
21
+ if ( substr_count( $sIp, ':' ) === 1 ) { // "IP:PORT"
22
+ $sIp = substr( $sIp, 0, strpos( $sIp, ':' ) );
23
+ }
24
+ return filter_var( $sIp, FILTER_VALIDATE_IP ) !== false;
25
+ }
26
+ );
27
+ }
28
+
29
+ /**
30
+ * @return string[]
31
+ */
32
+ public function getIpSourceOptions() {
33
+ return [
34
+ 'REMOTE_ADDR',
35
+ 'HTTP_CF_CONNECTING_IP',
36
+ 'HTTP_X_FORWARDED_FOR',
37
+ 'HTTP_X_FORWARDED',
38
+ 'HTTP_X_REAL_IP',
39
+ 'HTTP_X_SUCURI_CLIENTIP',
40
+ 'HTTP_INCAP_CLIENT_IP',
41
+ 'HTTP_X_SP_FORWARDED_IP',
42
+ 'HTTP_FORWARDED',
43
+ 'HTTP_CLIENT_IP'
44
+ ];
45
+ }
46
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\Net;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class FindSourceFromIp
9
+ * @package FernleafSystems\Wordpress\Services\Utilities\Net
10
+ */
11
+ class FindSourceFromIp extends BaseIP {
12
+
13
+ /**
14
+ * @param string $sIP
15
+ * @return string|null
16
+ */
17
+ public function run( $sIP ) {
18
+ $sTheSource = null;
19
+ foreach ( $this->getIpSourceOptions() as $sSource ) {
20
+ try {
21
+ if ( Services::IP()->checkIp( $sIP, $this->getIpsFromSource( $sSource ) ) ) {
22
+ $sTheSource = $sSource;
23
+ break;
24
+ }
25
+ }
26
+ catch ( \Exception $oE ) {
27
+ }
28
+ }
29
+ return $sTheSource;
30
+ }
31
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php CHANGED
@@ -8,7 +8,7 @@ use FernleafSystems\Wordpress\Services\Services;
8
  * Class VisitorIpDetection
9
  * @package FernleafSystems\Wordpress\Services\Utilities\Net
10
  */
11
- class VisitorIpDetection {
12
 
13
  const DEFAULT_SOURCE = 'REMOTE_ADDR';
14
 
@@ -105,22 +105,6 @@ class VisitorIpDetection {
105
  ) );
106
  }
107
 
108
- /**
109
- * @param string $sSource
110
- * @return string[]
111
- */
112
- protected function getIpsFromSource( $sSource ) {
113
- return array_filter(
114
- array_map( 'trim', explode( ',', (string)Services::Request()->server( $sSource ) ) ),
115
- function ( $sIp ) {
116
- if ( substr_count( $sIp, ':' ) === 1 ) { // "IP:PORT"
117
- $sIp = substr( $sIp, 0, strpos( $sIp, ':' ) );
118
- }
119
- return filter_var( $sIp, FILTER_VALIDATE_IP ) !== false;
120
- }
121
- );
122
- }
123
-
124
  /**
125
  * @return string
126
  */
@@ -154,24 +138,6 @@ class VisitorIpDetection {
154
  return $this;
155
  }
156
 
157
- /**
158
- * @return string[]
159
- */
160
- public function getIpSourceOptions() {
161
- return [
162
- 'REMOTE_ADDR',
163
- 'HTTP_CF_CONNECTING_IP',
164
- 'HTTP_X_FORWARDED_FOR',
165
- 'HTTP_X_FORWARDED',
166
- 'HTTP_X_REAL_IP',
167
- 'HTTP_X_SUCURI_CLIENTIP',
168
- 'HTTP_INCAP_CLIENT_IP',
169
- 'HTTP_X_SP_FORWARDED_IP',
170
- 'HTTP_FORWARDED',
171
- 'HTTP_CLIENT_IP'
172
- ];
173
- }
174
-
175
  /**
176
  * @deprecated 0.1.49
177
  */
8
  * Class VisitorIpDetection
9
  * @package FernleafSystems\Wordpress\Services\Utilities\Net
10
  */
11
+ class VisitorIpDetection extends BaseIP {
12
 
13
  const DEFAULT_SOURCE = 'REMOTE_ADDR';
14
 
105
  ) );
106
  }
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  /**
109
  * @return string
110
  */
138
  return $this;
139
  }
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  /**
142
  * @deprecated 0.1.49
143
  */
src/processors/adminaccess_whitelabel.php DELETED
@@ -1,141 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
- use FernleafSystems\Wordpress\Services\Services;
5
-
6
- /**
7
- * Class ICWP_WPSF_Processor_AdminAccess_Whitelabel
8
- * @deprecated 8.6.2
9
- */
10
- class ICWP_WPSF_Processor_AdminAccess_Whitelabel extends Modules\BaseShield\ShieldProcessor {
11
-
12
- /**
13
- */
14
- public function run() {
15
- $oCon = $this->getCon();
16
- add_filter( $oCon->prefix( 'is_relabelled' ), '__return_true' );
17
- add_filter( $oCon->prefix( 'plugin_labels' ), [ $this, 'doRelabelPlugin' ] );
18
- add_filter( 'plugin_row_meta', [ $this, 'fRemoveDetailsMetaLink' ], 200, 2 );
19
- add_action( 'admin_print_footer_scripts-plugin-editor.php', [ $this, 'hideFromPluginEditor' ] );
20
- }
21
-
22
- public function onWpInit() {
23
- /** @var Modules\SecurityAdmin\Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- if ( $oOpts->isWlHideUpdates() && $this->isNeedToHideUpdates() && !$this->getCon()->isPluginAdmin() ) {
26
- $this->hideUpdates();
27
- }
28
- }
29
-
30
- /**
31
- * Depending on the page, we hide the update data,
32
- * or we adjust the number of displayed updates counts
33
- */
34
- protected function hideUpdates() {
35
- if ( in_array( Services::WpPost()->getCurrentPage(), [ 'plugins.php', 'update-core.php' ] ) ) {
36
- add_filter( 'site_transient_update_plugins', [ $this, 'hidePluginUpdatesFromUI' ] );
37
- }
38
- else {
39
- add_filter( 'wp_get_update_data', [ $this, 'adjustUpdateDataCount' ] );
40
- }
41
- }
42
-
43
- /**
44
- * Adjusts the available updates count so as not to include Shield updates if they're hidden
45
- * @param array $aUpdateData
46
- * @return array
47
- */
48
- public function adjustUpdateDataCount( $aUpdateData ) {
49
-
50
- $sFile = $this->getCon()->getPluginBaseFile();
51
- if ( Services::WpPlugins()->isUpdateAvailable( $sFile ) ) {
52
- $aUpdateData[ 'counts' ][ 'total' ]--;
53
- $aUpdateData[ 'counts' ][ 'plugins' ]--;
54
- }
55
-
56
- return $aUpdateData;
57
- }
58
-
59
- public function hideFromPluginEditor() {
60
- $oCon = $this->getCon();
61
- $sJs = Services::Data()->readFileContentsUsingInclude( $oCon->getPath_AssetJs( 'whitelabel.js' ) );
62
- echo sprintf( '<script type="text/javascript">%s</script>', sprintf( $sJs, $oCon->getPluginBaseFile() ) );
63
- }
64
-
65
- /**
66
- * @param array $aPluginLabels
67
- * @return array
68
- */
69
- public function doRelabelPlugin( $aPluginLabels ) {
70
- /** @var \ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
71
- $oFO = $this->getMod();
72
-
73
- $aWhiteLabels = $oFO->getWhitelabelOptions();
74
-
75
- // these are the old white labelling keys which will be replaced upon final release of white labelling.
76
- $sServiceName = $aWhiteLabels[ 'name_main' ];
77
- $aPluginLabels[ 'Name' ] = $sServiceName;
78
- $aPluginLabels[ 'Title' ] = $sServiceName;
79
- $aPluginLabels[ 'Author' ] = $aWhiteLabels[ 'name_company' ];
80
- $aPluginLabels[ 'AuthorName' ] = $aWhiteLabels[ 'name_company' ];
81
- $aPluginLabels[ 'MenuTitle' ] = $aWhiteLabels[ 'name_menu' ];
82
-
83
- $sTagLine = $aWhiteLabels[ 'description' ];
84
- if ( !empty( $sTagLine ) ) {
85
- $aPluginLabels[ 'Description' ] = $sTagLine;
86
- }
87
-
88
- $sUrl = $aWhiteLabels[ 'url_home' ];
89
- if ( !empty( $sUrl ) ) {
90
- $aPluginLabels[ 'PluginURI' ] = $sUrl;
91
- $aPluginLabels[ 'AuthorURI' ] = $sUrl;
92
- }
93
-
94
- $sIconUrl = $aWhiteLabels[ 'url_icon' ];
95
- if ( !empty( $sIconUrl ) ) {
96
- $aPluginLabels[ 'icon_url_16x16' ] = $sIconUrl;
97
- $aPluginLabels[ 'icon_url_32x32' ] = $sIconUrl;
98
- }
99
-
100
- $sLogoUrl = $aWhiteLabels[ 'url_dashboardlogourl' ];
101
- if ( !empty( $sLogoUrl ) ) {
102
- $aPluginLabels[ 'icon_url_128x128' ] = $sLogoUrl;
103
- }
104
-
105
- return array_merge( $aWhiteLabels, $aPluginLabels );
106
- }
107
-
108
- /**
109
- * @filter
110
- * @param array $aPluginMeta
111
- * @param string $sPluginBaseFileName
112
- * @return array
113
- */
114
- public function fRemoveDetailsMetaLink( $aPluginMeta, $sPluginBaseFileName ) {
115
- if ( $sPluginBaseFileName == $this->getCon()->getPluginBaseFile() ) {
116
- unset( $aPluginMeta[ 2 ] ); // View details
117
- unset( $aPluginMeta[ 3 ] ); // Rate 5*
118
- }
119
- return $aPluginMeta;
120
- }
121
-
122
- /**
123
- * Hides the update if the page loaded is the plugins page or the updates page.
124
- * @param stdClass $oPlugins
125
- * @return stdClass
126
- */
127
- public function hidePluginUpdatesFromUI( $oPlugins ) {
128
- $sFile = $this->getCon()->getPluginBaseFile();
129
- if ( isset( $oPlugins->response[ $sFile ] ) ) {
130
- unset( $oPlugins->response[ $sFile ] );
131
- }
132
- return $oPlugins;
133
- }
134
-
135
- /**
136
- * @return bool
137
- */
138
- private function isNeedToHideUpdates() {
139
- return is_admin() && !Services::WpGeneral()->isCron();
140
- }
141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/autoupdates.php CHANGED
@@ -558,21 +558,4 @@ class ICWP_WPSF_Processor_Autoupdates extends Modules\BaseShield\ShieldProcessor
558
  protected function getHookPriority() {
559
  return $this->getOptions()->getDef( 'action_hook_priority' );
560
  }
561
-
562
- /**
563
- * This is a filter method designed to say whether a WordPress translations upgrades should be permitted,
564
- * based on the plugin settings.
565
- * @param bool $bUpdate
566
- * @return bool
567
- * @deprecated 8.6.2
568
- */
569
- public function autoupdate_translations( $bUpdate ) {
570
- return $bUpdate;
571
- }
572
-
573
- /**
574
- * @deprecated 8.6.2
575
- */
576
- private function forceRunAutoUpdates() {
577
- }
578
  }
558
  protected function getHookPriority() {
559
  return $this->getOptions()->getDef( 'action_hook_priority' );
560
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  }
src/processors/email.php CHANGED
@@ -7,42 +7,6 @@ class ICWP_WPSF_Processor_Email extends Modules\BaseShield\ShieldProcessor {
7
 
8
  const Slug = 'email';
9
 
10
- /**
11
- * @var string
12
- * @deprecated 8.6.2
13
- */
14
- protected static $sModeFile_EmailThrottled;
15
-
16
- /**
17
- * @var int
18
- * @deprecated 8.6.2
19
- */
20
- protected static $nThrottleInterval = 1;
21
-
22
- /**
23
- * @var int
24
- * @deprecated 8.6.2
25
- */
26
- protected $nEmailThrottleLimit;
27
-
28
- /**
29
- * @var int
30
- * @deprecated 8.6.2
31
- */
32
- protected $nEmailThrottleTime;
33
-
34
- /**
35
- * @var int
36
- * @deprecated 8.6.2
37
- */
38
- protected $nEmailThrottleCount;
39
-
40
- /**
41
- * @var bool
42
- * @deprecated 8.6.2
43
- */
44
- protected $bEmailIsThrottled;
45
-
46
  /**
47
  * @return array
48
  */
@@ -182,24 +146,6 @@ class ICWP_WPSF_Processor_Email extends Modules\BaseShield\ShieldProcessor {
182
  return $this->sendEmailWithWrap( null, $sEmailSubject, $aMessage );
183
  }
184
 
185
- /**
186
- * Whether we're throttled is dependent on 2 signals. The time interval has changed, or the there's a file
187
- * system object telling us we're throttled.
188
- * The file system object takes precedence.
189
- * @return bool
190
- * @deprecated 8.6.2
191
- */
192
- protected function updateEmailThrottle() {
193
- return true;
194
- }
195
-
196
- /**
197
- * @param bool $infOn
198
- * @deprecated 8.6.2
199
- */
200
- public function setThrottledFile( $infOn = false ) {
201
- }
202
-
203
  /**
204
  * @param string $sEmail
205
  * @return string
@@ -207,12 +153,4 @@ class ICWP_WPSF_Processor_Email extends Modules\BaseShield\ShieldProcessor {
207
  public function verifyEmailAddress( $sEmail = '' ) {
208
  return Services::Data()->validEmail( $sEmail ) ? $sEmail : Services::WpGeneral()->getSiteAdminEmail();
209
  }
210
-
211
-
212
- /**
213
- * @deprecated 8.6.2
214
- */
215
- public function getThrottleLimit() {
216
- return 0;
217
- }
218
  }
7
 
8
  const Slug = 'email';
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  /**
11
  * @return array
12
  */
146
  return $this->sendEmailWithWrap( null, $sEmailSubject, $aMessage );
147
  }
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  /**
150
  * @param string $sEmail
151
  * @return string
153
  public function verifyEmailAddress( $sEmail = '' ) {
154
  return Services::Data()->validEmail( $sEmail ) ? $sEmail : Services::WpGeneral()->getSiteAdminEmail();
155
  }
 
 
 
 
 
 
 
 
156
  }
src/processors/ips.php CHANGED
@@ -5,17 +5,9 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
5
 
6
  class ICWP_WPSF_Processor_Ips extends Shield\Modules\BaseShield\ShieldProcessor {
7
 
8
- /**
9
- */
10
  public function run() {
11
  ( new IPs\Lib\BlacklistHandler() )
12
  ->setMod( $this->getMod() )
13
  ->run();
14
  }
15
-
16
- /**
17
- * @deprecated 8.6.2
18
- */
19
- private function doBlackMarkCurrentVisitor() {
20
- }
21
  }
5
 
6
  class ICWP_WPSF_Processor_Ips extends Shield\Modules\BaseShield\ShieldProcessor {
7
 
 
 
8
  public function run() {
9
  ( new IPs\Lib\BlacklistHandler() )
10
  ->setMod( $this->getMod() )
11
  ->run();
12
  }
 
 
 
 
 
 
13
  }
src/processors/login_protect.php CHANGED
@@ -1,7 +1,6 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor;
5
  use FernleafSystems\Wordpress\Services\Services;
6
 
7
  class ICWP_WPSF_Processor_LoginProtect extends Modules\BaseShield\ShieldProcessor {
@@ -105,49 +104,8 @@ class ICWP_WPSF_Processor_LoginProtect extends Modules\BaseShield\ShieldProcesso
105
  return [
106
  'cooldown' => 'ICWP_WPSF_Processor_LoginProtect_Cooldown',
107
  'gasp' => 'ICWP_WPSF_Processor_LoginProtect_Gasp',
108
- 'intent' => 'ICWP_WPSF_Processor_LoginProtect_Intent',
109
  'recaptcha' => 'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha',
110
  'rename' => 'ICWP_WPSF_Processor_LoginProtect_WpLogin',
111
  ];
112
  }
113
-
114
- /**
115
- * @return \ICWP_WPSF_Processor_LoginProtect_Cooldown
116
- * @deprecated 8.6.0
117
- */
118
- private function getSubProCooldown() {
119
- return $this->getSubPro( 'cooldown' );
120
- }
121
-
122
- /**
123
- * @return \ICWP_WPSF_Processor_LoginProtect_Gasp
124
- * @deprecated 8.6.0
125
- */
126
- private function getSubProGasp() {
127
- return $this->getSubPro( 'gasp' );
128
- }
129
-
130
- /**
131
- * @return \ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha
132
- * @deprecated 8.6.0
133
- */
134
- private function getSubProRecaptcha() {
135
- return $this->getSubPro( 'recaptcha' );
136
- }
137
-
138
- /**
139
- * @return \ICWP_WPSF_Processor_LoginProtect_WpLogin
140
- * @deprecated 8.6.0
141
- */
142
- private function getSubProRename() {
143
- return $this->getSubPro( 'rename' );
144
- }
145
-
146
- /**
147
- * @return \ICWP_WPSF_Processor_LoginProtect_Intent
148
- * @deprecated 8.6.0
149
- */
150
- public function getSubProIntent() {
151
- return $this->getSubPro( 'intent' );
152
- }
153
  }
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
 
4
  use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_Processor_LoginProtect extends Modules\BaseShield\ShieldProcessor {
104
  return [
105
  'cooldown' => 'ICWP_WPSF_Processor_LoginProtect_Cooldown',
106
  'gasp' => 'ICWP_WPSF_Processor_LoginProtect_Gasp',
 
107
  'recaptcha' => 'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha',
108
  'rename' => 'ICWP_WPSF_Processor_LoginProtect_WpLogin',
109
  ];
110
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
src/processors/loginprotect_base.php CHANGED
@@ -128,6 +128,12 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends Modules\BaseShield\
128
  // MemberPress - Checkout == Registration
129
  add_action( 'mepr-checkout-before-submit', [ $this, 'printRegisterFormItems_MePr' ], 10 );
130
  add_filter( 'mepr-validate-signup', [ $this, 'checkReqRegistration_MePr' ], 10, 2 );
 
 
 
 
 
 
131
  // Ultimate Member
132
  add_action( 'um_after_register_fields', [ $this, 'printFormItems_UltMem' ], 100 );
133
  add_action( 'um_submit_form_register', [ $this, 'checkReqRegistration_UltMem' ], 5, 0 );
@@ -430,6 +436,36 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends Modules\BaseShield\
430
  return $sFieldNameOrError;
431
  }
432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
  /**
434
  */
435
  public function checkReqRegistration_UltMem() {
@@ -508,6 +544,13 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends Modules\BaseShield\
508
  $this->printLoginFormItems();
509
  }
510
 
 
 
 
 
 
 
 
511
  /**
512
  * LearnPress
513
  * @return void
@@ -638,11 +681,25 @@ abstract class ICWP_WPSF_Processor_LoginProtect_Base extends Modules\BaseShield\
638
  return defined( 'MEPR_LIB_PATH' ) || defined( 'MEPR_PLUGIN_NAME' );
639
  }
640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
641
  /**
642
  * @return bool
643
  */
644
  protected function isUltimateMember() {
645
- return function_exists( 'UM' ) && class_exists( 'UM' ) && method_exists( 'UM', 'form' );
646
  }
647
 
648
  /**
128
  // MemberPress - Checkout == Registration
129
  add_action( 'mepr-checkout-before-submit', [ $this, 'printRegisterFormItems_MePr' ], 10 );
130
  add_filter( 'mepr-validate-signup', [ $this, 'checkReqRegistration_MePr' ], 10, 2 );
131
+ // Paid Member Subscriptions (https://wordpress.org/plugins/paid-member-subscriptions)
132
+ add_action( 'pms_register_form_after_fields', [ $this, 'printFormItems_PaidMemberSubscriptions' ], 100 );
133
+ add_filter( 'pms_register_form_validation', [ $this, 'checkReqReg_PaidMemberSubscriptions' ], 100 );
134
+ // Profile Builder (https://wordpress.org/plugins/profile-builder/)
135
+ add_action( 'wppb_form_before_submit_button', [ $this, 'printLoginFormItems' ], 100 );
136
+ add_filter( 'wppb_output_field_errors_filter', [ $this, 'checkReqReg_ProfileBuilder' ], 100 );
137
  // Ultimate Member
138
  add_action( 'um_after_register_fields', [ $this, 'printFormItems_UltMem' ], 100 );
139
  add_action( 'um_submit_form_register', [ $this, 'checkReqRegistration_UltMem' ], 5, 0 );
436
  return $sFieldNameOrError;
437
  }
438
 
439
+ public function checkReqReg_PaidMemberSubscriptions() {
440
+ if ( $this->isPaidMemberSubscriptions() ) {
441
+ try {
442
+ $this->setActionToAudit( 'paidmembersubscriptions-register' )
443
+ ->performCheckWithException();
444
+ }
445
+ catch ( \Exception $oE ) {
446
+ \pms_errors()->add( 'shield-fail-register', $oE->getMessage() );
447
+ }
448
+ }
449
+ }
450
+
451
+ /**
452
+ * @param array $aErrors
453
+ * @return array
454
+ */
455
+ public function checkReqReg_ProfileBuilder( $aErrors ) {
456
+ if ( $this->isProfileBuilder() ) {
457
+ try {
458
+ $this->setActionToAudit( 'profilebuilder-register' )
459
+ ->performCheckWithException();
460
+ }
461
+ catch ( \Exception $oE ) {
462
+ $aErrors[ 'shield-fail-register' ] =
463
+ '<span class="wppb-form-error">Bot</span>';
464
+ }
465
+ }
466
+ return $aErrors;
467
+ }
468
+
469
  /**
470
  */
471
  public function checkReqRegistration_UltMem() {
544
  $this->printLoginFormItems();
545
  }
546
 
547
+ /**
548
+ * @return void
549
+ */
550
+ public function printFormItems_PaidMemberSubscriptions() {
551
+ $this->printLoginFormItems();
552
+ }
553
+
554
  /**
555
  * LearnPress
556
  * @return void
681
  return defined( 'MEPR_LIB_PATH' ) || defined( 'MEPR_PLUGIN_NAME' );
682
  }
683
 
684
+ /**
685
+ * @return bool
686
+ */
687
+ protected function isPaidMemberSubscriptions() {
688
+ return @class_exists( 'Paid_Member_Subscriptions' ) && function_exists( 'pms_errors' );
689
+ }
690
+
691
+ /**
692
+ * @return bool
693
+ */
694
+ protected function isProfileBuilder() {
695
+ return defined( 'PROFILE_BUILDER_VERSION' );
696
+ }
697
+
698
  /**
699
  * @return bool
700
  */
701
  protected function isUltimateMember() {
702
+ return function_exists( 'UM' ) && @class_exists( 'UM' ) && method_exists( 'UM', 'form' );
703
  }
704
 
705
  /**
src/processors/loginprotect_intent.php DELETED
@@ -1,128 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Plugin\Shield;
4
- use FernleafSystems\Wordpress\Services\Services;
5
-
6
- /**
7
- * @deprecated 8.6.0
8
- */
9
- class ICWP_WPSF_Processor_LoginProtect_Intent extends Shield\Modules\BaseShield\ShieldProcessor {
10
-
11
- /**
12
- * @var ICWP_WPSF_Processor_LoginProtect_Track
13
- */
14
- private $oLoginTrack;
15
-
16
- /**
17
- * @var bool
18
- */
19
- private $bLoginIntentProcessed;
20
-
21
- /**
22
- */
23
- public function run() {
24
- }
25
-
26
- /**
27
- * @param int $nUserId
28
- */
29
- public function onWcSocialLogin( $nUserId ) {
30
- }
31
-
32
- protected function setupLoginIntent() {
33
- }
34
-
35
- /**
36
- * @param WP_User|WP_Error $oUser
37
- */
38
- protected function initLoginIntent( $oUser ) {}
39
-
40
- /**
41
- * hooked to 'init' and only run if a user is logged-in (not on the login request)
42
- */
43
- private function processLoginIntent() {}
44
-
45
- /**
46
- * Use this ONLY when the login intent has been successfully verified.
47
- * @return $this
48
- */
49
- private function removeLoginIntent() {
50
- return $this->setLoginIntentExpiresAt( 0 );
51
- }
52
-
53
- /**
54
- * @param int $nExpirationTime
55
- * @return $this
56
- */
57
- protected function setLoginIntentExpiresAt( $nExpirationTime ) {
58
- return $this;
59
- }
60
-
61
- /**
62
- * @return int
63
- */
64
- protected function getLoginIntentExpiresAt() {
65
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
66
- $oFO = $this->getMod();
67
- return $oFO->hasSession() ? $oFO->getSession()->login_intent_expires_at : 0;
68
- }
69
-
70
- /**
71
- * @return bool
72
- */
73
- protected function hasLoginIntent() {
74
- return $this->getLoginIntentExpiresAt() > 0;
75
- }
76
-
77
- /**
78
- * @return bool
79
- */
80
- protected function hasValidLoginIntent() {
81
- return $this->hasLoginIntent() && ( $this->getLoginIntentExpiresAt() > Services::Request()->ts() );
82
- }
83
-
84
- /**
85
- */
86
- private function printLoginIntentForm() {}
87
- /**
88
- */
89
- public function onWpLogout() {
90
- }
91
-
92
- /**
93
- * @return ICWP_WPSF_Processor_LoginProtect_Track
94
- */
95
- public function getLoginTrack() {
96
- return $this->oLoginTrack;
97
- }
98
-
99
- /**
100
- * assume that a user is logged in.
101
- * @return bool
102
- */
103
- private function isLoginIntentValid() {
104
- return false;
105
- }
106
-
107
- /**
108
- * @return bool
109
- */
110
- public function isLoginIntentProcessed() {
111
- return true;
112
- }
113
-
114
- /**
115
- * @return $this
116
- */
117
- public function setLoginIntentProcessed() {
118
- return $this;
119
- }
120
-
121
- /**
122
- * @param ICWP_WPSF_Processor_LoginProtect_Track $oLoginTrack
123
- * @return $this
124
- */
125
- public function setLoginTrack( $oLoginTrack ) {
126
- return $this;
127
- }
128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_intent_tracker.php DELETED
@@ -1,166 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class ICWP_WPSF_Processor_LoginProtect_Track
5
- * @deprecated 8.6.0
6
- */
7
- class ICWP_WPSF_Processor_LoginProtect_Track {
8
-
9
- const Factor_Google_Authenticator = 'ga';
10
- const Factor_Yubikey = 'yubi';
11
- const Factor_Email = 'email';
12
- const Factor_BackupCode = 'backupcode';
13
-
14
- /**
15
- * @var array
16
- */
17
- private $aFactorsTracked;
18
-
19
- /**
20
- * @var array
21
- */
22
- private $aFactorsToTrack;
23
-
24
- /**
25
- * @param string $sFactor
26
- * @return $this
27
- */
28
- public function addFactorToTrack( $sFactor ) {
29
- $aFactorsToTrack = $this->getAuthFactorsToTrack();
30
- $aFactorsToTrack[ $sFactor ] = true;
31
- $this->aFactorsToTrack = $aFactorsToTrack;
32
- return $this;
33
- }
34
-
35
- /**
36
- * @param string $sFactor
37
- * @return $this
38
- */
39
- public function addSuccessfulFactor( $sFactor ) {
40
- return $this->setFactorState( $sFactor, true );
41
- }
42
-
43
- /**
44
- * @param string $sFactor
45
- * @return $this
46
- */
47
- public function addUnSuccessfulFactor( $sFactor ) {
48
- return $this->setFactorState( $sFactor, false );
49
- }
50
-
51
- /**
52
- * @return array
53
- */
54
- public function getAuthFactorsTracked() {
55
- if ( !isset( $this->aFactorsTracked ) ) {
56
- $this->aFactorsTracked = [];
57
- }
58
- return $this->aFactorsTracked;
59
- }
60
-
61
- /**
62
- * @return array
63
- */
64
- public function getAuthFactorsToTrack() {
65
- if ( !is_array( $this->aFactorsToTrack ) ) {
66
- $this->aFactorsToTrack = [];
67
- }
68
- return array_unique( $this->aFactorsToTrack );
69
- }
70
-
71
- /**
72
- * @return int
73
- */
74
- public function getCountAuthFactorsTrackedTotal() {
75
- return count( $this->getAuthFactorsTracked() );
76
- }
77
-
78
- /**
79
- * Works by using array_filter() with no callback, so only those values in the
80
- * array that don't evaluate as false are returned. #SuperOmgElegant :)
81
- * @return int
82
- */
83
- public function getCountFactorsSuccessful() {
84
- return count( $this->getFactorsSuccessful() );
85
- }
86
-
87
- /**
88
- * @return array
89
- */
90
- public function getFactorsSuccessful() {
91
- return array_keys( array_filter( $this->getAuthFactorsTracked() ) ); // filter out the 'falses'
92
- }
93
-
94
- /**
95
- * @return array
96
- */
97
- public function getFactorsUnsuccessful() {
98
- return array_diff( array_keys( $this->getAuthFactorsTracked() ), $this->getFactorsSuccessful() );
99
- }
100
-
101
- /**
102
- * @return int
103
- */
104
- public function getCountFactorsUnsuccessful() {
105
- return ( $this->getCountAuthFactorsTrackedTotal() - $this->getCountFactorsSuccessful() );
106
- }
107
-
108
- /**
109
- * @return int
110
- */
111
- public function getCountFactorsRemainingToTrack() {
112
- return count( $this->getAuthFactorsToTrack() );
113
- }
114
-
115
- /**
116
- * @return bool
117
- */
118
- public function hasFactorsRemainingToTrack() {
119
- return ( $this->getCountFactorsRemainingToTrack() > 0 );
120
- }
121
-
122
- /**
123
- * @return bool
124
- */
125
- public function hasSuccessfulFactor() {
126
- return ( $this->getCountFactorsSuccessful() > 0 );
127
- }
128
-
129
- /**
130
- * @return bool
131
- */
132
- public function hasUnSuccessfulFactor() {
133
- return ( $this->getCountFactorsUnsuccessful() > 0 );
134
- }
135
-
136
- /**
137
- * @return bool
138
- */
139
- public function isFinalFactorRemainingToTrack() {
140
- return ( $this->getCountFactorsRemainingToTrack() === 1 );
141
- }
142
-
143
- /**
144
- * @param string $sFactor
145
- * @return $this
146
- */
147
- public function removeFactorToTrack( $sFactor ) {
148
- $aFactorsToTrack = $this->getAuthFactorsToTrack();
149
- unset( $aFactorsToTrack[ $sFactor ] );
150
- $this->aFactorsToTrack = $aFactorsToTrack;
151
- return $this;
152
- }
153
-
154
- /**
155
- * Also remove remaining factors to track
156
- * @param string $sFactor
157
- * @param bool $bState
158
- * @return $this
159
- */
160
- protected function setFactorState( $sFactor, $bState ) {
161
- $aFactors = $this->getAuthFactorsTracked();
162
- $aFactors[ $sFactor ] = $bState;
163
- $this->aFactorsTracked = $aFactors;
164
- return $this->removeFactorToTrack( $sFactor );
165
- }
166
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_intentprovider_backup.php DELETED
@@ -1,118 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Services\Services;
4
-
5
- /**
6
- * @deprecated 8.6.0
7
- */
8
- class ICWP_WPSF_Processor_LoginProtect_BackupCodes extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
9
-
10
- /**
11
- * @param \WP_User $oUser
12
- */
13
- public function addOptionsToUserEditProfile( $oUser ) {
14
- // Allow no actions to be taken on other user profiles
15
- }
16
-
17
- /**
18
- * @param array $aFields
19
- * @return array
20
- */
21
- public function addLoginIntentField( $aFields ) {
22
- if ( $this->getCurrentUserHasValidatedProfile() ) {
23
- $aFields[] = [
24
- 'name' => $this->getLoginFormParameter(),
25
- 'type' => 'text',
26
- 'value' => '',
27
- 'placeholder' => __( 'Please use your Backup Code to login.', 'wp-simple-firewall' ),
28
- 'text' => __( 'Login Backup Code', 'wp-simple-firewall' ),
29
- 'help_link' => '',
30
- ];
31
- }
32
- return $aFields;
33
- }
34
-
35
- /**
36
- * Backup codes shouldn't make a user subject to login intent, but only be presented as required
37
- * - i.e. they have other MFA options but they can't be used at the moment. So no MFA options =
38
- * no need for backup codes
39
- * @param bool $bIsSubjectTo
40
- * @param \WP_User $oUser
41
- * @return bool
42
- */
43
- public function filterUserSubjectToIntent( $bIsSubjectTo, $oUser ) {
44
- return $bIsSubjectTo;
45
- }
46
-
47
- /**
48
- * @param \WP_User $oUser
49
- * @return bool
50
- */
51
- protected function hasValidatedProfile( $oUser ) {
52
- return $this->hasValidSecret( $oUser );
53
- }
54
-
55
- /**
56
- * Backup Code are 1-time only and if you have MFA, then we need to remove all the other tracking factors
57
- * @param WP_User $oUser
58
- * @param string $sOtpCode
59
- * @return bool
60
- */
61
- protected function processOtp( $oUser, $sOtpCode ) {
62
- $bValid = $this->validateBackupCode( $oUser, $sOtpCode );
63
- if ( $bValid ) {
64
- $this->deleteSecret( $oUser );
65
- }
66
- return $bValid;
67
- }
68
-
69
- /**
70
- * @param WP_User $oUser
71
- * @param string $sOtpCode
72
- * @return bool
73
- */
74
- private function validateBackupCode( $oUser, $sOtpCode ) {
75
- return wp_check_password( str_replace( '-', '', $sOtpCode ), $this->getSecret( $oUser ) );
76
- }
77
-
78
- /**
79
- * @param \WP_User $oUser
80
- * @param bool $bIsSuccess
81
- */
82
- protected function auditLogin( $oUser, $bIsSuccess ) {
83
- $this->getCon()->fireEvent(
84
- $bIsSuccess ? '2fa_backupcode_verified' : '2fa_backupcode_fail',
85
- [
86
- 'audit' => [
87
- 'user_login' => $oUser->user_login,
88
- 'method' => 'Backup Code',
89
- ]
90
- ]
91
- );
92
- }
93
-
94
- /**
95
- * @param \WP_User $oUser
96
- * @return string
97
- */
98
- protected function genNewSecret( \WP_User $oUser ) {
99
- return wp_generate_password( 25, false );
100
- }
101
-
102
- /**
103
- * @param WP_User $oUser
104
- * @param string $sNewSecret
105
- * @return $this
106
- */
107
- protected function setSecret( $oUser, $sNewSecret ) {
108
- parent::setSecret( $oUser, wp_hash_password( $sNewSecret ) );
109
- return $this;
110
- }
111
-
112
- /**
113
- * @return string
114
- */
115
- protected function getStub() {
116
- return ICWP_WPSF_Processor_LoginProtect_Track::Factor_BackupCode;
117
- }
118
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_intentprovider_base.php DELETED
@@ -1,316 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
- use FernleafSystems\Wordpress\Services\Services;
5
-
6
- /**
7
- * @deprecated 8.6.0
8
- */
9
- abstract class ICWP_WPSF_Processor_LoginProtect_IntentProviderBase extends Modules\BaseShield\ShieldProcessor {
10
-
11
- /**
12
- * @var ICWP_WPSF_Processor_LoginProtect_Track
13
- */
14
- private $oLoginTrack;
15
-
16
- /**
17
- */
18
- public function run() {
19
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
20
- $oMod = $this->getMod();
21
-
22
- $this->getLoginTrack()->addFactorToTrack( $this->getStub() );
23
-
24
- if ( $oMod->getIfUseLoginIntentPage() ) {
25
- add_filter( $oMod->prefix( 'login-intent-form-fields' ), [ $this, 'addLoginIntentField' ] );
26
- add_action( $oMod->prefix( 'login-intent-validation' ), [ $this, 'validateLoginIntent' ] );
27
- }
28
-
29
- if ( Services::WpGeneral()->isLoginRequest() || $oMod->getIfSupport3rdParty() ) {
30
- // add_filter( 'authenticate', array( $this, 'processLoginAttempt_Filter' ), 30, 2 );
31
- }
32
-
33
- // Necessary so we don't show user intent to people without it
34
- add_filter( $oMod->prefix( 'user_subject_to_login_intent' ), [ $this, 'filterUserSubjectToIntent' ], 10, 2 );
35
-
36
- add_action( 'show_user_profile', [ $this, 'addOptionsToUserProfile' ] );
37
- add_action( 'personal_options_update', [ $this, 'handleUserProfileSubmit' ] );
38
-
39
- if ( $this->getCon()->isPluginAdmin() ) {
40
- add_action( 'edit_user_profile', [ $this, 'addOptionsToUserEditProfile' ] );
41
- add_action( 'edit_user_profile_update', [ $this, 'handleEditOtherUserProfileSubmit' ] );
42
- }
43
- }
44
-
45
- /**
46
- * @param string $sUsername
47
- * @param \WP_User $oUser
48
- */
49
- public function onWpLogin( $sUsername, $oUser ) {
50
- $this->processLoginAttempt( $oUser );
51
- }
52
-
53
- /**
54
- * @param string $sCookie
55
- * @param int $nExpire
56
- * @param int $nExpiration
57
- * @param int $nUserId
58
- */
59
- public function onWpSetLoggedInCookie( $sCookie, $nExpire, $nExpiration, $nUserId ) {
60
- $this->processLoginAttempt( Services::WpUsers()->getUserById( $nUserId ) );
61
- }
62
-
63
- /**
64
- * @param \WP_User $oUser
65
- */
66
- public function validateLoginIntent( $oUser ) {
67
- $oLoginTrack = $this->getLoginTrack();
68
-
69
- $sFactor = $this->getStub();
70
- if ( !$this->isProfileReady( $oUser ) ) {
71
- $oLoginTrack->removeFactorToTrack( $sFactor );
72
- }
73
- else {
74
- $sReqOtpCode = $this->fetchCodeFromRequest();
75
- $bOtpSuccess = $this->processOtp( $oUser, $sReqOtpCode );
76
- if ( $bOtpSuccess ) {
77
- $oLoginTrack->addSuccessfulFactor( $sFactor );
78
- }
79
- else {
80
- $oLoginTrack->addUnSuccessfulFactor( $sFactor );
81
- }
82
-
83
- $this->postOtpProcessAction( $oUser, $bOtpSuccess, !empty( $sReqOtpCode ) );
84
- }
85
- }
86
-
87
- /**
88
- * @return bool
89
- */
90
- public function getCurrentUserHasValidatedProfile() {
91
- return $this->hasValidatedProfile( Services::WpUsers()->getCurrentWpUser() );
92
- }
93
-
94
- /**
95
- * @param \WP_User $oUser
96
- * @return bool
97
- * @since 6.9.0 removed fallback to old user meta
98
- */
99
- protected function hasValidatedProfile( $oUser ) {
100
- $sKey = $this->getStub().'_validated';
101
- return ( $oUser instanceof \WP_User )
102
- && $this->hasValidSecret( $oUser )
103
- && $this->getCon()->getUserMeta( $oUser )->{$sKey} === true;
104
- }
105
-
106
- /**
107
- * @param \WP_User $oUser
108
- * @return string
109
- */
110
- protected function getSecret( \WP_User $oUser ) {
111
- $sKey = $this->getStub().'_secret';
112
- $oMeta = $this->getCon()->getUserMeta( $oUser );
113
- $sSecret = $oMeta->{$sKey};
114
- return empty( $sSecret ) ? '' : $oMeta->{$sKey};
115
- }
116
-
117
- /**
118
- * @param \WP_User $oUser
119
- * @return bool
120
- */
121
- protected function isProfileReady( \WP_User $oUser ) {
122
- return $this->hasValidatedProfile( $oUser ) && $this->hasValidSecret( $oUser );
123
- }
124
-
125
- /**
126
- * @param \WP_User $oUser
127
- * @return bool
128
- */
129
- protected function hasValidSecret( \WP_User $oUser ) {
130
- return $this->isSecretValid( $this->getSecret( $oUser ) );
131
- }
132
-
133
- /**
134
- * @param string $sSecret
135
- * @return bool
136
- */
137
- protected function isSecretValid( $sSecret ) {
138
- return !empty( $sSecret ) && is_string( $sSecret );
139
- }
140
-
141
- /**
142
- * @param \WP_User $oUser
143
- * @return $this
144
- */
145
- public function deleteSecret( $oUser ) {
146
- $oMeta = $this->getCon()->getUserMeta( $oUser );
147
- $sKey = $this->getStub().'_secret';
148
- $oMeta->{$sKey} = null;
149
- return $this;
150
- }
151
-
152
- /**
153
- * @param \WP_User $oUser
154
- * @return string
155
- */
156
- public function resetSecret( \WP_User $oUser ) {
157
- $sNewSecret = $this->genNewSecret( $oUser );
158
- $this->setSecret( $oUser, $sNewSecret );
159
- return $sNewSecret;
160
- }
161
-
162
- /**
163
- * @param \WP_User $oUser
164
- * @param bool $bValidated set true for validated, false for invalidated
165
- * @return $this
166
- */
167
- public function setProfileValidated( $oUser, $bValidated = true ) {
168
- $sKey = $this->getStub().'_validated';
169
- $oMeta = $this->getCon()->getUserMeta( $oUser );
170
- $oMeta->{$sKey} = $bValidated;
171
- return $this;
172
- }
173
-
174
- /**
175
- * @param \WP_User $oUser
176
- * @param string $sNewSecret
177
- * @return $this
178
- */
179
- protected function setSecret( $oUser, $sNewSecret ) {
180
- $oMeta = $this->getCon()->getUserMeta( $oUser );
181
- $sKey = $this->getStub().'_secret';
182
- $oMeta->{$sKey} = $sNewSecret;
183
- return $this;
184
- }
185
-
186
- /**
187
- * @param \WP_User $oUser
188
- * @return string
189
- */
190
- protected function genNewSecret( \WP_User $oUser ) {
191
- return '';
192
- }
193
-
194
- /**
195
- * @param \WP_User $oUser
196
- * @param string $sOtpCode
197
- * @return bool
198
- */
199
- abstract protected function processOtp( $oUser, $sOtpCode );
200
-
201
- /**
202
- * Look to LoginTracker
203
- * @return string
204
- */
205
- abstract protected function getStub();
206
-
207
- /**
208
- * This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
209
- * functions. Otherwise we need to be careful of mixing up users.
210
- * @param \WP_User $oUser
211
- */
212
- public function addOptionsToUserProfile( $oUser ) {
213
- }
214
-
215
- /**
216
- * ONLY TO BE HOOKED TO USER PROFILE EDIT
217
- * @param \WP_User $oUser
218
- */
219
- public function addOptionsToUserEditProfile( $oUser ) {
220
- $this->addOptionsToUserProfile( $oUser );
221
- }
222
-
223
- /**
224
- * The only thing we can do is REMOVE Google Authenticator from an account that is not our own
225
- * But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
226
- * @param int $nSavingUserId
227
- */
228
- public function handleEditOtherUserProfileSubmit( $nSavingUserId ) {
229
- }
230
-
231
- /**
232
- * @param \WP_User $oUser
233
- */
234
- protected function processRemovalFromAccount( $oUser ) {
235
- }
236
-
237
- /**
238
- * This MUST only ever be hooked into when the User is looking at their OWN profile,
239
- * so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
240
- * @param int $nSavingUserId
241
- */
242
- public function handleUserProfileSubmit( $nSavingUserId ) {
243
- }
244
-
245
- /**
246
- * @param WP_Error|WP_User $oUser
247
- * @return WP_Error|WP_User
248
- */
249
- public function processLoginAttempt( $oUser ) {
250
- return $oUser;
251
- }
252
-
253
- /**
254
- * @param array $aFields
255
- * @return array
256
- */
257
- abstract public function addLoginIntentField( $aFields );
258
-
259
- /**
260
- * @param \WP_User $oUser
261
- * @param bool $bIsSuccess
262
- */
263
- abstract protected function auditLogin( $oUser, $bIsSuccess );
264
-
265
- /**
266
- * @param \WP_User $oUser
267
- * @param bool $bIsOtpSuccess
268
- * @param bool $bOtpProvided - whether a OTP was actually provided
269
- * @return $this
270
- */
271
- protected function postOtpProcessAction( $oUser, $bIsOtpSuccess, $bOtpProvided ) {
272
- if ( $bOtpProvided ) {
273
- $this->auditLogin( $oUser, $bIsOtpSuccess );
274
- }
275
- return $this;
276
- }
277
-
278
- /**
279
- * @return string
280
- */
281
- protected function getLoginFormParameter() {
282
- return $this->getCon()->prefixOption( $this->getStub().'_otp' );
283
- }
284
-
285
- /**
286
- * @return string
287
- */
288
- protected function fetchCodeFromRequest() {
289
- return esc_attr( Services::Request()->request( $this->getLoginFormParameter(), false, '' ) );
290
- }
291
-
292
- /**
293
- * @param bool $bIsSubjectTo
294
- * @param \WP_User $oUser
295
- * @return bool
296
- */
297
- public function filterUserSubjectToIntent( $bIsSubjectTo, $oUser ) {
298
- return ( $bIsSubjectTo || $this->hasValidatedProfile( $oUser ) );
299
- }
300
-
301
- /**
302
- * @return ICWP_WPSF_Processor_LoginProtect_Track
303
- */
304
- public function getLoginTrack() {
305
- return $this->oLoginTrack;
306
- }
307
-
308
- /**
309
- * @param ICWP_WPSF_Processor_LoginProtect_Track $oLoginTrack
310
- * @return $this
311
- */
312
- public function setLoginTrack( $oLoginTrack ) {
313
- $this->oLoginTrack = $oLoginTrack;
314
- return $this;
315
- }
316
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_intentprovider_email.php DELETED
@@ -1,149 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Services\Services;
4
-
5
- /**
6
- * @deprecated 8.6.0
7
- */
8
- class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
9
-
10
- /**
11
- * @param WP_User|WP_Error|null $oUser
12
- * @return WP_Error|WP_User|null - WP_User when the login success AND the IP is authenticated. null when login
13
- * not successful but IP is valid. WP_Error otherwise.
14
- */
15
- public function processLoginAttempt( $oUser ) {
16
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
17
- $oMod = $this->getMod();
18
-
19
- if ( !$this->isLoginCaptured() && $oUser instanceof WP_User
20
- && $this->hasValidatedProfile( $oUser ) && !$oMod->canUserMfaSkip( $oUser ) ) {
21
-
22
- /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Update $oUpd */
23
- $oUpd = $oMod->getDbHandler_Sessions()->getQueryUpdater();
24
- $oUpd->setLoginIntentCodeEmail( $oMod->getSession(), $this->getSecret( $oUser ) );
25
-
26
- // Now send email with authentication link for user.
27
- $this->setLoginCaptured();
28
- }
29
- return $oUser;
30
- }
31
-
32
- /**
33
- * @param WP_User $oUser
34
- * @param bool $bIsSuccess
35
- */
36
- protected function auditLogin( $oUser, $bIsSuccess ) {
37
- $this->getCon()->fireEvent(
38
- $bIsSuccess ? 'email_verified' : 'email_fail',
39
- [
40
- 'audit' => [
41
- 'user_login' => $oUser->user_login,
42
- 'method' => 'Email',
43
- ]
44
- ]
45
- );
46
- }
47
-
48
- /**
49
- * @param WP_User $oUser
50
- * @param string $sOtpCode
51
- * @return bool
52
- */
53
- protected function processOtp( $oUser, $sOtpCode ) {
54
- $bValid = !empty( $sOtpCode ) && ( $sOtpCode == $this->getStoredSessionHashCode() );
55
- if ( $bValid ) {
56
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
57
- $oMod = $this->getMod();
58
- /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Update $oUpd */
59
- $oUpd = $oMod->getDbHandler_Sessions()->getQueryUpdater();
60
- $oUpd->clearLoginIntentCodeEmail( $oMod->getSession() );
61
- }
62
- return $bValid;
63
- }
64
-
65
- /**
66
- * @param array $aFields
67
- * @return array
68
- */
69
- public function addLoginIntentField( $aFields ) {
70
- if ( $this->getCurrentUserHasValidatedProfile() ) {
71
- $aFields[] = [
72
- 'name' => $this->getLoginFormParameter(),
73
- 'type' => 'text',
74
- 'value' => $this->fetchCodeFromRequest(),
75
- 'placeholder' => __( 'This code was just sent to your registered Email address.', 'wp-simple-firewall' ),
76
- 'text' => __( 'Email OTP', 'wp-simple-firewall' ),
77
- 'help_link' => 'https://shsec.io/3t'
78
- ];
79
- }
80
- return $aFields;
81
- }
82
-
83
- /**
84
- * @param WP_User $oUser
85
- * @return bool
86
- */
87
- protected function hasValidatedProfile( $oUser ) {
88
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
89
- $oFO = $this->getMod();
90
- // Currently it's a global setting but this will evolve to be like Google Authenticator so that it's a user meta
91
- return ( $oFO->isEmailAuthenticationActive() && $this->isSubjectToEmailAuthentication( $oUser ) );
92
- }
93
-
94
- /**
95
- * @param WP_User $oUser
96
- * @return bool
97
- */
98
- private function isSubjectToEmailAuthentication( $oUser ) {
99
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
100
- $oFO = $this->getMod();
101
- return count( array_intersect( $oFO->getEmail2FaRoles(), $oUser->roles ) ) > 0;
102
- }
103
-
104
- /**
105
- * We don't use user meta as it's dependent on the particular user sessions in-use
106
- * @param \WP_User $oUser
107
- * @return string
108
- */
109
- protected function getSecret( \WP_User $oUser ) {
110
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
111
- $oMod = $this->getMod();
112
- return strtoupper( substr(
113
- hash_hmac( 'sha1', $this->getCon()->getUniqueRequestId(), $oMod->getTwoAuthSecretKey() ),
114
- 0, 6
115
- ) );
116
- }
117
-
118
- /**
119
- * @return string The unique 2FA 6-digit code
120
- */
121
- protected function getStoredSessionHashCode() {
122
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
123
- $oFO = $this->getMod();
124
- return $oFO->hasSession() ? $oFO->getSession()->getLoginIntentCodeEmail() : '';
125
- }
126
-
127
- /**
128
- * @param string $sSecret
129
- * @return bool
130
- */
131
- protected function isSecretValid( $sSecret ) {
132
- $sHash = $this->getStoredSessionHashCode();
133
- return !empty( $sHash );
134
- }
135
-
136
- /**
137
- * @return string
138
- */
139
- protected function getStub() {
140
- return ICWP_WPSF_Processor_LoginProtect_Track::Factor_Email;
141
- }
142
-
143
- /**
144
- * @return string
145
- */
146
- protected function get2FaCodeUserMetaKey() {
147
- return $this->getMod()->prefix( 'tfaemail_reqid' );
148
- }
149
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_intentprovider_ga.php DELETED
@@ -1,325 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Services\Services;
4
- use Dolondro\GoogleAuthenticator;
5
-
6
- /**
7
- * @deprecated 8.6.0
8
- */
9
- class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
10
-
11
- /**
12
- * @var GoogleAuthenticator\Secret
13
- */
14
- private $oWorkingSecret;
15
-
16
- /**
17
- */
18
- public function run() {
19
- parent::run();
20
- if ( $this->getCon()->getShieldAction() == 'garemovalconfirm' ) {
21
- add_action( 'wp_loaded', [ $this, 'validateUserGaRemovalLink' ], 10 );
22
- }
23
- }
24
-
25
- /**
26
- * @param \WP_User $oUser
27
- * @return string
28
- */
29
- public function getGaRegisterChartUrl( $oUser ) {
30
- if ( empty( $oUser ) ) {
31
- $sUrl = '';
32
- }
33
- else {
34
- $sUrl = ( new GoogleAuthenticator\QrImageGenerator\GoogleQrImageGenerator () )
35
- ->generateUri(
36
- $this->getGaSecret( $oUser )
37
- );
38
- }
39
- return $sUrl;
40
- }
41
-
42
- /**
43
- * The only thing we can do is REMOVE Google Authenticator from an account that is not our own
44
- * But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
45
- * @param int $nSavingUserId
46
- */
47
- public function handleEditOtherUserProfileSubmit( $nSavingUserId ) {
48
-
49
- // Can only edit other users if you're admin/security-admin
50
- if ( $this->getCon()->isPluginAdmin() ) {
51
- $oWpUsers = Services::WpUsers();
52
- $oSavingUser = $oWpUsers->getUserById( $nSavingUserId );
53
-
54
- $sShieldTurnOff = Services::Request()->post( 'shield_turn_off_google_authenticator' );
55
- if ( !empty( $sShieldTurnOff ) && $sShieldTurnOff == 'Y' ) {
56
-
57
- $bPermissionToRemoveGa = true;
58
- // if the current user has Google Authenticator on THEIR account, process their OTP.
59
- $oCurrentUser = $oWpUsers->getCurrentWpUser();
60
- if ( $this->hasValidatedProfile( $oCurrentUser ) ) {
61
- $bPermissionToRemoveGa = $this->processOtp( $oCurrentUser, $this->fetchCodeFromRequest() );
62
- }
63
-
64
- if ( $bPermissionToRemoveGa ) {
65
- $this->processRemovalFromAccount( $oSavingUser );
66
- $sMsg = __( 'Google Authenticator was successfully removed from the account.', 'wp-simple-firewall' );
67
- }
68
- else {
69
- $sMsg = __( 'Google Authenticator could not be removed from the account - ensure your code is correct.', 'wp-simple-firewall' );
70
- }
71
- $this->getMod()->setFlashAdminNotice( $sMsg, $bPermissionToRemoveGa );
72
- }
73
- }
74
- else {
75
- // DO NOTHING EVER
76
- }
77
- }
78
-
79
- /**
80
- * @param WP_User $oUser
81
- * @return $this
82
- */
83
- protected function processRemovalFromAccount( $oUser ) {
84
- $this->setProfileValidated( $oUser, false )
85
- ->resetSecret( $oUser );
86
- return $this;
87
- }
88
-
89
- /**
90
- * This MUST only ever be hooked into when the User is looking at their OWN profile,
91
- * so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
92
- * @param int $nSavingUserId
93
- */
94
- public function handleUserProfileSubmit( $nSavingUserId ) {
95
- $oWpUsers = Services::WpUsers();
96
-
97
- $oSavingUser = $oWpUsers->getUserById( $nSavingUserId );
98
-
99
- // If it's your own account, you CANT do anything without your OTP (except turn off via email).
100
- $sOtp = $this->fetchCodeFromRequest();
101
- $bValidOtp = $this->processOtp( $oSavingUser, $sOtp );
102
-
103
- $sMessageOtpInvalid = __( 'One Time Password (OTP) was not valid.', 'wp-simple-firewall' ).' '.__( 'Please try again.', 'wp-simple-firewall' );
104
-
105
- $sShieldTurnOff = Services::Request()->post( 'shield_turn_off_google_authenticator' );
106
- if ( !empty( $sShieldTurnOff ) && $sShieldTurnOff == 'Y' ) {
107
-
108
- $bError = false;
109
- if ( $bValidOtp ) {
110
- $this->processRemovalFromAccount( $oSavingUser );
111
- $sFlash = __( 'Google Authenticator was successfully removed from the account.', 'wp-simple-firewall' );
112
- }
113
- elseif ( empty( $sOtp ) ) {
114
-
115
- if ( $this->sendEmailConfirmationGaRemoval( $oSavingUser ) ) {
116
- $sFlash = __( 'An email has been sent to you in order to confirm Google Authenticator removal', 'wp-simple-firewall' );
117
- }
118
- else {
119
- $bError = true;
120
- $sFlash = __( 'We tried to send an email for you to confirm Google Authenticator removal but it failed.', 'wp-simple-firewall' );
121
- }
122
- }
123
- else {
124
- $bError = true;
125
- $sFlash = $sMessageOtpInvalid;
126
- }
127
- $this->getMod()->setFlashAdminNotice( $sFlash, $bError );
128
- return;
129
- }
130
-
131
- // At this stage, if the OTP was empty, then we have no further processing to do.
132
- if ( empty( $sOtp ) ) {
133
- return;
134
- }
135
-
136
- // We're trying to validate our OTP to activate our GA
137
- if ( !$this->hasValidatedProfile( $oSavingUser ) ) {
138
-
139
- if ( $bValidOtp ) {
140
- $this->setProfileValidated( $oSavingUser );
141
- $sFlash = sprintf(
142
- __( '%s was successfully added to your account.', 'wp-simple-firewall' ),
143
- __( 'Google Authenticator', 'wp-simple-firewall' )
144
- );
145
- }
146
- else {
147
- $this->resetSecret( $oSavingUser );
148
- $sFlash = $sMessageOtpInvalid;
149
- }
150
- $this->getMod()->setFlashAdminNotice( $sFlash, !$bValidOtp );
151
- }
152
- }
153
-
154
- /**
155
- * @param array $aFields
156
- * @return array
157
- */
158
- public function addLoginIntentField( $aFields ) {
159
- if ( $this->getCurrentUserHasValidatedProfile() ) {
160
- $aFields[] = [
161
- 'name' => $this->getLoginFormParameter(),
162
- 'type' => 'text',
163
- 'value' => '',
164
- 'placeholder' => __( 'Please use your Google Authenticator App to retrieve your code.', 'wp-simple-firewall' ),
165
- 'text' => __( 'Google Authenticator Code', 'wp-simple-firewall' ),
166
- 'help_link' => 'https://shsec.io/wpsf42',
167
- 'extras' => [
168
- 'onkeyup' => "this.value=this.value.replace(/[^\d]/g,'')"
169
- ]
170
- ];
171
- }
172
- return $aFields;
173
- }
174
-
175
- /**
176
- * @param WP_User $oUser
177
- * @return bool
178
- */
179
- protected function sendEmailConfirmationGaRemoval( $oUser ) {
180
- $bSendSuccess = false;
181
-
182
- $aEmailContent = [];
183
- $aEmailContent[] = __( 'You have requested the removal of Google Authenticator from your WordPress account.', 'wp-simple-firewall' )
184
- .__( 'Please click the link below to confirm.', 'wp-simple-firewall' );
185
- $aEmailContent[] = $this->generateGaRemovalConfirmationLink();
186
-
187
- $sRecipient = $oUser->get( 'user_email' );
188
- if ( Services::Data()->validEmail( $sRecipient ) ) {
189
- $sEmailSubject = __( 'Google Authenticator Removal Confirmation', 'wp-simple-firewall' );
190
- $bSendSuccess = $this->getEmailProcessor()
191
- ->sendEmailWithWrap( $sRecipient, $sEmailSubject, $aEmailContent );
192
- }
193
- return $bSendSuccess;
194
- }
195
-
196
- /**
197
- */
198
- public function validateUserGaRemovalLink() {
199
- // Must be already logged in for this link to work.
200
- $oWpCurrentUser = Services::WpUsers()->getCurrentWpUser();
201
- if ( empty( $oWpCurrentUser ) ) {
202
- return;
203
- }
204
-
205
- // Session IDs must be the same
206
- $sSessionId = Services::Request()->query( 'sessionid' );
207
- if ( empty( $sSessionId ) || ( $sSessionId !== $this->getCon()->getSessionId() ) ) {
208
- return;
209
- }
210
-
211
- $this->processRemovalFromAccount( $oWpCurrentUser );
212
- $this->getMod()
213
- ->setFlashAdminNotice( __( 'Google Authenticator was successfully removed from this account.', 'wp-simple-firewall' ) );
214
- Services::Response()->redirectToAdmin();
215
- }
216
-
217
- /**
218
- * @param WP_User $oUser
219
- * @param string $sOtpCode
220
- * @return bool
221
- */
222
- protected function processOtp( $oUser, $sOtpCode ) {
223
- return $this->validateGaCode( $oUser, $sOtpCode );
224
- }
225
-
226
- /**
227
- * @param WP_User $oUser
228
- * @param string $sOtpCode
229
- * @return bool
230
- */
231
- public function validateGaCode( $oUser, $sOtpCode ) {
232
- $bValidOtp = false;
233
- if ( !empty( $sOtpCode ) && preg_match( '#^[0-9]{6}$#', $sOtpCode ) ) {
234
- try {
235
- $bValidOtp = ( new GoogleAuthenticator\GoogleAuthenticator() )
236
- ->authenticate( $this->getSecret( $oUser ), $sOtpCode );
237
- }
238
- catch ( \Exception $oE ) {
239
- }
240
- catch ( \Psr\Cache\CacheException $oE ) {
241
- }
242
- }
243
- return $bValidOtp;
244
- }
245
-
246
- /**
247
- * @param WP_User $oUser
248
- * @param bool $bIsSuccess
249
- */
250
- protected function auditLogin( $oUser, $bIsSuccess ) {
251
- $this->getCon()->fireEvent(
252
- $bIsSuccess ? 'googleauth_verified' : 'googleauth_fail',
253
- [
254
- 'audit' => [
255
- 'user_login' => $oUser->user_login,
256
- 'method' => 'Google Authenticator',
257
- ]
258
- ]
259
- );
260
- }
261
-
262
- /**
263
- * @return string
264
- */
265
- protected function generateGaRemovalConfirmationLink() {
266
- $aQueryArgs = [
267
- 'shield_action' => 'garemovalconfirm',
268
- 'sessionid' => $this->getCon()->getSessionId()
269
- ];
270
- return add_query_arg( $aQueryArgs, Services::WpGeneral()->getAdminUrl() );
271
- }
272
-
273
- /**
274
- * @param \WP_User $oUser
275
- * @return string
276
- */
277
- protected function genNewSecret( \WP_User $oUser ) {
278
- try {
279
- return $this->getGaSecret( $oUser )->getSecretKey();
280
- }
281
- catch ( \InvalidArgumentException $oE ) {
282
- return '';
283
- }
284
- }
285
-
286
- /**
287
- * @param \WP_User $oUser
288
- * @return GoogleAuthenticator\Secret
289
- * @throws InvalidArgumentException
290
- */
291
- private function getGaSecret( $oUser ) {
292
- if ( !isset( $this->oWorkingSecret ) ) {
293
- $this->oWorkingSecret = ( new GoogleAuthenticator\SecretFactory() )
294
- ->create(
295
- sanitize_user( $oUser->user_login ),
296
- preg_replace( '#[^0-9a-z]#i', '', Services::WpGeneral()->getSiteName() )
297
- );
298
- }
299
- return $this->oWorkingSecret;
300
- }
301
-
302
- /**
303
- * @param \WP_User $oUser
304
- * @return string
305
- */
306
- protected function getSecret( WP_User $oUser ) {
307
- $sSec = parent::getSecret( $oUser );
308
- return empty( $sSec ) ? $this->resetSecret( $oUser ) : $sSec;
309
- }
310
-
311
- /**
312
- * @return string
313
- */
314
- protected function getStub() {
315
- return ICWP_WPSF_Processor_LoginProtect_Track::Factor_Google_Authenticator;
316
- }
317
-
318
- /**
319
- * @param string $sSecret
320
- * @return bool
321
- */
322
- protected function isSecretValid( $sSecret ) {
323
- return parent::isSecretValid( $sSecret ) && ( strlen( $sSecret ) == 16 );
324
- }
325
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_intentprovider_yubikey.php DELETED
@@ -1,248 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Services\Services;
4
-
5
- /**
6
- * @deprecated 8.6.0
7
- */
8
- class ICWP_WPSF_Processor_LoginProtect_Yubikey extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
9
-
10
- const OTP_LENGTH = 12;
11
- /**
12
- * @const string
13
- */
14
- const URL_YUBIKEY_VERIFY = 'https://api.yubico.com/wsapi/2.0/verify';
15
-
16
- /**
17
- * This MUST only ever be hooked into when the User is looking at their OWN profile,
18
- * so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
19
- * @param int $nSavingUserId
20
- */
21
- public function handleUserProfileSubmit( $nSavingUserId ) {
22
-
23
- // If it's your own account, you CANT do anything without your OTP (except turn off via email).
24
- $sOtp = $this->fetchCodeFromRequest();
25
-
26
- // At this stage, if the OTP was empty, then we have no further processing to do.
27
- if ( empty( $sOtp ) ) {
28
- return;
29
- }
30
-
31
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
32
- $oFO = $this->getMod();
33
-
34
- if ( !$this->sendYubiOtpRequest( $sOtp ) ) {
35
- $oFO->setFlashAdminNotice(
36
- __( 'One Time Password (OTP) was not valid.', 'wp-simple-firewall' ).' '.__( 'Please try again.', 'wp-simple-firewall' ),
37
- true
38
- );
39
- return;
40
- }
41
-
42
- /*
43
- * How we proceed depends on :
44
- * 1) Is the OTP for a registered ID - if so, remove it; If not, add it;
45
- * 2) Is this a premium Shield installation - if so, multiple yubikeys are permitted
46
- */
47
-
48
- $oSavingUser = Services::WpUsers()->getUserById( $nSavingUserId );
49
- $sYubiId = $this->getYubiIdFromOtp( $sOtp );
50
-
51
- $bError = false;
52
- if ( $this->hasYubiIdInProfile( $oSavingUser, $sYubiId ) ) {
53
- $this->removeYubiIdFromProfile( $oSavingUser, $sYubiId );
54
- $sMsg = sprintf(
55
- __( '%s was removed from your profile.', 'wp-simple-firewall' ),
56
- __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' "%s"', $sYubiId )
57
- );
58
- }
59
- elseif ( count( $this->getYubiIds( $oSavingUser ) ) == 0 || $oFO->isPremium() ) {
60
- $this->addYubiIdToProfile( $oSavingUser, $sYubiId );
61
- $sMsg = sprintf(
62
- __( '%s was added to your profile.', 'wp-simple-firewall' ),
63
- __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $sYubiId )
64
- );
65
- }
66
- else {
67
- $bError = true;
68
- $sMsg = __( 'No changes were made to your Yubikey configuration', 'wp-simple-firewall' );
69
- }
70
-
71
- $this->setProfileValidated( $oSavingUser, $this->hasValidSecret( $oSavingUser ) );
72
- $oFO->setFlashAdminNotice( $sMsg, $bError );
73
- }
74
-
75
- /**
76
- * @param \WP_User $oUser
77
- * @return array
78
- */
79
- protected function getYubiIds( \WP_User $oUser ) {
80
- return explode( ',', parent::getSecret( $oUser ) );
81
- }
82
-
83
- /**
84
- * @param string $sOTP
85
- * @return string
86
- */
87
- protected function getYubiIdFromOtp( $sOTP ) {
88
- return substr( $sOTP, 0, $this->getYubiOtpLength() );
89
- }
90
-
91
- /**
92
- * @param WP_User $oUser
93
- * @param string $sKey
94
- * @return bool
95
- */
96
- protected function hasYubiIdInProfile( \WP_User $oUser, $sKey ) {
97
- return in_array( $sKey, $this->getYubiIds( $oUser ) );
98
- }
99
-
100
- /**
101
- * @param \WP_User $oUser
102
- * @param string $sOneTimePassword
103
- * @return bool
104
- */
105
- protected function processOtp( $oUser, $sOneTimePassword ) {
106
- $bSuccess = false;
107
-
108
- $aYubiKeys = $this->getYubiIds( $oUser );
109
-
110
- // Only process the 1st secret if premium
111
- if ( !$this->getCon()->isPremiumActive() ) {
112
- $aYubiKeys = array_slice( $aYubiKeys, 0, 1 );
113
- }
114
-
115
- foreach ( $aYubiKeys as $sKey ) {
116
- $bSuccess = strpos( $sOneTimePassword, $sKey ) === 0
117
- && $this->sendYubiOtpRequest( $sOneTimePassword );
118
- if ( $bSuccess ) {
119
- break;
120
- }
121
- }
122
-
123
- return $bSuccess;
124
- }
125
-
126
- /**
127
- * @param string $sOTP
128
- * @return bool
129
- */
130
- private function sendYubiOtpRequest( $sOTP ) {
131
- $sOTP = trim( $sOTP );
132
- $bSuccess = false;
133
-
134
- if ( preg_match( '#^[a-z]{44}$#', $sOTP ) ) {
135
- $aParts = [
136
- 'otp' => $sOTP,
137
- 'nonce' => md5( uniqid( rand() ) ),
138
- 'id' => $this->getOptions()->getOpt( 'yubikey_app_id' )
139
- ];
140
-
141
- $sReqUrl = add_query_arg( $aParts, self::URL_YUBIKEY_VERIFY );
142
- $sYubiResponse = Services::HttpRequest()->getContent( $sReqUrl );
143
-
144
- unset( $aParts[ 'id' ] );
145
- $aParts[ 'status' ] = 'OK';
146
-
147
- $bSuccess = true;
148
- foreach ( $aParts as $sKey => $mVal ) {
149
- $bSuccess = $bSuccess && preg_match( sprintf( '#%s=%s#', $sKey, $mVal ), $sYubiResponse );
150
- }
151
- }
152
-
153
- return $bSuccess;
154
- }
155
-
156
- /**
157
- * @param \WP_User $oUser
158
- * @param string $sNewKey
159
- * @return $this
160
- */
161
- protected function addYubiIdToProfile( $oUser, $sNewKey ) {
162
- $aKeys = $this->getYubiIds( $oUser );
163
- $aKeys[] = $sNewKey;
164
- return $this->storeYubiIdInProfile( $oUser, $aKeys );
165
- }
166
-
167
- /**
168
- * @param \WP_User $oUser
169
- * @param string $sKey
170
- * @return $this
171
- */
172
- protected function removeYubiIdFromProfile( $oUser, $sKey ) {
173
- $aKeys = Services::DataManipulation()->removeFromArrayByValue( $this->getYubiIds( $oUser ), $sKey );
174
- return $this->storeYubiIdInProfile( $oUser, $aKeys );
175
- }
176
-
177
- /**
178
- * @param \WP_User $oUser
179
- * @param array $aKeys
180
- * @return $this
181
- */
182
- private function storeYubiIdInProfile( $oUser, $aKeys ) {
183
- parent::setSecret( $oUser, implode( ',', array_unique( array_filter( $aKeys ) ) ) );
184
- return $this;
185
- }
186
-
187
- /**
188
- * @param \WP_User $oUser
189
- * @param bool $bIsSuccess
190
- */
191
- protected function auditLogin( $oUser, $bIsSuccess ) {
192
- $this->getCon()->fireEvent(
193
- $bIsSuccess ? 'yubikey_verified' : 'yubikey_fail',
194
- [
195
- 'audit' => [
196
- 'user_login' => $oUser->user_login,
197
- 'method' => 'Yubikey',
198
- ]
199
- ]
200
- );
201
- }
202
-
203
- /**
204
- * @param array $aFields
205
- * @return array
206
- */
207
- public function addLoginIntentField( $aFields ) {
208
- if ( $this->getCurrentUserHasValidatedProfile() ) {
209
- $aFields[] = [
210
- 'name' => $this->getLoginFormParameter(),
211
- 'type' => 'text',
212
- 'placeholder' => __( 'Use your Yubikey to generate a new code.', 'wp-simple-firewall' ),
213
- 'value' => '',
214
- 'text' => __( 'Yubikey OTP', 'wp-simple-firewall' ),
215
- 'help_link' => 'https://shsec.io/4i'
216
- ];
217
- }
218
- return $aFields;
219
- }
220
-
221
- /**
222
- * @return string
223
- */
224
- protected function getStub() {
225
- return ICWP_WPSF_Processor_LoginProtect_Track::Factor_Yubikey;
226
- }
227
-
228
- /**
229
- * @param string $sSecret
230
- * @return bool
231
- */
232
- protected function isSecretValid( $sSecret ) {
233
- $bValid = parent::isSecretValid( $sSecret );
234
- if ( $bValid ) {
235
- foreach ( explode( ',', $sSecret ) as $sId ) {
236
- $bValid = $bValid && preg_match( sprintf( '#^[a-z]{%s}$#', $this->getYubiOtpLength() ), $sId );
237
- }
238
- }
239
- return $bValid;
240
- }
241
-
242
- /**
243
- * @return int
244
- */
245
- protected function getYubiOtpLength() {
246
- return self::OTP_LENGTH;
247
- }
248
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/loginprotect_wplogin.php CHANGED
@@ -29,10 +29,12 @@ class ICWP_WPSF_Processor_LoginProtect_WpLogin extends Modules\BaseShield\Shield
29
  add_action( 'login_init', [ $this, 'aLoginFormAction' ], 0 );
30
 
31
  // ensure that wp-login.php is never used in site urls or redirects
32
- add_filter( 'site_url', [ $this, 'fCheckForLoginPhp' ], 20, 2 );
33
- add_filter( 'network_site_url', [ $this, 'fCheckForLoginPhp' ], 20, 2 );
34
- add_filter( 'wp_redirect', [ $this, 'fCheckForLoginPhp' ], 20, 2 );
35
- add_filter( 'wp_redirect', [ $this, 'fProtectUnauthorizedLoginRedirect' ], 50, 2 );
 
 
36
  add_filter( 'register_url', [ $this, 'blockRegisterUrlRedirect' ], 20, 1 );
37
 
38
  add_filter( 'et_anticipate_exceptions', [ $this, 'fAddToEtMaintenanceExceptions' ] );
@@ -143,10 +145,9 @@ class ICWP_WPSF_Processor_LoginProtect_WpLogin extends Modules\BaseShield\Shield
143
 
144
  /**
145
  * @param string $sLocation
146
- * @param string $mStatus
147
  * @return string
148
  */
149
- public function fCheckForLoginPhp( $sLocation, $mStatus ) {
150
 
151
  $sRedirectPath = parse_url( $sLocation, PHP_URL_PATH );
152
  if ( strpos( $sRedirectPath, 'wp-login.php' ) !== false ) {
@@ -164,10 +165,9 @@ class ICWP_WPSF_Processor_LoginProtect_WpLogin extends Modules\BaseShield\Shield
164
 
165
  /**
166
  * @param string $sLocation
167
- * @param string $mStatus
168
  * @return string
169
  */
170
- public function fProtectUnauthorizedLoginRedirect( $sLocation, $mStatus ) {
171
 
172
  if ( !Services::WpGeneral()->isLoginUrl() ) {
173
  $sRedirectPath = trim( parse_url( $sLocation, PHP_URL_PATH ), '/' );
29
  add_action( 'login_init', [ $this, 'aLoginFormAction' ], 0 );
30
 
31
  // ensure that wp-login.php is never used in site urls or redirects
32
+ add_filter( 'site_url', [ $this, 'fCheckForLoginPhp' ], 20, 1 );
33
+ add_filter( 'network_site_url', [ $this, 'fCheckForLoginPhp' ], 20, 1 );
34
+ add_filter( 'wp_redirect', [ $this, 'fCheckForLoginPhp' ], 20, 1 );
35
+ if ( !Services::WpUsers()->isUserLoggedIn() ) {
36
+ add_filter( 'wp_redirect', [ $this, 'fProtectUnauthorizedLoginRedirect' ], 50, 1 );
37
+ }
38
  add_filter( 'register_url', [ $this, 'blockRegisterUrlRedirect' ], 20, 1 );
39
 
40
  add_filter( 'et_anticipate_exceptions', [ $this, 'fAddToEtMaintenanceExceptions' ] );
145
 
146
  /**
147
  * @param string $sLocation
 
148
  * @return string
149
  */
150
+ public function fCheckForLoginPhp( $sLocation ) {
151
 
152
  $sRedirectPath = parse_url( $sLocation, PHP_URL_PATH );
153
  if ( strpos( $sRedirectPath, 'wp-login.php' ) !== false ) {
165
 
166
  /**
167
  * @param string $sLocation
 
168
  * @return string
169
  */
170
+ public function fProtectUnauthorizedLoginRedirect( $sLocation ) {
171
 
172
  if ( !Services::WpGeneral()->isLoginUrl() ) {
173
  $sRedirectPath = trim( parse_url( $sLocation, PHP_URL_PATH ), '/' );
src/processors/plugin.php CHANGED
@@ -173,18 +173,6 @@ class ICWP_WPSF_Processor_Plugin extends Modules\BaseShield\ShieldProcessor {
173
  $this->getCon()->fireEvent( 'test_cron_run' );
174
  }
175
 
176
- /**
177
- * @deprecated 8.5.7
178
- */
179
- protected function maintainPluginLoadPosition() {
180
- $oWpPlugins = Services::WpPlugins();
181
- $sBaseFile = $this->getCon()->getPluginBaseFile();
182
- $nLoadPosition = $oWpPlugins->getActivePluginLoadPosition( $sBaseFile );
183
- if ( $nLoadPosition !== 0 && $nLoadPosition > 0 ) {
184
- $oWpPlugins->setActivePluginLoadFirst( $sBaseFile );
185
- }
186
- }
187
-
188
  /**
189
  * Lets you remove certain plugin conflicts that might interfere with this plugin
190
  */
173
  $this->getCon()->fireEvent( 'test_cron_run' );
174
  }
175
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  /**
177
  * Lets you remove certain plugin conflicts that might interfere with this plugin
178
  */
src/processors/plugin_crondaily.php DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
- use FernleafSystems\Wordpress\Services\Services;
5
-
6
- class ICWP_WPSF_Processor_Plugin_CronDaily extends Modules\BaseShield\ShieldProcessor {
7
-
8
- use \FernleafSystems\Wordpress\Plugin\Shield\Crons\StandardCron;
9
-
10
- /**
11
- */
12
- public function run() {
13
- $this->setupCron();
14
- }
15
-
16
- /**
17
- * @return string
18
- * @throws \Exception
19
- */
20
- protected function getCronName() {
21
- return $this->getCon()->prefix( 'daily' );
22
- }
23
-
24
- /**
25
- * Use the included action to hook into the plugin's daily cron
26
- */
27
- public function runCron() {
28
- do_action( $this->getCon()->prefix( 'daily_cron' ) );
29
- }
30
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/plugin_cronhourly.php DELETED
@@ -1,33 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
-
5
- class ICWP_WPSF_Processor_Plugin_CronHourly extends Modules\BaseShield\ShieldProcessor {
6
-
7
- use \FernleafSystems\Wordpress\Plugin\Shield\Crons\StandardCron;
8
-
9
- public function run() {
10
- $this->setupCron();
11
- }
12
-
13
- /**
14
- * @return string
15
- */
16
- protected function getCronFrequency() {
17
- return 'hourly';
18
- }
19
-
20
- /**
21
- * @return string
22
- */
23
- protected function getCronName() {
24
- return $this->getCon()->prefix( 'hourly' );
25
- }
26
-
27
- /**
28
- * Use the included action to hook into the plugin's daily cron
29
- */
30
- public function runCron() {
31
- do_action( $this->getCon()->prefix( 'hourly_cron' ) );
32
- }
33
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/processors/traffic.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
 
4
 
5
  /**
6
  * Class ICWP_WPSF_Processor_Traffic
@@ -8,35 +9,15 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules;
8
  class ICWP_WPSF_Processor_Traffic extends Modules\BaseShield\ShieldProcessor {
9
 
10
  public function run() {
11
- $this->getProcessorLogger()->execute();
12
- }
13
-
14
- /**
15
- * Not fully tested- aim for 8.1 release
16
- */
17
- public function onWpInit() {
18
  /** @var Modules\Traffic\Options $oOpts */
19
  $oOpts = $this->getOptions();
20
- if ( false && $oOpts->isTrafficLimitEnabled() ) {
21
- ( new Modules\Traffic\Limiter\Limiter() )
 
 
 
22
  ->setMod( $this->getMod() )
23
  ->run();
24
  }
25
  }
26
-
27
- /**
28
- * @return \ICWP_WPSF_Processor_TrafficLogger|mixed
29
- */
30
- public function getProcessorLogger() {
31
- return $this->getSubPro( 'logger' );
32
- }
33
-
34
- /**
35
- * @return array
36
- */
37
- protected function getSubProMap() {
38
- return [
39
- 'logger' => 'ICWP_WPSF_Processor_TrafficLogger',
40
- ];
41
- }
42
  }
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
4
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib;
5
 
6
  /**
7
  * Class ICWP_WPSF_Processor_Traffic
9
  class ICWP_WPSF_Processor_Traffic extends Modules\BaseShield\ShieldProcessor {
10
 
11
  public function run() {
 
 
 
 
 
 
 
12
  /** @var Modules\Traffic\Options $oOpts */
13
  $oOpts = $this->getOptions();
14
+ if ( $oOpts->isTrafficLoggerEnabled() ) {
15
+ ( new Lib\Logger() )
16
+ ->setMod( $this->getMod() )
17
+ ->run();
18
+ ( new Lib\Limit\Limiter() )
19
  ->setMod( $this->getMod() )
20
  ->run();
21
  }
22
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
src/processors/traffic_logger.php CHANGED
@@ -1,16 +1,14 @@
1
  <?php
2
 
3
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield\ShieldProcessor;
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Options;
6
- use FernleafSystems\Wordpress\Services\Services;
7
 
 
 
 
 
8
  class ICWP_WPSF_Processor_TrafficLogger extends ShieldProcessor {
9
 
10
  public function onModuleShutdown() {
11
- if ( $this->getIfLogRequest() ) {
12
- $this->logTraffic();
13
- }
14
  parent::onModuleShutdown();
15
  }
16
 
@@ -18,104 +16,30 @@ class ICWP_WPSF_Processor_TrafficLogger extends ShieldProcessor {
18
  * @return bool
19
  */
20
  protected function getIfLogRequest() {
21
- /** @var ICWP_WPSF_FeatureHandler_Traffic $oMod */
22
- $oMod = $this->getMod();
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- $oWp = Services::WpGeneral();
26
- $bLoggedIn = Services::WpUsers()->isUserLoggedIn();
27
- return parent::getIfLogRequest()
28
- && !$this->getCon()->isPluginDeleting()
29
- && ( $oOpts->getMaxEntries() > 0 )
30
- && ( !$this->isCustomExcluded() )
31
- && ( $oMod->isIncluded_Simple() || count( Services::Request()->getRawRequestParams( false ) ) > 0 )
32
- && ( $oMod->isIncluded_LoggedInUser() || !$bLoggedIn )
33
- && ( $oMod->isIncluded_Ajax() || !$oWp->isAjax() )
34
- && ( $oMod->isIncluded_Cron() || !$oWp->isCron() )
35
- && (
36
- $bLoggedIn || // only run these service IP checks if not logged in.
37
- (
38
- ( $oMod->isIncluded_Search() || !$this->isServiceIp_Search() )
39
- && ( $oMod->isIncluded_Uptime() || !$this->isServiceIp_Uptime() )
40
- )
41
- );
42
  }
43
 
44
  /**
45
  * @return bool
46
  */
47
  protected function isCustomExcluded() {
48
- /** @var Options $oOpts */
49
- $oOpts = $this->getOptions();
50
- /** @var \ICWP_WPSF_FeatureHandler_Traffic $oMod */
51
- $oMod = $this->getMod();
52
- $oReq = Services::Request();
53
-
54
- $sAgent = $oReq->getUserAgent();
55
- $sPath = $oReq->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) );
56
-
57
- $bExcluded = false;
58
- foreach ( $oMod->getCustomExclusions() as $sExcl ) {
59
- if ( stripos( $sAgent, $sExcl ) !== false || stripos( $sPath, $sExcl ) !== false ) {
60
- $bExcluded = true;
61
- }
62
- }
63
- return $bExcluded;
64
  }
65
 
66
  /**
67
  * @return bool
68
  */
69
  protected function isServiceIp_Search() {
70
- $oSP = Services::ServiceProviders();
71
-
72
- $sIp = Services::IP()->getRequestIp();
73
- $sAgent = (string)Services::Request()->getUserAgent();
74
- return $oSP->isIp_GoogleBot( $sIp, $sAgent )
75
- || $oSP->isIp_BingBot( $sIp, $sAgent )
76
- || $oSP->isIp_DuckDuckGoBot( $sIp, $sAgent )
77
- || $oSP->isIp_YandexBot( $sIp, $sAgent )
78
- || $oSP->isIp_BaiduBot( $sIp, $sAgent )
79
- || $oSP->isIp_YahooBot( $sIp, $sAgent )
80
- || $oSP->isIp_AppleBot( $sIp, $sAgent );
81
  }
82
 
83
  /**
84
  * @return bool
85
  */
86
  protected function isServiceIp_Uptime() {
87
- $oSP = Services::ServiceProviders();
88
- $sIp = Services::IP()->getRequestIp();
89
- $sAgent = (string)Services::Request()->getUserAgent();
90
- return $oSP->isIp_Statuscake( $sIp, $sAgent )
91
- || $oSP->isIp_UptimeRobot( $sIp, $sAgent )
92
- || $oSP->isIp_Pingdom( $sIp, $sAgent )
93
- || $oSP->isIpInCollection( $sIp, $oSP->getIps_NodePing() );
94
  }
95
 
96
  protected function logTraffic() {
97
- /** @var \ICWP_WPSF_FeatureHandler_Traffic $oMod */
98
- $oMod = $this->getMod();
99
- $oReq = Services::Request();
100
- /** @var Traffic\Handler $oDbh */
101
- $oDbh = $oMod->getDbHandler_Traffic();
102
-
103
- // For multisites that are separated by sub-domains we also show the host.
104
- $sLeadingPath = Services::WpGeneral()->isMultisite_SubdomainInstall() ? $oReq->getHost() : '';
105
-
106
- /** @var Traffic\EntryVO $oEntry */
107
- $oEntry = $oDbh->getVo();
108
-
109
- $oEntry->rid = $this->getCon()->getShortRequestId();
110
- $oEntry->uid = Services::WpUsers()->getCurrentWpUserId();
111
- $oEntry->ip = inet_pton( Services::IP()->getRequestIp() );
112
- $oEntry->verb = $oReq->getMethod();
113
- $oEntry->path = $sLeadingPath.$oReq->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) );
114
- $oEntry->code = http_response_code();
115
- $oEntry->ua = $oReq->getUserAgent();
116
- $oEntry->trans = $oMod->getIfIpTransgressed() ? 1 : 0;
117
-
118
- $oDbh->getQueryInserter()
119
- ->insert( $oEntry );
120
  }
121
  }
1
  <?php
2
 
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield\ShieldProcessor;
 
 
4
 
5
+ /**
6
+ * Class ICWP_WPSF_Processor_TrafficLogger
7
+ * @deprecated 8.7.0
8
+ */
9
  class ICWP_WPSF_Processor_TrafficLogger extends ShieldProcessor {
10
 
11
  public function onModuleShutdown() {
 
 
 
12
  parent::onModuleShutdown();
13
  }
14
 
16
  * @return bool
17
  */
18
  protected function getIfLogRequest() {
19
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
  /**
23
  * @return bool
24
  */
25
  protected function isCustomExcluded() {
26
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  /**
30
  * @return bool
31
  */
32
  protected function isServiceIp_Search() {
33
+ return false;
 
 
 
 
 
 
 
 
 
 
34
  }
35
 
36
  /**
37
  * @return bool
38
  */
39
  protected function isServiceIp_Uptime() {
40
+ return false;
 
 
 
 
 
 
41
  }
42
 
43
  protected function logTraffic() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
  }
src/wizards/login_protect.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
 
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor;
4
  use FernleafSystems\Wordpress\Services\Services;
5
 
@@ -185,16 +186,16 @@ class ICWP_WPSF_Wizard_LoginProtect extends ICWP_WPSF_Wizard_BaseWpsf {
185
  * @return string[]
186
  */
187
  private function determineWizardSteps_Mfa() {
188
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
189
- $oFO = $this->getMod();
190
 
191
  $aStepsSlugs = [ 'start' ];
192
 
193
- if ( !$oFO->getIfCanSendEmailVerified() || !$oFO->isEmailAuthenticationActive() ) {
194
  $aStepsSlugs[] = 'authemail';
195
  }
196
 
197
- if ( !$oFO->isEnabledGoogleAuthenticator() ) {
198
  $aStepsSlugs[] = 'authga';
199
  }
200
 
@@ -210,6 +211,8 @@ class ICWP_WPSF_Wizard_LoginProtect extends ICWP_WPSF_Wizard_BaseWpsf {
210
  protected function getRenderData_SlideExtra( $sStep ) {
211
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
212
  $oMod = $this->getMod();
 
 
213
 
214
  $aAdditional = [];
215
 
@@ -248,7 +251,7 @@ class ICWP_WPSF_Wizard_LoginProtect extends ICWP_WPSF_Wizard_BaseWpsf {
248
  case 'multiselect':
249
  $aAdditional = [
250
  'flags' => [
251
- 'has_multiselect' => $oMod->isChainedAuth(),
252
  ]
253
  ];
254
  break;
1
  <?php
2
 
3
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
4
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor;
5
  use FernleafSystems\Wordpress\Services\Services;
6
 
186
  * @return string[]
187
  */
188
  private function determineWizardSteps_Mfa() {
189
+ /** @var LoginGuard\Options $oOpts */
190
+ $oOpts = $this->getOptions();
191
 
192
  $aStepsSlugs = [ 'start' ];
193
 
194
+ if ( !$oOpts->getIfCanSendEmailVerified() || !$oOpts->isEmailAuthenticationActive() ) {
195
  $aStepsSlugs[] = 'authemail';
196
  }
197
 
198
+ if ( !$oOpts->isEnabledGoogleAuthenticator() ) {
199
  $aStepsSlugs[] = 'authga';
200
  }
201
 
211
  protected function getRenderData_SlideExtra( $sStep ) {
212
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
213
  $oMod = $this->getMod();
214
+ /** @var LoginGuard\Options $oOpts */
215
+ $oOpts = $this->getOptions();
216
 
217
  $aAdditional = [];
218
 
251
  case 'multiselect':
252
  $aAdditional = [
253
  'flags' => [
254
+ 'has_multiselect' => $oOpts->isChainedAuth(),
255
  ]
256
  ];
257
  break;
src/wizards/plugin.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
4
  use FernleafSystems\Wordpress\Services\Services;
 
5
 
6
  /**
7
  * Class ICWP_WPSF_Processor_LoginProtect_Wizard
@@ -328,6 +329,8 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
328
  * @return \FernleafSystems\Utilities\Response
329
  */
330
  private function wizardIpDetect() {
 
 
331
  $oIps = Services::IP();
332
  $sIp = Services::Request()->post( 'ip' );
333
 
@@ -343,14 +346,14 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
343
  // $sMessage = 'The IP address supplied was not a valid IP address.';
344
  // }
345
  else {
346
- $sSource = $oIps->determineSourceFromIp( $sIp );
347
  if ( empty( $sSource ) ) {
348
  $sMessage = __( "The address source couldn't be found from this IP.", 'wp-simple-firewall' );
349
  }
350
  else {
351
  $oMod = $this->getCon()
352
  ->getModule_Plugin();
353
- $oMod->setVisitorAddressSource( $sSource );
354
  $oMod->saveModOptions();
355
  $oResponse->setSuccessful( true );
356
  $sMessage = __( 'Success!', 'wp-simple-firewall' ).' '
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
4
  use FernleafSystems\Wordpress\Services\Services;
5
+ use FernleafSystems\Wordpress\Services\Utilities\Net\FindSourceFromIp;
6
 
7
  /**
8
  * Class ICWP_WPSF_Processor_LoginProtect_Wizard
329
  * @return \FernleafSystems\Utilities\Response
330
  */
331
  private function wizardIpDetect() {
332
+ /** @var Plugin\Options $oOpts */
333
+ $oOpts = $this->getOptions();
334
  $oIps = Services::IP();
335
  $sIp = Services::Request()->post( 'ip' );
336
 
346
  // $sMessage = 'The IP address supplied was not a valid IP address.';
347
  // }
348
  else {
349
+ $sSource = ( new FindSourceFromIp() )->run( Services::Request()->post( 'ip' ) );
350
  if ( empty( $sSource ) ) {
351
  $sMessage = __( "The address source couldn't be found from this IP.", 'wp-simple-firewall' );
352
  }
353
  else {
354
  $oMod = $this->getCon()
355
  ->getModule_Plugin();
356
+ $oOpts->setVisitorAddressSource( $sSource );
357
  $oMod->saveModOptions();
358
  $oResponse->setSuccessful( true );
359
  $sMessage = __( 'Success!', 'wp-simple-firewall' ).' '
templates/php/admin_bootstrap.php DELETED
@@ -1,6 +0,0 @@
1
- <?php
2
- ?>
3
-
4
- <div id="ContentHolder">
5
- <h6 style="margin: 30px">Loading options ...</h6>
6
- </div>
 
 
 
 
 
 
templates/php/feature-default.php DELETED
@@ -1,29 +0,0 @@
1
- <div id="IcwpCarouselOptions" class="icwp-carousel carousel slide carousel-fade">
2
- <div class="carousel-inner">
3
-
4
- <div class="carousel-item active">
5
- <div class="d-block w-100 content-options">
6
- <?php echo $flags[ 'show_standard_options' ] ? $content[ 'options_form' ] : ''; ?>
7
- <?php echo $flags[ 'show_alt_content' ] ? $content[ 'alt' ] : ''; ?>
8
- </div>
9
- </div>
10
-
11
- <div class="carousel-item carousel-wizards">
12
- <div class="d-block w-100"><?php echo $content[ 'wizard_landing' ]; ?></div>
13
- </div>
14
-
15
- <div class="carousel-item carousel-help">
16
- <div class="d-block w-100"><?php echo $content[ 'help' ]; ?></div>
17
- </div>
18
- </div>
19
- </div>
20
-
21
- <script>
22
- jQuery( document ).ready( function () {
23
- jQuery( '.icwp-carousel' ).carousel( {
24
- interval: false,
25
- keyboard: false
26
- } );
27
- }
28
- );
29
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/index.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
- $sBaseDirName = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
3
-
4
- if ( $flags[ 'wrap_page_content' ] ) : ?>
5
- <div class="wrap">
6
- <div class="bootstrap-wpadmin1 icwp-options-page <?php echo $data[ 'mod_slug' ]; ?>">
7
- <h1 style="height: 0; display: none"></h1>
8
- <?php endif; ?>
9
-
10
- <?php if ( $flags[ 'access_restricted' ] ) : ?>
11
- <?php else : ?>
12
- <?php include( $sBaseDirName.'index_body.php' ); ?>
13
- <?php endif; ?>
14
-
15
- <?php if ( $flags[ 'wrap_page_content' ] ) : ?>
16
- </div><!-- / bootstrap-wpadmin -->
17
- </div><!-- / wrap -->
18
- <?php endif; ?>
19
-
20
- <?php include_once( $sBaseDirName.'index_footer.php' ); ?>
21
-
22
- <?php if ( !empty( $aPluginLabels[ 'icon_url_128x128' ] ) ) : ?>
23
- <style>
24
- #TopPluginIcon {
25
- background-image: url( "<?php echo $aPluginLabels[ 'icon_url_128x128' ]; ?>" ) !important;
26
- }
27
- </style>
28
- <?php endif;
29
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/index_body.php DELETED
@@ -1,26 +0,0 @@
1
- <div class="row no-gutters" id="ModulePageTopRow">
2
-
3
- <div class="col-1 modules smoothwidth" id="ColumnModules">
4
- <div id="TopPluginIcon" class="img-fluid">&nbsp;</div>
5
- <div class="nav flex-column">
6
- <?php foreach ( $aSummaryData as $nKey => $aSummary ) : ?>
7
- <a class="nav-link module <?php echo $aSummary[ 'active' ] ? 'active' : ''; ?>
8
- <?php echo $aSummary[ 'enabled' ] ? 'enabled' : 'notenabled'; ?>"
9
- id="tab-<?php echo $aSummary[ 'slug' ]; ?>"
10
- data-toggle="tooltip" data-placement="right" data-trigger="hover"
11
- title="<?php echo $aSummary[ 'tooltip' ] ?>"
12
- href="<?php echo $aSummary[ 'href' ]; ?>" role="tab">
13
- <div class="module-icon" id="module-<?php echo $aSummary[ 'slug' ] ?>">
14
- </div>
15
- </a>
16
- <?php endforeach; ?>
17
- </div>
18
- </div>
19
-
20
- <div class="col" id="ColumnOptions">
21
- <?php include( $sBaseDirName.'feature-default.php' ); ?>
22
- </div>
23
- </div>
24
- <script>
25
- jQuery( 'a.nav-link.module' ).tooltip();
26
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/index_footer.php DELETED
@@ -1,26 +0,0 @@
1
- <?php if ( $flags[ 'show_ads' ] ) : ?>
2
- <div id="FooterWizardBanner" class="container-fluid">
3
- <div id="WizardBanner" class="row">
4
- <div class="col-lg-6 offset-lg-1 col-7">
5
- <h6 class="text-left">Exclusive Security Extras when you go Pro:</h6>
6
- <p>Vulnerability Scanner; Plugins Hack Guard; More Frequent Scans; Email Support +much more.</p>
7
- </div>
8
- <div class="col-lg-4 col-5">
9
- <a href="<?php echo $hrefs['goprofooter'];?>" target="_blank" class="btn btn-success">
10
- Get Even More Protection With Pro &rarr;</a>
11
- </div>
12
- </div>
13
- </div>
14
- <?php endif; ?>
15
- <script type="text/javascript">
16
- jQuery( document ).ready( function () {
17
- jQuery( 'a.btn-icwp-wizard' ).tooltip( {
18
- placement: 'bottom',
19
- trigger: 'hover focus'
20
- } );
21
- jQuery( 'a.module .dashicons' ).tooltip( {
22
- placement: 'right',
23
- trigger: 'hover focus'
24
- } );
25
- } );
26
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/index_header.php DELETED
@@ -1,3 +0,0 @@
1
- <?php
2
- $sBaseDirName = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
3
- include_once( $sBaseDirName.'widgets/icwp_widgets.php' );
 
 
 
templates/php/snippets/module-actions-template.php DELETED
@@ -1,30 +0,0 @@
1
- <div class="row no-gutters">
2
- <div class="col">
3
- <div class="module-headline">
4
- <h4>
5
- <?php echo $sPageTitle; ?>
6
-
7
- <div class="btn-group float-right icwp-top-buttons" role="group">
8
-
9
- <a href="javascript:void(0)" class="btn btn-outline-success icwp-carousel-0">
10
- <?php echo $strings[ 'btn_options' ]; ?></a>
11
-
12
- <?php if ( $flags[ 'has_wizard' ] ) : ?>
13
- <a class="btn btn-outline-dark btn-icwp-wizard icwp-carousel-1"
14
- title="Launch Guided Walk-Through Wizards" href="javascript:void(0)">
15
- <?php echo $strings[ 'btn_wizards' ]; ?></a>
16
- <?php else : ?>
17
- <a class="btn btn-outline-dark btn-icwp-wizard disabled"
18
- href="javascript:{}"
19
- title="No Wizards for this module."
20
- <?php echo $strings[ 'btn_wizards' ]; ?></a>
21
- <?php endif; ?>
22
-
23
- <a href="javascript:void(0)" class="btn btn-outline-info icwp-carousel-2">
24
- <?php echo $strings[ 'btn_help' ]; ?></a>
25
- </div>
26
- <small class="module-tagline"><?php echo $sTagline; ?></small>
27
- </h4>
28
- </div>
29
- </div>
30
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/snippets/options_form.php DELETED
@@ -1,293 +0,0 @@
1
- <form action="<?php echo $form_action; ?>" method="post" class="icwpOptionsForm" novalidate="novalidate"
2
- autocomplete="off">
3
- <input type="hidden" id="_wpnonce" name="_wpnonce" value="<?php echo $data[ 'form_nonce' ] ?>">
4
- <input type="hidden" name="mod_slug" value="<?php echo $data[ 'mod_slug' ]; ?>" />
5
-
6
- <?php foreach ( $ajax[ 'mod_options' ] as $sAjKey => $sAjVal ) : ?>
7
- <input type="hidden" name="<?php echo $sAjKey; ?>" value="<?php echo $sAjVal; ?>" />
8
- <?php endforeach; ?>
9
-
10
- <div style="margin-bottom: -1px">
11
- <div class="row no-gutters">
12
- <div class="col">
13
- <div class="module-headline">
14
- <h4>
15
- <span class="headline-title"><?php echo $sPageTitle; ?></span>
16
- <div class="float-right">
17
- <button type="submit" class="btn btn-primary icwp-form-button"
18
- name="submit" style="margin-right: 12px">
19
- <?php echo $strings[ 'btn_save' ]; ?>
20
- </button>
21
-
22
- <div class="btn-group" role="group" aria-label="Basic example">
23
-
24
- <a aria-disabled="true" class="btn btn-success disabled icwp-carousel-0"
25
- href="javascript:void(0)">
26
- <?php echo $strings[ 'btn_options' ]; ?></a>
27
-
28
- <?php if ( $flags[ 'has_wizard' ] ) : ?>
29
- <a class="btn btn-outline-dark btn-icwp-wizard icwp-carousel-1"
30
- title="Launch Guided Walk-Through Wizards" href="javascript:void(0)">
31
- <?php echo $strings[ 'btn_wizards' ]; ?></a>
32
- <?php else : ?>
33
- <a class="btn btn-outline-dark btn-icwp-wizard disabled"
34
- href="javascript:{}"
35
- title="No Wizards for this module."
36
- <?php echo $strings[ 'btn_wizards' ]; ?></a>
37
- <?php endif; ?>
38
-
39
- <a class="btn btn-outline-info icwp-carousel-2" href="javascript:void(0)">
40
- <?php echo $strings[ 'btn_help' ]; ?></a>
41
- </div>
42
- </div>
43
- <small class="module-tagline"><?php echo $sTagline; ?></small>
44
- </h4>
45
- </div>
46
- </div>
47
- </div>
48
-
49
- <div class="row no-gutters">
50
- <div class="col-2 smoothwidth">
51
-
52
- <ul id="ModuleOptionsNav" class="nav flex-column"
53
- role="tablist" aria-orientation="vertical">
54
- <?php foreach ( $data[ 'all_options' ] as $aOptSection ) : ?>
55
- <li class="nav-item">
56
- <a class="nav-link <?php echo $aOptSection[ 'primary' ] ? 'active' : '' ?>"
57
- id="pills-tab-<?php echo $aOptSection[ 'slug' ]; ?>"
58
- data-toggle="pill" href="#pills-<?php echo $aOptSection[ 'slug' ]; ?>"
59
- role="tab" aria-controls="pills-<?php echo $aOptSection[ 'slug' ]; ?>"
60
- <?php echo $aOptSection[ 'primary' ] ? 'aria-selected="true"' : '' ?>
61
- ><?php echo $aOptSection[ 'title_short' ]; ?></a>
62
- </li>
63
- <?php endforeach; ?>
64
- </ul>
65
- </div>
66
- <div class="col" style="margin: 0 4px 5px 0;">
67
- <div class="tab-content" id="pills-tabContent">
68
- <?php foreach ( $data[ 'all_options' ] as $aOptSection ) : ?>
69
- <div class="tab-pane <?php echo $aOptSection[ 'primary' ] ? 'active' : '' ?>"
70
- id="pills-<?php echo $aOptSection[ 'slug' ]; ?>"
71
- role="tabpanel" aria-labelledby="pills-tab-<?php echo $aOptSection[ 'slug' ]; ?>">
72
-
73
- <div class="option_section_row <?php echo $aOptSection[ 'primary' ] ? 'primary_section' : 'non_primary_section'; ?>"
74
- id="row-<?php echo $aOptSection[ 'slug' ]; ?>">
75
- <div class="options-body">
76
- <legend><?php echo $aOptSection[ 'title' ]; ?></legend>
77
-
78
- <div class="row_section_summary row">
79
- <div class="col-8">
80
- <?php if ( !empty( $aOptSection[ 'summary' ] ) ) : ?>
81
- <?php foreach ( $aOptSection[ 'summary' ] as $sItem ) : ?>
82
- <p class="noselect"><?php echo $sItem; ?></p>
83
- <?php endforeach; ?>
84
- <?php endif; ?>
85
- </div>
86
-
87
- <div class="col-4">
88
- <?php if ( !empty( $aOptSection[ 'help_video' ] ) ) : ?>
89
- <button class="btn btn-lg btn-outline-info section_help_video" type="button"
90
- data-toggle="collapse"
91
- data-target="#sectionVideo<?php echo $aOptSection[ 'help_video' ][ 'id' ]; ?>"
92
- aria-expanded="false"
93
- aria-controls="sectionVideo<?php echo $aOptSection[ 'help_video' ][ 'id' ]; ?>">
94
- <span class="dashicons dashicons-controls-play"></span> Watch The Video</button>
95
- <?php endif; ?>
96
- </div>
97
-
98
- <?php if ( !empty( $aOptSection[ 'help_video' ] ) ) : ?>
99
- <div class="w-100"></div>
100
- <div class="col">
101
- <div class="collapse section_video"
102
- id="sectionVideo<?php echo $aOptSection[ 'help_video' ][ 'id' ]; ?>">
103
- <div class="embed-responsive embed-responsive-16by9">
104
- <iframe src="<?php echo $aOptSection[ 'help_video' ][ 'embed_url' ]; ?>"
105
- width="640" height="360" class="embed-responsive-item"
106
- allowfullscreen></iframe>
107
- </div>
108
- </div>
109
- </div>
110
- <?php endif; ?>
111
- </div>
112
-
113
- <?php if ( !empty( $aOptSection[ 'warnings' ] ) ) : ?>
114
- <div class="row">
115
- <div class="col">
116
- <?php foreach ( $aOptSection[ 'warnings' ] as $sWarning ) : ?>
117
- <div class="alert alert-warning text-center"><?php echo $sWarning; ?></div>
118
- <?php endforeach; ?>
119
- </div>
120
- </div>
121
- <?php endif; ?>
122
-
123
- <?php if ( !empty( $aOptSection[ 'notices' ] ) ) : ?>
124
- <div class="row">
125
- <div class="col">
126
- <?php foreach ( $aOptSection[ 'notices' ] as $sNotices ) : ?>
127
- <div class="alert alert-info text-center"><?php echo $sNotices; ?></div>
128
- <?php endforeach; ?>
129
- </div>
130
- </div>
131
- <?php endif; ?>
132
-
133
- <?php foreach ( $aOptSection[ 'options' ] as $nKeyRow => $aOption ) :
134
- $sOptKey = $aOption[ 'key' ];
135
- $mOptValue = $aOption[ 'value' ];
136
- $sOptType = $aOption[ 'type' ];
137
- $bEnabled = $aOption[ 'enabled' ];
138
- $sDisabledText = $bEnabled ? '' : 'disabled="Disabled"';
139
- ?>
140
- <div class="form-group row row_number_<?php echo $nKeyRow; ?>">
141
-
142
- <label class="form-label col-3 col-form-label" for="Opt-<?php echo $sOptKey; ?>">
143
- <div class="form-label-inner text-right">
144
- <div class="optname"><?php echo $aOption[ 'name' ]; ?></div>
145
- <?php if ( !empty( $aOption[ 'link_info' ] ) ) : ?>
146
- <span class="optlinks">[
147
- <a href="<?php echo $aOption[ 'link_info' ]; ?>"
148
- target="_blank"><?php echo $strings[ 'more_info' ]; ?></a>
149
- <?php if ( !empty( $aOption[ 'link_blog' ] ) ) : ?>
150
- | <a href="<?php echo $aOption[ 'link_blog' ]; ?>"
151
- target="_blank"><?php echo $strings[ 'blog' ]; ?></a>
152
- <?php endif; ?>
153
- ]</span>
154
- <?php endif; ?>
155
- </div>
156
- </label>
157
-
158
- <div class="col-8 option_container
159
- <?php echo $bEnabled ? 'enabled' : 'disabled overlay_container' ?>">
160
-
161
- <?php if ( !$bEnabled ) : ?>
162
- <div class="option_overlay">
163
- <div class="overlay_message">
164
- <a href="<?php echo $hrefs[ 'go_pro' ]; ?>" target="_blank">
165
- Sorry, this is a premium-only feature</a>
166
- </div>
167
- </div>
168
- <?php endif; ?>
169
-
170
- <div class="option_section <?php echo ( $mOptValue == 'Y' ) ? 'selected_item' : ''; ?>"
171
- id="option_section_<?php echo $sOptKey; ?>">
172
-
173
- <label id="Label-<?php echo $sOptKey ?>" class="for<?php echo $sOptType; ?>"
174
- for="Opt-<?php echo $sOptKey; ?>">
175
-
176
- <?php if ( $sOptType == 'checkbox' ) : ?>
177
- <span class="icwp-switch">
178
- <input type="checkbox"
179
- name="<?php echo $sOptKey; ?>" id="Opt-<?php echo $sOptKey; ?>"
180
- value="Y" <?php echo ( $mOptValue == 'Y' ) ? 'checked="checked"' : ''; ?>
181
- aria-labelledby="Label-<?php echo $sOptKey ?>"
182
- <?php echo $sDisabledText; ?> />
183
- <span class="icwp-slider round"></span>
184
- </span>
185
- <span class="summary"><?php echo $aOption[ 'summary' ]; ?></span>
186
-
187
- <?php elseif ( $sOptType == 'text' ) : ?>
188
-
189
- <p><?php echo $aOption[ 'summary' ]; ?></p>
190
- <textarea name="<?php echo $sOptKey; ?>"
191
- id="Opt-<?php echo $sOptKey; ?>"
192
- placeholder="<?php echo $mOptValue; ?>"
193
- rows="<?php echo $aOption[ 'rows' ]; ?>"
194
- <?php echo $sDisabledText; ?>
195
- ><?php echo $mOptValue; ?></textarea>
196
-
197
- <?php elseif ( $sOptType == 'noneditable_text' ) : ?>
198
-
199
- <p><?php echo $aOption[ 'summary' ]; ?></p>
200
- <input type="text" value="<?php echo $mOptValue; ?>" readonly />
201
-
202
- <?php elseif ( $sOptType == 'password' ) : ?>
203
-
204
- <p><?php echo $aOption[ 'summary' ]; ?></p>
205
- <input type="password" name="<?php echo $sOptKey; ?>" class="col form-control"
206
- id="Opt-<?php echo $sOptKey; ?>" value="<?php echo $mOptValue; ?>"
207
- placeholder="<?php echo $strings[ 'supply_password' ]; ?>"
208
- style="margin-bottom: 5px"
209
- <?php echo $sDisabledText; ?> />
210
-
211
- <input type="password" name="<?php echo $sOptKey; ?>_confirm"
212
- id="Opt-<?php echo $sOptKey; ?>_confirm" class="col form-control"
213
- placeholder="<?php echo $strings[ 'confirm_password' ]; ?>"
214
- <?php echo $sDisabledText; ?> />
215
-
216
- <?php elseif ( $sOptType == 'email' ) : ?>
217
-
218
- <p><?php echo $aOption[ 'summary' ]; ?></p>
219
- <input type="email" name="<?php echo $sOptKey; ?>"
220
- id="Opt-<?php echo $sOptKey; ?>"
221
- value="<?php echo $mOptValue; ?>"
222
- placeholder="<?php echo $mOptValue; ?>"
223
- <?php echo $sDisabledText; ?> />
224
-
225
- <?php elseif ( $sOptType == 'select' ) : ?>
226
-
227
- <p><?php echo $aOption[ 'summary' ]; ?></p>
228
- <select name="<?php echo $sOptKey; ?>"
229
- id="Opt-<?php echo $sOptKey; ?>"
230
- <?php echo $sDisabledText; ?> >
231
- <?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
232
- <option value="<?php echo $sOptionValue; ?>"
233
- id="<?php echo $sOptKey; ?>_<?php echo $sOptionValue; ?>"
234
- <?php echo ( $sOptionValue == $mOptValue ) ? 'selected="selected"' : ''; ?>
235
- ><?php echo $sOptionValueName; ?></option>
236
- <?php endforeach; ?>
237
- </select>
238
-
239
- <?php elseif ( $sOptType == 'multiple_select' ) : ?>
240
-
241
- <p><?php echo $aOption[ 'summary' ]; ?></p>
242
- <select name="<?php echo $sOptKey; ?>[]"
243
- id="Opt-<?php echo $sOptKey; ?>"
244
- multiple="multiple" multiple
245
- size="<?php echo count( $aOption[ 'value_options' ] ); ?>"
246
- <?php echo $sDisabledText; ?> >
247
- <?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
248
- <option value="<?php echo $sOptionValue; ?>"
249
- id="<?php echo $sOptKey; ?>_<?php echo $sOptionValue; ?>"
250
- <?php echo in_array( $sOptionValue, $mOptValue ) ? 'selected="selected"' : ''; ?>
251
- ><?php echo $sOptionValueName; ?></option>
252
- <?php endforeach; ?>
253
- </select>
254
-
255
- <?php elseif ( in_array( $sOptType, array( 'comma_separated_lists', 'array' ) ) ) : ?>
256
-
257
- <p><?php echo $aOption[ 'summary' ]; ?></p>
258
- <textarea name="<?php echo $sOptKey; ?>"
259
- id="Opt-<?php echo $sOptKey; ?>"
260
- placeholder="<?php echo $mOptValue; ?>"
261
- rows="<?php echo $aOption[ 'rows' ]; ?>"
262
- <?php echo $sDisabledText; ?>
263
- ><?php echo $mOptValue; ?></textarea>
264
-
265
- <?php elseif ( $sOptType == 'integer' ) : ?>
266
-
267
- <p><?php echo $aOption[ 'summary' ]; ?></p>
268
- <input type="text" name="<?php echo $sOptKey; ?>"
269
- id="Opt-<?php echo $sOptKey; ?>"
270
- value="<?php echo $mOptValue; ?>"
271
- placeholder="<?php echo $mOptValue; ?>"
272
- <?php echo $sDisabledText; ?> />
273
-
274
- <?php else : ?>
275
- ERROR: Should never reach this point.
276
- <?php endif; ?>
277
-
278
- </label>
279
- <p class="help-block"><?php echo $aOption[ 'description' ]; ?></p>
280
- <div style="clear:both"></div>
281
- </div>
282
- </div><!-- controls -->
283
- </div>
284
- <?php endforeach; ?>
285
- </div>
286
- </div>
287
- </div>
288
- <?php endforeach; ?>
289
- </div>
290
- </div>
291
- </div>
292
- </div>
293
- </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/snippets/summary_single.php DELETED
@@ -1,7 +0,0 @@
1
- <?php
2
- if ( !$enabled ) {
3
- echo 'All module features disabled.';
4
- return;
5
- }
6
- ?>
7
- Module: Enabled
 
 
 
 
 
 
 
templates/php/snippets/widget_iframe_side.php DELETED
@@ -1,7 +0,0 @@
1
- <iframe name="<?php echo $sWidgetIframeName; ?>"
2
- src="<?php echo $sWidgetIframeSource; ?>"
3
- width="<?php echo $sWidgetIframeWidth; ?>"
4
- height="<?php echo $sWidgetIframeHeight; ?>"
5
- frameborder="0"
6
- scrolling="no"
7
- style="background-color:<?php echo $sWidgetIframeColor; ?>;" ></iframe>
 
 
 
 
 
 
 
templates/php/subfeature-statistics_data_viewer.php DELETED
@@ -1,18 +0,0 @@
1
- <div class="row">
2
- <div class="span12">
3
-
4
- <dl>
5
- <?php foreach ( $aStatsData as $sStatKey => $nCount ) : ?>
6
- <?php if ( !is_int( $nCount ) ) continue; ?>
7
- <dt>
8
- <?php echo $sStatKey; ?>
9
- </dt>
10
- <dd>
11
- <?php echo $nCount; ?>
12
- </dd>
13
- <?php endforeach; ?>
14
- </dl>
15
-
16
-
17
- </div><!-- / span9 -->
18
- </div><!-- / row -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/widgets/icwp_widgets.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
- function getWidgetIframeHtml( $insSnippet ) {
3
-
4
- $sSubPageNow = isset( $_GET['page'] )? 'page='.$_GET['page'].'&': '';
5
-
6
- $sWidth = '100%';
7
- $sBackgroundColor = "rgba(0, 0, 0, 0)";
8
- $sIframeName = 'iframe-hlt-bootstrapcss-'.$insSnippet;
9
-
10
- if ( strpos( $insSnippet, 'side-widgets') !== false ) {
11
- $sHeight = '700px';
12
- }
13
- elseif ( strpos( $insSnippet, 'dashboard-widget-developerchannel') !== false ) {
14
- $sHeight = '312px';
15
- }
16
- elseif ( strpos( $insSnippet, 'dashboard-widget-worpit') !== false ) {
17
- $sHeight = '230px';
18
- $sBackgroundColor = 'whiteSmoke';
19
- }
20
-
21
- return '<iframe name="'.$sIframeName.'"
22
- src="//www.icontrolwp.com/custom/remote/plugins/hlt-bootstrapcss-plugin-widgets.php?'.$sSubPageNow.'snippet='.$insSnippet.'"
23
- width="'.$sWidth.'" height="'.$sHeight.'" frameborder="0" scrolling="no" style="background-color:'.$sBackgroundColor.';" ></iframe>
24
- ';
25
-
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/common/macros.twig CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  {% macro slideTitle(content) %}
2
  <h4>{{ content }}</h4>
3
  {% endmacro %}
1
+ {% macro shieldpro() %}
2
+ <span class="shieldpro"><strong>Shield</strong><span style="text-transform: uppercase">pro</span></span>
3
+ {% endmacro %}
4
+
5
  {% macro slideTitle(content) %}
6
  <h4>{{ content }}</h4>
7
  {% endmacro %}
templates/twig/components/options_form/main.twig ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form action="{{ form_action }}" method="post" class="icwpOptionsForm form" novalidate="novalidate"
2
+ autocomplete="off">
3
+
4
+ <div id="ModuleOptionsNav" class="list-group list-group-horizontal" role="tablist" aria-orientation="horizontal">
5
+ {% for opt_sect_key,opt_section in data.all_options %}
6
+ <a href="#tab-{{ opt_section.slug }}"
7
+ class="list-group-item list-group-item-action nav-link {{ opt_section.primary ? 'active' : '' }}"
8
+ {% if opt_section.primary %}aria-selected="true"{% endif %}
9
+ id="tab-navlink-{{ opt_section.slug }}"
10
+ data-toggle="tab" role="tab" aria-controls="{{ opt_section.slug }}">
11
+ <span>{{ opt_section.title_short }}</span>
12
+ </a>
13
+ {% endfor %}
14
+ </div>
15
+
16
+ <div class="tab-content container-fluid">
17
+ {% for opt_section in data.all_options %}
18
+ <div class="tab-pane {{ opt_section.primary ? 'active show primary_section' : 'non_primary_section' }}"
19
+ role="tabpanel" id="tab-{{ opt_section.slug }}">
20
+
21
+ <div class="row">
22
+ <div class="col-12">
23
+ <h5 class="mb-3 mt-3">
24
+ <small>
25
+ {% if opt_section.help_video_url is not empty %}
26
+ <a class="section-help-video"
27
+ title="{{ strings.show_help_video_section }}"
28
+ href="{{ opt_section.help_video_url }}"
29
+ data-featherlight="iframe" data-featherlight-iframe-allowfullscreen="true"
30
+ data-featherlight-iframe-width="1200"
31
+ data-featherlight-iframe-height="675">
32
+ <span class="dashicons dashicons-video-alt3"></span>
33
+ </a>
34
+ {% endif %}
35
+ </small>
36
+ {{ opt_section.title }}
37
+
38
+ {% if ( opt_section.summary is defined ) and opt_section.summary|length %}
39
+ <a class="section_title_info"
40
+ data-toggle="popover"
41
+ data-content="<ul>
42
+ {% for item in opt_section.summary %}
43
+ <li class='mt-2'>{{ item|raw|escape }}</li>
44
+ {% endfor %}
45
+ </ul>">
46
+ <span class="dashicons dashicons-info"></span></a>
47
+ {% endif %}
48
+
49
+ </h5>
50
+ </div>
51
+ </div>
52
+
53
+ {% if opt_section.warnings|length %}
54
+ {% for section_warning in opt_section.warnings %}
55
+ <div class="row">
56
+ <div class="col">
57
+ <div class="alert alert-warning text-center">{{ section_warning|raw }}</div>
58
+ </div>
59
+ </div>
60
+ {% endfor %}
61
+ {% endif %}
62
+
63
+ {% if opt_section.notices|length %}
64
+ {% for section_notice in opt_section.notices %}
65
+ <div class="row">
66
+ <div class="col">
67
+ <div class="alert alert-success text-center">{{ section_notice|raw }}</div>
68
+ </div>
69
+ </div>
70
+ {% endfor %}
71
+ {% endif %}
72
+
73
+ {% for key, aOption in opt_section.options %}
74
+ {% include '/components/options_form/option.twig' %}
75
+ {% endfor %}
76
+ </div>
77
+ {% endfor %}
78
+ </div>
79
+ <div class="container-fluid form-actions" id="OptionsFormActions">
80
+ <div class="row">
81
+ <div class="col">
82
+ <button type="submit" class="btn btn-primary btn-lg icwp-form-button"
83
+ name="submit">{{ strings.save_all_settings }}</button>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ </form>
templates/twig/components/options_form/option.twig ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="form-group row option_form_row">
2
+
3
+ <div class="col-2" style="min-width: 140px">
4
+ <label for="Opt-{{ aOption.key }}"
5
+ id="Label-{{ aOption.key }}"
6
+ class="col-form-label">
7
+ <span class="option_label_name">{{ aOption.name }}
8
+ {% if aOption.link_info %}
9
+ <a href="{{ aOption.link_info }}" class="option_link_info d-inline-block" target="_blank"
10
+ title="{{ strings.opt_info_helpdesk }}">
11
+ <span class="dashicons dashicons-editor-help"></span></a>
12
+ {% endif %}
13
+ </span>
14
+
15
+ {% if aOption.disabled %}
16
+ <br />
17
+ <div class="badge badge-success">
18
+ <a href="{{ hrefs.go_pro }}" target="_blank"
19
+ class="text-light">{{ strings.pro_only_option }}</a>
20
+ </div>
21
+ {% endif %}
22
+ </label>
23
+ </div>
24
+
25
+ <div class="col-4">
26
+
27
+ {% if aOption.type is sameas('checkbox') %}
28
+ <div class="form-check-null">
29
+ <div>
30
+ <span class="icwp-switch">
31
+ <input type="checkbox" name="{{ aOption.key }}"
32
+ id="Opt-{{ aOption.key }}" class="form-check-input"
33
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
34
+ aria-labelledby="Label-{{ aOption.key }}"
35
+ value="Y" {{ ( aOption.value is sameas('Y') ) ? 'checked="checked"' : '' }} />
36
+ <span class="icwp-slider round"></span>
37
+ </span>
38
+ </div>
39
+ <div>
40
+ <label class="form-check-label"
41
+ for="Opt-{{ aOption.key }}">{{ aOption.summary }}</label>
42
+ </div>
43
+ </div>
44
+
45
+ {% elseif aOption.type is sameas('text') %}
46
+
47
+ <input type="text" name="{{ aOption.key }}"
48
+ id="Opt-{{ aOption.key }}"
49
+ value="{{ aOption.value|raw }}"
50
+ placeholder="{{ aOption.value }}"
51
+ {% if aOption.disabled %}
52
+ disabled="disabled"
53
+ {% endif %}
54
+ class="form-control" />
55
+
56
+ {% elseif aOption.type is sameas('password') %}
57
+
58
+ <input type="password" name="{{ aOption.key }}"
59
+ id="Opt-{{ aOption.key }}"
60
+ value="{{ aOption.value|raw }}"
61
+ placeholder="{{ strings.supply_password }}"
62
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
63
+ class="form-control mb-2" />
64
+
65
+ <input type="password" name="{{ aOption.key }}_confirm"
66
+ id="Opt-{{ aOption.key }}_confirm"
67
+ value="{{ aOption.value|raw }}"
68
+ placeholder="{{ strings.confirm_password }}"
69
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
70
+ class="form-control" />
71
+
72
+ {% elseif aOption.type is sameas('email') %}
73
+
74
+ <input type="text" name="{{ aOption.key }}"
75
+ id="Opt-{{ aOption.key }}"
76
+ value="{{ aOption.value|raw }}"
77
+ placeholder="{{ aOption.value }}"
78
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
79
+ class="form-control" />
80
+
81
+ {% elseif aOption.type is sameas('select') %}
82
+
83
+ <select name="{{ aOption.key }}"
84
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
85
+ id="Opt-{{ aOption.key }}"
86
+ class="custom-select">
87
+ {% for option_value, option_value_name in aOption.value_options %}
88
+ <option value="{{ option_value }}"
89
+ {% if aOption.value == option_value %}
90
+ selected="selected"
91
+ {% endif %}
92
+ id="Opt-{{ aOption.key }}_{{ option_value }}">
93
+ {{ option_value_name }}
94
+ </option>
95
+ {% endfor %}
96
+ </select>
97
+
98
+ {% elseif aOption.type is sameas('multiple_select') %}
99
+
100
+ <select name="{{ aOption.key }}[]"
101
+ id="Opt-{{ aOption.key }}"
102
+ multiple="multiple" multiple
103
+ size="{{ aOption.value_options|length }}"
104
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
105
+ class="custom-select">
106
+ {% for option_value, option_value_name in aOption.value_options %}
107
+ <option value="{{ option_value }}"
108
+ {% if option_value in aOption.value %}
109
+ selected="selected"
110
+ {% endif %}
111
+ id="Opt-{{ aOption.key }}_{{ option_value }}">
112
+ {{ option_value_name }}
113
+ </option>
114
+ {% endfor %}
115
+ </select>
116
+
117
+ {% elseif aOption.type is sameas('array') %}
118
+
119
+ <textarea name="{{ aOption.key }}"
120
+ id="Opt-{{ aOption.key }}"
121
+ placeholder="{{ aOption.value|raw }}"
122
+ rows="{{ aOption.rows }}"
123
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
124
+ class="form-control">{{ aOption.value|raw }}</textarea>
125
+
126
+ {% elseif aOption.type is sameas('comma_separated_lists') %}
127
+
128
+ <textarea name="{{ aOption.key }}"
129
+ id="Opt-{{ aOption.key }}"
130
+ placeholder="{{ aOption.value }}"
131
+ rows="{{ aOption.rows }}"
132
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
133
+ class="form-control">{{ aOption.value }}</textarea>
134
+
135
+ {% elseif aOption.type is sameas('noneditable_text') %}
136
+
137
+ <input name="{{ aOption.key }}" id="Opt-{{ aOption.key }}"
138
+ type="text" readonly
139
+ class="form-control"
140
+ value="{{ aOption.value }}" />
141
+
142
+ {% elseif aOption.type is sameas('integer') %}
143
+
144
+ <input type="text" name="{{ aOption.key }}"
145
+ id="Opt-{{ aOption.key }}"
146
+ value="{{ aOption.value }}"
147
+ placeholder="{{ aOption.value }}"
148
+ {% if aOption.disabled %}disabled="disabled"{% endif %}
149
+ class="form-control" />
150
+
151
+ {% else %}
152
+ ERROR: Should never reach this point.
153
+ {% endif %}
154
+
155
+ {% if aOption.type is not sameas('checkbox') %}
156
+ {# checkboxes display slightly differently #}
157
+ <div class="options-summary">{{ aOption.summary }}</div>
158
+ {% endif %}
159
+ </div>
160
+
161
+ <div class="col">
162
+ <div class="option-description" id="Description{{ aOption.key }}">
163
+ {{ aOption.description|raw }}
164
+ {% if aOption.link_info %}
165
+ <div class="mt-3 text-left text-nowrap">
166
+ <a href="{{ aOption.link_info }}" target="_blank"
167
+ title="{{ strings.opt_info_helpdesk }}">{{ strings.more_info }}</a>
168
+ {% if aOption.link_blog %}
169
+ <span class="m-1">&vert;</span>
170
+ <a href="{{ aOption.link_blog }}" target="_blank"
171
+ title="{{ strings.opt_info_blog }}">{{ strings.blog }}</a>
172
+ {% endif %}
173
+ </div>
174
+ {% endif %}
175
+ </div>
176
+ </div>
177
+ </div>
templates/twig/features/feature-default.twig CHANGED
@@ -6,7 +6,7 @@
6
 
7
  {% if data.all_options|length %}
8
  <div id="icwp-options-form">
9
- {% include '/snippets/options_form.twig' %}
10
  </div>
11
  {% endif %}
12
 
6
 
7
  {% if data.all_options|length %}
8
  <div id="icwp-options-form">
9
+ {% include '/components/options_form/main.twig' %}
10
  </div>
11
  {% endif %}
12
 
templates/twig/snippets/options_form.twig DELETED
@@ -1,255 +0,0 @@
1
- <form action="{{ form_action }}" method="post" class="icwpOptionsForm form" novalidate="novalidate"
2
- autocomplete="off">
3
-
4
- <ul id="ModuleOptionsNav" class="nav nav-tabs" role="tablist" aria-orientation="vertical">
5
- {% for opt_section in data.all_options %}
6
- <li class="nav-item">
7
- <a href="#tab-{{ opt_section.slug }}" class="nav-link {{ opt_section.primary ? 'active' : '' }}"
8
- {% if opt_section.primary %}aria-selected="true"{% endif %}
9
- id="tab-navlink-{{ opt_section.slug }}"
10
- data-toggle="tab" role="tab" aria-controls="{{ opt_section.slug }}"
11
- >{{ opt_section.title_short }}</a>
12
- </li>
13
- {% endfor %}
14
- </ul>
15
-
16
- <div class="tab-content container-fluid">
17
- {% for opt_section in data.all_options %}
18
- <div class="tab-pane {{ opt_section.primary ? 'active show primary_section' : 'non_primary_section' }}"
19
- role="tabpanel" id="tab-{{ opt_section.slug }}">
20
-
21
- <div class="row">
22
- <div class="col-12">
23
- <h5 class="mb-3 mt-3">
24
- <small>
25
- {% if opt_section.help_video_url is not empty %}
26
- <a class="section-help-video"
27
- title="{{ strings.show_help_video_section }}"
28
- href="{{ opt_section.help_video_url }}"
29
- data-featherlight="iframe" data-featherlight-iframe-allowfullscreen="true"
30
- data-featherlight-iframe-width="1200"
31
- data-featherlight-iframe-height="675">
32
- <span class="dashicons dashicons-video-alt3"></span>
33
- </a>
34
- {% endif %}
35
- </small>
36
- {{ opt_section.title }}
37
- </h5>
38
- </div>
39
- <div class="col-12">
40
- {% if ( opt_section.summary is defined ) and opt_section.summary|length %}
41
- <div class="row">
42
- <div class="col">
43
- <div class="alert alert-secondary" role="definition">
44
- <ul class="mb-0">
45
- {% for item in opt_section.summary %}
46
- <li class="">{{ item|raw }}</li>
47
- {% endfor %}
48
- </ul>
49
- </div>
50
- </div>
51
- </div>
52
- {% endif %}
53
- </div>
54
- </div>
55
-
56
- {% if opt_section.warnings|length %}
57
- {% for section_warning in opt_section.warnings %}
58
- <div class="row">
59
- <div class="col">
60
- <div class="alert alert-warning text-center">{{ section_warning|raw }}</div>
61
- </div>
62
- </div>
63
- {% endfor %}
64
- {% endif %}
65
-
66
- {% if opt_section.notices|length %}
67
- {% for section_notice in opt_section.notices %}
68
- <div class="row">
69
- <div class="col">
70
- <div class="alert alert-info text-center">{{ section_notice|raw }}</div>
71
- </div>
72
- </div>
73
- {% endfor %}
74
- {% endif %}
75
-
76
- {% for key, aOption in opt_section.options %}
77
- <div class="form-group row">
78
- <label for="Opt-{{ aOption.key }}"
79
- id="Label-{{ aOption.key }}"
80
- class="col-sm-1 col-md-2 col-lg-3 col-xl-2 col-form-label">
81
- {{ aOption.name }}
82
- {% if aOption.disabled %}
83
- <br />
84
- <div class="badge badge-success">
85
- <a href="{{ hrefs.go_pro }}" target="_blank"
86
- class="text-light">{{ strings.pro_only_option }}</a>
87
- </div>
88
- {% endif %}
89
- </label>
90
-
91
- <div class="col-xl-6 col-lg-7 col-md-8 col-sm-8">
92
-
93
- {% if aOption.type is sameas('checkbox') %}
94
- <div class="form-check-null">
95
- <span class="icwp-switch">
96
- <input type="checkbox" name="{{ aOption.key }}"
97
- id="Opt-{{ aOption.key }}" class="form-check-input"
98
- {% if aOption.disabled %}disabled="disabled"{% endif %}
99
- aria-labelledby="Label-{{ aOption.key }}"
100
- value="Y" {{ ( aOption.value is sameas('Y') ) ? 'checked="checked"' : '' }} />
101
- <span class="icwp-slider round"></span>
102
- </span>
103
- <label class="form-check-label"
104
- for="Opt-{{ aOption.key }}">{{ aOption.summary }}</label>
105
- </div>
106
-
107
- {% elseif aOption.type is sameas('text') %}
108
-
109
- <input type="text" name="{{ aOption.key }}"
110
- id="Opt-{{ aOption.key }}"
111
- value="{{ aOption.value|raw }}"
112
- placeholder="{{ aOption.value }}"
113
- {% if aOption.disabled %}
114
- disabled="disabled"
115
- {% endif %}
116
- class="form-control" />
117
-
118
- {% elseif aOption.type is sameas('password') %}
119
-
120
- <input type="password" name="{{ aOption.key }}"
121
- id="Opt-{{ aOption.key }}"
122
- value="{{ aOption.value|raw }}"
123
- placeholder="{{ strings.supply_password }}"
124
- {% if aOption.disabled %}disabled="disabled"{% endif %}
125
- class="form-control mb-2" />
126
-
127
- <input type="password" name="{{ aOption.key }}_confirm"
128
- id="Opt-{{ aOption.key }}_confirm"
129
- value="{{ aOption.value|raw }}"
130
- placeholder="{{ strings.confirm_password }}"
131
- {% if aOption.disabled %}disabled="disabled"{% endif %}
132
- class="form-control" />
133
-
134
- {% elseif aOption.type is sameas('email') %}
135
-
136
- <input type="text" name="{{ aOption.key }}"
137
- id="Opt-{{ aOption.key }}"
138
- value="{{ aOption.value|raw }}"
139
- placeholder="{{ aOption.value }}"
140
- {% if aOption.disabled %}disabled="disabled"{% endif %}
141
- class="form-control" />
142
-
143
- {% elseif aOption.type is sameas('select') %}
144
-
145
- <select name="{{ aOption.key }}"
146
- {% if aOption.disabled %}disabled="disabled"{% endif %}
147
- id="Opt-{{ aOption.key }}"
148
- class="custom-select">
149
- {% for option_value, option_value_name in aOption.value_options %}
150
- <option value="{{ option_value }}"
151
- {% if aOption.value == option_value %}
152
- selected="selected"
153
- {% endif %}
154
- id="Opt-{{ aOption.key }}_{{ option_value }}">
155
- {{ option_value_name }}
156
- </option>
157
- {% endfor %}
158
- </select>
159
-
160
- {% elseif aOption.type is sameas('multiple_select') %}
161
-
162
- <select name="{{ aOption.key }}[]"
163
- id="Opt-{{ aOption.key }}"
164
- multiple="multiple" multiple
165
- size="{{ aOption.value_options|length }}"
166
- {% if aOption.disabled %}disabled="disabled"{% endif %}
167
- class="custom-select">
168
- {% for option_value, option_value_name in aOption.value_options %}
169
- <option value="{{ option_value }}"
170
- {% if option_value in aOption.value %}
171
- selected="selected"
172
- {% endif %}
173
- id="Opt-{{ aOption.key }}_{{ option_value }}">
174
- {{ option_value_name }}
175
- </option>
176
- {% endfor %}
177
- </select>
178
-
179
- {% elseif aOption.type is sameas('array') %}
180
-
181
- <textarea name="{{ aOption.key }}"
182
- id="Opt-{{ aOption.key }}"
183
- placeholder="{{ aOption.value|raw }}"
184
- rows="{{ aOption.rows }}"
185
- {% if aOption.disabled %}disabled="disabled"{% endif %}
186
- class="form-control">{{ aOption.value|raw }}</textarea>
187
-
188
- {% elseif aOption.type is sameas('comma_separated_lists') %}
189
-
190
- <textarea name="{{ aOption.key }}"
191
- id="Opt-{{ aOption.key }}"
192
- placeholder="{{ aOption.value }}"
193
- rows="{{ aOption.rows }}"
194
- {% if aOption.disabled %}disabled="disabled"{% endif %}
195
- class="form-control">{{ aOption.value }}</textarea>
196
-
197
- {% elseif aOption.type is sameas('noneditable_text') %}
198
-
199
- <input name="{{ aOption.key }}" id="Opt-{{ aOption.key }}"
200
- type="text" readonly
201
- class="form-control"
202
- value="{{ aOption.value }}" />
203
-
204
- {% elseif aOption.type is sameas('integer') %}
205
-
206
- <input type="text" name="{{ aOption.key }}"
207
- id="Opt-{{ aOption.key }}"
208
- value="{{ aOption.value }}"
209
- placeholder="{{ aOption.value }}"
210
- {% if aOption.disabled %}disabled="disabled"{% endif %}
211
- class="form-control" />
212
-
213
- {% else %}
214
- ERROR: Should never reach this point.
215
- {% endif %}
216
-
217
- {% if aOption.type is not sameas('checkbox') %}
218
- {# checkboxes display slightly differently #}
219
- <div>{{ aOption.summary }}</div>
220
- {% endif %}
221
- <div class="collapse option-description"
222
- id="Description{{ aOption.key }}">{{ aOption.description|raw }}</div>
223
- </div>
224
-
225
- <div class="col-1">
226
- <div class="option-links">
227
- <ul>
228
- <li><a data-toggle="collapse" href="#Description{{ aOption.key }}" role="button"
229
- class="option-link">{{ strings.description }}</a></li>
230
- {% if aOption.link_info %}
231
- <li><a href="{{ aOption.link_info }}" target="_blank" class="option-link">
232
- {{ strings.more_info }}</a></li>
233
- {% if aOption.link_blog %}
234
- <li><a href="{{ aOption.link_blog }}" target="_blank" class="option-link">
235
- {{ strings.blog }}</a></li>
236
- {% endif %}
237
- {% endif %}
238
- </ul>
239
-
240
- </div>
241
- </div>
242
- </div>
243
- {% endfor %}
244
- </div>
245
- {% endfor %}
246
- </div>
247
- <div class="container-fluid form-actions">
248
- <div class="row">
249
- <div class="col">
250
- <button type="submit" class="btn btn-primary btn-lg icwp-form-button"
251
- name="submit">{{ strings.save_all_settings }}</button>
252
- </div>
253
- </div>
254
- </div>
255
- </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wpadmin_pages/insights/license/license.twig CHANGED
@@ -1,3 +1,4 @@
 
1
  <style>
2
  #accordionTop .accordion-toggle h3 {
3
  color: #333333;
@@ -122,12 +123,12 @@
122
 
123
  <div class="card gopro-card">
124
  <div class="card-header" id="headingOne">
125
- <h5 class="mb-0">
126
  <button class="btn btn-link" data-toggle="collapse" data-target="#collone"
127
  aria-expanded="true" aria-controls="collone">
128
- &rarr; Shield Pro gives you ...
129
  </button>
130
- </h5>
131
  </div>
132
 
133
  <div id="collone" class="collapse show" aria-labelledby="headingOne"
@@ -135,13 +136,23 @@
135
  <div class="card-body">
136
  <p><a href="https://shsec.io/gp" target="_blank" class="btn btn-success">
137
  See All PRO Features and Extras &nearr;</a></p>
138
- <dl>
 
 
 
 
 
139
  <dt>Powerful, Auto-Learning Malware Scanner</dt>
140
  <dd>Detects common and uncommon malware patterns in PHP files and alerts you immediately.
141
  <br/>With ShieldNET crowd-sourcing intelligence, Shield automatically hides false-positives
142
  so you can focus on risks that matter, and can ignore the noise that wastes your time.
143
  </dd>
144
 
 
 
 
 
 
145
  <dt>Plugin and Theme Vulnerability Scanner</dt>
146
  <dd>Alerts to plugin/theme vulnerabilities.
147
  Shield can then automatically upgrade as updates become available.
1
+ {% import "/common/macros.twig" as icwp_macros %}
2
  <style>
3
  #accordionTop .accordion-toggle h3 {
4
  color: #333333;
123
 
124
  <div class="card gopro-card">
125
  <div class="card-header" id="headingOne">
126
+ <h4 class="mb-0">
127
  <button class="btn btn-link" data-toggle="collapse" data-target="#collone"
128
  aria-expanded="true" aria-controls="collone">
129
+ &rarr; {{ icwp_macros.shieldpro }} gives you ...
130
  </button>
131
+ </h4>
132
  </div>
133
 
134
  <div id="collone" class="collapse show" aria-labelledby="headingOne"
136
  <div class="card-body">
137
  <p><a href="https://shsec.io/gp" target="_blank" class="btn btn-success">
138
  See All PRO Features and Extras &nearr;</a></p>
139
+ <dl class="pro-features">
140
+ <dt>Easiest, Frustration-Free WP Pro-Upgrade Anywhere</dt>
141
+ <dd>No more license keys to remember/copy-paste! Simply activate your site URL in your
142
+ {{ icwp_macros.shieldpro }} control panel and get Pro features enabled on your site automatically.
143
+ </dd>
144
+
145
  <dt>Powerful, Auto-Learning Malware Scanner</dt>
146
  <dd>Detects common and uncommon malware patterns in PHP files and alerts you immediately.
147
  <br/>With ShieldNET crowd-sourcing intelligence, Shield automatically hides false-positives
148
  so you can focus on risks that matter, and can ignore the noise that wastes your time.
149
  </dd>
150
 
151
+ <dt>Traffic Rate Limiting</dt>
152
+ <dd>Prevent abuse of your web hosting resources by detecting and blocking bots that send
153
+ too many requests to your site.
154
+ </dd>
155
+
156
  <dt>Plugin and Theme Vulnerability Scanner</dt>
157
  <dd>Alerts to plugin/theme vulnerabilities.
158
  Shield can then automatically upgrade as updates become available.
templates/twig/wpadmin_pages/insights/scans/results/apc.twig CHANGED
@@ -14,7 +14,7 @@
14
  {% if scan.flags.is_enabled %}
15
 
16
  {% if not scan.flags.has_items %}
17
- <div class="alert alert-info m-0">{{ strings.no_entries_to_display }}</div>
18
  {% else %}
19
  <div id="TableScanApc" class="container-scantable"></div>
20
  {% endif %}
14
  {% if scan.flags.is_enabled %}
15
 
16
  {% if not scan.flags.has_items %}
17
+ <div class="alert alert-success m-0">{{ strings.no_entries_to_display }}</div>
18
  {% else %}
19
  <div id="TableScanApc" class="container-scantable"></div>
20
  {% endif %}
templates/twig/wpadmin_pages/insights/scans/results/common_disabled.twig CHANGED
@@ -1,6 +1,6 @@
1
  <div class="row">
2
  <div class="col-12">
3
- <div class="alert alert-info m-0">
4
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
5
  <p class="m-0"><a class="alert-link" href="{{ scan.hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
6
  </div>
1
  <div class="row">
2
  <div class="col-12">
3
+ <div class="alert alert-success m-0">
4
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
5
  <p class="m-0"><a class="alert-link" href="{{ scan.hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
6
  </div>
templates/twig/wpadmin_pages/insights/scans/results/mal.twig CHANGED
@@ -15,7 +15,7 @@
15
  {% if scan.flags.is_available %}
16
 
17
  {% if not scan.flags.has_items %}
18
- <div class="alert alert-info m-0">{{ strings.no_entries_to_display }}</div>
19
  {% else %}
20
  <div id="TableScanMal" class="container-scantable"></div>
21
  {% endif %}
15
  {% if scan.flags.is_available %}
16
 
17
  {% if not scan.flags.has_items %}
18
+ <div class="alert alert-success m-0">{{ strings.no_entries_to_display }}</div>
19
  {% else %}
20
  <div id="TableScanMal" class="container-scantable"></div>
21
  {% endif %}
templates/twig/wpadmin_pages/insights/scans/results/mal_disabled.twig CHANGED
@@ -1,6 +1,6 @@
1
  <div class="row">
2
  <div class="col-12">
3
- <div class="alert alert-info m-0">
4
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
5
  <p class="m-0"><a class="alert-link" href="{{ scan.hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
6
  </div>
1
  <div class="row">
2
  <div class="col-12">
3
+ <div class="alert alert-success m-0">
4
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
5
  <p class="m-0"><a class="alert-link" href="{{ scan.hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
6
  </div>
templates/twig/wpadmin_pages/insights/scans/results/ptg.twig CHANGED
@@ -13,7 +13,7 @@
13
  {% else %}
14
  {% if scan.flags.is_available %}
15
  {% if not scan.flags.has_items %}
16
- <div class="alert alert-info m-0">{{ strings.no_entries_to_display }}</div>
17
  {% else %}
18
  {% include '/wpadmin_pages/insights/scans/results/'~scankey~'_table.twig' %}
19
  {% endif %}
13
  {% else %}
14
  {% if scan.flags.is_available %}
15
  {% if not scan.flags.has_items %}
16
+ <div class="alert alert-success m-0">{{ strings.no_entries_to_display }}</div>
17
  {% else %}
18
  {% include '/wpadmin_pages/insights/scans/results/'~scankey~'_table.twig' %}
19
  {% endif %}
templates/twig/wpadmin_pages/insights/scans/results/wpv.twig CHANGED
@@ -15,7 +15,7 @@
15
  {% if scan.flags.is_available %}
16
 
17
  {% if not scan.flags.has_items %}
18
- <div class="alert alert-info m-0">{{ strings.no_entries_to_display }}</div>
19
  {% else %}
20
  <div id="TableScanWpv" class="container-scantable"></div>
21
  {% endif %}
15
  {% if scan.flags.is_available %}
16
 
17
  {% if not scan.flags.has_items %}
18
+ <div class="alert alert-success m-0">{{ strings.no_entries_to_display }}</div>
19
  {% else %}
20
  <div id="TableScanWpv" class="container-scantable"></div>
21
  {% endif %}
templates/twig/wpadmin_pages/insights/settings/index.twig CHANGED
@@ -2,18 +2,25 @@
2
 
3
  {% block page_main %}
4
  <div class="row" id="ModulePageTopRow">
5
- <div class="col-1 modules smoothwidth" id="ColumnModules">
6
 
7
  <div class="nav flex-column">
 
 
8
  {% for mod_summary in aSummaryData %}
9
- <a class="nav-link module {% if mod_summary.active %}active{% endif %}
 
10
  {% if mod_summary.enabled %}enabled{% else %}notenabled{% endif %}"
11
  id="tab-{{ mod_summary.slug }}"
12
- data-toggle="tooltip"
13
- title="{{ mod_summary.tooltip }}"
14
  href="{{ mod_summary.href }}" role="tab">
15
- <div class="module-icon module-icon-{{ mod_summary.slug }}"
16
- id="module-{{ mod_summary.slug }}"></div>
 
 
 
 
 
 
17
  </a>
18
  {% endfor %}
19
  </div>
@@ -25,11 +32,11 @@
25
  <script>
26
  iCWP_WPSF_OptsPageRender.renderForm( {{ ajax.mod_opts_form_render|raw }} );
27
  iCWP_WPSF_OptionsFormSubmit.updateAjaxReqParams( {{ ajax.mod_options|raw }} );
28
- jQuery( 'a.nav-link.module' ).tooltip({
29
  placement: 'right',
30
  trigger: 'hover'
31
  } );
32
- jQuery( 'a.section-help-video' ).tooltip({
33
  placement: 'right',
34
  trigger: 'hover'
35
  } );
2
 
3
  {% block page_main %}
4
  <div class="row" id="ModulePageTopRow">
5
+ <div class="modules smoothwidth" id="ColumnModules">
6
 
7
  <div class="nav flex-column">
8
+ <h5 class="mt-3 border-bottom"
9
+ style="font-variant: small-caps;font-weight: normal">Shield Modules</h5>
10
  {% for mod_summary in aSummaryData %}
11
+ <a class="nav-link module
12
+ {% if mod_summary.active %}active{% endif %}
13
  {% if mod_summary.enabled %}enabled{% else %}notenabled{% endif %}"
14
  id="tab-{{ mod_summary.slug }}"
 
 
15
  href="{{ mod_summary.href }}" role="tab">
16
+ <div>
17
+ {% if mod_summary.active %}&rdsh;{% endif %}
18
+ <span class="module-icon module-icon-{{ mod_summary.slug }}"
19
+ id="module-{{ mod_summary.slug }}"></span>
20
+ <span class="module-name">
21
+ {{ mod_summary.tooltip }}
22
+ </span>
23
+ </div>
24
  </a>
25
  {% endfor %}
26
  </div>
32
  <script>
33
  iCWP_WPSF_OptsPageRender.renderForm( {{ ajax.mod_opts_form_render|raw }} );
34
  iCWP_WPSF_OptionsFormSubmit.updateAjaxReqParams( {{ ajax.mod_options|raw }} );
35
+ jQuery( 'a.nav-link.module' ).tooltip( {
36
  placement: 'right',
37
  trigger: 'hover'
38
  } );
39
+ jQuery( 'a.section-help-video' ).tooltip( {
40
  placement: 'right',
41
  trigger: 'hover'
42
  } );
templates/twig/wpadmin_pages/insights/traffic/index.twig CHANGED
@@ -5,7 +5,7 @@
5
  <div class="col-12 insights_section">
6
  {% if flags.can_traffic %}
7
  {% if not flags.is_enabled %}
8
- <div class="alert alert-info">
9
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
10
  <p class="m-0"><a class="alert-link" href="{{ hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
11
  </div>
5
  <div class="col-12 insights_section">
6
  {% if flags.can_traffic %}
7
  {% if not flags.is_enabled %}
8
+ <div class="alert alert-success">
9
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
10
  <p class="m-0"><a class="alert-link" href="{{ hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
11
  </div>
templates/twig/wpadmin_pages/insights/traffic/traffic_disabled.twig CHANGED
@@ -6,7 +6,7 @@
6
 
7
  <div class="row">
8
  <div class="col-12">
9
- <div class="alert alert-info m-0">
10
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
11
  <p class="m-0"><a class="alert-link" href="{{ hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
12
  </div>
6
 
7
  <div class="row">
8
  <div class="col-12">
9
+ <div class="alert alert-success m-0">
10
  <h6 class="alert-heading">{{ strings.not_enabled }}</h6>
11
  <p class="m-0"><a class="alert-link" href="{{ hrefs.please_enable }}">{{ strings.please_enable }}</a></p>
12
  </div>
templates/twig/wpadmin_pages/security_admin/index.twig CHANGED
@@ -50,15 +50,16 @@
50
 
51
  </form>
52
 
53
- <div class="alert alert-info mb-0 mt-5 text-center">
54
  {% if flags.allow_email_override %}
55
 
56
  <p>
57
  {{ strings.force_remove_email }}
58
  </p>
59
  <p class="mb-0">
60
- <a href="#" id="SecAdminRemoveConfirmEmail">{{ strings.click_email }}</a>
61
- <br/>
 
62
  ({{ strings.send_to_email }})
63
  </p>
64
  {% else %}
50
 
51
  </form>
52
 
53
+ <div class="alert alert-success mb-0 mt-5 text-center">
54
  {% if flags.allow_email_override %}
55
 
56
  <p>
57
  {{ strings.force_remove_email }}
58
  </p>
59
  <p class="mb-0">
60
+ <a href="#" id="SecAdminRemoveConfirmEmail"
61
+ class="alert-link">{{ strings.click_email }}</a>
62
+ <br />
63
  ({{ strings.send_to_email }})
64
  </p>
65
  {% else %}