Shield Security for WordPress - Version 16.1.0

Version Description

Download this release

Release Info

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

Code changes from version 16.0.9 to 16.1.0

Files changed (149) hide show
  1. cl.json +24 -1
  2. config/admin_access_restriction.json +6 -2
  3. config/deprecated/admin_access_restriction.php +6 -2
  4. config/deprecated/firewall.php +2 -13
  5. config/deprecated/ips.php +10 -3
  6. config/deprecated/plugin.php +0 -52
  7. config/firewall.json +2 -13
  8. config/ips.json +10 -3
  9. config/plugin.json +0 -52
  10. icwp-wpsf.php +3 -1
  11. plugin-spec.php +16 -9
  12. plugin.json +21 -9
  13. readme.txt +3 -3
  14. resources/css/plugin.css +17 -2
  15. resources/css/shield/merlin.css +38 -0
  16. resources/css/shield/wizard.css +0 -542
  17. resources/images/bootstrap/box-arrow-left.svg +4 -0
  18. resources/images/bootstrap/magic.svg +3 -0
  19. resources/js/plugin.js +16 -11
  20. resources/js/shield/ipanalyse.js +2 -3
  21. resources/js/shield/merlin.js +33 -0
  22. resources/js/shield/wizard.js +0 -0
  23. src/lib/src/Blocks/RenderBlockPages/RenderBlockAuthorFishing.php +0 -4
  24. src/lib/src/Blocks/RenderBlockPages/RenderBlockFirewall.php +0 -1
  25. src/lib/src/Modules/AuditTrail/Lib/LogTable/BuildAuditTableData.php +2 -3
  26. src/lib/src/Modules/AuditTrail/UI.php +1 -1
  27. src/lib/src/Modules/Base/Lib/Request/FormParams.php +2 -1
  28. src/lib/src/Modules/Base/ModCon.php +48 -110
  29. src/lib/src/Modules/Base/Options.php +8 -0
  30. src/lib/src/Modules/Base/Options/BuildForDisplay.php +1 -0
  31. src/lib/src/Modules/Base/Options/HandleOptionsSaveRequest.php +6 -3
  32. src/lib/src/Modules/Base/Strings.php +0 -1
  33. src/lib/src/Modules/Base/UI.php +10 -7
  34. src/lib/src/Modules/BaseShield/AjaxHandler.php +0 -10
  35. src/lib/src/Modules/BaseShield/ModCon.php +1 -2
  36. src/lib/src/Modules/Firewall/ModCon.php +0 -1
  37. src/lib/src/Modules/Firewall/Rules/Build/FirewallLeadingSchema.php +3 -0
  38. src/lib/src/Modules/Firewall/Strings.php +0 -6
  39. src/lib/src/Modules/IPs/BotTrack/TrackLinkCheese.php +6 -13
  40. src/lib/src/Modules/IPs/Lib/AutoUnblock/AutoUnblockCrowdsec.php +4 -0
  41. src/lib/src/Modules/IPs/Lib/AutoUnblock/AutoUnblockMagicLink.php +4 -0
  42. src/lib/src/Modules/IPs/Lib/AutoUnblock/AutoUnblockVisitor.php +4 -0
  43. src/lib/src/Modules/IPs/Lib/AutoUnblock/BaseAutoUnblock.php +14 -0
  44. src/lib/src/Modules/IPs/Lib/CrowdSec/Api/DecisionsDownload.php +5 -0
  45. src/lib/src/Modules/IPs/Lib/CrowdSec/Decisions/ImportDecisions.php +4 -0
  46. src/lib/src/Modules/IPs/Lib/Table/BuildIpRulesTableData.php +1 -1
  47. src/lib/src/Modules/IPs/Strings.php +12 -1
  48. src/lib/src/Modules/IPs/UI.php +1 -1
  49. src/lib/src/Modules/Insights/AjaxHandler.php +27 -9
  50. src/lib/src/Modules/Insights/Lib/Merlin/MerlinController.php +130 -0
  51. src/lib/src/Modules/Insights/Lib/Merlin/Steps/Base.php +82 -0
  52. src/lib/src/Modules/Insights/Lib/Merlin/Steps/CommentSpam.php +49 -0
  53. src/lib/src/Modules/Insights/Lib/Merlin/Steps/FreeTrial.php +27 -0
  54. src/lib/src/Modules/Insights/Lib/Merlin/Steps/GuidedSetupWelcome.php +25 -0
  55. src/lib/src/Modules/Insights/Lib/Merlin/Steps/Import.php +67 -0
  56. src/lib/src/Modules/Insights/Lib/Merlin/Steps/IpBlocking.php +68 -0
  57. src/lib/src/Modules/Insights/Lib/Merlin/Steps/IpDetect.php +71 -0
  58. src/lib/src/Modules/Insights/Lib/Merlin/Steps/License.php +45 -0
  59. src/lib/src/Modules/Insights/Lib/Merlin/Steps/LoginProtection.php +47 -0
  60. src/lib/src/Modules/Insights/Lib/Merlin/Steps/OptIn.php +38 -0
  61. src/lib/src/Modules/Insights/Lib/Merlin/Steps/SecurityAdmin.php +58 -0
  62. src/lib/src/Modules/Insights/Lib/Merlin/Steps/SecurityBadge.php +47 -0
  63. src/lib/src/Modules/Insights/Lib/Merlin/Steps/ThankYou.php +34 -0
  64. src/lib/src/Modules/Insights/Lib/MeterAnalysis/Handler.php +42 -19
  65. src/lib/src/Modules/Insights/Lib/MeterAnalysis/MeterIntegrity.php +6 -4
  66. src/lib/src/Modules/Insights/Lib/NavMenuBuilder.php +8 -21
  67. src/lib/src/Modules/Insights/ModCon.php +38 -1
  68. src/lib/src/Modules/Insights/UI.php +19 -35
  69. src/lib/src/Modules/Lockdown/ModCon.php +1 -1
  70. src/lib/src/Modules/Lockdown/Rules/Build/IsRequestAuthorDiscovery.php +1 -1
  71. src/lib/src/Modules/LoginGuard/UI.php +16 -2
  72. src/lib/src/Modules/Plugin/AdminNotices.php +0 -27
  73. src/lib/src/Modules/Plugin/AjaxHandler.php +0 -14
  74. src/lib/src/Modules/Plugin/Debug.php +4 -4
  75. src/lib/src/Modules/Plugin/Lib/SelectSearchData.php +7 -0
  76. src/lib/src/Modules/Plugin/UI.php +0 -27
  77. src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Ops/ToggleSecAdminStatus.php +1 -0
  78. src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php +28 -2
  79. src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/WhitelabelController.php +0 -2
  80. src/lib/src/Modules/SecurityAdmin/ModCon.php +3 -35
  81. src/lib/src/Modules/SecurityAdmin/Strings.php +9 -2
  82. src/lib/src/Modules/Traffic/Lib/TrafficTable/BuildTrafficTableData.php +1 -1
  83. src/lib/src/Modules/Traffic/UI.php +1 -1
  84. src/lib/src/Tables/DataTables/Build/{AuditTrail/ForAuditTrail.php → ForAuditTrail.php} +16 -17
  85. src/lib/src/Tables/DataTables/Build/{IpRules/ForIpRules.php → ForIpRules.php} +34 -33
  86. src/lib/src/Tables/DataTables/Build/{Traffic/ForTraffic.php → ForTraffic.php} +9 -10
  87. src/lib/src/Utilities/Response.php +55 -0
  88. src/lib/src/Utilities/Tool/AssessDirWrite.php +3 -0
  89. src/lib/vendor/composer/autoload_classmap.php +18 -7
  90. src/lib/vendor/composer/autoload_static.php +18 -7
  91. src/lib/vendor/composer/installed.php +6 -6
  92. src/wizards/base.php +0 -477
  93. src/wizards/base_wpsf.php +0 -115
  94. src/wizards/login_protect.php +0 -142
  95. src/wizards/plugin.php +1 -332
  96. templates/twig/common/macros.twig +28 -21
  97. templates/twig/components/merlin/container.twig +52 -0
  98. templates/twig/components/merlin/steps/base.twig +40 -0
  99. templates/twig/components/merlin/steps/comment_spam.twig +35 -0
  100. templates/twig/components/merlin/steps/free_trial.twig +27 -0
  101. templates/twig/components/merlin/steps/guided_setup_welcome.twig +11 -0
  102. templates/twig/components/merlin/steps/import.twig +44 -0
  103. templates/twig/components/merlin/steps/ip_blocking.twig +72 -0
  104. templates/twig/components/merlin/steps/ip_detect.twig +52 -0
  105. templates/twig/components/merlin/steps/license.twig +24 -0
  106. templates/twig/{wizard/slides/welcome/login_protect.twig → components/merlin/steps/login_protection.twig} +11 -12
  107. templates/twig/{wizard/slides/welcome/optin.twig → components/merlin/steps/opt_in.twig} +1 -4
  108. templates/twig/components/merlin/steps/security_admin.twig +37 -0
  109. templates/twig/{wizard/slides/welcome/plugin_badge.twig → components/merlin/steps/security_badge.twig} +3 -4
  110. templates/twig/components/merlin/steps/thank_you.twig +22 -0
  111. templates/twig/components/options_form/main.twig +13 -0
  112. templates/twig/wizard/pages/base.twig +0 -17
  113. templates/twig/wizard/pages/landing.twig +0 -14
  114. templates/twig/wizard/pages/wizard.twig +0 -279
  115. templates/twig/wizard/slides/common/base.twig +0 -61
  116. templates/twig/wizard/slides/common/base_finish.twig +0 -50
  117. templates/twig/wizard/slides/common/base_start.twig +0 -4
  118. templates/twig/wizard/slides/common/no_access.twig +0 -15
  119. templates/twig/wizard/slides/common/security_admin_verify.twig +0 -19
  120. templates/twig/wizard/slides/importexport/finished.twig +0 -6
  121. templates/twig/wizard/slides/importexport/import.twig +0 -80
  122. templates/twig/wizard/slides/importexport/start.twig +0 -29
  123. templates/twig/wizard/slides/ptg/config.twig +0 -26
  124. templates/twig/wizard/slides/ptg/finished.twig +0 -7
  125. templates/twig/wizard/slides/ptg/scanresult_base.twig +0 -121
  126. templates/twig/wizard/slides/ptg/scanresult_plugins.twig +0 -1
  127. templates/twig/wizard/slides/ptg/scanresult_themes.twig +0 -1
  128. templates/twig/wizard/slides/ptg/start.twig +0 -18
  129. templates/twig/wizard/slides/ufc/config.twig +0 -23
  130. templates/twig/wizard/slides/ufc/exclusions.twig +0 -49
  131. templates/twig/wizard/slides/ufc/finished.twig +0 -6
  132. templates/twig/wizard/slides/ufc/scanresult.twig +0 -40
  133. templates/twig/wizard/slides/ufc/start.twig +0 -18
  134. templates/twig/wizard/slides/wcf/config.twig +0 -23
  135. templates/twig/wizard/slides/wcf/finished.twig +0 -6
  136. templates/twig/wizard/slides/wcf/scanresult.twig +0 -56
  137. templates/twig/wizard/slides/wcf/start.twig +0 -14
  138. templates/twig/wizard/slides/welcome/admin_access_restriction.twig +0 -35
  139. templates/twig/wizard/slides/welcome/comments_filter.twig +0 -37
  140. templates/twig/wizard/slides/welcome/free_trial.twig +0 -29
  141. templates/twig/wizard/slides/welcome/ip_detect.twig +0 -41
  142. templates/twig/wizard/slides/welcome/ips.twig +0 -38
  143. templates/twig/wizard/slides/welcome/thankyou.twig +0 -40
  144. templates/twig/wizard/slides/welcome/welcome.twig +0 -21
  145. templates/twig/wizard/snippets/wizard_landing.twig +0 -28
  146. templates/twig/wizard/wizard_container.twig +0 -285
  147. templates/twig/wpadmin_pages/insights/{wizard → default}/index.twig +1 -1
  148. templates/twig/wpadmin_pages/insights/overview/progress_meter/meter_card.twig +63 -0
  149. templates/twig/wpadmin_pages/insights/overview/progress_meter/progress_meters.twig +7 -57
cl.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "16.0": {
3
  "version": "16.1",
4
- "released_at": 1662379200,
5
  "hrefs": {
6
  "release": "https://shsec.io/shieldrelease161",
7
  "upgrade": "https://shsec.io/shieldupgradeguide161"
@@ -83,6 +83,14 @@
83
  "Shield offer a much better navbar on the dashboard with built-in search, helpdesk links and updates."
84
  ]
85
  },
 
 
 
 
 
 
 
 
86
  {
87
  "type": "new",
88
  "pro_only": false,
@@ -91,6 +99,21 @@
91
  "Shield now captures creation of new Application Passwords in the Activity Log."
92
  ]
93
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  {
95
  "type": "fixed",
96
  "pro_only": false,
1
  {
2
  "16.0": {
3
  "version": "16.1",
4
+ "released_at": 1662984000,
5
  "hrefs": {
6
  "release": "https://shsec.io/shieldrelease161",
7
  "upgrade": "https://shsec.io/shieldupgradeguide161"
83
  "Shield offer a much better navbar on the dashboard with built-in search, helpdesk links and updates."
84
  ]
85
  },
86
+ {
87
+ "type": "improved",
88
+ "pro_only": false,
89
+ "title": "Protection Against Unauthorised Deactivation",
90
+ "description": [
91
+ "The Security Admin feature that protects against unauthorised deactivation has been further strengthened with offenses."
92
+ ]
93
+ },
94
  {
95
  "type": "new",
96
  "pro_only": false,
99
  "Shield now captures creation of new Application Passwords in the Activity Log."
100
  ]
101
  },
102
+ {
103
+ "type": "new",
104
+ "title": "Removed: Leading Schema Firewall Rule",
105
+ "description": [
106
+ "This rules flags too many false positives for members."
107
+ ]
108
+ },
109
+ {
110
+ "type": "changed",
111
+ "title": "Minimum WordPress Version: 4.7",
112
+ "description": [
113
+ "Based on Shield telemetry data, we're pushing our minimum supported WordPress version up to 4.7.",
114
+ "We'll continue to push this upwards as usage data suggests it make sense to do so."
115
+ ]
116
+ },
117
  {
118
  "type": "fixed",
119
  "pro_only": false,
config/admin_access_restriction.json CHANGED
@@ -427,14 +427,18 @@
427
  "users.php"
428
  ],
429
  "events": {
430
- "key_success": {
431
  "level": "debug",
432
  "recent": true
433
  },
434
- "key_fail": {
435
  "level": "warning",
436
  "recent": true,
437
  "offense": true
 
 
 
 
438
  }
439
  },
440
  "options_to_restrict": {
427
  "users.php"
428
  ],
429
  "events": {
430
+ "key_success": {
431
  "level": "debug",
432
  "recent": true
433
  },
434
+ "key_fail": {
435
  "level": "warning",
436
  "recent": true,
437
  "offense": true
438
+ },
439
+ "attempt_deactivation": {
440
+ "level": "warning",
441
+ "offense": true
442
  }
443
  },
444
  "options_to_restrict": {
config/deprecated/admin_access_restriction.php CHANGED
@@ -427,14 +427,18 @@
427
  "users.php"
428
  ],
429
  "events": {
430
- "key_success": {
431
  "level": "debug",
432
  "recent": true
433
  },
434
- "key_fail": {
435
  "level": "warning",
436
  "recent": true,
437
  "offense": true
 
 
 
 
438
  }
439
  },
440
  "options_to_restrict": {
427
  "users.php"
428
  ],
429
  "events": {
430
+ "key_success": {
431
  "level": "debug",
432
  "recent": true
433
  },
434
+ "key_fail": {
435
  "level": "warning",
436
  "recent": true,
437
  "offense": true
438
+ },
439
+ "attempt_deactivation": {
440
+ "level": "warning",
441
+ "offense": true
442
  }
443
  },
444
  "options_to_restrict": {
config/deprecated/firewall.php CHANGED
@@ -161,18 +161,6 @@
161
  "summary": "Block Executable File Uploads",
162
  "description": "This will block executable file uploads (.php, .exe, etc.)."
163
  },
164
- {
165
- "key": "block_leading_schema",
166
- "section": "section_firewall_blocking_options",
167
- "advanced": true,
168
- "default": "N",
169
- "type": "checkbox",
170
- "link_info": "",
171
- "link_blog": "",
172
- "name": "Leading Schemas",
173
- "summary": "Block Leading Schemas (HTTPS / HTTP)",
174
- "description": "This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with other plugins)."
175
- },
176
  {
177
  "key": "block_aggressive",
178
  "section": "section_firewall_blocking_options",
@@ -331,7 +319,8 @@
331
  "joe-chnlcustid",
332
  "spd-custhash",
333
  "joe-custinfo",
334
- "_wpcf7cf_hidden_group_fields"
 
335
  ]
336
  }
337
  },
161
  "summary": "Block Executable File Uploads",
162
  "description": "This will block executable file uploads (.php, .exe, etc.)."
163
  },
 
 
 
 
 
 
 
 
 
 
 
 
164
  {
165
  "key": "block_aggressive",
166
  "section": "section_firewall_blocking_options",
319
  "joe-chnlcustid",
320
  "spd-custhash",
321
  "joe-custinfo",
322
+ "_wpcf7cf_hidden_group_fields",
323
+ "wl_homeurl"
324
  ]
325
  }
326
  },
config/deprecated/ips.php CHANGED
@@ -947,6 +947,13 @@
947
  "offense": false,
948
  "stat": false
949
  },
 
 
 
 
 
 
 
950
  "ip_unblock_flag": {
951
  "audit_params": [
952
  "ip"
@@ -1028,20 +1035,20 @@
1028
  ]
1029
  },
1030
  "crowdsec_mach_register": {
1031
- "level": "info",
1032
  "audit_params": [
1033
  "machine_id",
1034
  "url"
1035
  ]
1036
  },
1037
  "crowdsec_auth_acquire": {
1038
- "level": "info",
1039
  "audit_params": [
1040
  "expiration"
1041
  ]
1042
  },
1043
  "crowdsec_mach_enroll": {
1044
- "level": "info",
1045
  "audit_params": [
1046
  "id",
1047
  "name"
947
  "offense": false,
948
  "stat": false
949
  },
950
+ "ip_unblock_auto": {
951
+ "audit_params": [
952
+ "ip",
953
+ "method"
954
+ ],
955
+ "level": "alert"
956
+ },
957
  "ip_unblock_flag": {
958
  "audit_params": [
959
  "ip"
1035
  ]
1036
  },
1037
  "crowdsec_mach_register": {
1038
+ "level": "notice",
1039
  "audit_params": [
1040
  "machine_id",
1041
  "url"
1042
  ]
1043
  },
1044
  "crowdsec_auth_acquire": {
1045
+ "level": "notice",
1046
  "audit_params": [
1047
  "expiration"
1048
  ]
1049
  },
1050
  "crowdsec_mach_enroll": {
1051
+ "level": "notice",
1052
  "audit_params": [
1053
  "id",
1054
  "name"
config/deprecated/plugin.php CHANGED
@@ -82,11 +82,6 @@
82
  "can_dismiss": false,
83
  "type": "warning"
84
  },
85
- "wizard_welcome": {
86
- "id": "wizard_welcome",
87
- "per_user": false,
88
- "type": "info"
89
- },
90
  "plugin-mailing-list-signup": {
91
  "id": "plugin-mailing-list-signup",
92
  "min_install_days": 5,
@@ -685,53 +680,6 @@
685
  "offense": false,
686
  "stat": false
687
  }
688
- },
689
- "wizards": {
690
- "welcome": {
691
- "title": "Getting Started Setup Wizard",
692
- "desc": "An introduction to this security plugin, helping you get setup and started quickly with the core features.",
693
- "min_user_permissions": "manage_options",
694
- "steps": {
695
- "welcome": {
696
- "security_admin": false,
697
- "title": "Welcome"
698
- },
699
- "ip_detect": {
700
- "title": "IP Detection"
701
- },
702
- "admin_access_restriction": {
703
- "title": "Security Admin"
704
- },
705
- "audit_trail": {
706
- "title": "Activity Log"
707
- },
708
- "ips": {
709
- "title": "IP Blacklist"
710
- },
711
- "login_protect": {
712
- "title": "Login Protection"
713
- },
714
- "comments_filter": {
715
- "title": "Comment SPAM"
716
- },
717
- "plugin_badge": {
718
- "title": "Security Badge"
719
- },
720
- "plugin_telemetry": {
721
- "title": "Plugin Telemetry"
722
- },
723
- "free_trial": {
724
- "title": "Free Trial"
725
- },
726
- "optin": {
727
- "title": "Join Us!"
728
- },
729
- "thankyou": {
730
- "security_admin": false,
731
- "title": "Thank You!"
732
- }
733
- }
734
- }
735
  }
736
  }
737
  }
82
  "can_dismiss": false,
83
  "type": "warning"
84
  },
 
 
 
 
 
85
  "plugin-mailing-list-signup": {
86
  "id": "plugin-mailing-list-signup",
87
  "min_install_days": 5,
680
  "offense": false,
681
  "stat": false
682
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
  }
684
  }
685
  }
config/firewall.json CHANGED
@@ -161,18 +161,6 @@
161
  "summary": "Block Executable File Uploads",
162
  "description": "This will block executable file uploads (.php, .exe, etc.)."
163
  },
164
- {
165
- "key": "block_leading_schema",
166
- "section": "section_firewall_blocking_options",
167
- "advanced": true,
168
- "default": "N",
169
- "type": "checkbox",
170
- "link_info": "",
171
- "link_blog": "",
172
- "name": "Leading Schemas",
173
- "summary": "Block Leading Schemas (HTTPS / HTTP)",
174
- "description": "This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with other plugins)."
175
- },
176
  {
177
  "key": "block_aggressive",
178
  "section": "section_firewall_blocking_options",
@@ -331,7 +319,8 @@
331
  "joe-chnlcustid",
332
  "spd-custhash",
333
  "joe-custinfo",
334
- "_wpcf7cf_hidden_group_fields"
 
335
  ]
336
  }
337
  },
161
  "summary": "Block Executable File Uploads",
162
  "description": "This will block executable file uploads (.php, .exe, etc.)."
163
  },
 
 
 
 
 
 
 
 
 
 
 
 
164
  {
165
  "key": "block_aggressive",
166
  "section": "section_firewall_blocking_options",
319
  "joe-chnlcustid",
320
  "spd-custhash",
321
  "joe-custinfo",
322
+ "_wpcf7cf_hidden_group_fields",
323
+ "wl_homeurl"
324
  ]
325
  }
326
  },
config/ips.json CHANGED
@@ -947,6 +947,13 @@
947
  "offense": false,
948
  "stat": false
949
  },
 
 
 
 
 
 
 
950
  "ip_unblock_flag": {
951
  "audit_params": [
952
  "ip"
@@ -1028,20 +1035,20 @@
1028
  ]
1029
  },
1030
  "crowdsec_mach_register": {
1031
- "level": "info",
1032
  "audit_params": [
1033
  "machine_id",
1034
  "url"
1035
  ]
1036
  },
1037
  "crowdsec_auth_acquire": {
1038
- "level": "info",
1039
  "audit_params": [
1040
  "expiration"
1041
  ]
1042
  },
1043
  "crowdsec_mach_enroll": {
1044
- "level": "info",
1045
  "audit_params": [
1046
  "id",
1047
  "name"
947
  "offense": false,
948
  "stat": false
949
  },
950
+ "ip_unblock_auto": {
951
+ "audit_params": [
952
+ "ip",
953
+ "method"
954
+ ],
955
+ "level": "alert"
956
+ },
957
  "ip_unblock_flag": {
958
  "audit_params": [
959
  "ip"
1035
  ]
1036
  },
1037
  "crowdsec_mach_register": {
1038
+ "level": "notice",
1039
  "audit_params": [
1040
  "machine_id",
1041
  "url"
1042
  ]
1043
  },
1044
  "crowdsec_auth_acquire": {
1045
+ "level": "notice",
1046
  "audit_params": [
1047
  "expiration"
1048
  ]
1049
  },
1050
  "crowdsec_mach_enroll": {
1051
+ "level": "notice",
1052
  "audit_params": [
1053
  "id",
1054
  "name"
config/plugin.json CHANGED
@@ -82,11 +82,6 @@
82
  "can_dismiss": false,
83
  "type": "warning"
84
  },
85
- "wizard_welcome": {
86
- "id": "wizard_welcome",
87
- "per_user": false,
88
- "type": "info"
89
- },
90
  "plugin-mailing-list-signup": {
91
  "id": "plugin-mailing-list-signup",
92
  "min_install_days": 5,
@@ -685,53 +680,6 @@
685
  "offense": false,
686
  "stat": false
687
  }
688
- },
689
- "wizards": {
690
- "welcome": {
691
- "title": "Getting Started Setup Wizard",
692
- "desc": "An introduction to this security plugin, helping you get setup and started quickly with the core features.",
693
- "min_user_permissions": "manage_options",
694
- "steps": {
695
- "welcome": {
696
- "security_admin": false,
697
- "title": "Welcome"
698
- },
699
- "ip_detect": {
700
- "title": "IP Detection"
701
- },
702
- "admin_access_restriction": {
703
- "title": "Security Admin"
704
- },
705
- "audit_trail": {
706
- "title": "Activity Log"
707
- },
708
- "ips": {
709
- "title": "IP Blacklist"
710
- },
711
- "login_protect": {
712
- "title": "Login Protection"
713
- },
714
- "comments_filter": {
715
- "title": "Comment SPAM"
716
- },
717
- "plugin_badge": {
718
- "title": "Security Badge"
719
- },
720
- "plugin_telemetry": {
721
- "title": "Plugin Telemetry"
722
- },
723
- "free_trial": {
724
- "title": "Free Trial"
725
- },
726
- "optin": {
727
- "title": "Join Us!"
728
- },
729
- "thankyou": {
730
- "security_admin": false,
731
- "title": "Thank You!"
732
- }
733
- }
734
- }
735
  }
736
  }
737
  }
82
  "can_dismiss": false,
83
  "type": "warning"
84
  },
 
 
 
 
 
85
  "plugin-mailing-list-signup": {
86
  "id": "plugin-mailing-list-signup",
87
  "min_install_days": 5,
680
  "offense": false,
681
  "stat": false
682
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
  }
684
  }
685
  }
icwp-wpsf.php CHANGED
@@ -3,11 +3,13 @@
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: 16.0.9
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
10
  * Author URI: https://shsec.io/bv
 
 
11
  */
12
 
13
  /**
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: 16.1.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
10
  * Author URI: https://shsec.io/bv
11
+ * Requires at least: 4.7
12
+ * Requires PHP: 7.0
13
  */
14
 
15
  /**
plugin-spec.php CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "16.0.9",
4
  "release_timestamp": 1662984000,
5
- "build": "202209.0702",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
@@ -18,7 +18,7 @@
18
  },
19
  "requirements": {
20
  "php": "7.0",
21
- "wordpress": "3.7",
22
  "mysql": "5.6"
23
  },
24
  "reqs_rest": {
@@ -126,6 +126,9 @@
126
  "datatables-bootstrap"
127
  ]
128
  },
 
 
 
129
  "global-plugin": {},
130
  "plugin": {
131
  "deps": [
@@ -133,10 +136,11 @@
133
  "global-plugin"
134
  ]
135
  },
136
- "shield/wizard": {
137
  "deps": [
138
  "bootstrap",
139
- "global-plugin"
 
140
  ]
141
  },
142
  "jquery/featherlight": {
@@ -261,8 +265,11 @@
261
  },
262
  "lz-string.min": {},
263
  "jquery/fileDownload": {},
264
- "jquery/steps": {
265
- "url": "https://cdnjs.cloudflare.com/ajax/libs/jquery-steps/1.1.0/jquery.steps.min.js"
 
 
 
266
  },
267
  "jquery/featherlight": {
268
  "url": "https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.13/featherlight.min.js"
@@ -381,11 +388,11 @@
381
  ],
382
  "footer": true
383
  },
384
- "shield/wizard": {
385
  "deps": [
386
  "bootstrap",
387
  "global-plugin",
388
- "jquery/steps"
389
  ]
390
  },
391
  "shield/login2fa": {
1
  {
2
  "properties": {
3
+ "version": "16.1.0",
4
  "release_timestamp": 1662984000,
5
+ "build": "202209.1001",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
18
  },
19
  "requirements": {
20
  "php": "7.0",
21
+ "wordpress": "4.7",
22
  "mysql": "5.6"
23
  },
24
  "reqs_rest": {
126
  "datatables-bootstrap"
127
  ]
128
  },
129
+ "jquery/smartwizard": {
130
+ "url": "https://cdn.jsdelivr.net/npm/smartwizard@6/dist/css/smart_wizard_all.min.css"
131
+ },
132
  "global-plugin": {},
133
  "plugin": {
134
  "deps": [
136
  "global-plugin"
137
  ]
138
  },
139
+ "shield/merlin": {
140
  "deps": [
141
  "bootstrap",
142
+ "global-plugin",
143
+ "jquery/smartwizard"
144
  ]
145
  },
146
  "jquery/featherlight": {
265
  },
266
  "lz-string.min": {},
267
  "jquery/fileDownload": {},
268
+ "jquery/smartwizard": {
269
+ "url": "https://cdn.jsdelivr.net/npm/smartwizard@6/dist/js/jquery.smartWizard.min.js",
270
+ "deps": [
271
+ "wp-jquery"
272
+ ]
273
  },
274
  "jquery/featherlight": {
275
  "url": "https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.13/featherlight.min.js"
388
  ],
389
  "footer": true
390
  },
391
+ "shield/merlin": {
392
  "deps": [
393
  "bootstrap",
394
  "global-plugin",
395
+ "jquery/smartwizard"
396
  ]
397
  },
398
  "shield/login2fa": {
plugin.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "16.0.9",
4
  "release_timestamp": 1662984000,
5
- "build": "202209.0702",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
@@ -18,7 +18,7 @@
18
  },
19
  "requirements": {
20
  "php": "7.0",
21
- "wordpress": "3.7",
22
  "mysql": "5.6"
23
  },
24
  "reqs_rest": {
@@ -35,6 +35,11 @@
35
  "php": "7.0",
36
  "wp": "3.7",
37
  "mysql": "5.6"
 
 
 
 
 
38
  }
39
  },
40
  "paths": {
@@ -126,6 +131,9 @@
126
  "datatables-bootstrap"
127
  ]
128
  },
 
 
 
129
  "global-plugin": {},
130
  "plugin": {
131
  "deps": [
@@ -133,10 +141,11 @@
133
  "global-plugin"
134
  ]
135
  },
136
- "shield/wizard": {
137
  "deps": [
138
  "bootstrap",
139
- "global-plugin"
 
140
  ]
141
  },
142
  "jquery/featherlight": {
@@ -261,8 +270,11 @@
261
  },
262
  "lz-string.min": {},
263
  "jquery/fileDownload": {},
264
- "jquery/steps": {
265
- "url": "https://cdnjs.cloudflare.com/ajax/libs/jquery-steps/1.1.0/jquery.steps.min.js"
 
 
 
266
  },
267
  "jquery/featherlight": {
268
  "url": "https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.13/featherlight.min.js"
@@ -381,11 +393,11 @@
381
  ],
382
  "footer": true
383
  },
384
- "shield/wizard": {
385
  "deps": [
386
  "bootstrap",
387
  "global-plugin",
388
- "jquery/steps"
389
  ]
390
  },
391
  "shield/login2fa": {
1
  {
2
  "properties": {
3
+ "version": "16.1.0",
4
  "release_timestamp": 1662984000,
5
+ "build": "202209.1001",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
18
  },
19
  "requirements": {
20
  "php": "7.0",
21
+ "wordpress": "4.7",
22
  "mysql": "5.6"
23
  },
24
  "reqs_rest": {
35
  "php": "7.0",
36
  "wp": "3.7",
37
  "mysql": "5.6"
38
+ },
39
+ "16.0": {
40
+ "php": "7.0",
41
+ "wp": "4.7",
42
+ "mysql": "5.6"
43
  }
44
  },
45
  "paths": {
131
  "datatables-bootstrap"
132
  ]
133
  },
134
+ "jquery/smartwizard": {
135
+ "url": "https://cdn.jsdelivr.net/npm/smartwizard@6/dist/css/smart_wizard_all.min.css"
136
+ },
137
  "global-plugin": {},
138
  "plugin": {
139
  "deps": [
141
  "global-plugin"
142
  ]
143
  },
144
+ "shield/merlin": {
145
  "deps": [
146
  "bootstrap",
147
+ "global-plugin",
148
+ "jquery/smartwizard"
149
  ]
150
  },
151
  "jquery/featherlight": {
270
  },
271
  "lz-string.min": {},
272
  "jquery/fileDownload": {},
273
+ "jquery/smartwizard": {
274
+ "url": "https://cdn.jsdelivr.net/npm/smartwizard@6/dist/js/jquery.smartWizard.min.js",
275
+ "deps": [
276
+ "wp-jquery"
277
+ ]
278
  },
279
  "jquery/featherlight": {
280
  "url": "https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.13/featherlight.min.js"
393
  ],
394
  "footer": true
395
  },
396
+ "shield/merlin": {
397
  "deps": [
398
  "bootstrap",
399
  "global-plugin",
400
+ "jquery/smartwizard"
401
  ]
402
  },
403
  "shield/login2fa": {
readme.txt CHANGED
@@ -4,13 +4,13 @@ Donate link: https://shsec.io/bw
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
  Tags: limit login, malware scan, firewall, two factor authentication, login protection
7
- Requires at least: 3.7
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 6.0
11
- Stable tag: 16.0.9
12
 
13
- Bad Bots Are Your #1 Security Risk. Stop playing whack-a-mole with malware and vulnerabilities. Discover the security-before-marketing advantage.
14
 
15
  == Description ==
16
 
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
  Tags: limit login, malware scan, firewall, two factor authentication, login protection
7
+ Requires at least: 4.7
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 6.0
11
+ Stable tag: 16.1.0
12
 
13
+ Bad Bots Are Your #1 Security Risk. Stop playing whack-a-mole with malware and vulnerabilities. Discover the advantage of putting real security before marketing.
14
 
15
  == Description ==
16
 
resources/css/plugin.css CHANGED
@@ -896,8 +896,23 @@ body.folded #FooterBannerGoPro {
896
  #odp-PageContainer .card.progress-meter {
897
  box-shadow: 1px 1px 2px rgb(0 0 0 / 20%);
898
  background: rgb(253 253 253 / 45%);
899
- border-radius: 24px;
900
- border: 1px solid rgb(177 216 178);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
901
  }
902
  .card.progress-meter .card-header {
903
  text-align: center;
896
  #odp-PageContainer .card.progress-meter {
897
  box-shadow: 1px 1px 2px rgb(0 0 0 / 20%);
898
  background: rgb(253 253 253 / 45%);
899
+ border-radius: 6px;
900
+ border: 1px solid white;
901
+ }
902
+ #odp-PageContainer .card.progress-meter.progress-meter-integrity {
903
+ box-shadow: none;
904
+ background: transparent !important;
905
+ border-radius: 0;
906
+ border: 1px solid transparent !important;
907
+ }
908
+ #odp-PageContainer .card.progress-meter.meter-success {
909
+ background: rgba(249, 255, 246, 0.2);
910
+ }
911
+ #odp-PageContainer .card.progress-meter.meter-warning {
912
+ background: rgba(255, 247, 240, 0.4);
913
+ }
914
+ #odp-PageContainer .card.progress-meter.meter-critical {
915
+ background: rgba(255, 246, 246, 0.4);
916
  }
917
  .card.progress-meter .card-header {
918
  text-align: center;
resources/css/shield/merlin.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --sw-border-color: #eeeeee;
3
+ --sw-toolbar-btn-color: #ffffff;
4
+ --sw-toolbar-btn-background-color: #4aa938;
5
+ --sw-anchor-default-primary-color: #f8f9fa;
6
+ --sw-anchor-default-secondary-color: #e7e7e7;
7
+ --sw-anchor-active-primary-color: #5aaf51;
8
+ --sw-anchor-active-secondary-color: #ffffff;
9
+ --sw-anchor-done-primary-color: #abc0ab;
10
+ --sw-anchor-done-secondary-color: #fefefe;
11
+ --sw-anchor-disabled-primary-color: #f8f9fa;
12
+ --sw-anchor-disabled-secondary-color: #dbe0e5;
13
+ --sw-anchor-error-primary-color: #dc3545;
14
+ --sw-anchor-error-secondary-color: #ffffff;
15
+ --sw-anchor-warning-primary-color: #ffc107;
16
+ --sw-anchor-warning-secondary-color: #ffffff;
17
+ --sw-progress-color: #3fad41;
18
+ --sw-progress-background-color: #f8f9fa;
19
+ --sw-loader-color: #59a84d;
20
+ --sw-loader-background-color: #f8f9fa;
21
+ --sw-loader-background-wrapper-color: rgba(255, 255, 255, 0.7);
22
+ }
23
+ .sw .list-group{
24
+ --bs-list-group-bg: transparent;
25
+ }
26
+ .sw h4 {
27
+ }
28
+ .sw li,
29
+ .sw p {
30
+ font-size: 14px;
31
+ }
32
+
33
+ .sw .vimeo-feather {
34
+ box-shadow: 2px 2px 5px rgb(0 0 0 / 20%);
35
+ }
36
+ .sw input[name=offenses] {
37
+ width: 60px;
38
+ }
resources/css/shield/wizard.css DELETED
@@ -1,542 +0,0 @@
1
- html {
2
- overflow-y: scroll;
3
- }
4
- body {
5
- padding-bottom: 200px;
6
- overflow-y: visible;
7
- }
8
- body.wait {
9
- cursor: wait !important;
10
- }
11
- .wizard > .content {
12
- background: #ffffff;
13
- box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
14
- }
15
- .wizard > .steps .current a {
16
- text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.1);
17
- }
18
- .wizard.vertical > .steps {
19
- width: 20%; /** from 30 **/
20
- }
21
- /*
22
- Common
23
- */
24
- .wizard,
25
- .tabcontrol {
26
- display: block;
27
- width: 100%;
28
- overflow: hidden;
29
- }
30
- .wizard a,
31
- .tabcontrol a {
32
- outline: 0;
33
- }
34
- .wizard ul,
35
- .tabcontrol ul {
36
- list-style: none;
37
- padding: 0;
38
- margin: 0;
39
- }
40
- .wizard ul > li,
41
- .tabcontrol ul > li {
42
- display: block;
43
- padding: 0;
44
- }
45
- /* Accessibility */
46
- .wizard > .steps .current-info,
47
- .tabcontrol > .steps .current-info {
48
- position: absolute;
49
- left: -999em;
50
- }
51
- .wizard > .content > .title,
52
- .tabcontrol > .content > .title {
53
- position: absolute;
54
- left: -999em;
55
- }
56
- /*
57
- Wizard
58
- */
59
- .wizard > .steps {
60
- position: relative;
61
- display: block;
62
- width: 100%;
63
- }
64
- .wizard.vertical > .steps {
65
- display: inline;
66
- float: left;
67
- width: 30%;
68
- }
69
- .wizard > .steps .number {
70
- font-size: 1.429em;
71
- }
72
- .wizard > .steps > ul > li {
73
- width: 25%;
74
- }
75
- .wizard > .steps > ul > li,
76
- .wizard > .actions > ul > li {
77
- float: left;
78
- }
79
- .wizard.vertical > .steps > ul > li {
80
- float: none;
81
- width: 100%;
82
- }
83
- .wizard > .steps a,
84
- .wizard > .steps a:hover,
85
- .wizard > .steps a:active {
86
- display: block;
87
- width: auto;
88
- margin: 0 0.5em 0.5em;
89
- padding: 1em 1em;
90
- text-decoration: none;
91
- -webkit-border-radius: 5px;
92
- -moz-border-radius: 5px;
93
- border-radius: 5px;
94
- }
95
- .wizard > .steps .disabled a,
96
- .wizard > .steps .disabled a:hover,
97
- .wizard > .steps .disabled a:active {
98
- background: #eeeeee;
99
- color: #aaaaaa;
100
- cursor: default;
101
- }
102
- .wizard > .steps .current a,
103
- .wizard > .steps .current a:hover,
104
- .wizard > .steps .current a:active {
105
- background: rgba(69, 119, 0, 1);
106
- color: #ffffff;
107
- cursor: default;
108
- }
109
- .wizard > .steps .done a,
110
- .wizard > .steps .done a:hover,
111
- .wizard > .steps .done a:active {
112
- background: rgba(69, 119, 0, 0.5);
113
- color: #ffffff;
114
- }
115
- .wizard > .steps .error a,
116
- .wizard > .steps .error a:hover,
117
- .wizard > .steps .error a:active {
118
- background: #ff3111;
119
- color: #ffffff;
120
- }
121
- .wizard > .content {
122
- background: transparent;
123
- display: block;
124
- margin: 0.5em;
125
- min-height: 35em;
126
- overflow: hidden;
127
- position: relative;
128
- width: auto;
129
- -webkit-border-radius: 5px;
130
- -moz-border-radius: 5px;
131
- border-radius: 5px;
132
- border: 1px solid transparent;
133
- }
134
- .wizard.vertical > .content {
135
- display: inline;
136
- float: left;
137
- margin: 0 2.5% 0.5em 2.5%;
138
- width: 65%;
139
- }
140
- .wizard > .content > .body {
141
- float: left;
142
- position: absolute;
143
- width: 95%;
144
- height: 95%;
145
- padding: 2.5%;
146
- }
147
- .wizard > .content > .body ul {
148
- list-style: disc;
149
- }
150
- .wizard > .content > .body ul > li {
151
- display: list-item;
152
- }
153
- .wizard > .content > .body > iframe {
154
- border: 0 none;
155
- width: 100%;
156
- height: 100%;
157
- }
158
- .wizard > .content > .body input {
159
- /*display: block;*/
160
- /*border: 1px solid #ccc;*/
161
- }
162
- .wizard > .content > .body input[type="checkbox"] {
163
- display: inline-block;
164
- }
165
- .wizard > .content > .body input.error {
166
- background: rgb(251, 227, 228);
167
- border: 1px solid #fbc2c4;
168
- color: #8a1f11;
169
- }
170
- .wizard > .content > .body label {
171
- /*display: inline-block;*/
172
- /*margin-bottom: 0.5em;*/
173
- }
174
- .wizard > .content > .body label.error {
175
- color: #8a1f11;
176
- display: inline-block;
177
- margin-left: 1.5em;
178
- }
179
- .wizard > .actions {
180
- position: relative;
181
- display: block;
182
- text-align: right;
183
- width: 100%;
184
- }
185
- .wizard.vertical > .actions {
186
- display: inline;
187
- float: right;
188
- margin: 0 2.5%;
189
- width: 95%;
190
- }
191
- .wizard > .actions > ul {
192
- display: inline-block;
193
- text-align: right;
194
- }
195
- .wizard > .actions > ul > li {
196
- margin: 0 0.5em;
197
- }
198
- .wizard.vertical > .actions > ul > li {
199
- margin: 0 0 0 1em;
200
- }
201
- .wizard > .actions a,
202
- .wizard > .actions a:hover,
203
- .wizard > .actions a:active {
204
- background: rgba(69, 119, 0, 1);
205
- color: #ffffff;
206
- display: block;
207
- padding: 0.5em 1em;
208
- text-decoration: none;
209
- -webkit-border-radius: 5px;
210
- -moz-border-radius: 5px;
211
- border-radius: 5px;
212
- }
213
- .wizard > .actions .disabled a,
214
- .wizard > .actions .disabled a:hover,
215
- .wizard > .actions .disabled a:active {
216
- background: #eeeeee;
217
- color: #aaaaaa;
218
- }
219
- .wizard > .loading {
220
- }
221
- .wizard > .loading .spinner {
222
- }
223
- /*
224
- Tabcontrol
225
- */
226
- .tabcontrol > .steps {
227
- position: relative;
228
- display: block;
229
- width: 100%;
230
- }
231
- .tabcontrol > .steps > ul {
232
- position: relative;
233
- margin: 6px 0 0 0;
234
- top: 1px;
235
- z-index: 1;
236
- }
237
- .tabcontrol > .steps > ul > li {
238
- float: left;
239
- margin: 5px 2px 0 0;
240
- padding: 1px;
241
- -webkit-border-top-left-radius: 5px;
242
- -webkit-border-top-right-radius: 5px;
243
- -moz-border-radius-topleft: 5px;
244
- -moz-border-radius-topright: 5px;
245
- border-top-left-radius: 5px;
246
- border-top-right-radius: 5px;
247
- }
248
- .tabcontrol > .steps > ul > li:hover {
249
- background: #edecec;
250
- border: 1px solid #bbbbbb;
251
- padding: 0;
252
- }
253
- .tabcontrol > .steps > ul > li.current {
254
- background: #ffffff;
255
- border: 1px solid #bbbbbb;
256
- border-bottom: 0 none;
257
- padding: 0 0 1px 0;
258
- margin-top: 0;
259
- }
260
- .tabcontrol > .steps > ul > li > a {
261
- color: #5f5f5f;
262
- display: inline-block;
263
- border: 0 none;
264
- margin: 0;
265
- padding: 10px 30px;
266
- text-decoration: none;
267
- }
268
- .tabcontrol > .steps > ul > li > a:hover {
269
- text-decoration: none;
270
- }
271
- .tabcontrol > .steps > ul > li.current > a {
272
- padding: 15px 30px 10px 30px;
273
- }
274
- .tabcontrol > .content {
275
- position: relative;
276
- display: inline-block;
277
- width: 100%;
278
- height: 35em;
279
- overflow: hidden;
280
- border-top: 1px solid #bbbbbb;
281
- padding-top: 20px;
282
- }
283
- .tabcontrol > .content > .body {
284
- float: left;
285
- position: absolute;
286
- width: 95%;
287
- height: 95%;
288
- padding: 2.5%;
289
- }
290
- .tabcontrol > .content > .body ul {
291
- list-style: disc !important;
292
- }
293
- .tabcontrol > .content > .body ul > li {
294
- display: list-item;
295
- }
296
- .wizard.vertical > .content {
297
- width: 75%; /** from 65 **/
298
- }
299
- .wizard > .content > .body {
300
- height: auto;
301
- position: relative;
302
- padding: 0;
303
- width: 100%
304
- }
305
- .wizard > .content > .body .slide-header {
306
- padding: 3% 3% 0 3%;
307
- }
308
- .wizard > .content > .body .slide-header .btn-block {
309
- margin-bottom: -1px;
310
- }
311
- .wizard > .content > .body .slide-header hr {
312
- margin: 15px 0;
313
- }
314
- .wizard > .content > .body .slide-body {
315
- padding: 0 6% 0 6%;
316
- }
317
- .wizard > .content > .body .slide-footer {
318
- padding: 0 6% 3% 6%;
319
- }
320
- .wizard.vertical > .actions {
321
- margin-bottom: 20px;
322
- }
323
- .wizard h3 {
324
- margin-bottom: 20px;
325
- }
326
- .wizard h4 {
327
- font-size: 2rem;
328
- margin: 2rem 0;
329
- }
330
- .wizard li,
331
- .wizard p {
332
- font-size: 16px;
333
- margin-bottom: 1.2rem;
334
- }
335
- .wizard .body ol,
336
- .wizard .body ul {
337
- margin-bottom: 20px;
338
- padding-left: 20px;
339
- }
340
- .wizard .body ul {
341
- list-style: square inside none;
342
- }
343
- .wizard p.wizard-response {
344
- /*padding: 10px 15px;*/
345
- }
346
- .wizard .slide-body img {
347
- }
348
- .wizard .slide-body .media {
349
- margin-top: 25px
350
- }
351
- .wizard .slide-body .media-object {
352
- border: 1px solid #888888;
353
- height: 64px;
354
- width: 64px;
355
- }
356
- .wizard .indent_slight {
357
- margin-left: 26px;
358
- }
359
- .wizard_slot {
360
- border: 1px solid #dddddd;
361
- border-radius: 3px;
362
- margin-top: 30px;
363
- padding: 0 20px 20px;
364
- }
365
- .wizard_slot:hover {
366
- background-color: #ffffff;
367
- }
368
- .wizard form label {
369
- }
370
- .wizard form input[type="radio"]:checked + span {
371
- font-weight: bolder;
372
- letter-spacing: -0.4px;
373
- }
374
- .wizard form .form-check-label {
375
- margin-bottom: 10px;
376
- }
377
- .wizard form .form-check-inline .form-check-label {
378
- margin-bottom: 0;
379
- }
380
- .shield-go-pro {
381
- min-width: 200px;
382
- display: block;
383
- margin: 5px auto 20px;
384
- background-color: #1e7e34;
385
- border-color: #1c7430;
386
- }
387
- #GoProBtn {
388
- width: 128px;
389
- display: block;
390
- margin: 5px auto 20px;
391
- }
392
- #FooterWizardBanner {
393
- position: fixed;
394
- bottom: -50px;
395
- height: 100px;
396
- width: 100%;
397
- }
398
- #WizardTop {
399
- height: 40px;
400
- background-color: #fafafa;
401
- background: linear-gradient(to top, rgba(250, 250, 250, 0.95), rgba(250, 250, 250, 0.7));
402
- }
403
- #WizardBanner {
404
- height: 100px;
405
- background-color: #eaffea;
406
- border-top: 1px solid #bbbbbb;
407
- padding-top: 10px;
408
- text-align: center;
409
- word-break: keep-all;
410
- white-space: nowrap;
411
- }
412
- #WizardBanner p {
413
- margin: 0;
414
- line-height: 20px;
415
- text-align: left;
416
- }
417
- #MoreDetails {
418
- margin-top: 12px;
419
- }
420
- .more_details {
421
- margin-bottom: 12px;
422
- }
423
- .more_details:hover {
424
- cursor: pointer;
425
- }
426
- .more_details_body {
427
- margin-bottom: 12px;
428
- }
429
- .scan-results-accordian {
430
- }
431
- .scan-results-accordian .card {
432
- margin-bottom: 24px;
433
- }
434
- .scan-results-accordian .card-header {
435
- padding: .5rem 1.25rem;
436
- }
437
- .scan-results-accordian .card-header button:hover,
438
- .scan-results-accordian .card-header button {
439
- color: #f1f1f1
440
- }
441
- .embed-vimeo {
442
- margin-bottom: 20px;
443
- border-radius: 3px;
444
- box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
445
- }
446
- span.shield-progress-bar {
447
- position: relative;
448
- top: 8px;
449
- width: 130%;
450
- background-color: #2271b1;
451
- height: 2px;
452
- left: 75%;
453
- }
454
- /* override jquery.steps.css */
455
- .wizard > .actions a,
456
- .wizard > .actions a:hover,
457
- .wizard > .actions a:active,
458
- .wizard > .steps .current a,
459
- .wizard > .steps .current a:hover,
460
- .wizard > .steps .current a:active,
461
- .wizard > .steps .disabled a, .wizard > .steps .disabled a:hover, .wizard > .steps .disabled a:active,
462
- .wizard > .steps .done a, .wizard > .steps .done a:hover, .wizard > .steps .done a:active {
463
- background: none !important;
464
- }
465
- .wizard > .steps > ul > li {
466
- }
467
- div.steps ul {
468
- display: flex;
469
- flex-direction: row;
470
- flex-wrap: nowrap;
471
- justify-content: space-evenly;
472
- }
473
- div.step {
474
- display: flex;
475
- align-content: center;
476
- justify-content: space-between;
477
- flex-direction: column;
478
- flex-wrap: nowrap;
479
- align-items: center;
480
- }
481
- div.step-number {
482
- width: 15px;
483
- height: 15px;
484
- border-radius: 100%;
485
- }
486
- li div.step-number {
487
- background-color: rgba(34, 113, 177, 1);
488
- z-index: 5;
489
- }
490
- li div.step-title {
491
- color: rgba(34, 113, 177, 1);
492
- text-align: center;
493
- }
494
- li.done div.step-number {
495
- background-color: #95c125;
496
- }
497
- li.done div.step-title {
498
- color: #95c125;
499
- }
500
- li.disabled div.step-number {
501
- background-color: #aaaaaa;
502
- }
503
- li.disabled div.step-title {
504
- color: #aaaaaa;
505
- }
506
- .wizard > .content {
507
- -webkit-border-radius: 0;
508
- border-radius: 0;
509
- margin: 0;
510
- }
511
- li.disabled span.shield-progress-bar {
512
- background-color: #aaaaaa;
513
- }
514
- div.steps ul li:last-child span.shield-progress-bar {
515
- display: none;
516
- }
517
- /* override bootstrap */
518
- a, a:not([href]):not([class]) {
519
- color: #2271b1;
520
- text-decoration: underline;
521
- }
522
- a:hover, a:visited {
523
- color: #135e96;
524
- }
525
- .vimeo-feather img {
526
- padding: 3px;
527
- border: 1px solid #008000;
528
- background: white;
529
- }
530
- .vimeo-feather img {
531
- width: 400px;
532
- }
533
- .button > svg {
534
- width: 24px;
535
- height: 24px;
536
- margin-right: 3px;
537
- }
538
-
539
- .wp-core-ui button.wizard-button-go-back {
540
- border: 0 none;
541
- background: transparent;
542
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
resources/images/bootstrap/box-arrow-left.svg ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-left" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M6 12.5a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v2a.5.5 0 0 1-1 0v-2A1.5 1.5 0 0 1 6.5 2h8A1.5 1.5 0 0 1 16 3.5v9a1.5 1.5 0 0 1-1.5 1.5h-8A1.5 1.5 0 0 1 5 12.5v-2a.5.5 0 0 1 1 0v2z"/>
3
+ <path fill-rule="evenodd" d="M.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L1.707 7.5H10.5a.5.5 0 0 1 0 1H1.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"/>
4
+ </svg>
resources/images/bootstrap/magic.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-magic" viewBox="0 0 16 16">
2
+ <path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0v1.829Zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707L14 2.707ZM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707L7.293 4Zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1h1.829Zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1h1.829ZM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707L13.293 10ZM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0v1.829Zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0L8.354 9.06Z"/>
3
+ </svg>
resources/js/plugin.js CHANGED
@@ -77,12 +77,15 @@ var iCWP_WPSF_Toaster = new function () {
77
  let toasterContainer;
78
 
79
  this.showMessage = function ( msg, success ) {
80
- let $toaster = jQuery( toasterContainer )
 
 
 
 
81
  let $toastBody = jQuery( '.toast-body', $toaster );
82
  $toastBody.html( '' );
83
 
84
  jQuery( '<span></span>' ).html( msg )
85
- .addClass( success ? 'text-dark' : 'text-danger' )
86
  .appendTo( $toastBody );
87
 
88
  $toaster.css( 'z-index', 100000000 );
@@ -124,7 +127,7 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
124
  * This works around mod_security rules that even unpack b64 encoded params and look
125
  * for patterns within them.
126
  */
127
- var sendForm = function ( useCompression = false ) {
128
 
129
  let formData = $form.serialize();
130
  if ( useCompression ) {
@@ -137,7 +140,7 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
137
  return false;
138
  }
139
 
140
- let reqs = jQuery.extend(
141
  workingData.ajax.mod_options_save,
142
  {
143
  'form_params': Base64.encode( formData ),
@@ -149,15 +152,15 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
149
  iCWP_WPSF_BodyOverlay.show();
150
  jQuery.ajax(
151
  {
152
- type: "POST",
153
  url: ajaxurl,
154
- data: reqs,
155
- dataType: "text",
156
  success: function ( raw ) {
157
  handleResponse( raw );
158
  },
159
  }
160
- ).fail( function () {
161
  if ( useCompression ) {
162
  handleResponse( raw );
163
  }
@@ -194,13 +197,13 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
194
  }, 1000 );
195
  };
196
 
197
- let submitOptionsForm = function ( event ) {
 
198
 
199
  if ( requestRunning ) {
200
  return false;
201
  }
202
  requestRunning = true;
203
- event.preventDefault();
204
 
205
  $form = jQuery( this );
206
 
@@ -220,6 +223,8 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
220
  if ( $passwordsReady ) {
221
  sendForm( false );
222
  }
 
 
223
  };
224
 
225
  this.initialise = function ( data ) {
@@ -338,7 +343,7 @@ jQuery.fn.icwpWpsfAjaxTable = function ( aOptions ) {
338
  if ( typeof icwp_wpsf_vars_plugin !== 'undefined' ) {
339
 
340
  jQuery( document ).ready( function () {
341
- jQuery( document ).on( 'click', 'a.shield_file_download, a.shield_file_download ', function ( evt ) {
342
  evt.preventDefault();
343
  /** Cache busting **/
344
  let url = jQuery( this ).attr( 'href' ) + '&rand='
77
  let toasterContainer;
78
 
79
  this.showMessage = function ( msg, success ) {
80
+ let $toaster = jQuery( toasterContainer );
81
+
82
+ $toaster.removeClass( 'text-bg-success text-bg-warning' );
83
+ $toaster.addClass( success ? 'text-bg-success' : 'text-bg-warning' );
84
+
85
  let $toastBody = jQuery( '.toast-body', $toaster );
86
  $toastBody.html( '' );
87
 
88
  jQuery( '<span></span>' ).html( msg )
 
89
  .appendTo( $toastBody );
90
 
91
  $toaster.css( 'z-index', 100000000 );
127
  * This works around mod_security rules that even unpack b64 encoded params and look
128
  * for patterns within them.
129
  */
130
+ let sendForm = function ( useCompression = false ) {
131
 
132
  let formData = $form.serialize();
133
  if ( useCompression ) {
140
  return false;
141
  }
142
 
143
+ let reqData = jQuery.extend(
144
  workingData.ajax.mod_options_save,
145
  {
146
  'form_params': Base64.encode( formData ),
152
  iCWP_WPSF_BodyOverlay.show();
153
  jQuery.ajax(
154
  {
155
+ type: 'POST',
156
  url: ajaxurl,
157
+ data: reqData,
158
+ dataType: 'text',
159
  success: function ( raw ) {
160
  handleResponse( raw );
161
  },
162
  }
163
+ ).fail( function ( jqXHR, textStatus ) {
164
  if ( useCompression ) {
165
  handleResponse( raw );
166
  }
197
  }, 1000 );
198
  };
199
 
200
+ let submitOptionsForm = function ( evt ) {
201
+ evt.preventDefault();
202
 
203
  if ( requestRunning ) {
204
  return false;
205
  }
206
  requestRunning = true;
 
207
 
208
  $form = jQuery( this );
209
 
223
  if ( $passwordsReady ) {
224
  sendForm( false );
225
  }
226
+
227
+ return false;
228
  };
229
 
230
  this.initialise = function ( data ) {
343
  if ( typeof icwp_wpsf_vars_plugin !== 'undefined' ) {
344
 
345
  jQuery( document ).ready( function () {
346
+ jQuery( document ).on( 'click', 'a.shield_file_download', function ( evt ) {
347
  evt.preventDefault();
348
  /** Cache busting **/
349
  let url = jQuery( this ).attr( 'href' ) + '&rand='
resources/js/shield/ipanalyse.js CHANGED
@@ -70,8 +70,8 @@ jQuery.fn.icwpWpsfIpRules = function ( options ) {
70
  } );
71
 
72
  document.addEventListener( 'submit', function ( evt ) {
73
- evt.preventDefault();
74
  if ( typeof evt.target.id !== 'undefined' && evt.target.id === ipRuleAddFormSelector ) {
 
75
 
76
  let reqData = jQuery.extend(
77
  opts[ 'ajax' ][ 'ip_rule_add_form' ],
@@ -102,9 +102,8 @@ jQuery.fn.icwpWpsfIpRules = function ( options ) {
102
  iCWP_WPSF_BodyOverlay.hide();
103
  }
104
  );
 
105
  }
106
-
107
- return false;
108
  } );
109
  };
110
 
70
  } );
71
 
72
  document.addEventListener( 'submit', function ( evt ) {
 
73
  if ( typeof evt.target.id !== 'undefined' && evt.target.id === ipRuleAddFormSelector ) {
74
+ evt.preventDefault();
75
 
76
  let reqData = jQuery.extend(
77
  opts[ 'ajax' ][ 'ip_rule_add_form' ],
102
  iCWP_WPSF_BodyOverlay.hide();
103
  }
104
  );
105
+ return false;
106
  }
 
 
107
  } );
108
  };
109
 
resources/js/shield/merlin.js ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ( $ ) {
2
+ let $merlinContainer;
3
+ let $merlin;
4
+
5
+ $( document ).ready( function () {
6
+ init();
7
+ } );
8
+
9
+ function init() {
10
+ $merlinContainer = $( '#merlin' );
11
+ $merlin = $merlinContainer.smartWizard( merlin.vars.smartwizard_cfg );
12
+
13
+ $( 'form.merlin-form.ajax-form', $merlinContainer ).on( 'submit', runSettingUpdate );
14
+
15
+ $merlinContainer.on( 'click', 'a.skip-step', function () {
16
+ $merlin.smartWizard( 'next' );
17
+ } );
18
+ $( document ).on( 'shield-merlin_save', function ( evt, resp ) {
19
+ if ( resp.success ) {
20
+ $merlin.smartWizard( 'next' );
21
+ }
22
+ iCWP_WPSF_BodyOverlay.hide();
23
+ } );
24
+ }
25
+
26
+ let runSettingUpdate = function ( evt ) {
27
+ evt.preventDefault();
28
+ merlin.ajax.merlin_action.form_params = $( evt.target ).serialize();
29
+ iCWP_WPSF_StandardAjax.send_ajax_req( merlin.ajax.merlin_action, false, 'merlin_save' );
30
+ return false;
31
+ };
32
+
33
+ })( jQuery );
resources/js/shield/wizard.js DELETED
File without changes
src/lib/src/Blocks/RenderBlockPages/RenderBlockAuthorFishing.php CHANGED
@@ -2,10 +2,6 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Blocks\RenderBlockPages;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\QueryRemainingOffenses;
7
- use FernleafSystems\Wordpress\Services\Services;
8
-
9
  class RenderBlockAuthorFishing extends BaseBlockPage {
10
 
11
  protected function getPageSpecificData() :array {
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Blocks\RenderBlockPages;
4
 
 
 
 
 
5
  class RenderBlockAuthorFishing extends BaseBlockPage {
6
 
7
  protected function getPageSpecificData() :array {
src/lib/src/Blocks/RenderBlockPages/RenderBlockFirewall.php CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Blocks\RenderBlockPages;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\QueryRemainingOffenses;
7
- use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class RenderBlockFirewall extends BaseBlockPage {
10
 
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\QueryRemainingOffenses;
 
7
 
8
  class RenderBlockFirewall extends BaseBlockPage {
9
 
src/lib/src/Modules/AuditTrail/Lib/LogTable/BuildAuditTableData.php CHANGED
@@ -5,10 +5,9 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\LogTabl
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\DB\LoadLogs;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\DB\LogRecord;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\AuditMessageBuilder;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\AuditTrail\ForAuditTrail;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseBuildTableData;
10
  use FernleafSystems\Wordpress\Services\Services;
11
- use FernleafSystems\Wordpress\Services\Utilities\Net\IpID;
12
 
13
  class BuildAuditTableData extends BaseBuildTableData {
14
 
@@ -113,7 +112,7 @@ class BuildAuditTableData extends BaseBuildTableData {
113
  $loader->order_dir = $this->getOrderDirection();
114
  $loader->order_by = $this->getOrderBy();
115
  return array_filter(
116
- $loader->run( true ),
117
  function ( $logRecord ) {
118
  return $this->getCon()->loadEventsService()->eventExists( $logRecord->event_slug );
119
  }
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\DB\LoadLogs;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\DB\LogRecord;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\AuditMessageBuilder;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\ForAuditTrail;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseBuildTableData;
10
  use FernleafSystems\Wordpress\Services\Services;
 
11
 
12
  class BuildAuditTableData extends BaseBuildTableData {
13
 
112
  $loader->order_dir = $this->getOrderDirection();
113
  $loader->order_by = $this->getOrderBy();
114
  return array_filter(
115
+ $loader->run(),
116
  function ( $logRecord ) {
117
  return $this->getCon()->loadEventsService()->eventExists( $logRecord->event_slug );
118
  }
src/lib/src/Modules/AuditTrail/UI.php CHANGED
@@ -4,7 +4,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\AuditTrail\ForAuditTrail;
8
 
9
  class UI extends BaseShield\UI {
10
 
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\ForAuditTrail;
8
 
9
  class UI extends BaseShield\UI {
10
 
src/lib/src/Modules/Base/Lib/Request/FormParams.php CHANGED
@@ -35,10 +35,11 @@ class FormParams {
35
 
36
  case 'none':
37
  default:
 
38
  break;
39
  }
40
 
41
- parse_str( $raw, $formParams );
42
  }
43
 
44
  return is_array( $formParams ) ? $formParams : [];
35
 
36
  case 'none':
37
  default:
38
+ $raw = '';
39
  break;
40
  }
41
 
42
+ parse_str( (string)$raw, $formParams );
43
  }
44
 
45
  return is_array( $formParams ) ? $formParams : [];
src/lib/src/Modules/Base/ModCon.php CHANGED
@@ -30,11 +30,6 @@ abstract class ModCon extends DynPropertiesClass {
30
  */
31
  private $oProcessor;
32
 
33
- /**
34
- * @var \ICWP_WPSF_Wizard_Base
35
- */
36
- private $oWizard;
37
-
38
  /**
39
  * @var Shield\Modules\Base\Reporting
40
  */
@@ -318,8 +313,6 @@ abstract class ModCon extends DynPropertiesClass {
318
  }
319
  }
320
 
321
- $this->runWizards();
322
-
323
  // GDPR
324
  if ( $this->isPremium() ) {
325
  add_filter( $con->prefix( 'wpPrivacyExport' ), [ $this, 'onWpPrivacyExport' ], 10, 3 );
@@ -368,20 +361,6 @@ abstract class ModCon extends DynPropertiesClass {
368
  return $this->oProcessor;
369
  }
370
 
371
- /**
372
- * Override this and adapt per feature
373
- * @return string
374
- */
375
- protected function getWizardClassName() {
376
- return implode( '_',
377
- [
378
- strtoupper( $this->getCon()->getPluginPrefix( '_' ) ),
379
- 'Wizard',
380
- str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getSlug() ) ) )
381
- ]
382
- );
383
- }
384
-
385
  public function onPluginShutdown() {
386
  if ( !$this->getCon()->plugin_deleting ) {
387
  $this->saveModOptions();
@@ -667,21 +646,6 @@ abstract class ModCon extends DynPropertiesClass {
667
  $this->getOptions()->setOpt( 'ui_track', $UI->getRawData() );
668
  }
669
 
670
- /**
671
- * @return \ICWP_WPSF_Wizard_Base|null
672
- */
673
- public function getWizardHandler() {
674
- if ( !isset( $this->oWizard ) ) {
675
- $class = $this->getWizardClassName();
676
- if ( !class_exists( $class ) ) {
677
- return null;
678
- }
679
- $this->oWizard = new $class();
680
- $this->oWizard->setMod( $this );
681
- }
682
- return $this->oWizard;
683
- }
684
-
685
  /**
686
  * @return $this
687
  */
@@ -778,15 +742,6 @@ abstract class ModCon extends DynPropertiesClass {
778
  return $this->getCon()->isPremiumActive();
779
  }
780
 
781
- protected function runWizards() {
782
- if ( $this->isWizardPage() && $this->hasWizard() ) {
783
- $wiz = $this->getWizardHandler();
784
- if ( $wiz instanceof \ICWP_WPSF_Wizard_Base ) {
785
- $wiz->init();
786
- }
787
- }
788
- }
789
-
790
  public function isThisModulePage() :bool {
791
  return $this->getCon()->isModulePage()
792
  && Services::Request()->query( 'page' ) == $this->getModSlug();
@@ -796,15 +751,6 @@ abstract class ModCon extends DynPropertiesClass {
796
  return Services::Request()->query( 'page' ) == $this->getCon()->getModule_Insights()->getModSlug();
797
  }
798
 
799
- public function isPage_InsightsThisModule() :bool {
800
- return $this->isPage_Insights()
801
- && Services::Request()->query( 'inav' ) == $this->getSlug();
802
- }
803
-
804
- protected function isWizardPage() :bool {
805
- return $this->getCon()->getShieldAction() == 'wizard' && $this->isThisModulePage();
806
- }
807
-
808
  protected function buildContextualHelp() {
809
  if ( !function_exists( 'get_current_screen' ) ) {
810
  require_once( ABSPATH.'wp-admin/includes/screen.php' );
@@ -825,62 +771,6 @@ abstract class ModCon extends DynPropertiesClass {
825
  );
826
  }
827
 
828
- /**
829
- * @uses nonce
830
- */
831
- public function getUrl_Wizard( string $wizardSlug ) :string {
832
- $def = $this->getWizardDefinition( $wizardSlug );
833
- if ( empty( $def[ 'min_user_permissions' ] ) ) { // i.e. no login/minimum perms
834
- $url = Services::WpGeneral()->getHomeUrl();
835
- }
836
- else {
837
- $url = Services::WpGeneral()->getAdminUrl( 'admin.php' );
838
- }
839
-
840
- return add_query_arg(
841
- [
842
- 'page' => $this->getCon()->getModule_Insights()->getModSlug(),
843
- 'inav' => 'wizard',
844
- 'shield_action' => 'wizard',
845
- 'wizard' => $wizardSlug,
846
- 'nonwizard' => wp_create_nonce( 'wizard'.$wizardSlug )
847
- ],
848
- $url
849
- );
850
- }
851
-
852
- /**
853
- * @return string
854
- */
855
- public function getUrl_WizardLanding() {
856
- return $this->getUrl_Wizard( 'landing' );
857
- }
858
-
859
- /**
860
- * @param string $wizardSlug
861
- * @return array
862
- */
863
- public function getWizardDefinition( string $wizardSlug ) {
864
- $def = null;
865
- if ( $this->hasWizardDefinition( $wizardSlug ) ) {
866
- $def = $this->getWizardDefinitions()[ $wizardSlug ];
867
- }
868
- return $def;
869
- }
870
-
871
- public function getWizardDefinitions() :array {
872
- $wiz = $this->getOptions()->getDef( 'wizards' );
873
- return is_array( $wiz ) ? $wiz : [];
874
- }
875
-
876
- public function hasWizard() :bool {
877
- return count( $this->getWizardDefinitions() ) > 0;
878
- }
879
-
880
- public function hasWizardDefinition( string $wizardSlug ) :bool {
881
- return !empty( $this->getWizardDefinitions()[ $wizardSlug ] );
882
- }
883
-
884
  public function getIsShowMarketing() :bool {
885
  return (bool)apply_filters( 'shield/show_marketing', !$this->isPremium() );
886
  }
@@ -1118,4 +1008,52 @@ abstract class ModCon extends DynPropertiesClass {
1118
  public function savePluginOptions() {
1119
  $this->saveModOptions();
1120
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1121
  }
30
  */
31
  private $oProcessor;
32
 
 
 
 
 
 
33
  /**
34
  * @var Shield\Modules\Base\Reporting
35
  */
313
  }
314
  }
315
 
 
 
316
  // GDPR
317
  if ( $this->isPremium() ) {
318
  add_filter( $con->prefix( 'wpPrivacyExport' ), [ $this, 'onWpPrivacyExport' ], 10, 3 );
361
  return $this->oProcessor;
362
  }
363
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
  public function onPluginShutdown() {
365
  if ( !$this->getCon()->plugin_deleting ) {
366
  $this->saveModOptions();
646
  $this->getOptions()->setOpt( 'ui_track', $UI->getRawData() );
647
  }
648
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
  /**
650
  * @return $this
651
  */
742
  return $this->getCon()->isPremiumActive();
743
  }
744
 
 
 
 
 
 
 
 
 
 
745
  public function isThisModulePage() :bool {
746
  return $this->getCon()->isModulePage()
747
  && Services::Request()->query( 'page' ) == $this->getModSlug();
751
  return Services::Request()->query( 'page' ) == $this->getCon()->getModule_Insights()->getModSlug();
752
  }
753
 
 
 
 
 
 
 
 
 
 
754
  protected function buildContextualHelp() {
755
  if ( !function_exists( 'get_current_screen' ) ) {
756
  require_once( ABSPATH.'wp-admin/includes/screen.php' );
771
  );
772
  }
773
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
  public function getIsShowMarketing() :bool {
775
  return (bool)apply_filters( 'shield/show_marketing', !$this->isPremium() );
776
  }
1008
  public function savePluginOptions() {
1009
  $this->saveModOptions();
1010
  }
1011
+
1012
+ /**
1013
+ * @deprecated 16.0
1014
+ * @var \ICWP_WPSF_Wizard_Base
1015
+ */
1016
+ private $oWizard;
1017
+
1018
+ /**
1019
+ * @deprecated 16.0
1020
+ */
1021
+ public function hasWizard() :bool {
1022
+ return false;
1023
+ }
1024
+
1025
+ /**
1026
+ * @deprecated 16.0
1027
+ */
1028
+ public function hasWizardDefinition( string $wizardSlug ) :bool {
1029
+ return false;
1030
+ }
1031
+
1032
+ /**
1033
+ * @deprecated 16.0
1034
+ * @return \ICWP_WPSF_Wizard_Base|null
1035
+ */
1036
+ public function getWizardHandler() {
1037
+ return null;
1038
+ }
1039
+
1040
+ /**
1041
+ * @deprecated 16.0
1042
+ */
1043
+ public function getWizardDefinitions() :array {
1044
+ return [];
1045
+ }
1046
+
1047
+ /**
1048
+ * @deprecated 16.1
1049
+ */
1050
+ protected function runWizards() {
1051
+ }
1052
+
1053
+ /**
1054
+ * @deprecated 16.0
1055
+ */
1056
+ protected function isWizardPage() :bool {
1057
+ return false;
1058
+ }
1059
  }
src/lib/src/Modules/Base/Options.php CHANGED
@@ -421,6 +421,14 @@ class Options {
421
  return $this->getRawData_FullFeatureConfig()[ 'requirements' ] ?? [];
422
  }
423
 
 
 
 
 
 
 
 
 
424
  public function getSelectOptionValueText( string $key ) :string {
425
  $text = '';
426
  foreach ( $this->getOptDefinition( $key )[ 'value_options' ] as $opt ) {
421
  return $this->getRawData_FullFeatureConfig()[ 'requirements' ] ?? [];
422
  }
423
 
424
+ public function getSelectOptionValueKeys( string $key ) :array {
425
+ $keys = [];
426
+ foreach ( $this->getOptDefinition( $key )[ 'value_options' ] as $opt ) {
427
+ $keys[] = $opt[ 'value_key' ];
428
+ }
429
+ return $keys;
430
+ }
431
+
432
  public function getSelectOptionValueText( string $key ) :string {
433
  $text = '';
434
  foreach ( $this->getOptDefinition( $key )[ 'value_options' ] as $opt ) {
src/lib/src/Modules/Base/Options/BuildForDisplay.php CHANGED
@@ -83,6 +83,7 @@ class BuildForDisplay {
83
  $UI->getSectionWarnings( $sect[ 'slug' ] )
84
  );
85
  $sections[ $sectionKey ][ 'notices' ] = $UI->getSectionNotices( $sect[ 'slug' ] );
 
86
  }
87
  }
88
  }
83
  $UI->getSectionWarnings( $sect[ 'slug' ] )
84
  );
85
  $sections[ $sectionKey ][ 'notices' ] = $UI->getSectionNotices( $sect[ 'slug' ] );
86
+ $sections[ $sectionKey ][ 'critical_warnings' ] = $UI->getSectionCriticalWarnings( $sect[ 'slug' ] );
87
  }
88
  }
89
  }
src/lib/src/Modules/Base/Options/HandleOptionsSaveRequest.php CHANGED
@@ -14,10 +14,13 @@ class HandleOptionsSaveRequest {
14
  private $form;
15
 
16
  public function handleSave() :bool {
17
- $form = $this->getForm();
18
- $this->setMod( $this->getCon()->getModule( $form[ 'working_mod' ] ) );
19
-
20
  try {
 
 
 
 
 
 
21
  $con = $this->getCon();
22
  if ( !$con->isPluginAdmin() ) {
23
  throw new \Exception( __( "You don't currently have permission to save settings.", 'wp-simple-firewall' ) );
14
  private $form;
15
 
16
  public function handleSave() :bool {
 
 
 
17
  try {
18
+ $form = $this->getForm();
19
+ if ( empty( $form ) ) {
20
+ throw new \Exception( 'options form parameters were empty.' );
21
+ }
22
+
23
+ $this->setMod( $this->getCon()->getModule( $form[ 'working_mod' ] ) );
24
  $con = $this->getCon();
25
  if ( !$con->isPluginAdmin() ) {
26
  throw new \Exception( __( "You don't currently have permission to save settings.", 'wp-simple-firewall' ) );
src/lib/src/Modules/Base/Strings.php CHANGED
@@ -40,7 +40,6 @@ class Strings {
40
  'btn_save' => __( 'Save Options' ),
41
  'btn_options' => __( 'Options' ),
42
  'btn_help' => __( 'Help' ),
43
- 'btn_wizards' => $this->getMod()->hasWizard() ? __( 'Wizards' ) : __( 'No Wizards' ),
44
  'go_to_settings' => __( 'Configuration', 'wp-simple-firewall' ),
45
  'on' => __( 'On', 'wp-simple-firewall' ),
46
  'off' => __( 'Off', 'wp-simple-firewall' ),
40
  'btn_save' => __( 'Save Options' ),
41
  'btn_options' => __( 'Options' ),
42
  'btn_help' => __( 'Help' ),
 
43
  'go_to_settings' => __( 'Configuration', 'wp-simple-firewall' ),
44
  'on' => __( 'On', 'wp-simple-firewall' ),
45
  'off' => __( 'Off', 'wp-simple-firewall' ),
src/lib/src/Modules/Base/UI.php CHANGED
@@ -35,20 +35,18 @@ class UI {
35
  'show_standard_options' => true,
36
  'show_content_help' => true,
37
  'show_alt_content' => false,
38
- 'has_wizard' => $mod->hasWizard(),
39
  'is_premium' => $con->isPremiumActive(),
40
  'is_whitelablled' => $isWhitelabelled,
41
  'show_transfer_switch' => $con->isPremiumActive(),
42
  'is_wpcli' => $pluginOptions->isEnabledWpcli(),
43
  ],
44
  'hrefs' => [
45
- 'helpdesk' => $con->labels->url_helpdesk,
46
- 'plugin_home' => $con->labels->PluginURI,
47
- 'go_pro' => 'https://shsec.io/shieldgoprofeature',
48
- 'goprofooter' => 'https://shsec.io/goprofooter',
49
- 'wizard_link' => $mod->getUrl_WizardLanding(),
50
- 'wizard_landing' => $mod->getUrl_WizardLanding(),
51
 
 
52
  'form_action' => Services::Request()->getUri(),
53
  'css_bootstrap' => $urlBuilder->forCss( 'bootstrap' ),
54
  'css_pages' => $urlBuilder->forCss( 'shield/pages' ),
@@ -70,6 +68,7 @@ class UI {
70
  'ignore' => $con->svgs->raw( 'bootstrap/eye-slash-fill.svg' ),
71
  'triangle' => $con->svgs->raw( 'bootstrap/triangle-fill.svg' ),
72
  'megaphone' => $con->svgs->raw( 'bootstrap/megaphone.svg' ),
 
73
  ],
74
  'favicon' => $urlBuilder->forImage( 'pluginlogo_24x24.png' ),
75
  'plugin_banner' => $urlBuilder->forImage( 'banner-1500x500-transparent.png' ),
@@ -107,4 +106,8 @@ class UI {
107
  public function getSectionWarnings( string $section ) :array {
108
  return [];
109
  }
 
 
 
 
110
  }
35
  'show_standard_options' => true,
36
  'show_content_help' => true,
37
  'show_alt_content' => false,
 
38
  'is_premium' => $con->isPremiumActive(),
39
  'is_whitelablled' => $isWhitelabelled,
40
  'show_transfer_switch' => $con->isPremiumActive(),
41
  'is_wpcli' => $pluginOptions->isEnabledWpcli(),
42
  ],
43
  'hrefs' => [
44
+ 'helpdesk' => $con->labels->url_helpdesk,
45
+ 'plugin_home' => $con->labels->PluginURI,
46
+ 'go_pro' => 'https://shsec.io/shieldgoprofeature',
47
+ 'goprofooter' => 'https://shsec.io/goprofooter',
 
 
48
 
49
+ 'dashboard_home' => $con->getPluginUrl_DashboardHome(),
50
  'form_action' => Services::Request()->getUri(),
51
  'css_bootstrap' => $urlBuilder->forCss( 'bootstrap' ),
52
  'css_pages' => $urlBuilder->forCss( 'shield/pages' ),
68
  'ignore' => $con->svgs->raw( 'bootstrap/eye-slash-fill.svg' ),
69
  'triangle' => $con->svgs->raw( 'bootstrap/triangle-fill.svg' ),
70
  'megaphone' => $con->svgs->raw( 'bootstrap/megaphone.svg' ),
71
+ 'exit' => $con->svgs->raw( 'bootstrap/box-arrow-left.svg' ),
72
  ],
73
  'favicon' => $urlBuilder->forImage( 'pluginlogo_24x24.png' ),
74
  'plugin_banner' => $urlBuilder->forImage( 'banner-1500x500-transparent.png' ),
106
  public function getSectionWarnings( string $section ) :array {
107
  return [];
108
  }
109
+
110
+ public function getSectionCriticalWarnings( string $section ) :array {
111
+ return [];
112
+ }
113
  }
src/lib/src/Modules/BaseShield/AjaxHandler.php CHANGED
@@ -6,14 +6,4 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
 
7
  class AjaxHandler extends Base\AjaxHandler {
8
 
9
- protected function getAjaxActionCallbackMap( bool $isAuth ) :array {
10
- $map = parent::getAjaxActionCallbackMap( $isAuth );
11
- if ( $isAuth ) {
12
- $map = array_merge( $map, [
13
- 'wiz_process_step' => [ $this->getMod()->getWizardHandler(), 'ajaxExec_WizProcessStep' ],
14
- 'wiz_render_step' => [ $this->getMod()->getWizardHandler(), 'ajaxExec_WizRenderStep' ],
15
- ] );
16
- }
17
- return $map;
18
- }
19
  }
6
 
7
  class AjaxHandler extends Base\AjaxHandler {
8
 
 
 
 
 
 
 
 
 
 
 
9
  }
src/lib/src/Modules/BaseShield/ModCon.php CHANGED
@@ -6,7 +6,6 @@ use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
8
  use FernleafSystems\Wordpress\Services\Services;
9
- use FernleafSystems\Wordpress\Services\Utilities;
10
 
11
  class ModCon extends Base\ModCon {
12
 
@@ -19,7 +18,7 @@ class ModCon extends Base\ModCon {
19
 
20
  public function onWpInit() {
21
  parent::onWpInit();
22
- if ( $this->isThisModulePage() && !$this->isWizardPage() && ( $this->getSlug() != 'insights' ) ) {
23
  $this->redirectToInsightsSubPage();
24
  }
25
  }
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
8
  use FernleafSystems\Wordpress\Services\Services;
 
9
 
10
  class ModCon extends Base\ModCon {
11
 
18
 
19
  public function onWpInit() {
20
  parent::onWpInit();
21
+ if ( $this->isThisModulePage() && ( $this->getSlug() != 'insights' ) ) {
22
  $this->redirectToInsightsSubPage();
23
  }
24
  }
src/lib/src/Modules/Firewall/ModCon.php CHANGED
@@ -18,7 +18,6 @@ class ModCon extends BaseShield\ModCon {
18
  Rules\Build\FirewallFieldTruncation::class,
19
  Rules\Build\FirewallWordpressTerms::class,
20
  Rules\Build\FirewallPhpCode::class,
21
- Rules\Build\FirewallLeadingSchema::class,
22
  Rules\Build\FirewallAggressive::class,
23
  Rules\Build\FirewallExeFileUploads::class,
24
  ],
18
  Rules\Build\FirewallFieldTruncation::class,
19
  Rules\Build\FirewallWordpressTerms::class,
20
  Rules\Build\FirewallPhpCode::class,
 
21
  Rules\Build\FirewallAggressive::class,
22
  Rules\Build\FirewallExeFileUploads::class,
23
  ],
src/lib/src/Modules/Firewall/Rules/Build/FirewallLeadingSchema.php CHANGED
@@ -4,6 +4,9 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\Rules\Build;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
 
 
 
 
7
  class FirewallLeadingSchema extends BuildFirewallBase {
8
 
9
  const SLUG = 'shield/firewall_leading_schema';
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
 
7
+ /**
8
+ * @deprecated 16.0
9
+ */
10
  class FirewallLeadingSchema extends BuildFirewallBase {
11
 
12
  const SLUG = 'shield/firewall_leading_schema';
src/lib/src/Modules/Firewall/Strings.php CHANGED
@@ -116,12 +116,6 @@ class Strings extends Base\Strings {
116
  $desc = [ __( 'This will block executable file uploads (.php, .exe, etc.).', 'wp-simple-firewall' ) ];
117
  break;
118
 
119
- case 'block_leading_schema' :
120
- $name = __( 'Leading Schemas', 'wp-simple-firewall' );
121
- $summary = __( 'Block Leading Schemas (HTTPS / HTTP)', 'wp-simple-firewall' );
122
- $desc = [ __( 'This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with other plugins).', 'wp-simple-firewall' ) ];
123
- break;
124
-
125
  case 'block_aggressive' :
126
  $name = __( 'Aggressive Scan', 'wp-simple-firewall' );
127
  $summary = __( 'Aggressively Block Data', 'wp-simple-firewall' );
116
  $desc = [ __( 'This will block executable file uploads (.php, .exe, etc.).', 'wp-simple-firewall' ) ];
117
  break;
118
 
 
 
 
 
 
 
119
  case 'block_aggressive' :
120
  $name = __( 'Aggressive Scan', 'wp-simple-firewall' );
121
  $summary = __( 'Aggressively Block Data', 'wp-simple-firewall' );
src/lib/src/Modules/IPs/BotTrack/TrackLinkCheese.php CHANGED
@@ -20,7 +20,7 @@ class TrackLinkCheese extends Base {
20
  }
21
 
22
  public function testCheese() {
23
- if ( is_404() && $this->isCheese() ) {
24
 
25
  if ( function_exists( 'wp_robots_sensitive_page' ) ) {
26
  add_filter( 'wp_robots', 'wp_robots_sensitive_page', 1000 );
@@ -33,6 +33,7 @@ class TrackLinkCheese extends Base {
33
  elseif ( !has_action( 'wp_head', 'wp_no_robots' ) ) {
34
  add_action( 'wp_head', 'wp_no_robots' );
35
  }
 
36
  $this->doTransgression();
37
  }
38
  }
@@ -47,20 +48,12 @@ class TrackLinkCheese extends Base {
47
  }
48
 
49
  private function isCheese() :bool {
 
50
  $WP = Services::WpGeneral();
51
 
52
- if ( $WP->isPermalinksEnabled() ) {
53
- $reqPath = trim( (string)Services::Request()->getPath(), '/' );
54
- $isCheese = ( $reqPath ===
55
- trim( (string)parse_url( $WP->getHomeUrl( $this->getCheeseWord() ), PHP_URL_PATH ), '/' ) )
56
- || preg_match( '#icwp-wpsf-[a-z]+-[a-z\d]{7,9}#', $reqPath ) > 0;
57
- /** TODO: 10.3 legacy remove */
58
- }
59
- else {
60
- $isCheese = Services::Request()->query( $this->getCheeseWord() ) === '1';
61
- }
62
-
63
- return $isCheese;
64
  }
65
 
66
  public function insertMouseTrap() {
20
  }
21
 
22
  public function testCheese() {
23
+ if ( ( is_404() || is_front_page() ) && $this->isCheese() ) {
24
 
25
  if ( function_exists( 'wp_robots_sensitive_page' ) ) {
26
  add_filter( 'wp_robots', 'wp_robots_sensitive_page', 1000 );
33
  elseif ( !has_action( 'wp_head', 'wp_no_robots' ) ) {
34
  add_action( 'wp_head', 'wp_no_robots' );
35
  }
36
+
37
  $this->doTransgression();
38
  }
39
  }
48
  }
49
 
50
  private function isCheese() :bool {
51
+ $req = Services::Request();
52
  $WP = Services::WpGeneral();
53
 
54
+ return $WP->isPermalinksEnabled() ?
55
+ trim( $req->getPath(), '/' ) === trim( (string)parse_url( $WP->getHomeUrl( $this->getCheeseWord() ), PHP_URL_PATH ), '/' )
56
+ : $req->query( $this->getCheeseWord() ) == '1';
 
 
 
 
 
 
 
 
 
57
  }
58
 
59
  public function insertMouseTrap() {
src/lib/src/Modules/IPs/Lib/AutoUnblock/AutoUnblockCrowdsec.php CHANGED
@@ -17,6 +17,10 @@ class AutoUnblockCrowdsec extends BaseAutoUnblock {
17
  && $this->getCon()->this_req->is_ip_blocked_crowdsec && $opts->isEnabledCrowdSecAutoVisitorUnblock();
18
  }
19
 
 
 
 
 
20
  protected function getIpRecord() :IpRuleRecord {
21
  $theRecord = null;
22
  $status = ( new IpRuleStatus( $this->getCon()->this_req->ip ) )->setMod( $this->getMod() );
17
  && $this->getCon()->this_req->is_ip_blocked_crowdsec && $opts->isEnabledCrowdSecAutoVisitorUnblock();
18
  }
19
 
20
+ protected function getUnblockMethodName() :string {
21
+ return 'CrowdSec Auto-Unblock';
22
+ }
23
+
24
  protected function getIpRecord() :IpRuleRecord {
25
  $theRecord = null;
26
  $status = ( new IpRuleStatus( $this->getCon()->this_req->ip ) )->setMod( $this->getMod() );
src/lib/src/Modules/IPs/Lib/AutoUnblock/AutoUnblockMagicLink.php CHANGED
@@ -14,6 +14,10 @@ class AutoUnblockMagicLink extends BaseAutoUnblockShield {
14
  return $opts->isEnabledMagicEmailLinkRecover() && parent::isUnblockAvailable();
15
  }
16
 
 
 
 
 
17
  protected function run() {
18
  $req = Services::Request();
19
  try {
14
  return $opts->isEnabledMagicEmailLinkRecover() && parent::isUnblockAvailable();
15
  }
16
 
17
+ protected function getUnblockMethodName() :string {
18
+ return 'Magic Link';
19
+ }
20
+
21
  protected function run() {
22
  $req = Services::Request();
23
  try {
src/lib/src/Modules/IPs/Lib/AutoUnblock/AutoUnblockVisitor.php CHANGED
@@ -11,6 +11,10 @@ class AutoUnblockVisitor extends BaseAutoUnblockShield {
11
  return parent::canRun() && Services::Request()->isPost();
12
  }
13
 
 
 
 
 
14
  public function isUnblockAvailable() :bool {
15
  /** @var Options $opts */
16
  $opts = $this->getOptions();
11
  return parent::canRun() && Services::Request()->isPost();
12
  }
13
 
14
+ protected function getUnblockMethodName() :string {
15
+ return 'Visitor Auto-Unblock';
16
+ }
17
+
18
  public function isUnblockAvailable() :bool {
19
  /** @var Options $opts */
20
  $opts = $this->getOptions();
src/lib/src/Modules/IPs/Lib/AutoUnblock/BaseAutoUnblock.php CHANGED
@@ -145,11 +145,25 @@ abstract class BaseAutoUnblock extends ExecOnceModConsumer {
145
  'unblocked_at' => Services::Request()->ts(),
146
  'last_access_at' => Services::Request()->ts(),
147
  ] );
 
148
  }
149
 
150
  return $unblocked;
151
  }
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  /**
154
  * @throws \Exception
155
  */
145
  'unblocked_at' => Services::Request()->ts(),
146
  'last_access_at' => Services::Request()->ts(),
147
  ] );
148
+ $this->fireEvent();
149
  }
150
 
151
  return $unblocked;
152
  }
153
 
154
+ protected function fireEvent() {
155
+ $this->getCon()->fireEvent( 'ip_unblock_auto', [
156
+ 'audit_params' => [
157
+ 'ip' => $this->getCon()->this_req->ip,
158
+ 'method' => $this->getUnblockMethodName()
159
+ ]
160
+ ] );
161
+ }
162
+
163
+ protected function getUnblockMethodName() :string {
164
+ return '';
165
+ }
166
+
167
  /**
168
  * @throws \Exception
169
  */
src/lib/src/Modules/IPs/Lib/CrowdSec/Api/DecisionsDownload.php CHANGED
@@ -15,6 +15,11 @@ class DecisionsDownload extends BaseAuth {
15
  $this->request_method = 'get';
16
  $decisions = $this->sendReq();
17
  if ( !is_array( $decisions ) || !isset( $decisions[ 'new' ] ) || !isset( $decisions[ 'deleted' ] ) ) {
 
 
 
 
 
18
  throw new DownloadDecisionsStreamFailedException( sprintf( 'Failed to download decisions: %s',
19
  var_export( $this->last_http_req->lastResponse->body, true ) ) );
20
  }
15
  $this->request_method = 'get';
16
  $decisions = $this->sendReq();
17
  if ( !is_array( $decisions ) || !isset( $decisions[ 'new' ] ) || !isset( $decisions[ 'deleted' ] ) ) {
18
+ error_log( var_export( $this->getApiRequestUrl(), true ) );
19
+ error_log( var_export( $this->getRequestParams(), true ) );
20
+ error_log( var_export( $this->params_body, true ) );
21
+ error_log( var_export( $this->params_query, true ) );
22
+ error_log( var_export( $this->headers, true ) );
23
  throw new DownloadDecisionsStreamFailedException( sprintf( 'Failed to download decisions: %s',
24
  var_export( $this->last_http_req->lastResponse->body, true ) ) );
25
  }
src/lib/src/Modules/IPs/Lib/CrowdSec/Decisions/ImportDecisions.php CHANGED
@@ -35,6 +35,9 @@ class ImportDecisions extends ExecOnceModConsumer {
35
  }
36
 
37
  public function runImport() {
 
 
 
38
  // We currently only import decisions that have a TTL of at least 5 days.
39
  $minimumExpiresAt = Services::Request()
40
  ->carbon()
@@ -52,6 +55,7 @@ class ImportDecisions extends ExecOnceModConsumer {
52
  }
53
  }
54
  catch ( \Exception $e ) {
 
55
  error_log( $e->getMessage() );
56
  }
57
  }
35
  }
36
 
37
  public function runImport() {
38
+ /** @var ModCon $mod */
39
+ $mod = $this->getMod();
40
+ $api = $mod->getCrowdSecCon()->getApi();
41
  // We currently only import decisions that have a TTL of at least 5 days.
42
  $minimumExpiresAt = Services::Request()
43
  ->carbon()
55
  }
56
  }
57
  catch ( \Exception $e ) {
58
+ error_log( 'Auth token: '.$api->getAuthorizationToken() );
59
  error_log( $e->getMessage() );
60
  }
61
  }
src/lib/src/Modules/IPs/Lib/Table/BuildIpRulesTableData.php CHANGED
@@ -9,7 +9,7 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\IpRuleRecord;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\LoadIpRules;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\Ops\Handler;
11
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Options;
12
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\IpRules\ForIpRules;
13
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseBuildTableData;
14
  use FernleafSystems\Wordpress\Services\Services;
15
 
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\LoadIpRules;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\Ops\Handler;
11
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Options;
12
+ use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\ForIpRules;
13
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseBuildTableData;
14
  use FernleafSystems\Wordpress\Services\Services;
15
 
src/lib/src/Modules/IPs/Strings.php CHANGED
@@ -48,6 +48,12 @@ class Strings extends Base\Strings {
48
  __( '{{ip}} removed from block list ({{type}}).', 'wp-simple-firewall' ),
49
  ],
50
  ],
 
 
 
 
 
 
51
  'ip_unblock_flag' => [
52
  'name' => __( 'IP Unblocked (Flag File)', 'wp-simple-firewall' ),
53
  'audit' => [
@@ -285,8 +291,10 @@ class Strings extends Base\Strings {
285
  * @throws \Exception
286
  */
287
  public function getOptionStrings( string $key ) :array {
 
 
288
  $pluginName = $this->getCon()->getHumanName();
289
- $modName = $this->getMod()->getMainFeatureName();
290
 
291
  switch ( $key ) {
292
 
@@ -383,6 +391,7 @@ class Strings extends Base\Strings {
383
  break;
384
 
385
  case 'cs_enroll_id' :
 
386
  $name = __( 'CrowdSec Enroll ID', 'wp-simple-firewall' );
387
  $summary = __( 'CrowdSec Instance Enroll ID', 'wp-simple-firewall' );
388
  $desc = [
@@ -390,6 +399,8 @@ class Strings extends Base\Strings {
390
  __( 'You can link this WordPress site to your CrowdSec console by providing your Enroll ID.', 'wp-simple-firewall' ),
391
  sprintf( '%s: <a href="%s" target="_blank">%s</a>', __( 'Login or Signup for your free CrowdSec console', 'wp-simple-firewall' ),
392
  'https://shsec.io/crowdsecapp', 'https://app.crowdsec.net' ),
 
 
393
  ];
394
  break;
395
 
48
  __( '{{ip}} removed from block list ({{type}}).', 'wp-simple-firewall' ),
49
  ],
50
  ],
51
+ 'ip_unblock_auto' => [
52
+ 'name' => __( 'IP Unblocked By Visitor', 'wp-simple-firewall' ),
53
+ 'audit' => [
54
+ __( "Visitor unblocked their IP address '{{ip}}' using the '{{method}}' method.", 'wp-simple-firewall' ),
55
+ ],
56
+ ],
57
  'ip_unblock_flag' => [
58
  'name' => __( 'IP Unblocked (Flag File)', 'wp-simple-firewall' ),
59
  'audit' => [
291
  * @throws \Exception
292
  */
293
  public function getOptionStrings( string $key ) :array {
294
+ /** @var ModCon $mod */
295
+ $mod = $this->getMod();
296
  $pluginName = $this->getCon()->getHumanName();
297
+ $modName = $mod->getMainFeatureName();
298
 
299
  switch ( $key ) {
300
 
391
  break;
392
 
393
  case 'cs_enroll_id' :
394
+ $machID = $mod->getCrowdSecCon()->getApi()->getMachineID();
395
  $name = __( 'CrowdSec Enroll ID', 'wp-simple-firewall' );
396
  $summary = __( 'CrowdSec Instance Enroll ID', 'wp-simple-firewall' );
397
  $desc = [
399
  __( 'You can link this WordPress site to your CrowdSec console by providing your Enroll ID.', 'wp-simple-firewall' ),
400
  sprintf( '%s: <a href="%s" target="_blank">%s</a>', __( 'Login or Signup for your free CrowdSec console', 'wp-simple-firewall' ),
401
  'https://shsec.io/crowdsecapp', 'https://app.crowdsec.net' ),
402
+ empty( $machID ) ? __( "Your site isn't registered with CrowdSec yet.", 'wp-simple-firewall' )
403
+ : sprintf( __( "Your registered machine ID with CrowdSec is: %s", 'wp-simple-firewall' ), '<code>'.$machID.'</code>' ),
404
  ];
405
  break;
406
 
src/lib/src/Modules/IPs/UI.php CHANGED
@@ -5,7 +5,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\Ops\Handler;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot\TestNotBotLoading;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\IpRules\ForIpRules;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
  class UI extends BaseShield\UI {
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\IpRules\Ops\Handler;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot\TestNotBotLoading;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\ForIpRules;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
  class UI extends BaseShield\UI {
src/lib/src/Modules/Insights/AjaxHandler.php CHANGED
@@ -3,7 +3,6 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
 
8
  class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
9
 
@@ -11,7 +10,8 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
11
  $map = parent::getAjaxActionCallbackMap( $isAuth );
12
  if ( $isAuth ) {
13
  $map = array_merge( $map, [
14
- 'dynamic_load' => [ $this, 'ajaxExec_DynamicLoad' ],
 
15
  ] );
16
  }
17
  return $map;
@@ -23,23 +23,41 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
23
  ->setMod( $this->getMod() )
24
  ->build( Shield\Modules\Base\Lib\Request\FormParams::Retrieve() );
25
  $success = true;
 
26
  }
27
  catch ( \Exception $e ) {
28
- $pageData = [
29
- 'success' => false,
30
- 'message' => $e->getMessage(),
31
- ];
32
  $success = false;
33
  }
34
 
35
  return array_merge(
36
  [
37
- 'success' => false,
38
- 'message' => 'no msg',
39
  'html' => 'no html',
40
  'show_toast' => !$success,
41
  ],
42
- $pageData
43
  );
44
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
 
6
 
7
  class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
8
 
10
  $map = parent::getAjaxActionCallbackMap( $isAuth );
11
  if ( $isAuth ) {
12
  $map = array_merge( $map, [
13
+ 'dynamic_load' => [ $this, 'ajaxExec_DynamicLoad' ],
14
+ 'merlin_action' => [ $this, 'ajaxExec_MerlinAction' ],
15
  ] );
16
  }
17
  return $map;
23
  ->setMod( $this->getMod() )
24
  ->build( Shield\Modules\Base\Lib\Request\FormParams::Retrieve() );
25
  $success = true;
26
+ $msg = 'render success';
27
  }
28
  catch ( \Exception $e ) {
29
+ $msg = $e->getMessage();
 
 
 
30
  $success = false;
31
  }
32
 
33
  return array_merge(
34
  [
35
+ 'success' => $success,
36
+ 'message' => $msg,
37
  'html' => 'no html',
38
  'show_toast' => !$success,
39
  ],
40
+ $pageData ?? []
41
  );
42
  }
43
+
44
+ public function ajaxExec_MerlinAction() :array {
45
+ try {
46
+ $response = ( new Shield\Modules\Insights\Lib\Merlin\MerlinController() )
47
+ ->setMod( $this->getMod() )
48
+ ->processFormSubmit( Shield\Modules\Base\Lib\Request\FormParams::Retrieve() );
49
+ $success = $response->success;
50
+ $msg = $response->getRelevantMsg();
51
+ }
52
+ catch ( \Exception $e ) {
53
+ $success = false;
54
+ $msg = $e->getMessage();
55
+ }
56
+
57
+ return [
58
+ 'success' => $success,
59
+ 'message' => $msg,
60
+ 'page_reload' => $response->data[ 'page_reload' ] ?? false,
61
+ ];
62
+ }
63
  }
src/lib/src/Modules/Insights/Lib/Merlin/MerlinController.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class MerlinController {
8
+
9
+ use Shield\Modules\ModConsumer;
10
+
11
+ private $workingKey;
12
+
13
+ public function render( string $key ) :string {
14
+ $this->workingKey = $key;
15
+ return $this->getMod()->renderTemplate(
16
+ '/components/merlin/container.twig',
17
+ [
18
+ 'content' => [
19
+ 'steps' => $this->buildSteps()
20
+ ],
21
+ ]
22
+ );
23
+ }
24
+
25
+ /**
26
+ * @throws \Exception
27
+ */
28
+ public function processFormSubmit( array $form ) :Shield\Utilities\Response {
29
+ $step = $form[ 'step_slug' ] ?? '';
30
+ if ( empty( $step ) ) {
31
+ throw new \Exception( 'No step configured for this form' );
32
+ }
33
+ $handlers = $this->getStepHandlers( false );
34
+ if ( !isset( $handlers[ $step ] ) ) {
35
+ throw new \Exception( 'Invalid Step.' );
36
+ }
37
+ return $handlers[ $step ]->processStepFormSubmit( $form );
38
+ }
39
+
40
+ private function buildSteps() :array {
41
+ return array_map(
42
+ function ( $handler ) {
43
+ return [
44
+ 'step_slug' => $handler::SLUG,
45
+ 'step_name' => $handler->getName(),
46
+ 'step_body' => $handler->render(),
47
+ ];
48
+ },
49
+ array_filter( $this->getStepHandlers( true ), function ( $handler ) {
50
+ return !$handler->skipStep();
51
+ } )
52
+ );
53
+ }
54
+
55
+ private function getStepKeys() :array {
56
+ switch ( $this->workingKey ) {
57
+ case 'guided_setup':
58
+ default:
59
+ $steps = [
60
+ 'guided_setup_welcome',
61
+ 'license',
62
+ 'ip_detect',
63
+ 'security_admin',
64
+ 'ip_blocking',
65
+ 'login_protection',
66
+ 'comment_spam',
67
+ 'security_badge',
68
+ 'free_trial',
69
+ 'opt_in',
70
+ 'thank_you',
71
+ ];
72
+ break;
73
+ }
74
+ return $steps;
75
+ }
76
+
77
+ /**
78
+ * @return Steps\Base[]
79
+ */
80
+ private function getStepHandlers( bool $filterByStepKeys ) :array {
81
+ $stepKeys = array_flip( $this->getStepKeys() );
82
+
83
+ // Extracts and ORDERS all the required Step Handlers
84
+ $handlers = $this->enumStepHandlers();
85
+ if ( $filterByStepKeys ) {
86
+ $handlers = array_filter(
87
+ array_merge( $stepKeys, array_intersect_key( $handlers, $stepKeys ) ),
88
+ function ( $handler ) {
89
+ return !is_numeric( $handler );
90
+ }
91
+ );
92
+ }
93
+
94
+ return array_map(
95
+ function ( string $handlerClass ) {
96
+ /** @var Steps\Base $handler */
97
+ $handler = new $handlerClass();
98
+ return $handler->setMod( $this->getMod() );
99
+ },
100
+ $handlers
101
+ );
102
+ }
103
+
104
+ /**
105
+ * @return Steps\Base[]
106
+ */
107
+ private function enumStepHandlers() :array {
108
+ $classes = [
109
+ Steps\GuidedSetupWelcome::class,
110
+ Steps\Import::class,
111
+ Steps\IpDetect::class,
112
+ Steps\IpBlocking::class,
113
+ Steps\LoginProtection::class,
114
+ Steps\CommentSpam::class,
115
+ Steps\SecurityAdmin::class,
116
+ Steps\SecurityBadge::class,
117
+ Steps\FreeTrial::class,
118
+ Steps\License::class,
119
+ Steps\OptIn::class,
120
+ Steps\ThankYou::class,
121
+ ];
122
+
123
+ $handlers = [];
124
+ foreach ( $classes as $class ) {
125
+ $handlers[ $class::SLUG ] = $class;
126
+ }
127
+
128
+ return $handlers;
129
+ }
130
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/Base.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Base extends Shield\Utilities\Render\BaseTemplateRenderer {
9
+
10
+ use Shield\Modules\ModConsumer;
11
+
12
+ const SLUG = '';
13
+
14
+ public function getName() :string {
15
+ return 'Title Unset';
16
+ }
17
+
18
+ public function skipStep() :bool {
19
+ return false;
20
+ }
21
+
22
+ protected function getTemplateBaseDir() :string {
23
+ return '/components/merlin/steps/';
24
+ }
25
+
26
+ protected function getTemplateStub() :string {
27
+ return static::SLUG;
28
+ }
29
+
30
+ protected function getRenderData() :array {
31
+ $step = $this->getStepRenderData();
32
+
33
+ if ( !empty( $step[ 'vars' ][ 'video_id' ] ) ) {
34
+ $step[ 'imgs' ][ 'video_thumb' ] = $this->getVideoThumbnailUrl( $step[ 'vars' ][ 'video_id' ] );
35
+ }
36
+
37
+ return Services::DataManipulation()->mergeArraysRecursive(
38
+ $this->getCon()->getModule_Plugin()->getUIHandler()->getBaseDisplayData(),
39
+ $this->getCommonStepRenderData(),
40
+ $step
41
+ );
42
+ }
43
+
44
+ /**
45
+ * @throws \Exception
46
+ */
47
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
48
+ $resp = new Shield\Utilities\Response();
49
+ $resp->success = false;
50
+ $resp->error = 'No form processing has been configured for this step';
51
+ $resp->addData( 'page_reload', false );
52
+ return $resp;
53
+ }
54
+
55
+ protected function getCommonStepRenderData() :array {
56
+ return [
57
+ 'hrefs' => [
58
+ 'dashboard' => $this->getCon()->getPluginUrl_DashboardHome(),
59
+ 'gopro' => 'https://shsec.io/ap',
60
+ ],
61
+ 'imgs' => [
62
+ 'play_button' => $this->getCon()->urls->forImage( 'bootstrap/play-circle.svg' )
63
+ ],
64
+ 'vars' => [
65
+ 'step_slug' => static::SLUG
66
+ ],
67
+ ];
68
+ }
69
+
70
+ protected function getStepRenderData() :array {
71
+ return [];
72
+ }
73
+
74
+ /**
75
+ * @see https://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo
76
+ */
77
+ private function getVideoThumbnailUrl( string $videoID ) :string {
78
+ $raw = Services::HttpRequest()
79
+ ->getContent( sprintf( 'https://vimeo.com/api/v2/video/%s.json', $videoID ) );
80
+ return empty( $raw ) ? '' : json_decode( $raw, true )[ 0 ][ 'thumbnail_large' ];
81
+ }
82
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/CommentSpam.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class CommentSpam extends Base {
8
+
9
+ const SLUG = 'comment_spam';
10
+
11
+ public function getName() :string {
12
+ return 'SPAM';
13
+ }
14
+
15
+ protected function getStepRenderData() :array {
16
+ return [
17
+ 'strings' => [
18
+ 'step_title' => __( "Block 100% Bots Comment SPAM Without CAPTCHAs!", 'wp-simple-firewall' ),
19
+ ],
20
+ 'vars' => [
21
+ 'video_id' => '269193270'
22
+ ],
23
+ ];
24
+ }
25
+
26
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
27
+ $value = $form[ 'CommentsFilterOption' ] ?? '';
28
+ if ( empty( $value ) ) {
29
+ throw new \Exception( 'Please select one of the options, or proceed to the next step.' );
30
+ }
31
+
32
+ $mod = $this->getCon()->getModule_Comments();
33
+
34
+ $toEnable = $value === 'Y';
35
+ if ( $toEnable ) { // we don't disable the whole module
36
+ $mod->setIsMainFeatureEnabled( true );
37
+ }
38
+ /** @var Shield\Modules\CommentsFilter\Options $opts */
39
+ $opts = $mod->getOptions();
40
+ $opts->setEnabledAntiBot( $toEnable );
41
+ $mod->saveModOptions();
42
+
43
+ $resp = parent::processStepFormSubmit( $form );
44
+ $resp->success = true;
45
+ $resp->msg = $toEnable ? __( 'Bot comment SPAM will now be blocked', 'wp-simple-firewall' )
46
+ : __( 'Bot comment SPAM will not be blocked', 'wp-simple-firewall' );
47
+ return $resp;
48
+ }
49
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/FreeTrial.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ class FreeTrial extends Base {
6
+
7
+ const SLUG = 'free_trial';
8
+
9
+ public function getName() :string {
10
+ return 'Free Trial';
11
+ }
12
+
13
+ protected function getStepRenderData() :array {
14
+ return [
15
+ 'hrefs' => [
16
+ 'free_trial' => 'https://shsec.io/freetrialwizard',
17
+ 'features' => 'https://getshieldsecurity.com/features/',
18
+ ],
19
+ 'imgs' => [
20
+ 'free_trial' => $this->getCon()->svgs->raw( 'bootstrap/shield-fill-plus.svg' ),
21
+ ],
22
+ 'strings' => [
23
+ 'step_title' => 'Try ShieldPRO For Free',
24
+ ],
25
+ ];
26
+ }
27
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/GuidedSetupWelcome.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class GuidedSetupWelcome extends Base {
8
+
9
+ const SLUG = 'guided_setup_welcome';
10
+
11
+ public function getName() :string {
12
+ return 'Welcome';
13
+ }
14
+
15
+ protected function getStepRenderData() :array {
16
+ return [
17
+ 'strings' => [
18
+ 'step_title' => __( "Welcome to Shield Security's Guided Setup Wizard", 'wp-simple-firewall' ),
19
+ ],
20
+ 'vars' => [
21
+ 'video_id' => '269191603'
22
+ ],
23
+ ];
24
+ }
25
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/Import.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class Import extends Base {
8
+
9
+ const SLUG = 'import';
10
+
11
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
12
+ $mod = $this->getCon()->getModule_IPs();
13
+ $opts = $mod->getOptions();
14
+
15
+ $offenses = $form[ 'offenses' ] ?? '';
16
+ if ( empty( $offenses ) ) {
17
+ throw new \Exception( 'Please provide an offense limit' );
18
+ }
19
+ $offenses = (int)$offenses;
20
+ if ( $offenses <= 1 ) {
21
+ throw new \Exception( 'The offense limit should be at least 2' );
22
+ }
23
+ if ( $offenses > 20 ) {
24
+ throw new \Exception( 'The offense limit should be less than 20' );
25
+ }
26
+
27
+ $blockLength = $form[ 'block_length' ] ?? '';
28
+ if ( empty( $blockLength ) ) {
29
+ throw new \Exception( 'Please provide a block length' );
30
+ }
31
+ if ( !in_array( $blockLength, [ 'day', 'week', 'month' ], true ) ) {
32
+ throw new \Exception( 'Invalid request.' );
33
+ }
34
+
35
+ $csBlock = $form[ 'cs_block' ] ?? '';
36
+ if ( !in_array( $csBlock, [ '', 'Y' ], true ) ) {
37
+ throw new \Exception( 'Invalid request.' );
38
+ }
39
+
40
+ $mod->setIsMainFeatureEnabled( true );
41
+ $opts->setOpt( 'transgression_limit', $offenses );
42
+ $opts->setOpt( 'auto_expire', $blockLength );
43
+ $opts->setOpt( 'cs_block', $csBlock === 'Y' ? 'block_with_unblock' : 'disabled' );
44
+ $mod->saveModOptions();
45
+
46
+ $resp = parent::processStepFormSubmit( $form );
47
+ $resp->success = true;
48
+ $resp->msg = __( 'IP blocking options have been applied', 'wp-simple-firewall' );
49
+ return $resp;
50
+ }
51
+
52
+ public function getName() :string {
53
+ return 'Import';
54
+ }
55
+
56
+ protected function getStepRenderData() :array {
57
+ return [
58
+ 'strings' => [
59
+ 'step_title' => __( 'Import Settings From Another Site', 'wp-simple-firewall' ),
60
+ ],
61
+ ];
62
+ }
63
+
64
+ public function skipStep() :bool {
65
+ return !$this->getCon()->isPremiumActive();
66
+ }
67
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/IpBlocking.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class IpBlocking extends Base {
8
+
9
+ const SLUG = 'ip_blocking';
10
+
11
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
12
+ $mod = $this->getCon()->getModule_IPs();
13
+ $opts = $mod->getOptions();
14
+
15
+ $offenses = $form[ 'offenses' ] ?? '';
16
+ if ( empty( $offenses ) ) {
17
+ throw new \Exception( 'Please provide an offense limit' );
18
+ }
19
+ $offenses = (int)$offenses;
20
+ if ( $offenses <= 1 ) {
21
+ throw new \Exception( 'The offense limit should be at least 2' );
22
+ }
23
+ if ( $offenses > 20 ) {
24
+ throw new \Exception( 'The offense limit should be less than 20' );
25
+ }
26
+
27
+ $blockLength = $form[ 'block_length' ] ?? '';
28
+ if ( empty( $blockLength ) ) {
29
+ throw new \Exception( 'Please provide a block length' );
30
+ }
31
+ if ( !in_array( $blockLength, [ 'day', 'week', 'month' ], true ) ) {
32
+ throw new \Exception( 'Invalid request.' );
33
+ }
34
+
35
+ $csBlock = $form[ 'cs_block' ] ?? '';
36
+ if ( !in_array( $csBlock, [ '', 'Y' ], true ) ) {
37
+ throw new \Exception( 'Invalid request.' );
38
+ }
39
+
40
+ $mod->setIsMainFeatureEnabled( true );
41
+ $opts->setOpt( 'transgression_limit', $offenses );
42
+ $opts->setOpt( 'auto_expire', $blockLength );
43
+ $opts->setOpt( 'cs_block', $csBlock === 'Y' ? 'block_with_unblock' : 'disabled' );
44
+ $mod->saveModOptions();
45
+
46
+ $resp = parent::processStepFormSubmit( $form );
47
+ $resp->success = true;
48
+ $resp->msg = __( 'IP blocking options have been applied', 'wp-simple-firewall' );
49
+ return $resp;
50
+ }
51
+
52
+ public function getName() :string {
53
+ return 'IP Block';
54
+ }
55
+
56
+ protected function getStepRenderData() :array {
57
+ /** @var Shield\Modules\IPs\Options $opts */
58
+ $opts = $this->getCon()->getModule_IPs()->getOptions();
59
+ return [
60
+ 'strings' => [
61
+ 'step_title' => __( 'Automatically Block Malicious IP Addresses', 'wp-simple-firewall' ),
62
+ ],
63
+ 'vars' => [
64
+ 'offense_limit' => $opts->getOffenseLimit()
65
+ ]
66
+ ];
67
+ }
68
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/IpDetect.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Utilities\Net\RequestIpDetect;
7
+
8
+ class IpDetect extends Base {
9
+
10
+ const SLUG = 'ip_detect';
11
+
12
+ public function getName() :string {
13
+ return 'IP Detect';
14
+ }
15
+
16
+ protected function getStepRenderData() :array {
17
+ $allIPs = $this->gatherUniqueIpSources();
18
+ return [
19
+ 'hrefs' => [
20
+ 'visitor_ip' => 'https://shsec.io/visitorip',
21
+ ],
22
+ 'flags' => [
23
+ 'has_none' => count( $allIPs ) === 0,
24
+ 'has_only_1' => count( $allIPs ) === 1, // step is skipped
25
+ 'has_multiple' => count( $allIPs ) > 1,
26
+ ],
27
+ 'vars' => [
28
+ 'video_id' => '269189603',
29
+ 'the_ip' => $this->getCon()->this_req->ip,
30
+ 'all_ips' => $allIPs,
31
+ ],
32
+ 'strings' => [
33
+ 'step_title' => 'Setup Correct IP Address Detection',
34
+ ],
35
+ ];
36
+ }
37
+
38
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
39
+ $mod = $this->getCon()->getModule_Plugin();
40
+ /** @var Shield\Modules\Plugin\Options $opts */
41
+ $opts = $mod->getOptions();
42
+
43
+ $source = $form[ 'ip_source' ] ?? '';
44
+ if ( empty( $source ) ) {
45
+ throw new \Exception( 'Not a valid request' );
46
+ }
47
+ if ( !in_array( $source, $opts->getSelectOptionValueKeys( 'visitor_address_source' ) ) ) {
48
+ throw new \Exception( 'Not a valid visitor IP Source' );
49
+ }
50
+
51
+ $opts->setVisitorAddressSource( $source );
52
+ $mod->saveModOptions();
53
+
54
+ $resp = parent::processStepFormSubmit( $form );
55
+ $resp->success = true;
56
+ $resp->msg = __( 'Visitor IP address source set', 'wp-simple-firewall' );
57
+ return $resp;
58
+ }
59
+
60
+ private function gatherUniqueIpSources() :array {
61
+ $allIPs = [];
62
+ foreach ( ( new RequestIpDetect() )->getPublicRequestIPData()[ 'all_ips' ] as $source => $ips ) {
63
+ $allIPs[ $source ] = current( $ips );
64
+ }
65
+ return array_unique( $allIPs );
66
+ }
67
+
68
+ public function skipStep() :bool {
69
+ return count( $this->gatherUniqueIpSources() ) === 1;
70
+ }
71
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/License.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class License extends Base {
8
+
9
+ const SLUG = 'license';
10
+
11
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
12
+ $resp = parent::processStepFormSubmit( $form );
13
+ $resp->success = $this->getCon()
14
+ ->getModule_License()
15
+ ->getLicenseHandler()
16
+ ->verify( true )
17
+ ->hasValidWorkingLicense();
18
+ if ( $resp->success ) {
19
+ $resp->msg = 'License found and installed successfully';
20
+ }
21
+ else {
22
+ $resp->error = "There doesn't appear to be a active ShieldPRO license available for this site.";
23
+ }
24
+
25
+ $resp->addData( 'page_reload', $resp->success );
26
+
27
+ return $resp;
28
+ }
29
+
30
+ public function getName() :string {
31
+ return 'ShieldPRO';
32
+ }
33
+
34
+ protected function getStepRenderData() :array {
35
+ return [
36
+ 'strings' => [
37
+ 'step_title' => __( "Activate Your ShieldPRO License", 'wp-simple-firewall' ),
38
+ ],
39
+ ];
40
+ }
41
+
42
+ public function skipStep() :bool {
43
+ return $this->getCon()->isPremiumActive();
44
+ }
45
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/LoginProtection.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class LoginProtection extends Base {
8
+
9
+ const SLUG = 'login_protection';
10
+
11
+ public function getName() :string {
12
+ return 'Login';
13
+ }
14
+
15
+ protected function getStepRenderData() :array {
16
+ return [
17
+ 'strings' => [
18
+ 'step_title' => __( "Brute Force Login Protection", 'wp-simple-firewall' ),
19
+ ],
20
+ 'vars' => [
21
+ 'video_id' => '269191603'
22
+ ],
23
+ ];
24
+ }
25
+
26
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
27
+ $value = $form[ 'LoginProtectOption' ] ?? '';
28
+ if ( empty( $value ) ) {
29
+ throw new \Exception( 'Please select one of the options, or proceed to the next step.' );
30
+ }
31
+
32
+ $mod = $this->getCon()->getModule_LoginGuard();
33
+
34
+ $toEnable = $value === 'Y';
35
+ if ( $toEnable ) { // we don't disable the whole module
36
+ $mod->setIsMainFeatureEnabled( true );
37
+ }
38
+ $mod->getOptions()->setOpt( 'enable_antibot_check', $toEnable ? 'Y' : 'N' );
39
+ $mod->saveModOptions();
40
+
41
+ $resp = parent::processStepFormSubmit( $form );
42
+ $resp->success = true;
43
+ $resp->msg = $toEnable ? __( 'Bot comment SPAM will now be blocked', 'wp-simple-firewall' )
44
+ : __( 'Bot comment SPAM will not be blocked', 'wp-simple-firewall' );
45
+ return $resp;
46
+ }
47
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/OptIn.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class OptIn extends Base {
8
+
9
+ const SLUG = 'opt_in';
10
+
11
+ public function getName() :string {
12
+ return 'Join Us!';
13
+ }
14
+
15
+ protected function getStepRenderData() :array {
16
+ $con = $this->getCon();
17
+ $user = Services::WpUsers()->getCurrentWpUser();
18
+ return [
19
+ 'hrefs' => [
20
+ 'facebook' => 'https://shsec.io/pluginshieldsecuritygroupfb',
21
+ 'twitter' => 'https://shsec.io/pluginshieldsecuritytwitter',
22
+ 'email' => 'https://shsec.io/pluginshieldsecuritynewsletter',
23
+ ],
24
+ 'imgs' => [
25
+ 'facebook' => $con->svgs->raw( 'bootstrap/facebook.svg' ),
26
+ 'twitter' => $con->svgs->raw( 'bootstrap/twitter.svg' ),
27
+ 'email' => $con->svgs->raw( 'bootstrap/envelope-fill.svg' ),
28
+ ],
29
+ 'vars' => [
30
+ 'name' => $user->first_name,
31
+ 'email' => $user->user_email
32
+ ],
33
+ 'strings' => [
34
+ 'step_title' => 'Come Join Us!',
35
+ ],
36
+ ];
37
+ }
38
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/SecurityAdmin.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class SecurityAdmin extends Base {
8
+
9
+ const SLUG = 'security_admin';
10
+
11
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
12
+
13
+ $pin = $form[ 'SecAdminPIN' ] ?? '';
14
+ if ( empty( $pin ) ) {
15
+ throw new \Exception( 'Please provide a Security PIN, or proceed to the next step.' );
16
+ }
17
+ if ( $pin !== ( $form[ 'SecAdminPINConfirm' ] ?? '' ) ) {
18
+ throw new \Exception( 'The Security PINs provided do not match.' );
19
+ }
20
+ if ( !$this->getCon()->isPluginAdmin() ) {
21
+ throw new \Exception( "You don't have permission to update the Security PIN." );
22
+ }
23
+
24
+ $mod = $this->getCon()->getModule_SecAdmin();
25
+ $mod->setIsMainFeatureEnabled( true );
26
+ $mod->getOptions()->setOpt( 'admin_access_key', md5( $pin ) );
27
+ ( new Shield\Modules\SecurityAdmin\Lib\SecurityAdmin\Ops\ToggleSecAdminStatus() )
28
+ ->setMod( $mod )
29
+ ->turnOn();
30
+ $mod->saveModOptions();
31
+
32
+ $resp = parent::processStepFormSubmit( $form );
33
+ $resp->success = true;
34
+ $resp->msg = __( 'Security Admin is now active', 'wp-simple-firewall' );
35
+ return $resp;
36
+ }
37
+
38
+ public function getName() :string {
39
+ return 'Security Admin';
40
+ }
41
+
42
+ protected function getStepRenderData() :array {
43
+ return [
44
+ 'strings' => [
45
+ 'step_title' => __( "Protect Your Shield Plugin From Tampering", 'wp-simple-firewall' ),
46
+ ],
47
+ 'vars' => [
48
+ ]
49
+ ];
50
+ }
51
+
52
+ public function skipStep() :bool {
53
+ return $this->getCon()
54
+ ->getModule_SecAdmin()
55
+ ->getSecurityAdminController()
56
+ ->isEnabledSecAdmin();
57
+ }
58
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/SecurityBadge.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ class SecurityBadge extends Base {
8
+
9
+ const SLUG = 'security_badge';
10
+
11
+ public function getName() :string {
12
+ return 'Badge';
13
+ }
14
+
15
+ protected function getStepRenderData() :array {
16
+ return [
17
+ 'strings' => [
18
+ 'step_title' => __( "Show Your Visitors That You Take Security Seriously!", 'wp-simple-firewall' ),
19
+ ],
20
+ 'vars' => [
21
+ 'video_id' => '552430272'
22
+ ],
23
+ ];
24
+ }
25
+
26
+ public function processStepFormSubmit( array $form ) :Shield\Utilities\Response {
27
+ $value = $form[ 'SecurityPluginBadge' ] ?? '';
28
+ if ( empty( $value ) ) {
29
+ throw new \Exception( 'Please select one of the options, or proceed to the next step.' );
30
+ }
31
+
32
+ $mod = $this->getCon()->getModule_Plugin();
33
+
34
+ $toEnable = $value === 'Y';
35
+ if ( $toEnable ) { // we don't disable the whole module
36
+ $mod->setIsMainFeatureEnabled( true );
37
+ }
38
+ $mod->getOptions()->setOpt( 'display_plugin_badge', $toEnable ? 'Y' : 'N' );
39
+ $mod->saveModOptions();
40
+
41
+ $resp = parent::processStepFormSubmit( $form );
42
+ $resp->success = true;
43
+ $resp->msg = $toEnable ? __( 'The Security Badge will be displayed to your visitors', 'wp-simple-firewall' )
44
+ : __( "The Security Badge won't be displayed to your visitors", 'wp-simple-firewall' );
45
+ return $resp;
46
+ }
47
+ }
src/lib/src/Modules/Insights/Lib/Merlin/Steps/ThankYou.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\Merlin\Steps;
4
+
5
+ class ThankYou extends Base {
6
+
7
+ const SLUG = 'thank_you';
8
+
9
+ public function getName() :string {
10
+ return 'Thanks!';
11
+ }
12
+
13
+ protected function getStepRenderData() :array {
14
+ $con = $this->getCon();
15
+ return [
16
+ 'hrefs' => [
17
+ 'facebook' => 'https://shsec.io/pluginshieldsecuritygroupfb',
18
+ 'twitter' => 'https://shsec.io/pluginshieldsecuritytwitter',
19
+ 'email' => 'https://shsec.io/pluginshieldsecuritynewsletter',
20
+ ],
21
+ 'imgs' => [
22
+ 'facebook' => $con->svgs->raw( 'bootstrap/facebook.svg' ),
23
+ 'twitter' => $con->svgs->raw( 'bootstrap/twitter.svg' ),
24
+ 'email' => $con->svgs->raw( 'bootstrap/envelope-fill.svg' ),
25
+ ],
26
+ 'vars' => [
27
+ 'video_id' => '269364269',
28
+ ],
29
+ 'strings' => [
30
+ 'step_title' => 'Thank You For Choosing Shield Security',
31
+ ],
32
+ ];
33
+ }
34
+ }
src/lib/src/Modules/Insights/Lib/MeterAnalysis/Handler.php CHANGED
@@ -17,24 +17,48 @@ class Handler {
17
  }
18
 
19
  public function renderDashboardMeters() :string {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  $con = $this->getCon();
21
- $mod = $this->getMod();
22
- return $mod->getRenderer()
23
- ->setTemplate( '/wpadmin_pages/insights/overview/progress_meter/progress_meters.twig' )
24
- ->setRenderData( [
25
- 'strings' => [
26
- 'analysis' => __( 'Analysis', 'wp-simple-firewall' ),
27
- ],
28
- 'imgs' => [
29
- 'svgs' => [
30
- 'analysis' => $con->svgs->raw( 'bootstrap/clipboard2-data-fill.svg' ),
31
- ],
32
- ],
33
- 'vars' => [
34
- 'progress_meters' => $this->buildAllMeterComponents()
35
- ],
36
- ] )
37
- ->render();
 
 
 
 
 
 
 
 
38
  }
39
 
40
  private function buildAllMeterComponents() :array {
@@ -71,10 +95,9 @@ class Handler {
71
 
72
  public function enumMeters() :array {
73
  $meters = [
74
- // MeterAll::class,
75
  MeterIntegrity::class,
76
- MeterAssets::class,
77
  MeterIpBlocking::class,
 
78
  MeterScans::class,
79
  MeterFirewall::class,
80
  MeterLockdown::class,
17
  }
18
 
19
  public function renderDashboardMeters() :string {
20
+ $meters = $this->renderMeters();
21
+ $primary = $meters[ MeterIntegrity::SLUG ];
22
+ unset( $meters[ MeterIntegrity::SLUG ] );
23
+ return $this->getMod()
24
+ ->getRenderer()
25
+ ->setTemplate( '/wpadmin_pages/insights/overview/progress_meter/progress_meters.twig' )
26
+ ->setRenderData( [
27
+ 'content' => [
28
+ 'primary_meter' => $primary,
29
+ 'meters' => $meters
30
+ ],
31
+ ] )
32
+ ->render();
33
+ }
34
+
35
+ private function renderMeters() :array {
36
  $con = $this->getCon();
37
+ $renderer = $this->getMod()
38
+ ->getRenderer()
39
+ ->setTemplate( '/wpadmin_pages/insights/overview/progress_meter/meter_card.twig' );
40
+ $renderData = [
41
+ 'strings' => [
42
+ 'analysis' => __( 'Analysis', 'wp-simple-firewall' ),
43
+ ],
44
+ 'imgs' => [
45
+ 'svgs' => [
46
+ 'analysis' => $con->svgs->raw( 'bootstrap/clipboard2-data-fill.svg' ),
47
+ ],
48
+ ],
49
+ ];
50
+
51
+ $meters = [];
52
+ foreach ( $this->buildAllMeterComponents() as $meterSlug => $meter ) {
53
+ $renderData[ 'vars' ] = [
54
+ 'meter_slug' => $meterSlug,
55
+ 'meter' => $meter,
56
+ ];
57
+ $meters[ $meterSlug ] = $renderer
58
+ ->setRenderData( $renderData )
59
+ ->render();
60
+ }
61
+ return $meters;
62
  }
63
 
64
  private function buildAllMeterComponents() :array {
95
 
96
  public function enumMeters() :array {
97
  $meters = [
 
98
  MeterIntegrity::class,
 
99
  MeterIpBlocking::class,
100
+ MeterAssets::class,
101
  MeterScans::class,
102
  MeterFirewall::class,
103
  MeterLockdown::class,
src/lib/src/Modules/Insights/Lib/MeterAnalysis/MeterIntegrity.php CHANGED
@@ -17,7 +17,7 @@ class MeterIntegrity extends MeterBase {
17
  }
18
 
19
  protected function title() :string {
20
- return __( 'Site Security Integrity', 'wp-simple-firewall' );
21
  }
22
 
23
  protected function subtitle() :string {
@@ -26,9 +26,11 @@ class MeterIntegrity extends MeterBase {
26
 
27
  protected function description() :array {
28
  return [
29
- __( "There are many components to a well-protected WordPress site.", 'wp-simple-firewall' ),
30
- __( "This section assesses from an overall perspective and will assist you in managing your WordPress security in the most effective way possible.", 'wp-simple-firewall' ),
31
- __( "There is an overall score included here that incorporates all other security overview scores.", 'wp-simple-firewall' ),
 
 
32
  ];
33
  }
34
 
17
  }
18
 
19
  protected function title() :string {
20
+ return __( 'Overall Site Security Integrity', 'wp-simple-firewall' );
21
  }
22
 
23
  protected function subtitle() :string {
26
 
27
  protected function description() :array {
28
  return [
29
+ __( "There are many aspects and considerations that affect the security of a WordPress website.", 'wp-simple-firewall' ),
30
+ __( "This section assesses your security from an high-level perspective so you can see, at a glance, how you're progressing.", 'wp-simple-firewall' )
31
+ .' '.__( "It uses a simple grading system from A - F, where A is best, and F is worst.", 'wp-simple-firewall' ),
32
+ __( "Your overall grade in this section incorporates all other security scores.", 'wp-simple-firewall' )
33
+ .' '.__( "Use the 'Analysis' buttons in each section to review the areas that might need improvement.", 'wp-simple-firewall' ),
34
  ];
35
  }
36
 
src/lib/src/Modules/Insights/Lib/NavMenuBuilder.php CHANGED
@@ -103,14 +103,7 @@ class NavMenuBuilder {
103
  'slug' => $slug.'-antibotsettings',
104
  'title' => __( 'AntiBot Config', 'wp-simple-firewall' ),
105
  'href' => $this->getOffCanvasJavascriptLinkFor( 'section_antibot' ),
106
- // 'href' => $con->getModule_IPs()->getUrl_DirectLinkToSection( 'section_antibot' ),
107
- ],
108
- // [ TODO
109
- // 'slug' => 'ips-download',
110
- // 'href' => $con->getModule_IPs()->createFileDownloadLink( 'db_ip' ),
111
- // 'classes' => [ 'shield_file_download' ],
112
- // 'title' => sprintf( __( 'Download (%s)', 'wp-simple-firewall' ), 'CSV' ),
113
- // ],
114
  ];
115
 
116
  return [
@@ -142,14 +135,7 @@ class NavMenuBuilder {
142
  'slug' => $slug.'-settings',
143
  'title' => __( 'Configure', 'wp-simple-firewall' ),
144
  'href' => $this->getOffCanvasJavascriptLinkFor( $con->getModule_AuditTrail()->getSlug() ),
145
- // 'href' => $con->getModule_AuditTrail()->getUrl_AdminPage(),
146
- ],
147
- // [
148
- // 'slug' => 'audit-download',
149
- // 'title' => sprintf( __( 'Download (%s)', 'wp-simple-firewall' ), 'JSON' ),
150
- // 'href' => $con->getModule_AuditTrail()->createFileDownloadLink( 'db_log' ),
151
- // 'classes' => [ 'shield_file_download' ],
152
- // ],
153
  [
154
  'slug' => 'audit-glossary',
155
  'title' => __( 'Glossary', 'wp-simple-firewall' ),
@@ -305,7 +291,6 @@ class NavMenuBuilder {
305
  }
306
 
307
  private function integrations() :array {
308
- $con = $this->getCon();
309
  return [
310
  'slug' => 'integrations',
311
  'img' => $this->getCon()->svgs->raw( 'bootstrap/puzzle.svg' ),
@@ -319,13 +304,11 @@ class NavMenuBuilder {
319
  'slug' => 'integrations-contact',
320
  'title' => __( 'Contact Form SPAM', 'wp-simple-firewall' ),
321
  'href' => $this->getOffCanvasJavascriptLinkFor( 'section_spam' ),
322
- // 'href' => $con->getModule_Integrations()->getUrl_DirectLinkToSection( '' ),
323
  ],
324
  [
325
  'slug' => 'integrations-login',
326
  'title' => __( 'Custom Login Forms', 'wp-simple-firewall' ),
327
  'href' => $this->getOffCanvasJavascriptLinkFor( 'section_user_forms' ),
328
- // 'href' => $con->getModule_Integrations()->getUrl_DirectLinkToSection( 'section_user_forms' ),
329
  ],
330
  ],
331
  ];
@@ -385,7 +368,6 @@ class NavMenuBuilder {
385
  }
386
 
387
  private function tools() :array {
388
- $con = $this->getCon();
389
  /** @var ModCon $mod */
390
  $mod = $this->getMod();
391
 
@@ -408,6 +390,12 @@ class NavMenuBuilder {
408
  'href' => $mod->getUrl_SubInsightsPage( 'notes' ),
409
  'active' => $this->getInav() === 'notes'
410
  ],
 
 
 
 
 
 
411
  [
412
  'slug' => $slug.'-rules',
413
  'title' => __( 'Rules', 'wp-simple-firewall' ),
@@ -434,7 +422,6 @@ class NavMenuBuilder {
434
  }
435
 
436
  private function traffic() :array {
437
- $con = $this->getCon();
438
  /** @var ModCon $mod */
439
  $mod = $this->getMod();
440
 
103
  'slug' => $slug.'-antibotsettings',
104
  'title' => __( 'AntiBot Config', 'wp-simple-firewall' ),
105
  'href' => $this->getOffCanvasJavascriptLinkFor( 'section_antibot' ),
106
+ ],
 
 
 
 
 
 
 
107
  ];
108
 
109
  return [
135
  'slug' => $slug.'-settings',
136
  'title' => __( 'Configure', 'wp-simple-firewall' ),
137
  'href' => $this->getOffCanvasJavascriptLinkFor( $con->getModule_AuditTrail()->getSlug() ),
138
+ ],
 
 
 
 
 
 
 
139
  [
140
  'slug' => 'audit-glossary',
141
  'title' => __( 'Glossary', 'wp-simple-firewall' ),
291
  }
292
 
293
  private function integrations() :array {
 
294
  return [
295
  'slug' => 'integrations',
296
  'img' => $this->getCon()->svgs->raw( 'bootstrap/puzzle.svg' ),
304
  'slug' => 'integrations-contact',
305
  'title' => __( 'Contact Form SPAM', 'wp-simple-firewall' ),
306
  'href' => $this->getOffCanvasJavascriptLinkFor( 'section_spam' ),
 
307
  ],
308
  [
309
  'slug' => 'integrations-login',
310
  'title' => __( 'Custom Login Forms', 'wp-simple-firewall' ),
311
  'href' => $this->getOffCanvasJavascriptLinkFor( 'section_user_forms' ),
 
312
  ],
313
  ],
314
  ];
368
  }
369
 
370
  private function tools() :array {
 
371
  /** @var ModCon $mod */
372
  $mod = $this->getMod();
373
 
390
  'href' => $mod->getUrl_SubInsightsPage( 'notes' ),
391
  'active' => $this->getInav() === 'notes'
392
  ],
393
+ [
394
+ 'slug' => $slug.'-merlin',
395
+ 'title' => __( 'Guided Setup', 'wp-simple-firewall' ),
396
+ 'href' => $mod->getUrl_SubInsightsPage( 'merlin' ),
397
+ 'active' => $this->getInav() === 'merlin'
398
+ ],
399
  [
400
  'slug' => $slug.'-rules',
401
  'title' => __( 'Rules', 'wp-simple-firewall' ),
422
  }
423
 
424
  private function traffic() :array {
 
425
  /** @var ModCon $mod */
426
  $mod = $this->getMod();
427
 
src/lib/src/Modules/Insights/ModCon.php CHANGED
@@ -24,7 +24,7 @@ class ModCon extends BaseShield\ModCon {
24
  $con = $this->getCon();
25
  if ( !Services::WpGeneral()->isAjax() && is_admin() ) {
26
  if ( !$con->isModulePage() && $con->getModule_Plugin()->getActivateLength() < 5 ) {
27
- Services::Response()->redirect( $con->getModule_Plugin()->getUrl_Wizard( 'welcome' ) );
28
  }
29
  elseif ( $this->getAdminPage()->isCurrentPage() && empty( $this->getCurrentInsightsPage() ) ) {
30
  Services::Response()->redirect( $con->getPluginUrl_DashboardHome() );
@@ -84,6 +84,38 @@ class ModCon extends BaseShield\ModCon {
84
  ],
85
  ]
86
  ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  $locals[] = [
89
  'shield/navigation',
@@ -136,6 +168,11 @@ class ModCon extends BaseShield\ModCon {
136
  ];
137
  break;
138
 
 
 
 
 
 
139
  case 'wizard':
140
  $enq[ Enqueue::JS ][] = 'shield/wizard';
141
  $enq[ Enqueue::CSS ][] = 'shield/wizard';
24
  $con = $this->getCon();
25
  if ( !Services::WpGeneral()->isAjax() && is_admin() ) {
26
  if ( !$con->isModulePage() && $con->getModule_Plugin()->getActivateLength() < 5 ) {
27
+ Services::Response()->redirect( $this->getUrl_SubInsightsPage( 'merlin' ) );
28
  }
29
  elseif ( $this->getAdminPage()->isCurrentPage() && empty( $this->getCurrentInsightsPage() ) ) {
30
  Services::Response()->redirect( $con->getPluginUrl_DashboardHome() );
84
  ],
85
  ]
86
  ];
87
+ $locals[] = [
88
+ 'shield/merlin',
89
+ 'merlin',
90
+ [
91
+ 'ajax' => [
92
+ 'merlin_action' => $this->getAjaxActionData( 'merlin_action' )
93
+ ],
94
+ 'vars' => [
95
+ /** http://techlaboratory.net/jquery-smartwizard#advanced-options */
96
+ 'smartwizard_cfg' => [
97
+ 'selected' => 0,
98
+ 'theme' => 'dots',
99
+ 'justified' => true,
100
+ 'autoAdjustHeight' => true,
101
+ 'backButtonSupport' => true,
102
+ 'enableUrlHash' => true,
103
+ 'lang' => [
104
+ 'next' => __( 'Next Step', 'wp-simple-firewall' ),
105
+ 'previous' => __( 'Previous Step', 'wp-simple-firewall' ),
106
+ ],
107
+ 'toolbar' => [
108
+ // both, top, none
109
+ 'position' => 'bottom',
110
+ // 'extraHtml' => '<a href="https://testing.aptotechnologies.com/test1/wp-admin/admin.php?page=icwp-wpsf-insights&amp;inav=overview"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-left" viewBox="0 0 16 16">
111
+ // <path fill-rule="evenodd" d="M6 12.5a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v2a.5.5 0 0 1-1 0v-2A1.5 1.5 0 0 1 6.5 2h8A1.5 1.5 0 0 1 16 3.5v9a1.5 1.5 0 0 1-1.5 1.5h-8A1.5 1.5 0 0 1 5 12.5v-2a.5.5 0 0 1 1 0v2z"></path>
112
+ // <path fill-rule="evenodd" d="M.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L1.707 7.5H10.5a.5.5 0 0 1 0 1H1.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"></path>
113
+ //</svg> Exit Wizard</a>',
114
+ ],
115
+ ]
116
+ ]
117
+ ]
118
+ ];
119
 
120
  $locals[] = [
121
  'shield/navigation',
168
  ];
169
  break;
170
 
171
+ case 'merlin':
172
+ $enq[ Enqueue::JS ][] = 'shield/merlin';
173
+ $enq[ Enqueue::CSS ][] = 'shield/merlin';
174
+ break;
175
+
176
  case 'wizard':
177
  $enq[ Enqueue::JS ][] = 'shield/wizard';
178
  $enq[ Enqueue::CSS ][] = 'shield/wizard';
src/lib/src/Modules/Insights/UI.php CHANGED
@@ -193,19 +193,17 @@ class UI extends BaseShield\UI {
193
  $data = $this->buildInsightsVars_Overview();
194
  break;
195
 
196
- case 'wizard':
197
- $wiz = $con->getModule_Plugin()->getWizardHandler();
198
- if ( $wiz instanceof \ICWP_WPSF_Wizard_Base ) {
199
- $data = [
200
- 'content' => [
201
- 'wizard' => $wiz->setCurrentWizard( $req->query( 'wizard' ) )
202
- ->renderWizard()
203
- ],
204
- 'flags' => [
205
- 'show_sidebar_nav' => 0
206
- ],
207
- ];
208
- }
209
  break;
210
  default:
211
  throw new \Exception( 'Not available' );
@@ -276,7 +274,10 @@ class UI extends BaseShield\UI {
276
  __( 'Tools', 'wp-simple-firewall' ),
277
  __( 'Rules', 'wp-simple-firewall' ),
278
  ],
279
- 'wizard' => __( 'Wizard', 'wp-simple-firewall' ),
 
 
 
280
  ];
281
 
282
  $pageTitle = is_array( $availablePages[ $inav ] ) ? implode( ' > ', $availablePages[ $inav ] ) : $availablePages[ $inav ];
@@ -286,24 +287,7 @@ class UI extends BaseShield\UI {
286
  __( 'Configuration', 'wp-simple-firewall' ), empty( $mod ) ? 'Unknown Module' : $mod->getMainFeatureName() );
287
  }
288
 
289
- if ( $con->getModule_SecAdmin()->getWhiteLabelController()->isEnabled() ) {
290
-
291
- if ( !empty( $con->labels ) ) {
292
- $bannerLogo = $con->labels->url_img_pagebanner;
293
- }
294
- else {
295
- /** @deprecated 15.1 */
296
- $bannerLogo = ( new Shield\Modules\SecurityAdmin\Lib\WhiteLabel\BuildOptions() )
297
- ->setMod( $con->getModule_SecAdmin() )
298
- ->build()[ 'url_login2fa_logourl' ];
299
- }
300
- }
301
- else {
302
- $bannerLogo = $con->urls->forImage( 'pluginlogo_banner-170x40.png' );
303
- }
304
-
305
- $DP = Services::DataManipulation();
306
- $data = $DP->mergeArraysRecursive(
307
  $this->getBaseDisplayData(),
308
  [
309
  'classes' => [
@@ -317,7 +301,7 @@ class UI extends BaseShield\UI {
317
  'nav_home' => $mod->getUrl_AdminPage(),
318
  ],
319
  'imgs' => [
320
- 'logo_banner' => $bannerLogo,
321
  ],
322
  'strings' => [
323
  'page_title' => $pageTitle
@@ -332,7 +316,7 @@ class UI extends BaseShield\UI {
332
  $data
333
  );
334
 
335
- $templateDir = $inav;
336
  if ( strpos( $inav, 'scans_' ) === 0 ) {
337
  $templateDir = implode( '/', explode( '_', $inav, 2 ) );
338
  }
@@ -430,7 +414,7 @@ class UI extends BaseShield\UI {
430
  'flags' => [
431
  'show_promo' => $con->isModulePage()
432
  && !$con->isPremiumActive()
433
- && ( !in_array( $nav, [ 'scans_results', 'scans_run', 'wizard' ] ) ),
434
  ],
435
  'hrefs' => [
436
  'go_pro' => 'https://shsec.io/shieldgoprofeature',
193
  $data = $this->buildInsightsVars_Overview();
194
  break;
195
 
196
+ case 'merlin':
197
+ $data = [
198
+ 'content' => [
199
+ 'page_main' => ( new Lib\Merlin\MerlinController() )
200
+ ->setMod( $mod )
201
+ ->render( empty( $subNavSection ) ? 'guided_setup_wizard' : $subNavSection )
202
+ ],
203
+ 'flags' => [
204
+ 'show_sidebar_nav' => 0
205
+ ],
206
+ ];
 
 
207
  break;
208
  default:
209
  throw new \Exception( 'Not available' );
274
  __( 'Tools', 'wp-simple-firewall' ),
275
  __( 'Rules', 'wp-simple-firewall' ),
276
  ],
277
+ 'merlin' => [
278
+ __( 'Wizard', 'wp-simple-firewall' ),
279
+ __( 'Guided Setup', 'wp-simple-firewall' ),
280
+ ],
281
  ];
282
 
283
  $pageTitle = is_array( $availablePages[ $inav ] ) ? implode( ' > ', $availablePages[ $inav ] ) : $availablePages[ $inav ];
287
  __( 'Configuration', 'wp-simple-firewall' ), empty( $mod ) ? 'Unknown Module' : $mod->getMainFeatureName() );
288
  }
289
 
290
+ $data = Services::DataManipulation()->mergeArraysRecursive(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  $this->getBaseDisplayData(),
292
  [
293
  'classes' => [
301
  'nav_home' => $mod->getUrl_AdminPage(),
302
  ],
303
  'imgs' => [
304
+ 'logo_banner' => $con->labels->url_img_pagebanner,
305
  ],
306
  'strings' => [
307
  'page_title' => $pageTitle
316
  $data
317
  );
318
 
319
+ $templateDir = in_array( $inav, [ 'merlin' ] ) ? 'default' : $inav;
320
  if ( strpos( $inav, 'scans_' ) === 0 ) {
321
  $templateDir = implode( '/', explode( '_', $inav, 2 ) );
322
  }
414
  'flags' => [
415
  'show_promo' => $con->isModulePage()
416
  && !$con->isPremiumActive()
417
+ && ( !in_array( $nav, [ 'scans_results', 'scans_run' ] ) ),
418
  ],
419
  'hrefs' => [
420
  'go_pro' => 'https://shsec.io/shieldgoprofeature',
src/lib/src/Modules/Lockdown/ModCon.php CHANGED
@@ -12,7 +12,7 @@ class ModCon extends BaseShield\ModCon {
12
  return [
13
  $opts->isXmlrpcDisabled() ? Rules\Build\DisableXmlrpc::class : null,
14
  $opts->isOptFileEditingDisabled() ? Rules\Build\DisableFileEditing::class : null,
15
- Rules\Build\IsRequestAuthorDiscovery::class,
16
  $opts->isOpt( 'hide_wordpress_generator_tag', 'Y' ) ? Rules\Build\HideGeneratorTag::class : null,
17
  ( $opts->isOpt( 'force_ssl_admin', 'Y' ) && function_exists( 'force_ssl_admin' ) ) ? Rules\Build\ForceSslAdmin::class : null,
18
  ];
12
  return [
13
  $opts->isXmlrpcDisabled() ? Rules\Build\DisableXmlrpc::class : null,
14
  $opts->isOptFileEditingDisabled() ? Rules\Build\DisableFileEditing::class : null,
15
+ $opts->isOpt( 'block_author_discovery', 'Y' ) ? Rules\Build\IsRequestAuthorDiscovery::class : null,
16
  $opts->isOpt( 'hide_wordpress_generator_tag', 'Y' ) ? Rules\Build\HideGeneratorTag::class : null,
17
  ( $opts->isOpt( 'force_ssl_admin', 'Y' ) && function_exists( 'force_ssl_admin' ) ) ? Rules\Build\ForceSslAdmin::class : null,
18
  ];
src/lib/src/Modules/Lockdown/Rules/Build/IsRequestAuthorDiscovery.php CHANGED
@@ -38,7 +38,7 @@ class IsRequestAuthorDiscovery extends BuildRuleCoreShieldBase {
38
  'params' => [
39
  'match_param' => 'author',
40
  'match_patterns' => [
41
- '^\d+$'
42
  ],
43
  ],
44
  ],
38
  'params' => [
39
  'match_param' => 'author',
40
  'match_patterns' => [
41
+ '\d'
42
  ],
43
  ],
44
  ],
src/lib/src/Modules/LoginGuard/UI.php CHANGED
@@ -4,6 +4,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Common\BaseHandler;
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Time\WorldTimeApi;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
@@ -64,8 +65,7 @@ class UI extends BaseShield\UI {
64
  );
65
  }
66
  }
67
-
68
- if ( $section == 'section_2fa_ga' ) {
69
  try {
70
  $diff = ( new WorldTimeApi() )->diffServerWithReal();
71
  if ( $diff > 10 ) {
@@ -89,4 +89,18 @@ class UI extends BaseShield\UI {
89
 
90
  return $warnings;
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Common\BaseHandler;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\IpRules\IpRuleStatus;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Time\WorldTimeApi;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
65
  );
66
  }
67
  }
68
+ elseif ( $section == 'section_2fa_ga' ) {
 
69
  try {
70
  $diff = ( new WorldTimeApi() )->diffServerWithReal();
71
  if ( $diff > 10 ) {
89
 
90
  return $warnings;
91
  }
92
+
93
+ public function getSectionCriticalWarnings( string $section ) :array {
94
+ $warnings = [];
95
+ if ( $section == 'section_rename_wplogin' ) {
96
+ $isBypass = ( new IpRuleStatus( $this->getCon()->this_req->ip ) )
97
+ ->setMod( $this->getMod() )
98
+ ->isBypass();
99
+ if ( $isBypass ) {
100
+ $warnings[] = sprintf( __( "Your IP address is whitelisted! This setting doesn't apply to YOU, so you must always use the normal login page: %s" ),
101
+ basename( Services::WpGeneral()->getLoginUrl() ) );
102
+ }
103
+ }
104
+ return $warnings;
105
+ }
106
  }
src/lib/src/Modules/Plugin/AdminNotices.php CHANGED
@@ -49,10 +49,6 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
49
  $this->buildNotice_PluginMailingListSignup( $notice );
50
  break;
51
 
52
- case 'wizard_welcome':
53
- $this->buildNotice_WelcomeWizard( $notice );
54
- break;
55
-
56
  case 'allow-tracking':
57
  $this->buildNotice_AllowTracking( $notice );
58
  break;
@@ -230,25 +226,6 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
230
  ];
231
  }
232
 
233
- private function buildNotice_WelcomeWizard( NoticeVO $notice ) {
234
- $name = $this->getCon()->getHumanName();
235
- $insideWizard = Services::Request()->query( 'wizard', false ) === 'welcome';
236
- $notice->render_data = [
237
- 'notice_attributes' => [
238
- 'insideWizard' => $insideWizard ? 1 : 0,
239
- ],
240
- 'strings' => [
241
- 'dismiss' => __( "I don't need the setup wizard just now", 'wp-simple-firewall' ),
242
- 'title' => sprintf( __( 'Get started quickly with the %s Setup Wizard', 'wp-simple-firewall' ), $name ),
243
- 'setup' => sprintf( __( 'The welcome wizard will help you get setup quickly and become familiar with some of the core %s features', 'wp-simple-firewall' ), $name ),
244
- 'launch' => sprintf( __( "Launch the welcome wizard", 'wp-simple-firewall' ), $name ),
245
- ],
246
- 'hrefs' => [
247
- 'wizard' => $this->getMod()->getUrl_Wizard( 'welcome' ),
248
- ],
249
- ];
250
- }
251
-
252
  private function buildNotice_AllowTracking( NoticeVO $notice ) {
253
  /** @var ModCon $mod */
254
  $mod = $this->getMod();
@@ -306,10 +283,6 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
306
  $needed = $this->isNeeded_DatabasesNotReady();
307
  break;
308
 
309
- case 'wizard_welcome':
310
- $needed = false;
311
- break;
312
-
313
  case 'rules-not-running':
314
  $needed = $this->isNeeded_RulesNotRunning();
315
  break;
49
  $this->buildNotice_PluginMailingListSignup( $notice );
50
  break;
51
 
 
 
 
 
52
  case 'allow-tracking':
53
  $this->buildNotice_AllowTracking( $notice );
54
  break;
226
  ];
227
  }
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  private function buildNotice_AllowTracking( NoticeVO $notice ) {
230
  /** @var ModCon $mod */
231
  $mod = $this->getMod();
283
  $needed = $this->isNeeded_DatabasesNotReady();
284
  break;
285
 
 
 
 
 
286
  case 'rules-not-running':
287
  $needed = $this->isNeeded_RulesNotRunning();
288
  break;
src/lib/src/Modules/Plugin/AjaxHandler.php CHANGED
@@ -33,7 +33,6 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
33
  'render_dashboard_widget' => [ $this, 'ajaxExec_RenderDashboardWidget' ],
34
  'render_offcanvas' => [ $this, 'ajaxExec_RenderOffCanvas' ],
35
  'select_search' => [ $this, 'ajaxExec_SelectSearch' ],
36
- 'wizard_step' => [ $this, 'ajaxExec_Wizard' ],
37
  ] );
38
  }
39
  return $map;
@@ -157,7 +156,6 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
157
  $success = false;
158
  }
159
  break;
160
-
161
  }
162
 
163
  return [
@@ -175,18 +173,6 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
175
  ];
176
  }
177
 
178
- public function ajaxExec_Wizard() :array {
179
- $params = FormParams::Retrieve();
180
- // step will be step1, step2 etc.
181
- $currentStep = intval( str_replace( 'step', '', $params[ 'step' ] ) );
182
- $data = $params[ $params[ 'step' ] ];
183
- return [
184
- 'success' => true,
185
- 'message' => $currentStep < 3 ? $data : 'done done done',
186
- 'next' => $currentStep < 3 ? 'step'.++$currentStep : 'done',
187
- ];
188
- }
189
-
190
  public function ajaxExec_PluginBadgeClose() :array {
191
  /** @var ModCon $mod */
192
  $mod = $this->getMod();
33
  'render_dashboard_widget' => [ $this, 'ajaxExec_RenderDashboardWidget' ],
34
  'render_offcanvas' => [ $this, 'ajaxExec_RenderOffCanvas' ],
35
  'select_search' => [ $this, 'ajaxExec_SelectSearch' ],
 
36
  ] );
37
  }
38
  return $map;
156
  $success = false;
157
  }
158
  break;
 
159
  }
160
 
161
  return [
173
  ];
174
  }
175
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  public function ajaxExec_PluginBadgeClose() :array {
177
  /** @var ModCon $mod */
178
  $mod = $this->getMod();
src/lib/src/Modules/Plugin/Debug.php CHANGED
@@ -115,7 +115,7 @@ class Debug extends Modules\Base\Debug {
115
  // ->getLicense()->crowdsec[ 'scenarios' ] ?? [];
116
 
117
  error_log( 'memory: '.round( memory_get_usage()/1024/1024 ) );
118
- var_dump( 'ready: '.var_export( $API->isReady(), true ) );
119
  // $res = ( new DecisionsDownload( $api->getAuthorizationToken(), 'crowdsec/1.2.1' ) )->run();
120
 
121
  // var_dump( $modIPs->getOptions()->getOpt('crowdsec_cfg') );
@@ -128,9 +128,9 @@ class Debug extends Modules\Base\Debug {
128
  // ( new Modules\IPs\Lib\CrowdSec\Signals\PushSignalsToCS() )
129
  // ->setMod( $this->getCon()->getModule_IPs() )
130
  // ->execute();
131
- // ( new Modules\IPs\Lib\CrowdSec\Decisions\ImportDecisions() )
132
- // ->setMod( $modIPs )
133
- // ->execute();
134
  // var_dump( $d );
135
  // $res = ( new Modules\IPs\Lib\CrowdSec\Api\DecisionsDownload(
136
  // $csCon->getApi()->getAuthorizationToken(),
115
  // ->getLicense()->crowdsec[ 'scenarios' ] ?? [];
116
 
117
  error_log( 'memory: '.round( memory_get_usage()/1024/1024 ) );
118
+ var_dump( 'api ready: '.var_export( $API->isReady(), true ) );
119
  // $res = ( new DecisionsDownload( $api->getAuthorizationToken(), 'crowdsec/1.2.1' ) )->run();
120
 
121
  // var_dump( $modIPs->getOptions()->getOpt('crowdsec_cfg') );
128
  // ( new Modules\IPs\Lib\CrowdSec\Signals\PushSignalsToCS() )
129
  // ->setMod( $this->getCon()->getModule_IPs() )
130
  // ->execute();
131
+ ( new Modules\IPs\Lib\CrowdSec\Decisions\ImportDecisions() )
132
+ ->setMod( $modIPs )
133
+ ->runImport();
134
  // var_dump( $d );
135
  // $res = ( new Modules\IPs\Lib\CrowdSec\Api\DecisionsDownload(
136
  // $csCon->getApi()->getAuthorizationToken(),
src/lib/src/Modules/Plugin/Lib/SelectSearchData.php CHANGED
@@ -256,6 +256,13 @@ class SelectSearchData {
256
  'tokens' => 'tool overview grade grading charts performance dashboard summary',
257
  'icon' => $this->getCon()->svgs->raw( 'bootstrap/speedometer.svg' ),
258
  ],
 
 
 
 
 
 
 
259
  [
260
  'id' => 'tool_debug',
261
  'text' => __( 'View Debug Info', 'wp-simple-firewall' ),
256
  'tokens' => 'tool overview grade grading charts performance dashboard summary',
257
  'icon' => $this->getCon()->svgs->raw( 'bootstrap/speedometer.svg' ),
258
  ],
259
+ [
260
+ 'id' => 'tool_guidedsetup',
261
+ 'text' => __( 'Run Guided Setup Wizard', 'wp-simple-firewall' ),
262
+ 'href' => $modInsights->getUrl_SubInsightsPage( 'merlin' ),
263
+ 'tokens' => 'tool setup guide guided wizard',
264
+ 'icon' => $this->getCon()->svgs->raw( 'bootstrap/magic.svg' ),
265
+ ],
266
  [
267
  'id' => 'tool_debug',
268
  'text' => __( 'View Debug Info', 'wp-simple-firewall' ),
src/lib/src/Modules/Plugin/UI.php CHANGED
@@ -30,33 +30,6 @@ class UI extends BaseShield\UI {
30
  ];
31
  }
32
 
33
- public function buildInsightsVars_Wizard( $wizard, $step ) :array {
34
- $data = [];
35
- switch ( $wizard ) {
36
- case 'welcome':
37
- $data = [
38
- 'steps' => [
39
- 'step1' => 'content for step1',
40
- 'step2' => 'content for step2',
41
- 'step3' => 'content for step3',
42
- ],
43
- 'currentStep' => 'step'.$step,
44
- 'ajax' => [
45
- 'wizard_step' => $this->getMod()->getAjaxActionData( 'wizard_step', true ),
46
- ],
47
- 'strings' => [
48
- 'hohoho' => sprintf( __( '%s %s Page' ), $wizard, $this->getCon()->getHumanName() ),
49
- ],
50
- 'showSideNav' => 0,
51
- ];
52
- break;
53
- default:
54
- break;
55
- }
56
-
57
- return $data;
58
- }
59
-
60
  public function getSectionWarnings( string $section ) :array {
61
  /** @var ModCon $mod */
62
  $mod = $this->getMod();
30
  ];
31
  }
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  public function getSectionWarnings( string $section ) :array {
34
  /** @var ModCon $mod */
35
  $mod = $this->getMod();
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Ops/ToggleSecAdminStatus.php CHANGED
@@ -24,6 +24,7 @@ class ToggleSecAdminStatus {
24
  ->getModule_Sessions()
25
  ->getSessionCon()
26
  ->updateSessionParameter( 'secadmin_at', $onOrOff ? Services::Request()->ts() : 0 );
 
27
  }
28
  return (bool)$session->valid;
29
  }
24
  ->getModule_Sessions()
25
  ->getSessionCon()
26
  ->updateSessionParameter( 'secadmin_at', $onOrOff ? Services::Request()->ts() : 0 );
27
+ $this->getCon()->this_req->is_security_admin = $onOrOff;
28
  }
29
  return (bool)$session->valid;
30
  }
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php CHANGED
@@ -35,6 +35,33 @@ class SecurityAdminController extends ExecOnceModConsumer {
35
  if ( !$this->getCon()->isThisPluginModuleRequest() ) {
36
  add_action( 'admin_footer', [ $this, 'printPinLoginForm' ] );
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
  }
40
 
@@ -54,8 +81,7 @@ class SecurityAdminController extends ExecOnceModConsumer {
54
  public function isEnabledSecAdmin() :bool {
55
  /** @var Options $opts */
56
  $opts = $this->getOptions();
57
- return $this->getMod()->isModOptEnabled() &&
58
- $opts->hasSecurityPIN() && $this->getSecAdminTimeout() > 0;
59
  }
60
 
61
  private function enqueueJS() {
35
  if ( !$this->getCon()->isThisPluginModuleRequest() ) {
36
  add_action( 'admin_footer', [ $this, 'printPinLoginForm' ] );
37
  }
38
+
39
+ add_action( 'pre_uninstall_plugin', function ( $pluginFile ) {
40
+ // This can only protect against rogue, programmatic uninstalls, not when Shield is inactive.
41
+ if ( $pluginFile === $this->getCon()->base_file ) {
42
+ $this->blockRemoval();
43
+ }
44
+ } );
45
+ add_action( $this->getCon()->prefix( 'pre_deactivate_plugin' ), [ $this, 'blockRemoval' ] );
46
+ }
47
+ }
48
+
49
+ public function blockRemoval() {
50
+ if ( !$this->getCon()->isPluginAdmin() ) {
51
+ if ( !Services::WpUsers()->isUserAdmin() ) {
52
+ $this->getCon()->fireEvent( 'attempt_deactivation' );
53
+ }
54
+ Services::WpGeneral()->wpDie(
55
+ sprintf(
56
+ '<p>%s</p><p>%s</p>',
57
+ __( "Sorry, this plugin is protected against unauthorised attempts to disable it.", 'wp-simple-firewall' ),
58
+ sprintf( '<a href="%s">%s</a>',
59
+ $this->getMod()->getUrl_AdminPage(),
60
+ sprintf( __( "Please authenticate with the %s Security Admin system and try again.", 'wp-simple-firewall' ),
61
+ $this->getCon()->getHumanName() )
62
+ )
63
+ )
64
+ );
65
  }
66
  }
67
 
81
  public function isEnabledSecAdmin() :bool {
82
  /** @var Options $opts */
83
  $opts = $this->getOptions();
84
+ return $this->getMod()->isModOptEnabled() && $opts->hasSecurityPIN() && $this->getSecAdminTimeout() > 0;
 
85
  }
86
 
87
  private function enqueueJS() {
src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/WhitelabelController.php CHANGED
@@ -151,8 +151,6 @@ class WhitelabelController extends ExecOnceModConsumer {
151
  * Full URL
152
  * Relative path URL: i.e. starts with /
153
  * Or Plugin image URL i.e. doesn't start with HTTP or /
154
- * @param string $key
155
- * @return string
156
  */
157
  private function constructImageURL( string $key ) :string {
158
  $opts = $this->getOptions();
151
  * Full URL
152
  * Relative path URL: i.e. starts with /
153
  * Or Plugin image URL i.e. doesn't start with HTTP or /
 
 
154
  */
155
  private function constructImageURL( string $key ) :string {
156
  $opts = $this->getOptions();
src/lib/src/Modules/SecurityAdmin/ModCon.php CHANGED
@@ -26,10 +26,6 @@ class ModCon extends BaseShield\ModCon {
26
  ];
27
  }
28
 
29
- protected function setupCustomHooks() {
30
- add_action( $this->getCon()->prefix( 'pre_deactivate_plugin' ), [ $this, 'preDeactivatePlugin' ] );
31
- }
32
-
33
  public function getWhiteLabelController() :Lib\WhiteLabel\WhitelabelController {
34
  if ( !$this->whitelabelCon instanceof Lib\WhiteLabel\WhitelabelController ) {
35
  $this->whitelabelCon = ( new Lib\WhiteLabel\WhitelabelController() )
@@ -106,28 +102,6 @@ class ModCon extends BaseShield\ModCon {
106
  }
107
  }
108
 
109
- /**
110
- * Used by Wizard. TODO: sort out the wizard requests!
111
- * @return $this
112
- * @throws \Exception
113
- */
114
- public function setNewPinManually( string $pin ) {
115
- if ( empty( $pin ) ) {
116
- throw new \Exception( 'Attempting to set an empty Security PIN.' );
117
- }
118
- if ( !$this->getCon()->isPluginAdmin() ) {
119
- throw new \Exception( 'User does not have permission to update the Security PIN.' );
120
- }
121
-
122
- $this->setIsMainFeatureEnabled( true );
123
- $this->getOptions()->setOpt( 'admin_access_key', md5( $pin ) );
124
- ( new Lib\SecurityAdmin\Ops\ToggleSecAdminStatus() )
125
- ->setMod( $this )
126
- ->turnOn();
127
-
128
- return $this->saveModOptions();
129
- }
130
-
131
  /**
132
  * This is the point where you would want to do any options verification
133
  */
@@ -169,15 +143,9 @@ class ModCon extends BaseShield\ModCon {
169
  }
170
  }
171
 
 
 
 
172
  public function preDeactivatePlugin() {
173
- if ( !$this->getCon()->isPluginAdmin() ) {
174
- Services::WpGeneral()->wpDie(
175
- __( "Sorry, this plugin is protected against unauthorised attempts to disable it.", 'wp-simple-firewall' )
176
- .'<br />'.sprintf( '<a href="%s">%s</a>',
177
- $this->getUrl_AdminPage(),
178
- __( "You'll just need to authenticate first and try again.", 'wp-simple-firewall' )
179
- )
180
- );
181
- }
182
  }
183
  }
26
  ];
27
  }
28
 
 
 
 
 
29
  public function getWhiteLabelController() :Lib\WhiteLabel\WhitelabelController {
30
  if ( !$this->whitelabelCon instanceof Lib\WhiteLabel\WhitelabelController ) {
31
  $this->whitelabelCon = ( new Lib\WhiteLabel\WhitelabelController() )
102
  }
103
  }
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  /**
106
  * This is the point where you would want to do any options verification
107
  */
143
  }
144
  }
145
 
146
+ /**
147
+ * @deprecated 16.1
148
+ */
149
  public function preDeactivatePlugin() {
 
 
 
 
 
 
 
 
 
150
  }
151
  }
src/lib/src/Modules/SecurityAdmin/Strings.php CHANGED
@@ -11,18 +11,25 @@ class Strings extends Base\Strings {
11
  */
12
  public function getEventStrings() :array {
13
  return [
14
- 'key_success' => [
15
  'name' => __( 'Security PIN Pass', 'wp-simple-firewall' ),
16
  'audit' => [
17
  __( 'Security PIN authentication successful.', 'wp-simple-firewall' ),
18
  ],
19
  ],
20
- 'key_fail' => [
21
  'name' => __( 'Security PIN Fail', 'wp-simple-firewall' ),
22
  'audit' => [
23
  __( 'Security PIN authentication failed.', 'wp-simple-firewall' ),
24
  ],
25
  ],
 
 
 
 
 
 
 
26
  ];
27
  }
28
 
11
  */
12
  public function getEventStrings() :array {
13
  return [
14
+ 'key_success' => [
15
  'name' => __( 'Security PIN Pass', 'wp-simple-firewall' ),
16
  'audit' => [
17
  __( 'Security PIN authentication successful.', 'wp-simple-firewall' ),
18
  ],
19
  ],
20
+ 'key_fail' => [
21
  'name' => __( 'Security PIN Fail', 'wp-simple-firewall' ),
22
  'audit' => [
23
  __( 'Security PIN authentication failed.', 'wp-simple-firewall' ),
24
  ],
25
  ],
26
+ 'attempt_deactivation' => [
27
+ 'name' => __( 'Unauthorized Deactivation Attempt', 'wp-simple-firewall' ),
28
+ 'audit' => [
29
+ sprintf( __( 'An attempt to deactivate the %s plugin by a non-admin was intercepted.', 'wp-simple-firewall' ),
30
+ $this->getCon()->getHumanName() ),
31
+ ],
32
+ ],
33
  ];
34
  }
35
 
src/lib/src/Modules/Traffic/Lib/TrafficTable/BuildTrafficTableData.php CHANGED
@@ -8,7 +8,7 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LogRecord;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\Ops\Handler;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\Lib\GeoIP\Lookup;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\IpRules\IpRuleStatus;
11
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Traffic\ForTraffic;
12
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseBuildTableData;
13
  use FernleafSystems\Wordpress\Services\Services;
14
  use FernleafSystems\Wordpress\Services\Utilities\Net\IpID;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\Ops\Handler;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\Lib\GeoIP\Lookup;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\IpRules\IpRuleStatus;
11
+ use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\ForTraffic;
12
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseBuildTableData;
13
  use FernleafSystems\Wordpress\Services\Services;
14
  use FernleafSystems\Wordpress\Services\Utilities\Net\IpID;
src/lib/src/Modules/Traffic/UI.php CHANGED
@@ -3,7 +3,7 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Traffic\ForTraffic;
7
 
8
  class UI extends BaseShield\UI {
9
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\ForTraffic;
7
 
8
  class UI extends BaseShield\UI {
9
 
src/lib/src/Tables/DataTables/Build/{AuditTrail/ForAuditTrail.php → ForAuditTrail.php} RENAMED
@@ -1,8 +1,6 @@
1
  <?php declare( strict_types=1 );
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\AuditTrail;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Base;
6
 
7
  class ForAuditTrail extends Base {
8
 
@@ -142,27 +140,28 @@ class ForAuditTrail extends Base {
142
  ],
143
  ],
144
  'date' => [
145
- 'data' => [
146
  '_' => 'created_since',
147
  'sort' => 'created_at',
148
  ],
149
- 'title' => __( 'Date' ),
150
- 'className' => 'date',
151
- 'orderable' => true,
152
- 'searchable' => false,
153
- 'visible' => true,
154
- 'searchPanes' => [
 
155
  'show' => false
156
  ],
157
  ],
158
  'meta' => [
159
- 'data' => 'meta',
160
- 'title' => __( 'Meta' ),
161
- 'className' => 'meta',
162
- 'orderable' => false,
163
- 'searchable' => false,
164
- 'visible' => true,
165
- 'searchPanes' => [
166
  'show' => false
167
  ],
168
  ],
1
  <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build;
 
 
4
 
5
  class ForAuditTrail extends Base {
6
 
140
  ],
141
  ],
142
  'date' => [
143
+ 'data' => [
144
  '_' => 'created_since',
145
  'sort' => 'created_at',
146
  ],
147
+ 'title' => __( 'Date' ),
148
+ 'className' => 'date',
149
+ 'orderable' => true,
150
+ 'orderSequence' => [ 'desc', 'asc' ],
151
+ 'searchable' => false,
152
+ 'visible' => true,
153
+ 'searchPanes' => [
154
  'show' => false
155
  ],
156
  ],
157
  'meta' => [
158
+ 'data' => 'meta',
159
+ 'title' => __( 'Meta' ),
160
+ 'className' => 'meta',
161
+ 'orderable' => false,
162
+ 'searchable' => false,
163
+ 'visible' => true,
164
+ 'searchPanes' => [
165
  'show' => false
166
  ],
167
  ],
src/lib/src/Tables/DataTables/Build/{IpRules/ForIpRules.php → ForIpRules.php} RENAMED
@@ -1,8 +1,6 @@
1
  <?php declare( strict_types=1 );
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\IpRules;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Base;
6
 
7
  class ForIpRules extends Base {
8
 
@@ -26,7 +24,7 @@ class ForIpRules extends Base {
26
 
27
  protected function getColumnDefs() :array {
28
  return [
29
- 'ip' => [
30
  'data' => 'ip',
31
  'title' => __( 'IP Address' ),
32
  'className' => 'ip',
@@ -37,7 +35,7 @@ class ForIpRules extends Base {
37
  'show' => true,
38
  ],
39
  ],
40
- 'ip_linked' => [
41
  'data' => 'ip_linked',
42
  'title' => __( 'IP Address or Range' ),
43
  'className' => 'ip_linked',
@@ -48,7 +46,7 @@ class ForIpRules extends Base {
48
  'show' => false,
49
  ],
50
  ],
51
- 'status' => [
52
  'data' => 'status',
53
  'title' => __( 'Status' ),
54
  'className' => 'status',
@@ -59,7 +57,7 @@ class ForIpRules extends Base {
59
  'show' => false,
60
  ],
61
  ],
62
- 'type' => [
63
  'data' => 'type',
64
  'title' => __( 'Type' ),
65
  'className' => 'type',
@@ -70,32 +68,34 @@ class ForIpRules extends Base {
70
  'show' => true,
71
  ],
72
  ],
73
- 'last_seen' => [
74
- 'data' => [
75
  '_' => 'last_seen',
76
  'sort' => 'last_access_at',
77
  ],
78
- 'title' => __( 'Last Seen' ),
79
- 'className' => 'date',
80
- 'orderable' => true,
81
- 'searchable' => false,
82
- 'visible' => true,
83
- 'searchPanes' => [
 
84
  'show' => false
85
  ],
86
  ],
87
- 'last_access_at' => [
88
- 'data' => 'last_access_at',
89
- 'title' => __( 'Last Access At' ),
90
- 'className' => 'date',
91
- 'orderable' => true,
92
- 'searchable' => false,
93
- 'visible' => false,
94
- 'searchPanes' => [
 
95
  'show' => false
96
  ],
97
  ],
98
- 'is_blocked' => [
99
  'data' => 'is_blocked',
100
  'title' => __( 'IP Block Status' ),
101
  'className' => 'is_blocked',
@@ -106,7 +106,7 @@ class ForIpRules extends Base {
106
  'show' => true
107
  ],
108
  ],
109
- 'unblocked_at' => [
110
  'data' => 'unblocked_at',
111
  'title' => __( 'Unblocked At' ),
112
  'className' => 'unblocked_at',
@@ -117,17 +117,18 @@ class ForIpRules extends Base {
117
  'show' => false
118
  ],
119
  ],
120
- 'date' => [
121
- 'data' => [
122
  '_' => 'created_since',
123
  'sort' => 'created_at',
124
  ],
125
- 'title' => __( 'Date Added' ),
126
- 'className' => 'date',
127
- 'orderable' => true,
128
- 'searchable' => false,
129
- 'visible' => true,
130
- 'searchPanes' => [
 
131
  'show' => false
132
  ],
133
  ],
1
  <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build;
 
 
4
 
5
  class ForIpRules extends Base {
6
 
24
 
25
  protected function getColumnDefs() :array {
26
  return [
27
+ 'ip' => [
28
  'data' => 'ip',
29
  'title' => __( 'IP Address' ),
30
  'className' => 'ip',
35
  'show' => true,
36
  ],
37
  ],
38
+ 'ip_linked' => [
39
  'data' => 'ip_linked',
40
  'title' => __( 'IP Address or Range' ),
41
  'className' => 'ip_linked',
46
  'show' => false,
47
  ],
48
  ],
49
+ 'status' => [
50
  'data' => 'status',
51
  'title' => __( 'Status' ),
52
  'className' => 'status',
57
  'show' => false,
58
  ],
59
  ],
60
+ 'type' => [
61
  'data' => 'type',
62
  'title' => __( 'Type' ),
63
  'className' => 'type',
68
  'show' => true,
69
  ],
70
  ],
71
+ 'last_seen' => [
72
+ 'data' => [
73
  '_' => 'last_seen',
74
  'sort' => 'last_access_at',
75
  ],
76
+ 'title' => __( 'Last Seen' ),
77
+ 'className' => 'date',
78
+ 'orderable' => true,
79
+ 'orderSequence' => [ 'desc', 'asc' ],
80
+ 'searchable' => false,
81
+ 'visible' => true,
82
+ 'searchPanes' => [
83
  'show' => false
84
  ],
85
  ],
86
+ 'last_access_at' => [
87
+ 'data' => 'last_access_at',
88
+ 'title' => __( 'Last Access At' ),
89
+ 'className' => 'date',
90
+ 'orderable' => true,
91
+ 'orderSequence' => [ 'desc', 'asc' ],
92
+ 'searchable' => false,
93
+ 'visible' => false,
94
+ 'searchPanes' => [
95
  'show' => false
96
  ],
97
  ],
98
+ 'is_blocked' => [
99
  'data' => 'is_blocked',
100
  'title' => __( 'IP Block Status' ),
101
  'className' => 'is_blocked',
106
  'show' => true
107
  ],
108
  ],
109
+ 'unblocked_at' => [
110
  'data' => 'unblocked_at',
111
  'title' => __( 'Unblocked At' ),
112
  'className' => 'unblocked_at',
117
  'show' => false
118
  ],
119
  ],
120
+ 'date' => [
121
+ 'data' => [
122
  '_' => 'created_since',
123
  'sort' => 'created_at',
124
  ],
125
+ 'title' => __( 'Date Added' ),
126
+ 'className' => 'date',
127
+ 'orderable' => true,
128
+ 'orderSequence' => [ 'desc', 'asc' ],
129
+ 'searchable' => false,
130
+ 'visible' => true,
131
+ 'searchPanes' => [
132
  'show' => false
133
  ],
134
  ],
src/lib/src/Tables/DataTables/Build/{Traffic/ForTraffic.php → ForTraffic.php} RENAMED
@@ -1,8 +1,6 @@
1
  <?php declare( strict_types=1 );
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Traffic;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Base;
6
 
7
  class ForTraffic extends Base {
8
 
@@ -146,16 +144,17 @@ class ForTraffic extends Base {
146
  'visible' => false,
147
  ],
148
  'date' => [
149
- 'data' => [
150
  '_' => 'created_since',
151
  'sort' => 'created_at',
152
  ],
153
- 'title' => __( 'Date' ),
154
- 'className' => 'date',
155
- 'orderable' => true,
156
- 'searchable' => false,
157
- 'visible' => true,
158
- 'searchPanes' => [
 
159
  'show' => false
160
  ],
161
  ],
1
  <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build;
 
 
4
 
5
  class ForTraffic extends Base {
6
 
144
  'visible' => false,
145
  ],
146
  'date' => [
147
+ 'data' => [
148
  '_' => 'created_since',
149
  'sort' => 'created_at',
150
  ],
151
+ 'title' => __( 'Date' ),
152
+ 'className' => 'date',
153
+ 'orderable' => true,
154
+ 'orderSequence' => [ 'desc', 'asc' ],
155
+ 'searchable' => false,
156
+ 'visible' => true,
157
+ 'searchPanes' => [
158
  'show' => false
159
  ],
160
  ],
src/lib/src/Utilities/Response.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Utilities;
4
+
5
+ use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
+
7
+ /**
8
+ * @property bool $success
9
+ * @property int $error_code
10
+ * @property string $msg
11
+ * @property string $error
12
+ * @property string $debug
13
+ * @property array $data
14
+ */
15
+ class Response extends DynPropertiesClass {
16
+
17
+ public function __get( string $key ) {
18
+ $value = parent::__get( $key );
19
+ switch ( $key ) {
20
+
21
+ case 'data':
22
+ $value = is_array( $value ) ? $value : [];
23
+ break;
24
+
25
+ case 'msg':
26
+ case 'error':
27
+ case 'debug':
28
+ $value = (string)$value;
29
+ break;
30
+
31
+ case 'error_code':
32
+ $value = (int)$value;
33
+ break;
34
+
35
+ case 'success':
36
+ $value = (bool)$value;
37
+ break;
38
+
39
+ default:
40
+ break;
41
+ }
42
+ return $value;
43
+ }
44
+
45
+ public function getRelevantMsg() :string {
46
+ return $this->success ? $this->msg : $this->error;
47
+ }
48
+
49
+ public function addData( string $key, $value ) :self {
50
+ $arr = is_array( $this->data ) ? $this->data : [];
51
+ $arr[ $key ] = $value;
52
+ $this->data = $arr;
53
+ return $this;
54
+ }
55
+ }
src/lib/src/Utilities/Tool/AssessDirWrite.php CHANGED
@@ -40,6 +40,9 @@ class AssessDirWrite {
40
  if ( $FS->isFile( $testDir ) ) {
41
  $FS->deleteFile( $testDir );
42
  }
 
 
 
43
 
44
  $FS->mkdir( $testDir );
45
  if ( $FS->isDir( $testDir ) ) {
40
  if ( $FS->isFile( $testDir ) ) {
41
  $FS->deleteFile( $testDir );
42
  }
43
+ if ( $FS->isDir( $testDir ) ) {
44
+ $FS->deleteDir( $testDir );
45
+ }
46
 
47
  $FS->mkdir( $testDir );
48
  if ( $FS->isDir( $testDir ) ) {
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -666,6 +666,20 @@ return array(
666
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => $baseDir . '/src/Modules/IPs/WpCli/Remove.php',
667
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AdminPage' => $baseDir . '/src/Modules/Insights/AdminPage.php',
668
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => $baseDir . '/src/Modules/Insights/AjaxHandler.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Components' => $baseDir . '/src/Modules/Insights/Lib/MeterAnalysis/Components.php',
670
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Handler' => $baseDir . '/src/Modules/Insights/Lib/MeterAnalysis/Handler.php',
671
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\MeterAll' => $baseDir . '/src/Modules/Insights/Lib/MeterAnalysis/MeterAll.php',
@@ -1181,14 +1195,14 @@ return array(
1181
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => $baseDir . '/src/Tables/Build/AdminNotes.php',
1182
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => $baseDir . '/src/Tables/Build/BaseBuild.php',
1183
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => $baseDir . '/src/Tables/Build/Sessions.php',
1184
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\AuditTrail\\ForAuditTrail' => $baseDir . '/src/Tables/DataTables/Build/AuditTrail/ForAuditTrail.php',
1185
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Base' => $baseDir . '/src/Tables/DataTables/Build/Base.php',
1186
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\IpRules\\ForIpRules' => $baseDir . '/src/Tables/DataTables/Build/IpRules/ForIpRules.php',
 
 
1187
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\BaseForScan' => $baseDir . '/src/Tables/DataTables/Build/Scans/BaseForScan.php',
1188
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForMalware' => $baseDir . '/src/Tables/DataTables/Build/Scans/ForMalware.php',
1189
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForPluginTheme' => $baseDir . '/src/Tables/DataTables/Build/Scans/ForPluginTheme.php',
1190
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForWordpress' => $baseDir . '/src/Tables/DataTables/Build/Scans/ForWordpress.php',
1191
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Traffic\\ForTraffic' => $baseDir . '/src/Tables/DataTables/Build/Traffic/ForTraffic.php',
1192
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\LoadData\\BaseBuildTableData' => $baseDir . '/src/Tables/DataTables/LoadData/BaseBuildTableData.php',
1193
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => $baseDir . '/src/Tables/Render/Common/BaseTable.php',
1194
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpCliTable/AuditTrail.php',
@@ -1222,6 +1236,7 @@ return array(
1222
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\ReCaptcha\\WordpressPost' => $baseDir . '/src/Utilities/ReCaptcha/WordpressPost.php',
1223
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => $baseDir . '/src/Utilities/Render/BasePageDisplay.php',
1224
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => $baseDir . '/src/Utilities/Render/BaseTemplateRenderer.php',
 
1225
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => $baseDir . '/src/Utilities/Time/WorldTimeApi.php',
1226
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\AssessDirWrite' => $baseDir . '/src/Utilities/Tool/AssessDirWrite.php',
1227
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => $baseDir . '/src/Utilities/Tool/DbTableExport.php',
@@ -1408,10 +1423,6 @@ return array(
1408
  'Html2Text\\Html2Text' => $vendorDir . '/soundasleep/html2text/src/Html2Text.php',
1409
  'Html2Text\\Html2TextException' => $vendorDir . '/soundasleep/html2text/src/Html2TextException.php',
1410
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => $baseDir . '/../processors/audit_trail_auditor.php',
1411
- 'ICWP_WPSF_Wizard_Base' => $baseDir . '/../wizards/base.php',
1412
- 'ICWP_WPSF_Wizard_BaseWpsf' => $baseDir . '/../wizards/base_wpsf.php',
1413
- 'ICWP_WPSF_Wizard_LoginProtect' => $baseDir . '/../wizards/login_protect.php',
1414
- 'ICWP_WPSF_Wizard_Plugin' => $baseDir . '/../wizards/plugin.php',
1415
  'IPLib\\Address\\AddressInterface' => $vendorDir . '/mlocati/ip-lib/src/Address/AddressInterface.php',
1416
  'IPLib\\Address\\AssignedRange' => $vendorDir . '/mlocati/ip-lib/src/Address/AssignedRange.php',
1417
  'IPLib\\Address\\IPv4' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv4.php',
666
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => $baseDir . '/src/Modules/IPs/WpCli/Remove.php',
667
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AdminPage' => $baseDir . '/src/Modules/Insights/AdminPage.php',
668
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => $baseDir . '/src/Modules/Insights/AjaxHandler.php',
669
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\MerlinController' => $baseDir . '/src/Modules/Insights/Lib/Merlin/MerlinController.php',
670
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\Base' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/Base.php',
671
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\CommentSpam' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/CommentSpam.php',
672
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\FreeTrial' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/FreeTrial.php',
673
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\GuidedSetupWelcome' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/GuidedSetupWelcome.php',
674
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\Import' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/Import.php',
675
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\IpBlocking' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/IpBlocking.php',
676
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\IpDetect' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/IpDetect.php',
677
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\License' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/License.php',
678
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\LoginProtection' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/LoginProtection.php',
679
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\OptIn' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/OptIn.php',
680
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\SecurityAdmin' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/SecurityAdmin.php',
681
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\SecurityBadge' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/SecurityBadge.php',
682
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\ThankYou' => $baseDir . '/src/Modules/Insights/Lib/Merlin/Steps/ThankYou.php',
683
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Components' => $baseDir . '/src/Modules/Insights/Lib/MeterAnalysis/Components.php',
684
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Handler' => $baseDir . '/src/Modules/Insights/Lib/MeterAnalysis/Handler.php',
685
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\MeterAll' => $baseDir . '/src/Modules/Insights/Lib/MeterAnalysis/MeterAll.php',
1195
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => $baseDir . '/src/Tables/Build/AdminNotes.php',
1196
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => $baseDir . '/src/Tables/Build/BaseBuild.php',
1197
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => $baseDir . '/src/Tables/Build/Sessions.php',
 
1198
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Base' => $baseDir . '/src/Tables/DataTables/Build/Base.php',
1199
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\ForAuditTrail' => $baseDir . '/src/Tables/DataTables/Build/ForAuditTrail.php',
1200
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\ForIpRules' => $baseDir . '/src/Tables/DataTables/Build/ForIpRules.php',
1201
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\ForTraffic' => $baseDir . '/src/Tables/DataTables/Build/ForTraffic.php',
1202
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\BaseForScan' => $baseDir . '/src/Tables/DataTables/Build/Scans/BaseForScan.php',
1203
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForMalware' => $baseDir . '/src/Tables/DataTables/Build/Scans/ForMalware.php',
1204
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForPluginTheme' => $baseDir . '/src/Tables/DataTables/Build/Scans/ForPluginTheme.php',
1205
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForWordpress' => $baseDir . '/src/Tables/DataTables/Build/Scans/ForWordpress.php',
 
1206
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\LoadData\\BaseBuildTableData' => $baseDir . '/src/Tables/DataTables/LoadData/BaseBuildTableData.php',
1207
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => $baseDir . '/src/Tables/Render/Common/BaseTable.php',
1208
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpCliTable/AuditTrail.php',
1236
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\ReCaptcha\\WordpressPost' => $baseDir . '/src/Utilities/ReCaptcha/WordpressPost.php',
1237
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => $baseDir . '/src/Utilities/Render/BasePageDisplay.php',
1238
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => $baseDir . '/src/Utilities/Render/BaseTemplateRenderer.php',
1239
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Response' => $baseDir . '/src/Utilities/Response.php',
1240
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => $baseDir . '/src/Utilities/Time/WorldTimeApi.php',
1241
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\AssessDirWrite' => $baseDir . '/src/Utilities/Tool/AssessDirWrite.php',
1242
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => $baseDir . '/src/Utilities/Tool/DbTableExport.php',
1423
  'Html2Text\\Html2Text' => $vendorDir . '/soundasleep/html2text/src/Html2Text.php',
1424
  'Html2Text\\Html2TextException' => $vendorDir . '/soundasleep/html2text/src/Html2TextException.php',
1425
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => $baseDir . '/../processors/audit_trail_auditor.php',
 
 
 
 
1426
  'IPLib\\Address\\AddressInterface' => $vendorDir . '/mlocati/ip-lib/src/Address/AddressInterface.php',
1427
  'IPLib\\Address\\AssignedRange' => $vendorDir . '/mlocati/ip-lib/src/Address/AssignedRange.php',
1428
  'IPLib\\Address\\IPv4' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv4.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -861,6 +861,20 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
861
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/Remove.php',
862
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AdminPage' => __DIR__ . '/../..' . '/src/Modules/Insights/AdminPage.php',
863
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Insights/AjaxHandler.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
864
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Components' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/MeterAnalysis/Components.php',
865
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Handler' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/MeterAnalysis/Handler.php',
866
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\MeterAll' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/MeterAnalysis/MeterAll.php',
@@ -1376,14 +1390,14 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1376
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Build/AdminNotes.php',
1377
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => __DIR__ . '/../..' . '/src/Tables/Build/BaseBuild.php',
1378
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Build/Sessions.php',
1379
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\AuditTrail\\ForAuditTrail' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/AuditTrail/ForAuditTrail.php',
1380
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Base' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Base.php',
1381
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\IpRules\\ForIpRules' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/IpRules/ForIpRules.php',
 
 
1382
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\BaseForScan' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/BaseForScan.php',
1383
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForMalware' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/ForMalware.php',
1384
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForPluginTheme' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/ForPluginTheme.php',
1385
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForWordpress' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/ForWordpress.php',
1386
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Traffic\\ForTraffic' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Traffic/ForTraffic.php',
1387
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\LoadData\\BaseBuildTableData' => __DIR__ . '/../..' . '/src/Tables/DataTables/LoadData/BaseBuildTableData.php',
1388
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => __DIR__ . '/../..' . '/src/Tables/Render/Common/BaseTable.php',
1389
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/AuditTrail.php',
@@ -1417,6 +1431,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1417
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\ReCaptcha\\WordpressPost' => __DIR__ . '/../..' . '/src/Utilities/ReCaptcha/WordpressPost.php',
1418
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => __DIR__ . '/../..' . '/src/Utilities/Render/BasePageDisplay.php',
1419
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => __DIR__ . '/../..' . '/src/Utilities/Render/BaseTemplateRenderer.php',
 
1420
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => __DIR__ . '/../..' . '/src/Utilities/Time/WorldTimeApi.php',
1421
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\AssessDirWrite' => __DIR__ . '/../..' . '/src/Utilities/Tool/AssessDirWrite.php',
1422
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => __DIR__ . '/../..' . '/src/Utilities/Tool/DbTableExport.php',
@@ -1603,10 +1618,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1603
  'Html2Text\\Html2Text' => __DIR__ . '/..' . '/soundasleep/html2text/src/Html2Text.php',
1604
  'Html2Text\\Html2TextException' => __DIR__ . '/..' . '/soundasleep/html2text/src/Html2TextException.php',
1605
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => __DIR__ . '/../..' . '/../processors/audit_trail_auditor.php',
1606
- 'ICWP_WPSF_Wizard_Base' => __DIR__ . '/../..' . '/../wizards/base.php',
1607
- 'ICWP_WPSF_Wizard_BaseWpsf' => __DIR__ . '/../..' . '/../wizards/base_wpsf.php',
1608
- 'ICWP_WPSF_Wizard_LoginProtect' => __DIR__ . '/../..' . '/../wizards/login_protect.php',
1609
- 'ICWP_WPSF_Wizard_Plugin' => __DIR__ . '/../..' . '/../wizards/plugin.php',
1610
  'IPLib\\Address\\AddressInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AddressInterface.php',
1611
  'IPLib\\Address\\AssignedRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AssignedRange.php',
1612
  'IPLib\\Address\\IPv4' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv4.php',
861
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/Remove.php',
862
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AdminPage' => __DIR__ . '/../..' . '/src/Modules/Insights/AdminPage.php',
863
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Insights/AjaxHandler.php',
864
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\MerlinController' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/MerlinController.php',
865
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\Base' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/Base.php',
866
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\CommentSpam' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/CommentSpam.php',
867
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\FreeTrial' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/FreeTrial.php',
868
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\GuidedSetupWelcome' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/GuidedSetupWelcome.php',
869
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\Import' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/Import.php',
870
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\IpBlocking' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/IpBlocking.php',
871
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\IpDetect' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/IpDetect.php',
872
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\License' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/License.php',
873
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\LoginProtection' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/LoginProtection.php',
874
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\OptIn' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/OptIn.php',
875
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\SecurityAdmin' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/SecurityAdmin.php',
876
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\SecurityBadge' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/SecurityBadge.php',
877
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Merlin\\Steps\\ThankYou' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Merlin/Steps/ThankYou.php',
878
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Components' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/MeterAnalysis/Components.php',
879
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\Handler' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/MeterAnalysis/Handler.php',
880
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\MeterAnalysis\\MeterAll' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/MeterAnalysis/MeterAll.php',
1390
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Build/AdminNotes.php',
1391
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => __DIR__ . '/../..' . '/src/Tables/Build/BaseBuild.php',
1392
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Build/Sessions.php',
 
1393
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Base' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Base.php',
1394
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\ForAuditTrail' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/ForAuditTrail.php',
1395
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\ForIpRules' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/ForIpRules.php',
1396
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\ForTraffic' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/ForTraffic.php',
1397
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\BaseForScan' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/BaseForScan.php',
1398
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForMalware' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/ForMalware.php',
1399
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForPluginTheme' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/ForPluginTheme.php',
1400
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\Build\\Scans\\ForWordpress' => __DIR__ . '/../..' . '/src/Tables/DataTables/Build/Scans/ForWordpress.php',
 
1401
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\DataTables\\LoadData\\BaseBuildTableData' => __DIR__ . '/../..' . '/src/Tables/DataTables/LoadData/BaseBuildTableData.php',
1402
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => __DIR__ . '/../..' . '/src/Tables/Render/Common/BaseTable.php',
1403
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/AuditTrail.php',
1431
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\ReCaptcha\\WordpressPost' => __DIR__ . '/../..' . '/src/Utilities/ReCaptcha/WordpressPost.php',
1432
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => __DIR__ . '/../..' . '/src/Utilities/Render/BasePageDisplay.php',
1433
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => __DIR__ . '/../..' . '/src/Utilities/Render/BaseTemplateRenderer.php',
1434
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Response' => __DIR__ . '/../..' . '/src/Utilities/Response.php',
1435
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => __DIR__ . '/../..' . '/src/Utilities/Time/WorldTimeApi.php',
1436
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\AssessDirWrite' => __DIR__ . '/../..' . '/src/Utilities/Tool/AssessDirWrite.php',
1437
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => __DIR__ . '/../..' . '/src/Utilities/Tool/DbTableExport.php',
1618
  'Html2Text\\Html2Text' => __DIR__ . '/..' . '/soundasleep/html2text/src/Html2Text.php',
1619
  'Html2Text\\Html2TextException' => __DIR__ . '/..' . '/soundasleep/html2text/src/Html2TextException.php',
1620
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => __DIR__ . '/../..' . '/../processors/audit_trail_auditor.php',
 
 
 
 
1621
  'IPLib\\Address\\AddressInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AddressInterface.php',
1622
  'IPLib\\Address\\AssignedRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AssignedRange.php',
1623
  'IPLib\\Address\\IPv4' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv4.php',
src/lib/vendor/composer/installed.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php return array(
2
  'root' => array(
3
- 'pretty_version' => 'dev-master',
4
- 'version' => 'dev-master',
5
  'type' => 'library',
6
  'install_path' => __DIR__ . '/../../',
7
  'aliases' => array(),
8
- 'reference' => 'e9e72ec528ce23944ba1e890131dcdaa109cd380',
9
  'name' => 'apto-shield/requirements',
10
  'dev' => true,
11
  ),
@@ -20,12 +20,12 @@
20
  'dev_requirement' => false,
21
  ),
22
  'apto-shield/requirements' => array(
23
- 'pretty_version' => 'dev-master',
24
- 'version' => 'dev-master',
25
  'type' => 'library',
26
  'install_path' => __DIR__ . '/../../',
27
  'aliases' => array(),
28
- 'reference' => 'e9e72ec528ce23944ba1e890131dcdaa109cd380',
29
  'dev_requirement' => false,
30
  ),
31
  'christian-riesen/base32' => array(
1
  <?php return array(
2
  'root' => array(
3
+ 'pretty_version' => 'dev-develop',
4
+ 'version' => 'dev-develop',
5
  'type' => 'library',
6
  'install_path' => __DIR__ . '/../../',
7
  'aliases' => array(),
8
+ 'reference' => '5f4642f2c038b77e969af37613c3842d43387017',
9
  'name' => 'apto-shield/requirements',
10
  'dev' => true,
11
  ),
20
  'dev_requirement' => false,
21
  ),
22
  'apto-shield/requirements' => array(
23
+ 'pretty_version' => 'dev-develop',
24
+ 'version' => 'dev-develop',
25
  'type' => 'library',
26
  'install_path' => __DIR__ . '/../../',
27
  'aliases' => array(),
28
+ 'reference' => '5f4642f2c038b77e969af37613c3842d43387017',
29
  'dev_requirement' => false,
30
  ),
31
  'christian-riesen/base32' => array(
src/wizards/base.php CHANGED
@@ -9,267 +9,6 @@ abstract class ICWP_WPSF_Wizard_Base {
9
 
10
  use Shield\Modules\ModConsumer;
11
 
12
- /**
13
- * @var string
14
- */
15
- private $sCurrentWizard;
16
-
17
- /**
18
- * Indicates if stepping through the wizard is automatic
19
- * or it needs to add the instruction to click next.
20
- *
21
- * @var bool
22
- */
23
- const WIZARD_STEPPING_AUTO = true;
24
-
25
- public function init() {
26
- add_action( 'wp_loaded', [ $this, 'onWpLoaded' ], 0 );
27
- }
28
-
29
- /**
30
- * Ensure to only ever process supported wizards
31
- */
32
- public function ajaxExec_WizRenderStep() {
33
- $oReq = Services::Request();
34
-
35
- $aResponse = [
36
- 'success' => false,
37
- 'next_step' => [],
38
- ];
39
-
40
- try {
41
- $this->setCurrentWizard( $oReq->post( 'wizard_slug' ) );
42
- if ( $this->getUserCan() ) {
43
- $aNextStep = $this->buildNextStep(
44
- $oReq->post( 'wizard_steps' ),
45
- (int)$oReq->post( 'current_index' )
46
- );
47
- $aResponse[ 'success' ] = true;
48
- $aResponse[ 'next_step' ] = $aNextStep;
49
- }
50
- else {
51
- $aResponse[ 'message' ] = 'Please login to run this wizard.';
52
- }
53
- }
54
- catch ( Exception $e ) {
55
- }
56
-
57
- return $aResponse;
58
- }
59
-
60
- /**
61
- * TODO: does not honour 'min_user_permissions' from the wizard definition
62
- */
63
- public function onWpLoaded() {
64
- $wizard = Services::Request()->query( 'wizard' );
65
- try {
66
- $this->setCurrentWizard( $wizard );
67
-
68
- $sDieMessage = 'Not Permitted';
69
- if ( $this->getUserCan() ) {
70
- $this->loadWizard();
71
- }
72
- else {
73
- $sDieMessage = 'Please login to run this wizard';
74
- }
75
-
76
- Services::WpGeneral()->wpDie( $sDieMessage );
77
- }
78
- catch ( \Exception $e ) {
79
- if ( $wizard == 'landing' ) {
80
- $this->loadWizardLanding();
81
- }
82
- }
83
- }
84
-
85
- /**
86
- * @uses echo()
87
- */
88
- protected function loadWizard() {
89
- try {
90
- $content = $this->renderWizard();
91
- }
92
- catch ( \Exception $e ) {
93
- $content = $e->getMessage();
94
- }
95
- echo $content;
96
- die();
97
- }
98
-
99
- /**
100
- * @return string
101
- */
102
- public function renderWizardLandingPage() {
103
- try {
104
- $content = $this->getMod()->renderTemplate(
105
- 'wizard/pages/landing.twig',
106
- $this->getRenderData_PageWizardLanding()
107
- );
108
- }
109
- catch ( \Exception $e ) {
110
- $content = $e->getMessage();
111
- }
112
- return $content;
113
- }
114
-
115
- /**
116
- * @return string
117
- */
118
- public function renderWizardLandingSnippet() {
119
- try {
120
- $content = $this->getMod()->renderTemplate(
121
- 'wizard/snippets/wizard_landing.twig',
122
- $this->getRenderData_PageWizardLanding()
123
- );
124
- }
125
- catch ( \Exception $e ) {
126
- $content = $e->getMessage();
127
- }
128
- return $content;
129
- }
130
-
131
- /**
132
- * @uses echo()
133
- */
134
- protected function loadWizardLanding() {
135
- echo $this->renderWizardLandingPage();
136
- die();
137
- }
138
-
139
- /**
140
- * @param string $sSlug
141
- * @return bool
142
- */
143
- protected function isSupportedWizard( $sSlug ) {
144
- return in_array( $sSlug, $this->getSupportedWizards() );
145
- }
146
-
147
- /**
148
- * @param string $sPerm
149
- * @return bool
150
- */
151
- protected function getUserCan( $sPerm = null ) {
152
- if ( empty( $sPerm ) ) {
153
- $sPerm = 'manage_options';
154
- }
155
- return $sPerm == 'none' || current_user_can( $sPerm );
156
- }
157
-
158
- /**
159
- * @param string $sSlide
160
- * @return bool
161
- */
162
- protected function getUserCanSlide( $sSlide ) {
163
- return $this->getUserCan();
164
- }
165
-
166
- /**
167
- * @return string[] the array of wizard slugs supported
168
- */
169
- protected function getSupportedWizards() {
170
- return array_keys( $this->getMod()->getWizardDefinitions() );
171
- }
172
-
173
- /**
174
- * @return array
175
- */
176
- public function ajaxExec_WizProcessStep() {
177
- $r = $this->processWizardStep( Services::Request()->post( 'wizard-step' ) );
178
- if ( !$r instanceof StdResponse ) {
179
- $response = new StdResponse();
180
- $response->msg_text = $r->getMessageText();
181
- $response->success = $r->successful();
182
- }
183
- else {
184
- $response = $r;
185
- }
186
-
187
- $msg = $response->msg_text;
188
- if ( $response->success ) {
189
- if ( !self::WIZARD_STEPPING_AUTO ) {
190
- $msg .= '<br />'.sprintf( 'Please click %s to continue.', __( 'Next Step' ) );
191
- }
192
- }
193
- else {
194
- $msg = sprintf( '%s: %s', __( 'Error' ), $msg );
195
- }
196
-
197
- $data = $response->getRawData();
198
- $data[ 'message' ] = $msg;
199
- $data[ 'success' ] = $response->success;
200
-
201
- return $data;
202
- }
203
-
204
- /**
205
- * @param string $step
206
- * @return StdResponse|\FernleafSystems\Utilities\Response|null
207
- */
208
- protected function processWizardStep( string $step ) {
209
- switch ( $step ) {
210
- default:
211
- $response = null; // we don't process any steps we don't recognise.
212
- break;
213
- }
214
- return $response;
215
- }
216
-
217
- /**
218
- * @param \FernleafSystems\Utilities\Response $oResponse
219
- * @return \FernleafSystems\Utilities\Response
220
- */
221
- protected function buildWizardResponse( $oResponse ) {
222
-
223
- $msg = $oResponse->getMessageText();
224
- if ( $oResponse->successful() ) {
225
- if ( !self::WIZARD_STEPPING_AUTO ) {
226
- $msg .= '<br />'.sprintf( 'Please click %s to continue.', __( 'Next Step' ) );
227
- }
228
- }
229
- else {
230
- $msg = sprintf( '%s: %s', __( 'Error' ), $msg );
231
- }
232
-
233
- $aData = $oResponse->getData();
234
- $aData[ 'message' ] = $msg;
235
- $oResponse->setData( $aData );
236
- return $oResponse;
237
- }
238
-
239
- /**
240
- * @return string
241
- * @throws Exception
242
- */
243
- public function renderWizard() {
244
- remove_all_actions( 'wp_footer' ); // FIX: nextgen gallery forces this to run.
245
- return $this->getMod()->renderTemplate( 'wizard/wizard_container.twig', $this->getRenderData_PageWizard() );
246
- }
247
-
248
- /**
249
- * @return array[]
250
- */
251
- protected function getModuleWizardsForRender() {
252
- /** @var Shield\Modules\Base\ModCon $mod */
253
- $mod = $this->getMod();
254
- $aWizards = $mod->getWizardDefinitions();
255
- foreach ( $aWizards as $sKey => &$aWizard ) {
256
- $aWizard[ 'has_perm' ] = empty( $aWizard[ 'min_user_permissions' ] ) || $this->getUserCan( $aWizard[ 'min_user_permissions' ] );
257
- $aWizard[ 'url' ] = $mod->getUrl_Wizard( $sKey );
258
- $aWizard[ 'has_premium' ] = isset( $aWizard[ 'has_premium' ] ) && $aWizard[ 'has_premium' ];
259
- $aWizard[ 'available' ] = $this->getWizardAvailability( $sKey );
260
- }
261
- return $aWizards;
262
- }
263
-
264
- /**
265
- * Override this to provide custom logic for wizard availability - e.g. isPremium() etc.
266
- * @param string $sKey
267
- * @return bool
268
- */
269
- protected function getWizardAvailability( $sKey ) {
270
- return true;
271
- }
272
-
273
  /**
274
  * @return array[]
275
  */
@@ -277,8 +16,6 @@ abstract class ICWP_WPSF_Wizard_Base {
277
  /** @var ModCon $mod */
278
  $mod = $this->getMod();
279
 
280
- $wizards = $this->getModuleWizardsForRender();
281
-
282
  return Services::DataManipulation()->mergeArraysRecursive(
283
  $mod->getUIHandler()->getBaseDisplayData(),
284
  [
@@ -286,10 +23,6 @@ abstract class ICWP_WPSF_Wizard_Base {
286
  'page_title' => 'Select Your Wizard',
287
  'premium_note' => 'Note: This uses features only available to Pro-licensed installations.'
288
  ],
289
- 'data' => [
290
- 'mod_wizards_count' => count( $wizards ),
291
- 'mod_wizards' => $wizards
292
- ],
293
  'hrefs' => [
294
  'dashboard' => $this->getCon()->getPluginUrl_DashboardHome(),
295
  'goprofooter' => 'https://shsec.io/goprofooter',
@@ -303,42 +36,16 @@ abstract class ICWP_WPSF_Wizard_Base {
303
  );
304
  }
305
 
306
- /**
307
- * TODO: Abstract and move elsewhere - it's here because Wizards on the only consumer of twig templates
308
- * @return array
309
- */
310
- protected function getRenderData_TwigPageBase() {
311
- return $this->getMod()->getUIHandler()->getBaseDisplayData();
312
- }
313
-
314
  /**
315
  * @return array
316
  */
317
  protected function getRenderData_PageWizard() {
318
- $con = $this->getMod()->getCon();
319
  /** @var ModCon $mod */
320
  $mod = $this->getMod();
321
 
322
- $steps = $this->buildSteps();
323
-
324
- $aStepsNames = [];
325
- foreach ( $steps as $stepKey ) {
326
- $aStepsNames[] = $this->getStepsDefinition()[ $stepKey ][ 'title' ];
327
- }
328
-
329
  return Services::DataManipulation()->mergeArraysRecursive(
330
  $mod->getUIHandler()->getBaseDisplayData(),
331
  [
332
- 'strings' => [
333
- 'page_title' => $this->getPageTitle(),
334
- 'plugin_name' => $con->getHumanName()
335
- ],
336
- 'data' => [
337
- 'wizard_slug' => $this->getWizardSlug(),
338
- 'wizard_steps' => json_encode( $steps ),
339
- 'wizard_step_names' => json_encode( $aStepsNames ),
340
- 'wizard_first_step' => json_encode( $this->getWizardFirstStep() ),
341
- ],
342
  'hrefs' => [
343
  'dashboard' => $this->getCon()->getPluginUrl_DashboardHome(),
344
  'goprofooter' => 'https://shsec.io/goprofooter',
@@ -351,188 +58,4 @@ abstract class ICWP_WPSF_Wizard_Base {
351
  ]
352
  );
353
  }
354
-
355
- protected function getPageTitle() :string {
356
- return sprintf( __( '%s Wizard', 'wp-simple-firewall' ), $this->getMod()->getCon()->getHumanName() );
357
- }
358
-
359
- protected function buildSteps() :array {
360
- return $this->getUserCan() ? $this->determineWizardSteps() : [ 'no_access' ];
361
- }
362
-
363
- /**
364
- * @return array
365
- * @throws Exception
366
- */
367
- protected function determineWizardSteps() :array {
368
- throw new \Exception( sprintf( 'Could not determine wizard steps for current wizard: %s', $this->getWizardSlug() ) );
369
- }
370
-
371
- /**
372
- * @return array
373
- */
374
- protected function getWizardFirstStep() {
375
- return $this->buildNextStep( $this->buildSteps(), -1 );
376
- }
377
-
378
- protected function getNextStepDefinition( $aStepsInThisInstance, $nCurrentStep ) {
379
- }
380
-
381
- /**
382
- * @param array $aStepsInThisInstance
383
- * @param int $nCurrentPos
384
- * @return array
385
- */
386
- protected function buildNextStep( $aStepsInThisInstance, $nCurrentPos ) {
387
- $aNextStepDef = $this->getNextStep( $aStepsInThisInstance, $nCurrentPos );
388
-
389
- try {
390
- $aNextStepDef[ 'content' ] = $this->renderWizardStep( $aNextStepDef[ 'slug' ] );
391
- }
392
- catch ( \Exception $e ) {
393
- $aNextStepDef[ 'content' ] = 'Content could not be displayed due to error: '.$e->getMessage();
394
- }
395
-
396
- return $aNextStepDef;
397
- }
398
-
399
- /**
400
- * @param array $aStepsInThisInstance
401
- * @param int $nCurrentPos
402
- * @return array
403
- */
404
- protected function getNextStep( $aStepsInThisInstance, $nCurrentPos ) {
405
- // The assumption here is that the step data exists!
406
- $sNextStepKey = $aStepsInThisInstance[ $nCurrentPos + 1 ];
407
- return $this->getStepsDefinition()[ $sNextStepKey ];
408
- }
409
-
410
- /**
411
- * @param string $sStep
412
- * @return array
413
- */
414
- protected function getRenderData_Slide( $sStep ) {
415
- return Services::DataManipulation()->mergeArraysRecursive(
416
- $this->getRenderData_SlideBase(),
417
- $this->getRenderData_SlideExtra( $sStep )
418
- );
419
- }
420
-
421
- protected function getRenderData_SlideBase() :array {
422
- $mod = $this->getMod();
423
- $aWizards = $this->getModuleWizardsForRender();
424
- return [
425
- 'strings' => $mod->getStrings()->getDisplayStrings(),
426
- 'flags' => [
427
- 'is_premium' => $mod->isPremium(),
428
- 'has_other_wizards' => false
429
- ],
430
- 'hrefs' => [
431
- 'dashboard' => $this->getCon()->getPluginUrl_DashboardHome(),
432
- 'gopro' => 'https://shsec.io/ap',
433
- ],
434
- 'imgs' => [
435
- 'play_button' => $this->getCon()->urls->forImage( 'bootstrap/play-circle.svg' )
436
- ],
437
- 'data' => [
438
- 'mod_wizards_count' => count( $aWizards ),
439
- 'mod_wizards' => $aWizards
440
- ],
441
- ];
442
- }
443
-
444
- /**
445
- * @param string $step
446
- * @return array
447
- */
448
- protected function getRenderData_SlideExtra( $step ) {
449
- return [];
450
- }
451
-
452
- /**
453
- * @param string $slug
454
- * @return string
455
- * @throws Exception
456
- */
457
- protected function renderWizardStep( $slug ) {
458
-
459
- $template = $slug;
460
- if ( strpos( $slug, '/' ) === false ) {
461
- $base = $this->isSlideCommon( $slug ) ? 'common' : $this->getWizardSlug();
462
- $template = sprintf( '%s/%s', $base, $slug );
463
- }
464
-
465
- return $this->getMod()->renderTemplate(
466
- sprintf( 'wizard/slides/%s.twig', $template ),
467
- $this->getRenderData_Slide( $slug )
468
- );
469
- }
470
-
471
- /**
472
- * @param string $sSlideSlug
473
- * @return bool
474
- */
475
- protected function isSlideCommon( $sSlideSlug ) {
476
- return in_array( $sSlideSlug, [ 'no_access' ] );
477
- }
478
-
479
- /**
480
- * @return array[]
481
- */
482
- protected function getAllDefinedSteps() {
483
- return $this->getWizard()[ 'steps' ];
484
- }
485
-
486
- /**
487
- * @return array[]
488
- */
489
- protected function getStepsDefinition() {
490
- $aNoAccess = [
491
- 'no_access' => [
492
- 'title' => __( 'No Access', 'wp-simple-firewall' ),
493
- ]
494
- ];
495
- $aSteps = array_merge( $this->getAllDefinedSteps(), $aNoAccess );
496
- foreach ( $aSteps as $sSlug => $aStep ) {
497
- $aSteps[ $sSlug ][ 'slug' ] = $sSlug;
498
- $aSteps[ $sSlug ][ 'content' ] = '';
499
- }
500
- return $aSteps;
501
- }
502
-
503
- /**
504
- * @return string
505
- */
506
- public function getWizardSlug() {
507
- return $this->sCurrentWizard;
508
- }
509
-
510
- /**
511
- * @return array
512
- */
513
- public function getWizard() {
514
- return $this->getMod()->getWizardDefinitions()[ $this->getWizardSlug() ];
515
- }
516
-
517
- /**
518
- * @param string $sKey
519
- * @return array
520
- */
521
- public function getWizardProperty( $sKey ) {
522
- $aW = $this->getWizard();
523
- return isset( $aW[ $sKey ] ) ? $aW[ $sKey ] : null;
524
- }
525
-
526
- /**
527
- * @param string $sCurrentWizard
528
- * @return $this
529
- * @throws Exception
530
- */
531
- public function setCurrentWizard( $sCurrentWizard ) {
532
- if ( empty( $sCurrentWizard ) || !$this->isSupportedWizard( $sCurrentWizard ) ) {
533
- throw new Exception( 'Not a supported wizard.' );
534
- }
535
- $this->sCurrentWizard = $sCurrentWizard;
536
- return $this;
537
- }
538
  }
9
 
10
  use Shield\Modules\ModConsumer;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * @return array[]
14
  */
16
  /** @var ModCon $mod */
17
  $mod = $this->getMod();
18
 
 
 
19
  return Services::DataManipulation()->mergeArraysRecursive(
20
  $mod->getUIHandler()->getBaseDisplayData(),
21
  [
23
  'page_title' => 'Select Your Wizard',
24
  'premium_note' => 'Note: This uses features only available to Pro-licensed installations.'
25
  ],
 
 
 
 
26
  'hrefs' => [
27
  'dashboard' => $this->getCon()->getPluginUrl_DashboardHome(),
28
  'goprofooter' => 'https://shsec.io/goprofooter',
36
  );
37
  }
38
 
 
 
 
 
 
 
 
 
39
  /**
40
  * @return array
41
  */
42
  protected function getRenderData_PageWizard() {
 
43
  /** @var ModCon $mod */
44
  $mod = $this->getMod();
45
 
 
 
 
 
 
 
 
46
  return Services::DataManipulation()->mergeArraysRecursive(
47
  $mod->getUIHandler()->getBaseDisplayData(),
48
  [
 
 
 
 
 
 
 
 
 
 
49
  'hrefs' => [
50
  'dashboard' => $this->getCon()->getPluginUrl_DashboardHome(),
51
  'goprofooter' => 'https://shsec.io/goprofooter',
58
  ]
59
  );
60
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
src/wizards/base_wpsf.php DELETED
@@ -1,115 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Services\Services;
4
-
5
- abstract class ICWP_WPSF_Wizard_BaseWpsf extends ICWP_WPSF_Wizard_Base {
6
-
7
- /**
8
- * @param string $sSlide
9
- * @return bool
10
- */
11
- protected function getUserCanSlide( $sSlide ) {
12
- $aSlide = $this->getStepsDefinition()[ $sSlide ];
13
- $bRestricted = !isset( $aSlide[ 'security_admin' ] ) || $aSlide[ 'security_admin' ];
14
- return !$bRestricted || $this->getCon()->isPluginAdmin();
15
- }
16
-
17
- /**
18
- * @param array $aStepsInThisInstance
19
- * @param int $nCurrentPos
20
- * @return array
21
- */
22
- protected function getNextStep( $aStepsInThisInstance, $nCurrentPos ) {
23
- $aNext = parent::getNextStep( $aStepsInThisInstance, $nCurrentPos );
24
- if ( !$this->getUserCanSlide( $aNext[ 'slug' ] ) ) {
25
- $aNext = $this->getStepsDefinition()[ 'security_admin_verify' ];
26
- }
27
- return $aNext;
28
- }
29
-
30
- /**
31
- * @param string $step
32
- * @return array
33
- */
34
- protected function getRenderData_SlideExtra( $step ) {
35
-
36
- switch ( $step ) {
37
- case 'security_admin_verify':
38
- $aAdditional = [ 'current_index' => Services::Request()->post( 'current_index' ) ];
39
- break;
40
- default:
41
- $aAdditional = parent::getRenderData_SlideExtra( $step );
42
- break;
43
- }
44
-
45
- return $aAdditional;
46
- }
47
-
48
- /**
49
- * @return array[]
50
- */
51
- protected function getStepsDefinition() {
52
- return array_merge(
53
- parent::getStepsDefinition(),
54
- [
55
- 'security_admin_verify' => [
56
- 'content' => '',
57
- 'slug' => 'security_admin_verify',
58
- 'title' => __( 'Security Admin', 'wp-simple-firewall' ),
59
- 'security_admin' => false
60
- ]
61
- ]
62
- );
63
- }
64
-
65
- /**
66
- * @param string $sSlideSlug
67
- * @return bool
68
- */
69
- protected function isSlideCommon( $sSlideSlug ) {
70
- return parent::isSlideCommon( $sSlideSlug ) || in_array( $sSlideSlug, [ 'security_admin_verify' ] );
71
- }
72
-
73
- /**
74
- * @param string $step
75
- * @return \FernleafSystems\Utilities\Response|null
76
- */
77
- protected function processWizardStep( string $step ) {
78
- switch ( $step ) {
79
- case 'security_admin_verify':
80
- $oResponse = $this->wizardSecurityAdminVerify();
81
- break;
82
- default:
83
- $oResponse = parent::processWizardStep( $step );
84
- break;
85
- }
86
- return $oResponse;
87
- }
88
-
89
- /**
90
- * @return \FernleafSystems\Utilities\Response
91
- */
92
- private function wizardSecurityAdminVerify() {
93
- $pin = Services::Request()->post( 'sec_admin_key' );
94
-
95
- $response = new \FernleafSystems\Utilities\Response();
96
- $success = false;
97
- $msg = '';
98
-
99
- if ( empty( $pin ) ) {
100
- $msg = 'Security Admin PIN was empty.';
101
- }
102
- elseif ( !$this->getCon()->getModule_SecAdmin()->getSecurityAdminController()->verifyPinRequest() ) {
103
- $msg = __( 'Security Admin PIN was not correct.', 'wp-simple-firewall' );
104
- }
105
- else {
106
- $success = true;
107
- $response->setData( [
108
- 'rerender' => true
109
- ] );
110
- }
111
-
112
- return $response->setSuccessful( $success )
113
- ->setMessageText( $msg );
114
- }
115
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/wizards/login_protect.php DELETED
@@ -1,142 +0,0 @@
1
- <?php
2
-
3
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
4
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Options;
5
- use FernleafSystems\Wordpress\Services\Services;
6
-
7
- class ICWP_WPSF_Wizard_LoginProtect extends ICWP_WPSF_Wizard_BaseWpsf {
8
-
9
- protected function getPageTitle() :string {
10
- return sprintf( __( '%s Multi-Factor Authentication Wizard', 'wp-simple-firewall' ), $this->getCon()
11
- ->getHumanName() );
12
- }
13
-
14
- /**
15
- * @return \FernleafSystems\Utilities\Response|null
16
- */
17
- protected function processWizardStep( string $step ) {
18
- switch ( $step ) {
19
- case 'authemail':
20
- $response = $this->processAuthEmail();
21
- break;
22
-
23
- default:
24
- $response = parent::processWizardStep( $step );
25
- break;
26
- }
27
- return $response;
28
- }
29
-
30
- private function processAuthEmail() :\FernleafSystems\Utilities\Response{
31
- /** @var LoginGuard\ModCon $mod */
32
- $mod = $this->getMod();
33
- /** @var Options $opts */
34
- $opts = $this->getOptions();
35
- $req = Services::Request();
36
-
37
- $response = new \FernleafSystems\Utilities\Response();
38
- $response->setSuccessful( false );
39
-
40
- $email = $req->post( 'email' );
41
- $code = $req->post( 'code' );
42
- $is2FA = $req->post( 'Email2FAOption' ) === 'Y';
43
-
44
- if ( empty( $email ) || !Services::Data()->validEmail( $email ) ) {
45
- $msg = __( 'Invalid email address', 'wp-simple-firewall' );
46
- }
47
- elseif ( empty( $code ) ) {
48
- if ( $mod->sendEmailVerifyCanSend( $email, false ) ) {
49
- $mod->setIfCanSendEmail( false );
50
- $response->setSuccessful( true );
51
- $msg = __( 'Verification email sent (please check your email including your SPAM).', 'wp-simple-firewall' )
52
- .' '.__( 'Enter the code from the email into the form above and click the button to verify.', 'wp-simple-firewall' );
53
- }
54
- else {
55
- $msg = 'Failed to send verification email';
56
- }
57
- }
58
- elseif ( $code == $mod->getCanEmailVerifyCode() ) {
59
- $response->setSuccessful( true );
60
- $msg = 'Email sending has been verified successfully.';
61
-
62
- $mod->setIfCanSendEmail( true );
63
-
64
- if ( $is2FA ) {
65
- $opts->setOpt( 'enable_email_authentication', 'Y' );
66
- $msg .= ' '.'Email-based two factor authentication is now enabled.';
67
- }
68
- else {
69
- $msg .= ' '.'Email-based two factor authentication is NOT enabled.';
70
- }
71
- }
72
- else {
73
- $msg = 'This does not appear to be the correct 6-digit code that was sent to you.'
74
- .'Email-based two factor authentication option has not been updated.';
75
- }
76
-
77
- return $response->setMessageText( $msg );
78
- }
79
-
80
- /**
81
- * @return string[]
82
- * @throws Exception
83
- */
84
- protected function determineWizardSteps() :array {
85
-
86
- switch ( $this->getWizardSlug() ) {
87
- case 'mfa':
88
- $aSteps = $this->determineWizardSteps_Mfa();
89
- break;
90
- default:
91
- parent::determineWizardSteps();
92
- break;
93
- }
94
- return array_values( array_intersect( array_keys( $this->getAllDefinedSteps() ), $aSteps ) );
95
- }
96
-
97
- /**
98
- * @return string[]
99
- */
100
- private function determineWizardSteps_Mfa() {
101
- /** @var LoginGuard\Options $oOpts */
102
- $oOpts = $this->getOptions();
103
-
104
- $aStepsSlugs = [ 'start' ];
105
-
106
- if ( !$oOpts->getIfCanSendEmailVerified() || !$oOpts->isEmailAuthenticationActive() ) {
107
- $aStepsSlugs[] = 'authemail';
108
- }
109
-
110
- $aStepsSlugs[] = 'finished';
111
- return $aStepsSlugs;
112
- }
113
-
114
- /**
115
- * @param string $step
116
- * @return array
117
- */
118
- protected function getRenderData_SlideExtra( $step ) {
119
- $additional = [];
120
-
121
- switch ( $step ) {
122
-
123
- case 'authemail':
124
- $user = Services::WpUsers()->getCurrentWpUser();
125
- $additional = [
126
- 'data' => [
127
- 'name' => $user->first_name,
128
- 'user_email' => $user->user_email
129
- ]
130
- ];
131
- break;
132
-
133
- default:
134
- break;
135
- }
136
-
137
- if ( empty( $additional ) ) {
138
- $additional = parent::getRenderData_SlideExtra( $step );
139
- }
140
- return $additional;
141
- }
142
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/wizards/plugin.php CHANGED
@@ -5,14 +5,7 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities\Net\FindSourceFromIp;
7
 
8
- class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
9
-
10
- /**
11
- * @return string
12
- */
13
- protected function getPageTitle() :string {
14
- return sprintf( __( '%s Welcome Wizard', 'wp-simple-firewall' ), $this->getCon()->getHumanName() );
15
- }
16
 
17
  /**
18
  * @param string $step
@@ -21,10 +14,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
21
  protected function processWizardStep( string $step ) {
22
  switch ( $step ) {
23
 
24
- case 'ip_detect':
25
- $response = $this->wizardIpDetect();
26
- break;
27
-
28
  case 'license':
29
  $response = $this->wizardLicense();
30
  break;
@@ -33,10 +22,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
33
  $response = $this->wizardImportOptions();
34
  break;
35
 
36
- case 'admin_access_restriction':
37
- $response = $this->wizardSecurityAdmin();
38
- break;
39
-
40
  case 'audit_trail':
41
  $response = $this->wizardAuditTrail();
42
  break;
@@ -74,93 +59,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
74
  return $response;
75
  }
76
 
77
- /**
78
- * @return string[]
79
- * @throws Exception
80
- */
81
- protected function determineWizardSteps() :array {
82
- switch ( $this->getWizardSlug() ) {
83
- case 'welcome':
84
- $aSteps = $this->determineWizardSteps_Welcome();
85
- break;
86
- case 'gdpr':
87
- $aSteps = $this->determineWizardSteps_Gdpr();
88
- break;
89
- case 'importexport':
90
- $aSteps = $this->determineWizardSteps_Import();
91
- break;
92
- default:
93
- parent::determineWizardSteps();
94
- break;
95
- }
96
- return array_values( array_intersect( array_keys( $this->getAllDefinedSteps() ), $aSteps ) );
97
- }
98
-
99
- /**
100
- * @return string[]
101
- */
102
- private function determineWizardSteps_Gdpr() {
103
- return [
104
- 'start',
105
- 'search',
106
- 'results',
107
- 'finished',
108
- ];
109
- }
110
-
111
- /**
112
- * @return string[]
113
- */
114
- private function determineWizardSteps_Import() {
115
- return [
116
- 'start',
117
- 'import',
118
- 'finished',
119
- ];
120
- }
121
-
122
- /**
123
- * @return string[]
124
- */
125
- private function determineWizardSteps_Welcome() {
126
- $con = $this->getCon();
127
-
128
- $stepsSlugs = [
129
- 'welcome',
130
- ];
131
-
132
- if ( $con->isPremiumActive() ) {
133
- $stepsSlugs[] = 'import';
134
- }
135
-
136
- if ( !$con->getModule( 'admin_access_restriction' )->isModuleEnabled() ) {
137
- $stepsSlugs[] = 'admin_access_restriction';
138
- }
139
-
140
- $mod = $con->getModule_AuditTrail();
141
- if ( !$mod->isModuleEnabled() ) {
142
- $stepsSlugs[] = 'audit_trail';
143
- }
144
-
145
- if ( !$con->getModule_IPs()->isModuleEnabled() ) {
146
- // $stepsSlugs[] = 'ips';
147
- }
148
-
149
- $stepsSlugs[] = 'login_protect';
150
- $stepsSlugs[] = 'comments_filter';
151
- $stepsSlugs[] = 'plugin_badge';
152
- // $stepsSlugs[] = 'plugin_telemetry';
153
- $stepsSlugs[] = 'free_trial';
154
- $stepsSlugs[] = 'optin';
155
-
156
- if ( !$con->isPremiumActive() ) {
157
- $stepsSlugs[] = 'import';
158
- }
159
-
160
- $stepsSlugs[] = 'thankyou';
161
- return $stepsSlugs;
162
- }
163
-
164
  /**
165
  * @param string $step
166
  * @return array
@@ -169,74 +67,9 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
169
  $con = $this->getCon();
170
 
171
  $additional = [];
172
-
173
- $sCurrentWiz = $this->getWizardSlug();
174
-
175
  if ( $sCurrentWiz == 'welcome' ) {
176
 
177
  switch ( $step ) {
178
- case 'welcome':
179
- $urlBuilder = $con->urls;
180
- $additional = [
181
- 'imgs' => [
182
- 'plugin_banner' => $urlBuilder->forImage( 'banner-1500x500-transparent.png' ),
183
- ],
184
- 'vars' => [
185
- 'video_id' => '267962208'
186
- ],
187
- 'strings' => [
188
- 'slide_title' => 'Welcome To Shield Security for WordPress',
189
- 'next_button' => 'Start',
190
- ],
191
- ];
192
- break;
193
-
194
- case 'ip_detect':
195
- $additional = [
196
- 'hrefs' => [
197
- 'visitor_ip' => 'https://shsec.io/visitorip',
198
- ],
199
- 'vars' => [
200
- 'video_id' => '269189603'
201
- ],
202
- 'strings' => [
203
- 'slide_title' => 'Accurate Visitor IP Detection',
204
- ],
205
- ];
206
- break;
207
-
208
- case 'login_protect':
209
- $additional = [
210
- 'vars' => [
211
- 'video_id' => '269191603'
212
- ],
213
- 'strings' => [
214
- 'slide_title' => 'Brute Force Login Protection',
215
- ],
216
- ];
217
- break;
218
-
219
- case 'comments_filter':
220
- $additional = [
221
- 'vars' => [
222
- 'video_id' => '269193270'
223
- ],
224
- 'strings' => [
225
- 'slide_title' => 'Block 100% Comment SPAM by Bots - no CAPTCHAs (really!)',
226
- ],
227
- ];
228
- break;
229
-
230
- case 'plugin_badge':
231
- $additional = [
232
- 'vars' => [
233
- 'video_id' => '552430272'
234
- ],
235
- 'strings' => [
236
- 'slide_title' => 'Demonstrate To Visitors That You Take Security Seriously',
237
- ],
238
- ];
239
- break;
240
 
241
  case 'plugin_telemetry':
242
  $additional = [
@@ -252,21 +85,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
252
  ];
253
  break;
254
 
255
- case 'free_trial':
256
- $additional = [
257
- 'hrefs' => [
258
- 'free_trial' => 'https://shsec.io/freetrialwizard',
259
- 'features' => 'https://getshieldsecurity.com/features/',
260
- ],
261
- 'imgs' => [
262
- 'free_trial' => $con->svgs->raw( 'bootstrap/shield-fill-plus.svg' ),
263
- ],
264
- 'strings' => [
265
- 'slide_title' => 'Try ShieldPRO For Free',
266
- ],
267
- ];
268
- break;
269
-
270
  case 'import':
271
  $additional = [
272
  'hrefs' => [
@@ -278,40 +96,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
278
  ];
279
  break;
280
 
281
- case 'optin':
282
- $users = Services::WpUsers()->getCurrentWpUser();
283
- $additional = [
284
- 'hrefs' => [
285
- 'facebook' => 'https://shsec.io/pluginshieldsecuritygroupfb',
286
- 'twitter' => 'https://shsec.io/pluginshieldsecuritytwitter',
287
- 'email' => 'https://shsec.io/pluginshieldsecuritynewsletter',
288
- ],
289
- 'imgs' => [
290
- 'facebook' => $con->svgs->raw( 'bootstrap/facebook.svg' ),
291
- 'twitter' => $con->svgs->raw( 'bootstrap/twitter.svg' ),
292
- 'email' => $con->svgs->raw( 'bootstrap/envelope-fill.svg' ),
293
- ],
294
- 'vars' => [
295
- 'name' => $users->first_name,
296
- 'email' => $users->user_email
297
- ],
298
- 'strings' => [
299
- 'slide_title' => 'Come Join Us!',
300
- ],
301
- ];
302
- break;
303
-
304
- case 'thankyou':
305
- $additional = [
306
- 'vars' => [
307
- 'video_id' => '269364269'
308
- ],
309
- 'strings' => [
310
- 'slide_title' => 'Thank You For Choosing Shield Security',
311
- ],
312
- ];
313
- break;
314
-
315
  case 'how_shield_works':
316
  $additional = [
317
  'imgs' => [
@@ -374,43 +158,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
374
  break;
375
  }
376
  }
377
- elseif ( $sCurrentWiz == 'gdpr' ) {
378
- switch ( $step ) {
379
-
380
- case 'results':
381
- $aItems = $this->getGdprSearchItems();
382
- $bHasSearchItems = !empty( $aItems );
383
- $aResults = $this->runGdprSearch();
384
-
385
- $nTotal = 0;
386
- foreach ( $aResults as $aResult ) {
387
- $nTotal += $aResult[ 'count' ];
388
- }
389
-
390
- $additional = [
391
- 'flags' => [
392
- 'has_search_items' => $bHasSearchItems
393
- ],
394
- 'data' => [
395
- 'result' => $this->runGdprSearch(),
396
- 'count_total' => $nTotal,
397
- 'has_results' => $nTotal > 0,
398
- ]
399
- ];
400
- break;
401
-
402
- default:
403
- break;
404
- }
405
- }
406
-
407
- if ( empty( $additional ) ) {
408
- $additional = parent::getRenderData_SlideExtra( $step );
409
- }
410
-
411
- if ( !empty( $additional[ 'vars' ][ 'video_id' ] ) ) {
412
- $additional[ 'imgs' ][ 'video_thumb' ] = $this->getVideoThumbnailUrl( $additional[ 'vars' ][ 'video_id' ] );
413
- }
414
 
415
  if ( empty( $additional[ 'vars' ][ 'step_slug' ] ) ) {
416
  $additional[ 'vars' ][ 'step' ] = $step;
@@ -419,52 +166,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
419
  return $additional;
420
  }
421
 
422
- /**
423
- * @see https://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo
424
- * @param string $videoID
425
- */
426
- private function getVideoThumbnailUrl( $videoID ) {
427
- $raw = Services::HttpRequest()
428
- ->getContent( sprintf( 'https://vimeo.com/api/v2/video/%s.json', $videoID ) );
429
- return empty( $raw ) ? '' : json_decode( $raw, true )[ 0 ][ 'thumbnail_large' ];
430
- }
431
-
432
- /**
433
- * @return \FernleafSystems\Utilities\Response
434
- */
435
- private function wizardIpDetect() {
436
- /** @var Plugin\Options $opts */
437
- $opts = $this->getOptions();
438
- $srvIP = Services::IP();
439
- $ip = trim( Services::Request()->post( 'ip', '' ) );
440
- $success = false;
441
-
442
- $response = new \FernleafSystems\Utilities\Response();
443
- if ( empty( $ip ) ) {
444
- $msg = __( 'IP address was empty.', 'wp-simple-firewall' );
445
- }
446
- elseif ( !$srvIP->isValidIp_PublicRemote( $ip ) ) {
447
- $msg = __( "IP address wasn't a valid public IP address.", 'wp-simple-firewall' );
448
- }
449
- else {
450
- $source = ( new FindSourceFromIp() )->run( Services::Request()->post( 'ip' ) );
451
- if ( empty( $source ) ) {
452
- $msg = __( "Sorry, we couldn't find an address source from this IP.", 'wp-simple-firewall' );
453
- }
454
- else {
455
- $success = true;
456
- $opts->setVisitorAddressSource( $source );
457
- $msg = __( 'Success!', 'wp-simple-firewall' ).' '
458
- .sprintf( '"%s" was found to be the best source of visitor IP addresses for your site.', $source );
459
- }
460
- }
461
-
462
- $this->getCon()->getModule_Plugin()->saveModOptions();
463
- $response->setSuccessful( $success );
464
-
465
- return $response->setMessageText( $msg );
466
- }
467
-
468
  /**
469
  * @return \FernleafSystems\Utilities\Response
470
  */
@@ -528,38 +229,6 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
528
  ->setMessageText( $sMessage );
529
  }
530
 
531
- /**
532
- * @return \FernleafSystems\Utilities\Response
533
- */
534
- private function wizardSecurityAdmin() {
535
- $req = Services::Request();
536
- $pin = $req->post( 'sec_admin_key' );
537
- $confirm = $req->post( 'AccessKeyConfirm' );
538
-
539
- $success = false;
540
- if ( empty( $pin ) ) {
541
- $msg = __( "Security Admin PIN was empty.", 'wp-simple-firewall' );
542
- }
543
- elseif ( $pin != $confirm ) {
544
- $msg = __( "Security PINs don't match.", 'wp-simple-firewall' );
545
- }
546
- else {
547
- $mod = $this->getCon()->getModule_SecAdmin();
548
- try {
549
- $mod->setNewPinManually( $pin );
550
- $success = true;
551
- $msg = __( 'Security Admin PIN setup was successful.', 'wp-simple-firewall' );
552
- }
553
- catch ( \Exception $e ) {
554
- $msg = __( $e->getMessage(), 'wp-simple-firewall' );
555
- }
556
- }
557
-
558
- return ( new \FernleafSystems\Utilities\Response() )
559
- ->setSuccessful( $success )
560
- ->setMessageText( $msg );
561
- }
562
-
563
  /**
564
  * @return \FernleafSystems\Utilities\Response
565
  */
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities\Net\FindSourceFromIp;
7
 
8
+ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_Base {
 
 
 
 
 
 
 
9
 
10
  /**
11
  * @param string $step
14
  protected function processWizardStep( string $step ) {
15
  switch ( $step ) {
16
 
 
 
 
 
17
  case 'license':
18
  $response = $this->wizardLicense();
19
  break;
22
  $response = $this->wizardImportOptions();
23
  break;
24
 
 
 
 
 
25
  case 'audit_trail':
26
  $response = $this->wizardAuditTrail();
27
  break;
59
  return $response;
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * @param string $step
64
  * @return array
67
  $con = $this->getCon();
68
 
69
  $additional = [];
 
 
 
70
  if ( $sCurrentWiz == 'welcome' ) {
71
 
72
  switch ( $step ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  case 'plugin_telemetry':
75
  $additional = [
85
  ];
86
  break;
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  case 'import':
89
  $additional = [
90
  'hrefs' => [
96
  ];
97
  break;
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  case 'how_shield_works':
100
  $additional = [
101
  'imgs' => [
158
  break;
159
  }
160
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  if ( empty( $additional[ 'vars' ][ 'step_slug' ] ) ) {
163
  $additional[ 'vars' ][ 'step' ] = $step;
166
  return $additional;
167
  }
168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  /**
170
  * @return \FernleafSystems\Utilities\Response
171
  */
229
  ->setMessageText( $sMessage );
230
  }
231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  /**
233
  * @return \FernleafSystems\Utilities\Response
234
  */
templates/twig/common/macros.twig CHANGED
@@ -3,14 +3,14 @@
3
  {% endmacro %}
4
 
5
  {% macro slideTitle(content) %}
6
- <h4>{{ content }}</h4>
7
  {% endmacro %}
8
 
9
  {% macro formInput_Hidden(name,value) %}
10
  <input name="{{ name }}" value="{{ value }}" type="hidden" />
11
  {% endmacro %}
12
 
13
- {% macro formInput_Checkbox(name,value,toplabel,label,help,id) %}
14
 
15
  {% if id is not defined or id|length < 1 %}
16
  {% set id='_'~name %}
@@ -21,8 +21,10 @@
21
  <div class="col-8">
22
  <div class="form-check">
23
  <input type="checkbox" name="{{ name }}"
24
- class="form-check-input"
25
- id="{{ id }}" value="{{ value }}" />
 
 
26
  <label class="form-check-label" for="{{ id }}">
27
  {{ label|raw }}
28
  </label>
@@ -44,9 +46,14 @@
44
  {{ icwp_macros.formInput_Base('password',name,value,label,placeholder,help,id) }}
45
  {% endmacro %}
46
 
47
- {% macro formInput_Text(name,value,label,placeholder,help,id) %}
48
  {% import _self as icwp_macros %}
49
- {{ icwp_macros.formInput_Base('text',name,value,label,placeholder,help,id) }}
 
 
 
 
 
50
  {% endmacro %}
51
 
52
  {% macro formInput_Radio(name,values,toplabel,id) %}
@@ -57,8 +64,8 @@
57
  {% for value,label in values %}
58
  <label class="form-check-label">
59
  <input type="radio" name="{{ name }}"
60
- class="form-check-input"
61
- id="{{ name~value }}" value="{{ value }}">
62
  {{ label|raw }}
63
  </label>
64
  {% endfor %}
@@ -76,13 +83,11 @@
76
  {% endfor %}
77
  {% endmacro %}
78
 
79
-
80
- {% macro formInput_Submit2(label,name,btn,large=false) %}
81
  <div class="row">
82
- <div class="col-4"></div>
83
- <div class="col-8">
84
  <button type="submit"
85
- class="button button-{{ btn|default('primary') }} {% if large %}py-2 px-4{% endif %}"
86
  {% if name is defined %} name="{{ name }}" {% endif %}
87
  >{{ label|default('Submit')|raw }}</button>
88
  </div>
@@ -94,14 +99,14 @@
94
  <div class="col-6"></div>
95
  <div class="col-6">
96
  <button type="submit"
97
- class="{% if large == true %} btn-block {% endif %} button button-{{ btn|default('primary') }}"
98
  {% if name is defined %} name="{{ name }}" {% endif %}
99
  >{{ label|default('Submit')|raw }}</button>
100
  </div>
101
  </div>
102
  {% endmacro %}
103
 
104
- {% macro formInput_Base(type,name,value,label,placeholder,help,id) %}
105
  {% if id is not defined or id|length < 1 %}
106
  {% set id='_'~name %}
107
  {% endif %}
@@ -110,7 +115,9 @@
110
  <label class="col-4 col-form-label" for="{{ id }}">{{ label }}</label>
111
  <div class="col-8">
112
  <input name="{{ name }}" value="{{ value }}" type="{{ type }}"
113
- class="form-control" id="{{ id }}" placeholder="{{ placeholder|default('') }}">
 
 
114
  {% if help is defined and help|length > 0 %}
115
  <small class="form-text text-muted">{{ help|raw }}</small>
116
  {% endif %}
@@ -120,18 +127,18 @@
120
 
121
  {% macro embedVimeo( video_id, width, height, class, id ) %}
122
  <div class="embed-vimeo embed-responsive {{ class|default('embed-responsive-16by9') }}"
123
- id="{{ id|default('') }}">
124
  <iframe src="https://player.vimeo.com/video/{{ video_id }}"
125
- width="{{ width|default(640) }}" height="{{ height|default(480) }}"
126
- frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
127
  </div>
128
  {% endmacro %}
129
 
130
  {% macro embedVimeoFeather( video_id, img_url, img_play, id ) %}
131
  <style>
132
  .vimeo-feather a {
133
- background-image: url({{ img_play }});
134
- }
135
  </style>
136
  <div class="d-flex justify-content-center">
137
  <div class="vimeo-feather">
3
  {% endmacro %}
4
 
5
  {% macro slideTitle(content) %}
6
+ <h4 class="my-3">{{ content }}</h4>
7
  {% endmacro %}
8
 
9
  {% macro formInput_Hidden(name,value) %}
10
  <input name="{{ name }}" value="{{ value }}" type="hidden" />
11
  {% endmacro %}
12
 
13
+ {% macro formInput_Checkbox(name,value,toplabel,label,help,id, checked=false) %}
14
 
15
  {% if id is not defined or id|length < 1 %}
16
  {% set id='_'~name %}
21
  <div class="col-8">
22
  <div class="form-check">
23
  <input type="checkbox" name="{{ name }}"
24
+ class="form-check-input"
25
+ id="{{ id }}" value="{{ value }}"
26
+ {{ checked ? 'checked checked="checked"' : '' }}
27
+ />
28
  <label class="form-check-label" for="{{ id }}">
29
  {{ label|raw }}
30
  </label>
46
  {{ icwp_macros.formInput_Base('password',name,value,label,placeholder,help,id) }}
47
  {% endmacro %}
48
 
49
+ {% macro formInput_Number(name,value,label,placeholder,help,id,classes='') %}
50
  {% import _self as icwp_macros %}
51
+ {{ icwp_macros.formInput_Base('number',name,value,label,placeholder,help,id,classes) }}
52
+ {% endmacro %}
53
+
54
+ {% macro formInput_Text(name,value,label,placeholder,help,id,type='text') %}
55
+ {% import _self as icwp_macros %}
56
+ {{ icwp_macros.formInput_Base(type,name,value,label,placeholder,help,id) }}
57
  {% endmacro %}
58
 
59
  {% macro formInput_Radio(name,values,toplabel,id) %}
64
  {% for value,label in values %}
65
  <label class="form-check-label">
66
  <input type="radio" name="{{ name }}"
67
+ class="form-check-input"
68
+ id="{{ name~value }}" value="{{ value }}">
69
  {{ label|raw }}
70
  </label>
71
  {% endfor %}
83
  {% endfor %}
84
  {% endmacro %}
85
 
86
+ {% macro formInput_Submit2(label,name,btn,large=false,classes='') %}
 
87
  <div class="row">
88
+ <div class="col-8 offset-4">
 
89
  <button type="submit"
90
+ class="button button-{{ btn|default('primary') }} {% if large %}py-2 px-4{% endif %} {{ classes }}"
91
  {% if name is defined %} name="{{ name }}" {% endif %}
92
  >{{ label|default('Submit')|raw }}</button>
93
  </div>
99
  <div class="col-6"></div>
100
  <div class="col-6">
101
  <button type="submit"
102
+ class="{% if large == true %} btn-block {% endif %} button button-{{ btn|default('primary') }}"
103
  {% if name is defined %} name="{{ name }}" {% endif %}
104
  >{{ label|default('Submit')|raw }}</button>
105
  </div>
106
  </div>
107
  {% endmacro %}
108
 
109
+ {% macro formInput_Base(type,name,value,label,placeholder,help,id,classes='') %}
110
  {% if id is not defined or id|length < 1 %}
111
  {% set id='_'~name %}
112
  {% endif %}
115
  <label class="col-4 col-form-label" for="{{ id }}">{{ label }}</label>
116
  <div class="col-8">
117
  <input name="{{ name }}" value="{{ value }}" type="{{ type }}"
118
+ class="form-control {{ classes }}" id="{{ id }}" placeholder="{{ placeholder|default('') }}"
119
+ {% if type is not empty %}type="{{ type }}"{% endif %}
120
+ >
121
  {% if help is defined and help|length > 0 %}
122
  <small class="form-text text-muted">{{ help|raw }}</small>
123
  {% endif %}
127
 
128
  {% macro embedVimeo( video_id, width, height, class, id ) %}
129
  <div class="embed-vimeo embed-responsive {{ class|default('embed-responsive-16by9') }}"
130
+ id="{{ id|default('') }}">
131
  <iframe src="https://player.vimeo.com/video/{{ video_id }}"
132
+ width="{{ width|default(640) }}" height="{{ height|default(480) }}"
133
+ frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
134
  </div>
135
  {% endmacro %}
136
 
137
  {% macro embedVimeoFeather( video_id, img_url, img_play, id ) %}
138
  <style>
139
  .vimeo-feather a {
140
+ background-image: url({{ img_play }});
141
+ }
142
  </style>
143
  <div class="d-flex justify-content-center">
144
  <div class="vimeo-feather">
templates/twig/components/merlin/container.twig ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% block body_content %}
2
+ <div class="container-fluid">
3
+ {% block body_content_header %}
4
+ <div class="row">
5
+ <div class="col-4 offset-4"></div>
6
+ </div>
7
+ {% endblock %}
8
+
9
+ {% block body_content_main %}
10
+ <div class="row row-cols-1 justify-content-center">
11
+ <div class="col-12">
12
+ <!-- SmartWizard html -->
13
+ <div id="merlin">
14
+ <ul class="nav">
15
+ {% for num,step in content.steps %}
16
+ <li class="nav-item">
17
+ <a class="nav-link" href="#step-{{ step.step_slug }}">{{ step.step_name }}</a>
18
+ </li>
19
+ {% endfor %}
20
+ </ul>
21
+
22
+ <div class="tab-content">
23
+ {% for step in content.steps %}
24
+ <div id="step-{{ step.step_slug }}" class="tab-pane" role="tabpanel"
25
+ aria-labelledby="step-{{ step.step_slug }}">
26
+ {{ step.step_body|raw }}
27
+ </div>
28
+ {% endfor %}
29
+ </div>
30
+
31
+ <div class="progress">
32
+ <div class="progress-bar" role="progressbar" style="width: 0" aria-valuenow="0" aria-valuemin="0"
33
+ aria-valuemax="100"></div>
34
+ </div>
35
+ </div>
36
+
37
+ </div>
38
+ </div>
39
+ {% endblock %}
40
+
41
+ {% block body_content_footer %}
42
+ <div class="row justify-content-center mt-4">
43
+ <div class="col-6 text-center">
44
+ <a href="{{ hrefs.dashboard_home }}">{{ imgs.svgs.exit|raw }} Exit Wizard</a>
45
+ </div>
46
+ </div>
47
+ {% endblock %}
48
+ </div>
49
+ {% endblock %}
50
+
51
+ {% block body_footer_scripts %}
52
+ {% endblock %}
templates/twig/components/merlin/steps/base.twig ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% import '/common/macros.twig' as icwp_macros %}
2
+
3
+ {% block step_header %}
4
+ {% endblock %}
5
+
6
+ {% block step_body %}
7
+
8
+ <div class="row row-cols-1 justify-content-center mt-4">
9
+ <div class="col-12 col-xl-10 col-lg-12 col-md-12">
10
+
11
+ {% block slide_body_title %}
12
+ <h4 class="mb-3">{{ strings.step_title|default('NO TITLE') }}</h4>
13
+ {% endblock %}
14
+
15
+ {% block slide_body_video_section %}
16
+ <div class="row">
17
+ <div class="col col-8">
18
+ {% block slide_body_video_section_blurb %}
19
+ {% endblock %}
20
+
21
+ <div class="mt-4">
22
+ {% block slide_body_action_area %}{% endblock %}
23
+ </div>
24
+ </div>
25
+ <div class="col col-4">
26
+ {% block slide_body_video_section_video %}
27
+ {% if vars.video_id|default('') is not empty %}
28
+ {{ icwp_macros.embedVimeoFeather( vars.video_id, imgs.video_thumb, imgs.play_button ) }}
29
+ {% endif %}
30
+ {% endblock %}
31
+ </div>
32
+ </div>
33
+ {% endblock %}
34
+
35
+ </div>
36
+ </div>
37
+ {% endblock %}
38
+
39
+ {% block step_footer %}
40
+ {% endblock %}
templates/twig/components/merlin/steps/comment_spam.twig ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>Nearly 100% of comments SPAM is by automated BOTS.</p>
5
+ <p>Shield Security provides exclusive, highly effective technology to block BOT SPAM. But unlike Akismet,
6
+ your private comment data is never sent offsite to 3rd parties, so you can remain as privacy compliant as you need.</p>
7
+ <p>The technology used to block comment SPAM is the same as that for login protection... so there's no CAPTCHAs
8
+ or any other annoying extras added to your forms.</p>
9
+ {% endblock %}
10
+
11
+ {% block slide_body_action_area %}
12
+
13
+ <form class="form-horizontal merlin-form ajax-form">
14
+
15
+ <div class="row">
16
+ <div class="col-4">
17
+ Comment SPAM Blocking
18
+ </div>
19
+ <div class="col-8">
20
+ {{ icwp_macros.formInput_Radio_Wizard(
21
+ 'CommentsFilterOption',
22
+ {
23
+ 'Y': '<span>Turn On</span> - Block automated bot SPAM comments',
24
+ 'N': "<span>Turn Off</span> - Don't block automated comment SPAM"
25
+ },
26
+ 'Comment SPAM Blocking'
27
+ ) }}
28
+ </div>
29
+ </div>
30
+
31
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
32
+ {{ icwp_macros.formInput_Submit2( 'Set Comment SPAM Protection', null, null, false ) }}
33
+ </form>
34
+
35
+ {% endblock %}
templates/twig/components/merlin/steps/free_trial.twig ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section %}
4
+ <div class="row">
5
+ <div class="col-12">
6
+ <p>Upgrade your WordPress security to professional-grade protection to add extra features such as:</p>
7
+ <ul class="list-group list-group-flush">
8
+ <li class="list-group-item">Malware scanning and repair</li>
9
+ <li class="list-group-item"><code>wp-config.php</code> protection and repair</li>
10
+ <li class="list-group-item">Plugin/Theme file protection and repair</li>
11
+ <li class="list-group-item">User Security Policies such as Password and Auto-Suspend Idle Users</li>
12
+ <li class="list-group-item">Contact Form SPAM protection for Ninja Forms, WPForms, Gravity Forms and more</li>
13
+ <li class="list-group-item">Many, <a href="{{ hrefs.features }}" target="_blank">many more features</a></li>
14
+ </ul>
15
+ <p class="mt-3">Get the risk-free, no obligation free trial of ShieldPRO today.</p>
16
+ <a href="{{ hrefs.free_trial }}"
17
+ class="button text-center p-3"
18
+ target="_blank"
19
+ >
20
+ {{ imgs.free_trial|raw }}
21
+ Get The Free Trial!
22
+ </a>
23
+ </div>
24
+ <div class="col-4">
25
+ </div>
26
+ </div>
27
+ {% endblock %}
templates/twig/components/merlin/steps/guided_setup_welcome.twig ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>If this is your first time installing Shield, please use this guided setup wizard to help you get started.</p>
5
+ <p>As Shield Security does a lot, and has a lot of options, we've provided this guided setup to introduce
6
+ some key features, and help you get started quickly with some important features.</p>
7
+ <p>We encourage you to watch the videos at each stage that has them, to familiarise yourself with
8
+ the details of settings you're changing.</p>
9
+ <p>You can skip any steps, or go back and revisit previous steps, or even exit the wizard altogether using
10
+ the link at the bottom of each step.</p>
11
+ {% endblock %}
templates/twig/components/merlin/steps/import.twig ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>If you have an export of setting from another Shield site, use the form below to upload them.</p>
5
+ {% endblock %}
6
+
7
+ {% block slide_body_action_area %}
8
+ TODO!
9
+ <form class="form-horizontal merlin-form" autocomplete="off" method="post" action="" enctype="multipart/form-data">
10
+ {% for input_name,input_value in vars.file_upload_nonce %}
11
+ <input type="hidden" name="{{ input_name }}" value="{{ input_value }}" />
12
+ {% endfor %}
13
+ <div class="">
14
+ <label for="ImportFile" class="form-label">{{ strings.select_import_file }}</label>
15
+ <input name="import_file" type="file" class="" id="ImportFile"
16
+ accept=".json">
17
+ </div>
18
+ <div class="">
19
+ <label for="_confirm_file" class="col-form-label">
20
+ <input type="checkbox" class="form-control text-end"
21
+ name="confirm" id="_confirm_file" value="Y" />
22
+ {{ strings.i_understand }}
23
+ <br />
24
+ <small class="form-text text-muted">{{ strings.be_sure }} {{ strings.not_undone }}</small>
25
+ </label>
26
+ </div>
27
+ <div class="text-end">
28
+ <input id="SubmitForm" href="#" class="btn btn-primary" type="submit"
29
+ value="{{ strings.import_options }}" />
30
+ </div>
31
+ </form>
32
+
33
+ <div class="row">
34
+ <div class="col-4">
35
+ Check License
36
+ </div>
37
+ <div class="col-8">
38
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
39
+ {{ icwp_macros.formInput_Submit2( 'Check For ShieldPRO License', null, null, false, 'mt-2' ) }}
40
+ </div>
41
+ </div>
42
+
43
+ </form>
44
+ {% endblock %}
templates/twig/components/merlin/steps/ip_blocking.twig ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>
5
+ Automatically blocking malicious IP addresses is Shield's most important security feature.
6
+ All other Shield features link back to this.
7
+ </p>
8
+ <p>The reason is simple - when you block malicious IP addresses,
9
+ you prevent all security problems associated with those bad bots and their automated hacking attempts, such as:</p>
10
+ <ul class="list-group list-group-flush mb-3">
11
+ <li class="list-group-item">brute force login attacks</li>
12
+ <li class="list-group-item">exploitation of current and future vulnerabilities within plugins/themes on your site</li>
13
+ <li class="list-group-item">malware injection and exploitation</li>
14
+ <li class="list-group-item">automated comment SPAM</li>
15
+ <li class="list-group-item">resource depletion through DoS attacks, excessive probing and any forceful hacking attempts</li>
16
+ </ul>
17
+ <p>Shield monitors every IP address that connects to your site.
18
+ When they do something bad, such as a failed login or comment SPAM attempt, it starts an "offense counter".</p>
19
+ <p>When the offense counter hits your limit (default: 10),
20
+ the IP address is completely blocked from further site access.
21
+ Then, once the IP has stopped accessing your site, to keep the list optimised for performance, the IP is automatically removed from the list.
22
+ </p>
23
+ <p><span class="badge text-bg-success">NEW</span>
24
+ In close partnership with CrowdSec, Shield offers crowd-sourced IP block-lists.
25
+ This means you can take advantage of knowledge gained by other WordPress sites
26
+ and instantly block IP addresses when they access your site.
27
+ [<a href="https://shsec.io/l7" target="_blank">more info</a>]
28
+ </p>
29
+ {% endblock %}
30
+
31
+ {% block slide_body_action_area %}
32
+
33
+ <form class="form-horizontal merlin-form ajax-form">
34
+
35
+ <div class="row">
36
+ <div class="col-4">
37
+ Configure IP Blocking
38
+ </div>
39
+ <div class="col-8">
40
+ {{ icwp_macros.formInput_Number( 'offenses', vars.offense_limit, 'Offense Limit', null,
41
+ 'We recommend somewhere between 5 and 10. The smaller the limit, the stricter Shield will be.',null
42
+ ) }}
43
+
44
+ <div class="form-group row mt-3">
45
+ <label class="col-4 col-form-label" for="_block_length">Block Length</label>
46
+ <div class="col-8">
47
+ <select name="block_length" id="_block_length">
48
+ <option value="day">1 Day</option>
49
+ <option value="week">1 Week</option>
50
+ <option value="month">1 Month</option>
51
+ </select>
52
+ <small class="form-text text-muted d-block">
53
+ Malicious IPs should be blocked for at least a day.
54
+ </small>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="mt-3"></div>
59
+ {{ icwp_macros.formInput_Checkbox(
60
+ 'cs_block', 'Y', 'Crowd-Sourced IPs', 'Use Crowd-Sourced IP Blocklist',
61
+ "Crowd-sourced IP block-lists involves sharing your IP block-list with others, and they share them with you.",
62
+ null, true
63
+ ) }}
64
+
65
+ <div class="mt-3"></div>
66
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
67
+ {{ icwp_macros.formInput_Submit2( 'Set IP Blocking Options', null, null, false, 'mt-2' ) }}
68
+ </div>
69
+ </div>
70
+
71
+ </form>
72
+ {% endblock %}
templates/twig/components/merlin/steps/ip_detect.twig ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>Being able to detect the correct visitor IP address is critical for any security system.</p>
5
+ <p>This step in the wizard might be your most important as it will help ensure Shield can always find the Visitor IP.</p>
6
+ <p>Shield tries to do this automatically, of course, and though it works 99% of the time, sometimes a funky webhost
7
+ might mix things up a little.</p>
8
+ <p>To solve this, you can tell Shield what your IP address is right now,
9
+ and this will help us configure the best visitor IP source going forward.</p>
10
+
11
+ {% if flags.has_none %}
12
+ <div class="alert alert-warning">Shield couldn't detect any IP addresses. This represents a critical webhosting configuration problem.</div>
13
+
14
+ {% elseif flags.has_only_1 %}
15
+ <div class="alert alert-info">Configuration isn't required as Shield could only detect 1 distinct IP address:
16
+ <code>{{ vars.the_ip }}</code></div>
17
+
18
+ {% elseif flags.has_multiple %}
19
+ <form class="form-horizontal merlin-form ajax-form mt-4">
20
+
21
+ <div class="row my-3">
22
+ <label class="col-4 col-form-label">
23
+ Step 1: What Is <em>Your</em> IP?
24
+ </label>
25
+ <div class="col-8">
26
+ <a href="{{ hrefs.visitor_ip }}" target="_blank">Click here to discover your current IP Address</a>
27
+ </div>
28
+ </div>
29
+
30
+ <div class="form-group row mt-3">
31
+ <label class="col-4 col-form-label" for="_ip_source">
32
+ Step 2: Select Your IP
33
+ </label>
34
+ <div class="col-8">
35
+ <select name="ip_source" id="_ip_source">
36
+ {% for ip_source,ip in vars.all_ips %}
37
+ <option value="{{ ip_source }}">{{ ip }}</option>
38
+ {% endfor %}
39
+ </select>
40
+ <small class="form-text text-muted d-block">
41
+ Is your IP address on this list?
42
+ </small>
43
+ </div>
44
+ </div>
45
+
46
+ <div class="mt-3"></div>
47
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
48
+ {{ icwp_macros.formInput_Submit2( 'Confirm My IP Address', null, null, false ) }}
49
+ </form>
50
+ {% endif %}
51
+
52
+ {% endblock %}
templates/twig/components/merlin/steps/license.twig ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>To better tailor this Guided Wizard to your needs, if you have a ShieldPRO license activated for this site,
5
+ please click the button below to install the license automatically.</p>
6
+ <p>If this doesn't apply to you, don't worry, you can <a href="javascript:{}" class="skip-step">skip to the next step</a>.</p>
7
+ {% endblock %}
8
+
9
+ {% block slide_body_action_area %}
10
+
11
+ <form class="form-horizontal merlin-form ajax-form">
12
+
13
+ <div class="row">
14
+ <div class="col-4">
15
+ Check License
16
+ </div>
17
+ <div class="col-8">
18
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
19
+ {{ icwp_macros.formInput_Submit2( 'Check For ShieldPRO License', null, null, false, 'mt-2' ) }}
20
+ </div>
21
+ </div>
22
+
23
+ </form>
24
+ {% endblock %}
templates/twig/{wizard/slides/welcome/login_protect.twig → components/merlin/steps/login_protection.twig} RENAMED
@@ -1,7 +1,6 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
 
3
  {% block slide_body_video_section_blurb %}
4
- <h5>Watch the quick (63s) explanatory video:</h5>
5
  <p>Shield is designed to protect your WP Login against automated, brute force login attacks from bots.</p>
6
  <p>Shield brings its exclusive AntiBot Detection Engine to your login pages to detect bots
7
  without the need for any CAPTCHAs, or any other UX-destructive additions to your forms whatsoever.</p>
@@ -9,25 +8,25 @@
9
 
10
  {% block slide_body_action_area %}
11
 
12
- {% set radiovalues =
13
- {
14
- 'Y': '<span>Turn On</span> - Protect my WordPress login from automated attacks',
15
- 'N': '<span>Turn Off</span> - Do not protect my WordPress login from automated attacks'
16
- }
17
- %}
18
-
19
- <form class="form-horizontal icwp-wizard-form">
20
 
21
  <div class="row">
22
  <div class="col-4">
23
  Brute Force Login Protection
24
  </div>
25
  <div class="col-8">
26
- {{ icwp_macros.formInput_Radio_Wizard( 'LoginProtectOption', radiovalues, 'Bot Login Protection' ) }}
 
 
 
 
 
 
 
27
  </div>
28
  </div>
29
 
 
30
  {{ icwp_macros.formInput_Submit2( 'Set Login Protection', null, null, false ) }}
31
- {{ icwp_macros.formInput_Hidden( 'wizard-step', vars.step ) }}
32
  </form>
33
  {% endblock %}
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
 
3
  {% block slide_body_video_section_blurb %}
 
4
  <p>Shield is designed to protect your WP Login against automated, brute force login attacks from bots.</p>
5
  <p>Shield brings its exclusive AntiBot Detection Engine to your login pages to detect bots
6
  without the need for any CAPTCHAs, or any other UX-destructive additions to your forms whatsoever.</p>
8
 
9
  {% block slide_body_action_area %}
10
 
11
+ <form class="form-horizontal merlin-form ajax-form">
 
 
 
 
 
 
 
12
 
13
  <div class="row">
14
  <div class="col-4">
15
  Brute Force Login Protection
16
  </div>
17
  <div class="col-8">
18
+ {{ icwp_macros.formInput_Radio_Wizard(
19
+ 'LoginProtectOption',
20
+ {
21
+ 'Y': '<span>Turn On</span> - Protect my WordPress login from automated attacks',
22
+ 'N': '<span>Turn Off</span> - Do not protect my WordPress login from automated attacks'
23
+ },
24
+ 'Bot Login Protection'
25
+ ) }}
26
  </div>
27
  </div>
28
 
29
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
30
  {{ icwp_macros.formInput_Submit2( 'Set Login Protection', null, null, false ) }}
 
31
  </form>
32
  {% endblock %}
templates/twig/{wizard/slides/welcome/optin.twig → components/merlin/steps/opt_in.twig} RENAMED
@@ -1,9 +1,6 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
 
3
  {% block slide_body_video_section %}
4
- {% endblock %}
5
-
6
- {% block slide_body_action_area %}
7
  <div class="row">
8
  <div class="col-8">
9
  <p>Jump into our Shield Security Facebook group where you can ask questions
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
 
3
  {% block slide_body_video_section %}
 
 
 
4
  <div class="row">
5
  <div class="col-8">
6
  <p>Jump into our Shield Security Facebook group where you can ask questions
templates/twig/components/merlin/steps/security_admin.twig ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>When the Security Admin feature is switched-on, only administrators that know the Security PIN will have
5
+ access to the Shield Security plugin.</p>
6
+ <p>This is particularly useful for websites with multiple admins, but where not all of them are familiar
7
+ with how to manage the site's security.</p>
8
+ <p>With the Security Admin enabled, you'll be able to restrict:</p>
9
+ <ul class="list-group list-group-flush mb-3">
10
+ <li class="list-group-item">who can view/change Shield Security settings</li>
11
+ <li class="list-group-item">who can deactivate and uninstall the Shield Security plugin</li>
12
+ <li class="list-group-item">who can modify key WordPress settings such as the home URL, permalinks, and others</li>
13
+ <li class="list-group-item">who can create or delete other admin users</li>
14
+ </ul>
15
+ <p>It's also a great extra layer of security in-case someone gets unauthorized access to your WordPress admin dashboard.</p>
16
+ <p>To turn this option on, please supply a password below (aka 'Security PIN').</p>
17
+ {% endblock %}
18
+
19
+ {% block slide_body_action_area %}
20
+
21
+ <form class="form-horizontal merlin-form ajax-form">
22
+
23
+ <div class="row">
24
+ <div class="col-4">
25
+ Supply A Security Access PIN
26
+ </div>
27
+ <div class="col-8">
28
+ {{ icwp_macros.formInput_Password( 'SecAdminPIN', '', 'Access PIN', '', 'Do not forget this key' ) }}
29
+ {{ icwp_macros.formInput_Password( 'SecAdminPINConfirm', '', 'Confirm PIN', 'Confirm PIN' ) }}
30
+
31
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
32
+ {{ icwp_macros.formInput_Submit2( 'Turn On Security Admin', null, null, false, 'mt-2' ) }}
33
+ </div>
34
+ </div>
35
+
36
+ </form>
37
+ {% endblock %}
templates/twig/{wizard/slides/welcome/plugin_badge.twig → components/merlin/steps/security_badge.twig} RENAMED
@@ -1,7 +1,6 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
 
3
  {% block slide_body_video_section_blurb %}
4
- <h5>Watch the quick (42s) explanatory video:</h5>
5
  <p>Shield's Security Badge demonstrates clearly that you take security seriously,
6
  both for yourself and also that of your customers.</p>
7
  <p>Enabling this option adds a translucent badge to the footer of your site.</p>
@@ -9,7 +8,7 @@
9
 
10
  {% block slide_body_action_area %}
11
 
12
- <form class="form-horizontal icwp-wizard-form">
13
 
14
  <div class="row">
15
  <div class="col-4">
@@ -27,7 +26,7 @@
27
  </div>
28
  </div>
29
 
 
30
  {{ icwp_macros.formInput_Submit2( 'Set Security Badge', null, null, false ) }}
31
- {{ icwp_macros.formInput_Hidden( 'wizard-step', vars.step ) }}
32
  </form>
33
  {% endblock %}
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
 
3
  {% block slide_body_video_section_blurb %}
 
4
  <p>Shield's Security Badge demonstrates clearly that you take security seriously,
5
  both for yourself and also that of your customers.</p>
6
  <p>Enabling this option adds a translucent badge to the footer of your site.</p>
8
 
9
  {% block slide_body_action_area %}
10
 
11
+ <form class="form-horizontal merlin-form ajax-form">
12
 
13
  <div class="row">
14
  <div class="col-4">
26
  </div>
27
  </div>
28
 
29
+ {{ icwp_macros.formInput_Hidden( 'step_slug', vars.step_slug ) }}
30
  {{ icwp_macros.formInput_Submit2( 'Set Security Badge', null, null, false ) }}
 
31
  </form>
32
  {% endblock %}
templates/twig/components/merlin/steps/thank_you.twig ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/components/merlin/steps/base.twig' %}
2
+
3
+ {% block slide_body_video_section_blurb %}
4
+ <p>Thank you for taking the time to go through the Guided Setup Wizard.</p>
5
+ <p>By default Shield is automatically configured to protect your site from numerous threats
6
+ and block bad visitors and bots without you having to do anything.</p>
7
+
8
+ <p class="mt-3">Here are some of the ways Shield is already protecting your site:</p>
9
+ <ul class="list-group list-group-flush">
10
+ <li class="list-group-item">Powerful <strong>Firewall</strong> is intercepting and blocking malicious traffic.</li>
11
+ <li class="list-group-item">Always <strong>watching for bots</strong> and maintaining a reputation score for each visitor.</li>
12
+ <li class="list-group-item"><strong>Scanning</strong> your core WordPress files and directories for changes and new files.</li>
13
+ <li class="list-group-item">Automatically <strong>blocking</strong> malicious visitors by IP (so you don't have to maintain an IP list yourself).</li>
14
+ <li class="list-group-item">Protecting against the #1 source of <strong>Comment SPAM</strong>.</li>
15
+ <li class="list-group-item">Keeping a log of <em>everything</em> significant in your <strong>Activity Log</strong>.</li>
16
+ <li class="list-group-item">Protecting your <strong>important user forms</strong> such as Login, Registration and Lost Password.</li>
17
+ </ul>
18
+
19
+ <a href="{{ hrefs.dashboard }}" class="button button-primary mt-3 py-2 px-4">
20
+ {{ strings.next_button|default('Go To Shield Overview') }} &rarr;
21
+ </a>
22
+ {% endblock %}
templates/twig/components/options_form/main.twig CHANGED
@@ -76,6 +76,19 @@
76
  {% endfor %}
77
  {% endif %}
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  {% if opt_section.notices|length %}
80
  {% for section_notice in opt_section.notices %}
81
  <div class="row">
76
  {% endfor %}
77
  {% endif %}
78
 
79
+ {% if opt_section.critical_warnings|length %}
80
+ {% for section_warning in opt_section.critical_warnings %}
81
+ <div class="row">
82
+ <div class="col">
83
+ <div class="alert alert-danger">
84
+ <h4 class="alert-heading">Important!</h4>
85
+ {{ section_warning|raw }}
86
+ </div>
87
+ </div>
88
+ </div>
89
+ {% endfor %}
90
+ {% endif %}
91
+
92
  {% if opt_section.notices|length %}
93
  {% for section_notice in opt_section.notices %}
94
  <div class="row">
templates/twig/wizard/pages/base.twig DELETED
@@ -1,17 +0,0 @@
1
- {% extends '/pages/base.twig' %}
2
-
3
- {% block body_footer %}
4
- {% if not flags.is_premium and false %}
5
- <div id="FooterWizardBanner" class="container-fluid">
6
- <div id="WizardBanner" class="row">
7
- <div class="col-lg-5 offset-lg-3 col-md-5 offset-md-3 col-sm-8 col-8">
8
- <p class="description">Support future development and get exclusive {{ strings.plugin_name }} features:
9
- <br />Vulnerability Scanner; Options Import; Email Support+more.</p>
10
- </div>
11
- <div class="col-lg-1 col-md-2 col-sm-2 col-4">
12
- <a href="{{ hrefs.goprofooter }}" target="_blank" class="btn btn-success shield-go-pro">Go Pro Today &rarr;</a>
13
- </div>
14
- </div>
15
- </div>
16
- {% endif %}
17
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/pages/landing.twig DELETED
@@ -1,14 +0,0 @@
1
- {% extends 'wizard/pages/base.twig' %}
2
-
3
- {% block head_stylesheets %}
4
- {{ parent() }}
5
- <link rel="stylesheet" href="{{ hrefs.css_wizard }}" />
6
- {% endblock %}
7
-
8
- {% block head_scripts %}
9
- {{ parent() }}
10
- {% endblock %}
11
-
12
- {% block body_content_main %}
13
- {% include 'wizard/snippets/wizard_landing.twig' %}
14
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/pages/wizard.twig DELETED
@@ -1,279 +0,0 @@
1
- {% extends 'wizard/pages/base.twig' %}
2
-
3
- {% block head_stylesheets %}
4
- {{ parent() }}
5
- <link rel="stylesheet" href="{{ hrefs.css_steps }}" />
6
- <link rel="stylesheet" href="{{ hrefs.css_wizard }}" />
7
- <link rel="stylesheet" href="{{ hrefs.css_fancybox }}" />
8
- {% endblock %}
9
-
10
- {% block head_scripts %}
11
- {{ parent() }}
12
- <script type="text/javascript" src="{{ hrefs.js_steps }}"></script>
13
- <script type="text/javascript" src="{{ hrefs.js_fancybox }}"></script>
14
- {% endblock %}
15
-
16
- {% block body_content_main %}
17
- <div class="row row-cols-1 justify-content-center">
18
- <div class="col-12 col-xl-8">
19
- <div id="wizard"></div>
20
- </div>
21
- </div>
22
- {% endblock %}
23
-
24
- {% block body_footer_scripts %}
25
- <script type="text/javascript">
26
-
27
- var bRequestCurrentlyRunning = false;
28
-
29
- // bring everything inside this IIFE so that they are aware of each other
30
- (function ( $ ) {
31
- $( document ).ready( function () {
32
- initializeSteps();
33
- initializeHandlers();
34
- } );
35
-
36
- function initializeSteps() {
37
- var settings = {
38
- /* Appearance */
39
- headerTag: "h1",
40
- bodyTag: "div",
41
- contentContainerTag: "div",
42
- actionContainerTag: "div",
43
- stepsContainerTag: "div",
44
- cssClass: "wizard",
45
- stepsOrientation: $.fn.steps.stepsOrientation.horizontal,
46
-
47
- /* Templates */
48
- titleTemplate: '<div class="step"><span class="shield-progress-bar"></span><div class="step-number"></div><div class="step-title">#title#</div></div>',
49
- loadingTemplate: '<span class="spinner"></span> #text#',
50
-
51
- /* Behaviour */
52
- autoFocus: false,
53
- enableAllSteps: false,
54
- enableKeyNavigation: true,
55
- enablePagination: true,
56
- suppressPaginationOnFocus: true,
57
- enableContentCache: true,
58
- enableCancelButton: false,
59
- enableFinishButton: false,
60
- preloadContent: false,
61
- showFinishButtonAlways: false,
62
- forceMoveForward: false,
63
- saveState: false,
64
- startIndex: 0,
65
-
66
- /* Transition Effects */
67
- transitionEffect: $.fn.steps.transitionEffect.slide,
68
- transitionEffectSpeed: 100,
69
-
70
- /* Events */
71
- onStepChanging: function ( event, currentIndex, newIndex ) {
72
- return true;
73
- },
74
- onStepChanged: function ( event, currentIndex, priorIndex ) {
75
- if ( currentIndex >= priorIndex ) {
76
- return;
77
- }
78
- // have to use this workaround
79
- // instead of removing steps and then adding, which does not work with jquery.steps
80
- // remove effectively does something similar internally so let's just use it directly
81
- for ( var x = 1; x < 6; x++ ) {
82
- $( '#wizard-t-' + (currentIndex + x) ).parent( 'li' ).removeClass( 'done' ).addClass( 'disabled' );
83
- }
84
- },
85
- onCanceled: function ( event ) {
86
- },
87
- onFinishing: function ( event, currentIndex ) {
88
- return true;
89
- },
90
- onFinished: function ( event, currentIndex ) {
91
- },
92
-
93
- /* Labels */
94
- labels: {
95
- cancel: "Cancel",
96
- current: "current step:",
97
- pagination: "Pagination",
98
- finish: "Finish",
99
- next: "Next",
100
- previous: "Previous",
101
- loading: "Loading ..."
102
- }
103
- };
104
-
105
- // Initialize wizard
106
- var $oWizardContainer = $( "#wizard" );
107
- var $oWizard = $oWizardContainer.steps( settings );
108
- addOtherSteps( $oWizard );
109
-
110
- var $oActions = $( 'div.actions', $oWizard );
111
- $oActions.prependTo( $oWizardContainer );
112
- $oActions.css( 'display', 'none' );
113
- }
114
-
115
- function addOtherSteps( $oWizard ) {
116
- // load all steps for showing progress bar
117
- var currentStep = {{ data.wizard_first_step|raw }};
118
- var otherSteps = {{ data.wizard_step_names|raw }};
119
- otherSteps.forEach( function ( step, index ) {
120
- if ( step === currentStep.title ) {
121
- $oWizard.steps( 'add', {{ data.wizard_first_step|raw }} );
122
- return;
123
- }
124
- $oWizard.steps( 'add', { title: step, contentMode: 'async' } );
125
- } );
126
- }
127
-
128
- function initializeHandlers() {
129
- $( document ).on( 'submit', 'form.icwp-wizard-form', submitWizardForm );
130
- $( document ).on( 'click', 'div.wizard-slide button.ButtonNextSlide', renderNext );
131
- }
132
-
133
- function reRenderCurrent() {
134
- var $oWizard = $( '#wizard' );
135
- $oWizard.steps( 'previous' );
136
- var nCurrent = $oWizard.steps( 'getCurrentIndex' );
137
- $oWizard.steps( 'remove', nCurrent + 1 );
138
- renderNextAuto( true );
139
- };
140
-
141
- function renderNext( event ) {
142
- event.preventDefault();
143
- renderNextAuto();
144
- };
145
-
146
- function renderNextAuto( overlay = false ) {
147
- if ( overlay ) {
148
- toggleOverlay( 'show' );
149
- }
150
-
151
- var aWizardSteps = {{ data.wizard_steps|raw }};
152
- var sWizardSlug = '{{ data.wizard_slug }}';
153
-
154
- var $oWizard = $( '#wizard' );
155
- var reqData = {{ ajax.steps_as_json|raw }};
156
- reqData.current_index = $oWizard.steps( 'getCurrentIndex' );
157
- reqData.wizard_steps = aWizardSteps;
158
- reqData.wizard_slug = sWizardSlug;
159
-
160
- $.post( '{{ ajax.steps.ajaxurl }}', reqData,
161
- function ( oResponse ) {
162
- if ( typeof oResponse === "undefined" || typeof oResponse.data === "undefined" ) {
163
- alert( 'There was a critical failure in the request. Cannot proceed. Example causes are HTTPS misconfiguration or PHP error warnings output.' );
164
- return;
165
- }
166
-
167
- if ( undefined !== oResponse.data.next_step ) {
168
- var removeIndex = $oWizard.steps( 'getCurrentIndex' ) + 1;
169
- $oWizard.steps( 'remove', removeIndex );
170
- $oWizard.steps( 'insert', removeIndex, oResponse.data.next_step );
171
- $oWizard.steps( 'next' );
172
- }
173
- }
174
- ).always(
175
- function () {
176
- if ( overlay ) {
177
- toggleOverlay( 'hide' );
178
- }
179
- }
180
- );
181
- };
182
-
183
- function toggleOverlay( showOrHide ) {
184
- if ( showOrHide === 'show' ) {
185
- iCWP_WPSF_BodyOverlay.show();
186
- $( 'body' ).addClass( 'wait' );
187
- }
188
- else {
189
- iCWP_WPSF_BodyOverlay.hide();
190
- $( 'body' ).removeClass( 'wait' );
191
- }
192
- }
193
-
194
- function submitWizardForm( event ) {
195
- event.preventDefault();
196
-
197
- var $oThis = jQuery( event.currentTarget );
198
- var $oForm = $oThis.closest( 'form' );
199
-
200
- sendFormRequest( $oForm );
201
- }
202
-
203
- function sendFormRequest( $oForm ) {
204
- if ( bRequestCurrentlyRunning ) {
205
- return false;
206
- }
207
- bRequestCurrentlyRunning = true;
208
-
209
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'action' )
210
- .attr( 'value', "{{ ajax.content.action }}" )
211
- .appendTo( $oForm );
212
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'exec' )
213
- .attr( 'value', "{{ ajax.content.exec }}" )
214
- .appendTo( $oForm );
215
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'exec_nonce' )
216
- .attr( 'value', "{{ ajax.content.exec_nonce }}" )
217
- .appendTo( $oForm );
218
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'mod_slug' )
219
- .attr( 'value', "{{ ajax.content.mod_slug }}" )
220
- .appendTo( $oForm );
221
-
222
- if ( jQuery( 'p.wizard-response', $oForm ).length === 0 ) {
223
- $oForm.append( '<p class="wizard-response alert"></p>' )
224
- }
225
-
226
- var $oResponseField = jQuery( 'p.wizard-response', $oForm );
227
- $oResponseField.removeClass( 'alert-danger alert-success' )
228
- .html( '...' );
229
-
230
- var $oSubmitButton = jQuery( 'button[type=submit]', $oForm );
231
-
232
- jQuery.post( '{{ ajax.content.ajaxurl }}', $oForm.serialize(),
233
- function ( oResponse ) {
234
-
235
- if ( typeof oResponse === "undefined" || typeof oResponse.data === "undefined" ) {
236
- alert( 'There was a critical failure in the request. Cannot proceed. Example causes are HTTPS misconfiguration or PHP error warnings output.' );
237
- return;
238
- }
239
-
240
- if ( oResponse.success ) {
241
- $oResponseField.removeClass( 'alert-danger' )
242
- .addClass( 'alert-success' );
243
- }
244
- else {
245
- $oResponseField.removeClass( 'alert-success' )
246
- .addClass( 'alert-danger' );
247
- }
248
-
249
- var bRerender = false;
250
- var sMessage = 'Unknown Error';
251
- if ( undefined !== oResponse.data ) {
252
-
253
- if ( undefined !== oResponse.data.rerender && oResponse.data.rerender === true ) {
254
- bRerender = true;
255
- }
256
- sMessage = oResponse.data.message;
257
- }
258
- $oResponseField.html( sMessage );
259
-
260
- if ( bRerender ) {
261
- reRenderCurrent();
262
- }
263
- else if ( oResponse.success ) {
264
- renderNextAuto( true );
265
- }
266
-
267
- jQuery( $oForm ).trigger( 'icwpWizardFormSubmit', oResponse );
268
- }
269
- ).always(
270
- function () {
271
- bRequestCurrentlyRunning = false;
272
- }
273
- );
274
- }
275
-
276
- })( jQuery );
277
-
278
- </script>
279
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/common/base.twig DELETED
@@ -1,61 +0,0 @@
1
- {% import '/common/macros.twig' as icwp_macros %}
2
- <div class="wizard-slide">
3
- <div class="slide-header">
4
- {% block slide_header %}
5
- {% block slide_header_nav %}
6
- <div class="container-fluid">
7
- {% if data.mod_wizards.welcome is not defined %}
8
- <div class="row">
9
- <div class="col-6">
10
- {% block slide_header_previous_top %}
11
- <button class="btn btn-outline-secondary btn-block ButtonPreviousSlide">&larr; Previous Step </button>
12
- {% endblock %}
13
- </div>
14
- <div class="col-6">
15
- {% block slide_header_next_top %}
16
- <button class="ButtonNextSlide">Next Step &rarr;</button>
17
- {% endblock %}
18
- </div>
19
- </div>
20
- {% endif %}
21
- </div>
22
- {% endblock %}
23
- {% endblock %}
24
- </div>
25
- <div class="slide-body">
26
- {% block slide_body %}
27
- {% block slide_body_top %}{% endblock %}
28
- {% block slide_body_middle %}{% endblock %}
29
- {% block slide_body_bottom %}{% endblock %}
30
- {% endblock %}
31
- </div>
32
- <div class="slide-footer">
33
- {% block slide_footer %}
34
- <hr />
35
- <div class="row">
36
- <div class="col">
37
- <p class="text-center mt-5">
38
- <a href="{{ hrefs.dashboard }}" class="text-dark" style="text-decoration: none">
39
- <span class="dashicons dashicons-exit" style="vertical-align: middle; width: 16px; height: 21px"></span>
40
- Exit Wizard</a></p>
41
- </div>
42
- </div>
43
-
44
- {% if data.mod_wizards.welcome is not defined %}
45
- <div class="row">
46
- <div class="col-6">
47
- {% block slide_header_previous_bottom %}
48
- <button class="btn btn-outline-secondary btn-block ButtonPreviousSlide">&larr; Previous Step </button>
49
- {% endblock %}
50
- </div>
51
- <div class="col-6">
52
- {% block slide_header_next_top_bottom %}
53
- <button class="btn btn-info btn-block ButtonNextSlide">Next Step &rarr;</button>
54
- {% endblock %}
55
- </div>
56
- </div>
57
- {% endif %}
58
-
59
- {% endblock %}
60
- </div>
61
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/common/base_finish.twig DELETED
@@ -1,50 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_header_next_top %}{% endblock %}
4
-
5
- {% block slide_body_middle %}
6
-
7
- {{ icwp_macros.slideTitle( 'Next Steps?' ) }}
8
-
9
- {% if data.mod_wizards_count > 1 %}
10
- <h5>All Wizards In This Module</h5>
11
- <ul>
12
- {% for wizard in data.mod_wizards %}
13
- <li><a href="{{ wizard.url }}">{{ wizard.title }}</a></li>
14
- {% endfor %}
15
- </ul>
16
- {% endif %}
17
-
18
- {% block slide_body_middle_gopro %}
19
- {% if not flags.is_premium %}
20
- <h5>Go Further With Pro :)</h5>
21
- <p class="description">We've added many advantages to the Pro version, and we've made it available for every budget
22
- for just $1/month - the most affordable Security plugin available today!</p>
23
- <p class="description">With your support, we'll continue our work and bring you ever-more powerful security features.</p>
24
- <p class="description">This is what you get for going Pro:</p>
25
- <ul>
26
- <li>Simple (+automatic) options import/export between all your websites</li>
27
- <li>Vulnerability Scanner - daily scans/alerts for security vulnerabilities</li>
28
- <li>Exclusive customer support</li>
29
- <li>3rd-Party Plugin integration including WooCommerce, BuddyPress etc.</li>
30
- <li>Unlimited audit trail</li>
31
- <li>Invisible Google reCAPTCHA</li>
32
- <li>Customize visitor messages</li>
33
- <li>(coming soon) Mobile Push Notifications</li>
34
- <li>(coming soon) White Labelling</li>
35
- <li>(coming soon) Refined options for 2-Factor Authentication</li>
36
- </ul>
37
- <a href="{{ hrefs.gopro }}" target="_blank" class="btn btn-success shield-go-pro">Go Pro Today!</a>
38
- {% endif %}
39
- {% endblock %}
40
-
41
- {% endblock %}
42
-
43
- {% block slide_body_bottom %}
44
- <a href="{{ hrefs.dashboard }}" class="btn btn-primary btn-block button button-primary">Return To The {{ strings.plugin_name }} WordPress Dashboard &rarr;</a>
45
- {% endblock %}
46
-
47
- {% block slide_footer %}
48
- {% endblock %}
49
-
50
- {% block slide_header_next_bottom %}{% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/common/base_start.twig DELETED
@@ -1,4 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_header_previous_top %}{% endblock %}
4
- {% block slide_header_previous_bottom %}{% endblock %}
 
 
 
 
templates/twig/wizard/slides/common/no_access.twig DELETED
@@ -1,15 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_header_nav %}{% endblock %}
4
-
5
- {% block slide_body %}
6
- {{ icwp_macros.slideTitle( "Sorry, you don't have access" ) }}
7
-
8
- <p class="description">To run this wizard you need to have certain privileges that are not met by your current account level.</p>
9
- <p class="description">If this doesn't seem right, please contact your site administrator.</p>
10
-
11
- <a href="{{ hrefs.dashboard }}" class="btn btn-outline-secondary">Go Back To {{ strings.plugin_name }} Dashboard</a>
12
-
13
- {% endblock %}
14
-
15
- {% block slide_footer %}{% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/common/security_admin_verify.twig DELETED
@@ -1,19 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Security Admin Verification' ) }}
5
-
6
- <p class="description">Since you have previously turned-on the Security Admin system, we just need you to verify access before proceeding.</p>
7
-
8
- <form class="form-horizontal icwp-wizard-form">
9
- {{ icwp_macros.formInput_Hidden( 'current_index', current_index ) }}
10
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'security_admin_verify' ) }}
11
- {{ icwp_macros.formInput_Password( 'sec_admin_key', '', 'Security PIN' ) }}
12
- {{ icwp_macros.formInput_Submit( 'Submit Key' ) }}
13
- </form>
14
-
15
- {% endblock %}
16
- {% block slide_header %}
17
- {% endblock %}
18
- {% block slide_footer %}
19
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/importexport/finished.twig DELETED
@@ -1,6 +0,0 @@
1
- {% extends 'wizard/slides/common/base_finish.twig' %}
2
-
3
- {% block slide_body_top %}
4
- {{ icwp_macros.slideTitle( 'Finished: Shield Options Import Wizard' ) }}
5
- <p>This is the end of the Shield Security Network/Import Wizard.</p>
6
- {% endblock %}
 
 
 
 
 
 
templates/twig/wizard/slides/importexport/import.twig DELETED
@@ -1,80 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Build Your Shield Security Network' ) }}
5
-
6
- {% if flags.is_premium %}
7
- <p>To setup this site quickly you may import the options directly from another site.</p>
8
- <p>You will need the WordPress homepage URL, and the Shield Secret Key from the source <em>Master</em>
9
- WordPress site. This key renews itself every hour so you may need to recheck its current value
10
- before proceeding.</p>
11
-
12
- <h4>Import Options</h4>
13
- <p><strong>Warning</strong>: If successful, all options on this site will be overwritten by
14
- those from the source.</p>
15
- <form class="form-horizontal icwp-wizard-form">
16
- <input name="wizard-step" value="import" type="hidden" />
17
-
18
- <div class="">
19
- <label class="col-md-4 control-label" for="MasterSiteUrl">Master Site URL</label>
20
- <div class="col-md-8">
21
- <input type="url" class="form-control"
22
- name="MasterSiteUrl" id="MasterSiteUrl" placeholder="http://www....">
23
- <span id="helpBlock"
24
- class="help-block">Remember to include <code>http://</code> or <code>https://</code>.</span>
25
- </div>
26
- </div>
27
-
28
- <div class="">
29
- <label class="col-md-4 control-label" for="MasterSiteSecretKey">Master Site Secret Key</label>
30
- <div class="col-md-8">
31
- <input type="text" class="form-control" maxlength="40" minlength="40" autocomplete="off"
32
- name="MasterSiteSecretKey" id="MasterSiteSecretKey" placeholder="Secret Key">
33
- <span id="helpBlock" class="help-block">
34
- The secret key can be found under<br />
35
- Shield Security > Dashboard > Import/Export > Secret Key</span>
36
- </div>
37
- </div>
38
-
39
- <div class="">
40
- <label class="col-md-4 control-label" for="ShieldNetworkCheck">Create Shield Network</label>
41
- <div class="col-md-8">
42
- <label for="ShieldNetworkCheck">
43
- <input type="checkbox" value="Y" name="ShieldNetworkCheck" id="ShieldNetworkCheck">
44
- Check to turn on link (optional)
45
- </label>
46
- <span id="helpBlock" class="help-block">
47
- Checking this option will link this site to Master site above, such that it will
48
- automatically import options from the Master site each night. You then update the options
49
- in the master site and they will be reflected in all your linked child sites (such as this one).
50
- </span>
51
- </div>
52
- </div>
53
-
54
- <div class="">
55
- <div class="col-md-offset-4 col-md-8">
56
- <button type="submit" class="btn btn-primary">Run Import Options</button>
57
- </div>
58
- </div>
59
-
60
- </form>
61
- {% else %}
62
- <h5>Automatic Options Import/Export</h5>
63
- <p>With Shield Pro you have the ability to quickly import options directly from any remote site that's
64
- running Shield Pro.</p>
65
- <p>Not only that, you can setup Shield to automatically (each day) import options from that site. This means
66
- you can create what we call a "Master options site". This is where you set your child sties to
67
- automatically copy the options from your master site - so you only need to manually update 1 site.</p>
68
- <p>You can <a href="{{ hrefs.blog_importexport }}" target="_blank">learn a bit more about this here</a>.</p>
69
- <p><img src="{{ imgs.shieldnetworkmini }}" class="img-responsive media-left" />
70
- This goes far beyond normal import/export features and you start creating your own adaptive
71
- <strong>Shield Security Network</strong>, with no extra work on your part.</p>
72
- <p>Options import is just the beginning of what you'll be able to achieve with your Shield Network.</p>
73
- <p>For now though, if you're not a Pro subscriber, you can just skip this
74
- part and setup the plugin manually as normal.
75
- Or, you can purchase <a href="{{ hrefs.gopro }}" target="_blank">Shield Pro for your sites ($1/month)</a>
76
- and return to this wizard (or launch the Import Wizard) at any time.</p>
77
- <div class="clearfix"></div>
78
- {% endif %}
79
-
80
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/importexport/start.twig DELETED
@@ -1,29 +0,0 @@
1
- {% extends 'wizard/slides/common/base_start.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Welcome To Shield Options Import Wizard' ) }}
5
-
6
- <p>Shield options import is a powerful feature that can drastically reduce the time you need to spend managing
7
- your sites.</p>
8
- <p>You can, of course, simply use this as an ad-hoc import tool, but much more powerful is to create a
9
- <strong>Shield Network</strong>.</p>
10
- <h4>What about simple options import?</h4>
11
- <p>This is easily done. Move to the next step and enter the information for the site you want
12
- to export from i.e. its URL and its secret key. Options will then be imported directly into this site.</p>
13
- <p>If you want to keep your site options "synced" with the export site, read on...</p>
14
- <h4>What is a Shield Network?</h4>
15
- <p>A Shield Network is where all your Shield Security sites are connected to a Master Site, from which they will
16
- derive their configuration. If you change settings on the Master Site, these will get propagated to the child sites.</p>
17
- <p>In the following screen, if you select the checkbox to enable Master-Child syncing, then this site will
18
- periodically (once a day) import settings from the Master site, overwriting any existing configuration here.</p>
19
- <p>Currently this is limited to options configuration, but over time we will increase the scope to include
20
- IP address blocking and white lists. But you will have full control over this when the time comes.</p>
21
- <p>A couple of points to note:</p>
22
- <ul>
23
- <li>The site from which you import (Master) must be running Shield Pro.</li>
24
- <li>All options on this site will be overwritten to align with that of the Master site.</li>
25
- <li>If you select to create the network, this site's URL will be added to the sync white list of the Master
26
- site, to allow for automated syncing.</li>
27
- </ul>
28
- <p>Right, let's get to it. Click 'Next Step' above to start your import.
29
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ptg/config.twig DELETED
@@ -1,26 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Turn On Plugin and Theme Guard Scanner' ) }}
5
-
6
- <p>It looks like the Plugin and Theme Guard scanner isn't set to run yet.</p>
7
- <p>You can adjust this using the settings below.</p>
8
-
9
- <form class="form-horizontal icwp-wizard-form">
10
-
11
- {% set radiovalues =
12
- {
13
- 'enabled': '<span>Scan and Report</span> - scan and email report (<em>recommended</em>)',
14
- 'disabled': '<span>Disabled</span> - do not scan.'
15
- } %}
16
- {{ icwp_macros.formInput_Radio( 'enable_scan', radiovalues, 'Enable Automatic Scanning' ) }}
17
-
18
- <span id="helpBlock" class="help-block">
19
- Be sure that when you're enabling this scan that you are satisfied that all active plugins
20
- and themes are in pristine condition, free from hacks or corruption.
21
- </span>
22
-
23
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'ptgconfig' ) }}
24
- {{ icwp_macros.formInput_Submit( 'Set Automatic Scan' ) }}
25
- </form>
26
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ptg/finished.twig DELETED
@@ -1,7 +0,0 @@
1
- {% extends 'wizard/slides/common/base_finish.twig' %}
2
-
3
- {% block slide_body_top %}
4
- {{ icwp_macros.slideTitle( 'Finished: Plugin & Theme Guard' ) }}
5
-
6
- <p>This is the end of Shield Security's Plugin & Theme Guard Scanner Wizard.</p>
7
- {% endblock %}
 
 
 
 
 
 
 
templates/twig/wizard/slides/ptg/scanresult_base.twig DELETED
@@ -1,121 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( data.context_sing~' Guard Scan Results' ) }}
5
-
6
- {% if data.result|length == 0 %}
7
- <div class="alert alert-success" role="alert">
8
- There were no files discovered that need your attention.
9
- </div>
10
- {% else %}
11
- <div class="alert alert-warning" role="alert">
12
- {{ data.result|length }} {{ data.context_sing }}(s) that need your attention.
13
- </div>
14
-
15
- <div id="accord{{ data.context_sing }}" class="scan-results-accordian">
16
- {% set resultCounter = 0 %}
17
- {% for item_name,item_res in data.result %}
18
- {% set resultCounter = resultCounter + 1 %}
19
- {% set isInstalled = item_res.flags.is_installed %}
20
-
21
- <div class="card">
22
- <div class="card-header {% if isInstalled %}bg-secondary{% else %}bg-danger{% endif %}">
23
- <h5 class="mb-0">
24
- <button class="btn btn-link btn-block text-start collapsed"
25
- data-bs-toggle="collapse" data-target="#coll{{ data.context~resultCounter }}">
26
- {{ data.context_sing }}: {{ item_name }}
27
- {% if not isInstalled %}
28
- [Warning - Appears To Be Missing]
29
- {% endif %}
30
- </button>
31
- </h5>
32
- </div>
33
-
34
- <div id="coll{{ data.context~resultCounter }}" class="collapse"
35
- data-parent="#accord{{ data.context_sing }}">
36
- <div class="card-body">
37
- {% if item_res.different is defined %}
38
- <div class="indent_slight">
39
- <h6>Modified Files: {{ item_res.different|length }}</h6>
40
- {% for file in item_res.different %}
41
- <li><code class="filepath">{{ file }}</code></li>
42
- {% endfor %}
43
- </div>
44
- {% endif %}
45
-
46
- {% if item_res.missing is defined %}
47
- <div class="indent_slight">
48
- <h6>Missing Files: {{ item_res.missing|length }}</h6>
49
- {% for file in item_res.missing %}
50
- <li><code class="filepath">{{ file }}</code></li>
51
- {% endfor %}
52
- </div>
53
- {% endif %}
54
-
55
- {% if item_res.unrecognised is defined %}
56
- <div class="indent_slight">
57
- <h6>Unrecognised Files: {{ item_res.unrecognised|length }}</h6>
58
- {% for file in item_res.unrecognised %}
59
- <li><code class="filepath">{{ file }}</code></li>
60
- {% endfor %}
61
- </div>
62
- {% endif %}
63
- </div>
64
- </div>
65
- <div class="card-footer">
66
- <form class="icwp-wizard-form mb-0">
67
- <div class="clearfix">
68
- <div class="form-check form-check-inline">
69
- <input class="form-check-input"
70
- type="radio"
71
- name="ptgaction"
72
- id="ptgaction_{{ item_res.flags.id }}1"
73
- {% if item_res.flags.can_reinstall %}
74
- {% else %}
75
- disabled
76
- {% endif %}
77
- value="reinstall" />
78
- <label class="form-check-label" for="ptgaction_{{ item_res.flags.id }}1">
79
- Re-Install / Upgrade</label>
80
- </div>
81
-
82
- {% if item_res.flags.can_deactivate %}
83
- <div class="form-check form-check-inline">
84
- <input class="form-check-input"
85
- type="radio"
86
- name="ptgaction"
87
- id="ptgaction_{{ item_res.flags.id }}2"
88
- {% if item_res.flags.can_deactivate %}
89
- {% else %}
90
- disabled
91
- {% endif %}
92
- value="deactivate" >
93
- <label class="form-check-label" for="ptgaction_{{ item_res.flags.id }}2">
94
- Deactivate</label>
95
- </div>
96
- {% endif %}
97
-
98
- <div class="form-check form-check-inline">
99
- <input class="form-check-input"
100
- type="radio"
101
- name="ptgaction"
102
- id="ptgaction_{{ item_res.flags.id }}3"
103
- value="ignore" >
104
- <label class="form-check-label" for="ptgaction_{{ item_res.flags.id }}3">
105
- Ignore Changes</label>
106
- </div>
107
- <button type="submit" class="btn btn-warning mb-2 float-end">
108
- Run Selected Action</button>
109
- </div>
110
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'ptg_assetaction' ) }}
111
- {{ icwp_macros.formInput_Hidden( 'slug', item_res.flags.slug ) }}
112
- {{ icwp_macros.formInput_Hidden( 'context', data.context ) }}
113
- </form>
114
- </div>
115
- </div>
116
- {% endfor %}
117
- </div>
118
-
119
- {% endif %}
120
-
121
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ptg/scanresult_plugins.twig DELETED
@@ -1 +0,0 @@
1
- {% extends 'wizard/slides/ptg/scanresult_base.twig' %}
 
templates/twig/wizard/slides/ptg/scanresult_themes.twig DELETED
@@ -1 +0,0 @@
1
- {% extends 'wizard/slides/ptg/scanresult_base.twig' %}
 
templates/twig/wizard/slides/ptg/start.twig DELETED
@@ -1,18 +0,0 @@
1
- {% extends 'wizard/slides/common/base_start.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Start: Plugin & Theme Guard' ) }}
5
-
6
- <p>What is the Plugin & Theme Guard?</p>
7
- <p>The purpose of this scanner is to detect potentially malicious or
8
- unintended changes to plugin and theme files.</p>
9
- <p>Why is this important?</p>
10
- <p>It is common for hacks to involve modifications to existing plugin and theme files.</p>
11
- <p>This scanner will detect filesystem changes that have occurred outside normal WordPress operations, specifically:</p>
12
- <ul>
13
- <li>files where content has been modified</li>
14
- <li>files that are missing</li>
15
- <li>files that have been added</li>
16
- </ul>
17
- <p>If you're in doubt about the results, please discuss the findings with your hosting provider.</p>
18
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ufc/config.twig DELETED
@@ -1,23 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Turn On Automatic Unrecognised File Scanner' ) }}
5
-
6
- <p>It looks like the unrecognised file scanner isn't set to run automatically.</p>
7
- <p>You can adjust this setting using the form below.</p>
8
- <p>We recommend the final option - Delete & Report
9
- (automatically delete discovered files and send an email report).</p>
10
-
11
- <form class="form-horizontal icwp-wizard-form">
12
- {% set radiovalues =
13
- {
14
- 'enabled_report_only': '<span>Report Only</span> - send email reports only.',
15
- 'enabled_delete_only': "<span>Delete Only</span> - automatically delete discovered files; don't send email report.",
16
- }
17
- %}
18
- {{ icwp_macros.formInput_Radio( 'enable_scan', radiovalues, 'Enable Automatic Scanning' ) }}
19
-
20
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'ufcconfig' ) }}
21
- {{ icwp_macros.formInput_Submit( 'Set Automatic Scan' ) }}
22
- </form>
23
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ufc/exclusions.twig DELETED
@@ -1,49 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Exclude Certain Files From Scan' ) }}
5
- <p class="font-italic">(Skip to the next step to run the scan immediately.)</p>
6
- <p>There are often different types of files on a website that are legitimate but
7
- not part of the WordPress Core.</p>
8
- <p>Since Shield can't automatically know about all the files on your hosting, we give you the ability
9
- to add your own list of files to exclude from the scanner.</p>
10
- <p>In the box below, add each file name you want to ignore. If you
11
- don't know what to put in here just now, skip to the next step to run the scanner.</p>
12
- <p>Note: You can come back here and add files if the scanner picks up something
13
- that you want to ignore.</p>
14
-
15
- <form class="form-horizontal icwp-wizard-form">
16
-
17
- <div class="row">
18
- <label class="col-4 col-form-label" for="_exclusions">Excluded Files List</label>
19
- <div class="col-8">
20
- <textarea class="form-control" name="exclusions" rows="{{ data.files.count + 2 }}"
21
- placeholder="{{ data.files.list }}" id="_exclusions">{{ data.files.list }}</textarea>
22
- </div>
23
- </div>
24
- <div class="row">
25
- <div class="col-11">
26
- Take a <strong>new line</strong> for each file name.
27
- <br />Note: You may also use regular expressions.
28
- <br />Regular expressions must <strong>start and end</strong> with a "hash" character
29
- i.e. <code>#</code>
30
- <br />You must escape special characters.
31
- <br />An example: <code>#\.log#</code>
32
- <br />This will match the following files:
33
- <code>test.log</code>, <code>text.log.txt</code>, <code>.log.ini</code>
34
- </div>
35
- </div>
36
-
37
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'exclusions' ) }}
38
- {{ icwp_macros.formInput_Submit( 'Update File Exclusions' ) }}
39
- </form>
40
-
41
- <script type="text/javascript">
42
- jQuery( document ).on( 'icwpWizardFormSubmit', function ( event, oResponse ) {
43
- if ( oResponse.success ) {
44
- var $oForm = jQuery( event.target );
45
- jQuery( 'button[type=submit]', $oForm ).prop( 'disabled', false );
46
- }
47
- } );
48
- </script>
49
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ufc/finished.twig DELETED
@@ -1,6 +0,0 @@
1
- {% extends 'wizard/slides/common/base_finish.twig' %}
2
-
3
- {% block slide_body_top %}
4
- {{ icwp_macros.slideTitle( 'Finished: Unrecognised File Scanner' ) }}
5
- <p>This is the end of Shield Security's Unrecognised File Scanner Wizard.</p>
6
- {% endblock %}
 
 
 
 
 
 
templates/twig/wizard/slides/ufc/scanresult.twig DELETED
@@ -1,40 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Unrecognised File Scanner Results' ) }}
5
-
6
- {% if data.files.has %}
7
- <div class="alert alert-warning" role="alert">
8
- {{ data.files.count }} file(s) were discovered that you need to review.
9
- </div>
10
- <div class="indent_slight">
11
- <ul>
12
- {% for file in data.files.list %}
13
- <li><code class="filepath">{{ file }}</code></li>
14
- {% endfor %}
15
- </ul>
16
- </div>
17
- <p>To have the scanner delete the files listed above, use the confirmation form below.</p>
18
- <p><strong>Important</strong>: Remember it is not the job of the scanner to determine
19
- whether you need these files on your website. This is <em>your role</em>.
20
- We can only show you what's there. If you have doubts, please discuss
21
- this with your web hosting provider.
22
- </p>
23
- <form class="form-horizontal icwp-wizard-form">
24
-
25
- {{ icwp_macros.formInput_Checkbox(
26
- 'DeleteFiles', 'Y', 'Delete Detected Files', 'Check to delete the unrecognised files',
27
- "If there are files on this list that you do not want to delete, please go back
28
- a step in the wizard and add them to your exclusions list.
29
- <br />For security reasons, the scanner <strong>does not</strong>
30
- currently support individual selection of files to delete."
31
- ) }}
32
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'deletefiles' ) }}
33
- {{ icwp_macros.formInput_Submit( 'Delete Unrecognised Files' ) }}
34
- </form>
35
-
36
- {% else %}
37
- <p>There were no files discovered in the scan.</p>
38
- <p>This could be because there are none, or your exclusions list is ensuring they're ignored.</p>
39
- {% endif %}
40
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/ufc/start.twig DELETED
@@ -1,18 +0,0 @@
1
- {% extends 'wizard/slides/common/base_start.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Start Unrecognised File Scanner' ) }}
5
-
6
- <p>What is the Unrecognised File Scanner?</p>
7
- <p>Where the Core File Scanner is preoccupied with finding any official
8
- WordPress files that are corrupt, the Unrecognised File Scanner is focused on
9
- discovering all the other files on your web hosting that are not part of a
10
- standard WordPress Installation.</p>
11
- <p>Why are these files important?</p>
12
- <p>They could perfectly fine, or they could be script files that a hacker has deployed on your hosting
13
- to access your site or corrupt your WordPress installation in some way.</p>
14
- <p><strong>Important Note: this scanner cannot direct you whether you should delete or keep these files,
15
- it can only tell you that they exist. It is up to you to determine if they're okay.</strong>
16
- </p>
17
- <p>If you're in doubt, please discuss any results with your hosting provider.</p>
18
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/wcf/config.twig DELETED
@@ -1,23 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Turn On Automatic WordPress Core File Scanner' ) }}
5
-
6
- <p>It looks like the WordPress Core File scanner isn't set to run automatically.</p>
7
- <p>You can adjust this setting using the form below.</p>
8
- <p>We recommend the final option - Repair & Report
9
- (automatically restore any discovered files and send an email report).</p>
10
-
11
- <form class="form-horizontal icwp-wizard-form">
12
- {% set radiovalues =
13
- {
14
- 'enabled_report_only': '<span>Report Only</span> - send email reports only.',
15
- 'enabled_restore_report': '<span>Repair &amp; Report</span> - automatically restore any discovered files; send email report. (<em>recommended</em>)'
16
- }
17
- %}
18
- {{ icwp_macros.formInput_Radio( 'enable_scan', radiovalues, 'Enable Automatic Scanning' ) }}
19
-
20
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'wcfconfig' ) }}
21
- {{ icwp_macros.formInput_Submit( 'Set Automatic Scan' ) }}
22
- </form>
23
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/wcf/finished.twig DELETED
@@ -1,6 +0,0 @@
1
- {% extends 'wizard/slides/common/base_finish.twig' %}
2
-
3
- {% block slide_body_top %}
4
- {{ icwp_macros.slideTitle( 'Finished: Core File Scanner' ) }}
5
- <p>This is the end of Shield Security's WordPress Core File Scanner Wizard.</p>
6
- {% endblock %}
 
 
 
 
 
 
templates/twig/wizard/slides/wcf/scanresult.twig DELETED
@@ -1,56 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Core File Scanner Results' ) }}
5
-
6
- {% if data.files.has %}
7
- <div class="alert alert-warning" role="alert">
8
- {{ data.files.count }} file(s) were discovered that you need to review.
9
- </div>
10
- <div class="indent_slight">
11
- {% if data.files.checksum.has %}
12
- <h5>Modified Core Files: {{ data.files.checksum.count }}</h5>
13
- <ul>
14
- {% for file in data.files.checksum.list %}
15
- <li><code class="filepath">{{ file }}</code></li>
16
- {% endfor %}
17
- </ul>
18
- {% endif %}
19
- </div>
20
-
21
- <div class="indent_slight">
22
- {% if data.files.missing.has %}
23
- <h4>Missing Core Files: {{ data.files.missing.count }}</h4>
24
- <ul>
25
- {% for file in data.files.missing.list %}
26
- <li><code class="filepath">{{ file }}</code></li>
27
- {% endfor %}
28
- </ul>
29
- {% endif %}
30
- </div>
31
-
32
- <p>To replace the files listed above with the official versions taken
33
- directly from WordPress.org, use the confirmation form below.</p>
34
- <p><strong>Important</strong>: Remember it is not the job of the scanner to determine
35
- whether you need to replace these files on your website. This is <em>your role</em>.
36
- We can only show you what's there. If you have doubts, please discuss
37
- this with your web hosting provider or developers.
38
- </p>
39
- <form class="form-horizontal icwp-wizard-form">
40
-
41
- {{ icwp_macros.formInput_Checkbox(
42
- 'RestoreFiles', 'Y', 'Replace Modified Files', 'Check to replace all of the modified files',
43
- "If you are unsure about whether you can restore these files to official
44
- WordPress originals, please discuss the results of this scan with your
45
- web host/developer.."
46
- ) }}
47
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'restorefiles' ) }}
48
- {{ icwp_macros.formInput_Submit( 'Replace Files With Originals' ) }}
49
- </form>
50
-
51
- {% else %}
52
- <div class="alert alert-success" role="alert">
53
- Great! There were no modified files discovered in the scan.
54
- </div>
55
- {% endif %}
56
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/wcf/start.twig DELETED
@@ -1,14 +0,0 @@
1
- {% extends 'wizard/slides/common/base_start.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Start: WordPress Core File Scanner' ) }}
5
- <p>What is the WordPress Core File Scanner?</p>
6
- <p>The purpose of this scanner is to detect malicious or
7
- unintended changes to your Core WordPress files.</p>
8
- <p>Why is this important?</p>
9
- <p>Your files may already be compromised and you wouldn't know it.
10
- The only way to know if your core WordPress files
11
- have been modified is to compare them against the official files from WordPress.org.</p>
12
- <p>This scanner will do exactly that and report to you any files it finds to be different.</p>
13
- <p>If you're in doubt about the results, please discuss the findings with your hosting provider.</p>
14
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/admin_access_restriction.twig DELETED
@@ -1,35 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Security Administrators' ) }}
5
-
6
- <p class="description">Shield lets you lock down access to the <em>Shield Security plugin itself</em> using a Security Access PIN.</p>
7
-
8
- <h6 class="more_details">
9
- <a class="btn btn-link" data-bs-toggle="collapse" data-target=".more_details_body">
10
- Click For More Details &rarr;</a>
11
- </h6>
12
- <div id="MoreDetails" class="collapse more_details_body">
13
- <div class="card card-body">
14
- <p class="description">This is important because it means that only admins with the access PIN will be able to:</p>
15
- <ul>
16
- <li>View Shield Security settings</li>
17
- <li>Change Shield Security settings</li>
18
- <li>Deactivate the Shield Security plugin</li>
19
- </ul>
20
- <p class="description">It's also a great layer of security in-case someone gets unauthorized access
21
- to your WordPress admin dashboard.</p>
22
- <p class="description">To turn this option on, please supply a password below (aka 'Access PIN').</p>
23
- </div>
24
- </div>
25
-
26
- <h6>Supply A New Security Access PIN</h6>
27
- <p class="description"><strong>Warning</strong>: You must remember this key to regain access to the Shield plugin.</p>
28
- <form class="form-horizontal icwp-wizard-form">
29
- {{ icwp_macros.formInput_Password( 'sec_admin_key', '', 'Access PIN', '', 'Do not forget this key' ) }}
30
- {{ icwp_macros.formInput_Password( 'AccessKeyConfirm', '', 'Confirm PIN', 'Confirm PIN' ) }}
31
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'admin_access_restriction' ) }}
32
- {{ icwp_macros.formInput_Submit( 'Turn On Security Admin' ) }}
33
- </form>
34
-
35
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/comments_filter.twig DELETED
@@ -1,37 +0,0 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
-
3
- {% block slide_body_video_section_blurb %}
4
- <h5>Watch the quick (68s) explanatory video</h5>
5
- <p>Nearly 100% of comments SPAM is by automated BOTS.</p>
6
- <p>Shield Security provides exclusive, highly effective techniques to block BOT SPAM.
7
- <br />Unlike Akismet, we never send your private comment data to 3rd parties for processing so you
8
- stay as compliant as you need.</p>
9
- <p>The technology used to block comment SPAM is the same as that for login protection... so there's no CAPTCHAs
10
- or any other annoying extras added to your forms.</p>
11
- {% endblock %}
12
-
13
- {% block slide_body_action_area %}
14
-
15
- <form class="form-horizontal icwp-wizard-form">
16
-
17
- <div class="row">
18
- <div class="col-4">
19
- Comment SPAM Blocking
20
- </div>
21
- <div class="col-8">
22
- {{ icwp_macros.formInput_Radio_Wizard(
23
- 'CommentsFilterOption',
24
- {
25
- 'Y': '<span>Turn On</span> - Block automated comments SPAM by bots',
26
- 'N': '<span>Turn Off</span> - Do not block automated comments SPAM'
27
- },
28
- 'Comment SPAM Blocking'
29
- ) }}
30
- </div>
31
- </div>
32
-
33
- {{ icwp_macros.formInput_Submit2( 'Set Comment SPAM Protection', null, null, false ) }}
34
- {{ icwp_macros.formInput_Hidden( 'wizard-step', vars.step ) }}
35
- </form>
36
-
37
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/free_trial.twig DELETED
@@ -1,29 +0,0 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
-
3
- {% block slide_body_video_section %}
4
- {% endblock %}
5
-
6
- {% block slide_body_action_area %}
7
- <div class="row">
8
- <div class="col-8">
9
- <p>Upgrade your WordPress security to professional-grade protection to add extra features such as</p>
10
- <ul>
11
- <li>Malware scanning and repair</li>
12
- <li>Plugin/Theme file protection and repair</li>
13
- <li>User Security Policies such as Password and Auto-Suspend Idle Users</li>
14
- <li>Contact Form SPAM protection for Ninja Forms, WPForms, Gravity Forms and more</li>
15
- <li>Many, <a href="{{ hrefs.features }}" target="_blank">many more features</a></li>
16
- </ul>
17
- <p>Get the risk-free, no obligation free trial of ShieldPRO today.</p>
18
- </div>
19
- <div class="col-4">
20
- <a href="{{ hrefs.free_trial }}"
21
- class="button d-block w-100 text-center p-3"
22
- target="_blank"
23
- >
24
- {{ imgs.free_trial|raw }}
25
- Get The Free Trial!
26
- </a>
27
- </div>
28
- </div>
29
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/ip_detect.twig DELETED
@@ -1,41 +0,0 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
-
3
- {% block slide_body_video_section_blurb %}
4
- <h5>Watch the quick (68s) explanatory video</h5>
5
- <p>All webhosts are configured a bit differently.
6
- This can make it tricky to detect a visitor's IP address correctly.</p>
7
- <p>We try to do this automatically, of course, but sometimes a server
8
- configuration can be... unexpected.</p>
9
- <p>To solve this, you can tell Shield what your IP address is right now,
10
- and this will help Shield determine the best method of detecting the visitor IP going forward.</p>
11
- {% endblock %}
12
-
13
- {% block slide_body_action_area %}
14
-
15
- <form class="form-horizontal icwp-wizard-form">
16
-
17
- <div class="row">
18
- <div class="col-4">
19
- Step 1: Find <em>your</em> current IP address
20
- </div>
21
- <div class="col-8">
22
- <a href="{{ hrefs.visitor_ip }}" target="_blank">Click here</a>
23
- to open up a new page that will tell you your current IP Address.
24
- </div>
25
- </div>
26
-
27
- <div class="row">
28
- <div class="col-4">
29
- Step 2: Tell Shield your IP address
30
- </div>
31
- <div class="col-8">
32
- <input name="ip" type="text" id="ip" placeholder="123.456.789.012" class="regular-text">
33
- <br />Copy-paste the IP address from Step 1
34
- </div>
35
- </div>
36
-
37
- {{ icwp_macros.formInput_Submit2( 'Confirm My IP Address', null, null, false ) }}
38
- {{ icwp_macros.formInput_Hidden( 'wizard-step', vars.step ) }}
39
- </form>
40
-
41
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/ips.twig DELETED
@@ -1,38 +0,0 @@
1
- {% extends 'wizard/slides/common/base.twig' %}
2
-
3
- {% block slide_body %}
4
- {{ icwp_macros.slideTitle( 'Automatic IP Blacklist' ) }}
5
-
6
- <p class="description">Turn on the IP Manager below so Shield can automatically limit login attempts and block automated attacks.</p>
7
-
8
- <h6 class="more_details">
9
- <a class="btn btn-link" data-bs-toggle="collapse" data-target=".more_details_body">
10
- Click For More Details &rarr;</a>
11
- </h6>
12
- <div id="MoreDetails" class="collapse more_details_body">
13
- <div class="card card-body">
14
- <p class="description">Many security plugins offer the option of blacklisting IP addresses.
15
- But the big secret they're not telling you is that this is complete waste of your time.</p>
16
- <p class="description">Can you think of anything you'd rather be doing, than getting 100s of email notifications and then
17
- having to add 100 IP addresses to a blacklist?</p>
18
- <p class="description">Shield's automatic IP Manager will track bad behaviour, and automatically block repeat offenders.
19
- But not permanently, because that would make your IP list explode,
20
- slowing down your site for normal visitors.</p>
21
- <p class="description">By default, bad visitors are blocked for 1 minute after 10 bad requests.</p>
22
- </div>
23
- </div>
24
-
25
- <h4>Turn On Automatic Blacklist Engine</h4>
26
- <form class="form-horizontal icwp-wizard-form">
27
- {% set radiovalues =
28
- {
29
- 'Y': '<span>Turn On</span> - Automatically block bad visitors and bots',
30
- 'N': '<span>Turn Off</span> - Do not use automatic black lists to protect against bad visitors and bots'
31
- }
32
- %}
33
- {{ icwp_macros.formInput_Radio( 'IpManagerOption', radiovalues, 'Automatic IP Blacklist' ) }}
34
- {{ icwp_macros.formInput_Hidden( 'wizard-step', 'ips' ) }}
35
- {{ icwp_macros.formInput_Submit( 'Set IP Blacklist Option' ) }}
36
- </form>
37
-
38
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/thankyou.twig DELETED
@@ -1,40 +0,0 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
-
3
- {% block slide_body_video_section_blurb %}
4
- <h5>Watch the Shield Plugin Overview video:</h5>
5
- <p>Thank you for taking the time to go through the Wizard.</p>
6
- <p>By default Shield is automatically configured to protect your site from numerous threats
7
- and block bad visitors and bots without you having to do anything.</p>
8
- {% endblock %}
9
-
10
- {% block slide_body_action_area %}
11
-
12
- <div class="row">
13
- <div class="col">
14
- <p>Here are just some of the ways Shield is protecting your site automatically:</p>
15
- <ul>
16
- <li>Powerful <strong>Firewall</strong> is intercepting and blocking malicious traffic.</li>
17
- <li>Always <strong>watching for bots</strong> and maintaining a reputation score for each visitor.</li>
18
- <li><strong>Scanning</strong> your core WordPress files and directories for changes and new files.</li>
19
- <li>Automatically <strong>blocking</strong> malicious visitors by IP (so you don't have to maintain an IP list yourself).</li>
20
- <li>Protecting against the #1 source of <strong>Comment SPAM</strong>.</li>
21
- <li>Keeping a log of <em>everything</em> significant in your <strong>Audit Trail</strong>.</li>
22
- <li>Protecting your <strong>important user forms</strong> such as Login, Registration and Lost Password.</li>
23
- </ul>
24
- </div>
25
- </div>
26
-
27
-
28
- <div class="row row-cols-1 justify-content-center mt-5">
29
- <div class="col">
30
- <a href="{{ hrefs.dashboard }}" class="button button-primary py-2 px-4">
31
- {{ strings.next_button|default('Go To Shield Overview') }} &rarr;
32
- </a>
33
- </div>
34
- </div>
35
-
36
-
37
- {% endblock %}
38
-
39
- {% block slide_body_button_area_next %}{% endblock %}
40
- {% block slide_footer %}{% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/slides/welcome/welcome.twig DELETED
@@ -1,21 +0,0 @@
1
- {% extends '/wizard/slides/welcome/base.twig' %}
2
-
3
- {% block slide_header %}
4
- <div class="row row-cols-1 justify-content-center">
5
- <div class="col-6 col-sm-6 col-xl-4">
6
- <img id="ShieldLogo" class="img-fluid" src="{{ imgs.plugin_banner }}" alt="ShieldLogo" />
7
- </div>
8
- </div>
9
- {% endblock %}
10
-
11
- {% block slide_body_video_section_blurb %}
12
- <h5>Watch the Introduction video to get started</h5>
13
- <p>If this is your first time installing Shield, please use this Welcome Wizard to
14
- help you get started.</p>
15
- <p>Shield Security does a lot, and has a lot of options.</p>
16
- <p>We encourage you to watch the videos at each stage to familiarise yourself with
17
- the details of settings you're changing.</p>
18
- {% endblock %}
19
-
20
- {% block slide_body_button_area_previous %}
21
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/snippets/wizard_landing.twig DELETED
@@ -1,28 +0,0 @@
1
- <div class="row">
2
- <div class="col-6 offset-3 col-sm-8 offset-sm-2 col-lg-6 offset-lg-3">
3
- <p class="description">This module comes with {{ data.mod_wizards_count }} Wizard(s).</p>
4
- <p class="description">Please click the link below of the Guided Wizard you'd like to launch.</p>
5
- </div>
6
- </div>
7
- {% for wizard in data.mod_wizards %}
8
- <div class="row">
9
- <div class="col-8 offset-2">
10
- <div class="wizard_slot">
11
- <div><h5>{{ wizard.title }}</h5></div>
12
- <div>
13
- <p class="description">{{ wizard.desc }}</p>
14
- {% if wizard.has_premium %}
15
- <p class="description">{{ strings.premium_note }}</p>
16
- {% endif %}
17
- </div>
18
- <div>
19
- {% if wizard.available %}
20
- <a class="btn btn-info" href="{{ wizard.url }}" target="_blank">Launch Wizard</a>
21
- {% else %}
22
- <button class="btn btn-outline-dark" disabled>Not Available</button>
23
- {% endif %}
24
- </div>
25
- </div>
26
- </div>
27
- </div>
28
- {% endfor %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wizard/wizard_container.twig DELETED
@@ -1,285 +0,0 @@
1
- {% block body_content %}
2
- <div class="container-fluid">
3
- {% block body_content_header %}
4
- <div class="row">
5
- <div class="col-4 offset-4"></div>
6
- </div>
7
- {% endblock %}
8
-
9
- {% block body_content_main %}
10
- <div class="row row-cols-1 justify-content-center">
11
- <div class="col-12">
12
- <div id="wizard"></div>
13
- </div>
14
- </div>
15
- {% endblock %}
16
-
17
- {% block body_content_footer %}
18
- <div class="row">
19
- <div class="col-4 offset-4"></div>
20
- </div>
21
- {% endblock %}
22
- </div>
23
- {% endblock %}
24
-
25
- {% block body_footer_scripts %}
26
- <script type="text/javascript">
27
-
28
- var bRequestCurrentlyRunning = false;
29
-
30
- // bring everything inside this IIFE so that they are aware of each other
31
- (function ( $ ) {
32
- $( document ).ready( function () {
33
- initializeSteps();
34
- initializeHandlers();
35
- } );
36
-
37
- function initializeSteps() {
38
- var settings = {
39
- /* Appearance */
40
- headerTag: "h1",
41
- bodyTag: "div",
42
- contentContainerTag: "div",
43
- actionContainerTag: "div",
44
- stepsContainerTag: "div",
45
- cssClass: "wizard",
46
- stepsOrientation: $.fn.steps.stepsOrientation.horizontal,
47
-
48
- /* Templates */
49
- titleTemplate: '<div class="step"><span class="shield-progress-bar"></span><div class="step-number"></div><div class="step-title">#title#</div></div>',
50
- loadingTemplate: '<span class="spinner"></span> #text#',
51
-
52
- /* Behaviour */
53
- autoFocus: false,
54
- enableAllSteps: false,
55
- enableKeyNavigation: true,
56
- enablePagination: true,
57
- suppressPaginationOnFocus: true,
58
- enableContentCache: true,
59
- enableCancelButton: false,
60
- enableFinishButton: false,
61
- preloadContent: false,
62
- showFinishButtonAlways: false,
63
- forceMoveForward: false,
64
- saveState: false,
65
- startIndex: 0,
66
-
67
- /* Transition Effects */
68
- transitionEffect: $.fn.steps.transitionEffect.slide,
69
- transitionEffectSpeed: 100,
70
-
71
- /* Events */
72
- onStepChanging: function ( event, currentIndex, newIndex ) {
73
- return true;
74
- },
75
- onStepChanged: function ( event, currentIndex, priorIndex ) {
76
- if ( currentIndex >= priorIndex ) {
77
- return;
78
- }
79
- // have to use this workaround
80
- // instead of removing steps and then adding, which does not work with jquery.steps
81
- // remove effectively does something similar internally so let's just use it directly
82
- for ( var x = 1; x < 6; x++ ) {
83
- $( '#wizard-t-' + (currentIndex + x) ).parent( 'li' ).removeClass( 'done' ).addClass( 'disabled' );
84
- }
85
- },
86
- onCanceled: function ( event ) {
87
- },
88
- onFinishing: function ( event, currentIndex ) {
89
- return true;
90
- },
91
- onFinished: function ( event, currentIndex ) {
92
- },
93
-
94
- /* Labels */
95
- labels: {
96
- cancel: "Cancel",
97
- current: "current step:",
98
- pagination: "Pagination",
99
- finish: "Finish",
100
- next: "Next",
101
- previous: "Previous",
102
- loading: "Loading ..."
103
- }
104
- };
105
-
106
- // Initialize wizard
107
- var $oWizardContainer = $( '#wizard' );
108
- var $oWizard = $oWizardContainer.steps( settings );
109
- addOtherSteps( $oWizard );
110
-
111
- var $oActions = $( 'div.actions', $oWizard );
112
- $oActions.prependTo( $oWizardContainer );
113
- $oActions.css( 'display', 'none' );
114
- }
115
-
116
- function addOtherSteps( $oWizard ) {
117
- // load all steps for showing progress bar
118
- var currentStep = {{ data.wizard_first_step|raw }};
119
- var otherSteps = {{ data.wizard_step_names|raw }};
120
- otherSteps.forEach( function ( step, index ) {
121
- if ( step === currentStep.title ) {
122
- $oWizard.steps( 'add', {{ data.wizard_first_step|raw }} );
123
- return;
124
- }
125
- $oWizard.steps( 'add', { title: step, contentMode: 'async' } );
126
- } );
127
- }
128
-
129
- function initializeHandlers() {
130
- $( document ).on( 'submit', 'form.icwp-wizard-form', submitWizardForm );
131
- $( document ).on( 'click', 'div.wizard-slide button.ButtonNextSlide', renderNext );
132
- $( document ).on( 'click', 'div.wizard-slide button.ButtonSlidePrevious', renderPrevious );
133
- }
134
-
135
- function reRenderCurrent() {
136
- var $oWizard = $( '#wizard' );
137
- $oWizard.steps( 'previous' );
138
- var nCurrent = $oWizard.steps( 'getCurrentIndex' );
139
- renderNextAuto( true );
140
- };
141
-
142
- function renderPrevious( event ) {
143
- var $oWizard = $( '#wizard' );
144
- $oWizard.steps( 'previous' );
145
- };
146
-
147
- function renderNext( event ) {
148
- event.preventDefault();
149
- renderNextAuto();
150
- };
151
-
152
- function renderNextAuto( overlay = false ) {
153
- if ( overlay ) {
154
- toggleOverlay( 'show' );
155
- }
156
-
157
- var aWizardSteps = {{ data.wizard_steps|raw }};
158
- var sWizardSlug = '{{ data.wizard_slug }}';
159
-
160
- var $oWizard = $( '#wizard' );
161
- var reqData = {{ ajax.steps_as_json|raw }};
162
- reqData.current_index = $oWizard.steps( 'getCurrentIndex' );
163
- reqData.wizard_steps = aWizardSteps;
164
- reqData.wizard_slug = sWizardSlug;
165
-
166
- $.post( '{{ ajax.steps.ajaxurl }}', reqData,
167
- function ( oResponse ) {
168
- if ( typeof oResponse === "undefined" || typeof oResponse.data === "undefined" ) {
169
- alert( 'There was a critical failure in the request. Cannot proceed. Example causes are HTTPS misconfiguration or PHP error warnings output.' );
170
- return;
171
- }
172
-
173
- if ( undefined !== oResponse.data.next_step ) {
174
- var removeIndex = $oWizard.steps( 'getCurrentIndex' ) + 1;
175
- $oWizard.steps( 'remove', removeIndex );
176
- $oWizard.steps( 'insert', removeIndex, oResponse.data.next_step );
177
- $oWizard.steps( 'next' );
178
- }
179
- }
180
- ).always(
181
- function () {
182
- if ( overlay ) {
183
- toggleOverlay( 'hide' );
184
- }
185
- }
186
- );
187
- };
188
-
189
- function toggleOverlay( showOrHide ) {
190
- if ( showOrHide === 'show' ) {
191
- iCWP_WPSF_BodyOverlay.show();
192
- $( 'body' ).addClass( 'wait' );
193
- }
194
- else {
195
- iCWP_WPSF_BodyOverlay.hide();
196
- $( 'body' ).removeClass( 'wait' );
197
- }
198
- }
199
-
200
- function submitWizardForm( event ) {
201
- event.preventDefault();
202
-
203
- var $oThis = jQuery( event.currentTarget );
204
- var $oForm = $oThis.closest( 'form' );
205
-
206
- sendFormRequest( $oForm );
207
- }
208
-
209
- function sendFormRequest( $oForm ) {
210
- if ( bRequestCurrentlyRunning ) {
211
- return false;
212
- }
213
- bRequestCurrentlyRunning = true;
214
-
215
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'action' )
216
- .attr( 'value', "{{ ajax.content.action }}" )
217
- .appendTo( $oForm );
218
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'exec' )
219
- .attr( 'value', "{{ ajax.content.exec }}" )
220
- .appendTo( $oForm );
221
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'exec_nonce' )
222
- .attr( 'value', "{{ ajax.content.exec_nonce }}" )
223
- .appendTo( $oForm );
224
- jQuery( '<input />' ).attr( 'type', 'hidden' ).attr( 'name', 'mod_slug' )
225
- .attr( 'value', "{{ ajax.content.mod_slug }}" )
226
- .appendTo( $oForm );
227
-
228
- if ( jQuery( 'p.wizard-response', $oForm ).length === 0 ) {
229
- $oForm.append( '<p class="wizard-response alert"></p>' )
230
- }
231
-
232
- var $oResponseField = jQuery( 'p.wizard-response', $oForm );
233
- $oResponseField.removeClass( 'alert-danger alert-success' )
234
- .html( '...' );
235
-
236
- var $oSubmitButton = jQuery( 'button[type=submit]', $oForm );
237
-
238
- jQuery.post( '{{ ajax.content.ajaxurl }}', $oForm.serialize(),
239
- function ( oResponse ) {
240
-
241
- if ( typeof oResponse === "undefined" || typeof oResponse.data === "undefined" ) {
242
- alert( 'There was a critical failure in the request. Cannot proceed. Example causes are HTTPS misconfiguration or PHP error warnings output.' );
243
- return;
244
- }
245
-
246
- if ( oResponse.success ) {
247
- $oResponseField.removeClass( 'alert-danger' )
248
- .addClass( 'alert-success' );
249
- }
250
- else {
251
- $oResponseField.removeClass( 'alert-success' )
252
- .addClass( 'alert-danger' );
253
- }
254
-
255
- var bRerender = false;
256
- var sMessage = 'Unknown Error';
257
- if ( undefined !== oResponse.data ) {
258
-
259
- if ( undefined !== oResponse.data.rerender && oResponse.data.rerender === true ) {
260
- bRerender = true;
261
- }
262
- sMessage = oResponse.data.message;
263
- }
264
- $oResponseField.html( sMessage );
265
-
266
- if ( bRerender ) {
267
- reRenderCurrent();
268
- }
269
- else if ( oResponse.success ) {
270
- // renderNextAuto( true );
271
- }
272
-
273
- jQuery( $oForm ).trigger( 'icwpWizardFormSubmit', oResponse );
274
- }
275
- ).always(
276
- function () {
277
- bRequestCurrentlyRunning = false;
278
- }
279
- );
280
- }
281
-
282
- })( jQuery );
283
-
284
- </script>
285
- {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/twig/wpadmin_pages/insights/{wizard → default}/index.twig RENAMED
@@ -2,6 +2,6 @@
2
 
3
  {% block page_main %}
4
 
5
- {{ content.wizard|raw }}
6
 
7
  {% endblock %}
2
 
3
  {% block page_main %}
4
 
5
+ {{ content.page_main|raw }}
6
 
7
  {% endblock %}
templates/twig/wpadmin_pages/insights/overview/progress_meter/meter_card.twig ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% set meter = vars.meter %}
2
+ {% set meter_slug = vars.meter_slug %}
3
+
4
+ <div class="card d-flex flex-column progress-meter progress-meter-{{ meter_slug }} h-100
5
+ {% if meter.has_critical|default(false) %}
6
+ meter-critical
7
+ {% elseif meter.totals.percentage > 50 %}
8
+ meter-success
9
+ {% else %}
10
+ meter-warning
11
+ {% endif %}
12
+ ">
13
+
14
+ <div class="card-header">
15
+ <h6>
16
+ {{ meter.title }}
17
+ <br /><small class="text-muted">{{ meter.subtitle }}</small>
18
+ </h6>
19
+ </div>
20
+
21
+ <div class="card-body">
22
+
23
+ <div class="row g-0">
24
+ <div class="col-md-4 col-lg-5 col-xl-5 d-flex justify-content-center align-items-start">
25
+
26
+ <div class="pie d-flex align-items-center justify-content-center" data-pie='{
27
+ "number": false,
28
+ "colorCircle": "rgba( {{ meter.rgbs|join(',') }},0.08 )",
29
+ "colorSlice": "rgb( {{ meter.rgbs|join(',') }} )",
30
+ "percent": {{ meter.totals.percentage }},
31
+ "size":180
32
+ }'>
33
+ <div class="letter-score"
34
+ style="color: rgb( {{ meter.rgbs|join(',') }} )">{{ meter.totals.letter_score }}</div>
35
+ </div>
36
+
37
+ </div>
38
+
39
+ <div class="col-md-8 col-lg-7 col-xl-7 d-flex flex-column">
40
+ {% if meter.warning|default([]) is not empty %}
41
+ <div class="alert alert-danger">
42
+ {{ meter.warning.text }}
43
+ <a href="{{ meter.warning.href }}" class="alert-link" target="_blank">
44
+ {{ strings.view_details }}</a>
45
+ </div>
46
+ {% endif %}
47
+ {% for desc in meter.description %}
48
+ <p class="card-text">{{ desc }}</p>
49
+ {% endfor %}
50
+ </div>
51
+ </div>
52
+
53
+ </div>
54
+
55
+ <div class="card-footer">
56
+ <a class="btn {% if meter.has_critical|default(false) %}btn-danger{% elseif meter.totals.percentage > 50 %}btn-success{% else %}btn-warning{% endif %}"
57
+ href="javascript:{iCWP_WPSF_OffCanvas.renderMeterAnalysis('{{ meter_slug }}')}"
58
+ aria-controls="ShieldProgressMeterOffcanvas">
59
+ <span class="svg-container">{{ imgs.svgs.analysis|raw }}</span>
60
+ {{ strings.analysis }}
61
+ </a>
62
+ </div>
63
+ </div>
templates/twig/wpadmin_pages/insights/overview/progress_meter/progress_meters.twig CHANGED
@@ -1,63 +1,13 @@
1
  {# https://github.com/tomik23/circular-progress-bar #}
 
 
 
 
 
2
  <div class="row row-cols-1 row-cols-sm-1 row-cols-md-1 row-cols-lg-1 row-cols-xl-2 justify-content-start">
3
-
4
- {% for meter_slug,meter in vars.progress_meters %}
5
  <div class="col mb-4">
6
-
7
- <div class="card d-flex flex-column progress-meter h-100
8
- {% if meter.has_critical|default(false) %}
9
- border-danger
10
- {% elseif meter.totals.percentage > 50 %}
11
- border-success
12
- {% else %}
13
- border-warning
14
- {% endif %}
15
- ">
16
- <div class="row g-0">
17
- <div class="col-md-4 col-lg-5 col-xl-5 d-flex justify-content-center align-items-center py-lg-4">
18
-
19
- <div class="pie d-flex align-items-center justify-content-center" data-pie='{
20
- "number": false,
21
- "colorCircle": "rgba( {{ meter.rgbs|join(',') }},0.08 )",
22
- "colorSlice": "rgb( {{ meter.rgbs|join(',') }} )",
23
- "percent": {{ meter.totals.percentage }}
24
- }'>
25
- <div class="letter-score" style="color: rgb( {{ meter.rgbs|join(',') }} )">{{ meter.totals.letter_score }}</div>
26
- </div>
27
-
28
- </div>
29
-
30
- <div class="col-md-8 col-lg-7 col-xl-7 d-flex flex-column">
31
-
32
- <div class="card-body">
33
- <h6 class="card-title">
34
- {{ meter.title }}
35
- <br /><small class="text-muted">{{ meter.subtitle }}</small>
36
- </h6>
37
- {% if meter.warning|default([]) is not empty %}
38
- <div class="alert alert-danger">
39
- {{ meter.warning.text }}
40
- <a href="{{ meter.warning.href }}" class="alert-link" target="_blank">
41
- {{ strings.view_details }}</a>
42
- </div>
43
- {% endif %}
44
- {% for desc in meter.description %}
45
- <p class="card-text">{{ desc }}</p>
46
- {% endfor %}
47
-
48
- </div>
49
- <div class="card-footer">
50
- <a class="btn {% if meter.has_critical|default(false) %}btn-danger{% elseif meter.totals.percentage > 50 %}btn-success{% else %}btn-warning{% endif %}"
51
- href="javascript:{iCWP_WPSF_OffCanvas.renderMeterAnalysis('{{ meter_slug }}')}"
52
- aria-controls="ShieldProgressMeterOffcanvas">
53
- <span class="svg-container">{{ imgs.svgs.analysis|raw }}</span>
54
- {{ strings.analysis }}
55
- </a>
56
- </div>
57
-
58
- </div>
59
- </div>
60
- </div>
61
  </div>
62
  {% endfor %}
63
  </div>
1
  {# https://github.com/tomik23/circular-progress-bar #}
2
+ <div class="row row-cols-1 justify-content-center">
3
+ <div class="col mb-4">
4
+ {{ content.primary_meter|raw }}
5
+ </div>
6
+ </div>
7
  <div class="row row-cols-1 row-cols-sm-1 row-cols-md-1 row-cols-lg-1 row-cols-xl-2 justify-content-start">
8
+ {% for meter in content.meters %}
 
9
  <div class="col mb-4">
10
+ {{ meter|raw }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  </div>
12
  {% endfor %}
13
  </div>