Shield Security for WordPress - Version 13.0.0

Version Description

Download this release

Release Info

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

Code changes from version 12.0.13 to 13.0.0

Files changed (365) hide show
  1. cl.json +97 -0
  2. config/audit_trail.json +5 -30
  3. config/deprecated/audit_trail.php +5 -30
  4. config/deprecated/hack_protect.php +243 -183
  5. config/deprecated/ips.php +0 -44
  6. config/deprecated/traffic.php +0 -24
  7. config/hack_protect.json +243 -183
  8. config/ips.json +0 -44
  9. config/traffic.json +0 -24
  10. icwp-wpsf.php +1 -1
  11. plugin-spec.php +7 -8
  12. plugin.json +7 -8
  13. readme.txt +5 -5
  14. resources/css/plugin.css +14 -16
  15. resources/images/bootstrap/zoom-in.svg +5 -0
  16. resources/js/global-plugin.js +2 -2
  17. resources/js/plugin.js +19 -1
  18. resources/js/shield/scans.js +5 -1
  19. resources/js/shield/scantables.js +14 -8
  20. resources/js/shield/userprofile.js +3 -1
  21. src/lib/src/Controller/Admin/AdminBarMenu.php +4 -4
  22. src/lib/src/Controller/Controller.php +24 -43
  23. src/lib/src/Controller/{Utilities/DebugMode.php → Modes/BaseMode.php} +14 -9
  24. src/lib/src/Controller/Modes/DebugMode.php +8 -0
  25. src/lib/src/Controller/Modes/StagingMode.php +8 -0
  26. src/lib/src/Controller/Plugin/PluginDelete.php +6 -0
  27. src/lib/src/Crons/BaseCron.php +1 -4
  28. src/lib/src/Databases/AuditTrail/Delete.php +0 -9
  29. src/lib/src/Databases/AuditTrail/Insert.php +0 -31
  30. src/lib/src/Databases/AuditTrail/Select.php +0 -89
  31. src/lib/src/Databases/AuditTrail/Update.php +0 -17
  32. src/lib/src/Databases/Base/EntryVO.php +0 -2
  33. src/lib/src/Databases/BotSignals/Common.php +0 -40
  34. src/lib/src/Databases/BotSignals/Delete.php +0 -10
  35. src/lib/src/Databases/BotSignals/EntryVO.php +0 -69
  36. src/lib/src/Databases/BotSignals/Handler.php +0 -7
  37. src/lib/src/Databases/BotSignals/Insert.php +0 -9
  38. src/lib/src/Databases/BotSignals/Select.php +0 -11
  39. src/lib/src/Databases/BotSignals/Update.php +0 -7
  40. src/lib/src/Databases/FileLocker/Common.php +3 -3
  41. src/lib/src/Databases/Scanner/EntryVO.php +1 -2
  42. src/lib/src/Databases/Scanner/Select.php +0 -17
  43. src/lib/src/Databases/Traffic/BaseTraffic.php +0 -82
  44. src/lib/src/Databases/Traffic/Delete.php +0 -10
  45. src/lib/src/Databases/Traffic/EntryVO.php +0 -55
  46. src/lib/src/Databases/Traffic/Handler.php +0 -9
  47. src/lib/src/Databases/Traffic/Insert.php +0 -23
  48. src/lib/src/Databases/Traffic/Select.php +0 -42
  49. src/lib/src/Logging/Processors/RequestMetaProcessor.php +10 -4
  50. src/lib/src/Modules/AuditTrail/Auditors/Emails.php +39 -45
  51. src/lib/src/Modules/AuditTrail/Auditors/Plugins.php +8 -10
  52. src/lib/src/Modules/AuditTrail/Auditors/Themes.php +8 -9
  53. src/lib/src/Modules/AuditTrail/Lib/AuditLogger.php +2 -7
  54. src/lib/src/Modules/AuditTrail/Lib/AuditWriter.php +0 -72
  55. src/lib/src/Modules/AuditTrail/Lib/LogTable/LoadRawTableData.php +0 -9
  56. src/lib/src/Modules/AuditTrail/Lib/Ops/Commit.php +0 -81
  57. src/lib/src/Modules/AuditTrail/Lib/Ops/ConvertLegacy.php +0 -146
  58. src/lib/src/Modules/AuditTrail/ModCon.php +2 -26
  59. src/lib/src/Modules/AuditTrail/Options.php +0 -7
  60. src/lib/src/Modules/AuditTrail/Processor.php +0 -19
  61. src/lib/src/Modules/AuditTrail/Upgrade.php +0 -5
  62. src/lib/src/Modules/Base/ModCon.php +0 -14
  63. src/lib/src/Modules/Base/Options.php +1 -154
  64. src/lib/src/Modules/Base/Strings.php +0 -11
  65. src/lib/src/Modules/Base/WpCli/BaseWpCliCmd.php +1 -1
  66. src/lib/src/Modules/Data/ModCon.php +2 -1
  67. src/lib/src/Modules/Events/Lib/EventsListener.php +6 -7
  68. src/lib/src/Modules/Events/Lib/EventsService.php +4 -6
  69. src/lib/src/Modules/Events/Lib/StatsWriter.php +1 -6
  70. src/lib/src/Modules/Events/Strings.php +0 -61
  71. src/lib/src/Modules/Firewall/Processor.php +0 -110
  72. src/lib/src/Modules/HackGuard/AjaxHandler.php +31 -54
  73. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Common.php +18 -0
  74. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Delete.php +10 -0
  75. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Handler.php +9 -0
  76. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Insert.php +9 -0
  77. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Record.php +12 -0
  78. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Select.php +10 -0
  79. src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Update.php +10 -0
  80. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Common.php +54 -0
  81. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Delete.php +10 -0
  82. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Handler.php +12 -0
  83. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Insert.php +9 -0
  84. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Record.php +17 -0
  85. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Select.php +10 -0
  86. src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Update.php +17 -0
  87. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Common.php +26 -0
  88. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Delete.php +10 -0
  89. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Handler.php +9 -0
  90. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Insert.php +9 -0
  91. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Record.php +64 -0
  92. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Select.php +43 -0
  93. src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Update.php +17 -0
  94. src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Common.php +14 -0
  95. src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Delete.php +10 -0
  96. src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Handler.php +12 -0
  97. src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Insert.php +9 -0
  98. src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Record.php +11 -0
  99. src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Select.php +10 -0
  100. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Common.php +32 -0
  101. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Delete.php +10 -0
  102. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Handler.php +9 -0
  103. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Insert.php +9 -0
  104. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Record.php +12 -0
  105. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Select.php +20 -0
  106. src/lib/src/Modules/HackGuard/DB/Scans/Ops/Update.php +13 -0
  107. src/lib/src/Modules/HackGuard/Debug.php +14 -0
  108. src/lib/src/Modules/HackGuard/Insights/OverviewCards.php +39 -72
  109. src/lib/src/Modules/HackGuard/Lib/FileLocker/FileLockerController.php +16 -9
  110. src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/Diff.php +4 -12
  111. src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/PerformAction.php +3 -26
  112. src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/ReadOriginalFileContent.php +3 -11
  113. src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/Restore.php +3 -7
  114. src/lib/src/Modules/HackGuard/Lib/Hashes/Exceptions/AssetHashesNotFound.php +7 -0
  115. src/lib/src/Modules/HackGuard/Lib/Hashes/Exceptions/NoneAssetFileException.php +7 -0
  116. src/lib/src/Modules/HackGuard/Lib/Hashes/Exceptions/UnrecognisedAssetFile.php +7 -0
  117. src/lib/src/Modules/HackGuard/Lib/Hashes/Query.php +105 -0
  118. src/lib/src/Modules/HackGuard/Lib/Hashes/Retrieve.php +116 -0
  119. src/lib/src/Modules/HackGuard/Lib/Reports/Query/ScanCounts.php +12 -43
  120. src/lib/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php +4 -7
  121. src/lib/src/Modules/HackGuard/Lib/ScanTables/DelegateAjaxHandler.php +22 -28
  122. src/lib/src/Modules/HackGuard/Lib/ScanTables/LoadRawTableData.php +68 -74
  123. src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildHistory.php +120 -0
  124. src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildInfo.php +131 -0
  125. src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/FileContents.php +58 -0
  126. src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php +176 -0
  127. src/lib/src/Modules/HackGuard/Lib/ScanTables/RetrieveFileContents.php +0 -63
  128. src/lib/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForCrowdSource.php +3 -2
  129. src/lib/src/Modules/HackGuard/Lib/Snapshots/CrowdSourced/SubmitHashes.php +2 -1
  130. src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/ScheduleBuildAll.php +14 -9
  131. src/lib/src/Modules/HackGuard/Lib/Utility/FileDownloadHandler.php +21 -15
  132. src/lib/src/Modules/HackGuard/ModCon.php +43 -20
  133. src/lib/src/Modules/HackGuard/Options.php +48 -108
  134. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionBase.php +8 -0
  135. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionLogs.php +0 -65
  136. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionMalware.php +9 -9
  137. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionPluginThemesBase.php +3 -4
  138. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionPlugins.php +4 -4
  139. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionThemes.php +4 -4
  140. src/lib/src/Modules/HackGuard/Render/ScanResults/SectionWordpress.php +9 -9
  141. src/lib/src/Modules/HackGuard/Scan/Controller/Afs.php +248 -0
  142. src/lib/src/Modules/HackGuard/Scan/Controller/Apc.php +31 -1
  143. src/lib/src/Modules/HackGuard/Scan/Controller/Base.php +125 -119
  144. src/lib/src/Modules/HackGuard/Scan/Controller/BaseForAssets.php +34 -10
  145. src/lib/src/Modules/HackGuard/Scan/Controller/BaseForFiles.php +39 -0
  146. src/lib/src/Modules/HackGuard/Scan/Controller/Mal.php +16 -57
  147. src/lib/src/Modules/HackGuard/Scan/Controller/Ptg.php +14 -103
  148. src/lib/src/Modules/HackGuard/Scan/Controller/ScanControllerConsumer.php +3 -3
  149. src/lib/src/Modules/HackGuard/Scan/Controller/Ufc.php +8 -31
  150. src/lib/src/Modules/HackGuard/Scan/Controller/Wcf.php +23 -20
  151. src/lib/src/Modules/HackGuard/Scan/Controller/Wpv.php +40 -2
  152. src/lib/src/Modules/HackGuard/Scan/Exceptions/NoQueueItems.php +7 -0
  153. src/lib/src/Modules/HackGuard/Scan/Exceptions/ScanException.php +13 -0
  154. src/lib/src/Modules/HackGuard/Scan/Exceptions/ScanExistsException.php +10 -0
  155. src/lib/src/Modules/HackGuard/Scan/Init/CreateNewScan.php +49 -0
  156. src/lib/src/Modules/HackGuard/Scan/Init/PopulateScanItems.php +59 -0
  157. src/lib/src/Modules/HackGuard/Scan/Init/ScansStatus.php +44 -0
  158. src/lib/src/Modules/HackGuard/Scan/Init/SetScanCompleted.php +93 -0
  159. src/lib/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilder.php +23 -22
  160. src/lib/src/Modules/HackGuard/Scan/Queue/BuildScanAction.php +0 -37
  161. src/lib/src/Modules/HackGuard/Scan/Queue/CleanQueue.php +86 -0
  162. src/lib/src/Modules/HackGuard/Scan/Queue/CollateResults.php +0 -47
  163. src/lib/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php +5 -53
  164. src/lib/src/Modules/HackGuard/Scan/Queue/Controller.php +17 -66
  165. src/lib/src/Modules/HackGuard/Scan/Queue/ConvertBetweenTypes.php +0 -45
  166. src/lib/src/Modules/HackGuard/Scan/Queue/IsScanEnqueued.php +0 -20
  167. src/lib/src/Modules/HackGuard/Scan/Queue/ProcessQueueItem.php +82 -0
  168. src/lib/src/Modules/HackGuard/Scan/Queue/ProcessQueueWpcli.php +70 -0
  169. src/lib/src/Modules/HackGuard/Scan/Queue/QueueInit.php +47 -0
  170. src/lib/src/Modules/HackGuard/Scan/Queue/QueueItemVO.php +32 -0
  171. src/lib/src/Modules/HackGuard/Scan/Queue/QueueItems.php +54 -0
  172. src/lib/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php +37 -74
  173. src/lib/src/Modules/HackGuard/Scan/Queue/QueueProcessorConsumer.php +4 -5
  174. src/lib/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php +0 -47
  175. src/lib/src/Modules/HackGuard/Scan/Queue/ScanExecute.php +0 -53
  176. src/lib/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php +0 -42
  177. src/lib/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php +0 -65
  178. src/lib/src/Modules/HackGuard/Scan/Results/Counts.php +97 -0
  179. src/lib/src/Modules/HackGuard/Scan/Results/ResultsDelete.php +0 -79
  180. src/lib/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php +0 -28
  181. src/lib/src/Modules/HackGuard/Scan/Results/ResultsStore.php +0 -68
  182. src/lib/src/Modules/HackGuard/Scan/Results/ResultsUpdate.php +0 -61
  183. src/lib/src/Modules/HackGuard/Scan/Results/Retrieve.php +333 -0
  184. src/lib/src/Modules/HackGuard/Scan/Results/ScanResultVO.php +49 -0
  185. src/lib/src/Modules/HackGuard/Scan/Results/Store.php +86 -0
  186. src/lib/src/Modules/HackGuard/Scan/Results/Update.php +46 -0
  187. src/lib/src/Modules/HackGuard/Scan/ScanActionFromSlug.php +7 -13
  188. src/lib/src/Modules/HackGuard/Scan/ScansController.php +77 -24
  189. src/lib/src/Modules/HackGuard/Scan/Utilities/ConvertLegacyResults.php +201 -0
  190. src/lib/src/Modules/HackGuard/Scan/Utilities/PtgAddReinstallLinks.php +6 -17
  191. src/lib/src/Modules/HackGuard/Scan/Utilities/WpvAddPluginRows.php +20 -29
  192. src/lib/src/Modules/HackGuard/Strings.php +43 -103
  193. src/lib/src/Modules/HackGuard/UI.php +7 -21
  194. src/lib/src/Modules/HackGuard/Upgrade.php +13 -7
  195. src/lib/src/Modules/HackGuard/WpCli.php +17 -0
  196. src/lib/src/Modules/HackGuard/WpCli/ScanRun.php +68 -0
  197. src/lib/src/Modules/IPs/AjaxHandler.php +26 -0
  198. src/lib/src/Modules/IPs/Components/ProcessOffense.php +9 -1
  199. src/lib/src/Modules/IPs/Lib/IpAnalyse/BuildDisplay.php +0 -3
  200. src/lib/src/Modules/IPs/Lib/IpAnalyse/FindAllPluginIps.php +8 -2
  201. src/lib/src/Modules/IPs/Lib/OffenseTracker.php +1 -8
  202. src/lib/src/Modules/IPs/Lib/Ops/ConvertLegacy.php +0 -97
  203. src/lib/src/Modules/IPs/ModCon.php +1 -8
  204. src/lib/src/Modules/IPs/UI.php +2 -4
  205. src/lib/src/Modules/IPs/Upgrade.php +0 -13
  206. src/lib/src/Modules/Insights/Lib/SummaryCards.php +3 -5
  207. src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Yubikey.php +40 -100
  208. src/lib/src/Modules/Plugin/Lib/Debug/Collate.php +1 -1
  209. src/lib/src/Modules/Plugin/WpCli/Import.php +0 -3
  210. src/lib/src/Modules/SecurityAdmin/WpCli/Pin.php +1 -1
  211. src/lib/src/Modules/Sessions/Processor.php +0 -7
  212. src/lib/src/Modules/Traffic/Lib/Logger.php +0 -84
  213. src/lib/src/Modules/Traffic/Lib/Ops/ConvertLegacy.php +0 -88
  214. src/lib/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php +27 -22
  215. src/lib/src/Modules/Traffic/ModCon.php +2 -15
  216. src/lib/src/Modules/Traffic/Options.php +0 -7
  217. src/lib/src/Modules/Traffic/UI.php +0 -5
  218. src/lib/src/Modules/Traffic/Upgrade.php +0 -12
  219. src/lib/src/Modules/UserManagement/Strings.php +2 -2
  220. src/lib/src/Scans/Afs/BuildScanAction.php +27 -0
  221. src/lib/src/Scans/{Mal/BuildFileMap.php → Afs/BuildScanItems.php} +32 -7
  222. src/lib/src/Scans/Afs/Exceptions/MalwareFileException.php +7 -0
  223. src/lib/src/Scans/Afs/Exceptions/PluginFileChecksumFailException.php +7 -0
  224. src/lib/src/Scans/Afs/Exceptions/PluginFileUnrecognisedException.php +7 -0
  225. src/lib/src/Scans/Afs/Exceptions/RealtimeFileDiscoveredException.php +7 -0
  226. src/lib/src/Scans/Afs/Exceptions/ScanFileException.php +17 -0
  227. src/lib/src/Scans/Afs/Exceptions/ThemeFileChecksumFailException.php +7 -0
  228. src/lib/src/Scans/Afs/Exceptions/ThemeFileUnrecognisedException.php +7 -0
  229. src/lib/src/Scans/Afs/Exceptions/WpCoreFileChecksumFailException.php +7 -0
  230. src/lib/src/Scans/Afs/Exceptions/WpCoreFileMissingException.php +7 -0
  231. src/lib/src/Scans/Afs/Exceptions/WpCoreFileUnrecognisedException.php +7 -0
  232. src/lib/src/Scans/Afs/FileScanner.php +146 -0
  233. src/lib/src/Scans/{Mal/Utilities/FalsePositiveQuery.php → Afs/Processing/MalFalsePositiveQuery.php} +4 -9
  234. src/lib/src/Scans/Afs/Processing/MalFalsePositiveReporter.php +105 -0
  235. src/lib/src/Scans/Afs/Processing/MalReportCache.php +50 -0
  236. src/lib/src/Scans/Afs/Processing/MalwareFalsePositive.php +67 -0
  237. src/lib/src/Scans/Afs/ResultItem.php +92 -0
  238. src/lib/src/Scans/Afs/ResultsSet.php +43 -0
  239. src/lib/src/Scans/{Mal → Afs}/Scan.php +2 -2
  240. src/lib/src/Scans/Afs/ScanActionVO.php +21 -0
  241. src/lib/src/Scans/{Mal → Afs}/ScanFromFileMap.php +3 -5
  242. src/lib/src/Scans/Afs/Scans/BasePluginThemeFile.php +10 -0
  243. src/lib/src/Scans/Afs/Scans/BaseScan.php +45 -0
  244. src/lib/src/Scans/Afs/Scans/MalwareFile.php +73 -0
  245. src/lib/src/Scans/Afs/Scans/PluginFile.php +66 -0
  246. src/lib/src/Scans/Afs/Scans/RealtimeFile.php +26 -0
  247. src/lib/src/Scans/Afs/Scans/ThemeFile.php +65 -0
  248. src/lib/src/Scans/Afs/Scans/WpCoreFile.php +85 -0
  249. src/lib/src/Scans/Afs/Scans/WpCoreUnrecognisedFile.php +62 -0
  250. src/lib/src/Scans/Afs/Utilities/ItemActionHandler.php +34 -0
  251. src/lib/src/Scans/{Mal → Afs}/Utilities/Patterns.php +4 -6
  252. src/lib/src/Scans/Afs/Utilities/RepairItem.php +216 -0
  253. src/lib/src/Scans/Apc/BuildScanAction.php +5 -6
  254. src/lib/src/Scans/Apc/BuildScanItems.php +13 -0
  255. src/lib/src/Scans/Apc/PluginScanner.php +32 -41
  256. src/lib/src/Scans/Apc/ResultItem.php +16 -6
  257. src/lib/src/Scans/Apc/ResultsSet.php +1 -7
  258. src/lib/src/Scans/Apc/Scan.php +13 -25
  259. src/lib/src/Scans/Apc/ScanActionVO.php +3 -3
  260. src/lib/src/Scans/Apc/Utilities/ItemActionHandler.php +0 -6
  261. src/lib/src/Scans/Apc/Utilities/Repair.php +0 -20
  262. src/lib/src/Scans/Base/BaseBuildFileMap.php +6 -4
  263. src/lib/src/Scans/Base/BaseScan.php +4 -3
  264. src/lib/src/Scans/Base/BaseScanActionVO.php +0 -20
  265. src/lib/src/Scans/Base/{BaseBuildScanAction.php → BuildScanAction.php} +16 -13
  266. src/lib/src/Scans/Base/DiffResultForStorage.php +0 -42
  267. src/lib/src/Scans/Base/FileResultItem.php +1 -7
  268. src/lib/src/Scans/Base/Files/BaseFileMapScan.php +1 -0
  269. src/lib/src/Scans/Base/Files/BaseFileScanner.php +2 -5
  270. src/lib/src/Scans/Base/Files/BaseScanFromFileMap.php +11 -12
  271. src/lib/src/Scans/Base/ResultItem.php +6 -26
  272. src/lib/src/Scans/Base/ResultsSet.php +17 -58
  273. src/lib/src/Scans/Base/Utilities/BaseRepair.php +2 -8
  274. src/lib/src/Scans/Base/Utilities/BuildScanItems.php +12 -0
  275. src/lib/src/Scans/Base/Utilities/ItemActionHandler.php +52 -49
  276. src/lib/src/Scans/Base/Utilities/ItemActionHandlerAssets.php +1 -1
  277. src/lib/src/Scans/Base/Utilities/ItemDeleteHandler.php +62 -0
  278. src/lib/src/Scans/Base/Utilities/{IgnoreItem.php → ItemIgnoreHandler.php} +6 -9
  279. src/lib/src/Scans/Base/Utilities/ItemRepairHandler.php +59 -0
  280. src/lib/src/Scans/Base/Utilities/RepairItemBase.php +24 -0
  281. src/lib/src/Scans/Common/Exceptions/ItemMayBeExcludedException.php +7 -0
  282. src/lib/src/Scans/Helpers/WpCoreFile.php +9 -13
  283. src/lib/src/Scans/Mal/BuildScanAction.php +0 -23
  284. src/lib/src/Scans/Mal/FileScanner.php +0 -225
  285. src/lib/src/Scans/Mal/ResultItem.php +0 -18
  286. src/lib/src/Scans/Mal/ResultsSet.php +0 -27
  287. src/lib/src/Scans/Mal/ScanActionVO.php +3 -1
  288. src/lib/src/Scans/Mal/Utilities/FalsePositiveReporter.php +0 -130
  289. src/lib/src/Scans/Mal/Utilities/ItemActionHandler.php +0 -39
  290. src/lib/src/Scans/Mal/Utilities/Repair.php +0 -204
  291. src/lib/src/Scans/Ptg/BuildFileMap.php +0 -65
  292. src/lib/src/Scans/Ptg/BuildScanAction.php +0 -28
  293. src/lib/src/Scans/Ptg/FileScanner.php +0 -225
  294. src/lib/src/Scans/Ptg/ResultItem.php +0 -16
  295. src/lib/src/Scans/Ptg/ResultsSet.php +0 -258
  296. src/lib/src/Scans/Ptg/Scan.php +0 -17
  297. src/lib/src/Scans/Ptg/ScanActionVO.php +3 -4
  298. src/lib/src/Scans/Ptg/ScanFromFileMap.php +0 -29
  299. src/lib/src/Scans/Ptg/Utilities/ItemActionHandler.php +0 -116
  300. src/lib/src/Scans/Ptg/Utilities/Repair.php +0 -82
  301. src/lib/src/Scans/Ufc/BuildFileMap.php +0 -52
  302. src/lib/src/Scans/Ufc/BuildScanAction.php +0 -32
  303. src/lib/src/Scans/Ufc/FileScanner.php +0 -58
  304. src/lib/src/Scans/Ufc/ResultItem.php +0 -7
  305. src/lib/src/Scans/Ufc/ResultsSet.php +0 -39
  306. src/lib/src/Scans/Ufc/Scan.php +0 -17
  307. src/lib/src/Scans/Ufc/ScanActionVO.php +3 -4
  308. src/lib/src/Scans/Ufc/ScanFromFileMap.php +0 -21
  309. src/lib/src/Scans/Ufc/Utilities/ItemActionHandler.php +0 -24
  310. src/lib/src/Scans/Ufc/Utilities/Repair.php +0 -45
  311. src/lib/src/Scans/Wcf/BuildFileMap.php +0 -35
  312. src/lib/src/Scans/Wcf/BuildScanAction.php +0 -27
  313. src/lib/src/Scans/Wcf/FileScanner.php +0 -76
  314. src/lib/src/Scans/Wcf/ResultItem.php +0 -17
  315. src/lib/src/Scans/Wcf/ResultsSet.php +0 -94
  316. src/lib/src/Scans/Wcf/Scan.php +0 -17
  317. src/lib/src/Scans/Wcf/ScanActionVO.php +3 -1
  318. src/lib/src/Scans/Wcf/ScanFromFileMap.php +0 -21
  319. src/lib/src/Scans/Wcf/Utilities/ItemActionHandler.php +0 -24
  320. src/lib/src/Scans/Wcf/Utilities/Repair.php +0 -31
  321. src/lib/src/Scans/Wpv/BuildScanAction.php +6 -19
  322. src/lib/src/Scans/Wpv/BuildScanItems.php +18 -0
  323. src/lib/src/Scans/Wpv/ResultItem.php +2 -11
  324. src/lib/src/Scans/Wpv/ResultsSet.php +8 -93
  325. src/lib/src/Scans/Wpv/Scan.php +24 -48
  326. src/lib/src/Scans/Wpv/ScanActionVO.php +3 -5
  327. src/lib/src/Scans/Wpv/Utilities/ItemActionHandler.php +0 -6
  328. src/lib/src/Scans/Wpv/Utilities/Repair.php +0 -47
  329. src/lib/src/Scans/Wpv/WpVulnDb/VulnVO.php +0 -2
  330. src/lib/src/ShieldNetApi/FileLocker/DecryptFile.php +3 -5
  331. src/lib/src/Tables/Build/AuditTrail.php +0 -149
  332. src/lib/src/Tables/DataTables/Build/Scans/BaseForScan.php +3 -3
  333. src/lib/src/Tables/DataTables/Build/Scans/ForMalware.php +4 -4
  334. src/lib/src/Tables/Render/WpListTable/AuditTrail.php +0 -50
  335. src/lib/src/Tables/Render/WpListTable/Traffic.php +0 -18
  336. src/lib/src/Utilities/CacheDir.php +3 -0
  337. src/lib/vendor/composer/autoload_classmap.php +111 -85
  338. src/lib/vendor/composer/autoload_static.php +111 -85
  339. src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Select.php +1 -1
  340. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/CoreFileHashes.php +3 -7
  341. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/BackgroundProcessing/BackgroundProcess.php +28 -33
  342. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Base/RepoBase.php +75 -75
  343. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Cp/Repo.php +76 -76
  344. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Plugin/Repo.php +65 -65
  345. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Theme/Files.php +122 -122
  346. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Theme/Repo.php +58 -58
  347. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Wp/Repo.php +71 -71
  348. templates/twig/admin/user/profile/mfa/mfa_yubi.twig +1 -1
  349. templates/twig/snippets/plugin_vulnerability.twig +4 -21
  350. templates/twig/wpadmin_pages/components/page/nav_sidebar.twig +2 -2
  351. templates/twig/wpadmin_pages/insights/ips/ip_analyse/index.twig +2 -1
  352. templates/twig/wpadmin_pages/insights/ips/ips_black.twig +1 -1
  353. templates/twig/wpadmin_pages/insights/ips/ips_white.twig +1 -1
  354. templates/twig/wpadmin_pages/insights/license/license.twig +12 -1
  355. templates/twig/wpadmin_pages/insights/reports/charts_custom.twig +1 -1
  356. templates/twig/wpadmin_pages/insights/scans/modal/base_modal_content.twig +23 -0
  357. templates/twig/wpadmin_pages/insights/scans/modal/code_render.twig +1 -1
  358. templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view.twig +21 -0
  359. templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/item_history.twig +16 -0
  360. templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/item_info.twig +16 -0
  361. templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/modal_content.twig +16 -0
  362. templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/tabpanel.twig +73 -0
  363. templates/twig/wpadmin_pages/insights/scans/modal/shield_modal_container.twig +11 -0
  364. templates/twig/wpadmin_pages/insights/scans/results/index.twig +1 -1
  365. templates/twig/wpadmin_pages/insights/scans/run/scan_areas.twig +7 -70
cl.json CHANGED
@@ -1,4 +1,101 @@
1
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  "12.0": {
3
  "version": "12.0",
4
  "released_at": 1631783098,
1
  {
2
+ "13.0": {
3
+ "version": "13.0",
4
+ "released_at": 1636970660,
5
+ "hrefs": {
6
+ "release": "https://shsec.io/shieldrelease130",
7
+ "upgrade": "https://shsec.io/shieldupgradeguide130"
8
+ },
9
+ "title": "Scanning Engine Overhaul",
10
+ "description": [
11
+ ],
12
+ "items": [
13
+ {
14
+ "type": "new",
15
+ "pro_only": false,
16
+ "title": "Complete Scanning Engine Overhaul",
17
+ "description": [
18
+ "We've completely rewritten the scanning engine to be faster and more intuitive.",
19
+ "Includes improvements to reduce cases where results are reported and then are no longer visible."
20
+ ]
21
+ },
22
+ {
23
+ "type": "new",
24
+ "pro_only": true,
25
+ "title": "Scans can now be executed using WP-CLI",
26
+ "description": [
27
+ "Audit Trail now uses our preferred table UI with built-in, useful search and filter controls.",
28
+ "There's also rapid and reliable pagination and data reloading."
29
+ ]
30
+ },
31
+ {
32
+ "type": "improved",
33
+ "pro_only": false,
34
+ "title": "Support for WP-CLI based cron execution",
35
+ "description": [
36
+ "Running WP Crons using WP-CLI is full supports automatic scans."
37
+ ]
38
+ },
39
+ {
40
+ "type": "improved",
41
+ "pro_only": false,
42
+ "title": "Scan Results Management",
43
+ "description": [
44
+ "Scan results management is improved with historical scan results display and more descriptive messaging."
45
+ ]
46
+ },
47
+ {
48
+ "type": "improved",
49
+ "pro_only": false,
50
+ "title": "Scan Result Diffs",
51
+ "description": [
52
+ "Wherever possible scan results will allow you to view a file diff showing any and all file changes clearly.",
53
+ "This is available only for official WordPress core files and plugins/themes hosted on WordPress.org."
54
+ ]
55
+ },
56
+ {
57
+ "type": "improved",
58
+ "pro_only": false,
59
+ "title": "Simplified Scan Options",
60
+ "description": [
61
+ "Hugely simplified and reduced the configuration options available for scans."
62
+ ]
63
+ },
64
+ {
65
+ "type": "improved",
66
+ "pro_only": false,
67
+ "title": "Dynamic Search For IP Analyse Tool",
68
+ "description": [
69
+ "IP Analyse tool use AJAX-based dynamic searching when selecting an IP address on the IP Analyse tool.",
70
+ "This makes the tool more practical and performant for sites with large IP datasets."
71
+ ]
72
+ },
73
+ {
74
+ "type": "improved",
75
+ "pro_only": false,
76
+ "title": "Traffic Logging for WP-CLI requests",
77
+ "description": [
78
+ "WP-CLI commands and their arguments are logged for WP-CLI requests just as with paths for web requests."
79
+ ]
80
+ },
81
+ {
82
+ "type": "improved",
83
+ "pro_only": false,
84
+ "title": "Yubikey Device Verification",
85
+ "description": [
86
+ "Yubikey One-Time Passwords are now verified when attempting to register a Yubikey device to your profile."
87
+ ]
88
+ },
89
+ {
90
+ "type": "fixed",
91
+ "pro_only": false,
92
+ "title": "Adding/Removing Yubikey Device Reliability",
93
+ "description": [
94
+ "Adding and removing Yubikey devices to and from your WP user profile is more reliable."
95
+ ]
96
+ }
97
+ ]
98
+ },
99
  "12.0": {
100
  "version": "12.0",
101
  "released_at": 1631783098,
config/audit_trail.json CHANGED
@@ -191,21 +191,14 @@
191
  "name": "File Logging Level",
192
  "summary": "Logging Level For File-Based Logs",
193
  "description": "Logging Level For File-Based Logs"
194
- },
195
- {
196
- "key": "legacy_db_deleted_at",
197
- "section": "section_non_ui",
198
- "transferable": false,
199
- "type": "integer",
200
- "default": ""
201
  }
202
  ],
203
  "definitions": {
204
- "db_handler_classes": {
205
  "at_logs": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Logs\\Ops\\Handler",
206
  "at_meta": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Meta\\Ops\\Handler"
207
  },
208
- "db_table_at_logs": {
209
  "slug": "at_logs",
210
  "has_updated_at": true,
211
  "has_created_at": true,
@@ -228,7 +221,7 @@
228
  }
229
  }
230
  },
231
- "db_table_at_meta": {
232
  "slug": "at_meta",
233
  "has_updated_at": false,
234
  "has_created_at": false,
@@ -252,26 +245,8 @@
252
  }
253
  }
254
  },
255
- "db_classes": {
256
- "audit_trail": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Handler"
257
- },
258
- "db_table_audit_trail": {
259
- "slug": "audit_trail",
260
- "has_updated_at": true,
261
- "cols_custom": {
262
- "rid": "varchar(10) NOT NULL DEFAULT '' COMMENT 'Request ID'",
263
- "ip": "varchar(40) NOT NULL DEFAULT 0 COMMENT 'Visitor IP Address'",
264
- "wp_username": "varchar(255) NOT NULL DEFAULT '-' COMMENT 'WP User'",
265
- "context": "varchar(32) NOT NULL DEFAULT 'none' COMMENT 'Audit Context'",
266
- "event": "varchar(50) NOT NULL DEFAULT 'none' COMMENT 'Specific Audit Event'",
267
- "category": "int(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Severity'",
268
- "meta": "text COMMENT 'Audit Event Data'",
269
- "count": "SMALLINT(5) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Repeat Count'"
270
- }
271
- },
272
- "max_free_days": 7,
273
- "audit_trail_table_name": "audit_trail",
274
- "events": {
275
  "plugin_activated": {
276
  "audit_params": [
277
  "plugin"
191
  "name": "File Logging Level",
192
  "summary": "Logging Level For File-Based Logs",
193
  "description": "Logging Level For File-Based Logs"
 
 
 
 
 
 
 
194
  }
195
  ],
196
  "definitions": {
197
+ "db_handler_classes": {
198
  "at_logs": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Logs\\Ops\\Handler",
199
  "at_meta": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Meta\\Ops\\Handler"
200
  },
201
+ "db_table_at_logs": {
202
  "slug": "at_logs",
203
  "has_updated_at": true,
204
  "has_created_at": true,
221
  }
222
  }
223
  },
224
+ "db_table_at_meta": {
225
  "slug": "at_meta",
226
  "has_updated_at": false,
227
  "has_created_at": false,
245
  }
246
  }
247
  },
248
+ "max_free_days": 7,
249
+ "events": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  "plugin_activated": {
251
  "audit_params": [
252
  "plugin"
config/deprecated/audit_trail.php CHANGED
@@ -191,21 +191,14 @@
191
  "name": "File Logging Level",
192
  "summary": "Logging Level For File-Based Logs",
193
  "description": "Logging Level For File-Based Logs"
194
- },
195
- {
196
- "key": "legacy_db_deleted_at",
197
- "section": "section_non_ui",
198
- "transferable": false,
199
- "type": "integer",
200
- "default": ""
201
  }
202
  ],
203
  "definitions": {
204
- "db_handler_classes": {
205
  "at_logs": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Logs\\Ops\\Handler",
206
  "at_meta": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Meta\\Ops\\Handler"
207
  },
208
- "db_table_at_logs": {
209
  "slug": "at_logs",
210
  "has_updated_at": true,
211
  "has_created_at": true,
@@ -228,7 +221,7 @@
228
  }
229
  }
230
  },
231
- "db_table_at_meta": {
232
  "slug": "at_meta",
233
  "has_updated_at": false,
234
  "has_created_at": false,
@@ -252,26 +245,8 @@
252
  }
253
  }
254
  },
255
- "db_classes": {
256
- "audit_trail": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Handler"
257
- },
258
- "db_table_audit_trail": {
259
- "slug": "audit_trail",
260
- "has_updated_at": true,
261
- "cols_custom": {
262
- "rid": "varchar(10) NOT NULL DEFAULT '' COMMENT 'Request ID'",
263
- "ip": "varchar(40) NOT NULL DEFAULT 0 COMMENT 'Visitor IP Address'",
264
- "wp_username": "varchar(255) NOT NULL DEFAULT '-' COMMENT 'WP User'",
265
- "context": "varchar(32) NOT NULL DEFAULT 'none' COMMENT 'Audit Context'",
266
- "event": "varchar(50) NOT NULL DEFAULT 'none' COMMENT 'Specific Audit Event'",
267
- "category": "int(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Severity'",
268
- "meta": "text COMMENT 'Audit Event Data'",
269
- "count": "SMALLINT(5) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Repeat Count'"
270
- }
271
- },
272
- "max_free_days": 7,
273
- "audit_trail_table_name": "audit_trail",
274
- "events": {
275
  "plugin_activated": {
276
  "audit_params": [
277
  "plugin"
191
  "name": "File Logging Level",
192
  "summary": "Logging Level For File-Based Logs",
193
  "description": "Logging Level For File-Based Logs"
 
 
 
 
 
 
 
194
  }
195
  ],
196
  "definitions": {
197
+ "db_handler_classes": {
198
  "at_logs": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Logs\\Ops\\Handler",
199
  "at_meta": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\DB\\Meta\\Ops\\Handler"
200
  },
201
+ "db_table_at_logs": {
202
  "slug": "at_logs",
203
  "has_updated_at": true,
204
  "has_created_at": true,
221
  }
222
  }
223
  },
224
+ "db_table_at_meta": {
225
  "slug": "at_meta",
226
  "has_updated_at": false,
227
  "has_created_at": false,
245
  }
246
  }
247
  },
248
+ "max_free_days": 7,
249
+ "events": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  "plugin_activated": {
251
  "audit_params": [
252
  "plugin"
config/deprecated/hack_protect.php CHANGED
@@ -66,16 +66,6 @@
66
  "Recommendation - Keep The Realtime Change Detection Active."
67
  ]
68
  },
69
- {
70
- "slug": "section_scan_ufc",
71
- "title": "Unrecognised Files Scanner",
72
- "title_short": "Unrecognised Files Scanner",
73
- "beacon_id": 395,
74
- "summary": [
75
- "Purpose - Scan your WordPress core folders for unrecognised files that don't belong.",
76
- "Recommendation - Keep the Unrecognised Files Scanner feature turned on."
77
- ]
78
- },
79
  {
80
  "slug": "section_scan_options",
81
  "title": "Scan Options",
@@ -114,6 +104,85 @@
114
  "summary": "Enable (or Disable) The Hack Guard Module",
115
  "description": "Un-Checking this option will completely disable the Hack Guard module"
116
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  {
118
  "key": "enabled_scan_apc",
119
  "section": "section_scan_wpv",
@@ -151,44 +220,6 @@
151
  "summary": "Apply Updates Automatically To Vulnerable Plugins",
152
  "description": "When an update becomes available, automatically apply updates to items with known vulnerabilities."
153
  },
154
- {
155
- "key": "enable_core_file_integrity_scan",
156
- "section": "section_file_guard",
157
- "default": "Y",
158
- "type": "checkbox",
159
- "link_info": "https://shsec.io/hd",
160
- "link_blog": "https://shsec.io/wpsf37",
161
- "beacon_id": 224,
162
- "name": "WP Core File Scanner",
163
- "summary": "Automatically Scans WordPress Core Files For Alterations",
164
- "description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
165
- },
166
- {
167
- "key": "mal_scan_enable",
168
- "section": "section_file_guard",
169
- "premium": true,
170
- "default": "Y",
171
- "type": "checkbox",
172
- "link_info": "https://shsec.io/fp",
173
- "link_blog": "https://shsec.io/fx",
174
- "beacon_id": 222,
175
- "name": "Automatic Malware Scan",
176
- "summary": "Enable Malware File Scanner",
177
- "description": "When enabled the Malware scanner will run automatically."
178
- },
179
- {
180
- "key": "ptg_enable",
181
- "section": "section_file_guard",
182
- "premium": true,
183
- "default": "Y",
184
- "type": "checkbox",
185
- "link_info": "https://shsec.io/bl",
186
- "link_blog": "https://shsec.io/bm",
187
- "beacon_id": 133,
188
- "name": "Enable/Disable Guard",
189
- "summary": "Enable The Guard For Plugin And Theme Files",
190
- "description": "When enabled the Guard will automatically scan for changes to your Plugin and Theme files."
191
- },
192
  {
193
  "key": "file_locker",
194
  "section": "section_realtime",
@@ -220,35 +251,6 @@
220
  "summary": "Lock Files Against Tampering and Changes",
221
  "description": "As soon as changes are detected to any selected files, the contents may be examined and reverted."
222
  },
223
- {
224
- "key": "file_repair_areas",
225
- "section": "section_file_guard",
226
- "type": "multiple_select",
227
- "default": [
228
- "wp",
229
- "plugin"
230
- ],
231
- "value_options": [
232
- {
233
- "value_key": "wp",
234
- "text": "WP Core"
235
- },
236
- {
237
- "value_key": "plugin",
238
- "text": "Plugin Files"
239
- },
240
- {
241
- "value_key": "theme",
242
- "text": "Theme Files"
243
- }
244
- ],
245
- "link_info": "https://shsec.io/wpsf36",
246
- "link_blog": "https://shsec.io/wpsf37",
247
- "beacon_id": 228,
248
- "name": "Auto File Repair",
249
- "summary": "Which Files Should Be Automatically Repaired?",
250
- "description": "When a file is modified, or malware is detected, Shield can try to repair files."
251
- },
252
  {
253
  "key": "scan_frequency",
254
  "section": "section_scan_options",
@@ -296,70 +298,6 @@
296
  "summary": "Number Of Times To Automatically Scan Core Files In 24 Hours",
297
  "description": "Default: Once every 24hrs. To improve security, increase the number of scans per day."
298
  },
299
- {
300
- "key": "enable_unrecognised_file_cleaner_scan",
301
- "section": "section_scan_ufc",
302
- "default": "enabled_report_only",
303
- "type": "select",
304
- "value_options": [
305
- {
306
- "value_key": "disabled",
307
- "text": "Automatic Scan Disabled"
308
- },
309
- {
310
- "value_key": "enabled_report_only",
311
- "text": "Scan Enabled - Report Only"
312
- },
313
- {
314
- "value_key": "enabled_delete_only",
315
- "text": "Scan Enabled - Automatically Delete Files"
316
- }
317
- ],
318
- "link_info": "https://shsec.io/9y",
319
- "link_blog": "https://shsec.io/95",
320
- "beacon_id": 227,
321
- "name": "Unrecognised Files Scanner",
322
- "summary": "Scans Core Directories For Unrecognised Files",
323
- "description": "Scans for, and automatically deletes, any files in your core WordPress folders that are not part of your WordPress installation."
324
- },
325
- {
326
- "key": "ufc_scan_uploads",
327
- "section": "section_scan_ufc",
328
- "advanced": true,
329
- "default": "N",
330
- "type": "checkbox",
331
- "link_info": "https://shsec.io/he",
332
- "link_blog": "https://shsec.io/95",
333
- "beacon_id": 347,
334
- "name": "Scan Uploads",
335
- "summary": "Scan Uploads Folder For PHP and Javascript",
336
- "description": "The Uploads folder is primarily for media, but could be used to store nefarious files."
337
- },
338
- {
339
- "key": "ufc_exclusions",
340
- "section": "section_scan_ufc",
341
- "advanced": true,
342
- "default": [
343
- "error_log",
344
- "php_error_log",
345
- ".htaccess",
346
- ".htpasswd",
347
- ".user.ini",
348
- "php.ini",
349
- "web.config",
350
- "php_mail.log",
351
- "mail.log",
352
- "wp-content/uploads/bb-plugin/cache/",
353
- "wp-content/uploads/cache/wpml/twig/"
354
- ],
355
- "type": "array",
356
- "link_info": "https://shsec.io/9z",
357
- "link_blog": "https://shsec.io/95",
358
- "beacon_id": 231,
359
- "name": "File Exclusions",
360
- "summary": "Provide A List Of Files To Be Excluded From The Scan",
361
- "description": "Take a new line for each file you wish to exclude from the scan. No commas are necessary."
362
- },
363
  {
364
  "key": "mal_autorepair_surgical",
365
  "section": "section_non_ui",
@@ -385,44 +323,6 @@
385
  "summary": "Show Re-Install Links For Plugins",
386
  "description": "Show links to re-install plugins and offer re-install when activating plugins."
387
  },
388
- {
389
- "key": "auto_filter_results",
390
- "section": "section_scan_options",
391
- "premium": false,
392
- "type": "checkbox",
393
- "default": "Y",
394
- "link_info": "",
395
- "link_blog": "",
396
- "beacon_id": 439,
397
- "name": "Auto-Filter Results",
398
- "summary": "Automatically Filter Results Of Irrelevant Items",
399
- "description": "Automatically remove items from results that are irrelevant."
400
- },
401
- {
402
- "key": "scan_path_exclusions",
403
- "section": "section_scan_options",
404
- "advanced": true,
405
- "premium": true,
406
- "default": [
407
- "wp-content/cache/",
408
- "wp-content/nfwlog/",
409
- "wp-content/wflogs/",
410
- "*/error_log",
411
- "*/php_error_log",
412
- "*/mail.log",
413
- "*/php_mail.log",
414
- "*/.stylelintrc-css.json",
415
- "*/.stylelintrc.json",
416
- "*/sucuri-*.php"
417
- ],
418
- "type": "array",
419
- "link_info": "",
420
- "link_blog": "",
421
- "beacon_id": 441,
422
- "name": "Scan Exclusions",
423
- "summary": "Scan File and Folder Exclusions",
424
- "description": "Scan File and Folder Exclusions."
425
- },
426
  {
427
  "key": "scans_to_build",
428
  "section": "section_non_ui",
@@ -454,16 +354,29 @@
454
  "tracking_exclude": true,
455
  "type": "array",
456
  "default": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  }
458
  ],
459
  "definitions": {
460
  "all_scan_slugs": [
461
  "apc",
462
- "mal",
463
- "ptg",
464
  "wpv",
465
- "wcf",
466
- "ufc"
467
  ],
468
  "file_scan_extensions": [
469
  "php",
@@ -478,6 +391,153 @@
478
  "twig",
479
  "hbs"
480
  ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  "db_classes": {
482
  "filelocker": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\FileLocker\\Handler",
483
  "scanner": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Scanner\\Handler",
66
  "Recommendation - Keep The Realtime Change Detection Active."
67
  ]
68
  },
 
 
 
 
 
 
 
 
 
 
69
  {
70
  "slug": "section_scan_options",
71
  "title": "Scan Options",
104
  "summary": "Enable (or Disable) The Hack Guard Module",
105
  "description": "Un-Checking this option will completely disable the Hack Guard module"
106
  },
107
+ {
108
+ "key": "enable_core_file_integrity_scan",
109
+ "section": "section_file_guard",
110
+ "default": "Y",
111
+ "type": "checkbox",
112
+ "link_info": "https://shsec.io/hd",
113
+ "link_blog": "https://shsec.io/wpsf37",
114
+ "beacon_id": 224,
115
+ "name": "WP Core File Scanner",
116
+ "summary": "Automatically Scans WordPress Core Files For Alterations",
117
+ "description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
118
+ },
119
+ {
120
+ "key": "file_repair_areas",
121
+ "section": "section_file_guard",
122
+ "type": "multiple_select",
123
+ "default": [
124
+ "wp",
125
+ "plugin"
126
+ ],
127
+ "value_options": [
128
+ {
129
+ "value_key": "wp",
130
+ "text": "WP Core"
131
+ },
132
+ {
133
+ "value_key": "plugin",
134
+ "text": "Plugin Files"
135
+ },
136
+ {
137
+ "value_key": "theme",
138
+ "text": "Theme Files"
139
+ }
140
+ ],
141
+ "link_info": "https://shsec.io/wpsf36",
142
+ "link_blog": "https://shsec.io/wpsf37",
143
+ "beacon_id": 228,
144
+ "name": "Auto File Repair",
145
+ "summary": "Which Files Should Be Automatically Repaired?",
146
+ "description": "When a file is modified, or malware is detected, Shield can try to repair files."
147
+ },
148
+ {
149
+ "key": "auto_filter_results",
150
+ "section": "section_file_guard",
151
+ "premium": false,
152
+ "type": "checkbox",
153
+ "default": "Y",
154
+ "link_info": "",
155
+ "link_blog": "",
156
+ "beacon_id": 439,
157
+ "name": "Auto-Filter Results",
158
+ "summary": "Automatically Filter Results Of Irrelevant Items",
159
+ "description": "Automatically remove items from results that are irrelevant."
160
+ },
161
+ {
162
+ "key": "scan_path_exclusions",
163
+ "section": "section_file_guard",
164
+ "advanced": true,
165
+ "premium": true,
166
+ "default": [
167
+ "wp-content/cache/",
168
+ "wp-content/nfwlog/",
169
+ "wp-content/wflogs/",
170
+ "*/error_log",
171
+ "*/php_error_log",
172
+ "*/mail.log",
173
+ "*/php_mail.log",
174
+ "*/.stylelintrc-css.json",
175
+ "*/.stylelintrc.json",
176
+ "*/sucuri-*.php"
177
+ ],
178
+ "type": "array",
179
+ "link_info": "",
180
+ "link_blog": "",
181
+ "beacon_id": 441,
182
+ "name": "Scan Exclusions",
183
+ "summary": "Scan File and Folder Exclusions",
184
+ "description": "Scan File and Folder Exclusions."
185
+ },
186
  {
187
  "key": "enabled_scan_apc",
188
  "section": "section_scan_wpv",
220
  "summary": "Apply Updates Automatically To Vulnerable Plugins",
221
  "description": "When an update becomes available, automatically apply updates to items with known vulnerabilities."
222
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  {
224
  "key": "file_locker",
225
  "section": "section_realtime",
251
  "summary": "Lock Files Against Tampering and Changes",
252
  "description": "As soon as changes are detected to any selected files, the contents may be examined and reverted."
253
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  {
255
  "key": "scan_frequency",
256
  "section": "section_scan_options",
298
  "summary": "Number Of Times To Automatically Scan Core Files In 24 Hours",
299
  "description": "Default: Once every 24hrs. To improve security, increase the number of scans per day."
300
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  {
302
  "key": "mal_autorepair_surgical",
303
  "section": "section_non_ui",
323
  "summary": "Show Re-Install Links For Plugins",
324
  "description": "Show links to re-install plugins and offer re-install when activating plugins."
325
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  {
327
  "key": "scans_to_build",
328
  "section": "section_non_ui",
354
  "tracking_exclude": true,
355
  "type": "array",
356
  "default": []
357
+ },
358
+ {
359
+ "key": "realtime_scan_last_at",
360
+ "section": "section_non_ui",
361
+ "transferable": false,
362
+ "tracking_exclude": true,
363
+ "type": "integer",
364
+ "default": 0
365
+ },
366
+ {
367
+ "key": "legacy_db_conversion_at",
368
+ "section": "section_non_ui",
369
+ "transferable": false,
370
+ "tracking_exclude": true,
371
+ "type": "integer",
372
+ "default": 0
373
  }
374
  ],
375
  "definitions": {
376
  "all_scan_slugs": [
377
  "apc",
 
 
378
  "wpv",
379
+ "afs"
 
380
  ],
381
  "file_scan_extensions": [
382
  "php",
391
  "twig",
392
  "hbs"
393
  ],
394
+ "db_handler_classes": {
395
+ "scans": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Handler",
396
+ "scanitems": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Handler",
397
+ "resultitems": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Handler",
398
+ "resultitem_meta": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Handler",
399
+ "scanresults": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Handler"
400
+ },
401
+ "db_table_scans": {
402
+ "autoexpire": 0,
403
+ "slug": "scans",
404
+ "col_older_than": "created_at",
405
+ "has_updated_at": false,
406
+ "cols_custom": {
407
+ "scan": {
408
+ "macro_type": "char",
409
+ "length": 3,
410
+ "comment": "Scan Slug"
411
+ },
412
+ "ready_at": {
413
+ "macro_type": "timestamp",
414
+ "comment": "Scan Ready At"
415
+ },
416
+ "finished_at": {
417
+ "macro_type": "timestamp",
418
+ "comment": "Scan Completed At"
419
+ },
420
+ "meta": {
421
+ "macro_type": "meta",
422
+ "comment": "Scan Meta Info"
423
+ }
424
+ }
425
+ },
426
+ "db_table_scanitems": {
427
+ "autoexpire": 0,
428
+ "slug": "scanitems",
429
+ "has_updated_at": false,
430
+ "has_created_at": false,
431
+ "has_deleted_at": false,
432
+ "col_older_than": "started_at",
433
+ "cols_custom": {
434
+ "scan_ref": {
435
+ "macro_type": "foreign_key_id",
436
+ "foreign_key": {
437
+ "ref_table": "icwp_wpsf_scans"
438
+ }
439
+ },
440
+ "items": {
441
+ "macro_type": "text",
442
+ "comment": "Array of scan items"
443
+ },
444
+ "started_at": {
445
+ "macro_type": "timestamp",
446
+ "comment": "Started Scanning Items At"
447
+ },
448
+ "finished_at": {
449
+ "macro_type": "timestamp",
450
+ "comment": "Finished Scanning Items At"
451
+ }
452
+ }
453
+ },
454
+ "db_table_resultitems": {
455
+ "autoexpire": 0,
456
+ "slug": "resultitems",
457
+ "has_updated_at": true,
458
+ "col_older_than": "updated_at",
459
+ "cols_custom": {
460
+ "item_type": {
461
+ "macro_type": "char",
462
+ "length": 1,
463
+ "comment": "Result Item Type"
464
+ },
465
+ "item_id": {
466
+ "macro_type": "varchar",
467
+ "length": 256,
468
+ "comment": "Result Item ID"
469
+ },
470
+ "ignored_at": {
471
+ "macro_type": "timestamp",
472
+ "comment": "Result Ignored"
473
+ },
474
+ "notified_at": {
475
+ "macro_type": "timestamp",
476
+ "comment": "Result Notification Sent"
477
+ },
478
+ "auto_filtered_at": {
479
+ "macro_type": "timestamp",
480
+ "comment": "Result Auto Filtered"
481
+ },
482
+ "attempt_repair_at": {
483
+ "macro_type": "timestamp",
484
+ "comment": "Attempted Repair At"
485
+ },
486
+ "item_repaired_at": {
487
+ "macro_type": "timestamp",
488
+ "comment": "Item Repaired At"
489
+ },
490
+ "item_deleted_at": {
491
+ "macro_type": "timestamp",
492
+ "comment": "Item Deleted At"
493
+ }
494
+ }
495
+ },
496
+ "db_table_resultitem_meta": {
497
+ "slug": "resultitem_meta",
498
+ "has_updated_at": false,
499
+ "has_created_at": false,
500
+ "has_deleted_at": false,
501
+ "cols_custom": {
502
+ "ri_ref": {
503
+ "macro_type": "foreign_key_id",
504
+ "foreign_key": {
505
+ "ref_table": "icwp_wpsf_resultitems"
506
+ },
507
+ "comment": "Reference to primary Result Item record"
508
+ },
509
+ "meta_key": {
510
+ "macro_type": "varchar",
511
+ "length": 32,
512
+ "comment": "Meta Key"
513
+ },
514
+ "meta_value": {
515
+ "macro_type": "text",
516
+ "comment": "Meta Data"
517
+ }
518
+ }
519
+ },
520
+ "db_table_scanresults": {
521
+ "autoexpire": 0,
522
+ "slug": "scanresults",
523
+ "has_updated_at": false,
524
+ "has_created_at": true,
525
+ "has_deleted_at": false,
526
+ "cols_custom": {
527
+ "scan_ref": {
528
+ "macro_type": "foreign_key_id",
529
+ "foreign_key": {
530
+ "ref_table": "icwp_wpsf_scans"
531
+ }
532
+ },
533
+ "resultitem_ref": {
534
+ "macro_type": "foreign_key_id",
535
+ "foreign_key": {
536
+ "ref_table": "icwp_wpsf_resultitems"
537
+ }
538
+ }
539
+ }
540
+ },
541
  "db_classes": {
542
  "filelocker": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\FileLocker\\Handler",
543
  "scanner": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Scanner\\Handler",
config/deprecated/ips.php CHANGED
@@ -582,13 +582,6 @@
582
  "transferable": false,
583
  "type": "array",
584
  "default": []
585
- },
586
- {
587
- "key": "legacy_db_deleted_at",
588
- "section": "section_non_ui",
589
- "transferable": false,
590
- "type": "integer",
591
- "default": ""
592
  }
593
  ],
594
  "definitions": {
@@ -722,7 +715,6 @@
722
  }
723
  },
724
  "db_classes": {
725
- "botsignals": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Handler",
726
  "ip_lists": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\IPs\\Handler"
727
  },
728
  "ip_lists_table_name": "ip_lists",
@@ -741,42 +733,6 @@
741
  "blocked_at": "IP Blocked"
742
  }
743
  },
744
- "db_table_botsignals": {
745
- "autoexpire": 3,
746
- "slug": "botsignals",
747
- "col_older_than": "updated_at",
748
- "has_updated_at": true,
749
- "cols_custom": {
750
- "ip": "varbinary(16) DEFAULT NULL COMMENT 'IP Address'"
751
- },
752
- "cols_timestamps": {
753
- "notbot_at": "NotBot",
754
- "frontpage_at": "Any Frontend Page Loaded",
755
- "loginpage_at": "Login Page Loaded",
756
- "bt404_at": "BotTrack 404",
757
- "btfake_at": "BotTrack FakeWebCrawler",
758
- "btcheese_at": "BotTrack LinkCheese",
759
- "btloginfail_at": "BotTrack LoginFailed",
760
- "btua_at": "BotTrack Useragent Fail",
761
- "btxml_at": "BotTrack XMLRPC Access",
762
- "btlogininvalid_at": "BotTrack LoginInvalid",
763
- "btinvalidscript_at": "BotTrack InvalidScript",
764
- "cooldown_at": "Triggered Cooldown",
765
- "humanspam_at": "Comment Marked As Human SPAM",
766
- "markspam_at": "Mark Comment As SPAM",
767
- "unmarkspam_at": "Unmark Comment As SPAM",
768
- "captchapass_at": "Captcha Passed",
769
- "captchafail_at": "Captcha Failed",
770
- "auth_at": "Successful Login",
771
- "firewall_at": "Triggered Firewall",
772
- "ratelimit_at": "Rate Limit Exceeded",
773
- "offense_at": "Last Offense",
774
- "blocked_at": "Last Block",
775
- "unblocked_at": "Unblocked",
776
- "bypass_at": "Bypass",
777
- "snsent_at": "Sent To ShieldNET"
778
- }
779
- },
780
  "events": {
781
  "custom_offense": {
782
  "audit_params": [
582
  "transferable": false,
583
  "type": "array",
584
  "default": []
 
 
 
 
 
 
 
585
  }
586
  ],
587
  "definitions": {
715
  }
716
  },
717
  "db_classes": {
 
718
  "ip_lists": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\IPs\\Handler"
719
  },
720
  "ip_lists_table_name": "ip_lists",
733
  "blocked_at": "IP Blocked"
734
  }
735
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
736
  "events": {
737
  "custom_offense": {
738
  "audit_params": [
config/deprecated/traffic.php CHANGED
@@ -210,33 +210,9 @@
210
  "name": "Request Limit Time Interval",
211
  "summary": "The Time Interval To Test For Excessive Requests",
212
  "description": "The time limit within which to monitor for excessive requests that exceed the limit."
213
- },
214
- {
215
- "key": "legacy_db_deleted_at",
216
- "section": "section_non_ui",
217
- "transferable": false,
218
- "type": "text",
219
- "default": 0
220
  }
221
  ],
222
  "definitions": {
223
- "db_classes": {
224
- "traffic": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Handler"
225
- },
226
- "db_table_traffic": {
227
- "slug": "traffic",
228
- "cols_custom": {
229
- "rid": "varchar(10) NOT NULL DEFAULT '' COMMENT 'Request ID'",
230
- "uid": "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'User ID'",
231
- "ip": "varbinary(16) DEFAULT NULL COMMENT 'Visitor IP Address'",
232
- "path": "text NOT NULL DEFAULT '' COMMENT 'Request Path or URI'",
233
- "code": "int(5) NOT NULL DEFAULT '200' COMMENT 'HTTP Response Code'",
234
- "verb": "varchar(10) NOT NULL DEFAULT 'get' COMMENT 'HTTP Method'",
235
- "ua": "text COMMENT 'Browser User Agent String'",
236
- "trans": "tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Trangression'"
237
- }
238
- },
239
- "traffic_table_name": "traffic",
240
  "events": {
241
  "request_limit_exceeded": {
242
  "audit_params": [
210
  "name": "Request Limit Time Interval",
211
  "summary": "The Time Interval To Test For Excessive Requests",
212
  "description": "The time limit within which to monitor for excessive requests that exceed the limit."
 
 
 
 
 
 
 
213
  }
214
  ],
215
  "definitions": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  "events": {
217
  "request_limit_exceeded": {
218
  "audit_params": [
config/hack_protect.json CHANGED
@@ -66,16 +66,6 @@
66
  "Recommendation - Keep The Realtime Change Detection Active."
67
  ]
68
  },
69
- {
70
- "slug": "section_scan_ufc",
71
- "title": "Unrecognised Files Scanner",
72
- "title_short": "Unrecognised Files Scanner",
73
- "beacon_id": 395,
74
- "summary": [
75
- "Purpose - Scan your WordPress core folders for unrecognised files that don't belong.",
76
- "Recommendation - Keep the Unrecognised Files Scanner feature turned on."
77
- ]
78
- },
79
  {
80
  "slug": "section_scan_options",
81
  "title": "Scan Options",
@@ -114,6 +104,85 @@
114
  "summary": "Enable (or Disable) The Hack Guard Module",
115
  "description": "Un-Checking this option will completely disable the Hack Guard module"
116
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  {
118
  "key": "enabled_scan_apc",
119
  "section": "section_scan_wpv",
@@ -151,44 +220,6 @@
151
  "summary": "Apply Updates Automatically To Vulnerable Plugins",
152
  "description": "When an update becomes available, automatically apply updates to items with known vulnerabilities."
153
  },
154
- {
155
- "key": "enable_core_file_integrity_scan",
156
- "section": "section_file_guard",
157
- "default": "Y",
158
- "type": "checkbox",
159
- "link_info": "https://shsec.io/hd",
160
- "link_blog": "https://shsec.io/wpsf37",
161
- "beacon_id": 224,
162
- "name": "WP Core File Scanner",
163
- "summary": "Automatically Scans WordPress Core Files For Alterations",
164
- "description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
165
- },
166
- {
167
- "key": "mal_scan_enable",
168
- "section": "section_file_guard",
169
- "premium": true,
170
- "default": "Y",
171
- "type": "checkbox",
172
- "link_info": "https://shsec.io/fp",
173
- "link_blog": "https://shsec.io/fx",
174
- "beacon_id": 222,
175
- "name": "Automatic Malware Scan",
176
- "summary": "Enable Malware File Scanner",
177
- "description": "When enabled the Malware scanner will run automatically."
178
- },
179
- {
180
- "key": "ptg_enable",
181
- "section": "section_file_guard",
182
- "premium": true,
183
- "default": "Y",
184
- "type": "checkbox",
185
- "link_info": "https://shsec.io/bl",
186
- "link_blog": "https://shsec.io/bm",
187
- "beacon_id": 133,
188
- "name": "Enable/Disable Guard",
189
- "summary": "Enable The Guard For Plugin And Theme Files",
190
- "description": "When enabled the Guard will automatically scan for changes to your Plugin and Theme files."
191
- },
192
  {
193
  "key": "file_locker",
194
  "section": "section_realtime",
@@ -220,35 +251,6 @@
220
  "summary": "Lock Files Against Tampering and Changes",
221
  "description": "As soon as changes are detected to any selected files, the contents may be examined and reverted."
222
  },
223
- {
224
- "key": "file_repair_areas",
225
- "section": "section_file_guard",
226
- "type": "multiple_select",
227
- "default": [
228
- "wp",
229
- "plugin"
230
- ],
231
- "value_options": [
232
- {
233
- "value_key": "wp",
234
- "text": "WP Core"
235
- },
236
- {
237
- "value_key": "plugin",
238
- "text": "Plugin Files"
239
- },
240
- {
241
- "value_key": "theme",
242
- "text": "Theme Files"
243
- }
244
- ],
245
- "link_info": "https://shsec.io/wpsf36",
246
- "link_blog": "https://shsec.io/wpsf37",
247
- "beacon_id": 228,
248
- "name": "Auto File Repair",
249
- "summary": "Which Files Should Be Automatically Repaired?",
250
- "description": "When a file is modified, or malware is detected, Shield can try to repair files."
251
- },
252
  {
253
  "key": "scan_frequency",
254
  "section": "section_scan_options",
@@ -296,70 +298,6 @@
296
  "summary": "Number Of Times To Automatically Scan Core Files In 24 Hours",
297
  "description": "Default: Once every 24hrs. To improve security, increase the number of scans per day."
298
  },
299
- {
300
- "key": "enable_unrecognised_file_cleaner_scan",
301
- "section": "section_scan_ufc",
302
- "default": "enabled_report_only",
303
- "type": "select",
304
- "value_options": [
305
- {
306
- "value_key": "disabled",
307
- "text": "Automatic Scan Disabled"
308
- },
309
- {
310
- "value_key": "enabled_report_only",
311
- "text": "Scan Enabled - Report Only"
312
- },
313
- {
314
- "value_key": "enabled_delete_only",
315
- "text": "Scan Enabled - Automatically Delete Files"
316
- }
317
- ],
318
- "link_info": "https://shsec.io/9y",
319
- "link_blog": "https://shsec.io/95",
320
- "beacon_id": 227,
321
- "name": "Unrecognised Files Scanner",
322
- "summary": "Scans Core Directories For Unrecognised Files",
323
- "description": "Scans for, and automatically deletes, any files in your core WordPress folders that are not part of your WordPress installation."
324
- },
325
- {
326
- "key": "ufc_scan_uploads",
327
- "section": "section_scan_ufc",
328
- "advanced": true,
329
- "default": "N",
330
- "type": "checkbox",
331
- "link_info": "https://shsec.io/he",
332
- "link_blog": "https://shsec.io/95",
333
- "beacon_id": 347,
334
- "name": "Scan Uploads",
335
- "summary": "Scan Uploads Folder For PHP and Javascript",
336
- "description": "The Uploads folder is primarily for media, but could be used to store nefarious files."
337
- },
338
- {
339
- "key": "ufc_exclusions",
340
- "section": "section_scan_ufc",
341
- "advanced": true,
342
- "default": [
343
- "error_log",
344
- "php_error_log",
345
- ".htaccess",
346
- ".htpasswd",
347
- ".user.ini",
348
- "php.ini",
349
- "web.config",
350
- "php_mail.log",
351
- "mail.log",
352
- "wp-content/uploads/bb-plugin/cache/",
353
- "wp-content/uploads/cache/wpml/twig/"
354
- ],
355
- "type": "array",
356
- "link_info": "https://shsec.io/9z",
357
- "link_blog": "https://shsec.io/95",
358
- "beacon_id": 231,
359
- "name": "File Exclusions",
360
- "summary": "Provide A List Of Files To Be Excluded From The Scan",
361
- "description": "Take a new line for each file you wish to exclude from the scan. No commas are necessary."
362
- },
363
  {
364
  "key": "mal_autorepair_surgical",
365
  "section": "section_non_ui",
@@ -385,44 +323,6 @@
385
  "summary": "Show Re-Install Links For Plugins",
386
  "description": "Show links to re-install plugins and offer re-install when activating plugins."
387
  },
388
- {
389
- "key": "auto_filter_results",
390
- "section": "section_scan_options",
391
- "premium": false,
392
- "type": "checkbox",
393
- "default": "Y",
394
- "link_info": "",
395
- "link_blog": "",
396
- "beacon_id": 439,
397
- "name": "Auto-Filter Results",
398
- "summary": "Automatically Filter Results Of Irrelevant Items",
399
- "description": "Automatically remove items from results that are irrelevant."
400
- },
401
- {
402
- "key": "scan_path_exclusions",
403
- "section": "section_scan_options",
404
- "advanced": true,
405
- "premium": true,
406
- "default": [
407
- "wp-content/cache/",
408
- "wp-content/nfwlog/",
409
- "wp-content/wflogs/",
410
- "*/error_log",
411
- "*/php_error_log",
412
- "*/mail.log",
413
- "*/php_mail.log",
414
- "*/.stylelintrc-css.json",
415
- "*/.stylelintrc.json",
416
- "*/sucuri-*.php"
417
- ],
418
- "type": "array",
419
- "link_info": "",
420
- "link_blog": "",
421
- "beacon_id": 441,
422
- "name": "Scan Exclusions",
423
- "summary": "Scan File and Folder Exclusions",
424
- "description": "Scan File and Folder Exclusions."
425
- },
426
  {
427
  "key": "scans_to_build",
428
  "section": "section_non_ui",
@@ -454,16 +354,29 @@
454
  "tracking_exclude": true,
455
  "type": "array",
456
  "default": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  }
458
  ],
459
  "definitions": {
460
  "all_scan_slugs": [
461
  "apc",
462
- "mal",
463
- "ptg",
464
  "wpv",
465
- "wcf",
466
- "ufc"
467
  ],
468
  "file_scan_extensions": [
469
  "php",
@@ -478,6 +391,153 @@
478
  "twig",
479
  "hbs"
480
  ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  "db_classes": {
482
  "filelocker": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\FileLocker\\Handler",
483
  "scanner": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Scanner\\Handler",
66
  "Recommendation - Keep The Realtime Change Detection Active."
67
  ]
68
  },
 
 
 
 
 
 
 
 
 
 
69
  {
70
  "slug": "section_scan_options",
71
  "title": "Scan Options",
104
  "summary": "Enable (or Disable) The Hack Guard Module",
105
  "description": "Un-Checking this option will completely disable the Hack Guard module"
106
  },
107
+ {
108
+ "key": "enable_core_file_integrity_scan",
109
+ "section": "section_file_guard",
110
+ "default": "Y",
111
+ "type": "checkbox",
112
+ "link_info": "https://shsec.io/hd",
113
+ "link_blog": "https://shsec.io/wpsf37",
114
+ "beacon_id": 224,
115
+ "name": "WP Core File Scanner",
116
+ "summary": "Automatically Scans WordPress Core Files For Alterations",
117
+ "description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
118
+ },
119
+ {
120
+ "key": "file_repair_areas",
121
+ "section": "section_file_guard",
122
+ "type": "multiple_select",
123
+ "default": [
124
+ "wp",
125
+ "plugin"
126
+ ],
127
+ "value_options": [
128
+ {
129
+ "value_key": "wp",
130
+ "text": "WP Core"
131
+ },
132
+ {
133
+ "value_key": "plugin",
134
+ "text": "Plugin Files"
135
+ },
136
+ {
137
+ "value_key": "theme",
138
+ "text": "Theme Files"
139
+ }
140
+ ],
141
+ "link_info": "https://shsec.io/wpsf36",
142
+ "link_blog": "https://shsec.io/wpsf37",
143
+ "beacon_id": 228,
144
+ "name": "Auto File Repair",
145
+ "summary": "Which Files Should Be Automatically Repaired?",
146
+ "description": "When a file is modified, or malware is detected, Shield can try to repair files."
147
+ },
148
+ {
149
+ "key": "auto_filter_results",
150
+ "section": "section_file_guard",
151
+ "premium": false,
152
+ "type": "checkbox",
153
+ "default": "Y",
154
+ "link_info": "",
155
+ "link_blog": "",
156
+ "beacon_id": 439,
157
+ "name": "Auto-Filter Results",
158
+ "summary": "Automatically Filter Results Of Irrelevant Items",
159
+ "description": "Automatically remove items from results that are irrelevant."
160
+ },
161
+ {
162
+ "key": "scan_path_exclusions",
163
+ "section": "section_file_guard",
164
+ "advanced": true,
165
+ "premium": true,
166
+ "default": [
167
+ "wp-content/cache/",
168
+ "wp-content/nfwlog/",
169
+ "wp-content/wflogs/",
170
+ "*/error_log",
171
+ "*/php_error_log",
172
+ "*/mail.log",
173
+ "*/php_mail.log",
174
+ "*/.stylelintrc-css.json",
175
+ "*/.stylelintrc.json",
176
+ "*/sucuri-*.php"
177
+ ],
178
+ "type": "array",
179
+ "link_info": "",
180
+ "link_blog": "",
181
+ "beacon_id": 441,
182
+ "name": "Scan Exclusions",
183
+ "summary": "Scan File and Folder Exclusions",
184
+ "description": "Scan File and Folder Exclusions."
185
+ },
186
  {
187
  "key": "enabled_scan_apc",
188
  "section": "section_scan_wpv",
220
  "summary": "Apply Updates Automatically To Vulnerable Plugins",
221
  "description": "When an update becomes available, automatically apply updates to items with known vulnerabilities."
222
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  {
224
  "key": "file_locker",
225
  "section": "section_realtime",
251
  "summary": "Lock Files Against Tampering and Changes",
252
  "description": "As soon as changes are detected to any selected files, the contents may be examined and reverted."
253
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  {
255
  "key": "scan_frequency",
256
  "section": "section_scan_options",
298
  "summary": "Number Of Times To Automatically Scan Core Files In 24 Hours",
299
  "description": "Default: Once every 24hrs. To improve security, increase the number of scans per day."
300
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  {
302
  "key": "mal_autorepair_surgical",
303
  "section": "section_non_ui",
323
  "summary": "Show Re-Install Links For Plugins",
324
  "description": "Show links to re-install plugins and offer re-install when activating plugins."
325
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  {
327
  "key": "scans_to_build",
328
  "section": "section_non_ui",
354
  "tracking_exclude": true,
355
  "type": "array",
356
  "default": []
357
+ },
358
+ {
359
+ "key": "realtime_scan_last_at",
360
+ "section": "section_non_ui",
361
+ "transferable": false,
362
+ "tracking_exclude": true,
363
+ "type": "integer",
364
+ "default": 0
365
+ },
366
+ {
367
+ "key": "legacy_db_conversion_at",
368
+ "section": "section_non_ui",
369
+ "transferable": false,
370
+ "tracking_exclude": true,
371
+ "type": "integer",
372
+ "default": 0
373
  }
374
  ],
375
  "definitions": {
376
  "all_scan_slugs": [
377
  "apc",
 
 
378
  "wpv",
379
+ "afs"
 
380
  ],
381
  "file_scan_extensions": [
382
  "php",
391
  "twig",
392
  "hbs"
393
  ],
394
+ "db_handler_classes": {
395
+ "scans": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Handler",
396
+ "scanitems": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Handler",
397
+ "resultitems": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Handler",
398
+ "resultitem_meta": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Handler",
399
+ "scanresults": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Handler"
400
+ },
401
+ "db_table_scans": {
402
+ "autoexpire": 0,
403
+ "slug": "scans",
404
+ "col_older_than": "created_at",
405
+ "has_updated_at": false,
406
+ "cols_custom": {
407
+ "scan": {
408
+ "macro_type": "char",
409
+ "length": 3,
410
+ "comment": "Scan Slug"
411
+ },
412
+ "ready_at": {
413
+ "macro_type": "timestamp",
414
+ "comment": "Scan Ready At"
415
+ },
416
+ "finished_at": {
417
+ "macro_type": "timestamp",
418
+ "comment": "Scan Completed At"
419
+ },
420
+ "meta": {
421
+ "macro_type": "meta",
422
+ "comment": "Scan Meta Info"
423
+ }
424
+ }
425
+ },
426
+ "db_table_scanitems": {
427
+ "autoexpire": 0,
428
+ "slug": "scanitems",
429
+ "has_updated_at": false,
430
+ "has_created_at": false,
431
+ "has_deleted_at": false,
432
+ "col_older_than": "started_at",
433
+ "cols_custom": {
434
+ "scan_ref": {
435
+ "macro_type": "foreign_key_id",
436
+ "foreign_key": {
437
+ "ref_table": "icwp_wpsf_scans"
438
+ }
439
+ },
440
+ "items": {
441
+ "macro_type": "text",
442
+ "comment": "Array of scan items"
443
+ },
444
+ "started_at": {
445
+ "macro_type": "timestamp",
446
+ "comment": "Started Scanning Items At"
447
+ },
448
+ "finished_at": {
449
+ "macro_type": "timestamp",
450
+ "comment": "Finished Scanning Items At"
451
+ }
452
+ }
453
+ },
454
+ "db_table_resultitems": {
455
+ "autoexpire": 0,
456
+ "slug": "resultitems",
457
+ "has_updated_at": true,
458
+ "col_older_than": "updated_at",
459
+ "cols_custom": {
460
+ "item_type": {
461
+ "macro_type": "char",
462
+ "length": 1,
463
+ "comment": "Result Item Type"
464
+ },
465
+ "item_id": {
466
+ "macro_type": "varchar",
467
+ "length": 256,
468
+ "comment": "Result Item ID"
469
+ },
470
+ "ignored_at": {
471
+ "macro_type": "timestamp",
472
+ "comment": "Result Ignored"
473
+ },
474
+ "notified_at": {
475
+ "macro_type": "timestamp",
476
+ "comment": "Result Notification Sent"
477
+ },
478
+ "auto_filtered_at": {
479
+ "macro_type": "timestamp",
480
+ "comment": "Result Auto Filtered"
481
+ },
482
+ "attempt_repair_at": {
483
+ "macro_type": "timestamp",
484
+ "comment": "Attempted Repair At"
485
+ },
486
+ "item_repaired_at": {
487
+ "macro_type": "timestamp",
488
+ "comment": "Item Repaired At"
489
+ },
490
+ "item_deleted_at": {
491
+ "macro_type": "timestamp",
492
+ "comment": "Item Deleted At"
493
+ }
494
+ }
495
+ },
496
+ "db_table_resultitem_meta": {
497
+ "slug": "resultitem_meta",
498
+ "has_updated_at": false,
499
+ "has_created_at": false,
500
+ "has_deleted_at": false,
501
+ "cols_custom": {
502
+ "ri_ref": {
503
+ "macro_type": "foreign_key_id",
504
+ "foreign_key": {
505
+ "ref_table": "icwp_wpsf_resultitems"
506
+ },
507
+ "comment": "Reference to primary Result Item record"
508
+ },
509
+ "meta_key": {
510
+ "macro_type": "varchar",
511
+ "length": 32,
512
+ "comment": "Meta Key"
513
+ },
514
+ "meta_value": {
515
+ "macro_type": "text",
516
+ "comment": "Meta Data"
517
+ }
518
+ }
519
+ },
520
+ "db_table_scanresults": {
521
+ "autoexpire": 0,
522
+ "slug": "scanresults",
523
+ "has_updated_at": false,
524
+ "has_created_at": true,
525
+ "has_deleted_at": false,
526
+ "cols_custom": {
527
+ "scan_ref": {
528
+ "macro_type": "foreign_key_id",
529
+ "foreign_key": {
530
+ "ref_table": "icwp_wpsf_scans"
531
+ }
532
+ },
533
+ "resultitem_ref": {
534
+ "macro_type": "foreign_key_id",
535
+ "foreign_key": {
536
+ "ref_table": "icwp_wpsf_resultitems"
537
+ }
538
+ }
539
+ }
540
+ },
541
  "db_classes": {
542
  "filelocker": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\FileLocker\\Handler",
543
  "scanner": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Scanner\\Handler",
config/ips.json CHANGED
@@ -582,13 +582,6 @@
582
  "transferable": false,
583
  "type": "array",
584
  "default": []
585
- },
586
- {
587
- "key": "legacy_db_deleted_at",
588
- "section": "section_non_ui",
589
- "transferable": false,
590
- "type": "integer",
591
- "default": ""
592
  }
593
  ],
594
  "definitions": {
@@ -722,7 +715,6 @@
722
  }
723
  },
724
  "db_classes": {
725
- "botsignals": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Handler",
726
  "ip_lists": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\IPs\\Handler"
727
  },
728
  "ip_lists_table_name": "ip_lists",
@@ -741,42 +733,6 @@
741
  "blocked_at": "IP Blocked"
742
  }
743
  },
744
- "db_table_botsignals": {
745
- "autoexpire": 3,
746
- "slug": "botsignals",
747
- "col_older_than": "updated_at",
748
- "has_updated_at": true,
749
- "cols_custom": {
750
- "ip": "varbinary(16) DEFAULT NULL COMMENT 'IP Address'"
751
- },
752
- "cols_timestamps": {
753
- "notbot_at": "NotBot",
754
- "frontpage_at": "Any Frontend Page Loaded",
755
- "loginpage_at": "Login Page Loaded",
756
- "bt404_at": "BotTrack 404",
757
- "btfake_at": "BotTrack FakeWebCrawler",
758
- "btcheese_at": "BotTrack LinkCheese",
759
- "btloginfail_at": "BotTrack LoginFailed",
760
- "btua_at": "BotTrack Useragent Fail",
761
- "btxml_at": "BotTrack XMLRPC Access",
762
- "btlogininvalid_at": "BotTrack LoginInvalid",
763
- "btinvalidscript_at": "BotTrack InvalidScript",
764
- "cooldown_at": "Triggered Cooldown",
765
- "humanspam_at": "Comment Marked As Human SPAM",
766
- "markspam_at": "Mark Comment As SPAM",
767
- "unmarkspam_at": "Unmark Comment As SPAM",
768
- "captchapass_at": "Captcha Passed",
769
- "captchafail_at": "Captcha Failed",
770
- "auth_at": "Successful Login",
771
- "firewall_at": "Triggered Firewall",
772
- "ratelimit_at": "Rate Limit Exceeded",
773
- "offense_at": "Last Offense",
774
- "blocked_at": "Last Block",
775
- "unblocked_at": "Unblocked",
776
- "bypass_at": "Bypass",
777
- "snsent_at": "Sent To ShieldNET"
778
- }
779
- },
780
  "events": {
781
  "custom_offense": {
782
  "audit_params": [
582
  "transferable": false,
583
  "type": "array",
584
  "default": []
 
 
 
 
 
 
 
585
  }
586
  ],
587
  "definitions": {
715
  }
716
  },
717
  "db_classes": {
 
718
  "ip_lists": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\IPs\\Handler"
719
  },
720
  "ip_lists_table_name": "ip_lists",
733
  "blocked_at": "IP Blocked"
734
  }
735
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
736
  "events": {
737
  "custom_offense": {
738
  "audit_params": [
config/traffic.json CHANGED
@@ -210,33 +210,9 @@
210
  "name": "Request Limit Time Interval",
211
  "summary": "The Time Interval To Test For Excessive Requests",
212
  "description": "The time limit within which to monitor for excessive requests that exceed the limit."
213
- },
214
- {
215
- "key": "legacy_db_deleted_at",
216
- "section": "section_non_ui",
217
- "transferable": false,
218
- "type": "text",
219
- "default": 0
220
  }
221
  ],
222
  "definitions": {
223
- "db_classes": {
224
- "traffic": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Handler"
225
- },
226
- "db_table_traffic": {
227
- "slug": "traffic",
228
- "cols_custom": {
229
- "rid": "varchar(10) NOT NULL DEFAULT '' COMMENT 'Request ID'",
230
- "uid": "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'User ID'",
231
- "ip": "varbinary(16) DEFAULT NULL COMMENT 'Visitor IP Address'",
232
- "path": "text NOT NULL DEFAULT '' COMMENT 'Request Path or URI'",
233
- "code": "int(5) NOT NULL DEFAULT '200' COMMENT 'HTTP Response Code'",
234
- "verb": "varchar(10) NOT NULL DEFAULT 'get' COMMENT 'HTTP Method'",
235
- "ua": "text COMMENT 'Browser User Agent String'",
236
- "trans": "tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Trangression'"
237
- }
238
- },
239
- "traffic_table_name": "traffic",
240
  "events": {
241
  "request_limit_exceeded": {
242
  "audit_params": [
210
  "name": "Request Limit Time Interval",
211
  "summary": "The Time Interval To Test For Excessive Requests",
212
  "description": "The time limit within which to monitor for excessive requests that exceed the limit."
 
 
 
 
 
 
 
213
  }
214
  ],
215
  "definitions": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  "events": {
217
  "request_limit_exceeded": {
218
  "audit_params": [
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 12.0.13
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 13.0.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
plugin-spec.php CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "12.0.13",
4
- "release_timestamp": 1633856080,
5
- "build": "202110.1001",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
@@ -84,7 +84,7 @@
84
  "register": {
85
  "css": {
86
  "bootstrap": {
87
- "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css"
88
  },
89
  "bootstrap-datepicker": {
90
  "url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css",
@@ -190,7 +190,7 @@
190
  },
191
  "js": {
192
  "bootstrap": {
193
- "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.bundle.min.js",
194
  "deps": [
195
  "wp-jquery"
196
  ]
@@ -450,11 +450,10 @@
450
  }
451
  ],
452
  "version_upgrades": [
453
- "10.1.0",
454
- "10.2.1",
455
  "11.2.0",
456
  "12.0.0",
457
- "12.0.1"
 
458
  ],
459
  "action_links": {
460
  "remove": null,
1
  {
2
  "properties": {
3
+ "version": "13.0.0",
4
+ "release_timestamp": 1636970660,
5
+ "build": "202111.1501",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
84
  "register": {
85
  "css": {
86
  "bootstrap": {
87
+ "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap.min.css"
88
  },
89
  "bootstrap-datepicker": {
90
  "url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css",
190
  },
191
  "js": {
192
  "bootstrap": {
193
+ "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/js/bootstrap.bundle.min.js",
194
  "deps": [
195
  "wp-jquery"
196
  ]
450
  }
451
  ],
452
  "version_upgrades": [
 
 
453
  "11.2.0",
454
  "12.0.0",
455
+ "12.0.1",
456
+ "13.0.0"
457
  ],
458
  "action_links": {
459
  "remove": null,
plugin.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "12.0.13",
4
- "release_timestamp": 1633856080,
5
- "build": "202110.1001",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
@@ -84,7 +84,7 @@
84
  "register": {
85
  "css": {
86
  "bootstrap": {
87
- "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css"
88
  },
89
  "bootstrap-datepicker": {
90
  "url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css",
@@ -190,7 +190,7 @@
190
  },
191
  "js": {
192
  "bootstrap": {
193
- "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.bundle.min.js",
194
  "deps": [
195
  "wp-jquery"
196
  ]
@@ -450,11 +450,10 @@
450
  }
451
  ],
452
  "version_upgrades": [
453
- "10.1.0",
454
- "10.2.1",
455
  "11.2.0",
456
  "12.0.0",
457
- "12.0.1"
 
458
  ],
459
  "action_links": {
460
  "remove": null,
1
  {
2
  "properties": {
3
+ "version": "13.0.0",
4
+ "release_timestamp": 1636970660,
5
+ "build": "202111.1501",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
84
  "register": {
85
  "css": {
86
  "bootstrap": {
87
+ "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap.min.css"
88
  },
89
  "bootstrap-datepicker": {
90
  "url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css",
190
  },
191
  "js": {
192
  "bootstrap": {
193
+ "url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/js/bootstrap.bundle.min.js",
194
  "deps": [
195
  "wp-jquery"
196
  ]
450
  }
451
  ],
452
  "version_upgrades": [
 
 
453
  "11.2.0",
454
  "12.0.0",
455
+ "12.0.1",
456
+ "13.0.0"
457
  ],
458
  "action_links": {
459
  "remove": null,
readme.txt CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.7
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.8
11
- Stable tag: 12.0.13
12
 
13
  No-Nonsense Security Hardening that protects WordPress against hackers, malicious bots, and spammers (no captchas!). Now with exclusive ShieldNET Technology.
14
 
@@ -349,11 +349,11 @@ You can view the entire [Shield changelog here](https://shsec.io/shieldwporgfull
349
 
350
  == Changelog ==
351
 
352
- The full Shield Security Changelog can be viewed from our home page:
353
 
354
- #### [Full Shield Security Changelog](https://shsec.io/shieldwporgfullchangelog)
 
355
 
356
- ShieldPRO delivers exclusive security features to the serious site administrator to maximise site security
357
- You'll also have direct access to our technical support team for any security related questions you might have.
358
 
359
  [Go Pro](https://shsec.io/aa) or grab the [free ShieldPRO Trial](https://shsec.io/shieldfreetrialwporgreadme).
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.8
11
+ Stable tag: 13.0.0
12
 
13
  No-Nonsense Security Hardening that protects WordPress against hackers, malicious bots, and spammers (no captchas!). Now with exclusive ShieldNET Technology.
14
 
349
 
350
  == Changelog ==
351
 
352
+ #### [View Shield Security Changelog](https://shsec.io/shieldwporgfullchangelog)
353
 
354
+ ShieldPRO delivers exclusive, enhanced security features for the serious site administrator
355
+ looking to maximise their WordPress security for themselves and their clients.
356
 
357
+ You'll of course have direct access to our technical support team and the option to reach out to us for any security questions or concerns.
 
358
 
359
  [Go Pro](https://shsec.io/aa) or grab the [free ShieldPRO Trial](https://shsec.io/shieldfreetrialwporgreadme).
resources/css/plugin.css CHANGED
@@ -3,6 +3,9 @@
3
  body {
4
  overflow-y: scroll;
5
  }
 
 
 
6
  body.rtl {
7
  text-align: right;
8
  }
@@ -1100,15 +1103,6 @@ input[type=checkbox].form-check-input {
1100
  .tooltip .arrow {
1101
  display: none !important;
1102
  }
1103
- table.odp-table tr.audit-cat-1 td {
1104
- background-color: #f8fbff;
1105
- }
1106
- table.odp-table tr.audit-cat-2 td {
1107
- background-color: #fffcfa;
1108
- }
1109
- table.odp-table tr.audit-cat-3 td {
1110
- background-color: #fffdfd;
1111
- }
1112
  .row-sticky td {
1113
  background-color: #5a5a5a;
1114
  position: sticky;
@@ -1543,8 +1537,8 @@ body.folded #FooterBannerGoPro {
1543
  border-color: rgb(177 216 178);
1544
  border-width: 1px 1px 1px 0;
1545
  border-style: solid;
1546
- min-width: 115px;
1547
- width: 115px;
1548
  }
1549
  #NavSideBar a.nav-link:hover {
1550
  }
@@ -1627,7 +1621,7 @@ body.folded #FooterBannerGoPro {
1627
  }
1628
  .primary_side_sub_menu a:hover {
1629
  color: #008000;
1630
- text-shadow: 0 1px 1px rgba(0,0,0,0.15);
1631
  }
1632
  .primary_side_sub_menu a.active {
1633
  border-left: 3px solid rgba(0, 128, 0, 0.4);
@@ -1728,20 +1722,24 @@ button.btn.action {
1728
  line-height: 16px;
1729
  }
1730
 
1731
- #CodeRenderModal pre.icwp-code-render {
1732
  counter-reset: line;
1733
  }
1734
- #CodeRenderModal pre.icwp-code-render > code {
1735
  counter-increment: line;
1736
  background-color: transparent;
1737
  padding: 0;
1738
  display: block;
1739
  }
1740
- #CodeRenderModal pre.icwp-code-render > code:before {
1741
  content: counter(line);
1742
  width: 32px;
1743
  display: inline-block;
1744
  }
1745
- #CodeRenderModal pre.icwp-code-render > code:before {
1746
  -webkit-user-select: none;
 
 
 
 
1747
  }
3
  body {
4
  overflow-y: scroll;
5
  }
6
+ body.shield-busy {
7
+ cursor: wait !important;
8
+ }
9
  body.rtl {
10
  text-align: right;
11
  }
1103
  .tooltip .arrow {
1104
  display: none !important;
1105
  }
 
 
 
 
 
 
 
 
 
1106
  .row-sticky td {
1107
  background-color: #5a5a5a;
1108
  position: sticky;
1537
  border-color: rgb(177 216 178);
1538
  border-width: 1px 1px 1px 0;
1539
  border-style: solid;
1540
+ min-width: 140px;
1541
+ width: 140px;
1542
  }
1543
  #NavSideBar a.nav-link:hover {
1544
  }
1621
  }
1622
  .primary_side_sub_menu a:hover {
1623
  color: #008000;
1624
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
1625
  }
1626
  .primary_side_sub_menu a.active {
1627
  border-left: 3px solid rgba(0, 128, 0, 0.4);
1722
  line-height: 16px;
1723
  }
1724
 
1725
+ #ShieldModalContainer pre.icwp-code-render {
1726
  counter-reset: line;
1727
  }
1728
+ #ShieldModalContainer pre.icwp-code-render > code {
1729
  counter-increment: line;
1730
  background-color: transparent;
1731
  padding: 0;
1732
  display: block;
1733
  }
1734
+ #ShieldModalContainer pre.icwp-code-render > code:before {
1735
  content: counter(line);
1736
  width: 32px;
1737
  display: inline-block;
1738
  }
1739
+ #ShieldModalContainer pre.icwp-code-render > code:before {
1740
  -webkit-user-select: none;
1741
+ }
1742
+
1743
+ .scan-item-history ul {
1744
+ list-style: inside disc;
1745
  }
resources/images/bootstrap/zoom-in.svg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-zoom-in" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M6.5 12a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zM13 6.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0z"/>
3
+ <path d="M10.344 11.742c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1 6.538 6.538 0 0 1-1.398 1.4z"/>
4
+ <path fill-rule="evenodd" d="M6.5 3a.5.5 0 0 1 .5.5V6h2.5a.5.5 0 0 1 0 1H7v2.5a.5.5 0 0 1-1 0V7H3.5a.5.5 0 0 1 0-1H6V3.5a.5.5 0 0 1 .5-.5z"/>
5
+ </svg>
resources/js/global-plugin.js CHANGED
@@ -255,7 +255,7 @@ var iCWP_WPSF_BodyOverlay = new function () {
255
  this.show = function () {
256
  nOverlays++;
257
  jQuery( 'div#icwp-fade-wrapper' ).fadeIn( 1000 );
258
- jQuery( 'html' ).css( 'cursor', 'wait' );
259
  };
260
 
261
  this.hide = function () {
@@ -264,7 +264,7 @@ var iCWP_WPSF_BodyOverlay = new function () {
264
  nOverlays = 0;
265
  jQuery( 'div#icwp-fade-wrapper' ).stop().fadeOut();
266
  }
267
- jQuery( 'html' ).css( 'cursor', 'initial' );
268
  };
269
 
270
  this.initialise = function () {
255
  this.show = function () {
256
  nOverlays++;
257
  jQuery( 'div#icwp-fade-wrapper' ).fadeIn( 1000 );
258
+ jQuery( 'body' ).addClass( 'shield-busy' );
259
  };
260
 
261
  this.hide = function () {
264
  nOverlays = 0;
265
  jQuery( 'div#icwp-fade-wrapper' ).stop().fadeOut();
266
  }
267
+ jQuery( 'body' ).removeClass( 'shield-busy' );
268
  };
269
 
270
  this.initialise = function () {
resources/js/plugin.js CHANGED
@@ -349,10 +349,28 @@ if ( typeof icwp_wpsf_vars_plugin !== 'undefined' ) {
349
  jQuery( document ).ready( function () {
350
  jQuery( document ).icwpWpsfTours();
351
  jQuery( document ).icwpWpsfPluginNavigation();
352
- jQuery( '.select2picker' ).select2( {
353
  width: 'resolve'
354
  } );
355
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  jQuery( document ).on( 'click', 'a.beacon-article', function ( evt ) {
357
  evt.preventDefault();
358
  let link = jQuery( evt.currentTarget );
349
  jQuery( document ).ready( function () {
350
  jQuery( document ).icwpWpsfTours();
351
  jQuery( document ).icwpWpsfPluginNavigation();
352
+ jQuery( '.select2picker.static' ).select2( {
353
  width: 'resolve'
354
  } );
355
 
356
+ jQuery( '#IpReviewSelect' ).select2( {
357
+ minimumInputLength: 2,
358
+ ajax: {
359
+ url: ajaxurl,
360
+ method: 'POST',
361
+ data: function ( params ) {
362
+ let reqParams = jQuery( this ).data( 'ajaxparams' );
363
+ reqParams.search = params.term;
364
+ return reqParams;
365
+ },
366
+ processResults: function ( data ) {
367
+ return {
368
+ results: data.data.ips
369
+ };
370
+ }
371
+ }
372
+ } );
373
+
374
  jQuery( document ).on( 'click', 'a.beacon-article', function ( evt ) {
375
  evt.preventDefault();
376
  let link = jQuery( evt.currentTarget );
resources/js/shield/scans.js CHANGED
@@ -70,6 +70,10 @@ jQuery.fn.icwpWpsfScansCheck = function ( aOptions ) {
70
  let bCurrentlyRunning = false;
71
  let nRunningCount = 0;
72
 
 
 
 
 
73
  let sendReq = function ( aParams ) {
74
  iCWP_WPSF_BodyOverlay.show();
75
 
@@ -100,7 +104,7 @@ jQuery.fn.icwpWpsfScansCheck = function ( aOptions ) {
100
  }
101
  else {
102
  setTimeout( function () {
103
- window.location.href = aOpts[ 'href_scans_results' ];
104
  }, 1000 );
105
  }
106
  }
70
  let bCurrentlyRunning = false;
71
  let nRunningCount = 0;
72
 
73
+ let loadResultsPage = function ( evt ) {
74
+ window.location.href = aOpts[ 'href_scans_results' ];
75
+ };
76
+
77
  let sendReq = function ( aParams ) {
78
  iCWP_WPSF_BodyOverlay.show();
79
 
104
  }
105
  else {
106
  setTimeout( function () {
107
+ loadResultsPage();
108
  }, 1000 );
109
  }
110
  }
resources/js/shield/scantables.js CHANGED
@@ -90,19 +90,22 @@
90
 
91
  base.$el.on(
92
  'click' + '.' + base._name,
93
- 'a.action.view-file',
94
  function ( evt ) {
95
  evt.preventDefault();
96
  let reqData = base.getBaseAjaxData();
97
  reqData.sub_action = 'view_file';
98
  reqData.rid = $( this ).data( 'rid' );
 
 
 
99
  $.post( ajaxurl, reqData, function ( response ) {
100
  if ( response.success ) {
101
- let $codeModal = jQuery( '#CodeRenderModal' );
102
- jQuery( '.modal-title', $codeModal ).html( response.data.vars.path );
103
- jQuery( '.modal-body', $codeModal ).html( response.data.vars.contents );
104
- $codeModal.modal( 'show' );
105
- $codeModal[ 0 ].querySelectorAll( 'pre.icwp-code-render code' ).forEach( ( el ) => {
106
  hljs.highlightElement( el );
107
  } );
108
  }
@@ -113,7 +116,10 @@
113
  }
114
  alert( msg );
115
  }
116
- } );
 
 
 
117
  }
118
  );
119
 
@@ -260,7 +266,7 @@
260
  className: 'action selected-action repair',
261
  action: function ( e, dt, node, config ) {
262
 
263
- if ( base.$table.rows().count() > 20 ) {
264
  alert( "Sorry, this tool isn't designed for such large repairs. We recommend completely removing and reinstalling the item." )
265
  }
266
  else if ( confirm( icwp_wpsf_vars_insights.strings.absolutely_sure ) ) {
90
 
91
  base.$el.on(
92
  'click' + '.' + base._name,
93
+ '.action.view-file',
94
  function ( evt ) {
95
  evt.preventDefault();
96
  let reqData = base.getBaseAjaxData();
97
  reqData.sub_action = 'view_file';
98
  reqData.rid = $( this ).data( 'rid' );
99
+
100
+ iCWP_WPSF_BodyOverlay.show();
101
+
102
  $.post( ajaxurl, reqData, function ( response ) {
103
  if ( response.success ) {
104
+ let $fileViewModal = jQuery( '#ShieldModalContainer' );
105
+ // jQuery( '.modal-title', $fileViewModal ).html( response.data.vars.path );
106
+ jQuery( '.modal-content', $fileViewModal ).html( response.data.vars.contents );
107
+ $fileViewModal.modal( 'show' );
108
+ $fileViewModal[ 0 ].querySelectorAll( 'pre.icwp-code-render code' ).forEach( ( el ) => {
109
  hljs.highlightElement( el );
110
  } );
111
  }
116
  }
117
  alert( msg );
118
  }
119
+ } )
120
+ .always( function () {
121
+ iCWP_WPSF_BodyOverlay.hide();
122
+ } );
123
  }
124
  );
125
 
266
  className: 'action selected-action repair',
267
  action: function ( e, dt, node, config ) {
268
 
269
+ if ( base.$table.rows( { selected: true } ).count() > 20 ) {
270
  alert( "Sorry, this tool isn't designed for such large repairs. We recommend completely removing and reinstalling the item." )
271
  }
272
  else if ( confirm( icwp_wpsf_vars_insights.strings.absolutely_sure ) ) {
resources/js/shield/userprofile.js CHANGED
@@ -47,10 +47,12 @@ jQuery.fn.ShieldUserProfile = function ( options ) {
47
 
48
  let initYubi = function ( shield_vars ) {
49
  let $yubiText = jQuery( 'input[type=text]#shield_yubi' );
50
- jQuery( document ).on( 'keyup', $yubiText, function ( evt ) {
51
  if ( evt.key === 'Enter' || evt.keyCode === 13 ) {
 
52
  shield_vars.ajax.user_yubikey_toggle.otp = $yubiText.val();
53
  sendReq( shield_vars.ajax.user_yubikey_toggle );
 
54
  }
55
  } );
56
 
47
 
48
  let initYubi = function ( shield_vars ) {
49
  let $yubiText = jQuery( 'input[type=text]#shield_yubi' );
50
+ jQuery( document ).on( 'keydown', $yubiText, function ( evt ) {
51
  if ( evt.key === 'Enter' || evt.keyCode === 13 ) {
52
+ evt.preventDefault();
53
  shield_vars.ajax.user_yubikey_toggle.otp = $yubiText.val();
54
  sendReq( shield_vars.ajax.user_yubikey_toggle );
55
+ return false;
56
  }
57
  } );
58
 
src/lib/src/Controller/Admin/AdminBarMenu.php CHANGED
@@ -32,17 +32,17 @@ class AdminBarMenu {
32
  if ( !empty( $items ) && is_array( $items ) ) {
33
  $warningCount = 0;
34
  foreach ( $items as $item ) {
35
- $warningCount += isset( $item[ 'warnings' ] ) ? $item[ 'warnings' ] : 0;
36
  }
37
 
38
- $sNodeId = $con->prefix( 'adminbarmenu' );
39
  $adminBar->add_node( [
40
- 'id' => $sNodeId,
41
  'title' => $con->getHumanName()
42
  .sprintf( '<div class="wp-core-ui wp-ui-notification shield-counter"><span aria-hidden="true">%s</span></div>', $warningCount ),
43
  ] );
44
  foreach ( $items as $item ) {
45
- $item[ 'parent' ] = $sNodeId;
46
  $adminBar->add_menu( $item );
47
  }
48
  }
32
  if ( !empty( $items ) && is_array( $items ) ) {
33
  $warningCount = 0;
34
  foreach ( $items as $item ) {
35
+ $warningCount += $item[ 'warnings' ] ?? 0;
36
  }
37
 
38
+ $nodeId = $con->prefix( 'adminbarmenu' );
39
  $adminBar->add_node( [
40
+ 'id' => $nodeId,
41
  'title' => $con->getHumanName()
42
  .sprintf( '<div class="wp-core-ui wp-ui-notification shield-counter"><span aria-hidden="true">%s</span></div>', $warningCount ),
43
  ] );
44
  foreach ( $items as $item ) {
45
+ $item[ 'parent' ] = $nodeId;
46
  $adminBar->add_menu( $item );
47
  }
48
  }
src/lib/src/Controller/Controller.php CHANGED
@@ -17,7 +17,9 @@ use FernleafSystems\Wordpress\Services\Utilities\Options\Transient;
17
  * @property Shield\Controller\Assets\Svgs $svgs
18
  * @property bool $cache_dir_ready
19
  * @property bool $is_activating
20
- * @property bool $is_debug
 
 
21
  * @property bool $is_my_upgrade
22
  * @property bool $modules_loaded
23
  * @property bool $plugin_deactivating
@@ -48,11 +50,6 @@ class Controller extends DynPropertiesClass {
48
  */
49
  protected static $sSessionId;
50
 
51
- /**
52
- * @var string
53
- */
54
- protected static $sRequestId;
55
-
56
  /**
57
  * @var string
58
  */
@@ -166,12 +163,27 @@ class Controller extends DynPropertiesClass {
166
  }
167
  break;
168
 
169
- case 'is_debug':
170
  if ( is_null( $val ) ) {
171
- $val = ( new Shield\Controller\Utilities\DebugMode() )
172
  ->setCon( $this )
173
- ->isDebugMode();
174
- $this->is_debug = $val;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  }
176
  break;
177
 
@@ -541,9 +553,9 @@ class Controller extends DynPropertiesClass {
541
  public function onPluginRowMeta( $pluginMeta, $pluginFile ) {
542
 
543
  if ( $pluginFile === $this->base_file ) {
544
- $sTemplate = '<strong><a href="%s" target="_blank">%s</a></strong>';
545
  foreach ( $this->cfg->plugin_meta as $aHref ) {
546
- array_push( $pluginMeta, sprintf( $sTemplate, $aHref[ 'href' ], $aHref[ 'name' ] ) );
547
  }
548
  }
549
  return $pluginMeta;
@@ -968,13 +980,6 @@ class Controller extends DynPropertiesClass {
968
  return $this->getModule_Plugin()->getUrl_AdminPage();
969
  }
970
 
971
- /**
972
- * @deprecated 12.0
973
- */
974
- public function getPath_ConfigFile( string $slug ) :string {
975
- return $this->paths->forModuleConfig( $slug );
976
- }
977
-
978
  public function getPath_Languages() :string {
979
  return trailingslashit( path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'languages' ) ) );
980
  }
@@ -1105,30 +1110,6 @@ class Controller extends DynPropertiesClass {
1105
  return self::$sSessionId;
1106
  }
1107
 
1108
- /**
1109
- * @param bool $setIfNeeded
1110
- * @return string
1111
- * @deprecated 12.0
1112
- */
1113
- public function getUniqueRequestId( bool $setIfNeeded = false ) :string {
1114
- if ( !isset( self::$sRequestId ) ) {
1115
- self::$sRequestId = md5(
1116
- $this->getSessionId( $setIfNeeded ).Services::IP()->getRequestIp().Services::Request()->ts().wp_rand()
1117
- );
1118
- }
1119
- return self::$sRequestId;
1120
- }
1121
-
1122
- /**
1123
- * @return string
1124
- * @deprecated 12
1125
- */
1126
- public function getShortRequestId() :string {
1127
- $req = Services::Request();
1128
- /** @deprecated 12.0 */
1129
- return substr( method_exists( $req, 'getID' ) ? $req->getID() : $this->getUniqueRequestId(), 0, 10 );
1130
- }
1131
-
1132
  public function hasSessionId() :bool {
1133
  return !empty( $this->getSessionId( false ) );
1134
  }
17
  * @property Shield\Controller\Assets\Svgs $svgs
18
  * @property bool $cache_dir_ready
19
  * @property bool $is_activating
20
+ * @property bool $is_mode_debug
21
+ * @property bool $is_mode_staging
22
+ * @property bool $is_mode_live
23
  * @property bool $is_my_upgrade
24
  * @property bool $modules_loaded
25
  * @property bool $plugin_deactivating
50
  */
51
  protected static $sSessionId;
52
 
 
 
 
 
 
53
  /**
54
  * @var string
55
  */
163
  }
164
  break;
165
 
166
+ case 'is_mode_debug':
167
  if ( is_null( $val ) ) {
168
+ $val = ( new Shield\Controller\Modes\DebugMode() )
169
  ->setCon( $this )
170
+ ->isModeActive();
171
+ $this->is_mode_debug = $val;
172
+ }
173
+ break;
174
+
175
+ case 'is_mode_live':
176
+ if ( is_null( $val ) ) {
177
+ $val = $this->is_mode_live = !$this->is_mode_staging && $this->is_mode_debug;
178
+ }
179
+ break;
180
+
181
+ case 'is_mode_staging':
182
+ if ( is_null( $val ) ) {
183
+ $val = ( new Shield\Controller\Modes\StagingMode() )
184
+ ->setCon( $this )
185
+ ->isModeActive();
186
+ $this->is_mode_staging = $val;
187
  }
188
  break;
189
 
553
  public function onPluginRowMeta( $pluginMeta, $pluginFile ) {
554
 
555
  if ( $pluginFile === $this->base_file ) {
556
+ $template = '<strong><a href="%s" target="_blank">%s</a></strong>';
557
  foreach ( $this->cfg->plugin_meta as $aHref ) {
558
+ array_push( $pluginMeta, sprintf( $template, $aHref[ 'href' ], $aHref[ 'name' ] ) );
559
  }
560
  }
561
  return $pluginMeta;
980
  return $this->getModule_Plugin()->getUrl_AdminPage();
981
  }
982
 
 
 
 
 
 
 
 
983
  public function getPath_Languages() :string {
984
  return trailingslashit( path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'languages' ) ) );
985
  }
1110
  return self::$sSessionId;
1111
  }
1112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1113
  public function hasSessionId() :bool {
1114
  return !empty( $this->getSessionId( false ) );
1115
  }
src/lib/src/Controller/{Utilities/DebugMode.php → Modes/BaseMode.php} RENAMED
@@ -1,14 +1,16 @@
1
  <?php declare( strict_types=1 );
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Controller\Utilities;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
8
- class DebugMode {
9
 
10
  use Shield\Modules\PluginControllerConsumer;
11
 
 
 
12
  public function enableViaFile() :bool {
13
  $FS = Services::WpFs();
14
  if ( !$this->isActiveViaModeFile() ) {
@@ -25,31 +27,34 @@ class DebugMode {
25
  return !$FS->isFile( $this->getPathToModeFile() );
26
  }
27
 
28
- public function isDebugMode() :bool {
29
  return $this->isActiveViaDefine() || $this->isActiveViaModeFile();
30
  }
31
 
32
  public function isActiveViaDefine() :bool {
33
- $constant = strtoupper( $this->getCon()->prefix( 'DEBUG_MODE', '_' ) );
 
 
34
  return defined( $constant ) && $constant;
35
  }
36
 
37
  public function isActiveViaModeFile() :bool {
38
  $con = $this->getCon();
39
  $FS = Services::WpFs();
40
- $correctPath = $con->paths->forFlag( 'mode.debug' );
 
41
 
42
  // We first look for the presence of the file (which may not be named in all lower-case)
43
- $foundFile = $FS->findFileInDir( 'mode.debug', $con->paths->forFlag(), false, false );
44
  if ( !empty( $foundFile )
45
  && $FS->isFile( $foundFile ) && !$FS->isFile( $correctPath )
46
- && !basename( $correctPath ) !== basename( $foundFile ) ) {
47
  $FS->move( $foundFile, $correctPath );
48
  }
49
  return $FS->isFile( $correctPath );
50
  }
51
 
52
- private function getPathToModeFile() :string {
53
- return $this->getCon()->paths->forFlag( 'mode.debug' );
54
  }
55
  }
1
  <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Controller\Modes;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
8
+ abstract class BaseMode {
9
 
10
  use Shield\Modules\PluginControllerConsumer;
11
 
12
+ const SLUG = '';
13
+
14
  public function enableViaFile() :bool {
15
  $FS = Services::WpFs();
16
  if ( !$this->isActiveViaModeFile() ) {
27
  return !$FS->isFile( $this->getPathToModeFile() );
28
  }
29
 
30
+ public function isModeActive() :bool {
31
  return $this->isActiveViaDefine() || $this->isActiveViaModeFile();
32
  }
33
 
34
  public function isActiveViaDefine() :bool {
35
+ $constant = strtoupper(
36
+ $this->getCon()->prefix( sprintf( 'MODE_%s', static::SLUG ), '_' )
37
+ );
38
  return defined( $constant ) && $constant;
39
  }
40
 
41
  public function isActiveViaModeFile() :bool {
42
  $con = $this->getCon();
43
  $FS = Services::WpFs();
44
+ $correctPath = $this->getPathToModeFile();
45
+ $baseFile = basename( $correctPath );
46
 
47
  // We first look for the presence of the file (which may not be named in all lower-case)
48
+ $foundFile = $FS->findFileInDir( $baseFile, $con->paths->forFlag(), false, false );
49
  if ( !empty( $foundFile )
50
  && $FS->isFile( $foundFile ) && !$FS->isFile( $correctPath )
51
+ && basename( $correctPath ) !== basename( $foundFile ) ) {
52
  $FS->move( $foundFile, $correctPath );
53
  }
54
  return $FS->isFile( $correctPath );
55
  }
56
 
57
+ protected function getPathToModeFile() :string {
58
+ return $this->getCon()->paths->forFlag( sprintf( 'mode.%s', strtolower( static::SLUG ) ) );
59
  }
60
  }
src/lib/src/Controller/Modes/DebugMode.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Controller\Modes;
4
+
5
+ class DebugMode extends BaseMode {
6
+
7
+ const SLUG = 'DEBUG';
8
+ }
src/lib/src/Controller/Modes/StagingMode.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Controller\Modes;
4
+
5
+ class StagingMode extends BaseMode {
6
+
7
+ const SLUG = 'STAGING';
8
+ }
src/lib/src/Controller/Plugin/PluginDelete.php CHANGED
@@ -53,6 +53,12 @@ class PluginDelete {
53
  $con->getModule_AuditTrail()->getDbH_Meta(),
54
  $con->getModule_AuditTrail()->getDbH_Logs(),
55
  $con->getModule_Data()->getDbH_ReqLogs(),
 
 
 
 
 
 
56
  $con->getModule_Data()->getDbH_IPs(),
57
  ]
58
  )
53
  $con->getModule_AuditTrail()->getDbH_Meta(),
54
  $con->getModule_AuditTrail()->getDbH_Logs(),
55
  $con->getModule_Data()->getDbH_ReqLogs(),
56
+ $con->getModule_HackGuard()->getDbH_ScanResults(),
57
+ $con->getModule_HackGuard()->getDbH_ResultItemMeta(),
58
+ $con->getModule_HackGuard()->getDbH_ResultItems(),
59
+ $con->getModule_HackGuard()->getDbH_ScanItems(),
60
+ $con->getModule_HackGuard()->getDbH_Scans(),
61
+ $con->getModule_IPs()->getDbH_BotSignal(),
62
  $con->getModule_Data()->getDbH_IPs(),
63
  ]
64
  )
src/lib/src/Crons/BaseCron.php CHANGED
@@ -12,10 +12,7 @@ abstract class BaseCron {
12
  use Shield\Crons\StandardCron;
13
  use PluginControllerConsumer;
14
 
15
- /**
16
- * @deprecated 12 - switch to protected
17
- */
18
- public function run() {
19
  $this->setupCron();
20
  }
21
  }
12
  use Shield\Crons\StandardCron;
13
  use PluginControllerConsumer;
14
 
15
+ protected function run() {
 
 
 
16
  $this->setupCron();
17
  }
18
  }
src/lib/src/Databases/AuditTrail/Delete.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Delete extends Base\Delete {
8
-
9
- }
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/AuditTrail/Insert.php DELETED
@@ -1,31 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
- use FernleafSystems\Wordpress\Services\Services;
7
-
8
- class Insert extends Base\Insert {
9
-
10
- /**
11
- * @return $this
12
- * @throws \Exception
13
- */
14
- protected function verifyInsertData() {
15
- parent::verifyInsertData();
16
-
17
- $data = $this->getInsertData();
18
-
19
- if ( isset( $data[ 'message' ] ) && is_array( $data[ 'message' ] ) ) {
20
- $data[ 'message' ] = implode( ' ', $data[ 'message' ] );
21
- }
22
- if ( isset( $data[ 'data' ] ) && !is_string( $data[ 'data' ] ) ) {
23
- $data[ 'data' ] = '';
24
- }
25
- if ( empty( $data[ 'ip' ] ) || !Services::IP()->isValidIp( $data[ 'ip' ] ) ) {
26
- $data[ 'ip' ] = '';
27
- }
28
-
29
- return $this->setInsertData( $data );
30
- }
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/AuditTrail/Select.php DELETED
@@ -1,89 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
- use FernleafSystems\Wordpress\Services\Services;
7
-
8
- class Select extends Base\Select {
9
-
10
- use Base\Traits\Select_IPTable;
11
-
12
- /**
13
- * @return string[]
14
- */
15
- public function getDistinctEvents() {
16
- return $this->getDistinct_FilterAndSort( 'event' );
17
- }
18
-
19
- /**
20
- * @return string[]
21
- */
22
- public function getDistinctUsernames() {
23
- return $this->getDistinct_FilterAndSort( 'wp_username' );
24
- }
25
-
26
- /**
27
- * @param string $event
28
- * @return $this
29
- */
30
- public function filterByEvent( $event ) {
31
- if ( !empty( $event ) && strtolower( $event ) != 'all' ) {
32
- $this->addWhereEquals( 'event', $event );
33
- }
34
- return $this;
35
- }
36
-
37
- /**
38
- * @param string $ip
39
- * @return $this
40
- */
41
- public function filterByIp( $ip ) {
42
- if ( Services::IP()->isValidIp( $ip ) ) {
43
- $this->addWhereEquals( 'ip', trim( $ip ) );
44
- }
45
- return $this;
46
- }
47
-
48
- /**
49
- * @param int $id
50
- * @return $this
51
- */
52
- public function filterByRequestID( int $id ) {
53
- return $this->addWhereEquals( 'rid', $id );
54
- }
55
-
56
- /**
57
- * @param string $sIp
58
- * @return $this
59
- */
60
- public function filterByNotIp( $sIp ) {
61
- if ( Services::IP()->isValidIp( $sIp ) ) {
62
- $this->addWhere( 'ip', trim( $sIp ), '!=' );
63
- }
64
- return $this;
65
- }
66
-
67
- /**
68
- * @param bool $bIsLoggedIn - true is logged-in, false is not logged-in
69
- * @return $this
70
- */
71
- public function filterByIsLoggedIn( $bIsLoggedIn ) {
72
- if ( $bIsLoggedIn ) {
73
- $this->addWhere( 'wp_username', '', '!=' )
74
- ->addWhere( 'wp_username', 'WP Cron', '!=' ); // special case
75
- }
76
- else {
77
- $this->addWhereEquals( 'wp_username', '' );
78
- }
79
- return $this;
80
- }
81
-
82
- /**
83
- * @param int $sUsername
84
- * @return $this
85
- */
86
- public function filterByUsername( $sUsername ) {
87
- return $this->addWhereEquals( 'wp_username', trim( $sUsername ) );
88
- }
89
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/AuditTrail/Update.php DELETED
@@ -1,17 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
4
-
5
- class Update extends \FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\Update {
6
-
7
- /**
8
- * @param EntryVO $entry
9
- * @param int $increase
10
- * @return bool
11
- */
12
- public function updateCount( $entry, $increase = 1 ) :bool {
13
- return $this->updateEntry( $entry, [
14
- 'count' => $entry->count + $increase,
15
- ] );
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/Base/EntryVO.php CHANGED
@@ -5,8 +5,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
5
  use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
 
7
  /**
8
- * Class BaseEntryVO
9
- *
10
  * @property int $id
11
  * @property array $meta
12
  * @property int $created_at
5
  use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
 
7
  /**
 
 
8
  * @property int $id
9
  * @property array $meta
10
  * @property int $created_at
src/lib/src/Databases/BotSignals/Common.php DELETED
@@ -1,40 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- use FernleafSystems\Wordpress\Services\Services;
6
-
7
- trait Common {
8
-
9
- /**
10
- * COPIED FROM PLUGIN CORE
11
- * @param string $ip
12
- * @return $this
13
- */
14
- public function filterByIPHuman( string $ip ) {
15
- $rightSide = null;
16
- if ( empty( $ip ) ) {
17
- $rightSide = "''";
18
- }
19
- elseif ( Services::IP()->isValidIp( $ip ) || Services::IP()->isValidIp( inet_ntop( $ip ) ) ) {
20
- $rightSide = sprintf( "INET6_ATON('%s')", Services::IP()->isValidIp( $ip ) ? $ip : inet_ntop( $ip ) );
21
- }
22
-
23
- if ( !empty( $rightSide ) ) {
24
- $this->addRawWhere( [ 'ip', '=', $rightSide ] );
25
- }
26
- return $this;
27
- }
28
-
29
- /**
30
- * Will test whether the Binary IP can be converted back before applying filter.
31
- * @param mixed $bBinaryIp - IP has already been converted using inet_pton
32
- * @return $this
33
- */
34
- public function filterByNotIp( $bBinaryIp ) {
35
- if ( inet_ntop( $bBinaryIp ) !== false ) {
36
- $this->addWhere( 'ip', $bBinaryIp, '!=' );
37
- }
38
- return $this;
39
- }
40
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/BotSignals/Delete.php DELETED
@@ -1,10 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Delete extends Base\Delete {
8
-
9
- use Common;
10
- }
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/BotSignals/EntryVO.php DELETED
@@ -1,69 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- /**
6
- * Class EntryVO
7
- * @property string $ip
8
- * @property int $notbot_at
9
- * @property int $frontpage_at
10
- * @property int $loginpage_at
11
- * @property int $bt404_at
12
- * @property int $btcheese_at
13
- * @property int $btfake_at
14
- * @property int $btinvalidscript_at
15
- * @property int $btloginfail_at
16
- * @property int $btlogininvalid_at
17
- * @property int $btua_at
18
- * @property int $btxml_at
19
- * @property int $cooldown_at
20
- * @property int $auth_at
21
- * @property int $offense_at
22
- * @property int $blocked_at
23
- * @property int $unblocked_at
24
- * @property int $bypass_at
25
- * @property int $humanspam_at
26
- * @property int $markspam_at
27
- * @property int $unmarkspam_at
28
- * @property int $captchapass_at
29
- * @property int $captchafail_at
30
- * @property int $ratelimit_at
31
- * @property int $updated_at
32
- * @property int $snsent_at
33
- */
34
- class EntryVO extends \FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\EntryVO {
35
-
36
- /**
37
- * @inheritDoc
38
- */
39
- public function __get( string $key ) {
40
- switch ( $key ) {
41
-
42
- case 'ip':
43
- $value = inet_ntop( parent::__get( $key ) );
44
- break;
45
-
46
- default:
47
- $value = parent::__get( $key );
48
- break;
49
- }
50
- return $value;
51
- }
52
-
53
- /**
54
- * @inheritDoc
55
- */
56
- public function __set( string $key, $value ) {
57
- switch ( $key ) {
58
-
59
- case 'ip':
60
- $value = inet_pton( $value );
61
- break;
62
-
63
- default:
64
- break;
65
- }
66
-
67
- parent::__set( $key, $value );
68
- }
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/BotSignals/Handler.php DELETED
@@ -1,7 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- class Handler extends \FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\Handler {
6
-
7
- }
 
 
 
 
 
 
 
src/lib/src/Databases/BotSignals/Insert.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Insert extends Base\Insert {
8
-
9
- }
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/BotSignals/Select.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Select extends Base\Select {
8
-
9
- use Common;
10
- use Base\Traits\Select_IPTable;
11
- }
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/BotSignals/Update.php DELETED
@@ -1,7 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
4
-
5
- class Update extends \FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\Update {
6
-
7
- }
 
 
 
 
 
 
 
src/lib/src/Databases/FileLocker/Common.php CHANGED
@@ -9,11 +9,11 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\FileLocker;
9
  trait Common {
10
 
11
  /**
12
- * @param string $sFile
13
  * @return $this
14
  */
15
- public function filterByFile( $sFile ) {
16
- return $this->addWhereEquals( 'file', base64_encode( $sFile ) );
17
  }
18
 
19
  /**
9
  trait Common {
10
 
11
  /**
12
+ * @param string $file
13
  * @return $this
14
  */
15
+ public function filterByFile( $file ) {
16
+ return $this->addWhereEquals( 'file', base64_encode( $file ) );
17
  }
18
 
19
  /**
src/lib/src/Databases/Scanner/EntryVO.php CHANGED
@@ -5,14 +5,13 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner;
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
 
7
  /**
8
- * Class EntryVO
9
  * @property string $hash
10
  * @property array $meta
11
  * @property string $scan
12
  * @property int $severity
13
- * @property int $discovered_at
14
  * @property int $ignored_at
15
  * @property int $notified_at
 
16
  */
17
  class EntryVO extends Base\EntryVO {
18
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
 
7
  /**
 
8
  * @property string $hash
9
  * @property array $meta
10
  * @property string $scan
11
  * @property int $severity
 
12
  * @property int $ignored_at
13
  * @property int $notified_at
14
+ * @property int $attempt_repair_at
15
  */
16
  class EntryVO extends Base\EntryVO {
17
 
src/lib/src/Databases/Scanner/Select.php CHANGED
@@ -24,21 +24,4 @@ class Select extends Base\Select {
24
  }
25
  return $counts;
26
  }
27
-
28
- public function countForScan( string $scan ) :int {
29
- return $this->reset()
30
- ->filterByNotIgnored()
31
- ->filterByScan( $scan )
32
- ->count();
33
- }
34
-
35
- /**
36
- * @param string $scan
37
- * @return EntryVO[]
38
- */
39
- public function forScan( $scan ) {
40
- return $this->reset()
41
- ->filterByScan( $scan )
42
- ->query();
43
- }
44
  }
24
  }
25
  return $counts;
26
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
src/lib/src/Databases/Traffic/BaseTraffic.php DELETED
@@ -1,82 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
-
5
- trait BaseTraffic {
6
-
7
- /**
8
- * Will test whether the Binary IP can be converted back before applying filter.
9
- * @param mixed $binaryIP - IP has already been converted using inet_pton
10
- * @return $this
11
- */
12
- public function filterByIp( $binaryIP ) {
13
- if ( inet_ntop( $binaryIP ) !== false ) {
14
- $this->addWhereEquals( 'ip', $binaryIP );
15
- }
16
- return $this;
17
- }
18
-
19
- /**
20
- * Will test whether the Binary IP can be converted back before applying filter.
21
- * @param mixed $bBinaryIp - IP has already been converted using inet_pton
22
- * @return $this
23
- */
24
- public function filterByNotIp( $bBinaryIp ) {
25
- if ( inet_ntop( $bBinaryIp ) !== false ) {
26
- $this->addWhere( 'ip', $bBinaryIp, '!=' );
27
- }
28
- return $this;
29
- }
30
-
31
- /**
32
- * @param bool $bIsLoggedIn - true is logged-in, false is not logged-in
33
- * @return $this
34
- */
35
- public function filterByIsLoggedIn( $bIsLoggedIn ) {
36
- return $this->addWhere( 'uid', 0, $bIsLoggedIn ? '>' : '=' );
37
- }
38
-
39
- /**
40
- * @param bool $bIsTransgression
41
- * @return $this
42
- */
43
- public function filterByIsTransgression( $bIsTransgression ) {
44
- return $this->addWhereEquals( 'trans', $bIsTransgression ? 1 : 0 );
45
- }
46
-
47
- /**
48
- * @param string $sTerm
49
- * @return $this
50
- */
51
- public function filterByPathContains( $sTerm ) {
52
- if ( !empty( $sTerm ) ) {
53
- $this->addWhereSearch( 'path', $sTerm );
54
- }
55
- return $this;
56
- }
57
-
58
- /**
59
- * @param int $nId
60
- * @return $this
61
- */
62
- public function filterByUserId( $nId ) {
63
- if ( $nId > 0 ) {
64
- $this->addWhereEquals( 'uid', (int)$nId );
65
- }
66
- return $this;
67
- }
68
-
69
- /**
70
- * @param string $sCode
71
- * @return $this
72
- */
73
- public function filterByResponseCode( $sCode ) {
74
- if ( is_numeric( $sCode ) ) {
75
- $sCode = (string)$sCode;
76
- if ( $sCode === '0' || preg_match( '#^[0-5]{1}[0-9]{2}$#', $sCode ) ) {
77
- $this->addWhereEquals( 'code', $sCode );
78
- }
79
- }
80
- return $this;
81
- }
82
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/Traffic/Delete.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Delete extends Base\Delete {
8
-
9
- use BaseTraffic;
10
- }
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/Traffic/EntryVO.php DELETED
@@ -1,55 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- /**
8
- * Class EntryVO
9
- * @property string $rid
10
- * @property int $uid
11
- * @property string $ip
12
- * @property string $path
13
- * @property string $code
14
- * @property string $ua
15
- * @property string $verb
16
- * @property bool $trans
17
- */
18
- class EntryVO extends Base\EntryVO {
19
-
20
- /**
21
- * @param string $key
22
- * @return mixed
23
- */
24
- public function __get( string $key ) {
25
- switch ( $key ) {
26
-
27
- case 'ip':
28
- $value = inet_ntop( parent::__get( $key ) );
29
- break;
30
-
31
- default:
32
- $value = parent::__get( $key );
33
- break;
34
- }
35
- return $value;
36
- }
37
-
38
- /**
39
- * @inheritDoc
40
- */
41
- public function __set( string $key, $value ) {
42
-
43
- switch ( $key ) {
44
-
45
- case 'ip':
46
- $value = inet_pton( $value );
47
- break;
48
-
49
- default:
50
- break;
51
- }
52
-
53
- parent::__set( $key, $value );
54
- }
55
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/Traffic/Handler.php DELETED
@@ -1,9 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Handler extends Base\Handler {
8
-
9
- }
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/Traffic/Insert.php DELETED
@@ -1,23 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
-
7
- class Insert extends Base\Insert {
8
-
9
- /**
10
- * @return $this
11
- * @throws \Exception
12
- */
13
- protected function verifyInsertData() {
14
- parent::verifyInsertData();
15
-
16
- $data = $this->getInsertData();
17
- if ( empty( $data[ 'ip' ] ) ) {
18
- throw new \Exception( 'IP address provided is not valid' );
19
- }
20
-
21
- return $this->setInsertData( $data );
22
- }
23
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Databases/Traffic/Select.php DELETED
@@ -1,42 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool\IpListSort;
7
- use FernleafSystems\Wordpress\Services\Services;
8
-
9
- class Select extends Base\Select {
10
-
11
- use BaseTraffic;
12
- use Base\Traits\Select_IPTable;
13
-
14
- /**
15
- * @return string[]
16
- */
17
- public function getDistinctCodes() {
18
- return $this->getDistinct_FilterAndSort( 'code' );
19
- }
20
-
21
- /**
22
- * @return string[]
23
- */
24
- public function getDistinctUserIds() {
25
- return $this->getDistinct_FilterAndSort( 'uid' );
26
- }
27
-
28
- /**
29
- * @return string[]
30
- */
31
- public function getDistinctUsernames() {
32
- $a = array_filter( array_map(
33
- function ( $nId ) {
34
- $oUser = Services::WpUsers()->getUserById( $nId );
35
- return ( $oUser instanceof \WP_User ) ? $oUser->user_login : null;
36
- },
37
- $this->getDistinctUserIds()
38
- ) );
39
- asort( $a );
40
- return $a;
41
- }
42
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Logging/Processors/RequestMetaProcessor.php CHANGED
@@ -1,15 +1,13 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Logging\Processors;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
6
  use FernleafSystems\Wordpress\Services\Services;
7
  use Monolog\Processor\ProcessorInterface;
8
 
9
  class RequestMetaProcessor implements ProcessorInterface {
10
 
11
  /**
12
- * @param array $record
13
  * @return array
14
  */
15
  public function __invoke( array $record ) {
@@ -18,13 +16,21 @@ class RequestMetaProcessor implements ProcessorInterface {
18
  $req = Services::Request();
19
  $leadingPath = Services::WpGeneral()->isMultisite_SubdomainInstall() ? $req->getHost() : '';
20
 
 
 
 
 
 
 
 
 
21
  $record[ 'extra' ][ 'meta_request' ] = [
22
  'ip' => $isWpCli ? '' : (string)Services::IP()->getRequestIp(),
23
  'rid' => Services::Request()->getID( true, 10 ),
24
  'ts' => microtime( true ),
25
  'ua' => $isWpCli ? 'wpcli' : $req->getUserAgent(),
26
  'verb' => $isWpCli ? '' : strtoupper( $req->getMethod() ),
27
- 'path' => $isWpCli ? '' : ( $leadingPath.$req->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) ) ),
28
  'code' => $isWpCli ? '' : http_response_code(),
29
  ];
30
 
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Logging\Processors;
4
 
 
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use Monolog\Processor\ProcessorInterface;
7
 
8
  class RequestMetaProcessor implements ProcessorInterface {
9
 
10
  /**
 
11
  * @return array
12
  */
13
  public function __invoke( array $record ) {
16
  $req = Services::Request();
17
  $leadingPath = Services::WpGeneral()->isMultisite_SubdomainInstall() ? $req->getHost() : '';
18
 
19
+ if ( $isWpCli ) {
20
+ global $argv;
21
+ $path = implode( ' ', $argv );
22
+ }
23
+ else {
24
+ $path = ( $leadingPath.$req->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) ) );
25
+ }
26
+
27
  $record[ 'extra' ][ 'meta_request' ] = [
28
  'ip' => $isWpCli ? '' : (string)Services::IP()->getRequestIp(),
29
  'rid' => Services::Request()->getID( true, 10 ),
30
  'ts' => microtime( true ),
31
  'ua' => $isWpCli ? 'wpcli' : $req->getUserAgent(),
32
  'verb' => $isWpCli ? '' : strtoupper( $req->getMethod() ),
33
+ 'path' => $path,
34
  'code' => $isWpCli ? '' : http_response_code(),
35
  ];
36
 
src/lib/src/Modules/AuditTrail/Auditors/Emails.php CHANGED
@@ -29,23 +29,23 @@ class Emails extends Base {
29
  ];
30
 
31
  // Attempt to capture BCC/CC
32
- $aCCs = [];
33
  if ( !empty( $email[ 'headers' ] ) ) {
34
- $aHeaders = $email[ 'headers' ];
35
- if ( is_string( $aHeaders ) ) {
36
- $aHeaders = explode( "\n", $aHeaders );
37
  }
38
- if ( is_array( $aHeaders ) ) {
39
- $aCCs = $this->extractCcFromHeaders( $aHeaders );
40
  }
41
  }
42
- $auditData[ 'cc' ] = empty( $aCCs[ 'cc' ] ) ? '-' : implode( ',', $aCCs[ 'cc' ] );
43
- $auditData[ 'bcc' ] = empty( $aCCs[ 'bcc' ] ) ? '-' : implode( ',', $aCCs[ 'bcc' ] );
44
 
45
  // Where was the wp_mail function called from
46
- $aBacktrace = $this->findEmailSenderBacktrace();
47
- $auditData[ 'bt_file' ] = empty( $aBacktrace[ 'file' ] ) ? 'unavailable' : str_replace( ABSPATH, '', $aBacktrace[ 'file' ] );
48
- $auditData[ 'bt_line' ] = empty( $aBacktrace[ 'line' ] ) ? 'unavailable' : $aBacktrace[ 'line' ];
49
 
50
  $this->getCon()->fireEvent( 'email_attempt_send', [ 'audit_params' => $auditData ] );
51
  }
@@ -53,52 +53,46 @@ class Emails extends Base {
53
  return $email;
54
  }
55
 
56
- /**
57
- * @param array $aHeaders
58
- * @return array
59
- */
60
- private function extractCcFromHeaders( $aHeaders ) {
61
- $aCCs = [
62
  'bcc' => [],
63
  'cc' => []
64
  ];
65
 
66
- $aHeaders = array_filter( array_map( 'trim', array_map( 'strtolower', $aHeaders ) ) );
67
- foreach ( $aHeaders as $sHeader ) {
68
- if ( preg_match( '#^\s*b?cc\s*:.+#i', $sHeader ) ) {
69
- list( $sHead, $sEmails ) = explode( ':', str_replace( ' ', '', $sHeader ), 2 );
70
- if ( strpos( ',', $sEmails ) !== false ) {
71
- $aEmails = explode( ',', $sEmails );
72
- }
73
- else {
74
- $aEmails = [ $sEmails ];
75
- }
76
 
77
- if ( isset( $aCCs[ $sHead ] ) ) {
78
- $aCCs[ $sHead ][] = array_unique( array_merge(
79
- $aCCs[ $sHead ],
80
- array_filter( $aEmails,
81
- function ( $sEmail ) {
82
- return Services::Data()->validEmail( $sEmail );
83
- } )
84
- ) );
85
  }
 
 
 
 
86
  }
87
  }
88
- return $aCCs;
89
  }
90
 
91
- /**
92
- * @return array
93
- */
94
- private function findEmailSenderBacktrace() {
95
- $aBT = [];
96
- foreach ( debug_backtrace( false ) as $aItem ) {
97
- if ( isset( $aItem[ 'function' ] ) && 'wp_mail' === strtolower( $aItem[ 'function' ] ) ) {
98
- $aBT = $aItem;
99
  break;
100
  }
101
  }
102
- return $aBT;
103
  }
104
  }
29
  ];
30
 
31
  // Attempt to capture BCC/CC
32
+ $CCs = [];
33
  if ( !empty( $email[ 'headers' ] ) ) {
34
+ $headers = $email[ 'headers' ];
35
+ if ( is_string( $headers ) ) {
36
+ $headers = explode( "\n", $headers );
37
  }
38
+ if ( is_array( $headers ) ) {
39
+ $CCs = $this->extractCcFromHeaders( $headers );
40
  }
41
  }
42
+ $auditData[ 'cc' ] = empty( $CCs[ 'cc' ] ) ? '-' : implode( ', ', $CCs[ 'cc' ] );
43
+ $auditData[ 'bcc' ] = empty( $CCs[ 'bcc' ] ) ? '-' : implode( ', ', $CCs[ 'bcc' ] );
44
 
45
  // Where was the wp_mail function called from
46
+ $backtrace = $this->findEmailSenderBacktrace();
47
+ $auditData[ 'bt_file' ] = empty( $backtrace[ 'file' ] ) ? 'unavailable' : str_replace( ABSPATH, '', $backtrace[ 'file' ] );
48
+ $auditData[ 'bt_line' ] = empty( $backtrace[ 'line' ] ) ? 'unavailable' : $backtrace[ 'line' ];
49
 
50
  $this->getCon()->fireEvent( 'email_attempt_send', [ 'audit_params' => $auditData ] );
51
  }
53
  return $email;
54
  }
55
 
56
+ private function extractCcFromHeaders( array $headers ) :array {
57
+ $CCs = [
 
 
 
 
58
  'bcc' => [],
59
  'cc' => []
60
  ];
61
 
62
+ $headers = array_filter(
63
+ array_map( function ( $header ) {
64
+ return str_replace( ' ', '', trim( strtolower( $header ) ) );
65
+ }, $headers ),
66
+ function ( $header ) {
67
+ return !empty( $header ) && preg_match( '#^\s*b?cc\s*:.+$#i', $header );
68
+ }
69
+ );
 
 
70
 
71
+ foreach ( $headers as $header ) {
72
+ list( $headerKey, $emails ) = explode( ':', $header, 2 );
73
+
74
+ $emails = array_filter(
75
+ array_map( 'trim', explode( ',', $emails ) ),
76
+ function ( $email ) {
77
+ return Services::Data()->validEmail( $email );
 
78
  }
79
+ );
80
+
81
+ if ( isset( $CCs[ $headerKey ] ) ) {
82
+ $CCs[ $headerKey ] = array_unique( array_merge( $CCs[ $headerKey ], $emails ) );
83
  }
84
  }
85
+ return $CCs;
86
  }
87
 
88
+ private function findEmailSenderBacktrace() :array {
89
+ $backtrace = [];
90
+ foreach ( debug_backtrace( false ) as $item ) {
91
+ if ( isset( $item[ 'function' ] ) && 'wp_mail' === strtolower( $item[ 'function' ] ) ) {
92
+ $backtrace = $item;
 
 
 
93
  break;
94
  }
95
  }
96
+ return $backtrace;
97
  }
98
  }
src/lib/src/Modules/AuditTrail/Auditors/Plugins.php CHANGED
@@ -1,13 +1,15 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Auditors;
4
 
 
 
5
  class Plugins extends Base {
6
 
7
  protected function run() {
8
  add_action( 'deactivated_plugin', [ $this, 'auditDeactivatedPlugin' ] );
9
  add_action( 'activated_plugin', [ $this, 'auditActivatedPlugin' ] );
10
- add_action( 'check_admin_referer', [ $this, 'auditEditedFile' ], 10, 2 );
11
  }
12
 
13
  /**
@@ -34,16 +36,12 @@ class Plugins extends Base {
34
  }
35
  }
36
 
37
- /**
38
- * @param string $sAction
39
- * @param bool $bResult
40
- */
41
- public function auditEditedFile( $sAction, $bResult ) {
42
- $sStub = 'edit-plugin_';
43
- if ( strpos( $sAction, $sStub ) === 0 ) {
44
  $this->getCon()->fireEvent(
45
  'plugin_file_edited',
46
- [ 'audit_params' => [ 'file' => str_replace( $sStub, '', $sAction ) ] ]
47
  );
48
  }
49
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Auditors;
4
 
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
  class Plugins extends Base {
8
 
9
  protected function run() {
10
  add_action( 'deactivated_plugin', [ $this, 'auditDeactivatedPlugin' ] );
11
  add_action( 'activated_plugin', [ $this, 'auditActivatedPlugin' ] );
12
+ add_action( 'wp_ajax_edit-theme-plugin-file', [ $this, 'auditEditedFile' ], -1 ); // they hook on 1
13
  }
14
 
15
  /**
36
  }
37
  }
38
 
39
+ public function auditEditedFile() {
40
+ $req = Services::Request();
41
+ if ( !empty( $req->post( 'plugin' ) ) ) {
 
 
 
 
42
  $this->getCon()->fireEvent(
43
  'plugin_file_edited',
44
+ [ 'audit_params' => [ 'file' => sanitize_text_field( $req->post( 'file' ) ) ] ]
45
  );
46
  }
47
  }
src/lib/src/Modules/AuditTrail/Auditors/Themes.php CHANGED
@@ -1,12 +1,14 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Auditors;
4
 
 
 
5
  class Themes extends Base {
6
 
7
  protected function run() {
8
  add_action( 'switch_theme', [ $this, 'auditSwitchTheme' ] );
9
- add_action( 'check_admin_referer', [ $this, 'auditEditedThemeFile' ] );
10
  }
11
 
12
  /**
@@ -21,15 +23,12 @@ class Themes extends Base {
21
  }
22
  }
23
 
24
- /**
25
- * @param string $action
26
- */
27
- public function auditEditedThemeFile( $action ) {
28
- $stub = 'edit-theme_';
29
- if ( strpos( $action, $stub ) === 0 ) {
30
  $this->getCon()->fireEvent(
31
  'theme_file_edited',
32
- [ 'audit_params' => [ 'file' => str_replace( $stub, '', $action ) ] ]
33
  );
34
  }
35
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Auditors;
4
 
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
  class Themes extends Base {
8
 
9
  protected function run() {
10
  add_action( 'switch_theme', [ $this, 'auditSwitchTheme' ] );
11
+ add_action( 'wp_ajax_edit-theme-plugin-file', [ $this, 'auditEditedFile' ], -1 ); // they hook on 1
12
  }
13
 
14
  /**
23
  }
24
  }
25
 
26
+ public function auditEditedFile() {
27
+ $req = Services::Request();
28
+ if ( !empty( $req->post( 'theme' ) ) ) {
 
 
 
29
  $this->getCon()->fireEvent(
30
  'theme_file_edited',
31
+ [ 'audit_params' => [ 'file' => sanitize_text_field( $req->post( 'file' ) ) ] ]
32
  );
33
  }
34
  }
src/lib/src/Modules/AuditTrail/Lib/AuditLogger.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib;
4
 
@@ -63,12 +63,7 @@ class AuditLogger extends EventsListener {
63
  return $this->logger;
64
  }
65
 
66
- /**
67
- * @param string $evt
68
- * @param array $meta
69
- * @param array $def
70
- */
71
- protected function captureEvent( string $evt, $meta = [], $def = [] ) {
72
 
73
  $meta = apply_filters( 'shield/audit_event_meta', $meta, $evt );
74
 
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib;
4
 
63
  return $this->logger;
64
  }
65
 
66
+ protected function captureEvent( string $evt, array $meta = [], array $def = [] ) {
 
 
 
 
 
67
 
68
  $meta = apply_filters( 'shield/audit_event_meta', $meta, $evt );
69
 
src/lib/src/Modules/AuditTrail/Lib/AuditWriter.php DELETED
@@ -1,72 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\HandlerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\Ops\Commit;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Events\Lib\EventsListener;
9
-
10
- /**
11
- * @deprecated 12.0
12
- */
13
- class AuditWriter extends EventsListener {
14
-
15
- use HandlerConsumer;
16
-
17
- /**
18
- * @var AuditTrail\EntryVO[]
19
- */
20
- private $aAuditLogs;
21
-
22
- /**
23
- * @param string $evt
24
- * @param array $meta
25
- * @param array $def
26
- */
27
- protected function captureEvent( string $evt, $meta = [], $def = [] ) {
28
- $con = $this->getCon();
29
-
30
- $meta = apply_filters( 'shield/audit_event_meta', $meta, $evt );
31
-
32
- if ( $def[ 'audit' ] && empty( $meta[ 'suppress_audit' ] ) ) { // only audit if it's an auditable event
33
- $entry = new AuditTrail\EntryVO();
34
- $entry->rid = $con->getShortRequestId();
35
- $entry->event = $evt;
36
- $entry->category = 1;
37
- $entry->context = $def[ 'context' ];
38
- $entry->meta = $meta[ 'audit' ] ?? [];
39
-
40
- $logs = $this->getLogs();
41
-
42
- // cater for where certain events may happen more than once in the same request
43
- if ( !empty( $def[ 'audit_multiple' ] ) ) {
44
- $logs[] = $entry;
45
- }
46
- else {
47
- $logs[ $evt ] = $entry;
48
- }
49
-
50
- $this->setLogs( $logs );
51
- }
52
- }
53
-
54
- protected function onShutdown() {
55
- }
56
-
57
- /**
58
- * @return AuditTrail\EntryVO[]
59
- */
60
- public function getLogs() :array {
61
- return is_array( $this->aAuditLogs ) ? $this->aAuditLogs : [];
62
- }
63
-
64
- /**
65
- * @param AuditTrail\EntryVO[] $logs
66
- * @return $this
67
- */
68
- public function setLogs( array $logs = [] ) {
69
- $this->aAuditLogs = $logs;
70
- return $this;
71
- }
72
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/AuditTrail/Lib/LogTable/LoadRawTableData.php CHANGED
@@ -5,8 +5,6 @@ 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\Modules\AuditTrail\Lib\Ops\ConvertLegacy;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseLoadTableData;
11
  use FernleafSystems\Wordpress\Services\Services;
12
 
@@ -18,13 +16,6 @@ class LoadRawTableData extends BaseLoadTableData {
18
  private $log;
19
 
20
  public function loadForLogs() :array {
21
- ( new Traffic\Lib\Ops\ConvertLegacy() )
22
- ->setMod( $this->getCon()->getModule_Traffic() )
23
- ->run();
24
- ( new ConvertLegacy() )
25
- ->setMod( $this->getMod() )
26
- ->run();
27
-
28
  $srvEvents = $this->getCon()->loadEventsService();
29
  return array_values( array_map(
30
  function ( $log ) use ( $srvEvents ) {
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\LoadData\BaseLoadTableData;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
16
  private $log;
17
 
18
  public function loadForLogs() :array {
 
 
 
 
 
 
 
19
  $srvEvents = $this->getCon()->loadEventsService();
20
  return array_values( array_map(
21
  function ( $log ) use ( $srvEvents ) {
src/lib/src/Modules/AuditTrail/Lib/Ops/Commit.php DELETED
@@ -1,81 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\Ops;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\HandlerConsumer;
7
- use FernleafSystems\Wordpress\Services\Services;
8
-
9
- class Commit {
10
-
11
- use HandlerConsumer;
12
-
13
- /**
14
- * @param AuditTrail\EntryVO[] $events
15
- */
16
- public function commitAudits( array $events ) {
17
- if ( is_array( $events ) ) {
18
- foreach ( $events as $entry ) {
19
- if ( $entry instanceof AuditTrail\EntryVO ) {
20
- $this->commitAudit( $entry );
21
- }
22
- }
23
- }
24
- }
25
-
26
- public function commitAudit( AuditTrail\EntryVO $entry ) {
27
- $WP = Services::WpGeneral();
28
- $WPU = Services::WpUsers();
29
-
30
- if ( empty( $entry->ip ) ) {
31
- $entry->ip = Services::IP()->getRequestIp();
32
- }
33
- if ( empty( $entry->wp_username ) ) {
34
- if ( $WPU->isUserLoggedIn() ) {
35
- $sUser = $WPU->getCurrentWpUsername();
36
- }
37
- elseif ( $WP->isCron() ) {
38
- $sUser = 'WP Cron';
39
- }
40
- elseif ( $WP->isWpCli() ) {
41
- $sUser = 'WP CLI';
42
- }
43
- else {
44
- $sUser = '-';
45
- }
46
- $entry->wp_username = $sUser;
47
- }
48
-
49
- $latest = null;
50
- $canCount = in_array( $entry->event, $this->getCanCountEvents() );
51
- if ( $canCount ) {
52
- /** @var AuditTrail\Select $select */
53
- $select = $this->getDbHandler()->getQuerySelector();
54
- $latest = $select->filterByEvent( $entry->event )
55
- ->filterByIp( $entry->ip )
56
- ->filterByCreatedAt( Services::Request()->carbon()->subDay()->timestamp, '>' )
57
- ->first();
58
- $canCount = ( $latest instanceof AuditTrail\EntryVO )
59
- && ( $latest->ip === $entry->ip );
60
- }
61
-
62
- if ( $canCount ) {
63
- /** @var AuditTrail\Update $updater */
64
- $updater = $this->getDbHandler()->getQueryUpdater();
65
- $updater->updateCount( $latest );
66
- }
67
- else {
68
- /** @var AuditTrail\Insert $inserter */
69
- $inserter = $this->getDbHandler()->getQueryInserter();
70
- $inserter->insert( $entry );
71
- }
72
- }
73
-
74
- /**
75
- * TODO: This should be a config
76
- * @return string[]
77
- */
78
- private function getCanCountEvents() :array {
79
- return [ 'conn_kill' ];
80
- }
81
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/AuditTrail/Lib/Ops/ConvertLegacy.php DELETED
@@ -1,146 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\Ops;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\AuditTrail;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\ModCon;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\IPs\IPRecords;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\RequestRecords;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\DB\{
10
- Logs,
11
- Meta
12
- };
13
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
14
- use FernleafSystems\Wordpress\Services\Services;
15
-
16
- class ConvertLegacy {
17
-
18
- use ModConsumer;
19
-
20
- public function run() {
21
- /** @var ModCon $mod */
22
- $mod = $this->getMod();
23
- $opts = $this->getOptions();
24
-
25
- if ( empty( $opts->getOpt( 'legacy_db_deleted_at' ) ) ) {
26
- $this->convert();
27
- $dbh = $mod->getDbHandler_AuditTrail();
28
- if ( $dbh->getQuerySelector()->count() === 0 ) {
29
- $opts->setOpt( 'legacy_db_deleted_at', Services::Request()->ts() );
30
- $dbh->tableDelete();
31
- }
32
- }
33
- }
34
-
35
- private function convert() {
36
- /** @var ModCon $mod */
37
- $mod = $this->getMod();
38
- $dbh = $mod->getDbHandler_AuditTrail();
39
-
40
- $metaInserter = $mod->getDbH_Meta()->getQueryInserter();
41
-
42
- $toDelete = [];
43
-
44
- /** @var AuditTrail\EntryVO $entry */
45
- foreach ( $dbh->getIterator() as $entry ) {
46
-
47
- try {
48
- $log = $this->createPrimaryLogRecord( $entry );
49
-
50
- $metaRecord = new Meta\Ops\Record();
51
- $metaRecord->log_ref = $log->id;
52
-
53
- $uid = '';
54
- if ( $entry->wp_username === 'WP Cron' ) {
55
- $uid = 'cron';
56
- }
57
- elseif ( $entry->wp_username === 'WP CLI' ) {
58
- $uid = 'cli';
59
- }
60
- elseif ( $entry->wp_username !== '-' ) {
61
- $user = Services::WpUsers()->getUserByUsername( $entry->wp_username );
62
- if ( $user instanceof \WP_User ) {
63
- $uid = $user->ID;
64
- }
65
- }
66
-
67
- if ( !empty( $uid ) ) {
68
- $metaRecord->meta_key = 'uid';
69
- $metaRecord->meta_value = $uid;
70
- $metaInserter->insert( $metaRecord );
71
- }
72
-
73
- foreach ( $entry->meta as $metaKey => $metaValue ) {
74
- if ( $metaKey == 'user' ) {
75
- $metaKey = 'user_login';
76
- }
77
- $metaRecord->meta_key = $metaKey;
78
- $metaRecord->meta_value = $metaValue;
79
- $mod->getDbH_Meta()
80
- ->getQueryInserter()
81
- ->insert( $metaRecord );
82
- }
83
- }
84
- catch ( \Exception $e ) {
85
- }
86
- finally {
87
- $toDelete[] = $entry->id;
88
- }
89
- }
90
-
91
- if ( !empty( $toDelete ) ) {
92
- $dbh->getQueryDeleter()
93
- ->addWhereIn( 'in', $toDelete )
94
- ->query();
95
- }
96
- // TODO: set hidden marker to say completed and delete table
97
- }
98
-
99
- /**
100
- * @param AuditTrail\EntryVO $entry
101
- * @return Logs\Ops\Record
102
- * @throws \Exception
103
- */
104
- protected function createPrimaryLogRecord( AuditTrail\EntryVO $entry ) :Logs\Ops\Record {
105
- /** @var ModCon $mod */
106
- $mod = $this->getMod();
107
-
108
- if ( empty( $entry->rid ) || empty( $entry->ip ) ) {
109
- throw new \Exception( 'No RID or IP' );
110
- }
111
-
112
- if ( !$this->getCon()->loadEventsService()->eventExists( (string)$entry->event ) ) {
113
- throw new \Exception( 'Not a supported event' );
114
- }
115
-
116
- $record = new Logs\Ops\Record();
117
- $record->event_slug = $entry->event;
118
- $record->site_id = 1;
119
- $record->created_at = $entry->created_at;
120
-
121
- $ipID = ( new IPRecords() )
122
- ->setMod( $this->getCon()->getModule_Data() )
123
- ->loadIP( $entry->ip )
124
- ->id;
125
- $record->req_ref = ( new RequestRecords() )
126
- ->setMod( $this->getCon()->getModule_Data() )
127
- ->loadReq( $entry->rid, $ipID )
128
- ->id;
129
-
130
- $success = $mod->getDbH_Logs()
131
- ->getQueryInserter()
132
- ->insert( $record );
133
- if ( !$success ) {
134
- throw new \Exception( 'Failed to insert' );
135
- }
136
-
137
- /** @var Logs\Ops\Record $log */
138
- $log = $mod->getDbH_Logs()
139
- ->getQuerySelector()
140
- ->byId( Services::WpDb()->getVar( 'SELECT LAST_INSERT_ID()' ) );
141
- if ( empty( $log ) ) {
142
- throw new \Exception( 'Could not load log record' );
143
- }
144
- return $log;
145
- }
146
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/AuditTrail/ModCon.php CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool\DbTableExport;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class ModCon extends BaseShield\ModCon {
@@ -25,7 +24,7 @@ class ModCon extends BaseShield\ModCon {
25
  }
26
 
27
  /**
28
- * @deprecated 12.0
29
  */
30
  public function getDbHandler_AuditTrail() :Shield\Databases\AuditTrail\Handler {
31
  return $this->getDbH( 'audit_trail' );
@@ -139,34 +138,11 @@ class ModCon extends BaseShield\ModCon {
139
  return $data;
140
  }
141
 
142
- /**
143
- * @return array
144
- * @deprecated 12.0 (Shield Central?)
145
- */
146
- public function getAllContexts() {
147
- return [
148
- 'all' => 'All', //special
149
- 'wpsf' => $this->getCon()->getHumanName(),
150
- 'wordpress' => 'WordPress',
151
- 'users' => 'Users',
152
- 'posts' => 'Posts',
153
- 'plugins' => 'Plugins',
154
- 'themes' => 'Themes',
155
- 'emails' => 'Emails',
156
- ];
157
- }
158
-
159
  /**
160
  * @inheritDoc
161
- * @deprecated 12.0
162
  */
163
  public function getDbHandlers( $bInitAll = false ) {
164
  return [];
165
  }
166
-
167
- /**
168
- * @deprecated 12.0
169
- */
170
- protected function cleanupDatabases() {
171
- }
172
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
 
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class ModCon extends BaseShield\ModCon {
24
  }
25
 
26
  /**
27
+ * @deprecated 12.1
28
  */
29
  public function getDbHandler_AuditTrail() :Shield\Databases\AuditTrail\Handler {
30
  return $this->getDbH( 'audit_trail' );
138
  return $data;
139
  }
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  /**
142
  * @inheritDoc
143
+ * @deprecated 13.0
144
  */
145
  public function getDbHandlers( $bInitAll = false ) {
146
  return [];
147
  }
 
 
 
 
 
 
148
  }
src/lib/src/Modules/AuditTrail/Options.php CHANGED
@@ -69,11 +69,4 @@ class Options extends BaseShield\Options {
69
  return !in_array( 'disabled', $this->getLogLevelsFile() )
70
  && !empty( $this->getLogFilePath() );
71
  }
72
-
73
- /**
74
- * @deprecated 12.0
75
- */
76
- public function getMaxEntries() :int {
77
- return PHP_INT_MAX;
78
- }
79
  }
69
  return !in_array( 'disabled', $this->getLogLevelsFile() )
70
  && !empty( $this->getLogFilePath() );
71
  }
 
 
 
 
 
 
 
72
  }
src/lib/src/Modules/AuditTrail/Processor.php CHANGED
@@ -8,30 +8,11 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
8
 
9
  class Processor extends BaseShield\Processor {
10
 
11
- /**
12
- * @var Lib\AuditWriter
13
- */
14
- private $auditWriter;
15
-
16
  protected function run() {
17
  $this->initAuditors();
18
  $this->getSubProAuditor()->execute();
19
  }
20
 
21
- /**
22
- * @return Lib\AuditWriter
23
- * @deprecated 12.0
24
- */
25
- private function loadAuditorWriter() :Lib\AuditWriter {
26
- if ( !isset( $this->auditWriter ) ) {
27
- /** @var ModCon $mod */
28
- $mod = $this->getMod();
29
- $this->auditWriter = ( new Lib\AuditWriter( $this->getCon() ) )
30
- ->setDbHandler( $mod->getDbHandler_AuditTrail() );
31
- }
32
- return $this->auditWriter;
33
- }
34
-
35
  private function initAuditors() {
36
  /** @var ModCon $mod */
37
  $mod = $this->getMod();
8
 
9
  class Processor extends BaseShield\Processor {
10
 
 
 
 
 
 
11
  protected function run() {
12
  $this->initAuditors();
13
  $this->getSubProAuditor()->execute();
14
  }
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  private function initAuditors() {
17
  /** @var ModCon $mod */
18
  $mod = $this->getMod();
src/lib/src/Modules/AuditTrail/Upgrade.php CHANGED
@@ -4,9 +4,4 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail;
4
 
5
  class Upgrade extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Upgrade {
6
 
7
- protected function upgrade_1200() {
8
- ( new Lib\Ops\ConvertLegacy() )
9
- ->setMod( $this->getMod() )
10
- ->run();
11
- }
12
  }
4
 
5
  class Upgrade extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Upgrade {
6
 
 
 
 
 
 
7
  }
src/lib/src/Modules/Base/ModCon.php CHANGED
@@ -7,10 +7,6 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Request\FormParams;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
- /**
11
- * Class ModCon
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Base
13
- */
14
  abstract class ModCon {
15
 
16
  use Modules\PluginControllerConsumer;
@@ -1444,14 +1440,4 @@ abstract class ModCon {
1444
  public function savePluginOptions() {
1445
  $this->saveModOptions();
1446
  }
1447
-
1448
- /**
1449
- * Get config 'definition'.
1450
- * @param string $key
1451
- * @return mixed|null
1452
- * @deprecated 12.0
1453
- */
1454
- public function getDef( string $key ) {
1455
- return $this->getOptions()->getDef( $key );
1456
- }
1457
  }
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Request\FormParams;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
 
 
 
 
10
  abstract class ModCon {
11
 
12
  use Modules\PluginControllerConsumer;
1440
  public function savePluginOptions() {
1441
  $this->saveModOptions();
1442
  }
 
 
 
 
 
 
 
 
 
 
1443
  }
src/lib/src/Modules/Base/Options.php CHANGED
@@ -429,19 +429,7 @@ class Options {
429
  }
430
 
431
  public function getOptDefinition( string $key ) :array {
432
- $def = $this->getRawData_AllOptions()[ $key ] ?? [];
433
- if ( empty( $def ) ) {
434
- /**
435
- * @deprecated 12.0 - this is the fallback before we switched to using keys
436
- */
437
- foreach ( $this->getRawData_AllOptions() as $option ) {
438
- if ( $option[ 'key' ] == $key ) {
439
- $def = $option;
440
- break;
441
- }
442
- }
443
- }
444
- return $def;
445
  }
446
 
447
  /**
@@ -759,13 +747,6 @@ class Options {
759
  return $this->cfgLoader;
760
  }
761
 
762
- /**
763
- * @deprecated 12.0
764
- */
765
- private function loadOptionsValuesFromStorage() :array {
766
- return $this->getOptsStorage()->loadOptions();
767
- }
768
-
769
  private function getOptsStorage() :Options\Storage {
770
  if ( empty( $this->optsStorage ) ) {
771
  $this->optsStorage = ( new Options\Storage() )->setMod( $this->getMod() );
@@ -773,20 +754,6 @@ class Options {
773
  return $this->optsStorage;
774
  }
775
 
776
- /**
777
- * @return array
778
- * @deprecated 12.0
779
- */
780
- private function readConfiguration() :array {
781
- try {
782
- $cfg = $this->getConfigLoader()->run();
783
- }
784
- catch ( \Exception $e ) {
785
- $cfg = [];
786
- }
787
- return $cfg;
788
- }
789
-
790
  /**
791
  * @param $values
792
  * @return $this
@@ -796,124 +763,4 @@ class Options {
796
  $this->setNeedSave( true );
797
  return $this;
798
  }
799
-
800
- /**
801
- * @deprecated 12.0
802
- */
803
- public function getStoredOptions() :array {
804
- try {
805
- return $this->loadOptionsValuesFromStorage();
806
- }
807
- catch ( \Exception $e ) {
808
- return [];
809
- }
810
- }
811
-
812
- /**
813
- * @deprecated 12.0
814
- */
815
- public function getConfigStorageKey() :string {
816
- return '';
817
- }
818
-
819
- /**
820
- * @return string
821
- * @throws \Exception
822
- * @deprecated 12.0
823
- */
824
- private function readConfigurationFileContents() {
825
- return '';
826
- }
827
-
828
- /**
829
- * @deprecated 12.0
830
- */
831
- private function getConfigFileExists() :bool {
832
- return true;
833
- }
834
-
835
- /**
836
- * @deprecated 12.0
837
- */
838
- protected function getConfigModTime() :int {
839
- return 0;
840
- }
841
-
842
- /**
843
- * @return array
844
- * @throws \Exception
845
- * @deprecated 12.0
846
- */
847
- private function readConfigurationJson() :array {
848
- throw new \Exception( sprintf( 'Reading JSON configuration from file "%s" failed.', $this->getSlug() ) );
849
- }
850
-
851
- /**
852
- * @deprecated 12.0
853
- */
854
- public function getPathToConfig() :string {
855
- return '';
856
- }
857
-
858
- /**
859
- * @deprecated 12.0
860
- */
861
- public function getRawData_SingleOption( string $key ) :array {
862
- return $this->getOptDefinition( $key );
863
- }
864
-
865
- /**
866
- * @deprecated 12.0
867
- */
868
- public function getOptionsStorageKey() :string {
869
- return $this->getMod()->getOptionsStorageKey();
870
- }
871
-
872
- /**
873
- * @param bool $bLoadFromSaved
874
- * @return $this
875
- * @deprecated 12.0
876
- */
877
- public function setIfLoadOptionsFromStorage( bool $bLoadFromSaved ) :self {
878
- return $this;
879
- }
880
-
881
- /**
882
- * @deprecated 12.0
883
- */
884
- public function getIfLoadOptionsFromStorage() {
885
- return true;
886
- }
887
-
888
- /**
889
- * @param string $key
890
- * @return $this
891
- * @deprecated 12.0
892
- */
893
- public function setOptionsStorageKey( string $key ) :self {
894
- return $this;
895
- }
896
-
897
- /**
898
- * @param string $sPathToConfig
899
- * @return $this
900
- * @deprecated 12.0
901
- */
902
- public function setPathToConfig( $sPathToConfig ) {
903
- return $this;
904
- }
905
-
906
- /**
907
- * @deprecated 12.0
908
- */
909
- public function getRebuildFromFile() :bool {
910
- return false;
911
- }
912
-
913
- /**
914
- * @deprecated 12.0
915
- */
916
- public function setRebuildFromFile( $bRebuild ) {
917
- return $this;
918
- }
919
  }
429
  }
430
 
431
  public function getOptDefinition( string $key ) :array {
432
+ return $this->getRawData_AllOptions()[ $key ] ?? [];
 
 
 
 
 
 
 
 
 
 
 
 
433
  }
434
 
435
  /**
747
  return $this->cfgLoader;
748
  }
749
 
 
 
 
 
 
 
 
750
  private function getOptsStorage() :Options\Storage {
751
  if ( empty( $this->optsStorage ) ) {
752
  $this->optsStorage = ( new Options\Storage() )->setMod( $this->getMod() );
754
  return $this->optsStorage;
755
  }
756
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
757
  /**
758
  * @param $values
759
  * @return $this
763
  $this->setNeedSave( true );
764
  return $this;
765
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
766
  }
src/lib/src/Modules/Base/Strings.php CHANGED
@@ -147,15 +147,6 @@ class Strings {
147
  return [];
148
  }
149
 
150
- /**
151
- * @param string $key
152
- * @return string[]
153
- * @deprecated 12.0
154
- */
155
- public function getAuditMessage( string $key ) :array {
156
- return [];
157
- }
158
-
159
  /**
160
  * @return string[][]|string[]
161
  */
@@ -171,8 +162,6 @@ class Strings {
171
  }
172
 
173
  /**
174
- * @param string $key
175
- * @return array
176
  * @throws \Exception
177
  */
178
  public function getOptionStrings( string $key ) :array {
147
  return [];
148
  }
149
 
 
 
 
 
 
 
 
 
 
150
  /**
151
  * @return string[][]|string[]
152
  */
162
  }
163
 
164
  /**
 
 
165
  * @throws \Exception
166
  */
167
  public function getOptionStrings( string $key ) :array {
src/lib/src/Modules/Base/WpCli/BaseWpCliCmd.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\WpCli;
4
 
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\WpCli;
4
 
src/lib/src/Modules/Data/ModCon.php CHANGED
@@ -44,6 +44,7 @@ class ModCon extends BaseShield\ModCon {
44
  ->getQuerySelector()
45
  ->getDistinctForColumn( 'ip_ref' )
46
  ) )
47
- );
 
48
  }
49
  }
44
  ->getQuerySelector()
45
  ->getDistinctForColumn( 'ip_ref' )
46
  ) )
47
+ )
48
+ ->query();
49
  }
50
  }
src/lib/src/Modules/Events/Lib/EventsListener.php CHANGED
@@ -23,7 +23,11 @@ abstract class EventsListener {
23
 
24
  add_action( $con->prefix( 'event' ),
25
  function ( $event, $meta = [], $def = [] ) use ( $con ) {
26
- $this->captureEvent( $event, $meta, $def );
 
 
 
 
27
  }, 10, 3 );
28
 
29
  add_action( $con->prefix( 'plugin_shutdown' ), function () {
@@ -36,12 +40,7 @@ abstract class EventsListener {
36
  protected function init() {
37
  }
38
 
39
- /**
40
- * @param string $evt
41
- * @param array $meta
42
- * @param array $def
43
- */
44
- abstract protected function captureEvent( string $evt, $meta = [], $def = [] );
45
 
46
  protected function onShutdown() {
47
 
23
 
24
  add_action( $con->prefix( 'event' ),
25
  function ( $event, $meta = [], $def = [] ) use ( $con ) {
26
+ $this->captureEvent(
27
+ (string)$event,
28
+ is_array( $meta ) ? $meta : [],
29
+ is_array( $def ) ? $def : []
30
+ );
31
  }, 10, 3 );
32
 
33
  add_action( $con->prefix( 'plugin_shutdown' ), function () {
40
  protected function init() {
41
  }
42
 
43
+ abstract protected function captureEvent( string $evt, array $meta = [], array $def = [] );
 
 
 
 
 
44
 
45
  protected function onShutdown() {
46
 
src/lib/src/Modules/Events/Lib/EventsService.php CHANGED
@@ -18,7 +18,7 @@ class EventsService {
18
  }
19
 
20
  public function fireEvent( string $event, array $meta = [] ) {
21
- if ( $this->isSupportedEvent( $event ) ) {
22
  try {
23
  $this->verifyAuditParams( $event, $meta );
24
  do_action(
@@ -71,8 +71,7 @@ class EventsService {
71
  $evt[ 'context' ] = $mod->getSlug();
72
  return $evt;
73
  },
74
- /** @deprecated 12.0 - replace with $opts->getEvents() */
75
- is_array( $opts->getDef( 'events' ) ) ? $opts->getDef( 'events' ) : []
76
  )
77
  );
78
  }
@@ -121,8 +120,7 @@ class EventsService {
121
 
122
  private function buildEvents( array $events ) :array {
123
  $defaults = [
124
- 'cat' => 0, //@deprecated 12.0
125
- 'level' => 'notice', // events default at "warning" level
126
  'stat' => true,
127
  'audit' => true,
128
  'recent' => false, // whether to show in the recent events logs
@@ -142,7 +140,7 @@ class EventsService {
142
  /**
143
  * @param string $eventKey
144
  * @return bool
145
- * @deprecated 12.0
146
  */
147
  public function isSupportedEvent( string $eventKey ) :bool {
148
  return array_key_exists( $eventKey, $this->getEvents() );
18
  }
19
 
20
  public function fireEvent( string $event, array $meta = [] ) {
21
+ if ( $this->eventExists( $event ) ) {
22
  try {
23
  $this->verifyAuditParams( $event, $meta );
24
  do_action(
71
  $evt[ 'context' ] = $mod->getSlug();
72
  return $evt;
73
  },
74
+ $opts->getEvents()
 
75
  )
76
  );
77
  }
120
 
121
  private function buildEvents( array $events ) :array {
122
  $defaults = [
123
+ 'level' => 'notice', // events default at "notice" level
 
124
  'stat' => true,
125
  'audit' => true,
126
  'recent' => false, // whether to show in the recent events logs
140
  /**
141
  * @param string $eventKey
142
  * @return bool
143
+ * @deprecated 12.1
144
  */
145
  public function isSupportedEvent( string $eventKey ) :bool {
146
  return array_key_exists( $eventKey, $this->getEvents() );
src/lib/src/Modules/Events/Lib/StatsWriter.php CHANGED
@@ -14,12 +14,7 @@ class StatsWriter extends EventsListener {
14
  */
15
  private $aEventStats;
16
 
17
- /**
18
- * @param string $evt
19
- * @param array $meta
20
- * @param array $def
21
- */
22
- protected function captureEvent( string $evt, $meta = [], $def = [] ) {
23
  if ( !empty( $def[ 'stat' ] ) ) {
24
  $stats = $this->getEventStats();
25
  if ( !isset( $stats[ $evt ] ) ) {
14
  */
15
  private $aEventStats;
16
 
17
+ protected function captureEvent( string $evt, array $meta = [], array $def = [] ) {
 
 
 
 
 
18
  if ( !empty( $def[ 'stat' ] ) ) {
19
  $stats = $this->getEventStats();
20
  if ( !isset( $stats[ $evt ] ) ) {
src/lib/src/Modules/Events/Strings.php CHANGED
@@ -6,65 +6,4 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
 
7
  class Strings extends Base\Strings {
8
 
9
- /**
10
- * @param string $eventKey
11
- * @return string
12
- * @deprecated 12.0
13
- */
14
- public function getEventName( string $eventKey ) :string {
15
- return $this->getCon()->loadEventsService()->getEventName( $eventKey );
16
- }
17
-
18
- /**
19
- * @param bool $auto
20
- * @return string[]
21
- * @deprecated 12.0
22
- */
23
- public function getEventNames( bool $auto = true ) :array {
24
- $names = [
25
- // 'block_param' => __( 'Firewall Blocked Request Parameter', 'wp-simple-firewall' ),
26
- // 'blockparam_dirtraversal' => sprintf( '%s: %s',
27
- // __( 'Firewall', 'wp-simple-firewall' ),
28
- // __( 'Directory Traversal', 'wp-simple-firewall' )
29
- // ),
30
- // 'blockparam_wpterms' => sprintf( '%s: %s',
31
- // __( 'Firewall', 'wp-simple-firewall' ),
32
- // __( 'WordPress Terms', 'wp-simple-firewall' )
33
- // ),
34
- // 'blockparam_fieldtruncation' => sprintf( '%s: %s',
35
- // __( 'Firewall', 'wp-simple-firewall' ),
36
- // __( 'Field Truncation', 'wp-simple-firewall' )
37
- // ),
38
- // 'blockparam_sqlqueries' => sprintf( '%s: %s',
39
- // __( 'Firewall', 'wp-simple-firewall' ),
40
- // __( 'SQL Queries', 'wp-simple-firewall' )
41
- // ),
42
- // 'blockparam_schema' => sprintf( '%s: %s',
43
- // __( 'Firewall', 'wp-simple-firewall' ),
44
- // __( 'Leading Schema', 'wp-simple-firewall' )
45
- // ),
46
- // 'blockparam_aggressive' => sprintf( '%s: %s',
47
- // __( 'Firewall', 'wp-simple-firewall' ),
48
- // __( 'Aggressive Rules', 'wp-simple-firewall' )
49
- // ),
50
- // 'blockparam_phpcode' => sprintf( '%s: %s',
51
- // __( 'Firewall', 'wp-simple-firewall' ),
52
- // __( 'PHP Code', 'wp-simple-firewall' )
53
- // ),
54
- // 'block_exefile' => sprintf( '%s: %s',
55
- // __( 'Firewall', 'wp-simple-firewall' ),
56
- // __( 'EXE File Uploads', 'wp-simple-firewall' )
57
- // ),
58
- ];
59
-
60
- if ( $auto ) {
61
- foreach ( $names as $key => $name ) {
62
- if ( empty( $name ) ) {
63
- $names[ $key ] = ucwords( str_replace( '_', ' ', $key ) );
64
- }
65
- }
66
- }
67
-
68
- return $names;
69
- }
70
  }
6
 
7
  class Strings extends Base\Strings {
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
src/lib/src/Modules/Firewall/Processor.php CHANGED
@@ -7,31 +7,8 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\Lib\Scan\FirewallHa
7
 
8
  class Processor extends BaseShield\Processor {
9
 
10
- /**
11
- * @deprecated 12.0
12
- */
13
- private $dieMessage;
14
-
15
- /**
16
- * @deprecated 12.0
17
- */
18
- protected $aPatterns;
19
-
20
- /**
21
- * @deprecated 12.0
22
- */
23
- private $aAuditBlockMessage;
24
-
25
- /**
26
- * @deprecated 12.0
27
- */
28
- private $params;
29
-
30
  private $firewallHandler;
31
 
32
- protected function run() {
33
- }
34
-
35
  public function onWpInit() {
36
  $this->getFirewallHandler()->execute();
37
  }
@@ -53,91 +30,4 @@ class Processor extends BaseShield\Processor {
53
  }
54
  return $pri;
55
  }
56
-
57
- private function getIfDoFirewallBlock() :bool {
58
- return false;
59
- }
60
-
61
- private function doPreFirewallBlock() {
62
- }
63
-
64
- private function doFirewallBlock() {
65
- }
66
-
67
- protected function getFirewallDieMessageForDisplay() :string {
68
- return '';
69
- }
70
-
71
- private function sendBlockEmail( string $recipient ) :bool {
72
- return false;
73
- }
74
-
75
- /**
76
- * @deprecated 12.0
77
- */
78
- private function getIfPerformFirewallScan() :bool {
79
- return false;
80
- }
81
-
82
- /**
83
- * @deprecated 12.0
84
- */
85
- private function isVisitorRequestPermitted() :bool {
86
- return true;
87
- }
88
-
89
- /**
90
- * @deprecated 12.0
91
- */
92
- protected function doPassCheckBlockExeFileUploads() :bool {
93
- return true;
94
- }
95
-
96
- /**
97
- * @deprecated 12.0
98
- */
99
- private function doPassCheck( string $blockKey ) :bool {
100
- return true;
101
- }
102
-
103
- protected function getFirewallPatterns( $key = null ) {
104
- return [];
105
- }
106
-
107
- /**
108
- * @deprecated 12.0
109
- */
110
- protected function getFirewallDieMessage() :array {
111
- return [ $this->getMod()->getTextOpt( 'text_firewalldie' ) ];
112
- }
113
-
114
- /**
115
- * @param string $msg
116
- * @return $this
117
- * @deprecated 12.0
118
- */
119
- protected function addToFirewallDieMessage( string $msg ) {
120
- return $this;
121
- }
122
-
123
- /**
124
- * @deprecated 12.0
125
- */
126
- private function getParamsToCheck() :array {
127
- return [];
128
- }
129
-
130
- /**
131
- * @deprecated 12.0
132
- */
133
- private function getRawRequestParams() :array {
134
- return [];
135
- }
136
-
137
- /**
138
- * @deprecated 12.0
139
- */
140
- private function getFirewallBlockKeyName( string $blockKey ) :string {
141
- return '';
142
- }
143
  }
7
 
8
  class Processor extends BaseShield\Processor {
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  private $firewallHandler;
11
 
 
 
 
12
  public function onWpInit() {
13
  $this->getFirewallHandler()->execute();
14
  }
30
  }
31
  return $pri;
32
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  }
src/lib/src/Modules/HackGuard/AjaxHandler.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
@@ -52,7 +52,8 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
52
  $FLCon = $mod->getFileLocker();
53
  $FS = Services::WpFs();
54
 
55
- $nRID = Services::Request()->post( 'rid' );
 
56
  $data = [
57
  'error' => '',
58
  'success' => false,
@@ -95,13 +96,7 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
95
  ]
96
  ];
97
  try {
98
- if ( !is_numeric( $nRID ) ) {
99
- throw new \Exception( 'Not a valid file lock request.' );
100
- }
101
  $lock = $FLCon->getFileLock( $nRID );
102
- if ( !$lock instanceof Databases\FileLocker\EntryVO ) {
103
- throw new \Exception( 'Not a valid file lock request.' );
104
- }
105
 
106
  $isDifferent = $lock->detected_at > 0;
107
  $data[ 'ajax' ] = $FLCon->createFileDownloadLinks( $lock );
@@ -109,7 +104,7 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
109
  $data[ 'html' ][ 'diff' ] = $isDifferent ?
110
  ( new FileLocker\Ops\PerformAction() )
111
  ->setMod( $this->getMod() )
112
- ->run( $nRID, 'diff' ) : '';
113
 
114
  $carb = Services::Request()->carbon( true );
115
 
@@ -157,14 +152,18 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
157
  }
158
 
159
  private function ajaxExec_FileLockerFileAction() :array {
 
 
 
160
  $req = Services::Request();
161
  $success = false;
162
 
163
  if ( $req->post( 'confirmed' ) == '1' ) {
164
  try {
 
165
  $success = ( new FileLocker\Ops\PerformAction() )
166
  ->setMod( $this->getMod() )
167
- ->run( $req->post( 'rid' ), $req->post( 'file_action' ) );
168
  $msg = __( 'Requested action completed successfully.', 'wp-simple-firewall' );
169
  }
170
  catch ( \Exception $e ) {
@@ -186,17 +185,16 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
186
  $mod = $this->getMod();
187
  $req = Services::Request();
188
 
189
- $bReinstall = (bool)$req->post( 'reinstall' );
190
- $bActivate = (bool)$req->post( 'activate' );
191
  $file = sanitize_text_field( wp_unslash( $req->post( 'file' ) ) );
192
 
193
- if ( $bReinstall ) {
194
- /** @var Scan\Controller\Ptg $scan */
195
- $scan = $mod->getScansCon()->getScanCon( 'ptg' );
196
- $bActivate = $scan->actionPluginReinstall( $file );
197
  }
198
 
199
- if ( $bActivate ) {
200
  Services::WpPlugins()->activate( $file );
201
  }
202
 
@@ -208,11 +206,10 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
208
  $mod = $this->getMod();
209
  /** @var Strings $strings */
210
  $strings = $mod->getStrings();
211
- /** @var Shield\Databases\ScanQueue\Select $selector */
212
- $selector = $mod->getDbHandler_ScanQueue()->getQuerySelector();
213
 
 
214
  $queueCon = $mod->getScanQueueController();
215
- $current = $selector->getCurrentScan();
216
  $hasCurrent = !empty( $current );
217
  if ( $hasCurrent ) {
218
  $currentScan = $strings->getScanName( $current );
@@ -221,12 +218,14 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
221
  $currentScan = __( 'No scan running.', 'wp-simple-firewall' );
222
  }
223
 
224
- if ( count( $selector->getInitiatedScans() ) === 0 ) {
 
 
225
  $remainingScans = __( 'No scans remaining.', 'wp-simple-firewall' );
226
  }
227
  else {
228
- $remainingScans = sprintf( __( '%s of %s scans remaining.', 'wp-simple-firewall' ),
229
- count( $selector->getUnfinishedScans() ), count( $selector->getInitiatedScans() ) );
230
  }
231
 
232
  return [
@@ -258,44 +257,22 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
258
  $success = false;
259
  $reloadPage = false;
260
  $msg = __( 'No scans were selected', 'wp-simple-firewall' );
261
- $formParams = FormParams::Retrieve();
262
-
263
- $scanCon = $mod->getScanQueueController();
264
-
265
- if ( !empty( $formParams ) ) {
266
- $selected = array_keys( $formParams );
267
 
 
268
  $uiTrack = $mod->getUiTrack();
269
- $uiTrack->selected_scans = array_intersect( array_keys( $formParams ), $opts->getScanSlugs() );
270
  $mod->setUiTrack( $uiTrack );
271
 
272
- $toScan = [];
273
- foreach ( $selected as $slug ) {
274
- try {
275
- $thisScanCon = $mod->getScanCon( $slug );
276
- if ( $thisScanCon->isReady() ) {
277
-
278
- $toScan[] = $slug;
279
-
280
- if ( isset( $formParams[ 'opt_clear_ignore' ] ) ) {
281
- $thisScanCon->resetIgnoreStatus();
282
- }
283
- if ( isset( $formParams[ 'opt_clear_notification' ] ) ) {
284
- $thisScanCon->resetNotifiedStatus();
285
- }
286
-
287
- $success = true;
288
- $reloadPage = true;
289
- $msg = __( 'Scans started.', 'wp-simple-firewall' ).' '.__( 'Please wait, as this will take a few moments.', 'wp-simple-firewall' );
290
- }
291
- }
292
- catch ( \Exception $e ) {
293
- }
294
  }
295
- $scanCon->startScans( $toScan );
296
  }
297
 
298
- $isScanRunning = $scanCon->hasRunningScans();
299
 
300
  return [
301
  'success' => $success,
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
52
  $FLCon = $mod->getFileLocker();
53
  $FS = Services::WpFs();
54
 
55
+ $nRID = (int)Services::Request()->post( 'rid' );
56
+
57
  $data = [
58
  'error' => '',
59
  'success' => false,
96
  ]
97
  ];
98
  try {
 
 
 
99
  $lock = $FLCon->getFileLock( $nRID );
 
 
 
100
 
101
  $isDifferent = $lock->detected_at > 0;
102
  $data[ 'ajax' ] = $FLCon->createFileDownloadLinks( $lock );
104
  $data[ 'html' ][ 'diff' ] = $isDifferent ?
105
  ( new FileLocker\Ops\PerformAction() )
106
  ->setMod( $this->getMod() )
107
+ ->run( $lock, 'diff' ) : '';
108
 
109
  $carb = Services::Request()->carbon( true );
110
 
152
  }
153
 
154
  private function ajaxExec_FileLockerFileAction() :array {
155
+ /** @var ModCon $mod */
156
+ $mod = $this->getMod();
157
+ $FLCon = $mod->getFileLocker();
158
  $req = Services::Request();
159
  $success = false;
160
 
161
  if ( $req->post( 'confirmed' ) == '1' ) {
162
  try {
163
+ $lock = $FLCon->getFileLock( (int)$req->post( 'rid' ) );
164
  $success = ( new FileLocker\Ops\PerformAction() )
165
  ->setMod( $this->getMod() )
166
+ ->run( $lock, (string)$req->post( 'file_action' ) );
167
  $msg = __( 'Requested action completed successfully.', 'wp-simple-firewall' );
168
  }
169
  catch ( \Exception $e ) {
185
  $mod = $this->getMod();
186
  $req = Services::Request();
187
 
188
+ $activate = $req->post( 'activate' );
 
189
  $file = sanitize_text_field( wp_unslash( $req->post( 'file' ) ) );
190
 
191
+ if ( $req->post( 'reinstall' ) ) {
192
+ /** @var Scan\Controller\Afs $scan */
193
+ $scan = $mod->getScansCon()->getScanCon( 'afs' );
194
+ $activate = $scan->actionPluginReinstall( $file );
195
  }
196
 
197
+ if ( $activate ) {
198
  Services::WpPlugins()->activate( $file );
199
  }
200
 
206
  $mod = $this->getMod();
207
  /** @var Strings $strings */
208
  $strings = $mod->getStrings();
 
 
209
 
210
+ $statusChecker = ( new Scan\Init\ScansStatus() )->setMod( $mod );
211
  $queueCon = $mod->getScanQueueController();
212
+ $current = $statusChecker->current();
213
  $hasCurrent = !empty( $current );
214
  if ( $hasCurrent ) {
215
  $currentScan = $strings->getScanName( $current );
218
  $currentScan = __( 'No scan running.', 'wp-simple-firewall' );
219
  }
220
 
221
+ $running = $statusChecker->enqueued();
222
+
223
+ if ( count( $running ) === 0 ) {
224
  $remainingScans = __( 'No scans remaining.', 'wp-simple-firewall' );
225
  }
226
  else {
227
+ $remainingScans = sprintf( __( '%s scans remaining.', 'wp-simple-firewall' ),
228
+ count( $running ) );
229
  }
230
 
231
  return [
257
  $success = false;
258
  $reloadPage = false;
259
  $msg = __( 'No scans were selected', 'wp-simple-firewall' );
260
+ $params = FormParams::Retrieve();
 
 
 
 
 
261
 
262
+ if ( !empty( $params ) ) {
263
  $uiTrack = $mod->getUiTrack();
264
+ $uiTrack->selected_scans = array_intersect( array_keys( $params ), $opts->getScanSlugs() );
265
  $mod->setUiTrack( $uiTrack );
266
 
267
+ $resetIgnore = (bool)( $params[ 'opt_clear_ignore' ] ?? false );
268
+ if ( $mod->getScansCon()->startNewScans( $uiTrack->selected_scans, $resetIgnore ) ) {
269
+ $success = true;
270
+ $reloadPage = true;
271
+ $msg = __( 'Scans started.', 'wp-simple-firewall' ).' '.__( 'Please wait, as this will take a few moments.', 'wp-simple-firewall' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  }
 
273
  }
274
 
275
+ $isScanRunning = $mod->getScanQueueController()->hasRunningScans();
276
 
277
  return [
278
  'success' => $success,
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Common.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ trait Common {
6
+
7
+ public function filterByMetaKey( string $key ) {
8
+ return $this->addWhereEquals( 'meta_key', $key );
9
+ }
10
+
11
+ public function filterByResultItemRef( int $ref ) {
12
+ return $this->filterByResultItems( [ $ref ] );
13
+ }
14
+
15
+ public function filterByResultItems( array $refs ) {
16
+ return $this->addWhereIn( 'ri_ref', array_map( 'intval', $refs ) );
17
+ }
18
+ }
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Delete.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Delete extends Base\Delete {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Handler.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Handler extends Base\Handler {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Insert.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Insert extends Base\Insert {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Record.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ /**
6
+ * @property int $ri_ref
7
+ * @property string $meta_key
8
+ * @property mixed $meta_value
9
+ */
10
+ class Record extends \FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Record {
11
+
12
+ }
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Select.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Select extends Base\Select {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Update.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItemMeta\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Update extends Base\Select {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Common.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ trait Common {
6
+
7
+ public function filterByNoRepairAttempted() {
8
+ return $this->addWhereEquals( 'attempt_repair_at', 0 );
9
+ }
10
+
11
+ public function filterByNotIgnored() {
12
+ return $this->addWhereEquals( 'ignored_at', 0 );
13
+ }
14
+
15
+ public function filterByItemNotRepaired() {
16
+ return $this->addWhereEquals( 'item_repaired_at', 0 );
17
+ }
18
+
19
+ public function filterByItemNotDeleted() {
20
+ return $this->addWhereEquals( 'item_deleted_at', 0 );
21
+ }
22
+
23
+ public function filterByIgnored() {
24
+ return $this->addWhereNewerThan( 0, 'ignored_at' );
25
+ }
26
+
27
+ public function filterByItemID( string $itemID ) {
28
+ return $this->addWhereEquals( 'item_id', $itemID );
29
+ }
30
+
31
+ public function filterByItemType( string $type ) {
32
+ return $this->addWhereEquals( 'item_type', $type );
33
+ }
34
+
35
+ public function filterByNotified() {
36
+ return $this->addWhereNewerThan( 0, 'notified_at' );
37
+ }
38
+
39
+ public function filterByNotNotified() {
40
+ return $this->addWhereNewerThan( 0, 'notified_at' );
41
+ }
42
+
43
+ public function filterByTypeFile() {
44
+ return $this->filterByItemType( Handler::ITEM_TYPE_FILE );
45
+ }
46
+
47
+ public function filterByTypePlugin() {
48
+ return $this->filterByItemType( Handler::ITEM_TYPE_PLUGIN );
49
+ }
50
+
51
+ public function filterByTypeTheme() {
52
+ return $this->filterByItemType( Handler::ITEM_TYPE_THEME );
53
+ }
54
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Delete.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Delete extends Base\Delete {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Handler.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Handler extends Base\Handler {
8
+
9
+ const ITEM_TYPE_FILE = 'f';
10
+ const ITEM_TYPE_PLUGIN = 'p';
11
+ const ITEM_TYPE_THEME = 't';
12
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Insert.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Insert extends Base\Insert {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Record.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ /**
6
+ * @property string $item_type
7
+ * @property string $item_id
8
+ * @property int $ignored_at
9
+ * @property int $notified_at
10
+ * @property int $auto_filtered_at
11
+ * @property int $attempt_repair_at
12
+ * @property int $item_repaired_at
13
+ * @property int $item_deleted_at
14
+ */
15
+ class Record extends \FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Record {
16
+
17
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Select.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Select extends Base\Select {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ResultItems/Ops/Update.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Update extends Base\Update {
9
+
10
+ public function setItemDeleted( int $recordID ) :bool {
11
+ return $this->updateById( $recordID, [ 'item_deleted_at' => Services::Request()->ts() ] );
12
+ }
13
+
14
+ public function setItemRepaired( int $recordID ) :bool {
15
+ return $this->updateById( $recordID, [ 'item_repaired_at' => Services::Request()->ts() ] );
16
+ }
17
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Common.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ trait Common {
6
+
7
+ public function filterByScan( int $scanID ) {
8
+ return $this->addWhereEquals( 'scan_ref', $scanID );
9
+ }
10
+
11
+ public function filterByFinished() {
12
+ return $this->addWhereNewerThan( 0, 'finished_at' );
13
+ }
14
+
15
+ public function filterByNotFinished() {
16
+ return $this->addWhereEquals( 'finished_at', 0 );
17
+ }
18
+
19
+ public function filterByStarted() {
20
+ return $this->addWhereNewerThan( 0, 'started_at' );
21
+ }
22
+
23
+ public function filterByNotStarted() {
24
+ return $this->addWhereEquals( 'started_at', 0 );
25
+ }
26
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Delete.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Delete extends Base\Delete {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Handler.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Handler extends Base\Handler {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Insert.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Insert extends Base\Insert {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Record.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ /**
6
+ * @property int $scan_ref
7
+ * @property array $items
8
+ * @property int $started_at
9
+ * @property int $finished_at
10
+ */
11
+ class Record extends \FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Record {
12
+
13
+ /**
14
+ * @param string $key
15
+ * @return mixed
16
+ */
17
+ public function __get( string $key ) {
18
+
19
+ $value = parent::__get( $key );
20
+
21
+ switch ( $key ) {
22
+
23
+ case 'items':
24
+ if ( is_string( $value ) && !empty( $value ) ) {
25
+ $value = base64_decode( $value );
26
+ if ( !empty( $value ) ) {
27
+ $value = @json_decode( $value, true );
28
+ }
29
+ }
30
+
31
+ if ( !is_array( $value ) ) {
32
+ $value = [];
33
+ }
34
+ break;
35
+
36
+ default:
37
+ break;
38
+ }
39
+
40
+ return $value;
41
+ }
42
+
43
+ /**
44
+ * @param string $key
45
+ * @param mixed $value
46
+ */
47
+ public function __set( string $key, $value ) {
48
+
49
+ switch ( $key ) {
50
+
51
+ case 'items':
52
+ if ( !is_array( $value ) ) {
53
+ $value = [];
54
+ }
55
+ $value = base64_encode( json_encode( $value ) );
56
+ break;
57
+
58
+ default:
59
+ break;
60
+ }
61
+
62
+ parent::__set( $key, $value );
63
+ }
64
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Select.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Select extends Base\Select {
8
+
9
+ use Common;
10
+
11
+ public function countAllForEachScan() :array {
12
+ /** @var Record[] $res */
13
+ $res = $this->setCustomSelect( '`scan_ref`,COUNT(*) as count' )
14
+ ->setGroupBy( 'scan_ref' )
15
+ ->setSelectResultsFormat( ARRAY_A )
16
+ ->queryWithResult();
17
+ $counts = [];
18
+ if ( is_array( $res ) ) {
19
+ foreach ( $res as $entry ) {
20
+ $entry = $entry->getRawData();
21
+ $counts[ $entry[ 'scan_ref' ] ] = $entry[ 'count' ];
22
+ }
23
+ }
24
+ return $counts;
25
+ }
26
+
27
+ public function countUnfinishedForEachScan() :array {
28
+ /** @var Record[] $res */
29
+ $res = $this->setCustomSelect( '`scan_ref`,COUNT(*) as count' )
30
+ ->filterByNotFinished()
31
+ ->setGroupBy( 'scan_ref' )
32
+ ->setSelectResultsFormat( ARRAY_A )
33
+ ->queryWithResult();
34
+ $counts = [];
35
+ if ( is_array( $res ) ) {
36
+ foreach ( $res as $entry ) {
37
+ $entry = $entry->getRawData();
38
+ $counts[ $entry[ 'scan_ref' ] ] = $entry[ 'count' ];
39
+ }
40
+ }
41
+ return $counts;
42
+ }
43
+ }
src/lib/src/Modules/HackGuard/DB/ScanItems/Ops/Update.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Update extends Base\Update {
9
+
10
+ public function setFinished( Record $record ) :bool {
11
+ return $this->updateRecord( $record, [ 'finished_at' => Services::Request()->ts() ] );
12
+ }
13
+
14
+ public function setStarted( Record $record ) :bool {
15
+ return $this->updateEntry( $record, [ 'started_at' => Services::Request()->ts() ] );
16
+ }
17
+ }
src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Common.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops;
4
+
5
+ trait Common {
6
+
7
+ public function filterByScan( int $scanID ) {
8
+ return $this->addWhereEquals( 'scan_ref', $scanID );
9
+ }
10
+
11
+ public function filterByResultItems( int $resultItemID ) {
12
+ return $this->addWhereEquals( 'resultitem_ref', $resultItemID );
13
+ }
14
+ }
src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Delete.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Delete extends Base\Delete {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Handler.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Handler extends Base\Handler {
8
+
9
+ const ITEM_TYPE_FILE = 'f';
10
+ const ITEM_TYPE_PLUGIN = 'p';
11
+ const ITEM_TYPE_THEME = 't';
12
+ }
src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Insert.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Insert extends Base\Insert {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Record.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops;
4
+
5
+ /**
6
+ * @property int $scan_ref
7
+ * @property int $resultitem_ref
8
+ */
9
+ class Record extends \FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Record {
10
+
11
+ }
src/lib/src/Modules/HackGuard/DB/ScanResults/Ops/Select.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Select extends Base\Select {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Common.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ trait Common {
8
+
9
+ public function filterByScan( string $scan ) {
10
+ return $this->addWhereEquals( 'scan', $scan );
11
+ }
12
+
13
+ public function filterByScans( array $scans ) {
14
+ return $this->addWhereIn( 'scan', $scans );
15
+ }
16
+
17
+ public function filterByNotFinished() {
18
+ return $this->addWhereEquals( 'finished_at', 0 );
19
+ }
20
+
21
+ public function filterByNotReady() {
22
+ return $this->addWhereEquals( 'ready_at', 0 );
23
+ }
24
+
25
+ public function filterByFinished() {
26
+ return $this->addWhereNewerThan( 0, 'finished_at' );
27
+ }
28
+
29
+ public function filterByReady() {
30
+ return $this->addWhereNewerThan( 0, 'ready_at' );
31
+ }
32
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Delete.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Delete extends Base\Delete {
8
+
9
+ use Common;
10
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Handler.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Handler extends Base\Handler {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Insert.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Insert extends Base\Insert {
8
+
9
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Record.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ /**
6
+ * @property string $scan
7
+ * @property int $ready_at
8
+ * @property int $finished_at
9
+ */
10
+ class Record extends \FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Record {
11
+
12
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Select.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+
7
+ class Select extends Base\Select {
8
+
9
+ use Common;
10
+
11
+ /**
12
+ * @param string $scan
13
+ * @return Record|null
14
+ */
15
+ public function getLatestForScan( string $scan ) {
16
+ return $this->filterByScan( $scan )
17
+ ->setOrderBy( 'id', 'DESC', true )
18
+ ->first();
19
+ }
20
+ }
src/lib/src/Modules/HackGuard/DB/Scans/Ops/Update.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans\Ops;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Update extends Base\Update {
9
+
10
+ public function setFinished( Record $record ) :bool {
11
+ return $this->updateRecord( $record, [ 'finished_at' => Services::Request()->ts() ] );
12
+ }
13
+ }
src/lib/src/Modules/HackGuard/Debug.php CHANGED
@@ -2,9 +2,23 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
 
 
 
5
  class Debug extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Debug {
6
 
7
  public function run() {
 
8
  die( 'finish' );
9
  }
 
 
 
 
 
 
 
 
 
 
10
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Afs;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\Retrieve;
7
+
8
  class Debug extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Debug {
9
 
10
  public function run() {
11
+ $this->testscans();
12
  die( 'finish' );
13
  }
14
+
15
+ private function testscans() {
16
+ /** @var ModCon $mod */
17
+ $mod = $this->getMod();
18
+ $res = ( new Retrieve() )
19
+ ->setScanController( $mod->getScanCon( Afs::SCAN_SLUG ) )
20
+ ->setMod( $this->getMod() )
21
+ ->retrieveLatest();
22
+ var_dump( $res );
23
+ }
24
  }
src/lib/src/Modules/HackGuard/Insights/OverviewCards.php CHANGED
@@ -3,6 +3,11 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Insights;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
 
 
 
 
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
 
8
  class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
@@ -32,7 +37,6 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
32
  $this->getCardsForMal(),
33
  $this->getCardsForWpv(),
34
  $this->getCardsForPtg(),
35
- $this->getCardsForUfc(),
36
  $this->getCardsForApc()
37
  );
38
  }
@@ -53,21 +57,22 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
53
  $mod = $this->getMod();
54
  /** @var HackGuard\Options $opts */
55
  $opts = $this->getOptions();
56
- $scanCon = $mod->getScanCon( HackGuard\Scan\Controller\Wcf::SCAN_SLUG );
 
57
 
58
  $cards = [];
59
 
60
- $bCore = $scanCon->isEnabled();
61
  $cards[ $scanCon::SCAN_SLUG ] = [
62
  'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
63
- 'state' => $bCore ? 1 : -2,
64
- 'summary' => $bCore ?
65
  __( 'WP Core files are scanned automatically', 'wp-simple-firewall' )
66
  : __( "WP Core files aren't automatically scanned!", 'wp-simple-firewall' ),
67
  'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
68
  'help' => __( 'Automatic WordPress Core File scanner should be turned-on.', 'wp-simple-firewall' )
69
  ];
70
- if ( $bCore ) {
71
  if ( !$opts->isRepairFileWP() ) {
72
  $cards[ 'wcf_repair' ] = [
73
  'name' => __( 'WP Core File Repair', 'wp-simple-firewall' ),
@@ -79,9 +84,10 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
79
  ];
80
  }
81
  }
82
- if ( $scanCon->getScanHasProblem() ) {
 
83
  $cards[ 'wcf_problem' ] = [
84
- 'name' => __( 'Core Files Changed', 'wp-simple-firewall' ),
85
  'summary' => __( 'WordPress core files have been modified.', 'wp-simple-firewall' ),
86
  'href' => $this->getUrlForScanResults(),
87
  'state' => -2,
@@ -92,73 +98,33 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
92
  return $cards;
93
  }
94
 
95
- private function getCardsForUfc() :array {
96
- /** @var HackGuard\ModCon $mod */
97
- $mod = $this->getMod();
98
- /** @var HackGuard\Options $opts */
99
- $opts = $this->getOptions();
100
- $scanCon = $mod->getScanCon( HackGuard\Scan\Controller\Ufc::SCAN_SLUG );
101
-
102
- $cards = [];
103
-
104
- $bUcf = $scanCon->isEnabled();
105
- $cards[ $scanCon::SCAN_SLUG ] = [
106
- 'name' => __( 'Unrecognised Files', 'wp-simple-firewall' ),
107
- 'summary' => $bUcf ?
108
- __( 'WP Core directories are scanned regularly for unrecognised files', 'wp-simple-firewall' )
109
- : __( "WP Core directories are never scanned for unrecognised files!", 'wp-simple-firewall' ),
110
- 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
111
- 'help' => __( 'Automatic scanning for non-WordPress core files is recommended.', 'wp-simple-firewall' ),
112
- 'state' => $bUcf ? 1 : -2,
113
- ];
114
- if ( $bUcf ) {
115
- $cards[ 'ufc_repair' ] = [
116
- 'name' => __( 'Unrecognised Files Removal', 'wp-simple-firewall' ),
117
- 'summary' => $opts->isUfsDeleteFiles() ?
118
- __( 'Unrecognised files are automatically removed', 'wp-simple-firewall' )
119
- : __( "Unrecognised files aren't automatically removed!", 'wp-simple-firewall' ),
120
- 'state' => $opts->isUfsDeleteFiles() ? 1 : -1,
121
- 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
122
- ];
123
- }
124
- if ( $scanCon->getScanHasProblem() ) {
125
- $cards[ 'ufc_problem' ] = [
126
- 'name' => __( 'Unrecognised Files', 'wp-simple-firewall' ),
127
- 'summary' => __( 'Unrecognised files found in WordPress Core directory.', 'wp-simple-firewall' ),
128
- 'help' => __( 'Scan and remove any files that are not meant to be in the WP core directories.', 'wp-simple-firewall' ),
129
- 'state' => -2,
130
- 'href' => $this->getUrlForScanResults(),
131
- ];
132
- }
133
-
134
- return $cards;
135
- }
136
-
137
  private function getCardsForPtg() :array {
138
  /** @var HackGuard\ModCon $mod */
139
  $mod = $this->getMod();
140
- $scanCon = $mod->getScanCon( HackGuard\Scan\Controller\Ptg::SCAN_SLUG );
 
141
 
142
  $cards = [];
143
 
144
- $bPtg = $scanCon->isEnabled();
145
  $cards[ $scanCon::SCAN_SLUG ] = [
146
- 'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
147
- 'summary' => $bPtg ?
148
  __( 'Plugins and Themes are guarded against tampering', 'wp-simple-firewall' )
149
  : __( "Plugins and Themes are never scanned for tampering!", 'wp-simple-firewall' ),
150
- 'state' => $bPtg ? 1 : -2,
151
- 'href' => $mod->getUrl_DirectLinkToOption( 'ptg_enable' ),
152
  'help' => __( 'Automatic detection of plugin/theme modifications is recommended.', 'wp-simple-firewall' ),
153
  ];
154
- if ( $scanCon->getScanHasProblem() ) {
 
 
155
  $cards[ 'ptg_problem' ] = [
156
- 'name' => $scanCon->getScanName(),
157
  'summary' => __( 'A plugin/theme was found to have been modified.', 'wp-simple-firewall' ),
158
  'state' => -2,
159
  'href' => $this->getUrlForScanResults(),
160
  'help' => __( 'Reviewing modifications to your plugins/themes is recommended.', 'wp-simple-firewall' ),
161
-
162
  ];
163
  }
164
 
@@ -168,23 +134,24 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
168
  private function getCardsForMal() :array {
169
  /** @var HackGuard\ModCon $mod */
170
  $mod = $this->getMod();
171
- $scanCon = $mod->getScanCon( HackGuard\Scan\Controller\Mal::SCAN_SLUG );
 
172
 
173
  $cards = [];
174
 
175
- $malEnabled = $scanCon->isEnabled();
176
  $cards[ $scanCon::SCAN_SLUG ] = [
177
  'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
178
  'summary' => $malEnabled ?
179
  sprintf( __( '%s Scanner runs automatically.' ), $scanCon->getScanName() )
180
  : sprintf( __( "%s Scanner isn't set to run automatically." ), $scanCon->getScanName() ),
181
  'state' => $malEnabled ? 1 : -2,
182
- 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_mal' ),
183
  'help' => __( 'Automatic detection of Malware is recommended.', 'wp-simple-firewall' )
184
  ];
185
- if ( $malEnabled && $scanCon->getScanHasProblem() ) {
186
  $cards[ 'mal_problem' ] = [
187
- 'name' => __( 'Malware Detected', 'wp-simple-firewall' ),
188
  'summary' => __( 'Potential Malware files have been discovered.', 'wp-simple-firewall' ),
189
  'state' => -2,
190
  'href' => $this->getUrlForScanResults(),
@@ -198,20 +165,20 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
198
  private function getCardsForApc() :array {
199
  /** @var HackGuard\ModCon $mod */
200
  $mod = $this->getMod();
201
- $scanCon = $mod->getScanCon( HackGuard\Scan\Controller\Apc::SCAN_SLUG );
202
 
203
  $cards = [];
204
 
205
- $bApc = $scanCon->isEnabled();
206
  $cards[ $scanCon::SCAN_SLUG ] = [
207
  'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
208
- 'state' => $bApc ? 1 : -1,
209
- 'summary' => $bApc ?
210
  sprintf( __( '%s Scanner is enabled.' ), $scanCon->getScanName() )
211
  : sprintf( __( '%s Scanner is not enabled.' ), $scanCon->getScanName() ),
212
  'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_apc' ),
213
  ];
214
- if ( $scanCon->getScanHasProblem() ) {
215
  $cards[ 'apc_problem' ] = [
216
  'name' => __( 'Plugin Abandoned' ),
217
  'summary' => __( 'At least 1 plugin on your site is abandoned.', 'wp-simple-firewall' ),
@@ -227,7 +194,7 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
227
  private function getCardsForWpv() :array {
228
  /** @var HackGuard\ModCon $mod */
229
  $mod = $this->getMod();
230
- $scanCon = $mod->getScanCon( HackGuard\Scan\Controller\Wpv::SCAN_SLUG );
231
 
232
  $cards = [];
233
 
@@ -253,7 +220,7 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
253
  'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
254
  ];
255
  }
256
- if ( $scanCon->getScanHasProblem() ) {
257
  $cards[ 'wpv_problem' ] = [
258
  'name' => __( 'Vulnerable Plugin', 'wp-simple-firewall' ),
259
  'summary' => __( 'Plugin with vulnerabilities found on site.', 'wp-simple-firewall' ),
@@ -266,7 +233,7 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
266
  return $cards;
267
  }
268
 
269
- private function getUrlForScanResults() :string{
270
  return $this->getCon()->getModule_Insights()->getUrl_ScansResults();
271
  }
272
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Insights;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\{
7
+ Afs,
8
+ Apc,
9
+ Wpv
10
+ };
11
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
12
 
13
  class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
37
  $this->getCardsForMal(),
38
  $this->getCardsForWpv(),
39
  $this->getCardsForPtg(),
 
40
  $this->getCardsForApc()
41
  );
42
  }
57
  $mod = $this->getMod();
58
  /** @var HackGuard\Options $opts */
59
  $opts = $this->getOptions();
60
+ /** @var Afs $scanCon */
61
+ $scanCon = $mod->getScanCon( Afs::SCAN_SLUG );
62
 
63
  $cards = [];
64
 
65
+ $scanCore = $scanCon->isEnabled();
66
  $cards[ $scanCon::SCAN_SLUG ] = [
67
  'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
68
+ 'state' => $scanCore ? 1 : -2,
69
+ 'summary' => $scanCore ?
70
  __( 'WP Core files are scanned automatically', 'wp-simple-firewall' )
71
  : __( "WP Core files aren't automatically scanned!", 'wp-simple-firewall' ),
72
  'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
73
  'help' => __( 'Automatic WordPress Core File scanner should be turned-on.', 'wp-simple-firewall' )
74
  ];
75
+ if ( $scanCore ) {
76
  if ( !$opts->isRepairFileWP() ) {
77
  $cards[ 'wcf_repair' ] = [
78
  'name' => __( 'WP Core File Repair', 'wp-simple-firewall' ),
84
  ];
85
  }
86
  }
87
+
88
+ if ( $scanCore && $scanCon->getScansController()->getScanResultsCount()->countWPFiles() ) {
89
  $cards[ 'wcf_problem' ] = [
90
+ 'name' => sprintf( '%s: %s', __( 'Modified', 'wp-simple-firewall' ), __( 'WordPress Core Files', 'wp-simple-firewall' ) ),
91
  'summary' => __( 'WordPress core files have been modified.', 'wp-simple-firewall' ),
92
  'href' => $this->getUrlForScanResults(),
93
  'state' => -2,
98
  return $cards;
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  private function getCardsForPtg() :array {
102
  /** @var HackGuard\ModCon $mod */
103
  $mod = $this->getMod();
104
+ /** @var Afs $scanCon */
105
+ $scanCon = $mod->getScanCon( Afs::SCAN_SLUG );
106
 
107
  $cards = [];
108
 
109
+ $isPTG = $scanCon->isEnabledPluginThemeScan();
110
  $cards[ $scanCon::SCAN_SLUG ] = [
111
+ 'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), __( 'Plugins & Themes', 'wp-simple-firewall' ) ),
112
+ 'summary' => $isPTG ?
113
  __( 'Plugins and Themes are guarded against tampering', 'wp-simple-firewall' )
114
  : __( "Plugins and Themes are never scanned for tampering!", 'wp-simple-firewall' ),
115
+ 'state' => $isPTG ? 1 : -2,
116
+ 'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
117
  'help' => __( 'Automatic detection of plugin/theme modifications is recommended.', 'wp-simple-firewall' ),
118
  ];
119
+
120
+ $status = $scanCon->getScansController()->getScanResultsCount();
121
+ if ( $isPTG && ( $status->countPluginFiles() + $status->countPluginFiles() ) > 0 ) {
122
  $cards[ 'ptg_problem' ] = [
123
+ 'name' => sprintf( '%s: %s', __( 'Modified', 'wp-simple-firewall' ), __( 'Plugins & Themes', 'wp-simple-firewall' ) ),
124
  'summary' => __( 'A plugin/theme was found to have been modified.', 'wp-simple-firewall' ),
125
  'state' => -2,
126
  'href' => $this->getUrlForScanResults(),
127
  'help' => __( 'Reviewing modifications to your plugins/themes is recommended.', 'wp-simple-firewall' ),
 
128
  ];
129
  }
130
 
134
  private function getCardsForMal() :array {
135
  /** @var HackGuard\ModCon $mod */
136
  $mod = $this->getMod();
137
+ /** @var Afs $scanCon */
138
+ $scanCon = $mod->getScanCon( Afs::SCAN_SLUG );
139
 
140
  $cards = [];
141
 
142
+ $malEnabled = $scanCon->isEnabledMalwareScan();
143
  $cards[ $scanCon::SCAN_SLUG ] = [
144
  'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
145
  'summary' => $malEnabled ?
146
  sprintf( __( '%s Scanner runs automatically.' ), $scanCon->getScanName() )
147
  : sprintf( __( "%s Scanner isn't set to run automatically." ), $scanCon->getScanName() ),
148
  'state' => $malEnabled ? 1 : -2,
149
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_file_guard' ),
150
  'help' => __( 'Automatic detection of Malware is recommended.', 'wp-simple-firewall' )
151
  ];
152
+ if ( $malEnabled && $scanCon->getScansController()->getScanResultsCount()->countMalware() ) {
153
  $cards[ 'mal_problem' ] = [
154
+ 'name' => __( 'Potential Malware Detected', 'wp-simple-firewall' ),
155
  'summary' => __( 'Potential Malware files have been discovered.', 'wp-simple-firewall' ),
156
  'state' => -2,
157
  'href' => $this->getUrlForScanResults(),
165
  private function getCardsForApc() :array {
166
  /** @var HackGuard\ModCon $mod */
167
  $mod = $this->getMod();
168
+ $scanCon = $mod->getScanCon( Apc::SCAN_SLUG );
169
 
170
  $cards = [];
171
 
172
+ $isAPC = $scanCon->isEnabled();
173
  $cards[ $scanCon::SCAN_SLUG ] = [
174
  'name' => sprintf( '%s: %s', __( 'Scanner', 'wp-simple-firewall' ), $scanCon->getScanName() ),
175
+ 'state' => $isAPC ? 1 : -1,
176
+ 'summary' => $isAPC ?
177
  sprintf( __( '%s Scanner is enabled.' ), $scanCon->getScanName() )
178
  : sprintf( __( '%s Scanner is not enabled.' ), $scanCon->getScanName() ),
179
  'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_apc' ),
180
  ];
181
+ if ( $isAPC && $scanCon->getScansController()->getScanResultsCount()->countAbandoned() > 0 ) {
182
  $cards[ 'apc_problem' ] = [
183
  'name' => __( 'Plugin Abandoned' ),
184
  'summary' => __( 'At least 1 plugin on your site is abandoned.', 'wp-simple-firewall' ),
194
  private function getCardsForWpv() :array {
195
  /** @var HackGuard\ModCon $mod */
196
  $mod = $this->getMod();
197
+ $scanCon = $mod->getScanCon( Wpv::SCAN_SLUG );
198
 
199
  $cards = [];
200
 
220
  'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
221
  ];
222
  }
223
+ if ( $enabledWpv && $scanCon->getScansController()->getScanResultsCount()->countVulnerableAssets() > 0 ) {
224
  $cards[ 'wpv_problem' ] = [
225
  'name' => __( 'Vulnerable Plugin', 'wp-simple-firewall' ),
226
  'summary' => __( 'Plugin with vulnerabilities found on site.', 'wp-simple-firewall' ),
233
  return $cards;
234
  }
235
 
236
+ private function getUrlForScanResults() :string {
237
  return $this->getCon()->getModule_Insights()->getUrl_ScansResults();
238
  }
239
  }
src/lib/src/Modules/HackGuard/Lib/FileLocker/FileLockerController.php CHANGED
@@ -84,9 +84,10 @@ class FileLockerController {
84
 
85
  public function handleFileDownloadRequest() {
86
  $req = Services::Request();
87
- $lock = $this->getFileLock( (int)$req->query( 'rid', 0 ) );
88
 
89
- if ( $lock instanceof FileLocker\EntryVO ) {
 
 
90
  $type = $req->query( 'type' );
91
 
92
  // Note: Download what's on the disk if nothing is changed.
@@ -108,8 +109,11 @@ class FileLockerController {
108
  ->downloadStringAsFile( $content, strtoupper( $type ).'-'.basename( $lock->file ) );
109
  }
110
  }
 
 
 
111
 
112
- wp_die( "Something about this request wasn't right" );
113
  }
114
 
115
  public function deleteAllLocks() {
@@ -125,13 +129,16 @@ class FileLockerController {
125
  }
126
 
127
  /**
128
- * @param int $ID
129
- * @return FileLocker\EntryVO|null
130
  */
131
- public function getFileLock( $ID ) {
132
- return ( new Lib\FileLocker\Ops\LoadFileLocks() )
133
- ->setMod( $this->getMod() )
134
- ->loadLocks()[ $ID ] ?? null;
 
 
 
 
135
  }
136
 
137
  public function runAnalysis() {
84
 
85
  public function handleFileDownloadRequest() {
86
  $req = Services::Request();
 
87
 
88
+ $dieMsg = "Something about this request wasn't right";
89
+ try {
90
+ $lock = $this->getFileLock( (int)$req->query( 'rid', 0 ) );
91
  $type = $req->query( 'type' );
92
 
93
  // Note: Download what's on the disk if nothing is changed.
109
  ->downloadStringAsFile( $content, strtoupper( $type ).'-'.basename( $lock->file ) );
110
  }
111
  }
112
+ catch ( \Exception $e ) {
113
+ $dieMsg = $e->getMessage();
114
+ }
115
 
116
+ wp_die( $dieMsg );
117
  }
118
 
119
  public function deleteAllLocks() {
129
  }
130
 
131
  /**
132
+ * @throws \Exception
 
133
  */
134
+ public function getFileLock( int $ID ) :FileLocker\EntryVO {
135
+ $lock = ( new Lib\FileLocker\Ops\LoadFileLocks() )
136
+ ->setMod( $this->getMod() )
137
+ ->loadLocks()[ $ID ] ?? null;
138
+ if ( empty( $lock ) ) {
139
+ throw new \Exception( 'Not a valid Lock File record' );
140
+ }
141
+ return $lock;
142
  }
143
 
144
  public function runAnalysis() {
src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/Diff.php CHANGED
@@ -6,14 +6,9 @@ use FernleafSystems\Wordpress\Plugin\Shield\Databases\FileLocker;
6
  use FernleafSystems\Wordpress\Services\Services;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes;
8
 
9
- /**
10
- * Class Diff
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops
12
- */
13
  class Diff extends BaseOps {
14
 
15
  /**
16
- * @param FileLocker\EntryVO $lock
17
  * @return string
18
  * @throws \Exception
19
  */
@@ -68,14 +63,11 @@ class Diff extends BaseOps {
68
  }
69
 
70
  /**
71
- * @param string $sOriginal
72
- * @param string $sCurrent
73
  * @return string
74
  */
75
- private function useWpDiff( $sOriginal, $sCurrent ) {
76
- return wp_text_diff(
77
- $sOriginal,
78
- $sCurrent
79
- );
80
  }
81
  }
6
  use FernleafSystems\Wordpress\Services\Services;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes;
8
 
 
 
 
 
9
  class Diff extends BaseOps {
10
 
11
  /**
 
12
  * @return string
13
  * @throws \Exception
14
  */
63
  }
64
 
65
  /**
66
+ * @param string $original
67
+ * @param string $current
68
  * @return string
69
  */
70
+ private function useWpDiff( $original, $current ) :string {
71
+ return wp_text_diff( $original, $current );
 
 
 
72
  }
73
  }
src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/PerformAction.php CHANGED
@@ -3,36 +3,14 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
 
8
- /**
9
- * Class PerformAction
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops
11
- */
12
  class PerformAction extends BaseOps {
13
 
14
  /**
15
- * @param int $lockID
16
- * @param string $action
17
- * @return string
18
  * @throws \Exception
19
  */
20
- public function run( $lockID, $action ) {
21
- /** @var ModCon $mod */
22
- $mod = $this->getMod();
23
-
24
- if ( !in_array( $action, [ 'accept', 'restore', 'diff' ] ) ) {
25
- throw new \Exception( __( 'Not a supported file lock action.', 'wp-simple-firewall' ) );
26
- }
27
- if ( !is_numeric( $lockID ) ) {
28
- throw new \Exception( __( 'Please select a valid file.', 'wp-simple-firewall' ) );
29
- }
30
- $lock = $mod->getDbHandler_FileLocker()
31
- ->getQuerySelector()
32
- ->byId( (int)$lockID );
33
- if ( !$lock instanceof Databases\FileLocker\EntryVO ) {
34
- throw new \Exception( __( 'Not valid file lock ID.', 'wp-simple-firewall' ) );
35
- }
36
 
37
  switch ( $action ) {
38
  case 'accept':
@@ -51,8 +29,7 @@ class PerformAction extends BaseOps {
51
  ->run( $lock );
52
  break;
53
  default:
54
- $mResult = false;
55
- break;
56
  }
57
  return $mResult;
58
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
 
6
 
 
 
 
 
7
  class PerformAction extends BaseOps {
8
 
9
  /**
10
+ * @return bool|string
 
 
11
  * @throws \Exception
12
  */
13
+ public function run( Databases\FileLocker\EntryVO $lock, string $action ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  switch ( $action ) {
16
  case 'accept':
29
  ->run( $lock );
30
  break;
31
  default:
32
+ throw new \Exception( __( 'Not a supported file lock action.', 'wp-simple-firewall' ) );
 
33
  }
34
  return $mResult;
35
  }
src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/ReadOriginalFileContent.php CHANGED
@@ -7,17 +7,12 @@ use FernleafSystems\Wordpress\Plugin\Shield\ShieldNetApi\FileLocker\DecryptFile;
7
  use FernleafSystems\Wordpress\Services\Services;
8
  use FernleafSystems\Wordpress\Services\Utilities\Encrypt\OpenSslEncryptVo;
9
 
10
- /**
11
- * Class ReadOriginalFileContent
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops
13
- */
14
  class ReadOriginalFileContent extends BaseOps {
15
 
16
  /**
17
- * @param Databases\FileLocker\EntryVO $lock
18
  * @return string
19
  */
20
- public function run( $lock ) {
21
  try {
22
  $content = $this->useOriginalFile( $lock );
23
  }
@@ -28,21 +23,18 @@ class ReadOriginalFileContent extends BaseOps {
28
  }
29
 
30
  /**
31
- * @param Databases\FileLocker\EntryVO $lock
32
- * @return string|null
33
  * @throws \Exception
34
  */
35
- private function useOriginalFile( Databases\FileLocker\EntryVO $lock ) {
36
  $FS = Services::WpFs();
37
  if ( empty( $lock->detected_at ) && empty( $lock->hash_current )
38
  && $FS->exists( $lock->file ) ) {
39
- return $FS->getFileContent( $lock->file );
40
  }
41
  throw new \Exception( 'Cannot use original file' );
42
  }
43
 
44
  /**
45
- * @param Databases\FileLocker\EntryVO $lock
46
  * @return string|null
47
  */
48
  private function useCacheAndApi( Databases\FileLocker\EntryVO $lock ) {
7
  use FernleafSystems\Wordpress\Services\Services;
8
  use FernleafSystems\Wordpress\Services\Utilities\Encrypt\OpenSslEncryptVo;
9
 
 
 
 
 
10
  class ReadOriginalFileContent extends BaseOps {
11
 
12
  /**
 
13
  * @return string
14
  */
15
+ public function run( Databases\FileLocker\EntryVO $lock ) {
16
  try {
17
  $content = $this->useOriginalFile( $lock );
18
  }
23
  }
24
 
25
  /**
 
 
26
  * @throws \Exception
27
  */
28
+ private function useOriginalFile( Databases\FileLocker\EntryVO $lock ) :string {
29
  $FS = Services::WpFs();
30
  if ( empty( $lock->detected_at ) && empty( $lock->hash_current )
31
  && $FS->exists( $lock->file ) ) {
32
+ return (string)$FS->getFileContent( $lock->file );
33
  }
34
  throw new \Exception( 'Cannot use original file' );
35
  }
36
 
37
  /**
 
38
  * @return string|null
39
  */
40
  private function useCacheAndApi( Databases\FileLocker\EntryVO $lock ) {
src/lib/src/Modules/HackGuard/Lib/FileLocker/Ops/Restore.php CHANGED
@@ -6,20 +6,16 @@ use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
- /**
10
- * Class Restore
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops
12
- */
13
  class Restore extends BaseOps {
14
 
15
  public function run( Databases\FileLocker\EntryVO $record ) :bool {
16
- $bReverted = Services::WpFs()->putFileContent(
17
  $record->file,
18
  ( new ReadOriginalFileContent() )
19
  ->setMod( $this->getMod() )
20
  ->run( $record )
21
  );
22
- if ( $bReverted ) {
23
  /** @var ModCon $mod */
24
  $mod = $this->getMod();
25
  /** @var Databases\FileLocker\Update $update */
@@ -27,6 +23,6 @@ class Restore extends BaseOps {
27
  $update->markReverted( $record );
28
  $this->clearFileLocksCache();
29
  }
30
- return $bReverted;
31
  }
32
  }
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
 
 
 
 
9
  class Restore extends BaseOps {
10
 
11
  public function run( Databases\FileLocker\EntryVO $record ) :bool {
12
+ $reverted = Services::WpFs()->putFileContent(
13
  $record->file,
14
  ( new ReadOriginalFileContent() )
15
  ->setMod( $this->getMod() )
16
  ->run( $record )
17
  );
18
+ if ( $reverted ) {
19
  /** @var ModCon $mod */
20
  $mod = $this->getMod();
21
  /** @var Databases\FileLocker\Update $update */
23
  $update->markReverted( $record );
24
  $this->clearFileLocksCache();
25
  }
26
+ return $reverted;
27
  }
28
  }
src/lib/src/Modules/HackGuard/Lib/Hashes/Exceptions/AssetHashesNotFound.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\Exceptions;
4
+
5
+ class AssetHashesNotFound extends \Exception {
6
+
7
+ }
src/lib/src/Modules/HackGuard/Lib/Hashes/Exceptions/NoneAssetFileException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\Exceptions;
4
+
5
+ class NoneAssetFileException extends \Exception {
6
+
7
+ }
src/lib/src/Modules/HackGuard/Lib/Hashes/Exceptions/UnrecognisedAssetFile.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\Exceptions;
4
+
5
+ class UnrecognisedAssetFile extends \Exception {
6
+
7
+ }
src/lib/src/Modules/HackGuard/Lib/Hashes/Query.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\Exceptions\{
6
+ AssetHashesNotFound,
7
+ NoneAssetFileException,
8
+ UnrecognisedAssetFile
9
+ };
10
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
11
+ use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
12
+ WpPluginVo,
13
+ WpThemeVo
14
+ };
15
+ use FernleafSystems\Wordpress\Services\Utilities\File\Compare\CompareHash;
16
+ use FernleafSystems\Wordpress\Services\Utilities\WpOrg\{
17
+ Plugin,
18
+ Theme
19
+ };
20
+
21
+ class Query {
22
+
23
+ use ModConsumer;
24
+
25
+ /**
26
+ * @param string $path
27
+ * @return array
28
+ * @throws AssetHashesNotFound
29
+ * @throws NoneAssetFileException
30
+ * @throws UnrecognisedAssetFile
31
+ * @throws \Exception
32
+ */
33
+ public function getHashesForFile( string $path ) :array {
34
+
35
+ $vo = $this->findAssetFromPath( $path );
36
+
37
+ if ( $vo->asset_type === 'plugin' ) {
38
+ $fragment = ( new Plugin\Files() )->getRelativeFilePathFromItsInstallDir( $path );
39
+ }
40
+ else {
41
+ $fragment = ( new Theme\Files() )->getRelativeFilePathFromItsInstallDir( $path );
42
+ }
43
+
44
+ $assetHashes = ( new Retrieve() )
45
+ ->setMod( $this->getMod() )
46
+ ->byVO( $vo );
47
+ $hash = $assetHashes[ $fragment ] ?? ( $assetHashes[ strtolower( $fragment ) ] ?? null );
48
+ if ( empty( $hash ) ) {
49
+ throw new UnrecognisedAssetFile( sprintf( 'No hashes exist for file: %s', $path ) );
50
+ }
51
+
52
+ return is_array( $hash ) ? $hash : [ $hash ];
53
+ }
54
+
55
+ /**
56
+ * @param string $path
57
+ * @return WpPluginVo|WpThemeVo
58
+ * @throws NoneAssetFileException
59
+ */
60
+ private function findAssetFromPath( string $path ) {
61
+ $vo = ( new Plugin\Files() )->findPluginFromFile( $path );;
62
+ if ( empty( $vo ) ) {
63
+ $vo = ( new Theme\Files() )->findThemeFromFile( $path );
64
+ if ( empty( $vo ) ) {
65
+ throw new NoneAssetFileException( 'Not a plugin or theme file path' );
66
+ }
67
+ }
68
+ return $vo;
69
+ }
70
+
71
+ /**
72
+ * @throws AssetHashesNotFound
73
+ * @throws NoneAssetFileException
74
+ * @throws \Exception
75
+ */
76
+ public function fileExistsInHash( string $path ) :bool {
77
+ try {
78
+ $exists = !empty( $this->getHashesForFile( $path ) );
79
+ }
80
+ catch ( UnrecognisedAssetFile $e ) {
81
+ $exists = false;
82
+ }
83
+ return $exists;
84
+ }
85
+
86
+ /**
87
+ * @param string $fullPath
88
+ * @return bool
89
+ * @throws AssetHashesNotFound
90
+ * @throws NoneAssetFileException
91
+ * @throws UnrecognisedAssetFile
92
+ * @throws \InvalidArgumentException
93
+ */
94
+ public function verifyHash( string $fullPath ) :bool {
95
+ $verified = false;
96
+ $compare = new CompareHash();
97
+ foreach ( $this->getHashesForFile( $fullPath ) as $hash ) {
98
+ if ( $compare->isEqualFile( $fullPath, $hash ) ) {
99
+ $verified = true;
100
+ break;
101
+ }
102
+ }
103
+ return $verified;
104
+ }
105
+ }
src/lib/src/Modules/HackGuard/Lib/Hashes/Retrieve.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\Exceptions\AssetHashesNotFound;
6
+ use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\CrowdSourcedHashes\Query;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction;
9
+ use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
10
+ WpPluginVo,
11
+ WpThemeVo
12
+ };
13
+ use FernleafSystems\Wordpress\Services\Services;
14
+
15
+ class Retrieve {
16
+
17
+ use ModConsumer;
18
+
19
+ private static $hashes;
20
+
21
+ public function __construct() {
22
+ if ( !isset( self::$hashes ) ) {
23
+ self::$hashes = [
24
+ 'plugins' => [],
25
+ 'themes' => [],
26
+ ];
27
+ }
28
+ }
29
+
30
+ /**
31
+ * @param WpPluginVo|WpThemeVo $vo
32
+ * @param array $hashes
33
+ */
34
+ private function addItemHashesToCache( $vo, array $hashes ) {
35
+ if ( $vo->asset_type == 'plugin' ) {
36
+ self::$hashes[ 'plugins' ][ $vo->slug ] = $hashes;
37
+ }
38
+ else {
39
+ self::$hashes[ 'themes' ][ $vo->slug ] = $hashes;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * @param WpPluginVo|WpThemeVo $vo
45
+ * @return array
46
+ */
47
+ private function getAssetHashesFromCache( $vo ) {
48
+ $key = ( $vo->asset_type == 'plugin' ) ? 'plugins' : 'themes';
49
+ return self::$hashes[ $key ][ $vo->slug ] ?? null;
50
+ }
51
+
52
+ /**
53
+ * @param WpPluginVo|WpThemeVo $vo
54
+ * @throws \Exception
55
+ */
56
+ private function fromLocalStore( $vo ) :array {
57
+ return ( new StoreAction\Load() )
58
+ ->setMod( $this->getMod() )
59
+ ->setAsset( $vo )
60
+ ->run()
61
+ ->getSnapData();
62
+ }
63
+
64
+ /**
65
+ * @param string $slug
66
+ * @return array
67
+ * @throws AssetHashesNotFound
68
+ * @throws \Exception
69
+ */
70
+ public function bySlug( string $slug ) :array {
71
+ $vo = Services::WpPlugins()->getPluginAsVo( $slug );
72
+ if ( empty( $vo ) ) {
73
+ $vo = Services::WpThemes()->getThemeAsVo( $slug );
74
+ if ( empty( $vo ) ) {
75
+ throw new \Exception( sprintf( 'Plugin or theme not installed for slug: %s', $slug ) );
76
+ }
77
+ }
78
+ return $this->byVO( $vo );
79
+ }
80
+
81
+ /**
82
+ * @param WpPluginVo|WpThemeVo $vo
83
+ * @return array
84
+ * @throws AssetHashesNotFound|\Exception
85
+ */
86
+ public function byVO( $vo ) :array {
87
+ $hashes = $this->getAssetHashesFromCache( $vo );
88
+
89
+ if ( is_null( $hashes ) ) {
90
+ $hashes = $this->fromCsHashes( $vo );
91
+ if ( empty( $hashes ) ) {
92
+ try {
93
+ $hashes = $this->fromLocalStore( $vo );
94
+ }
95
+ catch ( \Exception $e ) {
96
+ $hashes = [];
97
+ }
98
+ }
99
+ $this->addItemHashesToCache( $vo, $hashes );
100
+ }
101
+
102
+ if ( empty( $hashes ) ) {
103
+ throw new AssetHashesNotFound( sprintf( 'Could not locate hashes for VO: %s', $vo->slug ) );
104
+ }
105
+ return $hashes;
106
+ }
107
+
108
+ /**
109
+ * @param WpPluginVo|WpThemeVo $vo
110
+ * @return array
111
+ */
112
+ public function fromCsHashes( $vo ) :array {
113
+ $query = ( $vo->asset_type == 'plugin' ) ? new Query\Plugin() : new Query\Theme();
114
+ return $query->getHashesFromVO( $vo );
115
+ }
116
+ }
src/lib/src/Modules/HackGuard/Lib/Reports/Query/ScanCounts.php CHANGED
@@ -2,40 +2,17 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Reports\Query;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
 
 
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
- use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class ScanCounts {
11
 
12
  use ModConsumer;
13
 
14
- /**
15
- * @var int
16
- */
17
- public $from;
18
-
19
- /**
20
- * @var int
21
- */
22
- public $to;
23
-
24
- /**
25
- * @var bool
26
- */
27
- public $ignored = false;
28
-
29
- /**
30
- * @var bool
31
- */
32
- public $notified = false;
33
-
34
- public function __construct( $from = null, $to = null ) {
35
- $this->from = is_int( $from ) ? $from : 0;
36
- $this->to = is_int( $to ) ? $to : Services::Request()->ts();
37
- }
38
-
39
  /**
40
  * @return int[] - key is scan slug
41
  */
@@ -63,24 +40,16 @@ class ScanCounts {
63
  public function standard() :array {
64
  /** @var HackGuard\ModCon $mod */
65
  $mod = $this->getMod();
66
- /** @var HackGuard\Options $opts */
67
- $opts = $this->getOptions();
68
- /** @var Scanner\Select $qSel */
69
- $qSel = $mod->getDbHandler_ScanResults()->getQuerySelector();
70
 
71
  $counts = [];
72
-
73
- foreach ( $opts->getScanSlugs() as $slug ) {
74
- $qSel->filterByScan( $slug )
75
- ->filterByCreatedAt( $this->from, '>=' )
76
- ->filterByCreatedAt( $this->to, '<=' );
77
- if ( isset( $this->ignored ) ) {
78
- $this->ignored ? $qSel->filterByIgnored() : $qSel->filterByNotIgnored();
79
- }
80
- if ( isset( $this->notified ) ) {
81
- $this->notified ? $qSel->filterByNotified() : $qSel->filterByNotNotified();
82
- }
83
- $counts[ $slug ] = $qSel->count();
84
  }
85
 
86
  return $counts;
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Reports\Query;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\{
7
+ Scans,
8
+ ScanResults
9
+ };
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
 
11
 
12
  class ScanCounts {
13
 
14
  use ModConsumer;
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  /**
17
  * @return int[] - key is scan slug
18
  */
40
  public function standard() :array {
41
  /** @var HackGuard\ModCon $mod */
42
  $mod = $this->getMod();
 
 
 
 
43
 
44
  $counts = [];
45
+ foreach ( $mod->getScansCon()->getAllScanCons() as $scanCon ) {
46
+ $counts[ $scanCon->getSlug() ] = ( new HackGuard\Scan\Results\Retrieve() )
47
+ ->setMod( $this->getMod() )
48
+ ->setScanController( $scanCon )
49
+ ->setAdditionalWheres( [
50
+ "`ri`.notified_at=0",
51
+ ] )
52
+ ->count();
 
 
 
 
53
  }
54
 
55
  return $counts;
src/lib/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Reports;
4
 
@@ -15,9 +15,8 @@ class ScanAlerts extends BaseReporter {
15
  /** @var HackGuard\Strings $strings */
16
  $strings = $this->getMod()->getStrings();
17
 
18
- $rep = $this->getReport();
19
  $scanCounts = array_filter(
20
- ( new Query\ScanCounts( $rep->interval_start_at, $rep->interval_end_at ) )
21
  ->setMod( $this->getMod() )
22
  ->standard()
23
  );
@@ -59,11 +58,9 @@ class ScanAlerts extends BaseReporter {
59
  private function markAlertsAsNotified() {
60
  /** @var HackGuard\ModCon $mod */
61
  $mod = $this->getMod();
62
- /** @var Scanner\Update $updater */
63
- $updater = $mod->getDbHandler_ScanResults()->getQueryUpdater();
64
- $updater
65
  ->setUpdateWheres( [
66
- 'ignored_at' => 0,
67
  'notified_at' => 0,
68
  ] )
69
  ->setUpdateData( [
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Reports;
4
 
15
  /** @var HackGuard\Strings $strings */
16
  $strings = $this->getMod()->getStrings();
17
 
 
18
  $scanCounts = array_filter(
19
+ ( new Query\ScanCounts() )
20
  ->setMod( $this->getMod() )
21
  ->standard()
22
  );
58
  private function markAlertsAsNotified() {
59
  /** @var HackGuard\ModCon $mod */
60
  $mod = $this->getMod();
61
+ $mod->getDbH_ResultItems()
62
+ ->getQueryUpdater()
 
63
  ->setUpdateWheres( [
 
64
  'notified_at' => 0,
65
  ] )
66
  ->setUpdateData( [
src/lib/src/Modules/HackGuard/Lib/ScanTables/DelegateAjaxHandler.php CHANGED
@@ -5,6 +5,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTabl
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class DelegateAjaxHandler {
@@ -41,8 +42,6 @@ class DelegateAjaxHandler {
41
  }
42
 
43
  /**
44
- * @param string $action
45
- * @return array
46
  * @throws \Exception
47
  */
48
  private function doAction( string $action ) :array {
@@ -53,24 +52,23 @@ class DelegateAjaxHandler {
53
 
54
  $items = $this->getItemIDs();
55
 
56
- $resultIT = $mod->getDbHandler_ScanResults()->getIterator();
57
- $resultIT->setSelector(
58
- $resultIT->getSelector()->addWhereIn( 'id', $items )
59
- );
60
-
61
  $scanSlugs = [];
62
  $successfulItems = [];
63
-
64
- /** @var Databases\Scanner\EntryVO $entry */
65
- foreach ( $resultIT as $entry ) {
66
- $scanSlugs[ $entry->scan ] = 1;
67
- if ( $mod->getScanCon( $entry->scan )->executeEntryAction( $entry, $action ) ) {
68
- $successfulItems[] = $entry->id;
 
 
 
 
 
69
  }
70
  }
71
 
72
- $scanSlugs = array_keys( $scanSlugs );
73
-
74
  foreach ( $scanSlugs as $slug ) {
75
  $mod->getScanCon( $slug )->cleanStalesResults();
76
  }
@@ -80,13 +78,8 @@ class DelegateAjaxHandler {
80
  $msg = __( 'Action successful.' );
81
  }
82
  else {
83
- $msg = __( 'An error occurred.' ).' '.__( 'Some items may not have been processed.' );
84
- }
85
-
86
- // We don't rescan for ignores or malware
87
- $rescanSlugs = array_diff( $scanSlugs, [ HackGuard\Scan\Controller\Mal::SCAN_SLUG ] );
88
- if ( !empty( $rescanSlugs ) && !in_array( $action, [ 'ignore' ] ) ) {
89
- $mod->getScanQueueController()->startScans( $rescanSlugs );
90
  }
91
 
92
  return [
@@ -97,6 +90,9 @@ class DelegateAjaxHandler {
97
  ];
98
  }
99
 
 
 
 
100
  private function getItemIDs() :array {
101
  $items = Services::Request()->post( 'rids' );
102
  if ( empty( $items ) || !is_array( $items ) ) {
@@ -116,7 +112,6 @@ class DelegateAjaxHandler {
116
  }
117
 
118
  /**
119
- * @return array
120
  * @throws \Exception
121
  */
122
  private function viewFile() :array {
@@ -128,14 +123,13 @@ class DelegateAjaxHandler {
128
 
129
  return [
130
  'success' => true,
131
- 'vars' => ( new RetrieveFileContents() )
132
  ->setMod( $this->getMod() )
133
- ->retrieve( (int)$rid ),
134
  ];
135
  }
136
 
137
  /**
138
- * @return array
139
  * @throws \Exception
140
  */
141
  private function retrieveTableData() :array {
@@ -143,9 +137,9 @@ class DelegateAjaxHandler {
143
  return [
144
  'success' => true,
145
  'vars' => [
146
- 'data' => ( new LoadRawTableData() )
147
  ->setMod( $this->getMod() )
148
- ->loadFor( $req->post( 'type' ), $req->post( 'file' ) )
149
  ],
150
  ];
151
  }
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables\Modals\ScanItemView;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
  class DelegateAjaxHandler {
42
  }
43
 
44
  /**
 
 
45
  * @throws \Exception
46
  */
47
  private function doAction( string $action ) :array {
52
 
53
  $items = $this->getItemIDs();
54
 
 
 
 
 
 
55
  $scanSlugs = [];
56
  $successfulItems = [];
57
+ foreach ( $items as $itemID ) {
58
+ try {
59
+ $item = ( new HackGuard\Scan\Results\Retrieve() )
60
+ ->setMod( $this->getMod() )
61
+ ->byID( $itemID );
62
+ $scanSlugs[] = $item->VO->scan;
63
+ if ( $mod->getScanCon( $item->VO->scan )->executeItemAction( $item, $action ) ) {
64
+ $successfulItems[] = $item->VO->scanresult_id;
65
+ }
66
+ }
67
+ catch ( \Exception $e ) {
68
  }
69
  }
70
 
71
+ $scanSlugs = array_unique( $scanSlugs );
 
72
  foreach ( $scanSlugs as $slug ) {
73
  $mod->getScanCon( $slug )->cleanStalesResults();
74
  }
78
  $msg = __( 'Action successful.' );
79
  }
80
  else {
81
+ $msg = __( 'An error occurred.' )
82
+ .' '.__( 'Some items may not have been processed.' );
 
 
 
 
 
83
  }
84
 
85
  return [
90
  ];
91
  }
92
 
93
+ /**
94
+ * @throws \Exception
95
+ */
96
  private function getItemIDs() :array {
97
  $items = Services::Request()->post( 'rids' );
98
  if ( empty( $items ) || !is_array( $items ) ) {
112
  }
113
 
114
  /**
 
115
  * @throws \Exception
116
  */
117
  private function viewFile() :array {
123
 
124
  return [
125
  'success' => true,
126
+ 'vars' => ( new ScanItemView() )
127
  ->setMod( $this->getMod() )
128
+ ->run( (int)$rid ),
129
  ];
130
  }
131
 
132
  /**
 
133
  * @throws \Exception
134
  */
135
  private function retrieveTableData() :array {
137
  return [
138
  'success' => true,
139
  'vars' => [
140
+ 'data' => array_values( ( new LoadRawTableData() )
141
  ->setMod( $this->getMod() )
142
+ ->loadFor( $req->post( 'type' ), $req->post( 'file' ) ) )
143
  ],
144
  ];
145
  }
src/lib/src/Modules/HackGuard/Lib/ScanTables/LoadRawTableData.php CHANGED
@@ -4,12 +4,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTabl
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool\FormatBytes;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\{
8
- Mal,
9
- Ptg,
10
- Ufc,
11
- Wcf
12
- };
13
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
14
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
15
  use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
@@ -22,12 +17,7 @@ class LoadRawTableData {
22
 
23
  use ModConsumer;
24
 
25
- private static $GuardFiles;
26
-
27
  /**
28
- * @param string $type
29
- * @param string $file
30
- * @return array
31
  * @throws \Exception
32
  */
33
  public function loadFor( string $type, string $file ) :array {
@@ -65,15 +55,20 @@ class LoadRawTableData {
65
  return $data;
66
  }
67
 
 
 
 
68
  public function loadForMalware() :array {
69
  /** @var ModCon $mod */
70
  $mod = $this->getMod();
 
 
71
  return array_map(
72
  function ( $item ) {
73
- /** @var Scans\Mal\ResultItem $item */
74
  $data = $item->getRawData();
75
 
76
- $data[ 'rid' ] = $item->VO->id;
77
  $data[ 'file' ] = $item->path_fragment;
78
  $data[ 'detected_at' ] = $item->VO->created_at;
79
  $data[ 'detected_since' ] = Services::Request()
@@ -88,37 +83,61 @@ class LoadRawTableData {
88
 
89
  $data[ 'line_numbers' ] = implode( ', ', array_map(
90
  function ( $line ) {
91
- return $line + 1;
92
  },
93
- $item->file_lines // because lines start at ZERO
94
  ) );
95
- $data[ 'mal_sig' ] = sprintf( '<code style="white-space: nowrap">%s</code>', esc_html( base64_decode( $item->mal_sig ) ) );
96
  $data[ 'file_type' ] = strtoupper( Services::Data()->getExtension( $item->path_full ) );
97
  $data[ 'actions' ] = implode( ' ', $this->getActions( $data[ 'status_slug' ], $item ) );
98
 
99
  return $data;
100
  },
101
- $mod->getScanCon( Mal::SCAN_SLUG )->getAllResults()->getItems()
102
  );
103
  }
104
 
 
 
 
105
  public function loadForPlugin( WpPluginVo $plugin ) :array {
106
- return $this->getGuardFilesDataFor( $plugin );
 
 
 
 
 
 
107
  }
108
 
 
 
 
109
  public function loadForTheme( WpThemeVo $theme ) :array {
110
- return $this->getGuardFilesDataFor( $theme );
 
 
 
 
 
 
111
  }
112
 
 
 
 
113
  public function loadForWordPress() :array {
114
  /** @var ModCon $mod */
115
  $mod = $this->getMod();
 
 
116
  try {
117
  $files = array_map(
118
  function ( $item ) {
119
- /** @var Scans\Wcf\ResultItem|Scans\Ufc\ResultItem $item */
120
  $data = $item->getRawData();
121
- $data[ 'rid' ] = $item->VO->id;
 
122
  $data[ 'file' ] = $item->path_fragment;
123
  $data[ 'detected_at' ] = $item->VO->created_at;
124
  $data[ 'detected_since' ] = Services::Request()
@@ -126,12 +145,7 @@ class LoadRawTableData {
126
  ->setTimestamp( $item->VO->created_at )
127
  ->diffForHumans();
128
 
129
- if ( !$item->is_missing ) {
130
- $data[ 'file_as_href' ] = $this->getColumnContent_File( $item );
131
- }
132
- else {
133
- $data[ 'file_as_href' ] = $item->path_fragment;
134
- }
135
 
136
  if ( $item->is_checksumfail ) {
137
  $data[ 'status_slug' ] = 'modified';
@@ -151,10 +165,7 @@ class LoadRawTableData {
151
  $data[ 'actions' ] = implode( ' ', $this->getActions( $data[ 'status_slug' ], $item ) );
152
  return $data;
153
  },
154
- array_merge(
155
- $mod->getScanCon( Wcf::SCAN_SLUG )->getAllResults()->getItems(),
156
- $mod->getScanCon( Ufc::SCAN_SLUG )->getAllResults()->getItems()
157
- )
158
  );
159
  }
160
  catch ( \Exception $e ) {
@@ -165,15 +176,17 @@ class LoadRawTableData {
165
  }
166
 
167
  /**
168
- * @param WpPluginVo|WpThemeVo $item
169
  * @return array
 
170
  */
171
- private function getGuardFilesDataFor( $item ) :array {
172
  return array_map(
173
  function ( $item ) {
 
174
 
175
  $data = $item->getRawData();
176
- $data[ 'rid' ] = $item->VO->id;
177
  $data[ 'file' ] = $item->path_fragment;
178
  $data[ 'detected_at' ] = $item->VO->created_at;
179
  $data[ 'detected_since' ] = Services::Request()
@@ -181,7 +194,7 @@ class LoadRawTableData {
181
  ->setTimestamp( $item->VO->created_at )
182
  ->diffForHumans();
183
 
184
- if ( $item->is_different ) {
185
  $data[ 'status_slug' ] = 'modified';
186
  $data[ 'status' ] = __( 'Modified', 'wp-simple-firewall' );
187
  }
@@ -195,18 +208,13 @@ class LoadRawTableData {
195
  }
196
  $data[ 'status' ] = $this->getColumnContent_FileStatus( $item, $data[ 'status' ] );
197
 
198
- if ( !$item->is_missing ) {
199
- $data[ 'file_as_href' ] = $this->getColumnContent_File( $item );
200
- }
201
- else {
202
- $data[ 'file_as_href' ] = $item->path_fragment;
203
- }
204
 
205
  $data[ 'file_type' ] = strtoupper( Services::Data()->getExtension( $item->path_full ) );
206
  $data[ 'actions' ] = implode( ' ', $this->getActions( $data[ 'status_slug' ], $item ) );
207
  return $data;
208
  },
209
- $this->getGuardFiles()->getItemsForSlug( $item->asset_type === 'plugin' ? $item->file : $item->stylesheet )
210
  );
211
  }
212
 
@@ -231,22 +239,31 @@ class LoadRawTableData {
231
  'action',
232
  ];
233
 
 
 
 
 
 
 
 
 
 
234
  if ( in_array( $status, [ 'unrecognised', 'malware' ] ) ) {
235
  $actions[] = sprintf( '<button class="btn-danger delete %s" title="%s" data-rid="%s">%s</button>',
236
  implode( ' ', $defaultButtonClasses ),
237
  __( 'Delete', 'wp-simple-firewall' ),
238
- $item->VO->id,
239
  $con->svgs->raw( 'bootstrap/x-square.svg' )
240
  );
241
  }
242
 
243
  try {
244
- if ( in_array( $status, [ 'modified', 'missing', 'malware' ] ) && $actionHandler->getRepairer()
245
- ->canRepair() ) {
246
  $actions[] = sprintf( '<button class="btn-warning repair %s" title="%s" data-rid="%s">%s</button>',
247
  implode( ' ', $defaultButtonClasses ),
248
  __( 'Repair', 'wp-simple-firewall' ),
249
- $item->VO->id,
250
  $con->svgs->raw( 'bootstrap/tools.svg' )
251
  );
252
  }
@@ -254,44 +271,21 @@ class LoadRawTableData {
254
  catch ( \Exception $e ) {
255
  }
256
 
257
- if ( in_array( $status, [ 'modified', 'unrecognised', 'malware' ] ) ) {
258
- $actions[] = sprintf( '<button class="btn-dark href-download %s" title="%s" data-href-download="%s">%s</button>',
259
- implode( ' ', $defaultButtonClasses ),
260
- __( 'Download', 'wp-simple-firewall' ),
261
- $mod->getScanCon( $item->VO->scan )->createFileDownloadLink( $item->VO->id ),
262
- $con->svgs->raw( 'bootstrap/download.svg' )
263
- );
264
- }
265
-
266
  $actions[] = sprintf( '<button class="btn-light ignore %s" title="%s" data-rid="%s">%s</button>',
267
  implode( ' ', $defaultButtonClasses ),
268
  __( 'Ignore', 'wp-simple-firewall' ),
269
- $item->VO->id,
270
  $con->svgs->raw( 'bootstrap/eye-slash-fill.svg' )
271
  );
272
 
273
  return $actions;
274
  }
275
 
276
- private function getGuardFiles() :Scans\Ptg\ResultsSet {
277
- /** @var ModCon $mod */
278
- $mod = $this->getMod();
279
- if ( !isset( self::$GuardFiles ) ) {
280
- try {
281
- self::$GuardFiles = $mod->getScanCon( Ptg::SCAN_SLUG )->getAllResults();
282
- }
283
- catch ( \Exception $e ) {
284
- self::$GuardFiles = new Scans\Ptg\ResultsSet();
285
- }
286
- }
287
- return self::$GuardFiles;
288
- }
289
-
290
- private function getColumnContent_File( Scans\Base\FileResultItem $item ) :string {
291
  return sprintf( '<div>%s</div>', $this->getColumnContent_FileAsHref( $item ) );
292
  }
293
 
294
- private function getColumnContent_FileStatus( Scans\Base\FileResultItem $item, string $status ) :string {
295
  $content = $status;
296
 
297
  $FS = Services::WpFs();
@@ -314,10 +308,10 @@ class LoadRawTableData {
314
  return $content;
315
  }
316
 
317
- private function getColumnContent_FileAsHref( Scans\Base\FileResultItem $item ) :string {
318
  return sprintf( '<a href="#" title="%s" class="action view-file" data-rid="%s">%s</a>',
319
  __( 'View File Contents', 'wp-simple-firewall' ),
320
- $item->VO->id,
321
  $item->path_fragment
322
  );
323
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool\FormatBytes;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Afs;
 
 
 
 
 
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
10
  use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
17
 
18
  use ModConsumer;
19
 
 
 
20
  /**
 
 
 
21
  * @throws \Exception
22
  */
23
  public function loadFor( string $type, string $file ) :array {
55
  return $data;
56
  }
57
 
58
+ /**
59
+ * @throws \Exception
60
+ */
61
  public function loadForMalware() :array {
62
  /** @var ModCon $mod */
63
  $mod = $this->getMod();
64
+ /** @var Scans\Afs\ResultsSet $RS */
65
+ $RS = $mod->getScanCon( Afs::SCAN_SLUG )->getResultsForDisplay();
66
  return array_map(
67
  function ( $item ) {
68
+ /** @var Scans\Afs\ResultItem $item */
69
  $data = $item->getRawData();
70
 
71
+ $data[ 'rid' ] = $item->VO->scanresult_id;
72
  $data[ 'file' ] = $item->path_fragment;
73
  $data[ 'detected_at' ] = $item->VO->created_at;
74
  $data[ 'detected_since' ] = Services::Request()
83
 
84
  $data[ 'line_numbers' ] = implode( ', ', array_map(
85
  function ( $line ) {
86
+ return $line + 1; // because lines start at ZERO
87
  },
88
+ array_keys( $item->mal_fp_lines )
89
  ) );
90
+ $data[ 'mal_sig' ] = sprintf( '<code style="white-space: nowrap">%s</code>', esc_html( $item->mal_sig ) );
91
  $data[ 'file_type' ] = strtoupper( Services::Data()->getExtension( $item->path_full ) );
92
  $data[ 'actions' ] = implode( ' ', $this->getActions( $data[ 'status_slug' ], $item ) );
93
 
94
  return $data;
95
  },
96
+ $RS->getMalware()->getItems()
97
  );
98
  }
99
 
100
+ /**
101
+ * @throws \Exception
102
+ */
103
  public function loadForPlugin( WpPluginVo $plugin ) :array {
104
+ /** @var ModCon $mod */
105
+ $mod = $this->getMod();
106
+ /** @var Scans\Afs\ResultsSet $RS */
107
+ $RS = $mod->getScanCon( Afs::SCAN_SLUG )->getResultsForDisplay();
108
+ return $this->getGuardFilesDataFor(
109
+ $RS->getForPlugin( $plugin->unique_id )
110
+ );
111
  }
112
 
113
+ /**
114
+ * @throws \Exception
115
+ */
116
  public function loadForTheme( WpThemeVo $theme ) :array {
117
+ /** @var ModCon $mod */
118
+ $mod = $this->getMod();
119
+ /** @var Scans\Afs\ResultsSet $RS */
120
+ $RS = $mod->getScanCon( Afs::SCAN_SLUG )->getResultsForDisplay();
121
+ return $this->getGuardFilesDataFor(
122
+ $RS->getForTheme( $theme->unique_id )
123
+ );
124
  }
125
 
126
+ /**
127
+ * @throws \Exception
128
+ */
129
  public function loadForWordPress() :array {
130
  /** @var ModCon $mod */
131
  $mod = $this->getMod();
132
+ /** @var Scans\Afs\ResultsSet $RS */
133
+ $RS = $mod->getScanCon( Afs::SCAN_SLUG )->getResultsForDisplay();
134
  try {
135
  $files = array_map(
136
  function ( $item ) {
137
+ /** @var Scans\Afs\ResultItem $item */
138
  $data = $item->getRawData();
139
+
140
+ $data[ 'rid' ] = $item->VO->scanresult_id;
141
  $data[ 'file' ] = $item->path_fragment;
142
  $data[ 'detected_at' ] = $item->VO->created_at;
143
  $data[ 'detected_since' ] = Services::Request()
145
  ->setTimestamp( $item->VO->created_at )
146
  ->diffForHumans();
147
 
148
+ $data[ 'file_as_href' ] = $this->getColumnContent_File( $item );
 
 
 
 
 
149
 
150
  if ( $item->is_checksumfail ) {
151
  $data[ 'status_slug' ] = 'modified';
165
  $data[ 'actions' ] = implode( ' ', $this->getActions( $data[ 'status_slug' ], $item ) );
166
  return $data;
167
  },
168
+ $RS->getWordpressCore()->getItems()
 
 
 
169
  );
170
  }
171
  catch ( \Exception $e ) {
176
  }
177
 
178
  /**
179
+ * @param Scans\Afs\ResultsSet $results
180
  * @return array
181
+ * @throws \Exception
182
  */
183
+ private function getGuardFilesDataFor( Scans\Afs\ResultsSet $results ) :array {
184
  return array_map(
185
  function ( $item ) {
186
+ /** @var Scans\Afs\ResultItem $item */
187
 
188
  $data = $item->getRawData();
189
+ $data[ 'rid' ] = $item->VO->scanresult_id;
190
  $data[ 'file' ] = $item->path_fragment;
191
  $data[ 'detected_at' ] = $item->VO->created_at;
192
  $data[ 'detected_since' ] = Services::Request()
194
  ->setTimestamp( $item->VO->created_at )
195
  ->diffForHumans();
196
 
197
+ if ( $item->is_checksumfail ) {
198
  $data[ 'status_slug' ] = 'modified';
199
  $data[ 'status' ] = __( 'Modified', 'wp-simple-firewall' );
200
  }
208
  }
209
  $data[ 'status' ] = $this->getColumnContent_FileStatus( $item, $data[ 'status' ] );
210
 
211
+ $data[ 'file_as_href' ] = $this->getColumnContent_File( $item );
 
 
 
 
 
212
 
213
  $data[ 'file_type' ] = strtoupper( Services::Data()->getExtension( $item->path_full ) );
214
  $data[ 'actions' ] = implode( ' ', $this->getActions( $data[ 'status_slug' ], $item ) );
215
  return $data;
216
  },
217
+ $results->getItems()
218
  );
219
  }
220
 
239
  'action',
240
  ];
241
 
242
+ if ( !empty( $item->path_fragment ) ) {
243
+ $actions[] = sprintf( '<button class="action view-file btn-dark %s" title="%s" data-rid="%s">%s</button>',
244
+ implode( ' ', $defaultButtonClasses ),
245
+ __( 'View File Details', 'wp-simple-firewall' ),
246
+ $item->VO->scanresult_id,
247
+ $con->svgs->raw( 'bootstrap/zoom-in.svg' )
248
+ );
249
+ }
250
+
251
  if ( in_array( $status, [ 'unrecognised', 'malware' ] ) ) {
252
  $actions[] = sprintf( '<button class="btn-danger delete %s" title="%s" data-rid="%s">%s</button>',
253
  implode( ' ', $defaultButtonClasses ),
254
  __( 'Delete', 'wp-simple-firewall' ),
255
+ $item->VO->scanresult_id,
256
  $con->svgs->raw( 'bootstrap/x-square.svg' )
257
  );
258
  }
259
 
260
  try {
261
+ if ( in_array( $status, [ 'modified', 'missing', 'malware' ] )
262
+ && $actionHandler->getRepairHandler()->canRepairItem() ) {
263
  $actions[] = sprintf( '<button class="btn-warning repair %s" title="%s" data-rid="%s">%s</button>',
264
  implode( ' ', $defaultButtonClasses ),
265
  __( 'Repair', 'wp-simple-firewall' ),
266
+ $item->VO->scanresult_id,
267
  $con->svgs->raw( 'bootstrap/tools.svg' )
268
  );
269
  }
271
  catch ( \Exception $e ) {
272
  }
273
 
 
 
 
 
 
 
 
 
 
274
  $actions[] = sprintf( '<button class="btn-light ignore %s" title="%s" data-rid="%s">%s</button>',
275
  implode( ' ', $defaultButtonClasses ),
276
  __( 'Ignore', 'wp-simple-firewall' ),
277
+ $item->VO->scanresult_id,
278
  $con->svgs->raw( 'bootstrap/eye-slash-fill.svg' )
279
  );
280
 
281
  return $actions;
282
  }
283
 
284
+ private function getColumnContent_File( Scans\Afs\ResultItem $item ) :string {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  return sprintf( '<div>%s</div>', $this->getColumnContent_FileAsHref( $item ) );
286
  }
287
 
288
+ private function getColumnContent_FileStatus( Scans\Afs\ResultItem $item, string $status ) :string {
289
  $content = $status;
290
 
291
  $FS = Services::WpFs();
308
  return $content;
309
  }
310
 
311
+ private function getColumnContent_FileAsHref( Scans\Afs\ResultItem $item ) :string {
312
  return sprintf( '<a href="#" title="%s" class="action view-file" data-rid="%s">%s</a>',
313
  __( 'View File Contents', 'wp-simple-firewall' ),
314
+ $item->VO->scanresult_id,
315
  $item->path_fragment
316
  );
317
  }
src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildHistory.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables\Modals;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\Retrieve;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
9
+ use FernleafSystems\Wordpress\Services\Services;
10
+
11
+ class BuildHistory {
12
+
13
+ use ModConsumer;
14
+
15
+ private $history = [];
16
+
17
+ /**
18
+ * @param Scans\Base\ResultItem $resultItem
19
+ * @return string
20
+ * @throws \Exception
21
+ */
22
+ public function run( $resultItem ) :string {
23
+ /** @var ModCon $mod */
24
+ $mod = $this->getMod();
25
+
26
+ $results = ( new Retrieve() )
27
+ ->setMod( $this->getMod() )
28
+ ->setAdditionalWheres( [
29
+ sprintf( "`ri`.`item_id`='%s'", $resultItem->VO->item_id )
30
+ ] )
31
+ ->retrieve();
32
+
33
+ foreach ( $results->getItems() as $item ) {
34
+ $vo = $item->VO;
35
+
36
+ foreach ( $this->columnMap() as $column => $name ) {
37
+ $ts = $vo->{$column};
38
+ if ( $ts > 0 ) {
39
+ $this->prepTimestamp( $ts );
40
+
41
+ if ( $column === 'created_at' ) {
42
+ $this->history[ $ts ][] = sprintf(
43
+ __( "File detected as %s by %s scanner.", 'wp-simple-firewall' ),
44
+ sprintf( '<strong>%s</strong>', $this->getItemFileStatus( $item ) ),
45
+ sprintf( '<strong>%s</strong>', $mod->getScanCon( $item->VO->scan )->getScanName() )
46
+ );
47
+ }
48
+ else {
49
+ $this->history[ $ts ][] = $name;
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ return $this->getMod()->renderTemplate(
56
+ '/wpadmin_pages/insights/scans/modal/scan_item_view/item_history.twig',
57
+ [
58
+ 'flags' => [
59
+ 'has_history' => $results->hasItems(),
60
+ ],
61
+ 'vars' => [
62
+ 'history' => $this->convertHistoryToHuman(),
63
+ ],
64
+ 'strings' => [
65
+ ],
66
+ ]
67
+ );
68
+ }
69
+
70
+ /**
71
+ * @param Scans\Base\ResultItem $item
72
+ * @return string
73
+ */
74
+ private function getItemFileStatus( $item ) :string {
75
+ if ( $item->is_unrecognised ) {
76
+ $status = __( 'Unrecognised', 'wp-simple-firewall' );
77
+ }
78
+ elseif ( $item->is_mal ) {
79
+ $status = __( 'Potential Malware', 'wp-simple-firewall' );
80
+ }
81
+ elseif ( $item->is_missing ) {
82
+ $status = __( 'Missing', 'wp-simple-firewall' );
83
+ }
84
+ elseif ( $item->is_checksumfail ) {
85
+ $status = __( 'Modified', 'wp-simple-firewall' );
86
+ }
87
+ else {
88
+ $status = __( 'Unknown', 'wp-simple-firewall' );
89
+ }
90
+ return $status;
91
+ }
92
+
93
+ private function convertHistoryToHuman() :array {
94
+ $WP = Services::WpGeneral();
95
+ $humanHistory = [];
96
+ ksort( $this->history );
97
+ foreach ( $this->history as $ts => $history ) {
98
+ $humanHistory[ $WP->getTimeStringForDisplay( $WP->getTimeAsGmtOffset( $ts ) ) ] = array_unique( $history );
99
+ }
100
+ return array_reverse( $humanHistory );
101
+ }
102
+
103
+ private function columnMap() :array {
104
+ return [
105
+ 'created_at' => __( 'File Detected By Scans' ),
106
+ 'attempt_repair_at' => __( 'File Repair Attempted' ),
107
+ 'item_repaired_at' => __( 'File Repaired' ),
108
+ 'item_deleted_at' => __( 'File Deleted' ),
109
+ 'ignored_at' => __( 'Item Marked As Ignored' ),
110
+ 'notified_at' => __( 'Notification Of Scan Detection Sent' ),
111
+ ];
112
+ }
113
+
114
+ private function prepTimestamp( $ts ) {
115
+ $ts = (int)$ts;
116
+ if ( !isset( $this->history[ $ts ] ) ) {
117
+ $this->history[ $ts ] = [];
118
+ }
119
+ }
120
+ }
src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildInfo.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables\Modals;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+ use FernleafSystems\Wordpress\Services\Utilities\WpOrg\{
9
+ Wp
10
+ };
11
+
12
+ class BuildInfo {
13
+
14
+ use ModConsumer;
15
+ use Scans\Common\ScanItemConsumer;
16
+
17
+ /**
18
+ * @throws \Exception
19
+ */
20
+ public function run() :string {
21
+ $WP = Services::WpGeneral();
22
+ /** @var Scans\Afs\ResultItem $item */
23
+ $item = $this->getScanItem();
24
+
25
+ $isCoreFile = Services::CoreFileHashes()->isCoreFile( $item->path_fragment );
26
+
27
+ return $this->getMod()->renderTemplate(
28
+ '/wpadmin_pages/insights/scans/modal/scan_item_view/item_info.twig',
29
+ [
30
+ 'flags' => [
31
+ 'is_core_file' => true,
32
+ ],
33
+ 'hrefs' => [
34
+ 'file_vcs' => $isCoreFile ?
35
+ ( new Wp\Repo() )
36
+ ->getVcsUrlForFileAndVersion( $item->path_fragment, $WP->getVersion(), false )
37
+ : ''
38
+ ],
39
+ 'vars' => [
40
+ 'path_fragment' => $item->path_fragment,
41
+ 'file_description' => $this->getFileDescriptionLines()
42
+ ],
43
+ 'strings' => [
44
+ 'file_status' => sprintf( '%s: %s',
45
+ __( 'File Status', 'wp-simple-firewall' ),
46
+ $this->getFileStatus()
47
+ ),
48
+ 'file_full_path' => sprintf( '%s: <code>%s</code>',
49
+ __( 'Full Path To File', 'wp-simple-firewall' ),
50
+ $item->path_full
51
+ ),
52
+ 'file_description' => __( 'Description', 'wp-simple-firewall' ),
53
+ 'view_file_vcs' => __( 'View Original File Contents', 'wp-simple-firewall' ),
54
+ ],
55
+ ]
56
+ );
57
+ }
58
+
59
+ private function getFileDescriptionLines() :array {
60
+ /** @var Scans\Afs\ResultItem $item */
61
+ $item = $this->getScanItem();
62
+
63
+ $description = [];
64
+ if ( $item->is_in_core ) {
65
+ if ( $item->is_unrecognised ) {
66
+ $description[] = sprintf(
67
+ __( "This file is located in a core WordPress directory isn't a recognised core file for WordPress %s.", 'wp-simple-firewall' ),
68
+ Services::WpGeneral()->getVersion()
69
+ );
70
+ }
71
+ else {
72
+ $description[] = sprintf(
73
+ __( 'This is a recognised core file for WordPress %s.', 'wp-simple-firewall' ),
74
+ Services::WpGeneral()->getVersion()
75
+ );
76
+ }
77
+ }
78
+ elseif ( $item->is_in_plugin ) {
79
+ if ( $item->is_unrecognised ) {
80
+ $description[] = __( "It's located in a WordPress plugin directory, but it's not recognised as an official file.", 'wp-simple-firewall' );
81
+ }
82
+ else {
83
+ $description[] = __( "It's located in a WordPress plugin directory, and is a recognised official file.", 'wp-simple-firewall' );
84
+ }
85
+ }
86
+ elseif ( $item->is_in_theme ) {
87
+ if ( $item->is_unrecognised ) {
88
+ $description[] = __( "It's located in a WordPress theme directory, but it's not recognised as an official file.", 'wp-simple-firewall' );
89
+ }
90
+ else {
91
+ $description[] = __( "It's located in a WordPress theme directory, and is a recognised official file.", 'wp-simple-firewall' );
92
+ }
93
+ }
94
+ if ( $item->is_checksumfail ) {
95
+ $description[] = __( 'Contents have been modified from what is expected.', 'wp-simple-firewall' );
96
+ }
97
+ if ( $item->is_mal ) {
98
+ $description[] = __( 'Contents could potentially contain malicious PHP malware.', 'wp-simple-firewall' );
99
+ $description[] = sprintf( __( 'The false positive score of this file is %s.', 'wp-simple-firewall' ),
100
+ sprintf( '<code>%s</code>', $item->mal_fp_confidence ) );
101
+ $description[] = __( "The lower the score the less we know about the file and the more likely it contains malicious code.", 'wp-simple-firewall' );
102
+ }
103
+
104
+ return $description;
105
+ }
106
+
107
+ private function getFileStatus() :string {
108
+ /** @var Scans\Afs\ResultItem $item */
109
+ $item = $this->getScanItem();
110
+
111
+ $status = [];
112
+ if ( $item->is_mal ) {
113
+ $status[] = __( 'Potential Malware', 'wp-simple-firewall' );
114
+ }
115
+
116
+ if ( $item->is_unrecognised ) {
117
+ $status[] = __( 'Unrecognised', 'wp-simple-firewall' );
118
+ }
119
+ elseif ( $item->is_missing ) {
120
+ $status[] = __( 'Missing', 'wp-simple-firewall' );
121
+ }
122
+ elseif ( $item->is_checksumfail ) {
123
+ $status[] = __( 'Modified', 'wp-simple-firewall' );
124
+ }
125
+ else {
126
+ $status[] = __( 'Unknown', 'wp-simple-firewall' );
127
+ }
128
+
129
+ return implode( ' / ', $status );
130
+ }
131
+ }
src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/FileContents.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables\Modals;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\Retrieve;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
+ use FernleafSystems\Wordpress\Services\Services;
9
+ use FernleafSystems\Wordpress\Services\Utilities\File\ConvertLineEndings;
10
+
11
+ class FileContents {
12
+
13
+ use ModConsumer;
14
+
15
+ /**
16
+ * @throws \Exception
17
+ */
18
+ public function run( int $rid, bool $rawContents = false ) :array {
19
+ try {
20
+ $item = ( new Retrieve() )
21
+ ->setMod( $this->getMod() )
22
+ ->byID( $rid );
23
+ }
24
+ catch ( \Exception $e ) {
25
+ throw new \Exception( 'Not a valid file record' );
26
+ }
27
+
28
+ if ( empty( $item->path_fragment ) ) {
29
+ throw new \Exception( 'There is no path associated with this record' );
30
+ }
31
+
32
+ $path = \path_join( ABSPATH, $item->path_fragment );
33
+ $FS = Services::WpFs();
34
+ if ( !$FS->isFile( $path ) ) {
35
+ throw new \Exception( 'File does not exist.' );
36
+ }
37
+
38
+ $contents = $FS->getFileContent( $path );
39
+ if ( empty( $contents ) ) {
40
+ throw new \Exception( 'File is empty or could not be read.' );
41
+ }
42
+
43
+ if ( !$rawContents ) {
44
+ $modContents = ( new ConvertLineEndings() )->fileDosToLinux( $path );
45
+ $contents = $this->getMod()
46
+ ->renderTemplate(
47
+ '/wpadmin_pages/insights/scans/modal/code_block.twig',
48
+ [
49
+ 'lines' => explode( "\n", str_replace( "\t", " ", $modContents ) ),
50
+ ]
51
+ );
52
+ }
53
+ return [
54
+ 'contents' => $contents,
55
+ 'path' => \esc_html( $item->path_fragment ),
56
+ ];
57
+ }
58
+ }
src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables\Modals;
4
+
5
+ use FernleafSystems\Wordpress\Services\Utilities\File\ConvertLineEndings;
6
+ use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\Retrieve;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
10
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
11
+ use FernleafSystems\Wordpress\Services\Services;
12
+ use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Util\Diff;
13
+
14
+ class ScanItemView {
15
+
16
+ use ModConsumer;
17
+
18
+ /**
19
+ * @throws \Exception
20
+ */
21
+ public function run( int $rid ) :array {
22
+ $con = $this->getCon();
23
+ /** @var ModCon $mod */
24
+ $mod = $this->getMod();
25
+ try {
26
+ /** @var Scans\Afs\ResultItem $item */
27
+ $item = ( new Retrieve() )
28
+ ->setMod( $mod )
29
+ ->byID( $rid );
30
+ }
31
+ catch ( \Exception $e ) {
32
+ throw new \Exception( 'Not a valid record' );
33
+ }
34
+
35
+ if ( empty( $item->path_fragment ) ) {
36
+ throw new \Exception( 'Non-file scan items are not supported yet.' );
37
+ }
38
+
39
+ $canDownload = Services::WpFs()->isFile( $item->path_full );
40
+
41
+ try {
42
+ $diffContent = $this->getFileDiff( $item );
43
+ $hasDiff = true;
44
+ }
45
+ catch ( \Exception $e ) {
46
+ $diffContent = $e->getMessage();
47
+ $hasDiff = false;
48
+ }
49
+
50
+ try {
51
+ $fileContent = ( new FileContents() )
52
+ ->setMod( $mod )
53
+ ->run( $rid )[ 'contents' ];
54
+ $hasContent = true;
55
+ }
56
+ catch ( \Exception $e ) {
57
+ $fileContent = $e->getMessage();
58
+ $hasContent = false;
59
+ }
60
+
61
+ try {
62
+ $historyContent = ( new BuildHistory() )
63
+ ->setMod( $this->getMod() )
64
+ ->run( $item );
65
+ $hasHistory = true;
66
+ }
67
+ catch ( \Exception $e ) {
68
+ $historyContent = $e->getMessage();
69
+ $hasHistory = false;
70
+ }
71
+
72
+ return [
73
+ 'path' => \esc_html( $item->path_fragment ),
74
+ 'contents' => $mod->renderTemplate(
75
+ '/wpadmin_pages/insights/scans/modal/scan_item_view/modal_content.twig',
76
+ [
77
+ 'content' => [
78
+ 'tab_filecontents' => $fileContent,
79
+ 'tab_diff' => $diffContent,
80
+ 'tab_history' => $historyContent,
81
+ 'tab_info' => ( new BuildInfo() )
82
+ ->setMod( $this->getMod() )
83
+ ->setScanItem( $item )
84
+ ->run(),
85
+ ],
86
+ 'flags' => [
87
+ 'can_download' => $canDownload,
88
+ 'has_content' => $hasContent,
89
+ 'has_diff' => $hasDiff,
90
+ 'has_history' => $hasHistory,
91
+ ],
92
+ 'hrefs' => [
93
+ 'file_download' => $mod->getScanCon( $item->VO->scan )
94
+ ->createFileDownloadLink( $item->VO->scanresult_id ),
95
+ 'has_content' => $hasContent,
96
+ 'has_diff' => $hasDiff,
97
+ 'has_history' => $hasHistory,
98
+ ],
99
+ 'imgs' => [
100
+ 'svgs' => [
101
+ 'file_download' => $con->svgs->raw( 'bootstrap/download.svg' ),
102
+ ],
103
+ ],
104
+ 'strings' => [
105
+ 'modal_title' => sprintf( '%s: %s', 'File', $item->path_fragment ),
106
+ 'tab_filecontents' => 'Contents',
107
+ 'tab_diff' => 'Diff',
108
+ 'tab_history' => 'History',
109
+ 'tab_info' => 'Info',
110
+ 'file_download' => __( 'Download File', 'wp-simple-firewall' ),
111
+ ],
112
+ ]
113
+ ),
114
+ ];
115
+ }
116
+
117
+ /**
118
+ * @param Scans\Afs\ResultItem $resultItem
119
+ * @return string
120
+ * @throws \Exception
121
+ */
122
+ private function getFileDiff( $resultItem ) :string {
123
+ $pathFull = $resultItem->path_full;
124
+
125
+ if ( $resultItem->is_missing || !Services::WpFs()->isFile( $pathFull ) ) {
126
+ throw new \Exception( 'Diff is unavailable for missing files.' );
127
+ }
128
+
129
+ $original = '';
130
+ $coreHashes = Services::CoreFileHashes();
131
+ if ( $coreHashes->isCoreFile( $pathFull ) ) {
132
+ $original = Services::WpFs()->getFileContent(
133
+ ( new WpOrg\Wp\Files() )->getOriginalFileFromVcs( $pathFull )
134
+ );
135
+ }
136
+ else {
137
+ $plugin = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $pathFull );
138
+ if ( !empty( $plugin ) && $plugin->isWpOrg() && $plugin->svn_uses_tags ) {
139
+ $originalFileDownload = ( new WpOrg\Plugin\Files() )->getOriginalFileFromVcs( $pathFull );
140
+ if ( !empty( $originalFileDownload ) ) {
141
+ $original = Services::WpFs()->getFileContent( $originalFileDownload );
142
+ }
143
+ }
144
+ else {
145
+ $theme = ( new WpOrg\Theme\Files() )->findThemeFromFile( $pathFull );
146
+ if ( !empty( $theme ) && $theme->isWpOrg() ) {
147
+ $originalFileDownload = ( new WpOrg\Theme\Files() )->getOriginalFileFromVcs( $pathFull );
148
+ if ( !empty( $originalFileDownload ) ) {
149
+ $original = Services::WpFs()->getFileContent( $originalFileDownload );
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ if ( empty( $original ) ) {
156
+ throw new \Exception( 'There is no original file available to create a diff.' );
157
+ }
158
+
159
+ $converter = new ConvertLineEndings();
160
+ $res = ( new Diff() )->getDiff(
161
+ $converter->dosToLinux( $original ),
162
+ $converter->fileDosToLinux( $pathFull )
163
+ );
164
+
165
+ if ( !is_array( $res ) || empty( $res[ 'html' ] ) ) {
166
+ throw new \Exception( 'Could not get a valid diff for this file.' );
167
+ }
168
+
169
+ return sprintf( '<style>%s</style>%s',
170
+ 'table.diff.diff-wrapper tbody tr td:nth-child(2){ width:auto;}'.
171
+ 'table.diff.diff-wrapper { table-layout: auto;}'.
172
+ base64_decode( $res[ 'html' ][ 'css_default' ] ),
173
+ base64_decode( $res[ 'html' ][ 'content' ] )
174
+ );
175
+ }
176
+ }
src/lib/src/Modules/HackGuard/Lib/ScanTables/RetrieveFileContents.php DELETED
@@ -1,63 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner\EntryVO;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\ConvertBetweenTypes;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
10
- use FernleafSystems\Wordpress\Services\Services;
11
-
12
- class RetrieveFileContents {
13
-
14
- use ModConsumer;
15
-
16
- /**
17
- * @param int $rid
18
- * @param bool $raw
19
- * @return array
20
- * @throws \Exception
21
- */
22
- public function retrieve( int $rid, bool $raw = false ) :array {
23
- /** @var ModCon $mod */
24
- $mod = $this->getMod();
25
-
26
- /** @var EntryVO $record */
27
- $record = $mod->getDbHandler_ScanResults()
28
- ->getQuerySelector()
29
- ->byId( $rid );
30
- if ( empty( $record ) ) {
31
- throw new \Exception( 'Not a valid file record' );
32
- }
33
- $item = ( new ConvertBetweenTypes() )
34
- ->setScanController( $mod->getScanCon( $record->scan ) )
35
- ->convertVoToResultItem( $record );
36
- $path = $item->path_full;
37
- if ( empty( $path ) ) {
38
- throw new \Exception( 'There is no path associated with this record' );
39
- }
40
- $FS = Services::WpFs();
41
- if ( !$FS->isFile( $path ) ) {
42
- throw new \Exception( 'File does not exist.' );
43
- }
44
- $contents = $FS->getFileContent( $path );
45
- if ( empty( $contents ) ) {
46
- throw new \Exception( 'File is empty or could not be read.' );
47
- }
48
- if ( !$raw ) {
49
- $modContents = Services::DataManipulation()->convertLineEndingsDosToLinux( $path );
50
- $contents = $this->getMod()
51
- ->renderTemplate(
52
- '/wpadmin_pages/insights/scans/modal/code_block.twig',
53
- [
54
- 'lines' => explode( "\n", str_replace( "\t", " ", $modContents ) ),
55
- ]
56
- );
57
- }
58
- return [
59
- 'contents' => $contents,
60
- 'path' => esc_html( $item->path_fragment ),
61
- ];
62
- }
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForCrowdSource.php CHANGED
@@ -3,6 +3,7 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\Build;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers\StandardDirectoryIterator;
 
6
  use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
7
  WpPluginVo,
8
  WpThemeVo
@@ -18,7 +19,7 @@ class BuildHashesForCrowdSource {
18
  */
19
  public function build( $asset, array $exts ) :array {
20
  $hashes = [];
21
- $DM = Services::DataManipulation();
22
  $dir = wp_normalize_path( $asset->getInstallDir() );
23
  try {
24
  if ( empty( $exts ) ) {
@@ -29,7 +30,7 @@ class BuildHashesForCrowdSource {
29
  if ( in_array( strtolower( $file->getExtension() ), $exts ) ) {
30
  $fullPath = $file->getPathname();
31
  $key = strtolower( str_replace( $dir, '', wp_normalize_path( $fullPath ) ) );
32
- $hashes[ $key ] = hash( 'sha1', $DM->convertLineEndingsDosToLinux( $fullPath ) );
33
  }
34
  }
35
  ksort( $hashes, SORT_NATURAL );
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\Build;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers\StandardDirectoryIterator;
6
+ use FernleafSystems\Wordpress\Services\Utilities\File\ConvertLineEndings;
7
  use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
8
  WpPluginVo,
9
  WpThemeVo
19
  */
20
  public function build( $asset, array $exts ) :array {
21
  $hashes = [];
22
+ $converter = new ConvertLineEndings();
23
  $dir = wp_normalize_path( $asset->getInstallDir() );
24
  try {
25
  if ( empty( $exts ) ) {
30
  if ( in_array( strtolower( $file->getExtension() ), $exts ) ) {
31
  $fullPath = $file->getPathname();
32
  $key = strtolower( str_replace( $dir, '', wp_normalize_path( $fullPath ) ) );
33
+ $hashes[ $key ] = hash( 'sha1', $converter->fileDosToLinux( $fullPath ) );
34
  }
35
  }
36
  ksort( $hashes, SORT_NATURAL );
src/lib/src/Modules/HackGuard/Lib/Snapshots/CrowdSourced/SubmitHashes.php CHANGED
@@ -49,7 +49,8 @@ class SubmitHashes {
49
  }
50
 
51
  private function canSubmitAsset() :bool {
52
- return preg_match( sprintf( '#^%s$#', Regex::ASSET_VERSION ), (string)$this->asset->Version )
 
53
  && preg_match( sprintf( '#^%s$#', Regex::ASSET_SLUG ), (string)$this->asset->slug );
54
  }
55
 
49
  }
50
 
51
  private function canSubmitAsset() :bool {
52
+ return $this->getCon()->is_mode_live
53
+ && preg_match( sprintf( '#^%s$#', Regex::ASSET_VERSION ), (string)$this->asset->Version )
54
  && preg_match( sprintf( '#^%s$#', Regex::ASSET_SLUG ), (string)$this->asset->slug );
55
  }
56
 
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/ScheduleBuildAll.php CHANGED
@@ -46,16 +46,15 @@ class ScheduleBuildAll extends BaseBulk {
46
  }
47
  }
48
 
49
- public function hookBuild() {
50
- if ( is_main_network() && wp_next_scheduled( $this->getCronHook() ) !== false ) {
51
- add_action( $this->getCronHook(), [ $this, 'build' ] );
52
- }
53
- }
54
-
55
  public function schedule() {
56
- $hook = $this->getCronHook();
57
- if ( wp_next_scheduled( $hook ) === false && count( $this->getAssetsThatNeedBuilt() ) > 0 ) {
58
- wp_schedule_single_event( Services::Request()->ts() + 60, $hook );
 
 
 
 
 
59
  }
60
  }
61
 
@@ -89,4 +88,10 @@ class ScheduleBuildAll extends BaseBulk {
89
  private function getCronHook() :string {
90
  return $this->getCon()->prefix( 'ptg_build_snapshots' );
91
  }
 
 
 
 
 
 
92
  }
46
  }
47
  }
48
 
 
 
 
 
 
 
49
  public function schedule() {
50
+ if ( count( $this->getAssetsThatNeedBuilt() ) > 0 ) {
51
+ $hook = $this->getCronHook();
52
+ if ( is_main_network() ) {
53
+ add_action( $hook, [ $this, 'build' ] );
54
+ }
55
+ if ( wp_next_scheduled( $hook ) === false ) {
56
+ wp_schedule_single_event( Services::Request()->ts() + 60, $hook );
57
+ }
58
  }
59
  }
60
 
88
  private function getCronHook() :string {
89
  return $this->getCon()->prefix( 'ptg_build_snapshots' );
90
  }
91
+
92
+ /**
93
+ * @deprecated 13.0
94
+ */
95
+ public function hookBuild() {
96
+ }
97
  }
src/lib/src/Modules/HackGuard/Lib/Utility/FileDownloadHandler.php CHANGED
@@ -2,30 +2,36 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Utility;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\HandlerConsumer;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner;
 
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class FileDownloadHandler {
10
 
11
- use HandlerConsumer;
12
 
13
  /**
14
- * @param int $itemID
15
  */
16
- public function downloadByItemId( int $itemID ) {
17
- /** @var Scanner\EntryVO $entry */
18
- $entry = $this->getDbHandler()
19
- ->getQuerySelector()
20
- ->byId( (int)$itemID );
21
- if ( $entry instanceof Scanner\EntryVO && !empty( $entry->meta[ 'path_full' ] ) ) {
22
- $path = $entry->meta[ 'path_full' ];
23
- $FS = Services::WpFs();
24
- if ( $FS->isFile( $path ) ) {
25
- header( 'Set-Cookie: fileDownload=true; path=/' );
26
- Services::Response()->downloadStringAsFile( $FS->getFileContent( $path ), basename( $path ) );
 
 
 
27
  }
28
  }
 
 
29
 
30
  wp_die( "Something about this request wasn't right" );
31
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Utility;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\Retrieve;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults\Ops\Handler;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class FileDownloadHandler {
11
 
12
+ use ModConsumer;
13
 
14
  /**
15
+ * @param int $resultID
16
  */
17
+ public function downloadByItemId( int $resultID ) {
18
+ try {
19
+ $item = ( new Retrieve() )
20
+ ->setMod( $this->getMod() )
21
+ ->byID( $resultID );
22
+
23
+ if ( !empty( $item ) &&
24
+ $item->VO->item_type === Handler::ITEM_TYPE_FILE && !empty( $item->VO->item_id ) ) {
25
+ $path = path_join( ABSPATH, $item->VO->item_id );
26
+ $FS = Services::WpFs();
27
+ if ( $FS->isFile( $path ) ) {
28
+ header( 'Set-Cookie: fileDownload=true; path=/' );
29
+ Services::Response()->downloadStringAsFile( $FS->getFileContent( $path ), basename( $path ) );
30
+ }
31
  }
32
  }
33
+ catch ( \Exception $e ) {
34
+ }
35
 
36
  wp_die( "Something about this request wasn't right" );
37
  }
src/lib/src/Modules/HackGuard/ModCon.php CHANGED
@@ -58,20 +58,40 @@ class ModCon extends BaseShield\ModCon {
58
  return $this->scanQueueCon;
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  /**
62
- * @param string $slug
63
  * @return Scan\Controller\Base|mixed
64
- * @throws \Exception
65
  */
66
  public function getScanCon( string $slug ) {
67
  return $this->getScansCon()->getScanCon( $slug );
68
  }
69
 
70
  public function getMainWpData() :array {
71
- $issues = ( new Lib\Reports\Query\ScanCounts() )->setMod( $this );
72
- $issues->notified = null;
73
  return array_merge( parent::getMainWpData(), [
74
- 'scan_issues' => array_filter( $issues->all() )
75
  ] );
76
  }
77
 
@@ -82,7 +102,7 @@ class ModCon extends BaseShield\ModCon {
82
  break;
83
  case 'scan_file':
84
  ( new Lib\Utility\FileDownloadHandler() )
85
- ->setDbHandler( $this->getDbHandler_ScanResults() )
86
  ->downloadByItemId( (int)Services::Request()->query( 'rid', 0 ) );
87
  break;
88
  }
@@ -190,14 +210,6 @@ class ModCon extends BaseShield\ModCon {
190
  $opts->setOpt( 'ufc_exclusions', array_unique( $excl ) );
191
  }
192
 
193
- public function isPtgEnabled() :bool {
194
- $opts = $this->getOptions();
195
- return $this->isModuleEnabled() && $this->isPremium()
196
- && $opts->isOpt( 'ptg_enable', 'enabled' )
197
- && $this->getCon()->hasCacheDir()
198
- && !empty( $this->getPtgSnapsBaseDir() );
199
- }
200
-
201
  public function getPtgSnapsBaseDir() :string {
202
  return ( new CacheDir() )
203
  ->setCon( $this->getCon() )
@@ -218,10 +230,16 @@ class ModCon extends BaseShield\ModCon {
218
  return $this->getDbH( 'filelocker' );
219
  }
220
 
 
 
 
221
  public function getDbHandler_ScanQueue() :Databases\ScanQueue\Handler {
222
  return $this->getDbH( 'scanq' );
223
  }
224
 
 
 
 
225
  public function getDbHandler_ScanResults() :Databases\Scanner\Handler {
226
  return $this->getDbH( 'scanner' );
227
  }
@@ -231,10 +249,7 @@ class ModCon extends BaseShield\ModCon {
231
  * @throws \Exception
232
  */
233
  protected function isReadyToExecute() :bool {
234
- return ( $this->getDbHandler_ScanQueue() instanceof Databases\ScanQueue\Handler )
235
- && $this->getDbHandler_ScanQueue()->isReady()
236
- && ( $this->getDbHandler_ScanResults() instanceof Databases\Scanner\Handler )
237
- && $this->getDbHandler_ScanResults()->isReady()
238
  && parent::isReadyToExecute();
239
  }
240
 
@@ -245,9 +260,17 @@ class ModCon extends BaseShield\ModCon {
245
  foreach ( $opts->getScanSlugs() as $slug ) {
246
  $this->getScanCon( $slug )->purge();
247
  }
248
- $this->getDbHandler_ScanQueue()->tableDelete();
249
- $this->getDbHandler_ScanResults()->tableDelete();
250
  // 2. Clean out the file locker
251
  $this->getFileLocker()->purge();
252
  }
 
 
 
 
 
 
 
 
253
  }
58
  return $this->scanQueueCon;
59
  }
60
 
61
+ public function getDbH_Scans() :DB\Scans\Ops\Handler {
62
+ return $this->getDbHandler()->loadDbH( 'scans' );
63
+ }
64
+
65
+ public function getDbH_ScanItems() :DB\ScanItems\Ops\Handler {
66
+ $this->getDbH_Scans();
67
+ return $this->getDbHandler()->loadDbH( 'scanitems' );
68
+ }
69
+
70
+ public function getDbH_ResultItems() :DB\ResultItems\Ops\Handler {
71
+ return $this->getDbHandler()->loadDbH( 'resultitems' );
72
+ }
73
+
74
+ public function getDbH_ResultItemMeta() :DB\ResultItemMeta\Ops\Handler {
75
+ $this->getDbH_ResultItems();
76
+ return $this->getDbHandler()->loadDbH( 'resultitem_meta' );
77
+ }
78
+
79
+ public function getDbH_ScanResults() :DB\ScanResults\Ops\Handler {
80
+ $this->getDbH_Scans();
81
+ $this->getDbH_ResultItems();
82
+ return $this->getDbHandler()->loadDbH( 'scanresults' );
83
+ }
84
+
85
  /**
 
86
  * @return Scan\Controller\Base|mixed
 
87
  */
88
  public function getScanCon( string $slug ) {
89
  return $this->getScansCon()->getScanCon( $slug );
90
  }
91
 
92
  public function getMainWpData() :array {
 
 
93
  return array_merge( parent::getMainWpData(), [
94
+ 'scan_issues' => array_filter( ( new Lib\Reports\Query\ScanCounts() )->setMod( $this )->all() )
95
  ] );
96
  }
97
 
102
  break;
103
  case 'scan_file':
104
  ( new Lib\Utility\FileDownloadHandler() )
105
+ ->setMod( $this )
106
  ->downloadByItemId( (int)Services::Request()->query( 'rid', 0 ) );
107
  break;
108
  }
210
  $opts->setOpt( 'ufc_exclusions', array_unique( $excl ) );
211
  }
212
 
 
 
 
 
 
 
 
 
213
  public function getPtgSnapsBaseDir() :string {
214
  return ( new CacheDir() )
215
  ->setCon( $this->getCon() )
230
  return $this->getDbH( 'filelocker' );
231
  }
232
 
233
+ /**
234
+ * @deprecated 12.1
235
+ */
236
  public function getDbHandler_ScanQueue() :Databases\ScanQueue\Handler {
237
  return $this->getDbH( 'scanq' );
238
  }
239
 
240
+ /**
241
+ * @deprecated 12.1
242
+ */
243
  public function getDbHandler_ScanResults() :Databases\Scanner\Handler {
244
  return $this->getDbH( 'scanner' );
245
  }
249
  * @throws \Exception
250
  */
251
  protected function isReadyToExecute() :bool {
252
+ return $this->getDbH_ScanResults()->isReady() && $this->getDbH_ScanItems()->isReady()
 
 
 
253
  && parent::isReadyToExecute();
254
  }
255
 
260
  foreach ( $opts->getScanSlugs() as $slug ) {
261
  $this->getScanCon( $slug )->purge();
262
  }
263
+ $this->getDbH_ScanItems()->tableDelete();
264
+ $this->getDbH_ScanResults()->tableDelete();
265
  // 2. Clean out the file locker
266
  $this->getFileLocker()->purge();
267
  }
268
+
269
+ /**
270
+ * @inheritDoc
271
+ * @deprecated 13.0
272
+ */
273
+ public function getDbHandlers( $bInitAll = false ) {
274
+ return [];
275
+ }
276
  }
src/lib/src/Modules/HackGuard/Options.php CHANGED
@@ -17,6 +17,18 @@ class Options extends BaseShield\Options {
17
  return is_array( $this->getOpt( 'file_repair_areas' ) ) ? $this->getOpt( 'file_repair_areas' ) : [];
18
  }
19
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  /**
21
  * @return string[] - precise REGEX patterns to match against PATH.
22
  */
@@ -39,29 +51,10 @@ class Options extends BaseShield\Options {
39
  );
40
  }
41
 
42
- /**
43
- * @return int[] - keys are the unique report hash
44
- */
45
- public function getMalFalsePositiveReports() :array {
46
- $FP = $this->getOpt( 'mal_fp_reports', [] );
47
- return is_array( $FP ) ? $FP : [];
48
- }
49
-
50
- public function isMalFalsePositiveReported( string $hash ) :bool {
51
- return isset( $this->getMalFalsePositiveReports()[ $hash ] );
52
- }
53
-
54
  public function getMalConfidenceBoundary() :int {
55
  return (int)apply_filters( 'shield/fp_confidence_boundary', 65 );
56
  }
57
 
58
- /**
59
- * @return int
60
- */
61
- public function getMalQueueExpirationInterval() {
62
- return MINUTE_IN_SECONDS*10;
63
- }
64
-
65
  /**
66
  * @return string[]
67
  */
@@ -153,48 +146,50 @@ class Options extends BaseShield\Options {
153
  }
154
 
155
  /**
156
- * @param string $sScan
157
- * @param bool $bAdd
158
- * @return Options
159
  */
160
- public function addRemoveScanToBuild( $sScan, $bAdd = true ) {
161
- $aS = $this->getScansToBuild();
162
- if ( $bAdd ) {
163
- $aS[ $sScan ] = Services::Request()->ts();
164
  }
165
- elseif ( isset( $aS[ $sScan ] ) ) {
166
- unset( $aS[ $sScan ] );
167
  }
168
- return $this->setScansToBuild( $aS );
169
  }
170
 
171
  /**
172
  * @return int[] - keys are scan slugs
173
  */
174
- public function getScansToBuild() {
175
- $aS = $this->getOpt( 'scans_to_build', [] );
176
- if ( !is_array( $aS ) ) {
177
- $aS = [];
178
  }
179
- if ( !empty( $aS ) ) {
 
180
  // We keep scans "to build" for no longer than a minute to prevent indefinite halting with failed Async HTTP.
181
- $aS = array_filter( $aS,
182
- function ( $nToBuildAt ) {
183
- return is_int( $nToBuildAt )
184
- && Services::Request()->carbon()->subMinute()->timestamp < $nToBuildAt;
185
  }
186
  );
187
- $this->setScansToBuild( $aS );
 
 
188
  }
189
- return $aS;
190
  }
191
 
192
  /**
193
- * @param array $aScans
194
- * @return Options
195
  */
196
- public function setScansToBuild( $aScans ) {
197
- return $this->setOpt( 'scans_to_build', array_intersect_key( $aScans, array_flip( $this->getScanSlugs() ) ) );
 
 
198
  }
199
 
200
  /**
@@ -203,15 +198,15 @@ class Options extends BaseShield\Options {
203
  * @return array[]
204
  */
205
  public function getUfcScanDirectories() :array {
206
- $aDirs = [
207
  path_join( ABSPATH, 'wp-admin' ) => [],
208
  path_join( ABSPATH, 'wp-includes' ) => []
209
  ];
210
 
211
  if ( $this->isOpt( 'ufc_scan_uploads', 'Y' ) ) { // include uploads
212
- $sUploadsDir = Services::WpGeneral()->getDirUploads();
213
- if ( !empty( $sUploadsDir ) ) {
214
- $aDirs[ $sUploadsDir ] = [
215
  'php',
216
  'php5',
217
  'js',
@@ -219,7 +214,7 @@ class Options extends BaseShield\Options {
219
  }
220
  }
221
 
222
- return $aDirs;
223
  }
224
 
225
  /**
@@ -233,73 +228,18 @@ class Options extends BaseShield\Options {
233
  return $this->getUnrecognisedFileScannerOption() === 'enabled_delete_only';
234
  }
235
 
236
- /**
237
- * @return string
238
- */
239
- public function getWcfFileExclusions() {
240
- $sPattern = null;
241
-
242
- $aExclusions = $this->getOptions()->getDef( 'wcf_exclusions' );
243
- $aExclusions = is_array( $aExclusions ) ? $aExclusions : [];
244
- // Flywheel specific mods
245
- if ( defined( 'FLYWHEEL_PLUGIN_DIR' ) ) {
246
- $aExclusions[] = 'wp-settings.php';
247
- $aExclusions[] = 'wp-admin/includes/upgrade.php';
248
- }
249
-
250
- if ( is_array( $aExclusions ) && !empty( $aExclusions ) ) {
251
- $aQuoted = array_map(
252
- function ( $sExcl ) {
253
- return preg_quote( $sExcl, '#' );
254
- },
255
- $aExclusions
256
- );
257
- $sPattern = '#('.implode( '|', $aQuoted ).')#i';
258
- }
259
- return $sPattern;
260
- }
261
-
262
- /**
263
- * Builds a regex-ready pattern for matching file names to exclude from scan if they're missing
264
- * @return string|null
265
- */
266
- public function getWcfMissingExclusions() {
267
- $sPattern = null;
268
- $aExclusions = $this->getOptions()->getDef( 'wcf_exclusions_missing_only' );
269
- if ( is_array( $aExclusions ) && !empty( $aExclusions ) ) {
270
- $aQuoted = array_map(
271
- function ( $sExcl ) {
272
- return preg_quote( $sExcl, '#' );
273
- },
274
- $aExclusions
275
- );
276
- $sPattern = '#('.implode( '|', $aQuoted ).')#i';
277
- }
278
- return $sPattern;
279
- }
280
-
281
  public function isScanCron() :bool {
282
  return (bool)$this->getOpt( 'is_scan_cron' );
283
  }
284
 
285
- /**
286
- * @param bool $isCron
287
- * @return $this
288
- */
289
- public function setIsScanCron( bool $isCron ) {
290
- return $this->setOpt( 'is_scan_cron', $isCron );
291
  }
292
 
293
  /**
294
- * @param array $aFP
295
  * @return $this
296
  */
297
- public function setMalFalsePositiveReports( array $aFP ) {
298
- return $this->setOpt( 'mal_fp_reports', array_filter(
299
- $aFP,
300
- function ( $nTS ) {
301
- return $nTS > Services::Request()->carbon()->subMonth()->timestamp;
302
- }
303
- ) );
304
  }
305
  }
17
  return is_array( $this->getOpt( 'file_repair_areas' ) ) ? $this->getOpt( 'file_repair_areas' ) : [];
18
  }
19
 
20
+ public function getLastRealtimeScanAt( bool $update = false ) :int {
21
+ $at = $this->getOpt( 'realtime_scan_last_at' );
22
+ if ( empty( $at ) ) {
23
+ $at = Services::Request()->ts();
24
+ $this->setOpt( 'realtime_scan_last_at', $at );
25
+ }
26
+ if ( $update ) {
27
+ $this->setOpt( 'realtime_scan_last_at', Services::Request()->ts() );
28
+ }
29
+ return $at;
30
+ }
31
+
32
  /**
33
  * @return string[] - precise REGEX patterns to match against PATH.
34
  */
51
  );
52
  }
53
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  public function getMalConfidenceBoundary() :int {
55
  return (int)apply_filters( 'shield/fp_confidence_boundary', 65 );
56
  }
57
 
 
 
 
 
 
 
 
58
  /**
59
  * @return string[]
60
  */
146
  }
147
 
148
  /**
149
+ * @return $this
 
 
150
  */
151
+ public function addRemoveScanToBuild( string $scan, bool $addScan = true ) {
152
+ $scans = $this->getScansToBuild();
153
+ if ( $addScan ) {
154
+ $scans[ $scan ] = Services::Request()->ts();
155
  }
156
+ else {
157
+ unset( $scans[ $scan ] );
158
  }
159
+ return $this->setScansToBuild( $scans );
160
  }
161
 
162
  /**
163
  * @return int[] - keys are scan slugs
164
  */
165
+ public function getScansToBuild() :array {
166
+ $toBuild = $this->getOpt( 'scans_to_build', [] );
167
+ if ( !is_array( $toBuild ) ) {
168
+ $toBuild = [];
169
  }
170
+ if ( !empty( $toBuild ) ) {
171
+ $wasCount = count( $toBuild );
172
  // We keep scans "to build" for no longer than a minute to prevent indefinite halting with failed Async HTTP.
173
+ $toBuild = array_filter( $toBuild,
174
+ function ( $toBuildAt ) {
175
+ return is_int( $toBuildAt )
176
+ && Services::Request()->carbon()->subMinute()->timestamp < $toBuildAt;
177
  }
178
  );
179
+ if ( $wasCount !== count( $toBuild ) ) {
180
+ $this->setScansToBuild( $toBuild );
181
+ }
182
  }
183
+ return $toBuild;
184
  }
185
 
186
  /**
187
+ * @return $this
 
188
  */
189
+ public function setScansToBuild( array $scans ) {
190
+ $this->setOpt( 'scans_to_build', array_intersect_key( $scans, array_flip( $this->getScanSlugs() ) ) );
191
+ $this->getMod()->saveModOptions();
192
+ return $this;
193
  }
194
 
195
  /**
198
  * @return array[]
199
  */
200
  public function getUfcScanDirectories() :array {
201
+ $dirs = [
202
  path_join( ABSPATH, 'wp-admin' ) => [],
203
  path_join( ABSPATH, 'wp-includes' ) => []
204
  ];
205
 
206
  if ( $this->isOpt( 'ufc_scan_uploads', 'Y' ) ) { // include uploads
207
+ $uploadsDir = Services::WpGeneral()->getDirUploads();
208
+ if ( !empty( $uploadsDir ) ) {
209
+ $dirs[ $uploadsDir ] = [
210
  'php',
211
  'php5',
212
  'js',
214
  }
215
  }
216
 
217
+ return $dirs;
218
  }
219
 
220
  /**
228
  return $this->getUnrecognisedFileScannerOption() === 'enabled_delete_only';
229
  }
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  public function isScanCron() :bool {
232
  return (bool)$this->getOpt( 'is_scan_cron' );
233
  }
234
 
235
+ public function isEnabledAutoFileScanner() :bool {
236
+ return $this->isOpt( 'enable_core_file_integrity_scan', 'Y' );
 
 
 
 
237
  }
238
 
239
  /**
 
240
  * @return $this
241
  */
242
+ public function setIsScanCron( bool $isCron ) {
243
+ return $this->setOpt( 'is_scan_cron', $isCron );
 
 
 
 
 
244
  }
245
  }
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionBase.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
 
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
@@ -56,4 +58,10 @@ class SectionBase {
56
  ]
57
  );
58
  }
 
 
 
 
 
 
59
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Afs;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
58
  ]
59
  );
60
  }
61
+
62
+ protected function getScanConAFS() :Afs {
63
+ /** @var ModCon $mod */
64
+ $mod = $this->getMod();
65
+ return $mod->getScanCon( Afs::SCAN_SLUG );
66
+ }
67
  }
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionLogs.php DELETED
@@ -1,65 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
6
- Lib\ScanTables\LoadRawTableData,
7
- ModCon,
8
- Scan\Controller\Mal
9
- };
10
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
11
- use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Scans\ForMalware;
12
- use FernleafSystems\Wordpress\Services\Services;
13
-
14
- class SectionLogs extends SectionBase {
15
-
16
- public function render() :string {
17
- return $this->getMod()
18
- ->renderTemplate(
19
- '/wpadmin_pages/insights/scans/results/section/logs/index.twig',
20
- $this->buildRenderData()
21
- );
22
- }
23
-
24
- protected function buildRenderData() :array {
25
- /** @var ModCon $mod */
26
- $mod = $this->getMod();
27
- $data = $this->buildMalwareData();
28
- return Services::DataManipulation()
29
- ->mergeArraysRecursive( $this->getCommonRenderData(), [
30
- 'strings' => [
31
- 'no_files' => __( "Previous scans didn't detect any files suspected of being malware.", 'wp-simple-firewall' ),
32
- 'files_found' => __( "Previous scans detected 1 or more files suspected of being malware.", 'wp-simple-firewall' ),
33
- 'mal_restricted' => __( 'The Malware File Scanner is only available with ShieldPRO.', 'wp-simple-firewall' ),
34
- ],
35
- 'flags' => [
36
- 'mal_is_restricted' => $mod->getScanCon( Mal::SCAN_SLUG )->isRestricted(),
37
- ],
38
- 'vars' => [
39
- 'count_items' => $data[ 'vars' ][ 'count_items' ],
40
- 'malware' => $data,
41
- 'datatables_init' => ( new ForMalware() )
42
- ->setMod( $this->getMod() )
43
- ->build()
44
- ]
45
- ] );
46
- }
47
-
48
- private function buildMalwareData() :array {
49
-
50
- $filesData = ( new LoadRawTableData() )
51
- ->setMod( $this->getMod() )
52
- ->loadForMalware();
53
-
54
- $data = [
55
- 'flags' => [
56
- 'has_malware' => !empty( $filesData ),
57
- ],
58
- 'vars' => [
59
- 'count_items' => count( $filesData )
60
- ]
61
- ];
62
- $data[ 'flags' ][ 'has_issue' ] = $data[ 'flags' ][ 'has_malware' ];
63
- return $data;
64
- }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionMalware.php CHANGED
@@ -3,8 +3,8 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
6
- Lib\ScanTables\LoadRawTableData,
7
  ModCon,
 
8
  Scan\Controller\Mal
9
  };
10
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
@@ -33,7 +33,7 @@ class SectionMalware extends SectionBase {
33
  'mal_restricted' => __( 'The Malware File Scanner is only available with ShieldPRO.', 'wp-simple-firewall' ),
34
  ],
35
  'flags' => [
36
- 'mal_is_restricted' => $mod->getScanCon( Mal::SCAN_SLUG )->isRestricted(),
37
  ],
38
  'vars' => [
39
  'count_items' => $data[ 'vars' ][ 'count_items' ],
@@ -47,17 +47,17 @@ class SectionMalware extends SectionBase {
47
  }
48
 
49
  private function buildMalwareData() :array {
50
-
51
- $filesData = ( new LoadRawTableData() )
52
- ->setMod( $this->getMod() )
53
- ->loadForMalware();
54
-
55
  $data = [
56
  'flags' => [
57
- 'has_malware' => !empty( $filesData ),
58
  ],
59
  'vars' => [
60
- 'count_items' => count( $filesData )
61
  ]
62
  ];
63
  $data[ 'flags' ][ 'has_issue' ] = $data[ 'flags' ][ 'has_malware' ];
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
 
6
  ModCon,
7
+ Scan\Controller\Afs,
8
  Scan\Controller\Mal
9
  };
10
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
33
  'mal_restricted' => __( 'The Malware File Scanner is only available with ShieldPRO.', 'wp-simple-firewall' ),
34
  ],
35
  'flags' => [
36
+ 'mal_is_restricted' => $this->getScanConAFS()->isRestrictedMalwareScan(),
37
  ],
38
  'vars' => [
39
  'count_items' => $data[ 'vars' ][ 'count_items' ],
47
  }
48
 
49
  private function buildMalwareData() :array {
50
+ /** @var ModCon $mod */
51
+ $mod = $this->getMod();
52
+ $count = $mod->getScansCon()
53
+ ->getScanResultsCount()
54
+ ->countMalware();
55
  $data = [
56
  'flags' => [
57
+ 'has_malware' => $count > 0,
58
  ],
59
  'vars' => [
60
+ 'count_items' => $count
61
  ]
62
  ];
63
  $data[ 'flags' ][ 'has_issue' ] = $data[ 'flags' ][ 'has_malware' ];
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionPluginThemesBase.php CHANGED
@@ -15,7 +15,6 @@ class SectionPluginThemesBase extends SectionBase {
15
  protected function getCommonRenderData() :array {
16
  /** @var ModCon $mod */
17
  $mod = $this->getMod();
18
-
19
  return Services::DataManipulation()
20
  ->mergeArraysRecursive( parent::getCommonRenderData(), [
21
  'strings' => [
@@ -23,7 +22,7 @@ class SectionPluginThemesBase extends SectionBase {
23
  'ptg_not_available' => __( 'The Plugin & Theme File Guard Scanner is only available with ShieldPRO.', 'wp-simple-firewall' ),
24
  ],
25
  'flags' => [
26
- 'ptg_is_restricted' => $mod->getScanCon( Ptg::SCAN_SLUG )->isRestricted(),
27
  ],
28
  'vars' => [
29
  'datatables_init' => ( new ForPluginTheme() )
@@ -38,7 +37,7 @@ class SectionPluginThemesBase extends SectionBase {
38
  /** @var ModCon $mod */
39
  $mod = $this->getMod();
40
  try {
41
- $this->vulnerable = $mod->getScanCon( Wpv::SCAN_SLUG )->getAllResults();
42
  }
43
  catch ( \Exception $e ) {
44
  $this->vulnerable = new Scans\Wpv\ResultsSet();
@@ -52,7 +51,7 @@ class SectionPluginThemesBase extends SectionBase {
52
  /** @var ModCon $mod */
53
  $mod = $this->getMod();
54
  try {
55
- $this->abandoned = $mod->getScanCon( Apc::SCAN_SLUG )->getAllResults();
56
  }
57
  catch ( \Exception $e ) {
58
  $this->abandoned = new Scans\Apc\ResultsSet();
15
  protected function getCommonRenderData() :array {
16
  /** @var ModCon $mod */
17
  $mod = $this->getMod();
 
18
  return Services::DataManipulation()
19
  ->mergeArraysRecursive( parent::getCommonRenderData(), [
20
  'strings' => [
22
  'ptg_not_available' => __( 'The Plugin & Theme File Guard Scanner is only available with ShieldPRO.', 'wp-simple-firewall' ),
23
  ],
24
  'flags' => [
25
+ 'ptg_is_restricted' => $this->getScanConAFS()->isRestrictedPluginThemeScan(),
26
  ],
27
  'vars' => [
28
  'datatables_init' => ( new ForPluginTheme() )
37
  /** @var ModCon $mod */
38
  $mod = $this->getMod();
39
  try {
40
+ $this->vulnerable = $mod->getScanCon( Wpv::SCAN_SLUG )->getResultsForDisplay();
41
  }
42
  catch ( \Exception $e ) {
43
  $this->vulnerable = new Scans\Wpv\ResultsSet();
51
  /** @var ModCon $mod */
52
  $mod = $this->getMod();
53
  try {
54
+ $this->abandoned = $mod->getScanCon( Apc::SCAN_SLUG )->getResultsForDisplay();
55
  }
56
  catch ( \Exception $e ) {
57
  $this->abandoned = new Scans\Apc\ResultsSet();
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionPlugins.php CHANGED
@@ -55,9 +55,9 @@ class SectionPlugins extends SectionPluginThemesBase {
55
  return Services::DataManipulation()
56
  ->mergeArraysRecursive( $this->getCommonRenderData(), [
57
  'strings' => [
58
- 'no_items' => __( "Previous scans didn't detect any modified or missing files in any plugin directories.", 'wp-simple-firewall' ),
59
- 'no_files' => __( "Previous scans didn't detect any modified or missing files in the plugin directory.", 'wp-simple-firewall' ),
60
- 'files_found' => __( "Previous scans detected 1 or more modified or missing files in the plugin directory.", 'wp-simple-firewall' ),
61
  'not_active' => __( "This plugin isn't active and should be uninstalled.", 'wp-simple-firewall' ),
62
  'go_to_plugins' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Plugins' ) ),
63
  ],
@@ -126,7 +126,7 @@ class SectionPlugins extends SectionPluginThemesBase {
126
  'is_wporg' => $plugin->isWpOrg(),
127
  ],
128
  'vars' => [
129
- 'abandoned_rid' => empty( $abandoned ) ? -1 : $abandoned->VO->id,
130
  'count_items' => count( $guardFilesData ) + count( $vulnerabilities )
131
  + ( empty( $abandoned ) ? 0 : 1 )
132
  ],
55
  return Services::DataManipulation()
56
  ->mergeArraysRecursive( $this->getCommonRenderData(), [
57
  'strings' => [
58
+ 'no_items' => __( "Previous scans didn't detect any modified or unrecognised files in any plugin directories.", 'wp-simple-firewall' ),
59
+ 'no_files' => __( "Previous scans didn't detect any modified or unrecognised files in the plugin directory.", 'wp-simple-firewall' ),
60
+ 'files_found' => __( "Previous scans detected 1 or more modified or unrecognised files in the plugin directory.", 'wp-simple-firewall' ),
61
  'not_active' => __( "This plugin isn't active and should be uninstalled.", 'wp-simple-firewall' ),
62
  'go_to_plugins' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Plugins' ) ),
63
  ],
126
  'is_wporg' => $plugin->isWpOrg(),
127
  ],
128
  'vars' => [
129
+ 'abandoned_rid' => empty( $abandoned ) ? -1 : $abandoned->VO->scanresult_id,
130
  'count_items' => count( $guardFilesData ) + count( $vulnerabilities )
131
  + ( empty( $abandoned ) ? 0 : 1 )
132
  ],
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionThemes.php CHANGED
@@ -57,9 +57,9 @@ class SectionThemes extends SectionPluginThemesBase {
57
  return Services::DataManipulation()
58
  ->mergeArraysRecursive( $this->getCommonRenderData(), [
59
  'strings' => [
60
- 'no_items' => __( "Previous scans didn't detect any modified or missing files in any Theme directories.", 'wp-simple-firewall' ),
61
- 'no_files' => __( "Previous scans didn't detect any modified or missing files in the Theme directories.", 'wp-simple-firewall' ),
62
- 'files_found' => __( "Previous scans detected 1 or more modified or missing files in the theme directory.", 'wp-simple-firewall' ),
63
  'not_active' => __( "This theme isn't active and should be uninstalled.", 'wp-simple-firewall' ),
64
  'go_to_themes' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Themes' ) ),
65
  ],
@@ -91,7 +91,7 @@ class SectionThemes extends SectionPluginThemesBase {
91
  ->setMod( $this->getMod() )
92
  ->loadForTheme( $theme );
93
 
94
- $vulnerabilities = $this->getVulnerabilities()->getItemsForSlug( $theme->file );
95
 
96
  $data = [
97
  'info' => [
57
  return Services::DataManipulation()
58
  ->mergeArraysRecursive( $this->getCommonRenderData(), [
59
  'strings' => [
60
+ 'no_items' => __( "Previous scans didn't detect any modified or unrecognised files in any Theme directories.", 'wp-simple-firewall' ),
61
+ 'no_files' => __( "Previous scans didn't detect any modified or unrecognised files in the Theme directories.", 'wp-simple-firewall' ),
62
+ 'files_found' => __( "Previous scans detected 1 or more modified or unrecognised files in the theme directory.", 'wp-simple-firewall' ),
63
  'not_active' => __( "This theme isn't active and should be uninstalled.", 'wp-simple-firewall' ),
64
  'go_to_themes' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Themes' ) ),
65
  ],
91
  ->setMod( $this->getMod() )
92
  ->loadForTheme( $theme );
93
 
94
+ $vulnerabilities = $this->getVulnerabilities()->getItemsForSlug( $theme->stylesheet );
95
 
96
  $data = [
97
  'info' => [
src/lib/src/Modules/HackGuard/Render/ScanResults/SectionWordpress.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\ScanTables\LoadRawTableData;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Scans\ForWordpress;
8
  use FernleafSystems\Wordpress\Services\Services;
@@ -36,25 +36,25 @@ class SectionWordpress extends SectionBase {
36
  }
37
 
38
  private function buildWordpressData() :array {
39
-
40
- $coreFilesData = ( new LoadRawTableData() )
41
- ->setMod( $this->getMod() )
42
- ->loadForWordPress();
43
-
44
  $WP = Services::WpGeneral();
 
 
 
 
 
45
  $data = [
46
  'info' => [
47
- 'type' => 'theme',
48
  'version' => $WP->getVersion(),
49
  'dir' => wp_normalize_path( ABSPATH ),
50
  ],
51
  'flags' => [
52
  'has_update' => $WP->hasCoreUpdate(),
53
- 'has_core_files' => !empty( $coreFilesData ),
54
  'is_vulnerable' => false,
55
  ],
56
  'vars' => [
57
- 'count_items' => count( $coreFilesData )
58
  ]
59
  ];
60
  $data[ 'flags' ][ 'has_issue' ] = $data[ 'flags' ][ 'has_core_files' ]
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Render\ScanResults;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Scans\ForWordpress;
8
  use FernleafSystems\Wordpress\Services\Services;
36
  }
37
 
38
  private function buildWordpressData() :array {
 
 
 
 
 
39
  $WP = Services::WpGeneral();
40
+ /** @var ModCon $mod */
41
+ $mod = $this->getMod();
42
+ $count = $mod->getScansCon()
43
+ ->getScanResultsCount()
44
+ ->countWPFiles();
45
  $data = [
46
  'info' => [
47
+ 'type' => 'wordpress',
48
  'version' => $WP->getVersion(),
49
  'dir' => wp_normalize_path( ABSPATH ),
50
  ],
51
  'flags' => [
52
  'has_update' => $WP->hasCoreUpdate(),
53
+ 'has_core_files' => $count > 0,
54
  'is_vulnerable' => false,
55
  ],
56
  'vars' => [
57
+ 'count_items' => $count
58
  ]
59
  ];
60
  $data[ 'flags' ][ 'has_issue' ] = $data[ 'flags' ][ 'has_core_files' ]
src/lib/src/Modules/HackGuard/Scan/Controller/Afs.php ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
8
+ Lib,
9
+ ModCon,
10
+ Options,
11
+ Scan
12
+ };
13
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops\Update;
14
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
15
+ use FernleafSystems\Wordpress\Services\Services;
16
+
17
+ class Afs extends BaseForFiles {
18
+
19
+ const SCAN_SLUG = 'afs';
20
+ use PluginCronsConsumer;
21
+
22
+ protected function run() {
23
+ parent::run();
24
+ ( new Scan\Utilities\PtgAddReinstallLinks() )
25
+ ->setScanController( $this )
26
+ ->execute();
27
+
28
+ $this->setupCronHooks();
29
+ add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] );
30
+ }
31
+
32
+ public function addAdminMenuBarItem( array $items ) :array {
33
+ $status = $this->getScansController()->getScanResultsCount();
34
+
35
+ $template = [
36
+ 'id' => $this->getCon()->prefix( 'problems-'.$this->getSlug() ),
37
+ 'title' => '<div class="wp-core-ui wp-ui-notification shield-counter"><span aria-hidden="true">%s</span></div>',
38
+ 'href' => $this->getCon()->getModule_Insights()->getUrl_ScansResults(),
39
+ ];
40
+
41
+ $count = $status->countMalware();
42
+ if ( $count > 0 ) {
43
+ $warning = $template;
44
+ $warning[ 'id' ] .= '-malware';
45
+ $warning[ 'title' ] = __( 'Potential Malware', 'wp-simple-firewall' ).sprintf( $warning[ 'title' ], $count );
46
+ $warning[ 'warnings' ] = $count;
47
+ $items[] = $warning;
48
+ }
49
+
50
+ $count = $status->countWPFiles();
51
+ if ( $count > 0 ) {
52
+ $warning = $template;
53
+ $warning[ 'id' ] .= '-wp';
54
+ $warning[ 'title' ] = __( 'WordPress Core Files', 'wp-simple-firewall' ).sprintf( $warning[ 'title' ], $count );
55
+ $warning[ 'warnings' ] = $count;
56
+ $items[] = $warning;
57
+ }
58
+
59
+ $count = $status->countPluginFiles();
60
+ if ( $count > 0 ) {
61
+ $warning = $template;
62
+ $warning[ 'id' ] .= '-plugin';
63
+ $warning[ 'title' ] = __( 'Plugin Files', 'wp-simple-firewall' ).sprintf( $warning[ 'title' ], $count );
64
+ $warning[ 'warnings' ] = $count;
65
+ $items[] = $warning;
66
+ }
67
+
68
+ $count = $status->countThemeFiles();
69
+ if ( $count > 0 ) {
70
+ $warning = $template;
71
+ $warning[ 'id' ] .= '-plugin';
72
+ $warning[ 'title' ] = __( 'Theme Files', 'wp-simple-firewall' ).sprintf( $warning[ 'title' ], $count );
73
+ $warning[ 'warnings' ] = $count;
74
+ $items[] = $warning;
75
+ }
76
+
77
+ return $items;
78
+ }
79
+
80
+ public function onWpLoaded() {
81
+ ( new Lib\Snapshots\StoreAction\ScheduleBuildAll() )
82
+ ->setMod( $this->getMod() )
83
+ ->schedule();
84
+ }
85
+
86
+ public function runHourlyCron() {
87
+ ( new Lib\Snapshots\StoreAction\TouchAll() )
88
+ ->setMod( $this->getMod() )
89
+ ->run();
90
+ ( new Lib\Snapshots\StoreAction\CleanAll() )
91
+ ->setMod( $this->getMod() )
92
+ ->run();
93
+ }
94
+
95
+ public function actionPluginReinstall( string $file ) :bool {
96
+ $success = false;
97
+ $WPP = Services::WpPlugins();
98
+ $plugin = $WPP->getPluginAsVo( $file );
99
+ if ( $plugin->isWpOrg() && $WPP->reinstall( $plugin->file ) ) {
100
+ try {
101
+ ( new Lib\Snapshots\StoreAction\Build() )
102
+ ->setMod( $this->getMod() )
103
+ ->setAsset( $plugin )
104
+ ->run();
105
+ $success = true;
106
+ }
107
+ catch ( \Exception $e ) {
108
+ }
109
+ }
110
+ return $success;
111
+ }
112
+
113
+ /**
114
+ * Can only possibly repair themes, plugins or core files.
115
+ * @return Scans\Afs\ResultsSet
116
+ */
117
+ protected function getItemsToAutoRepair() {
118
+ /** @var Options $opts */
119
+ $opts = $this->getOptions();
120
+
121
+ $repairResults = $this->getNewResultsSet();
122
+
123
+ /** @var Scans\Afs\ResultItem $item */
124
+ foreach ( parent::getItemsToAutoRepair()->getAllItems() as $item ) {
125
+
126
+ if ( $item->is_in_core && $opts->isRepairFileWP() ) {
127
+ $repairResults->addItem( $item );
128
+ }
129
+ if ( $item->is_in_plugin && $opts->isRepairFilePlugin() ) {
130
+ $repairResults->addItem( $item );
131
+ }
132
+ if ( $item->is_in_theme && $opts->isRepairFileTheme() ) {
133
+ $repairResults->addItem( $item );
134
+ }
135
+ }
136
+
137
+ return $repairResults;
138
+ }
139
+
140
+ /**
141
+ * @param Scans\Afs\ResultItem $item
142
+ */
143
+ public function cleanStaleResultItem( $item ) {
144
+ /** @var ModCon $mod */
145
+ $mod = $this->getMod();
146
+ $FS = Services::WpFs();
147
+ /** @var Update $updater */
148
+ $updater = $mod->getDbH_ResultItems()->getQueryUpdater();
149
+
150
+ if ( ( $item->is_unrecognised || $item->is_mal ) && !$FS->isFile( $item->path_full ) ) {
151
+ $updater->setItemDeleted( $item->VO->resultitem_id );
152
+ }
153
+ elseif ( $item->is_in_core ) {
154
+
155
+ $CFH = Services::CoreFileHashes();
156
+ if ( $item->is_checksumfail && $CFH->isCoreFileHashValid( $item->path_full ) ) {
157
+ $updater->setItemRepaired( $item->VO->resultitem_id );
158
+ }
159
+ elseif ( $item->is_missing && !$CFH->isCoreFile( $item->path_full ) ) {
160
+ $mod->getDbH_ResultItems()->getQueryDeleter()->deleteById( $item->VO->resultitem_id );
161
+ }
162
+ }
163
+ elseif ( $item->is_in_plugin || $item->is_in_theme ) {
164
+ try {
165
+ $verifiedHash = ( new Lib\Hashes\Query() )
166
+ ->setMod( $this->getMod() )
167
+ ->verifyHash( $item->path_full );
168
+ if ( $item->is_checksumfail && $verifiedHash ) {
169
+ /** @var Update $updater */
170
+ $updater = $mod->getDbH_ResultItems()->getQueryUpdater();
171
+ $updater->setItemRepaired( $item->VO->resultitem_id );
172
+ }
173
+ }
174
+ catch ( Lib\Hashes\Exceptions\AssetHashesNotFound $e ) {
175
+ // hashes are unavailable, so we do nothing
176
+ }
177
+ catch ( Lib\Hashes\Exceptions\NoneAssetFileException $e ) {
178
+ // asset has probably been since removed
179
+ $mod->getDbH_ResultItems()->getQueryDeleter()->deleteById( $item->VO->resultitem_id );
180
+ }
181
+ catch ( Lib\Hashes\Exceptions\UnrecognisedAssetFile $e ) {
182
+ // unrecognised file
183
+ }
184
+ catch ( \Exception $e ) {
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * @return Scans\Afs\Utilities\ItemActionHandler
191
+ */
192
+ protected function newItemActionHandler() {
193
+ return new Scans\Afs\Utilities\ItemActionHandler();
194
+ }
195
+
196
+ public function isCronAutoRepair() :bool {
197
+ /** @var Options $opts */
198
+ $opts = $this->getOptions();
199
+ return $opts->isRepairFileAuto();
200
+ }
201
+
202
+ public function isEnabled() :bool {
203
+ /** @var Options $opts */
204
+ $opts = $this->getOptions();
205
+ return $opts->isEnabledAutoFileScanner();
206
+ }
207
+
208
+ public function isEnabledMalwareScan() :bool {
209
+ return $this->isEnabled() && !$this->isRestrictedMalwareScan();
210
+ }
211
+
212
+ public function isEnabledPluginThemeScan() :bool {
213
+ return $this->isEnabled() && $this->getCon()->hasCacheDir() && !$this->isRestrictedPluginThemeScan();
214
+ }
215
+
216
+ public function isRestrictedMalwareScan() :bool {
217
+ return !$this->getCon()->isPremiumActive();
218
+ }
219
+
220
+ public function isRestrictedPluginThemeScan() :bool {
221
+ return !$this->getCon()->isPremiumActive();
222
+ }
223
+
224
+ protected function isPremiumOnly() :bool {
225
+ return false;
226
+ }
227
+
228
+ /**
229
+ * @return Scans\Afs\ScanActionVO
230
+ */
231
+ public function buildScanAction() {
232
+ return ( new Scans\Afs\BuildScanAction() )
233
+ ->setScanController( $this )
234
+ ->build()
235
+ ->getScanActionVO();
236
+ }
237
+
238
+ /**
239
+ * Since we can't track site assets while the plugin is inactive, our snapshots and results
240
+ * are unreliable once the plugin has been deactivated.
241
+ */
242
+ public function purge() {
243
+ parent::purge();
244
+ ( new Lib\Snapshots\StoreAction\DeleteAll() )
245
+ ->setMod( $this->getMod() )
246
+ ->run();
247
+ }
248
+ }
src/lib/src/Modules/HackGuard/Scan/Controller/Apc.php CHANGED
@@ -1,13 +1,33 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
 
7
  class Apc extends BaseForAssets {
8
 
9
  const SCAN_SLUG = 'apc';
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  * @return Scans\Apc\Utilities\ItemActionHandler
13
  */
@@ -22,4 +42,14 @@ class Apc extends BaseForAssets {
22
  protected function isPremiumOnly() :bool {
23
  return false;
24
  }
 
 
 
 
 
 
 
 
 
 
25
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
 
8
  class Apc extends BaseForAssets {
9
 
10
  const SCAN_SLUG = 'apc';
11
 
12
+ public function addAdminMenuBarItem( array $items ) :array {
13
+ $template = [
14
+ 'id' => $this->getCon()->prefix( 'problems-'.$this->getSlug() ),
15
+ 'title' => '<div class="wp-core-ui wp-ui-notification shield-counter"><span aria-hidden="true">%s</span></div>',
16
+ 'href' => $this->getCon()->getModule_Insights()->getUrl_ScansResults(),
17
+ ];
18
+
19
+ $count = $this->getScansController()->getScanResultsCount()->countAbandoned();
20
+ if ( $count > 0 ) {
21
+ $warning = $template;
22
+ $warning[ 'id' ] .= '-apc';
23
+ $warning[ 'title' ] = __( 'Abandoned Plugins', 'wp-simple-firewall' ).sprintf( $warning[ 'title' ], $count );
24
+ $warning[ 'warnings' ] = $count;
25
+ $items[] = $warning;
26
+ }
27
+
28
+ return $items;
29
+ }
30
+
31
  /**
32
  * @return Scans\Apc\Utilities\ItemActionHandler
33
  */
42
  protected function isPremiumOnly() :bool {
43
  return false;
44
  }
45
+
46
+ /**
47
+ * @return Scans\Apc\ScanActionVO
48
+ */
49
+ public function buildScanAction() {
50
+ return ( new Scans\Apc\BuildScanAction() )
51
+ ->setScanController( $this )
52
+ ->build()
53
+ ->getScanActionVO();
54
+ }
55
  }
src/lib/src/Modules/HackGuard/Scan/Controller/Base.php CHANGED
@@ -2,11 +2,14 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
 
 
 
 
10
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
11
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem;
12
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultsSet;
@@ -16,14 +19,15 @@ use FernleafSystems\Wordpress\Services\Services;
16
  abstract class Base extends ExecOnceModConsumer {
17
 
18
  const SCAN_SLUG = '';
19
- use PluginCronsConsumer;
20
 
21
  /**
22
  * @var BaseScanActionVO
23
  */
24
  private $scanActionVO;
25
 
26
- private static $resultsCounts;
 
 
27
 
28
  public function __construct() {
29
  }
@@ -38,53 +42,20 @@ abstract class Base extends ExecOnceModConsumer {
38
  function () {
39
  /** @var HackGuard\ModCon $mod */
40
  $mod = $this->getMod();
41
- $mod->getScanQueueController()->startScans( [ $this->getSlug() ] );
42
  }
43
  );
44
  add_filter( $this->getCon()->prefix( 'admin_bar_menu_items' ), [ $this, 'addAdminMenuBarItem' ], 100 );
45
  }
46
 
47
  public function addAdminMenuBarItem( array $items ) :array {
48
- $problems = $this->countScanProblems();
49
- if ( $problems > 0 ) {
50
- $items[] = [
51
- 'id' => $this->getCon()->prefix( 'problems-'.$this->getSlug() ),
52
- 'title' => $this->getScanName()
53
- .sprintf( '<div class="wp-core-ui wp-ui-notification shield-counter"><span aria-hidden="true">%s</span></div>', $problems ),
54
- 'href' => $this->getCon()->getModule_Insights()->getUrl_ScansResults(),
55
- 'warnings' => $problems
56
- ];
57
- }
58
- return $items;
59
  }
60
 
61
  public function cleanStalesResults() {
62
- $results = ( new HackGuard\Scan\Results\ResultsRetrieve() )
63
- ->setScanController( $this )
64
- ->retrieve();
65
- foreach ( $results->getItems() as $item ) {
66
- if ( !$this->isResultItemStale( $item ) ) {
67
- $results->removeItemByHash( $item->hash );
68
- }
69
  }
70
- try {
71
- ( new HackGuard\Scan\Results\ResultsDelete() )
72
- ->setScanController( $this )
73
- ->delete( $results, true );
74
- }
75
- catch ( \Exception $e ) {
76
- }
77
-
78
- $this->cleanStalesDeletedResults();
79
- }
80
-
81
- public function cleanStalesDeletedResults() {
82
- /** @var Databases\Scanner\Delete $deleter */
83
- $deleter = $this->getScanResultsDbHandler()->getQueryDeleter();
84
- $deleter->addWhere( 'deleted_at', 0, '>' )
85
- ->addWhereOlderThan( Services::Request()->carbon()->subMonths( 1 )->timestamp, 'deleted_at' )
86
- ->filterByScan( $this->getSlug() )
87
- ->query();
88
  }
89
 
90
  public function createFileDownloadLink( int $recordID ) :string {
@@ -92,31 +63,39 @@ abstract class Base extends ExecOnceModConsumer {
92
  }
93
 
94
  public function countScanProblems() :int {
95
- if ( !isset( self::$resultsCounts ) ) {
96
- /** @var ModCon $mod */
97
- $mod = $this->getMod();
98
- /** @var Databases\Scanner\Select $sel */
99
- $sel = $mod->getDbHandler_ScanResults()->getQuerySelector();
100
- self::$resultsCounts = $sel->countForEachScan();
 
 
 
 
 
101
  }
102
- return self::$resultsCounts[ static::SCAN_SLUG ] ?? 0;
103
  }
104
 
105
- public function getScanHasProblem() :bool {
106
- return $this->countScanProblems() > 0;
 
 
107
  }
108
 
109
  /**
110
- * @param ResultItem|mixed $item
111
- * @return bool
112
  */
113
- abstract protected function isResultItemStale( $item ) :bool;
114
-
115
- public function executeEntryAction( Databases\Scanner\EntryVO $entry, string $action ) :bool {
116
- $item = ( new HackGuard\Scan\Results\ConvertBetweenTypes() )
117
- ->setScanController( $this )
118
- ->convertVoToResultItem( $entry );
119
 
 
 
 
 
 
120
  return $this->getItemActionHandler()
121
  ->setScanItem( $item )
122
  ->process( $action );
@@ -126,31 +105,50 @@ abstract class Base extends ExecOnceModConsumer {
126
  * @return Scans\Base\ResultsSet|mixed
127
  */
128
  protected function getItemsToAutoRepair() {
129
- /** @var Databases\Scanner\Select $sel */
130
- $sel = $this->getScanResultsDbHandler()->getQuerySelector();
131
- $sel->filterByScan( $this->getSlug() )
132
- ->filterByNoRepairAttempted()
133
- ->filterByNotIgnored();
134
- return ( new HackGuard\Scan\Results\ConvertBetweenTypes() )
135
- ->setScanController( $this )
136
- ->fromVOsToResultsSet( $sel->query() );
 
 
137
  }
138
 
139
  /**
140
- * @param bool $includeIgnored
141
  * @return Scans\Base\ResultsSet|mixed
142
  */
143
- public function getAllResults( $includeIgnored = false ) {
144
- /** @var Databases\Scanner\Select $sel */
145
- $sel = $this->getScanResultsDbHandler()->getQuerySelector();
146
- $sel->filterByScan( $this->getSlug() );
147
- if ( !$includeIgnored ) {
148
- $sel->filterByNotIgnored();
 
 
 
 
 
 
 
149
  }
150
- $raw = $this->isRestricted() ? [] : $sel->query();
151
- return ( new HackGuard\Scan\Results\ConvertBetweenTypes() )
152
- ->setScanController( $this )
153
- ->fromVOsToResultsSet( $raw );
 
 
 
 
 
 
 
 
 
 
 
154
  }
155
 
156
  /**
@@ -171,7 +169,7 @@ abstract class Base extends ExecOnceModConsumer {
171
  * @return BaseScanActionVO|mixed
172
  */
173
  public function getScanActionVO() {
174
- if ( !$this->scanActionVO instanceof BaseScanActionVO ) {
175
  $this->scanActionVO = HackGuard\Scan\ScanActionFromSlug::GetAction( $this->getSlug() );
176
  }
177
  return $this->scanActionVO;
@@ -180,19 +178,17 @@ abstract class Base extends ExecOnceModConsumer {
180
  public function getScanName() :string {
181
  /** @var HackGuard\Strings $strings */
182
  $strings = $this->getMod()->getStrings();
183
- return $strings->getScanStrings()[ static::SCAN_SLUG ][ 'name' ];
184
  }
185
 
186
  public function isCronAutoRepair() :bool {
187
  return false;
188
  }
189
 
190
- public function canCronAutoDelete() :bool {
191
  return false;
192
  }
193
 
194
- abstract public function isEnabled() :bool;
195
-
196
  protected function isPremiumOnly() :bool {
197
  return true;
198
  }
@@ -207,38 +203,25 @@ abstract class Base extends ExecOnceModConsumer {
207
  return $this->isPremiumOnly() && !$this->getCon()->isPremiumActive();
208
  }
209
 
210
- public function resetIgnoreStatus() :bool {
211
- return $this->getScanResultsDbHandler()
212
- ->getQueryUpdater()
213
- ->setUpdateWheres( [ 'scan' => $this->getSlug() ] )
214
- ->setUpdateData( [ 'ignored_at' => 0 ] )
215
- ->query() !== false;
216
- }
217
-
218
- public function resetNotifiedStatus() :bool {
219
- return $this->getScanResultsDbHandler()
220
- ->getQueryUpdater()
221
- ->setUpdateWheres( [ 'scan' => $this->getSlug() ] )
222
- ->setUpdateData( [ 'notified_at' => 0 ] )
223
- ->query() !== false;
224
  }
225
 
226
  /**
227
  * TODO: Make private/protected
228
  */
229
  public function runCronAutoRepair() {
230
- $results = $this->getItemsToAutoRepair();
231
- if ( $results->hasItems() ) {
232
- foreach ( $results->getAllItems() as $item ) {
233
- try {
234
- $this->getItemActionHandler()
235
- ->setScanItem( $item )
236
- ->repair( $this->canCronAutoDelete() );
237
- }
238
- catch ( \Exception $e ) {
239
- }
240
  }
241
- $this->cleanStalesResults();
242
  }
243
  }
244
 
@@ -246,18 +229,10 @@ abstract class Base extends ExecOnceModConsumer {
246
  * @return $this
247
  */
248
  public function purge() {
249
- ( new HackGuard\Scan\Results\ResultsDelete() )
250
- ->setScanController( $this )
251
- ->deleteAllForScan();
252
  return $this;
253
  }
254
 
255
- public function getScanResultsDbHandler() :Databases\Scanner\Handler {
256
- /** @var ModCon $mod */
257
- $mod = $this->getMod();
258
- return $mod->getDbHandler_ScanResults();
259
- }
260
-
261
  public function getSlug() :string {
262
  try {
263
  $slug = strtolower( ( new \ReflectionClass( $this ) )->getShortName() );
@@ -294,10 +269,41 @@ abstract class Base extends ExecOnceModConsumer {
294
  return rtrim( $ns, '\\' ).'\\';
295
  }
296
 
297
- protected function scheduleOnDemandScan( int $nDelay = 3 ) {
298
- $sHook = $this->getCon()->prefix( 'ondemand_scan_'.$this->getSlug() );
299
- if ( !wp_next_scheduled( $sHook ) ) {
300
- wp_schedule_single_event( Services::Request()->ts() + $nDelay, $sHook );
301
  }
302
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\{
10
+ Retrieve,
11
+ Update
12
+ };
13
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
14
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem;
15
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultsSet;
19
  abstract class Base extends ExecOnceModConsumer {
20
 
21
  const SCAN_SLUG = '';
 
22
 
23
  /**
24
  * @var BaseScanActionVO
25
  */
26
  private $scanActionVO;
27
 
28
+ protected $latestResults;
29
+
30
+ private static $resultsCounts = [];
31
 
32
  public function __construct() {
33
  }
42
  function () {
43
  /** @var HackGuard\ModCon $mod */
44
  $mod = $this->getMod();
45
+ $mod->getScansCon()->startNewScans( [ $this->getSlug() ] );
46
  }
47
  );
48
  add_filter( $this->getCon()->prefix( 'admin_bar_menu_items' ), [ $this, 'addAdminMenuBarItem' ], 100 );
49
  }
50
 
51
  public function addAdminMenuBarItem( array $items ) :array {
52
+ return [];
 
 
 
 
 
 
 
 
 
 
53
  }
54
 
55
  public function cleanStalesResults() {
56
+ foreach ( $this->getAllResults()->getItems() as $item ) {
57
+ $this->cleanStaleResultItem( $item );
 
 
 
 
 
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
  public function createFileDownloadLink( int $recordID ) :string {
63
  }
64
 
65
  public function countScanProblems() :int {
66
+ if ( !isset( self::$resultsCounts[ $this->getSlug() ] ) ) {
67
+ if ( $this->isRestricted() ) {
68
+ $count = 0;
69
+ }
70
+ else {
71
+ $count = ( new Retrieve() )
72
+ ->setScanController( $this )
73
+ ->setMod( $this->getMod() )
74
+ ->count();
75
+ }
76
+ self::$resultsCounts[ $this->getSlug() ] = $count;
77
  }
78
+ return self::$resultsCounts[ $this->getSlug() ];
79
  }
80
 
81
+ public function getScansController() :HackGuard\Scan\ScansController {
82
+ /** @var ModCon $mod */
83
+ $mod = $this->getMod();
84
+ return $mod->getScansCon();
85
  }
86
 
87
  /**
88
+ * @param ResultItem $item
 
89
  */
90
+ public function cleanStaleResultItem( $item ) {
91
+ return true;
92
+ }
 
 
 
93
 
94
+ /**
95
+ * @param ResultItem $item
96
+ * @throws \Exception
97
+ */
98
+ public function executeItemAction( $item, string $action ) :bool {
99
  return $this->getItemActionHandler()
100
  ->setScanItem( $item )
101
  ->process( $action );
105
  * @return Scans\Base\ResultsSet|mixed
106
  */
107
  protected function getItemsToAutoRepair() {
108
+ if ( $this->isRestricted() || !$this->isCronAutoRepair() ) {
109
+ $results = $this->getNewResultsSet();
110
+ }
111
+ else {
112
+ $results = ( new Retrieve() )
113
+ ->setMod( $this->getMod() )
114
+ ->setScanController( $this )
115
+ ->retrieveForAutoRepair();
116
+ }
117
+ return $results;
118
  }
119
 
120
  /**
 
121
  * @return Scans\Base\ResultsSet|mixed
122
  */
123
+ public function getAllResults() {
124
+ if ( !isset( $this->latestResults ) ) {
125
+ $this->latestResults = $this->getNewResultsSet();
126
+ if ( !$this->isRestricted() ) {
127
+ try {
128
+ $this->latestResults = ( new HackGuard\Scan\Results\Retrieve() )
129
+ ->setMod( $this->getMod() )
130
+ ->setScanController( $this )
131
+ ->retrieveLatest( true );
132
+ }
133
+ catch ( \Exception $e ) {
134
+ }
135
+ }
136
  }
137
+ return $this->latestResults;
138
+ }
139
+
140
+ /**
141
+ * @return Scans\Base\ResultsSet|mixed
142
+ */
143
+ public function getLatestResults() {
144
+ return $this->getNewResultsSet();
145
+ }
146
+
147
+ /**
148
+ * @return Scans\Base\ResultsSet|mixed
149
+ */
150
+ public function getResultsForDisplay() {
151
+ return $this->getAllResults()->getNotIgnored();
152
  }
153
 
154
  /**
169
  * @return BaseScanActionVO|mixed
170
  */
171
  public function getScanActionVO() {
172
+ if ( empty( $this->scanActionVO ) ) {
173
  $this->scanActionVO = HackGuard\Scan\ScanActionFromSlug::GetAction( $this->getSlug() );
174
  }
175
  return $this->scanActionVO;
178
  public function getScanName() :string {
179
  /** @var HackGuard\Strings $strings */
180
  $strings = $this->getMod()->getStrings();
181
+ return $strings->getScanStrings()[ $this->getSlug() ][ 'name' ];
182
  }
183
 
184
  public function isCronAutoRepair() :bool {
185
  return false;
186
  }
187
 
188
+ public function isEnabled() :bool {
189
  return false;
190
  }
191
 
 
 
192
  protected function isPremiumOnly() :bool {
193
  return true;
194
  }
203
  return $this->isPremiumOnly() && !$this->getCon()->isPremiumActive();
204
  }
205
 
206
+ public function resetIgnoreStatus() {
207
+ ( new Update() )
208
+ ->setMod( $this->getMod() )
209
+ ->setScanController( $this )
210
+ ->clearIgnored();
 
 
 
 
 
 
 
 
 
211
  }
212
 
213
  /**
214
  * TODO: Make private/protected
215
  */
216
  public function runCronAutoRepair() {
217
+ foreach ( $this->getItemsToAutoRepair()->getAllItems() as $item ) {
218
+ try {
219
+ $this->getItemActionHandler()
220
+ ->setScanItem( $item )
221
+ ->repair( false );
222
+ }
223
+ catch ( \Exception $e ) {
 
 
 
224
  }
 
225
  }
226
  }
227
 
229
  * @return $this
230
  */
231
  public function purge() {
232
+ // TODO
 
 
233
  return $this;
234
  }
235
 
 
 
 
 
 
 
236
  public function getSlug() :string {
237
  try {
238
  $slug = strtolower( ( new \ReflectionClass( $this ) )->getShortName() );
269
  return rtrim( $ns, '\\' ).'\\';
270
  }
271
 
272
+ protected function scheduleOnDemandScan() {
273
+ $hook = $this->getCon()->prefix( 'ondemand_scan_'.$this->getSlug() );
274
+ if ( !wp_next_scheduled( $hook ) ) {
275
+ wp_schedule_single_event( Services::Request()->ts() + 10, $hook );
276
  }
277
  }
278
+
279
+ /**
280
+ * @return BaseScanActionVO|mixed
281
+ */
282
+ abstract public function buildScanAction();
283
+
284
+ abstract public function buildScanResult( array $rawResult ) :HackGuard\DB\ResultItems\Ops\Record;
285
+
286
+ /**
287
+ * @deprecated 12.1
288
+ */
289
+ public function getScanResultsDbHandler() :Databases\Scanner\Handler {
290
+ /** @var ModCon $mod */
291
+ $mod = $this->getMod();
292
+ return $mod->getDbHandler_ScanResults();
293
+ }
294
+
295
+ /**
296
+ * @param ResultItem|mixed $item
297
+ * @deprecated 12.1
298
+ */
299
+ public function isResultItemStale( $item ) :bool {
300
+ return false;
301
+ }
302
+
303
+ /**
304
+ * @deprecated 13.0
305
+ */
306
+ public function getScanHasProblem() :bool {
307
+ return false;
308
+ }
309
  }
src/lib/src/Modules/HackGuard/Scan/Controller/BaseForAssets.php CHANGED
@@ -1,25 +1,49 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
8
  abstract class BaseForAssets extends Base {
9
 
10
  /**
11
- * @param Scans\Ptg\ResultItem|Scans\Wpv\ResultItem|Scans\Apc\ResultItem $item
12
- * @return bool
13
  */
14
- protected function isResultItemStale( $item ) :bool {
15
- if ( $item->context == 'plugins' ) {
16
- $asset = Services::WpPlugins()->getPluginAsVo( $item->slug );
17
- $stale = empty( $asset );
 
 
18
  }
19
  else {
20
- $asset = Services::WpThemes()->getThemeAsVo( $item->slug );
21
- $stale = empty( $asset );
 
 
 
 
 
22
  }
23
- return $stale;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  abstract class BaseForAssets extends Base {
11
 
12
  /**
13
+ * @param Scans\Wpv\ResultItem|Scans\Apc\ResultItem $item
 
14
  */
15
+ public function cleanStaleResultItem( $item ) {
16
+ /** @var ModCon $mod */
17
+ $mod = $this->getMod();
18
+
19
+ if ( strpos( $item->VO->item_id, '/' ) ) {
20
+ $asset = Services::WpPlugins()->getPluginAsVo( $item->VO->item_id );
21
  }
22
  else {
23
+ $asset = Services::WpThemes()->getThemeAsVo( $item->VO->item_id );
24
+ }
25
+
26
+ if ( empty( $asset ) ) {
27
+ /** @var ResultItems\Ops\Update $updater */
28
+ $updater = $mod->getDbH_ResultItems()->getQueryUpdater();
29
+ $updater->setItemDeleted( $item->VO->resultitem_id );
30
  }
31
+ }
32
+
33
+ public function buildScanResult( array $rawResult ) :ResultItems\Ops\Record {
34
+ /** @var ModCon $mod */
35
+ $mod = $this->getMod();
36
+ /** @var ResultItems\Ops\Record $record */
37
+ $record = $mod->getDbH_ResultItems()->getRecord();
38
+ $record->item_id = $rawResult[ 'slug' ];
39
+ $record->item_type = strpos( $rawResult[ 'slug' ], '/' ) ?
40
+ ResultItems\Ops\Handler::ITEM_TYPE_PLUGIN :
41
+ ResultItems\Ops\Handler::ITEM_TYPE_THEME;
42
+
43
+ unset( $rawResult[ 'context' ] );
44
+ unset( $rawResult[ 'hash' ] );
45
+ unset( $rawResult[ 'slug' ] );
46
+ $record->meta = $rawResult;
47
+ return $record;
48
  }
49
  }
src/lib/src/Modules/HackGuard/Scan/Controller/BaseForFiles.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
+ use FernleafSystems\Wordpress\Services\Services;
9
+
10
+ abstract class BaseForFiles extends Base {
11
+
12
+ public function buildScanResult( array $rawResult ) :ResultItems\Ops\Record {
13
+ /** @var ModCon $mod */
14
+ $mod = $this->getMod();
15
+
16
+ $autoFiltered = $rawResult[ 'auto_filter' ] ?? false;
17
+
18
+ /** @var ResultItems\Ops\Record $record */
19
+ $record = $mod->getDbH_ResultItems()->getRecord();
20
+ $record->auto_filtered_at = $autoFiltered ? Services::Request()->ts() : 0;
21
+ $record->item_id = $rawResult[ 'path_fragment' ];
22
+ $record->item_type = ResultItems\Ops\Handler::ITEM_TYPE_FILE;
23
+
24
+ $metaToClear = [
25
+ 'auto_filter',
26
+ 'path_full',
27
+ 'scan',
28
+ 'hash',
29
+ ];
30
+ foreach ( $metaToClear as $metaItem ) {
31
+ unset( $rawResult[ $metaItem ] );
32
+ }
33
+
34
+ $meta = $rawResult;
35
+ $record->meta = $meta;
36
+
37
+ return $record;
38
+ }
39
+ }
src/lib/src/Modules/HackGuard/Scan/Controller/Mal.php CHANGED
@@ -2,63 +2,22 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
 
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
  use FernleafSystems\Wordpress\Services\Services;
8
  use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
9
 
10
- class Mal extends Base {
 
 
 
11
 
12
  const SCAN_SLUG = 'mal';
13
 
14
- /**
15
- * Can only possibly repair themes, plugins or core files.
16
- * @return Scans\Mal\ResultsSet
17
- */
18
- protected function getItemsToAutoRepair() {
19
- /** @var HackGuard\Options $opts */
20
- $opts = $this->getOptions();
21
-
22
- $oRes = new Scans\Mal\ResultsSet();
23
-
24
- /** @var Scans\Mal\ResultItem $item */
25
- foreach ( parent::getItemsToAutoRepair()->getAllItems() as $item ) {
26
-
27
- try {
28
- if ( $opts->isRepairFilePlugin()
29
- && ( new WpOrg\Plugin\Files() )->isValidFileFromPlugin( $item->path_full ) ) {
30
- $oRes->addItem( $item );
31
- }
32
- }
33
- catch ( \InvalidArgumentException $e ) {
34
- }
35
-
36
- try {
37
- if ( $opts->isRepairFileTheme()
38
- && ( new WpOrg\Theme\Files() )->isValidFileFromTheme( $item->path_full ) ) {
39
- $oRes->addItem( $item );
40
- }
41
- }
42
- catch ( \InvalidArgumentException $e ) {
43
- }
44
-
45
- if ( !$opts->isRepairFileWP()
46
- && Services::CoreFileHashes()->isCoreFile( $item->path_full ) ) {
47
- $oRes->addItem( $item );
48
- }
49
- }
50
-
51
- return $oRes;
52
- }
53
-
54
- /**
55
- * @param Scans\Mal\ResultItem $item
56
- * @return bool
57
- */
58
- protected function isResultItemStale( $item ) :bool {
59
- return !Services::WpFs()->exists( $item->path_full );
60
- }
61
-
62
  /**
63
  * @return Scans\Mal\Utilities\ItemActionHandler
64
  */
@@ -66,13 +25,13 @@ class Mal extends Base {
66
  return new Scans\Mal\Utilities\ItemActionHandler();
67
  }
68
 
69
- public function isCronAutoRepair() :bool {
70
- /** @var HackGuard\Options $opts */
71
- $opts = $this->getOptions();
72
- return $opts->isRepairFileAuto();
73
- }
74
-
75
- public function isEnabled() :bool {
76
- return $this->getOptions()->isOpt( 'mal_scan_enable', 'Y' );
77
  }
78
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems\Ops\Update;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
11
  use FernleafSystems\Wordpress\Services\Services;
12
  use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
13
 
14
+ /**
15
+ * @deprecated 13.0
16
+ */
17
+ class Mal extends BaseForFiles {
18
 
19
  const SCAN_SLUG = 'mal';
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * @return Scans\Mal\Utilities\ItemActionHandler
23
  */
25
  return new Scans\Mal\Utilities\ItemActionHandler();
26
  }
27
 
28
+ /**
29
+ * @return Scans\Mal\ScanActionVO
30
+ */
31
+ public function buildScanAction() {
32
+ return ( new Scans\Mal\BuildScanAction() )
33
+ ->setScanController( $this )
34
+ ->build()
35
+ ->getScanActionVO();
36
  }
37
  }
src/lib/src/Modules/HackGuard/Scan/Controller/Ptg.php CHANGED
@@ -2,101 +2,35 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
- use FernleafSystems\Wordpress\Services\Services;
9
- use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
10
 
11
- class Ptg extends BaseForAssets {
 
 
 
12
 
13
  const SCAN_SLUG = 'ptg';
 
14
 
15
  protected function run() {
16
  parent::run();
17
- ( new HackGuard\Scan\Utilities\PtgAddReinstallLinks() )
18
- ->setScanController( $this )
19
- ->execute();
20
-
21
- $this->setupCronHooks();
22
- add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] );
23
- add_action( $this->getCon()->prefix( 'plugin_shutdown' ), [ $this, 'onModuleShutdown' ] );
24
  }
25
 
26
  public function onWpLoaded() {
27
- ( new StoreAction\ScheduleBuildAll() )
28
- ->setMod( $this->getMod() )
29
- ->hookBuild();
30
  }
31
 
32
  public function onModuleShutdown() {
33
- ( new StoreAction\ScheduleBuildAll() )
34
- ->setMod( $this->getMod() )
35
- ->schedule();
36
  }
37
 
38
  public function runHourlyCron() {
39
- ( new StoreAction\TouchAll() )
40
- ->setMod( $this->getMod() )
41
- ->run();
42
- ( new StoreAction\CleanAll() )
43
- ->setMod( $this->getMod() )
44
- ->run();
45
- }
46
-
47
- /**
48
- * @return Scans\Ptg\ResultsSet
49
- */
50
- protected function getItemsToAutoRepair() {
51
- /** @var HackGuard\Options $opts */
52
- $opts = $this->getOptions();
53
-
54
- /** @var Scans\Ptg\ResultsSet $results */
55
- $results = parent::getItemsToAutoRepair();
56
-
57
- if ( !$opts->isRepairFilePlugin() || !$opts->isRepairFileTheme() ) {
58
- if ( $opts->isRepairFileTheme() ) {
59
- $results = $results->getResultsForThemesContext();
60
- }
61
- elseif ( $opts->isRepairFilePlugin() ) {
62
- $results = $results->getResultsForPluginsContext();
63
- }
64
-
65
- /** @var Scans\Ptg\ResultItem $item */
66
- foreach ( $results->getItems() as $item ) {
67
- if ( $item->is_unrecognised ) {
68
- $results->removeItem( $item );
69
- }
70
- }
71
- }
72
-
73
- return $results;
74
- }
75
-
76
- public function isCronAutoRepair() :bool {
77
- /** @var HackGuard\Options $opts */
78
- $opts = $this->getOptions();
79
- return $opts->isRepairFilePlugin() || $opts->isRepairFileTheme();
80
  }
81
 
82
  /**
83
  * @param Scans\Ptg\ResultItem $item
84
- * @return bool
85
  */
86
- protected function isResultItemStale( $item ) :bool {
87
- $FS = Services::WPFS();
88
- $stale = parent::isResultItemStale( $item )
89
- || ( ( $item->is_unrecognised || $item->is_different ) && !$FS->isFile( $item->path_full ) );
90
-
91
- if ( !$stale ) {
92
- $asset = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $item->path_full );
93
- if ( empty( $asset ) ) {
94
- $asset = ( new WpOrg\Theme\Files() )->findThemeFromFile( $item->path_full );
95
- }
96
- $stale = empty( $asset );
97
- }
98
-
99
- return $stale;
100
  }
101
 
102
  /**
@@ -106,40 +40,17 @@ class Ptg extends BaseForAssets {
106
  return new Scans\Ptg\Utilities\ItemActionHandler();
107
  }
108
 
109
- public function actionPluginReinstall( string $file ) :bool {
110
- $success = false;
111
- $WPP = Services::WpPlugins();
112
- $plugin = $WPP->getPluginAsVo( $file );
113
- if ( $plugin->isWpOrg() && $WPP->reinstall( $plugin->file ) ) {
114
- try {
115
- ( new HackGuard\Lib\Snapshots\StoreAction\Build() )
116
- ->setMod( $this->getMod() )
117
- ->setAsset( $plugin )
118
- ->run();
119
- $success = true;
120
- }
121
- catch ( \Exception $e ) {
122
- }
123
- }
124
- return $success;
125
- }
126
-
127
- public function isEnabled() :bool {
128
- return $this->getOptions()->isOpt( 'ptg_enable', 'Y' );
129
- }
130
-
131
  public function isReady() :bool {
132
  return parent::isReady() && $this->getCon()->hasCacheDir();
133
  }
134
 
135
  /**
136
- * Since we can't track site assets while the plugin is inactive, our snapshots and results
137
- * are unreliable once the plugin has been deactivated.
138
  */
139
- public function purge() {
140
- parent::purge();
141
- ( new HackGuard\Lib\Snapshots\StoreAction\DeleteAll() )
142
- ->setMod( $this->getMod() )
143
- ->run();
144
  }
145
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ResultItems;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
 
 
8
 
9
+ /**
10
+ * @deprecated 13.0
11
+ */
12
+ class Ptg extends BaseForFiles {
13
 
14
  const SCAN_SLUG = 'ptg';
15
+ use PluginCronsConsumer;
16
 
17
  protected function run() {
18
  parent::run();
 
 
 
 
 
 
 
19
  }
20
 
21
  public function onWpLoaded() {
 
 
 
22
  }
23
 
24
  public function onModuleShutdown() {
 
 
 
25
  }
26
 
27
  public function runHourlyCron() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
30
  /**
31
  * @param Scans\Ptg\ResultItem $item
 
32
  */
33
+ public function cleanStaleResultItem( $item ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
 
36
  /**
40
  return new Scans\Ptg\Utilities\ItemActionHandler();
41
  }
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  public function isReady() :bool {
44
  return parent::isReady() && $this->getCon()->hasCacheDir();
45
  }
46
 
47
  /**
48
+ * @return Scans\Ptg\ScanActionVO
 
49
  */
50
+ public function buildScanAction() {
51
+ return ( new Scans\Ptg\BuildScanAction() )
52
+ ->setScanController( $this )
53
+ ->build()
54
+ ->getScanActionVO();
55
  }
56
  }
src/lib/src/Modules/HackGuard/Scan/Controller/ScanControllerConsumer.php CHANGED
@@ -17,11 +17,11 @@ trait ScanControllerConsumer {
17
  }
18
 
19
  /**
20
- * @param Base $oCon
21
  * @return $this
22
  */
23
- public function setScanController( $oCon ) {
24
- $this->oScanController = $oCon;
25
  return $this;
26
  }
27
  }
17
  }
18
 
19
  /**
20
+ * @param Base $con
21
  * @return $this
22
  */
23
+ public function setScanController( $con ) {
24
+ $this->oScanController = $con;
25
  return $this;
26
  }
27
  }
src/lib/src/Modules/HackGuard/Scan/Controller/Ufc.php CHANGED
@@ -2,46 +2,23 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
- use FernleafSystems\Wordpress\Services\Services;
8
 
9
- class Ufc extends Base {
 
 
 
10
 
11
  const SCAN_SLUG = 'ufc';
12
 
13
- /**
14
- * @return Scans\Ufc\Utilities\ItemActionHandler
15
- */
16
  protected function newItemActionHandler() {
17
- return new Scans\Ufc\Utilities\ItemActionHandler();
18
- }
19
-
20
- public function canCronAutoDelete() :bool {
21
- return $this->isCronAutoRepair();
22
  }
23
 
24
  /**
25
- * @param Scans\Mal\ResultItem $item
26
- * @return bool
27
  */
28
- protected function isResultItemStale( $item ) :bool {
29
- return !Services::WpFs()->exists( $item->path_full );
30
- }
31
-
32
- public function isCronAutoRepair() :bool {
33
- /** @var HackGuard\Options $opts */
34
- $opts = $this->getOptions();
35
- return $opts->isUfsDeleteFiles();
36
- }
37
-
38
- public function isEnabled() :bool {
39
- /** @var HackGuard\Options $opts */
40
- $opts = $this->getOptions();
41
- return $opts->getUnrecognisedFileScannerOption() !== 'disabled';
42
- }
43
-
44
- protected function isPremiumOnly() :bool {
45
- return false;
46
  }
47
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
 
6
 
7
+ /**
8
+ * @deprecated 13.0
9
+ */
10
+ class Ufc extends BaseForFiles {
11
 
12
  const SCAN_SLUG = 'ufc';
13
 
 
 
 
14
  protected function newItemActionHandler() {
15
+ return null;
 
 
 
 
16
  }
17
 
18
  /**
19
+ * @return Scans\Ufc\ScanActionVO
 
20
  */
21
+ public function buildScanAction() {
22
+ return $this->getScanActionVO();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
  }
src/lib/src/Modules/HackGuard/Scan/Controller/Wcf.php CHANGED
@@ -2,41 +2,44 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
 
 
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
- class Wcf extends Base {
 
 
 
10
 
11
  const SCAN_SLUG = 'wcf';
12
 
13
- /**
14
- * @return Scans\Wcf\Utilities\ItemActionHandler
15
- */
16
- protected function newItemActionHandler() {
17
- return new Scans\Wcf\Utilities\ItemActionHandler();
18
  }
19
 
20
  /**
21
- * @param Scans\Wcf\ResultItem $item
22
- * @return bool
23
  */
24
- protected function isResultItemStale( $item ) :bool {
25
- $CFH = Services::CoreFileHashes();
26
- return !$CFH->isCoreFile( $item->path_full ) || $CFH->isCoreFileHashValid( $item->path_full );
27
  }
28
 
29
- public function isCronAutoRepair() :bool {
30
- /** @var HackGuard\Options $opts */
31
- $opts = $this->getOptions();
32
- return $opts->isRepairFileWP();
33
  }
34
 
35
- public function isEnabled() :bool {
36
- return $this->getOptions()->isOpt( 'enable_core_file_integrity_scan', 'Y' );
37
  }
38
 
39
- protected function isPremiumOnly() :bool {
40
- return false;
 
 
 
41
  }
42
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
6
+ DB\ResultItems\Ops\Update,
7
+ ModCon,
8
+ Options
9
+ };
10
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
11
  use FernleafSystems\Wordpress\Services\Services;
12
 
13
+ /**
14
+ * @deprecated 13.0
15
+ */
16
+ class Wcf extends BaseForFiles {
17
 
18
  const SCAN_SLUG = 'wcf';
19
 
20
+ public function getScanFileExclusions() :string {
21
+ return '';
 
 
 
22
  }
23
 
24
  /**
25
+ * Builds a regex-ready pattern for matching file names to exclude from scan if they're missing
 
26
  */
27
+ public function getScanExclusionsForMissingItems() :string {
28
+ return '';
 
29
  }
30
 
31
+ protected function newItemActionHandler() {
32
+ return null;
 
 
33
  }
34
 
35
+ public function cleanStaleResultItem( $item ) {
36
+ return true;
37
  }
38
 
39
+ /**
40
+ * @return Scans\Wcf\ScanActionVO
41
+ */
42
+ public function buildScanAction() {
43
+ return $this->getScanActionVO();
44
  }
45
  }
src/lib/src/Modules/HackGuard/Scan/Controller/Wpv.php CHANGED
@@ -3,6 +3,8 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
@@ -32,6 +34,27 @@ class Wpv extends BaseForAssets {
32
  }
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  /**
36
  * @param bool $bDoAutoUpdate
37
  * @param \stdClass|string $mItem
@@ -42,16 +65,21 @@ class Wpv extends BaseForAssets {
42
  return $bDoAutoUpdate || count( $this->getPluginVulnerabilities( $itemFile ) ) > 0;
43
  }
44
 
 
 
 
 
45
  /**
46
  * @param string $file
47
  * @return Scans\Wpv\WpVulnDb\VulnVO[]
48
  */
49
- public function getPluginVulnerabilities( $file ) {
50
  return array_map(
51
  function ( $item ) {
 
52
  return $item->getVulnVo();
53
  },
54
- $this->getAllResults()->getItemsForSlug( $file )
55
  );
56
  }
57
 
@@ -73,4 +101,14 @@ class Wpv extends BaseForAssets {
73
  $opts = $this->getOptions();
74
  return $opts->isPremium() && $opts->isOpt( 'enable_wpvuln_scan', 'Y' );
75
  }
 
 
 
 
 
 
 
 
 
 
76
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanResults;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
34
  }
35
  }
36
 
37
+ public function addAdminMenuBarItem( array $items ) :array {
38
+ $status = $this->getScansController()->getScanResultsCount();
39
+
40
+ $template = [
41
+ 'id' => $this->getCon()->prefix( 'problems-'.$this->getSlug() ),
42
+ 'title' => '<div class="wp-core-ui wp-ui-notification shield-counter"><span aria-hidden="true">%s</span></div>',
43
+ 'href' => $this->getCon()->getModule_Insights()->getUrl_ScansResults(),
44
+ ];
45
+
46
+ $count = $status->countVulnerableAssets();
47
+ if ( $count > 0 ) {
48
+ $warning = $template;
49
+ $warning[ 'id' ] .= '-wpv';
50
+ $warning[ 'title' ] = __( 'Vulnerable Plugins', 'wp-simple-firewall' ).sprintf( $warning[ 'title' ], $count );
51
+ $warning[ 'warnings' ] = $count;
52
+ $items[] = $warning;
53
+ }
54
+
55
+ return $items;
56
+ }
57
+
58
  /**
59
  * @param bool $bDoAutoUpdate
60
  * @param \stdClass|string $mItem
65
  return $bDoAutoUpdate || count( $this->getPluginVulnerabilities( $itemFile ) ) > 0;
66
  }
67
 
68
+ public function hasVulnerabilities( string $file ) :bool {
69
+ return count( $this->getResultsForDisplay()->getItemsForSlug( $file ) ) > 0;
70
+ }
71
+
72
  /**
73
  * @param string $file
74
  * @return Scans\Wpv\WpVulnDb\VulnVO[]
75
  */
76
+ public function getPluginVulnerabilities( string $file ) {
77
  return array_map(
78
  function ( $item ) {
79
+ /** @var $item Scans\Wpv\ResultItem */
80
  return $item->getVulnVo();
81
  },
82
+ $this->getResultsForDisplay()->getItemsForSlug( $file )
83
  );
84
  }
85
 
101
  $opts = $this->getOptions();
102
  return $opts->isPremium() && $opts->isOpt( 'enable_wpvuln_scan', 'Y' );
103
  }
104
+
105
+ /**
106
+ * @return Scans\Wpv\ScanActionVO
107
+ */
108
+ public function buildScanAction() {
109
+ return ( new Scans\Wpv\BuildScanAction() )
110
+ ->setScanController( $this )
111
+ ->build()
112
+ ->getScanActionVO();
113
+ }
114
  }
src/lib/src/Modules/HackGuard/Scan/Exceptions/NoQueueItems.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Exceptions;
4
+
5
+ class NoQueueItems extends \Exception {
6
+
7
+ }
src/lib/src/Modules/HackGuard/Scan/Exceptions/ScanException.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Exceptions;
4
+
5
+ class ScanException extends \Exception {
6
+
7
+ protected $scan;
8
+
9
+ public function __construct( string $scan, string $message = '' ) {
10
+ $this->scan = $scan;
11
+ parent::__construct( empty( $message ) ? sprintf( 'Scan Exception: %s', $scan ) : $message );
12
+ }
13
+ }
src/lib/src/Modules/HackGuard/Scan/Exceptions/ScanExistsException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Exceptions;
4
+
5
+ class ScanExistsException extends ScanException {
6
+
7
+ public function __construct( string $scan ) {
8
+ parent::__construct( $scan, sprintf( "Can't create new scan where one already exists: %s", $scan ) );
9
+ }
10
+ }
src/lib/src/Modules/HackGuard/Scan/Init/CreateNewScan.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Exceptions\ScanExistsException;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
+ use FernleafSystems\Wordpress\Services\Services;
10
+
11
+ class CreateNewScan {
12
+
13
+ use ModConsumer;
14
+
15
+ /**
16
+ * @param string $slug
17
+ * @return Scans\Ops\Record
18
+ * @throws ScanExistsException|\Exception
19
+ */
20
+ public function run( string $slug ) :Scans\Ops\Record {
21
+ /** @var ModCon $mod */
22
+ $mod = $this->getMod();
23
+
24
+ if ( $this->scanExists( $slug ) ) {
25
+ throw new ScanExistsException( $slug );
26
+ }
27
+
28
+ $dbh = $mod->getDbH_Scans();
29
+ /** @var Scans\Ops\Record $record */
30
+ $record = $dbh->getRecord();
31
+ $record->scan = $slug;
32
+ $success = $dbh->getQueryInserter()->insert( $record );
33
+ if ( !$success ) {
34
+ throw new \Exception( sprintf( 'Failed to create/insert a new scan "%s".', $slug ) );
35
+ }
36
+
37
+ return $dbh->getQuerySelector()->byId( Services::WpDb()->getVar( 'SELECT LAST_INSERT_ID()' ) );
38
+ }
39
+
40
+ private function scanExists( string $slug ) :bool {
41
+ /** @var ModCon $mod */
42
+ $mod = $this->getMod();
43
+ /** @var Scans\Ops\Select $selector */
44
+ $selector = $mod->getDbH_Scans()->getQuerySelector();
45
+ return $selector->filterByScan( $slug )
46
+ ->filterByNotFinished()
47
+ ->count() > 0;
48
+ }
49
+ }
src/lib/src/Modules/HackGuard/Scan/Init/PopulateScanItems.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Common\RecordConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems as ScanItemsDB;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
9
+ use FernleafSystems\Wordpress\Services\Services;
10
+
11
+ class PopulateScanItems {
12
+
13
+ use Controller\ScanControllerConsumer;
14
+ use RecordConsumer;
15
+
16
+ /**
17
+ * @throws \Exception
18
+ */
19
+ public function run() {
20
+ $scanCon = $this->getScanController();
21
+ /** @var ModCon $mod */
22
+ $mod = $scanCon->getMod();
23
+ $dbhItems = $mod->getDbH_ScanItems();
24
+
25
+ $scanRecord = $this->getRecord();
26
+ $scanAction = $scanCon->buildScanAction();
27
+
28
+ // ScanItems are stored separately
29
+ $allItems = $scanAction->items;
30
+ unset( $scanAction->items );
31
+
32
+ $scanRecord->meta = $scanAction->getRawData();
33
+ $mod->getDbH_Scans()
34
+ ->getQueryUpdater()
35
+ ->updateById( $scanRecord->id, [
36
+ 'meta' => $scanRecord->getRawData()[ 'meta' ]
37
+ ] );
38
+
39
+ $sliceSize = $scanAction::QUEUE_GROUP_SIZE_LIMIT;
40
+
41
+ /** @var ScanItemsDB\Ops\Record $newRecord */
42
+ $newRecord = $dbhItems->getRecord();
43
+ $newRecord->scan_ref = $scanRecord->id;
44
+ do {
45
+ $newRecord->items = array_slice( $allItems, 0, $sliceSize );
46
+ $dbhItems->getQueryInserter()->insert( $newRecord );
47
+ $allItems = array_slice( $allItems, $sliceSize );
48
+ } while ( !empty( $allItems ) );
49
+
50
+ // Marks the scan record as ready to run. It cannot run until this flag is set.
51
+ // This prevents a timing issue where we're populating scan items but the scan could get picked up and executed.
52
+ // TODO: review whether this entirely necessary depending on how scans are kicked off.
53
+ $mod->getDbH_Scans()
54
+ ->getQueryUpdater()
55
+ ->updateRecord( $scanRecord, [
56
+ 'ready_at' => Services::Request()->ts()
57
+ ] );
58
+ }
59
+ }
src/lib/src/Modules/HackGuard/Scan/Init/ScansStatus.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\Scans as ScansDB;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
+ use FernleafSystems\Wordpress\Services\Services;
9
+
10
+ class ScansStatus {
11
+
12
+ use ModConsumer;
13
+
14
+ public function current() :string {
15
+ /** @var ModCon $mod */
16
+ $mod = $this->getMod();
17
+
18
+ return (string)Services::WpDb()->getVar(
19
+ sprintf( "SELECT scans.scan
20
+ FROM `%s` as scans
21
+ INNER JOIN `%s` as `si`
22
+ ON `si`.scan_ref = `scans`.id
23
+ AND `si`.`started_at`>0
24
+ WHERE `scans`.`ready_at` > 0
25
+ AND `scans`.`finished_at`=0
26
+ LIMIT 1;",
27
+ $mod->getDbH_Scans()->getTableSchema()->table,
28
+ $mod->getDbH_ScanItems()->getTableSchema()->table
29
+ )
30
+ );
31
+ }
32
+
33
+ public function enqueued() :array {
34
+ /** @var ModCon $mod */
35
+ $mod = $this->getMod();
36
+
37
+ /** @var ScansDB\Ops\Select $selector */
38
+ $selector = $mod->getDbH_Scans()->getQuerySelector();
39
+ return $selector->filterByNotFinished()
40
+ ->addColumnToSelect( 'scan' )
41
+ ->setIsDistinct( true )
42
+ ->queryWithResult();
43
+ }
44
+ }
src/lib/src/Modules/HackGuard/Scan/Init/SetScanCompleted.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Base;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
+ use FernleafSystems\Wordpress\Services\Services;
9
+
10
+ /**
11
+ * TODO: not the most efficient
12
+ */
13
+ class SetScanCompleted {
14
+
15
+ use ModConsumer;
16
+
17
+ public function run() {
18
+ /** @var ModCon $mod */
19
+ $mod = $this->getMod();
20
+
21
+ foreach ( ( new ScansStatus() )->setMod( $mod )->enqueued() as $scan ) {
22
+ $count = (int)Services::WpDb()->getVar(
23
+ sprintf( "SELECT count(*)
24
+ FROM `%s` as scans
25
+ INNER JOIN `%s` as `si`
26
+ ON `si`.scan_ref = `scans`.id
27
+ AND `si`.finished_at=0
28
+ WHERE `scans`.`scan`='%s'
29
+ AND `scans`.`ready_at` > 0
30
+ AND `scans`.`finished_at`=0;",
31
+ $mod->getDbH_Scans()->getTableSchema()->table,
32
+ $mod->getDbH_ScanItems()->getTableSchema()->table,
33
+ $scan
34
+ )
35
+ );
36
+ if ( $count === 0 ) {
37
+ $mod->getDbH_Scans()
38
+ ->getQueryUpdater()
39
+ ->setUpdateWheres( [
40
+ 'scan' => $scan,
41
+ 'finished_at' => 0,
42
+ ] )
43
+ ->setUpdateData( [
44
+ 'finished_at' => Services::Request()->ts()
45
+ ] )
46
+ ->query();
47
+
48
+ $scanCon = $mod->getScanCon( $scan );
49
+ $this->getCon()
50
+ ->fireEvent( 'scan_run',
51
+ [
52
+ 'audit_params' => [
53
+ 'scan' => $scanCon->getScanName()
54
+ ]
55
+ ]
56
+ );
57
+
58
+ $this->auditLatestScanItems( $scanCon );
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @param Base $scanCon
65
+ */
66
+ private function auditLatestScanItems( $scanCon ) {
67
+ $results = $scanCon->getResultsForDisplay();
68
+
69
+ if ( $results->countItems() > 0 ) {
70
+
71
+ $items = $results->countItems() > 30 ?
72
+ __( 'Only the first 30 items are shown.', 'wp-simple-firewall' )
73
+ : __( 'The following items were discovered.', 'wp-simple-firewall' );
74
+
75
+ $itemDescriptions = array_slice( array_unique( array_map( function ( $item ) {
76
+ return $item->getDescriptionForAudit();
77
+ }, $results->getItems() ) ), 0, 30 );
78
+
79
+ $items .= ' "'.implode( '", "', $itemDescriptions ).'"';
80
+
81
+ $this->getCon()
82
+ ->fireEvent(
83
+ 'scan_items_found',
84
+ [
85
+ 'audit_params' => [
86
+ 'scan' => $scanCon->getScanName(),
87
+ 'items' => $items
88
+ ]
89
+ ]
90
+ );
91
+ }
92
+ }
93
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilder.php CHANGED
@@ -8,7 +8,6 @@ use FernleafSystems\Wordpress\Services\Utilities;
8
 
9
  class QueueBuilder extends Utilities\BackgroundProcessing\BackgroundProcess {
10
 
11
- use HackGuard\Scan\Queue\QueueProcessorConsumer;
12
  use Shield\Modules\ModConsumer;
13
 
14
  /**
@@ -17,15 +16,15 @@ class QueueBuilder extends Utilities\BackgroundProcessing\BackgroundProcess {
17
  * @return \stdClass Return the first batch from the queue
18
  */
19
  protected function get_batch() {
20
- /** @var HackGuard\Options $oOpts */
21
- $oOpts = $this->getOptions();
22
- $aScans = $oOpts->getScansToBuild();
23
- $sScan = key( $aScans );
24
 
25
- $oBatch = new \stdClass();
26
- $oBatch->key = $sScan;
27
- $oBatch->data = [ $sScan ];
28
- return $oBatch;
29
  }
30
 
31
  /**
@@ -53,15 +52,13 @@ class QueueBuilder extends Utilities\BackgroundProcessing\BackgroundProcess {
53
  * @return mixed
54
  */
55
  protected function task( $slug ) {
56
-
57
  try {
58
- ( new HackGuard\Scan\Queue\ScanInitiate() )
59
  ->setMod( $this->getMod() )
60
- ->setQueueProcessor( $this->getQueueProcessor() )
61
  ->init( (string)$slug );
62
  }
63
  catch ( \Exception $e ) {
64
- // error_log( $e->getMessage() );
65
  }
66
 
67
  // deletes the scan from the to-be-built array
@@ -76,19 +73,23 @@ class QueueBuilder extends Utilities\BackgroundProcessing\BackgroundProcess {
76
  */
77
  protected function complete() {
78
  parent::complete();
79
- $this->getQueueProcessor()->dispatch();
 
 
 
 
80
  }
81
 
82
  /**
83
  * Delete queue
84
  *
85
- * @param string $sScanSlug .
86
  * @return $this
87
  */
88
- public function delete( $sScanSlug ) {
89
- /** @var HackGuard\Options $oOpts */
90
- $oOpts = $this->getOptions();
91
- $oOpts->addRemoveScanToBuild( $sScanSlug, false );
92
  $this->save();
93
  return $this;
94
  }
@@ -99,9 +100,9 @@ class QueueBuilder extends Utilities\BackgroundProcessing\BackgroundProcess {
99
  * @return bool
100
  */
101
  protected function is_queue_empty() {
102
- /** @var HackGuard\Options $oOpts */
103
- $oOpts = $this->getOptions();
104
- return count( $oOpts->getScansToBuild() ) === 0;
105
  }
106
 
107
  /**
8
 
9
  class QueueBuilder extends Utilities\BackgroundProcessing\BackgroundProcess {
10
 
 
11
  use Shield\Modules\ModConsumer;
12
 
13
  /**
16
  * @return \stdClass Return the first batch from the queue
17
  */
18
  protected function get_batch() {
19
+ /** @var HackGuard\Options $opts */
20
+ $opts = $this->getOptions();
21
+ $scans = $opts->getScansToBuild();
22
+ $scan = key( $scans );
23
 
24
+ $batch = new \stdClass();
25
+ $batch->key = $scan;
26
+ $batch->data = [ $scan ];
27
+ return $batch;
28
  }
29
 
30
  /**
52
  * @return mixed
53
  */
54
  protected function task( $slug ) {
 
55
  try {
56
+ ( new HackGuard\Scan\Queue\QueueInit() )
57
  ->setMod( $this->getMod() )
 
58
  ->init( (string)$slug );
59
  }
60
  catch ( \Exception $e ) {
61
+ error_log( $e->getMessage() );
62
  }
63
 
64
  // deletes the scan from the to-be-built array
73
  */
74
  protected function complete() {
75
  parent::complete();
76
+ /** @var HackGuard\ModCon $mod */
77
+ $mod = $this->getMod();
78
+ $mod->getScanQueueController()
79
+ ->getQueueProcessor()
80
+ ->dispatch();
81
  }
82
 
83
  /**
84
  * Delete queue
85
  *
86
+ * @param string $scanSlug .
87
  * @return $this
88
  */
89
+ public function delete( $scanSlug ) {
90
+ /** @var HackGuard\Options $opts */
91
+ $opts = $this->getOptions();
92
+ $opts->addRemoveScanToBuild( $scanSlug, false );
93
  $this->save();
94
  return $this;
95
  }
100
  * @return bool
101
  */
102
  protected function is_queue_empty() {
103
+ /** @var HackGuard\Options $opts */
104
+ $opts = $this->getOptions();
105
+ return count( $opts->getScansToBuild() ) === 0;
106
  }
107
 
108
  /**
src/lib/src/Modules/HackGuard/Scan/Queue/BuildScanAction.php DELETED
@@ -1,37 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
-
8
- /**
9
- * Class BuildScanAction
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
11
- */
12
- class BuildScanAction {
13
-
14
- use Shield\Modules\ModConsumer;
15
-
16
- /**
17
- * @param string $slug
18
- * @return Shield\Scans\Base\BaseScanActionVO|mixed
19
- * @throws \Exception
20
- */
21
- public function build( $slug ) {
22
- /** @var ModCon $mod */
23
- $mod = $this->getMod();
24
-
25
- $oAction = $mod->getScanCon( $slug )->getScanActionVO();
26
-
27
- // Build the action definition:
28
-
29
- $sClass = $oAction->getScanNamespace().'BuildScanAction';
30
- /** @var Shield\Scans\Base\BaseBuildScanAction $oBuilder */
31
- $oBuilder = new $sClass();
32
- $oBuilder->setMod( $mod )
33
- ->setScanActionVO( $oAction )
34
- ->build();
35
- return $oAction;
36
- }
37
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Queue/CleanQueue.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\{
8
+ Scans as ScansDB,
9
+ ScanItems as ScanItemsDB
10
+ };
11
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
12
+
13
+ class CleanQueue extends ExecOnceModConsumer {
14
+
15
+ protected function run() {
16
+ $this->resetStaleScanItems();
17
+ $this->deleteStaleScans();
18
+ }
19
+
20
+ private function resetStaleScanItems() {
21
+ /** @var ModCon $mod */
22
+ $mod = $this->getMod();
23
+ $dbh = $mod->getDbH_ScanItems();
24
+ Services::WpDb()->doSql(
25
+ sprintf( "UPDATE `%s`
26
+ SET `started_at`=0
27
+ WHERE `started_at` > 0 AND `started_at` < %s",
28
+ $dbh->getTableSchema()->table,
29
+ Services::Request()->carbon()->subMinutes( 5 )->timestamp
30
+ )
31
+ );
32
+ }
33
+
34
+ private function deleteStaleScans() {
35
+ $this->deleteStaleScansForTime();
36
+ $this->deleteScansWithNoScanItems();
37
+ }
38
+
39
+ /**
40
+ * Stale: Scan has been ready for 20 minutes
41
+ */
42
+ private function deleteStaleScansForTime() {
43
+ /** @var ModCon $mod */
44
+ $mod = $this->getMod();
45
+ /** @var ScansDB\Ops\Delete $deleter */
46
+ $deleter = $mod->getDbH_Scans()->getQueryDeleter();
47
+
48
+ // Scan created but hasn't been set to ready within 10 minutes.
49
+ $deleter->filterByNotReady()
50
+ ->addWhereOlderThan(
51
+ Services::Request()->carbon()->subMinutes( 5 )->timestamp
52
+ )->query();
53
+
54
+ // Scan set to ready for longer than 20 minutes but never finished.
55
+ $deleter->reset()
56
+ ->filterByNotFinished()
57
+ ->filterByReady()
58
+ ->addWhereOlderThan(
59
+ Services::Request()->carbon()->subMinutes( 10 )->timestamp,
60
+ 'ready_at'
61
+ )->query();
62
+ }
63
+
64
+ /**
65
+ * Scan set to ready but no scan items available.
66
+ */
67
+ private function deleteScansWithNoScanItems() {
68
+ /** @var ModCon $mod */
69
+ $mod = $this->getMod();
70
+ /** @var ScansDB\Ops\Select $selector */
71
+ $selector = $mod->getDbH_Scans()->getQuerySelector();
72
+ /** @var ScansDB\Ops\Record[] $scans */
73
+ $scans = $selector->filterByReady()
74
+ ->filterByNotFinished()
75
+ ->queryWithResult();
76
+ foreach ( $scans as $scan ) {
77
+ /** @var ScanItemsDB\Ops\Select $selectorSI */
78
+ $selectorSI = $mod->getDbH_ScanItems()->getQuerySelector();
79
+ if ( $selectorSI->filterByScan( $scan->id )->count() === 0 ) {
80
+ $mod->getDbH_Scans()
81
+ ->getQueryDeleter()
82
+ ->deleteById( $scan->id );
83
+ }
84
+ }
85
+ }
86
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/CollateResults.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class CollateResults
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
12
- */
13
- class CollateResults {
14
-
15
- use Databases\Base\HandlerConsumer;
16
- use ScanControllerConsumer;
17
-
18
- /**
19
- * @param string $scanSlug
20
- * @return Scans\Base\ResultsSet|mixed
21
- */
22
- public function collate( $scanSlug ) {
23
- /** @var Databases\ScanQueue\Handler $dbh */
24
- $dbh = $this->getDbHandler();
25
- /** @var Databases\ScanQueue\Select $selector */
26
- $selector = $dbh->getQuerySelector();
27
- $selector->filterByScan( $scanSlug )
28
- ->setResultsAsVo( true );
29
-
30
- $resultsSet = $this->getScanController()->getNewResultsSet();
31
-
32
- /** @var Databases\ScanQueue\EntryVO $entry */
33
- foreach ( $selector->query() as $entry ) {
34
- $action = ( new ConvertBetweenTypes() )
35
- ->setDbHandler( $dbh )
36
- ->fromDbEntryToAction( $entry );
37
-
38
- foreach ( $action->results as $resultItemRawData ) {
39
- $resultsSet->addItem(
40
- $action->getNewResultItem()->applyFromArray( $resultItemRawData )
41
- );
42
- }
43
- }
44
-
45
- return $resultsSet;
46
- }
47
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php CHANGED
@@ -4,72 +4,24 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
10
  use FernleafSystems\Wordpress\Services\Services;
11
 
12
- /**
13
- * Class CompleteQueue
14
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
15
- */
16
  class CompleteQueue {
17
 
18
- use Databases\Base\HandlerConsumer;
19
  use ModConsumer;
20
 
21
- /**
22
- * Take care here not to confuse the 2x DB Handlers
23
- */
24
  public function complete() {
 
25
  /** @var ModCon $mod */
26
  $mod = $this->getMod();
27
- $con = $this->getCon();
28
- /** @var Databases\ScanQueue\Handler $dbh */
29
- $dbh = $this->getDbHandler();
30
- $selector = $dbh->getQuerySelector();
31
-
32
- foreach ( $selector->getDistinctForColumn( 'scan' ) as $scanSlug ) {
33
-
34
- $scanCon = $mod->getScanCon( $scanSlug );
35
-
36
- $resultsSet = ( new CollateResults() )
37
- ->setScanController( $scanCon )
38
- ->setDbHandler( $dbh )
39
- ->collate( $scanSlug );
40
-
41
- $con->fireEvent( 'scan_run', [ 'audit_params' => [ 'scan' => $scanCon->getScanName() ] ] );
42
 
43
- ( new HackGuard\Scan\Results\ResultsUpdate() )
44
- ->setScanController( $scanCon )
45
- ->update( $resultsSet );
46
-
47
- if ( $resultsSet->countItems() > 0 ) {
48
-
49
- $items = $resultsSet->countItems() > 30 ?
50
- __( 'Only the first 30 items are shown.', 'wp-simple-firewall' )
51
- : __( 'The following items were discovered.', 'wp-simple-firewall' );
52
-
53
- $itemDescriptions = array_slice( array_unique( array_map( function ( $item ) {
54
- return $item->getDescriptionForAudit();
55
- }, $resultsSet->getItems() ) ), 0, 30 );
56
- $items .= ' "'.implode( '", "', $itemDescriptions ).'"';
57
-
58
- $con->fireEvent(
59
- 'scan_items_found',
60
- [
61
- 'audit_params' => [
62
- 'scan' => $scanCon->getScanName(),
63
- 'items' => $items
64
- ]
65
- ]
66
- );
67
- }
68
-
69
- /** @var Databases\ScanQueue\Delete $deleter */
70
- $deleter = $dbh->getQueryDeleter();
71
- $deleter->filterByScan( $scanSlug )->query();
72
- }
73
 
74
  /** @var HackGuard\Options $opts */
75
  $opts = $this->getOptions();
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems as ScanItemsDB;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
11
  use FernleafSystems\Wordpress\Services\Services;
12
 
 
 
 
 
13
  class CompleteQueue {
14
 
 
15
  use ModConsumer;
16
 
 
 
 
17
  public function complete() {
18
+ $con = $this->getCon();
19
  /** @var ModCon $mod */
20
  $mod = $this->getMod();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ /** @var ScanItemsDB\Ops\Delete $deleter */
23
+ $deleter = $mod->getDbH_ScanItems()->getQueryDeleter();
24
+ $deleter->filterByFinished()->query();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  /** @var HackGuard\Options $opts */
27
  $opts = $this->getOptions();
src/lib/src/Modules/HackGuard/Scan/Queue/Controller.php CHANGED
@@ -2,15 +2,10 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\ScanQueue;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
- use FernleafSystems\Wordpress\Services\Services;
9
 
10
- /**
11
- * Class Controller
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
13
- */
14
  class Controller {
15
 
16
  use ModConsumer;
@@ -38,40 +33,16 @@ class Controller {
38
  * @return bool[]
39
  */
40
  public function getScansRunningStates() :array {
41
- /** @var HackGuard\ModCon $mod */
42
- $mod = $this->getMod();
43
  /** @var HackGuard\Options $opts */
44
  $opts = $this->getOptions();
45
- /** @var ScanQueue\Select $sel */
46
- $sel = $mod->getDbHandler_ScanQueue()->getQuerySelector();
47
-
48
- // First clean the queue:
49
- $this->cleanExpiredFromQueue();
50
 
51
  $scans = array_fill_keys( $opts->getScanSlugs(), false );
52
- foreach ( $sel->getInitiatedScans() as $sInitScan ) {
53
- $scans[ $sInitScan ] = true;
54
  }
55
  return $scans;
56
  }
57
 
58
- /**
59
- * @return bool
60
- */
61
- protected function cleanExpiredFromQueue() {
62
- /** @var HackGuard\ModCon $mod */
63
- $mod = $this->getMod();
64
- /** @var HackGuard\Options $opts */
65
- $opts = $this->getOptions();
66
- $nExpiredBoundary = Services::Request()
67
- ->carbon()
68
- ->subSeconds( $opts->getMalQueueExpirationInterval() )->timestamp;
69
- /** @var ScanQueue\Delete $deleter */
70
- $deleter = $mod->getDbHandler_ScanQueue()->getQueryDeleter();
71
- return $deleter->addWhereOlderThan( $nExpiredBoundary )
72
- ->query();
73
- }
74
-
75
  /**
76
  * @return string[]
77
  */
@@ -85,11 +56,11 @@ class Controller {
85
  public function getScanJobProgress() {
86
  /** @var HackGuard\ModCon $mod */
87
  $mod = $this->getMod();
88
- /** @var ScanQueue\Select $sel */
89
- $sel = $mod->getDbHandler_ScanQueue()->getQuerySelector();
90
 
91
- $countsAll = $sel->countAllForEachScan();
92
- $countsUnfinished = $sel->countUnfinishedForEachScan();
93
 
94
  if ( empty( $countsAll ) || empty( $countsUnfinished ) ) {
95
  $progress = 1;
@@ -111,46 +82,26 @@ class Controller {
111
  return count( $this->getRunningScans() ) > 0 || count( $opts->getScansToBuild() ) > 0;
112
  }
113
 
114
- /**
115
- * @param string|string[] $aScanSlugs
116
- */
117
- public function startScans( $aScanSlugs ) {
118
- if ( !is_array( $aScanSlugs ) ) {
119
- $aScanSlugs = [ $aScanSlugs ];
120
- }
121
- if ( !empty( $aScanSlugs ) ) {
122
- /** @var HackGuard\Options $oOpts */
123
- $oOpts = $this->getOptions();
124
- foreach ( $aScanSlugs as $sSlug ) {
125
- $oOpts->addRemoveScanToBuild( $sSlug );
126
- }
127
- $this->getQueueBuilder()->dispatch();
128
- }
129
- }
130
-
131
- /**
132
- * @return Build\QueueBuilder
133
- */
134
- public function getQueueBuilder() {
135
  if ( empty( $this->oQueueBuilder ) ) {
136
  $this->oQueueBuilder = ( new Build\QueueBuilder( 'shield_scanqbuild' ) )
137
- ->setMod( $this->getMod() )
138
- ->setQueueProcessor( $this->getQueueProcessor() );
139
  }
140
  return $this->oQueueBuilder;
141
  }
142
 
143
- /**
144
- * @return QueueProcessor
145
- */
146
- public function getQueueProcessor() {
147
  if ( empty( $this->oQueueProcessor ) ) {
148
- /** @var HackGuard\Options $oOpts */
149
- $oOpts = $this->getOptions();
150
  $this->oQueueProcessor = ( new QueueProcessor( 'shield_scanq' ) )
151
  ->setMod( $this->getMod() )
152
- ->setExpirationInterval( $oOpts->getMalQueueExpirationInterval() );
153
  }
154
  return $this->oQueueProcessor;
155
  }
 
 
 
 
 
 
156
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\ScanItems as ScanItemsDB;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
 
8
 
 
 
 
 
9
  class Controller {
10
 
11
  use ModConsumer;
33
  * @return bool[]
34
  */
35
  public function getScansRunningStates() :array {
 
 
36
  /** @var HackGuard\Options $opts */
37
  $opts = $this->getOptions();
 
 
 
 
 
38
 
39
  $scans = array_fill_keys( $opts->getScanSlugs(), false );
40
+ foreach ( ( new HackGuard\Scan\Init\ScansStatus() )->setMod( $this->getMod() )->enqueued() as $enqueued ) {
41
+ $scans[ $enqueued ] = true;
42
  }
43
  return $scans;
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * @return string[]
48
  */
56
  public function getScanJobProgress() {
57
  /** @var HackGuard\ModCon $mod */
58
  $mod = $this->getMod();
59
+ /** @var ScanItemsDB\Ops\Select $selector */
60
+ $selector = $mod->getDbH_ScanItems()->getQuerySelector();
61
 
62
+ $countsAll = $selector->countAllForEachScan();
63
+ $countsUnfinished = $selector->countUnfinishedForEachScan();
64
 
65
  if ( empty( $countsAll ) || empty( $countsUnfinished ) ) {
66
  $progress = 1;
82
  return count( $this->getRunningScans() ) > 0 || count( $opts->getScansToBuild() ) > 0;
83
  }
84
 
85
+ public function getQueueBuilder() :Build\QueueBuilder {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  if ( empty( $this->oQueueBuilder ) ) {
87
  $this->oQueueBuilder = ( new Build\QueueBuilder( 'shield_scanqbuild' ) )
88
+ ->setMod( $this->getMod() );
 
89
  }
90
  return $this->oQueueBuilder;
91
  }
92
 
93
+ public function getQueueProcessor() :QueueProcessor {
 
 
 
94
  if ( empty( $this->oQueueProcessor ) ) {
 
 
95
  $this->oQueueProcessor = ( new QueueProcessor( 'shield_scanq' ) )
96
  ->setMod( $this->getMod() )
97
+ ->setExpirationInterval( MINUTE_IN_SECONDS*10 );
98
  }
99
  return $this->oQueueProcessor;
100
  }
101
+
102
+ /**
103
+ * @deprecated 13.0
104
+ */
105
+ public function startScans( $scanSlugs ) {
106
+ }
107
  }
src/lib/src/Modules/HackGuard/Scan/Queue/ConvertBetweenTypes.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\ScanActionFromSlug;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ConvertBetweenTypes
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
12
- */
13
- class ConvertBetweenTypes {
14
-
15
- use Databases\Base\HandlerConsumer;
16
-
17
- /**
18
- * @param Databases\ScanQueue\EntryVO $entry
19
- * @return Scans\Base\BaseScanActionVO|mixed
20
- */
21
- public function fromDbEntryToAction( $entry ) {
22
- $action = ScanActionFromSlug::GetAction( $entry->scan );
23
- $action->applyFromArray( $entry->meta );
24
- $action->items = $entry->items;
25
- $action->results = $entry->results;
26
- return $action;
27
- }
28
-
29
- /**
30
- * @param Scans\Base\BaseScanActionVO $oAction
31
- * @return Databases\ScanQueue\EntryVO
32
- */
33
- public function fromActionToDbEntry( $oAction ) {
34
- $entry = new Databases\ScanQueue\EntryVO();
35
- foreach ( $this->getDbHandler()->getTableSchema()->getColumnNames() as $field ) {
36
- if ( isset( $oAction->{$field} ) ) {
37
- $entry->{$field} = $oAction->{$field};
38
- }
39
- }
40
- unset( $oAction->items );
41
- unset( $oAction->results );
42
- $entry->meta = $oAction->getRawData();
43
- return $entry;
44
- }
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Queue/IsScanEnqueued.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
-
7
- /**
8
- * Class IsScanInQueue
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
10
- */
11
- class IsScanEnqueued {
12
-
13
- use Databases\Base\HandlerConsumer;
14
-
15
- public function check( string $scan ) :bool {
16
- /** @var Databases\ScanQueue\Select $selector */
17
- $selector = $this->getDbHandler()->getQuerySelector();
18
- return $selector->countForScan( $scan ) > 0;
19
- }
20
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Queue/ProcessQueueItem.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init\SetScanCompleted;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\Store;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\ScanActionFromSlug;
10
+ use FernleafSystems\Wordpress\Services\Services;
11
+
12
+ class ProcessQueueItem {
13
+
14
+ use Shield\Modules\ModConsumer;
15
+
16
+ public function run( QueueItemVO $item ) {
17
+ /** @var ModCon $mod */
18
+ $mod = $this->getMod();
19
+
20
+ $mod->getDbH_ScanItems()
21
+ ->getQueryUpdater()
22
+ ->updateById( $item->qitem_id, [
23
+ 'started_at' => Services::Request()->ts()
24
+ ] );
25
+
26
+ try {
27
+ $results = $this->runScanOnItem( $item );
28
+
29
+ ( new Store() )
30
+ ->setMod( $this->getMod() )
31
+ ->store( $item, $results );
32
+
33
+ $mod->getDbH_ScanItems()
34
+ ->getQueryUpdater()
35
+ ->updateById( $item->qitem_id, [
36
+ 'finished_at' => Services::Request()->ts()
37
+ ] );
38
+
39
+ ( new SetScanCompleted() )
40
+ ->setMod( $this->getMod() )
41
+ ->run();
42
+ }
43
+ catch ( \Exception $e ) {
44
+ error_log( $e->getMessage() );
45
+ }
46
+ }
47
+
48
+ /**
49
+ * @throws \Exception
50
+ */
51
+ private function runScanOnItem( QueueItemVO $item ) :array {
52
+ $action = ScanActionFromSlug::GetAction( $item->scan )
53
+ ->applyFromArray( $item->meta );
54
+ $action->items = $item->items;
55
+
56
+ $this->getScanner( $action )
57
+ ->setScanActionVO( $action )
58
+ ->setMod( $this->getMod() )
59
+ ->run();
60
+
61
+ if ( $action->usleep > 0 ) {
62
+ usleep( $action->usleep );
63
+ }
64
+
65
+ return is_array( $action->results ) ? $action->results : [];
66
+ }
67
+
68
+ /**
69
+ * @param Shield\Scans\Base\BaseScanActionVO $action
70
+ * @return Shield\Scans\Base\BaseScan
71
+ */
72
+ private function getScanner( $action ) {
73
+ /** @var Shield\Modules\HackGuard\ModCon $mod */
74
+ $mod = $this->getMod();
75
+ $class = $action->getScanNamespace().'Scan';
76
+ /** @var Shield\Scans\Base\BaseScan $o */
77
+ $o = new $class();
78
+ return $o->setScanController( $mod->getScanCon( $action->scan ) )
79
+ ->setMod( $mod )
80
+ ->setScanActionVO( $action );
81
+ }
82
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/ProcessQueueWpcli.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
7
+ DB\ScanItems\Ops as ScanItemsDB,
8
+ ModCon,
9
+ Options,
10
+ Scan\Exceptions\NoQueueItems
11
+ };
12
+ use FernleafSystems\Wordpress\Services\Services;
13
+ use WP_CLI;
14
+
15
+ class ProcessQueueWpcli extends Shield\Modules\Base\Common\ExecOnceModConsumer {
16
+
17
+ protected function canRun() :bool {
18
+ return Services::WpGeneral()->isWpCli();
19
+ }
20
+
21
+ protected function run() {
22
+ /** @var ModCon $mod */
23
+ $mod = $this->getMod();
24
+ /** @var Options $opts */
25
+ $opts = $this->getOptions();
26
+ /** @var ScanItemsDB\Select $selector */
27
+ $selector = $mod->getDbH_ScanItems()->getQuerySelector();
28
+
29
+ foreach ( array_keys( $opts->getScansToBuild() ) as $scan ) {
30
+ $opts->addRemoveScanToBuild( $scan, false );
31
+ $mod->saveModOptions();
32
+ try {
33
+ WP_CLI::log( sprintf( 'Building scan items for scan: %s',
34
+ $mod->getScanCon( $scan )->getScanName() ) );
35
+ ( new QueueInit() )
36
+ ->setMod( $mod )
37
+ ->init( $scan );
38
+ }
39
+ catch ( \Exception $e ) {
40
+ }
41
+ }
42
+
43
+ WP_CLI::log( 'Starting Scans...' );
44
+
45
+ $progress = WP_CLI\Utils\make_progress_bar( 'Scans Progress',
46
+ array_sum( $selector->countAllForEachScan() ) );
47
+
48
+ do {
49
+ try {
50
+ $qItem = ( new QueueItems() )
51
+ ->setMod( $mod )
52
+ ->next();
53
+ ( new ProcessQueueItem() )
54
+ ->setMod( $mod )
55
+ ->run( $qItem );
56
+ }
57
+ catch ( NoQueueItems $e ) {
58
+ $qItem = null;
59
+ }
60
+ $progress->tick();
61
+ } while ( !empty( $qItem ) );
62
+
63
+ ( new CompleteQueue() )
64
+ ->setMod( $mod )
65
+ ->complete();
66
+
67
+ $progress->finish();
68
+ WP_CLI::log( 'Scans Complete.' );
69
+ }
70
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/QueueInit.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init\CreateNewScan;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Init\PopulateScanItems;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
10
+
11
+ class QueueInit {
12
+
13
+ use ModConsumer;
14
+
15
+ /**
16
+ * Build and Enqueue.
17
+ * @param string $slug
18
+ * @throws \Exception
19
+ */
20
+ public function init( string $slug ) {
21
+ $this->preInit();
22
+ $this->createScans( $slug );
23
+ }
24
+
25
+ private function preInit() {
26
+ ( new CleanQueue() )
27
+ ->setMod( $this->getMod() )
28
+ ->execute();
29
+ }
30
+
31
+ /**
32
+ * @throws \Exception
33
+ */
34
+ private function createScans( string $slug ) {
35
+ /** @var ModCon $mod */
36
+ $mod = $this->getMod();
37
+
38
+ $scanRecord = ( new CreateNewScan() )
39
+ ->setMod( $mod )
40
+ ->run( $slug );
41
+
42
+ ( new PopulateScanItems() )
43
+ ->setRecord( $scanRecord )
44
+ ->setScanController( $mod->getScanCon( $slug ) )
45
+ ->run();
46
+ }
47
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/QueueItemVO.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
+
5
+ use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
+
7
+ /**
8
+ * @property int $scan_id
9
+ * @property int $qitem_id
10
+ * @property string $scan
11
+ * @property array $meta
12
+ * @property array $items
13
+ */
14
+ class QueueItemVO extends DynPropertiesClass {
15
+
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ public function __get( string $key ) {
20
+ $value = parent::__get( $key );
21
+ switch ( $key ) {
22
+ case 'scan_id':
23
+ case 'qitem_id':
24
+ $value = (int)$value;
25
+ break;
26
+ default:
27
+ break;
28
+ }
29
+ return $value;
30
+ }
31
+
32
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/QueueItems.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Exceptions\NoQueueItems;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue\QueueItemVO;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
+ use FernleafSystems\Wordpress\Services\Services;
10
+
11
+ class QueueItems {
12
+
13
+ use ModConsumer;
14
+
15
+ /**
16
+ * @throws NoQueueItems
17
+ */
18
+ public function next() :QueueItemVO {
19
+ /** @var ModCon $mod */
20
+ $mod = $this->getMod();
21
+ $result = Services::WpDb()->selectRow(
22
+ sprintf( "SELECT scans.id as scan_id, scans.scan, scans.meta,
23
+ si.id as qitem_id, si.items
24
+ FROM `%s` as scans
25
+ INNER JOIN `%s` as `si`
26
+ ON `si`.scan_ref = `scans`.id
27
+ AND `si`.`started_at`=0
28
+ WHERE `scans`.`ready_at` > 0 AND `scans`.`finished_at`=0
29
+ ORDER BY `si`.`id` ASC
30
+ LIMIT 1;",
31
+ $mod->getDbH_Scans()->getTableSchema()->table,
32
+ $mod->getDbH_ScanItems()->getTableSchema()->table
33
+ )
34
+ );
35
+ if ( empty( $result ) ) {
36
+ throw new NoQueueItems( 'No items remaining in queue to select.' );
37
+ }
38
+ foreach ( [ 'items', 'meta' ] as $key ) {
39
+ $result[ $key ] = json_decode( base64_decode( $result[ $key ] ), true );
40
+ }
41
+ return ( new QueueItemVO() )->applyFromArray( $result );
42
+ }
43
+
44
+ public function hasNextItem() :bool {
45
+ try {
46
+ $this->next();
47
+ $has = true;
48
+ }
49
+ catch ( NoQueueItems $e ) {
50
+ $has = false;
51
+ }
52
+ return $has;
53
+ }
54
+ }
src/lib/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php CHANGED
@@ -3,9 +3,7 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\ScanQueue;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
8
- use FernleafSystems\Wordpress\Services\Services;
9
  use FernleafSystems\Wordpress\Services\Utilities;
10
 
11
  class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
@@ -18,18 +16,22 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
18
  * @return \stdClass Return the first batch from the queue
19
  */
20
  protected function get_batch() {
21
- /** @var ScanQueue\Select $oSel */
22
- $oSel = $this->getDbHandler()->getQuerySelector();
23
-
24
- $oEntry = $oSel->filterByNotStarted()
25
- ->filterByNotFinished()
26
- ->setOrderBy( 'id', 'ASC', true )
27
- ->first();
28
-
29
- $oBatch = new \stdClass();
30
- $oBatch->key = $oEntry->id;
31
- $oBatch->data = [ $oEntry ];
32
- return $oBatch;
 
 
 
 
33
  }
34
 
35
  /**
@@ -40,26 +42,14 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
40
  * in the next pass through. Or, return false to remove the
41
  * item from the queue.
42
  *
43
- * @param ScanQueue\EntryVO $entry Queue item to iterate over.
44
- * @return mixed
45
  */
46
- protected function task( $entry ) {
47
- $entry->started_at = Services::Request()->ts();
48
- /** @var ScanQueue\Update $updater */
49
- $updater = $this->getDbHandler()->getQueryUpdater();
50
- $updater->setStarted( $entry );
51
-
52
- try {
53
- ( new ScanExecute() )
54
- ->setMod( $this->getMod() )
55
- ->execute( $entry );
56
- }
57
- catch ( \Exception $e ) {
58
- // error_log( $e->getMessage() );
59
- }
60
-
61
- $updater->setFinished( $entry );
62
- return $entry;
63
  }
64
 
65
  /**
@@ -72,7 +62,6 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
72
  parent::complete();
73
 
74
  ( new CompleteQueue() )
75
- ->setDbHandler( $this->getDbHandler() )
76
  ->setMod( $this->getMod() )
77
  ->complete();
78
  }
@@ -84,9 +73,11 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
84
  * @return $this
85
  */
86
  public function delete( $key ) {
87
- /** @var ScanQueue\Delete $oDel */
88
- $oDel = $this->getDbHandler()->getQueryDeleter();
89
- $oDel->deleteById( $key );
 
 
90
  return $this;
91
  }
92
 
@@ -96,11 +87,9 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
96
  * @return bool
97
  */
98
  protected function is_queue_empty() {
99
- /** @var ScanQueue\Select $selector */
100
- $selector = $this->getDbHandler()->getQuerySelector();
101
- return $selector->filterByNotStarted()
102
- ->filterByNotFinished()
103
- ->count() === 0;
104
  }
105
 
106
  /**
@@ -109,50 +98,24 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
109
  * @return $this
110
  */
111
  public function save() {
112
-
113
- if ( is_array( $this->data ) ) {
114
- /** @var ScanQueue\Insert $inserter */
115
- $inserter = $this->getDbHandler()->getQueryInserter();
116
- foreach ( $this->data as $entry ) {
117
- /** @var ScanQueue\EntryVO $entry */
118
- if ( $entry instanceof ScanQueue\EntryVO ) {
119
- $inserter->insert( $entry );
120
- }
121
- }
122
- }
123
-
124
- $this->data = []; // critical to preventing duplicate entries
125
  return $this;
126
  }
127
 
128
  /**
129
  * Update queue
130
  *
131
- * @param string $key Key.
132
- * @param ScanQueue\EntryVO[] $data Data.
133
  * @return $this
134
  */
135
  public function update( $key, $data ) {
136
- /** @var ScanQueue\Update $updater */
137
- $updater = $this->getDbHandler()->getQueryUpdater();
138
- $entry = array_shift( $data );
139
- $updater->updateById( $entry->id, $entry->getRawData() );
140
  return $this;
141
  }
142
 
143
  public function handleExpiredItems() {
144
- $boundary = Services::Request()
145
- ->carbon()
146
- ->subSeconds( $this->getExpirationInterval() )->timestamp;
147
- $this->getDbHandler()->deleteRowsOlderThan( $boundary );
148
- }
149
-
150
- /**
151
- * @return ScanQueue\Handler
152
- */
153
- public function getDbHandler() {
154
- /** @var ModCon $mod */
155
- $mod = $this->getMod();
156
- return $mod->getDbHandler_ScanQueue();
157
  }
158
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
 
7
  use FernleafSystems\Wordpress\Services\Utilities;
8
 
9
  class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
16
  * @return \stdClass Return the first batch from the queue
17
  */
18
  protected function get_batch() {
19
+ $batch = new \stdClass();
20
+
21
+ try {
22
+ $qItem = ( new QueueItems() )
23
+ ->setMod( $this->getMod() )
24
+ ->next();
25
+
26
+ $batch->key = $qItem->qitem_id;
27
+ $batch->data = [ $qItem ];
28
+ }
29
+ catch ( Shield\Modules\HackGuard\Scan\Exceptions\NoQueueItems $e ) {
30
+ // This should never happen as "is_empty()" is called before
31
+ error_log( $e->getMessage() );
32
+ }
33
+
34
+ return $batch;
35
  }
36
 
37
  /**
42
  * in the next pass through. Or, return false to remove the
43
  * item from the queue.
44
  *
45
+ * @param QueueItemVO $item Queue item to iterate over.
46
+ * @return QueueItemVO
47
  */
48
+ protected function task( $item ) {
49
+ ( new ProcessQueueItem() )
50
+ ->setMod( $this->getMod() )
51
+ ->run( $item );
52
+ return $item;
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
 
55
  /**
62
  parent::complete();
63
 
64
  ( new CompleteQueue() )
 
65
  ->setMod( $this->getMod() )
66
  ->complete();
67
  }
73
  * @return $this
74
  */
75
  public function delete( $key ) {
76
+ /** @var ModCon $mod */
77
+ $mod = $this->getMod();
78
+ $mod->getDbH_ScanItems()
79
+ ->getQueryDeleter()
80
+ ->deleteById( $key );
81
  return $this;
82
  }
83
 
87
  * @return bool
88
  */
89
  protected function is_queue_empty() {
90
+ return !( new QueueItems() )
91
+ ->setMod( $this->getMod() )
92
+ ->hasNextItem();
 
 
93
  }
94
 
95
  /**
98
  * @return $this
99
  */
100
  public function save() {
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  return $this;
102
  }
103
 
104
  /**
105
  * Update queue
106
  *
107
+ * @param string $key Key.
108
+ * @param ScanItemsDB\Ops\Record[] $data Data.
109
  * @return $this
110
  */
111
  public function update( $key, $data ) {
112
+ // Do nothing. Results are stored separately.
 
 
 
113
  return $this;
114
  }
115
 
116
  public function handleExpiredItems() {
117
+ ( new CleanQueue() )
118
+ ->setMod( $this->getMod() )
119
+ ->execute();
 
 
 
 
 
 
 
 
 
 
120
  }
121
  }
src/lib/src/Modules/HackGuard/Scan/Queue/QueueProcessorConsumer.php CHANGED
@@ -3,8 +3,7 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
5
  /**
6
- * Trait QueueProcessorConsumer
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
8
  */
9
  trait QueueProcessorConsumer {
10
 
@@ -21,11 +20,11 @@ trait QueueProcessorConsumer {
21
  }
22
 
23
  /**
24
- * @param QueueProcessor $oQP
25
  * @return $this
26
  */
27
- public function setQueueProcessor( QueueProcessor $oQP ) {
28
- $this->oQueueProcessor = $oQP;
29
  return $this;
30
  }
31
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
 
5
  /**
6
+ * @deprecated 12.1
 
7
  */
8
  trait QueueProcessorConsumer {
9
 
20
  }
21
 
22
  /**
23
+ * @param QueueProcessor $QP
24
  * @return $this
25
  */
26
+ public function setQueueProcessor( QueueProcessor $QP ) {
27
+ $this->oQueueProcessor = $QP;
28
  return $this;
29
  }
30
  }
src/lib/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base\HandlerConsumer;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
-
8
- /**
9
- * Class ScanEnqueue
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
11
- */
12
- class ScanEnqueue {
13
-
14
- use HandlerConsumer;
15
- use QueueProcessorConsumer;
16
- use Scans\Common\ScanActionConsumer;
17
-
18
- /**
19
- * @throws \Exception
20
- */
21
- public function enqueue() {
22
- $action = $this->getScanActionVO();
23
- $aAllItems = (array)$action->items;
24
- unset( $action->items );
25
-
26
- $nSliceSize = $action::QUEUE_GROUP_SIZE_LIMIT;
27
-
28
- do {
29
- $oCurrent = clone $action;
30
- $oCurrent->items = array_slice( $aAllItems, 0, $nSliceSize );
31
- $this->pushActionToQueue( $oCurrent );
32
- $aAllItems = array_slice( $aAllItems, $nSliceSize );
33
- } while ( !empty( $aAllItems ) );
34
-
35
- $this->getQueueProcessor()->save();
36
- }
37
-
38
- /**
39
- * @param Scans\Base\BaseScanActionVO $action
40
- */
41
- protected function pushActionToQueue( $action ) {
42
- $entry = ( new ConvertBetweenTypes() )
43
- ->setDbHandler( $this->getDbHandler() )
44
- ->fromActionToDbEntry( $action );
45
- $this->getQueueProcessor()->push_to_queue( $entry );
46
- }
47
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Queue/ScanExecute.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\ScanQueue;
7
-
8
- /**
9
- * Class ScanExecute
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
11
- */
12
- class ScanExecute {
13
-
14
- use Shield\Modules\ModConsumer;
15
-
16
- /**
17
- * @param ScanQueue\EntryVO $entry
18
- * @return ScanQueue\EntryVO
19
- * @throws \Exception
20
- */
21
- public function execute( $entry ) {
22
- /** @var Shield\Modules\HackGuard\ModCon $mod */
23
- $mod = $this->getMod();
24
-
25
- $action = ( new ConvertBetweenTypes() )
26
- ->setDbHandler( $mod->getDbHandler_ScanQueue() )
27
- ->fromDbEntryToAction( $entry );
28
-
29
- $this->getScanner( $action )
30
- ->setScanActionVO( $action )
31
- ->setMod( $mod )
32
- ->run();
33
-
34
- if ( $action->usleep > 0 ) {
35
- usleep( $action->usleep );
36
- }
37
-
38
- $entry->results = $action->results;
39
- return $entry;
40
- }
41
-
42
- /**
43
- * @param Shield\Scans\Base\BaseScanActionVO $oAction
44
- * @return Shield\Scans\Base\BaseScan
45
- */
46
- private function getScanner( $oAction ) {
47
- $sClass = $oAction->getScanNamespace().'Scan';
48
- /** @var Shield\Scans\Base\BaseScan $o */
49
- $o = new $sClass();
50
- return $o->setMod( $this->getMod() )
51
- ->setScanActionVO( $oAction );
52
- }
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php DELETED
@@ -1,42 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ScanInitiate
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Queue
12
- */
13
- class ScanInitiate {
14
-
15
- use ModConsumer;
16
- use QueueProcessorConsumer;
17
-
18
- /**
19
- * Build and Enqueue.
20
- * @param string $slug
21
- * @throws \Exception
22
- */
23
- public function init( string $slug ) {
24
- /** @var ModCon $mod */
25
- $mod = $this->getMod();
26
- $dbh = $mod->getDbHandler_ScanQueue();
27
-
28
- if ( ( new IsScanEnqueued() )->setDbHandler( $dbh )->check( $slug ) ) {
29
- throw new \Exception( 'Scan is already running' );
30
- }
31
-
32
- $oAction = ( new BuildScanAction() )
33
- ->setMod( $mod )
34
- ->build( $slug );
35
-
36
- ( new ScanEnqueue() )
37
- ->setDbHandler( $dbh )
38
- ->setQueueProcessor( $this->getQueueProcessor() )
39
- ->setScanActionVO( $oAction )
40
- ->enqueue();
41
- }
42
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ConvertBetweenTypes
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results
12
- */
13
- class ConvertBetweenTypes {
14
-
15
- use ScanControllerConsumer;
16
-
17
- /**
18
- * @param Scans\Base\ResultsSet $resultsSet
19
- * @return Databases\Scanner\EntryVO[]|mixed
20
- */
21
- public function fromResultsToVOs( $resultsSet ) {
22
- $vos = [];
23
- foreach ( $resultsSet->getAllItems() as $item ) {
24
- /** @var Scans\Base\ResultItem $item */
25
- $vos[ $item->generateHash() ] = $this->convertResultItemToVO( $item );
26
- }
27
- return $vos;
28
- }
29
-
30
- /**
31
- * @param Databases\Scanner\EntryVO[] $VOs
32
- * @return Scans\Base\ResultsSet|mixed
33
- */
34
- public function fromVOsToResultsSet( $VOs ) {
35
- $results = $this->getScanController()->getNewResultsSet();
36
- foreach ( $VOs as $VO ) {
37
- $results->addItem( $this->convertVoToResultItem( $VO ) );
38
- }
39
- return $results;
40
- }
41
-
42
- /**
43
- * @param Databases\Scanner\EntryVO $VO
44
- * @return Scans\Base\ResultItem
45
- */
46
- public function convertVoToResultItem( Databases\Scanner\EntryVO $VO ) {
47
- $item = $this->getScanController()
48
- ->getNewResultItem()
49
- ->applyFromArray( $VO->meta );
50
- $item->VO = $VO;
51
- return $item;
52
- }
53
-
54
- /**
55
- * @param Scans\Base\ResultItem $item
56
- * @return Databases\Scanner\EntryVO
57
- */
58
- private function convertResultItemToVO( $item ) {
59
- $vo = new Databases\Scanner\EntryVO();
60
- $vo->hash = $item->hash;
61
- $vo->meta = $item->getData();
62
- $vo->scan = $this->getScanController()->getSlug();
63
- return $vo;
64
- }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/Counts.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\{
7
+ Afs,
8
+ Apc,
9
+ Wpv
10
+ };
11
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
12
+
13
+ class Counts {
14
+
15
+ use ModConsumer;
16
+
17
+ private $counts;
18
+
19
+ public function countMalware() :int {
20
+ return $this->getCount( 'malware_files' );
21
+ }
22
+
23
+ public function countAbandoned() :int {
24
+ return $this->getCount( 'abandoned' );
25
+ }
26
+
27
+ public function countPluginFiles() :int {
28
+ return $this->getCount( 'plugin_files' );
29
+ }
30
+
31
+ public function countThemeFiles() :int {
32
+ return $this->getCount( 'theme_files' );
33
+ }
34
+
35
+ public function countVulnerableAssets() :int {
36
+ return $this->getCount( 'assets_vulnerable' );
37
+ }
38
+
39
+ public function countWPFiles() :int {
40
+ return $this->getCount( 'wp_files' );
41
+ }
42
+
43
+ private function getCount( $resultType ) :int {
44
+ $counts = $this->getCounts();
45
+
46
+ if ( !isset( $counts[ $resultType ] ) ) {
47
+ /** @var ModCon $mod */
48
+ $mod = $this->getMod();
49
+ $resultsRetrieve = ( new Retrieve() )
50
+ ->setMod( $this->getMod() )
51
+ ->setScanController( $mod->getScanCon( Afs::SCAN_SLUG ) );
52
+
53
+ switch ( $resultType ) {
54
+
55
+ case 'malware_files':
56
+ $count = $resultsRetrieve->setAdditionalWheres( [ "`rim`.`meta_key`='is_mal'", ] )->count();
57
+ break;
58
+ case 'wp_files':
59
+ $count = $resultsRetrieve->setAdditionalWheres( [ "`rim`.`meta_key`='is_in_core'", ] )->count();
60
+ break;
61
+ case 'plugin_files':
62
+ $count = $resultsRetrieve->setAdditionalWheres( [ "`rim`.`meta_key`='is_in_plugin'", ] )->count();
63
+ break;
64
+ case 'theme_files':
65
+ $count = $resultsRetrieve->setAdditionalWheres( [ "`rim`.`meta_key`='is_in_theme'", ] )->count();
66
+ break;
67
+
68
+ case 'abandoned':
69
+ $count = $resultsRetrieve
70
+ ->setScanController( $mod->getScanCon( Apc::SCAN_SLUG ) )
71
+ ->setAdditionalWheres( [ "`rim`.`meta_key`='is_abandoned'", ] )
72
+ ->count();
73
+ break;
74
+ case 'assets_vulnerable':
75
+ $count = $resultsRetrieve
76
+ ->setScanController( $mod->getScanCon( Wpv::SCAN_SLUG ) )
77
+ ->setAdditionalWheres( [ "`rim`.`meta_key`='is_vulnerable'", ] )
78
+ ->count();
79
+ break;
80
+
81
+ default:
82
+ die( 'unsupported result type' );
83
+ }
84
+ $counts[ $resultType ] = $count;
85
+ $this->counts = $counts;
86
+ }
87
+
88
+ return $this->getCounts()[ $resultType ];
89
+ }
90
+
91
+ public function getCounts() :array {
92
+ if ( !is_array( $this->counts ) ) {
93
+ $this->counts = [];
94
+ }
95
+ return $this->counts;
96
+ }
97
+ }
src/lib/src/Modules/HackGuard/Scan/Results/ResultsDelete.php DELETED
@@ -1,79 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ResultsDelete
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results
12
- */
13
- class ResultsDelete {
14
-
15
- use ScanControllerConsumer;
16
-
17
- /**
18
- * @param Scans\Base\ResultsSet $resultsToDelete
19
- * @param bool $softDelete
20
- * @return bool
21
- * @throws \Exception
22
- */
23
- public function delete( $resultsToDelete, bool $softDelete = true ) {
24
- if ( !$resultsToDelete->hasItems() ) {
25
- throw new \Exception( 'No items' );
26
- }
27
-
28
- $hashes = array_filter( array_map(
29
- function ( $item ) {
30
- return (string)$item->hash;
31
- },
32
- $resultsToDelete->getAllItems()
33
- ) );
34
-
35
- $success = true;
36
- if ( !empty( $hashes ) ) {
37
- if ( $softDelete ) {
38
- $success = $this->softDelete( $hashes );
39
- }
40
- else {
41
- /** @var Databases\Scanner\Delete $deleter */
42
- $deleter = $this->getScanController()
43
- ->getScanResultsDbHandler()
44
- ->getQueryDeleter();
45
- $success = $deleter->filterByHashes( $hashes )->query();
46
- }
47
- }
48
- return $success;
49
- }
50
-
51
- protected function softDelete( array $hashes ) :bool {
52
- /** @var Databases\Scanner\Update $updater */
53
- $updater = $this->getScanController()
54
- ->getScanResultsDbHandler()
55
- ->getQueryUpdater();
56
- // This is an inefficient hack for multiple soft-deletes until we rewrite a custom SQL updater
57
- foreach ( $hashes as $hash ) {
58
- $updater->setSoftDeleted()
59
- ->setUpdateWheres( [
60
- 'hash' => $hash
61
- ] )
62
- ->query();
63
- }
64
-
65
- return true;
66
- }
67
-
68
- /**
69
- * @return $this
70
- */
71
- public function deleteAllForScan() {
72
- /** @var Databases\Scanner\Delete $deleter */
73
- $deleter = $this->getScanController()
74
- ->getScanResultsDbHandler()
75
- ->getQueryDeleter();
76
- $deleter->forScan( $this->getScanController()->getSlug() );
77
- return $this;
78
- }
79
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php DELETED
@@ -1,28 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ResultsRetrieve
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results
12
- */
13
- class ResultsRetrieve {
14
-
15
- use ScanControllerConsumer;
16
-
17
- /**
18
- * @return Scans\Base\ResultsSet|mixed
19
- */
20
- public function retrieve() {
21
- $oSCon = $this->getScanController();
22
- /** @var Databases\Scanner\Select $oSelector */
23
- $oSelector = $oSCon->getScanResultsDbHandler()->getQuerySelector();
24
- return ( new ConvertBetweenTypes() )
25
- ->setScanController( $oSCon )
26
- ->fromVOsToResultsSet( $oSelector->forScan( $oSCon->getSlug() ) );
27
- }
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/ResultsStore.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ResultsStore
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results
12
- */
13
- class ResultsStore {
14
-
15
- use ScanControllerConsumer;
16
-
17
- /**
18
- * @param Scans\Base\ResultsSet $resultsToStore
19
- * @throws \Exception
20
- */
21
- public function store( $resultsToStore ) {
22
- if ( !$resultsToStore->hasItems() ) {
23
- throw new \Exception( 'No items' );
24
- }
25
-
26
- $scanCon = $this->getScanController();
27
- $dbh = $scanCon->getScanResultsDbHandler();
28
-
29
- $VOs = ( new ConvertBetweenTypes() )
30
- ->setScanController( $scanCon )
31
- ->fromResultsToVOs( $resultsToStore );
32
-
33
- // Try to find all older, but deleted results.
34
- /** @var Databases\Scanner\Select $selector */
35
- $selector = $dbh->getQuerySelector();
36
- /** @var Databases\Scanner\EntryVO[] $existing */
37
- $existing = $selector->filterByScan( $scanCon->getSlug() )
38
- ->filterByHashes( array_keys( $VOs ) )
39
- ->setIncludeSoftDeleted( true )
40
- ->query();
41
-
42
- if ( !empty( $existing ) ) {
43
- foreach ( $existing as $existingRecord ) {
44
- foreach ( $VOs as $vo ) {
45
- if ( $existingRecord->hash === $vo->hash ) {
46
-
47
- $updateData = $vo->getRawData();
48
- $updateData[ 'deleted_at' ] = 0;
49
-
50
- $dbh->getQueryUpdater()
51
- ->setUpdateWheres( [
52
- 'scan' => $scanCon->getSlug(),
53
- 'hash' => $existingRecord->hash,
54
- ] )
55
- ->setUpdateData( $updateData )
56
- ->query();
57
- unset( $VOs[ $vo->hash ] );
58
- break;
59
- }
60
- }
61
- }
62
- }
63
-
64
- foreach ( $VOs as $vo ) {
65
- $dbh->getQueryInserter()->insert( $vo );
66
- }
67
- }
68
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/ResultsUpdate.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
8
-
9
- /**
10
- * Class ResultsUpdate
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results
12
- */
13
- class ResultsUpdate {
14
-
15
- use ScanControllerConsumer;
16
-
17
- /**
18
- * @param Scans\Base\ResultsSet $newResults
19
- */
20
- public function update( $newResults ) {
21
- $scanCon = $this->getScanController();
22
- $newCopy = clone $newResults; // so we don't modify these for later use.
23
-
24
- $existing = ( new ResultsRetrieve() )
25
- ->setScanController( $scanCon )
26
- ->retrieve();
27
-
28
- $itemsToDelete = ( new Scans\Base\DiffResultForStorage() )->diff( $existing, $newCopy );
29
-
30
- try {
31
- ( new ResultsDelete() )
32
- ->setScanController( $scanCon )
33
- ->delete( $itemsToDelete );
34
- }
35
- catch ( \Exception $e ) {
36
- }
37
-
38
- try {
39
- ( new ResultsStore() )
40
- ->setScanController( $scanCon )
41
- ->store( $newCopy );
42
- }
43
- catch ( \Exception $e ) {
44
- }
45
-
46
- if ( $existing->hasItems() ) {
47
- $updater = $scanCon->getScanResultsDbHandler()->getQueryUpdater();
48
- /** @var Databases\Scanner\EntryVO $vo */
49
- $converter = ( new ConvertBetweenTypes() )->setScanController( $scanCon );
50
- foreach ( $converter->fromResultsToVOs( $existing ) as $vo ) {
51
- $updater->reset()
52
- ->setUpdateWheres( [
53
- 'scan' => $scanCon->getSlug(),
54
- 'hash' => $vo->hash,
55
- ] )
56
- ->setUpdateData( $vo->getRawData() )
57
- ->query();
58
- }
59
- }
60
- }
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/HackGuard/Scan/Results/Retrieve.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\{
7
+ ResultItemMeta as ResultItemMetaDB,
8
+ Scans as ScansDB
9
+ };
10
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
11
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
12
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
13
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
14
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultsSet;
15
+ use FernleafSystems\Wordpress\Services\Services;
16
+
17
+ class Retrieve {
18
+
19
+ use ModConsumer;
20
+ use ScanControllerConsumer;
21
+
22
+ private $additionalWheres = [];
23
+
24
+ /**
25
+ * @param int $scanResultID
26
+ * @return Scans\Base\ResultItem
27
+ * @throws \Exception
28
+ */
29
+ public function byID( int $scanResultID ) {
30
+ /** @var ModCon $mod */
31
+ $mod = $this->getMod();
32
+ $WPDB = Services::WpDb();
33
+
34
+ // Need to determine the scan from the scan result.
35
+ $scan = $WPDB->getVar( sprintf( "SELECT scans.scan
36
+ FROM `%s` as scans
37
+ INNER JOIN `%s` as `sr`
38
+ ON `sr`.scan_ref = `scans`.id AND `sr`.id = %s
39
+ LIMIT 1;",
40
+ $mod->getDbH_Scans()->getTableSchema()->table,
41
+ $mod->getDbH_ScanResults()->getTableSchema()->table,
42
+ $scanResultID
43
+ ) );
44
+ if ( empty( $scan ) ) {
45
+ throw new \Exception( sprintf( 'Could not determine scan type from the scan result ID %s.', $scanResultID ) );
46
+ }
47
+ $this->setScanController( $mod->getScanCon( $scan ) );
48
+
49
+ $raw = Services::WpDb()->selectCustom(
50
+ sprintf( $this->getBaseQuery(),
51
+ implode( ',', $this->standardSelectFields() ),
52
+ implode( ' AND ', array_filter( array_merge(
53
+ [
54
+ sprintf( "`sr`.`id`=%s", $scanResultID )
55
+ ],
56
+ $this->getAdditionalWheres()
57
+ ) ) )
58
+ )
59
+ );
60
+ $rawResults = empty( $raw ) ? [] : $raw;
61
+
62
+ $resultSet = $this->convertToResultsSet( $rawResults );
63
+ if ( $resultSet->countItems() !== 1 ) {
64
+ throw new \Exception( sprintf( 'Scan result with ID %s does not exist.', $scanResultID ) );
65
+ }
66
+ $items = $resultSet->getAllItems();
67
+ return array_shift( $items );
68
+ }
69
+
70
+ /**
71
+ * @return Scans\Base\ResultsSet
72
+ */
73
+ public function byIDs( array $IDs ) {
74
+ $results = [];
75
+ if ( !$this->getScanController()->isRestricted() ) {
76
+ $latestID = $this->getLatestScanID();
77
+ if ( $latestID >= 0 ) {
78
+ $raw = Services::WpDb()->selectCustom(
79
+ sprintf( $this->getBaseQuery(),
80
+ implode( ',', $this->standardSelectFields() ),
81
+ implode( ' AND ', array_filter( array_merge(
82
+ [
83
+ sprintf( "`sr`.`id` IN (%s)", implode( ',', $IDs ) )
84
+ ],
85
+ $this->getAdditionalWheres()
86
+ ) ) )
87
+ )
88
+ );
89
+ if ( !empty( $raw ) ) {
90
+ $results = $raw;
91
+ }
92
+ }
93
+ }
94
+
95
+ return $this->convertToResultsSet( $results );
96
+ }
97
+
98
+ /**
99
+ * @return Scans\Base\ResultsSet
100
+ */
101
+ public function retrieveForAutoRepair() {
102
+
103
+ $latestID = $this->getLatestScanID();
104
+ if ( $latestID >= 0 ) {
105
+ $results = $this
106
+ ->setAdditionalWheres( [
107
+ sprintf( "`sr`.`scan_ref`=%s", $latestID ),
108
+ "`ri`.`attempt_repair_at`=0",
109
+ "`ri`.`item_repaired_at`=0",
110
+ "`ri`.`item_deleted_at`=0",
111
+ "`ri`.ignored_at=0"
112
+ ] )
113
+ ->retrieve();
114
+ }
115
+ else {
116
+ $results = $this->getScanController()->getNewResultsSet();
117
+ }
118
+
119
+ return $results;
120
+ }
121
+
122
+ /**
123
+ * @return Scans\Afs\ResultsSet|Scans\Apc\ResultsSet|Scans\Wpv\ResultsSet
124
+ */
125
+ public function retrieveLatest( bool $includeIgnored = true ) {
126
+
127
+ $latestID = $this->getLatestScanID();
128
+ if ( $latestID >= 0 ) {
129
+ $results = $this
130
+ ->setAdditionalWheres( [
131
+ sprintf( "`sr`.`scan_ref`=%s", $latestID ),
132
+ $includeIgnored ? '' : "`ri`.ignored_at = 0",
133
+ "`ri`.`item_repaired_at`=0",
134
+ "`ri`.`item_deleted_at`=0"
135
+ ] )
136
+ ->retrieve();
137
+ }
138
+ else {
139
+ $results = $this->getScanController()->getNewResultsSet();
140
+ }
141
+
142
+ return $results;
143
+ }
144
+
145
+ /**
146
+ * @return Scans\Base\ResultsSet
147
+ */
148
+ public function retrieve() {
149
+ $results = [];
150
+ $raw = Services::WpDb()->selectCustom(
151
+ sprintf( $this->getBaseQuery(),
152
+ implode( ',', $this->standardSelectFields() ),
153
+ implode( ' AND ', array_filter( array_merge(
154
+ [
155
+ "`ri`.`auto_filtered_at`=0",
156
+ "`ri`.`deleted_at`=0"
157
+ ],
158
+ $this->getAdditionalWheres()
159
+ ) ) )
160
+ )
161
+ );
162
+ if ( !empty( $raw ) ) {
163
+ $results = $raw;
164
+ }
165
+
166
+ return $this->convertToResultsSet( $results );
167
+ }
168
+
169
+ public function count() :int {
170
+ $count = 0;
171
+ $latestID = $this->getLatestScanID();
172
+ if ( $latestID >= 0 ) {
173
+ $count = (int)Services::WpDb()->getVar(
174
+ sprintf( $this->getBaseCountQuery(),
175
+ implode( ' AND ', array_filter( array_merge(
176
+ [
177
+ sprintf( "`sr`.`scan_ref`=%s", $latestID ),
178
+ "`ri`.`auto_filtered_at`=0",
179
+ "`ri`.`ignored_at` = 0",
180
+ "`ri`.`item_repaired_at`=0",
181
+ "`ri`.`item_deleted_at`=0",
182
+ "`ri`.`deleted_at`=0"
183
+ ],
184
+ $this->getAdditionalWheres()
185
+ ) ) )
186
+ )
187
+ );
188
+ }
189
+ return $count;
190
+ }
191
+
192
+ /**
193
+ * @param array[] $results
194
+ * @return ResultsSet|mixed
195
+ */
196
+ protected function convertToResultsSet( array $results ) {
197
+ /** @var ModCon $mod */
198
+ $mod = $this->getMod();
199
+ $resultsSet = $this->getNewResultsSet();
200
+
201
+ $workingScan = empty( $this->getScanController() ) ? '' : $this->getScanController()->getSlug();
202
+
203
+ /** @var ScanResultVO[] $scanResults */
204
+ $scanResults = array_map( function ( $r ) {
205
+ return ( new ScanResultVO() )->applyFromArray( $r );
206
+ }, $results );
207
+
208
+ $this->addMetaToResults( $scanResults );
209
+
210
+ foreach ( $scanResults as $vo ) {
211
+
212
+ // we haven't specified a type of scan, so we're collecting all results.
213
+ if ( empty( $workingScan ) ) {
214
+ foreach ( $vo->meta as $scanSlug => $scanMeta ) {
215
+ $scanCon = $mod->getScanCon( $vo->scan );
216
+ $item = $scanCon->getNewResultItem()->applyFromArray( $vo->meta );
217
+ $item->VO = $vo;
218
+ $resultsSet->addItem( $item );
219
+ }
220
+ }
221
+ elseif ( !empty( $vo->scan ) ) {
222
+ $scanCon = $mod->getScanCon( $workingScan );
223
+ $item = $scanCon->getNewResultItem()->applyFromArray( $vo->meta );
224
+ $item->VO = $vo;
225
+ $resultsSet->addItem( $item );
226
+ }
227
+ }
228
+ return $resultsSet;
229
+ }
230
+
231
+ /**
232
+ * @param ScanResultVO[] $results
233
+ */
234
+ private function addMetaToResults( array $results ) {
235
+ /** @var ModCon $mod */
236
+ $mod = $this->getMod();
237
+
238
+ $resultItemIDs = array_map( function ( $res ) {
239
+ return $res->resultitem_id;
240
+ }, $results );
241
+
242
+ /** @var ResultItemMetaDB\Ops\Select $rimSelector */
243
+ $rimSelector = $mod->getDbH_ResultItemMeta()->getQuerySelector();
244
+ /** @var ResultItemMetaDB\Ops\Record[] $metas */
245
+ $metas = $rimSelector->filterByResultItems( $resultItemIDs )->queryWithResult();
246
+
247
+ foreach ( $results as $result ) {
248
+ $meta = $result->meta;
249
+ foreach ( $metas as $metaRecord ) {
250
+ if ( $metaRecord->ri_ref == $result->resultitem_id ) {
251
+ $meta[ $metaRecord->meta_key ] = $metaRecord->meta_value;
252
+ }
253
+ }
254
+ $result->meta = $meta;
255
+ }
256
+ }
257
+
258
+ private function getLatestScanID() :int {
259
+ /** @var ModCon $mod */
260
+ $mod = $this->getMod();
261
+ /** @var ScansDB\Ops\Select $scansSelector */
262
+ $scansSelector = $mod->getDbH_Scans()->getQuerySelector();
263
+ $latest = $scansSelector->getLatestForScan( $this->getScanController()->getSlug() );
264
+ return empty( $latest ) ? -1 : $latest->id;
265
+ }
266
+
267
+ private function getBaseQuery() :string {
268
+ /** @var ModCon $mod */
269
+ $mod = $this->getMod();
270
+ return sprintf( "SELECT %%s
271
+ FROM `%s` as sr
272
+ INNER JOIN `%s` as `scans`
273
+ ON `sr`.scan_ref = `scans`.id
274
+ INNER JOIN `%s` as `ri`
275
+ ON `sr`.resultitem_ref = `ri`.id
276
+ WHERE %%s
277
+ ORDER BY `sr`.`id` ASC;",
278
+ $mod->getDbH_ScanResults()->getTableSchema()->table,
279
+ $mod->getDbH_Scans()->getTableSchema()->table,
280
+ $mod->getDbH_ResultItems()->getTableSchema()->table
281
+ );
282
+ }
283
+
284
+ private function getBaseCountQuery() :string {
285
+ /** @var ModCon $mod */
286
+ $mod = $this->getMod();
287
+ return sprintf( "SELECT COUNT(*)
288
+ FROM `%s` as sr
289
+ INNER JOIN `%s` as `scans`
290
+ ON `sr`.scan_ref = `scans`.id
291
+ INNER JOIN `%s` as `ri`
292
+ ON `sr`.resultitem_ref = `ri`.id
293
+ INNER JOIN `%s` as `rim`
294
+ ON `rim`.`ri_ref` = `ri`.id
295
+ WHERE %%s;",
296
+ $mod->getDbH_ScanResults()->getTableSchema()->table,
297
+ $mod->getDbH_Scans()->getTableSchema()->table,
298
+ $mod->getDbH_ResultItems()->getTableSchema()->table,
299
+ $mod->getDbH_ResultItemMeta()->getTableSchema()->table
300
+ );
301
+ }
302
+
303
+ private function standardSelectFields() :array {
304
+ return [
305
+ 'scans.scan',
306
+ 'scans.id as scan_id',
307
+ 'sr.id as scanresult_id',
308
+ 'ri.id as resultitem_id',
309
+ 'ri.item_type',
310
+ 'ri.item_id',
311
+ 'ri.ignored_at',
312
+ 'ri.notified_at',
313
+ 'ri.attempt_repair_at',
314
+ 'ri.item_repaired_at',
315
+ 'ri.item_deleted_at',
316
+ 'ri.created_at',
317
+ ];
318
+ }
319
+
320
+ private function getNewResultsSet() {
321
+ $scanCon = $this->getScanController();
322
+ return empty( $scanCon ) ? new ResultsSet() : $scanCon->getNewResultsSet();
323
+ }
324
+
325
+ public function getAdditionalWheres() :array {
326
+ return is_array( $this->additionalWheres ) ? $this->additionalWheres : [];
327
+ }
328
+
329
+ public function setAdditionalWheres( array $wheres ) {
330
+ $this->additionalWheres = $wheres;
331
+ return $this;
332
+ }
333
+ }
src/lib/src/Modules/HackGuard/Scan/Results/ScanResultVO.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Record;
6
+
7
+ /**
8
+ * @property int $scan_id
9
+ * @property string $scan
10
+ * @property string $hash
11
+ * @property int $resultitem_id
12
+ * @property int $scanresult_id
13
+ * @property string $item_type
14
+ * @property string $item_id
15
+ * @property array $meta
16
+ * @property int $att
17
+ * @property int $ignored_at
18
+ * @property int $notified_at
19
+ * @property int $auto_filtered_at
20
+ * @property int $attempt_repair_at
21
+ * @property int $item_repaired_at
22
+ * @property int $item_deleted_at
23
+ * @property int $created_at
24
+ */
25
+ class ScanResultVO extends Record {
26
+
27
+ /**
28
+ * @param string $key
29
+ * @return mixed
30
+ */
31
+ public function __get( string $key ) {
32
+
33
+ $value = parent::__get( $key );
34
+
35
+ switch ( $key ) {
36
+
37
+ case 'scan_id':
38
+ case 'resultitem_id':
39
+ case 'scanresult_id':
40
+ $value = (int)$value;
41
+ break;
42
+
43
+ default:
44
+ break;
45
+ }
46
+
47
+ return $value;
48
+ }
49
+ }
src/lib/src/Modules/HackGuard/Scan/Results/Store.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
6
+ ModCon,
7
+ Scan\Queue\QueueItemVO
8
+ };
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\DB\{
10
+ ResultItems as ResultItemsDB,
11
+ ResultItemMeta as ResultItemMetaDB,
12
+ ScanResults as ScanResultsDB
13
+ };
14
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
15
+ use FernleafSystems\Wordpress\Services\Services;
16
+
17
+ class Store {
18
+
19
+ use ModConsumer;
20
+
21
+ public function store( QueueItemVO $queueItem, array $results ) {
22
+ /** @var ModCon $mod */
23
+ $mod = $this->getMod();
24
+
25
+ $dbhResItems = $mod->getDbH_ResultItems();
26
+ $dbhResItemMetas = $mod->getDbH_ResultItemMeta();
27
+ /** @var ResultItemsDB\Ops\Select $resultSelector */
28
+ $resultSelector = $dbhResItems->getQuerySelector();
29
+ /** @var ScanResultsDB\Ops\Insert $scanResultsInserter */
30
+ $scanResultsInserter = $mod->getDbH_ScanResults()->getQueryInserter();
31
+
32
+ foreach ( $results as $result ) {
33
+
34
+ $scanResult = $mod->getScanCon( $queueItem->scan )->buildScanResult( $result );
35
+
36
+ /** @var ResultItemsDB\Ops\Record $resultRecord */
37
+ $resultRecord = $resultSelector->filterByItemID( $scanResult->item_id )
38
+ ->filterByItemNotDeleted()
39
+ ->filterByItemNotRepaired()
40
+ ->first();
41
+ if ( empty( $resultRecord ) ) {
42
+ $dbhResItems->getQueryInserter()->insert( $scanResult );
43
+ $resultRecord = $resultSelector->byId( Services::WpDb()->getVar( 'SELECT LAST_INSERT_ID()' ) );
44
+ }
45
+ else {
46
+ // If a result item is now auto-filtered, where before it wasn't, update it.
47
+ if ( empty( $resultRecord->auto_filtered_at ) && $scanResult->auto_filtered_at > 0 ) {
48
+ $dbhResItems->getQueryUpdater()->updateRecord( $resultRecord, [
49
+ 'auto_filtered_at' => $scanResult->auto_filtered_at
50
+ ] );
51
+ }
52
+
53
+ // Delete/Reset all metadata for the results in preparation for update.
54
+ /** @var ResultItemMetaDB\Ops\Delete $metaDeleter */
55
+ $metaDeleter = $dbhResItemMetas->getQueryDeleter();
56
+ $metaDeleter->filterByResultItemRef( $resultRecord->id )->query();
57
+ }
58
+
59
+ foreach ( $scanResult->meta as $metaKey => $metaValue ) {
60
+ /** @var ResultItemMetaDB\Ops\Insert $metaInserter */
61
+ $metaInserter = $dbhResItemMetas->getQueryInserter();
62
+ $metaInserter->setInsertData( [
63
+ 'ri_ref' => $resultRecord->id,
64
+ 'meta_key' => $metaKey,
65
+ 'meta_value' => is_scalar( $metaValue ) ? $metaValue : json_encode( $metaValue ),
66
+ ] )->query();
67
+ }
68
+
69
+ $scanResultsInserter->setInsertData( [
70
+ 'scan_ref' => $queueItem->scan_id,
71
+ 'resultitem_ref' => $resultRecord->id,
72
+ ] )->query();
73
+ }
74
+ $this->markQueueItemAsFinished( $queueItem );
75
+ }
76
+
77
+ private function markQueueItemAsFinished( QueueItemVO $queueItem ) {
78
+ /** @var ModCon $mod */
79
+ $mod = $this->getMod();
80
+ $mod->getDbH_ScanItems()
81
+ ->getQueryUpdater()
82
+ ->updateById( $queueItem->qitem_id, [
83
+ 'finished_at' => Services::Request()->ts()
84
+ ] );
85
+ }
86
+ }
src/lib/src/Modules/HackGuard/Scan/Results/Update.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
10
+ use FernleafSystems\Wordpress\Services\Services;
11
+
12
+ class Update {
13
+
14
+ use ModConsumer;
15
+ use ScanControllerConsumer;
16
+
17
+ public function clearIgnored() {
18
+ Services::WpDb()->doSql(
19
+ sprintf( $this->getBaseQuery(),
20
+ implode( ', ', [
21
+ "`ri`.`ignored_at`=0",
22
+ sprintf( "`ri`.`updated_at`=%s", Services::Request()->ts() ),
23
+ ] ),
24
+ implode( ' AND ', [
25
+ sprintf( "`scans`.`scan`='%s'", $this->getScanController()->getSlug() )
26
+ ] )
27
+ )
28
+ );
29
+ }
30
+
31
+ private function getBaseQuery() :string {
32
+ /** @var ModCon $mod */
33
+ $mod = $this->getMod();
34
+ return sprintf( "UPDATE `%s` as ri
35
+ INNER JOIN `%s` as `sr`
36
+ ON `ri`.id = `sr`.resultitem_ref
37
+ INNER JOIN `%s` as `scans`
38
+ ON `scans`.id = `sr`.scan_ref
39
+ SET %%s
40
+ WHERE %%s",
41
+ $mod->getDbH_ResultItems()->getTableSchema()->table,
42
+ $mod->getDbH_ScanResults()->getTableSchema()->table,
43
+ $mod->getDbH_Scans()->getTableSchema()->table
44
+ );
45
+ }
46
+ }
src/lib/src/Modules/HackGuard/Scan/ScanActionFromSlug.php CHANGED
@@ -7,24 +7,18 @@ use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
 
8
  class ScanActionFromSlug {
9
 
10
- public static function GetAction( string $slug ) :Scans\Base\BaseScanActionVO {
 
 
 
11
  $VO = null;
12
  switch ( $slug ) {
 
 
 
13
  case Controller\Apc::SCAN_SLUG:
14
  $VO = new Scans\Apc\ScanActionVO();
15
  break;
16
- case Controller\Mal::SCAN_SLUG:
17
- $VO = new Scans\Mal\ScanActionVO();
18
- break;
19
- case Controller\Ptg::SCAN_SLUG:
20
- $VO = new Scans\Ptg\ScanActionVO();
21
- break;
22
- case Controller\Ufc::SCAN_SLUG:
23
- $VO = new Scans\Ufc\ScanActionVO();
24
- break;
25
- case Controller\Wcf::SCAN_SLUG:
26
- $VO = new Scans\Wcf\ScanActionVO();
27
- break;
28
  case Controller\Wpv::SCAN_SLUG:
29
  $VO = new Scans\Wpv\ScanActionVO();
30
  break;
7
 
8
  class ScanActionFromSlug {
9
 
10
+ /**
11
+ * @return Scans\Base\BaseScanActionVO
12
+ */
13
+ public static function GetAction( string $slug ) {
14
  $VO = null;
15
  switch ( $slug ) {
16
+ case Controller\Afs::SCAN_SLUG:
17
+ $VO = new Scans\Afs\ScanActionVO();
18
+ break;
19
  case Controller\Apc::SCAN_SLUG:
20
  $VO = new Scans\Apc\ScanActionVO();
21
  break;
 
 
 
 
 
 
 
 
 
 
 
 
22
  case Controller\Wpv::SCAN_SLUG:
23
  $VO = new Scans\Wpv\ScanActionVO();
24
  break;
src/lib/src/Modules/HackGuard/Scan/ScansController.php CHANGED
@@ -2,19 +2,27 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Crons\StandardCron;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
 
 
 
 
10
  use FernleafSystems\Wordpress\Services\Services;
11
 
12
  class ScansController extends ExecOnceModConsumer {
13
 
14
  use StandardCron;
 
15
 
16
  private $scanCons;
17
 
 
 
18
  public function __construct() {
19
  $this->scanCons = [];
20
  }
@@ -24,9 +32,16 @@ class ScansController extends ExecOnceModConsumer {
24
  $scanCon->execute();
25
  }
26
  $this->setupCron();
 
27
  $this->handlePostScanCron();
28
  }
29
 
 
 
 
 
 
 
30
  /**
31
  * @return Controller\Base[]
32
  */
@@ -44,9 +59,7 @@ class ScansController extends ExecOnceModConsumer {
44
  }
45
 
46
  /**
47
- * @param string $slug
48
  * @return Controller\Base|mixed
49
- * @throws \Exception
50
  */
51
  public function getScanCon( string $slug ) {
52
  if ( !isset( $this->scanCons[ $slug ] ) ) {
@@ -56,13 +69,18 @@ class ScansController extends ExecOnceModConsumer {
56
  $obj = new $class();
57
  $this->scanCons[ $slug ] = $obj->setMod( $this->getMod() );
58
  }
59
- else {
60
- throw new \Exception( 'Scan slug does not have a class: '.$slug );
61
- }
62
  }
63
  return $this->scanCons[ $slug ];
64
  }
65
 
 
 
 
 
 
 
 
 
66
  private function handlePostScanCron() {
67
  add_action( $this->getCon()->prefix( 'post_scan' ), function () {
68
  $this->runAutoRepair();
@@ -70,29 +88,25 @@ class ScansController extends ExecOnceModConsumer {
70
  }
71
 
72
  private function runAutoRepair() {
73
- /** @var HackGuard\ModCon $mod */
74
  $mod = $this->getMod();
75
- /** @var HackGuard\Options $opts */
76
  $opts = $this->getOptions();
77
  foreach ( $opts->getScanSlugs() as $slug ) {
78
  $scanCon = $mod->getScanCon( $slug );
79
- if ( $scanCon->isCronAutoRepair() ) {
80
- $scanCon->runCronAutoRepair();
81
- }
82
  }
83
  }
84
 
85
- /**
86
- * Cron callback
87
- */
88
  public function runCron() {
89
  Services::WpGeneral()->getIfAutoUpdatesInstalled() ? $this->resetCron() : $this->cronScan();
90
  }
91
 
92
  private function cronScan() {
93
- /** @var HackGuard\ModCon $mod */
94
  $mod = $this->getMod();
95
- /** @var HackGuard\Options $opts */
96
  $opts = $this->getOptions();
97
 
98
  if ( $this->getCanScansExecute() ) {
@@ -106,8 +120,8 @@ class ScansController extends ExecOnceModConsumer {
106
 
107
  $opts->setIsScanCron( true );
108
  $mod->saveModOptions()
109
- ->getScanQueueController()
110
- ->startScans( $scans );
111
  }
112
  else {
113
  error_log( 'Shield scans cannot execute.' );
@@ -129,25 +143,64 @@ class ScansController extends ExecOnceModConsumer {
129
  return $reasons;
130
  }
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  public function getCanScansExecute() :bool {
133
  return count( $this->getReasonsScansCantExecute() ) === 0;
134
  }
135
 
136
  protected function getCronFrequency() {
137
- /** @var HackGuard\Options $opts */
138
  $opts = $this->getOptions();
139
  return $opts->getScanFrequency();
140
  }
141
 
142
  public function getFirstRunTimestamp() :int {
 
143
 
144
- $startHour = (int)apply_filters( 'shield/scan_cron_start_hour', 3 );
145
- $startMinute = (int)apply_filters( 'shield/scan_cron_start_minute', (int)rand( 0, 59 ) );
146
  if ( $startHour < 0 || $startHour > 23 ) {
147
- $startHour = 3;
148
  }
149
  if ( $startMinute < 1 || $startMinute > 59 ) {
150
- $startMinute = (int)rand( 1, 59 );
151
  }
152
 
153
  $c = Services::Request()->carbon( true );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Crons\StandardCron;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
10
+ ModCon,
11
+ Options,
12
+ Scan\Queue\CleanQueue,
13
+ Scan\Queue\ProcessQueueWpcli
14
+ };
15
  use FernleafSystems\Wordpress\Services\Services;
16
 
17
  class ScansController extends ExecOnceModConsumer {
18
 
19
  use StandardCron;
20
+ use PluginCronsConsumer;
21
 
22
  private $scanCons;
23
 
24
+ private $scanResultsStatus;
25
+
26
  public function __construct() {
27
  $this->scanCons = [];
28
  }
32
  $scanCon->execute();
33
  }
34
  $this->setupCron();
35
+ $this->setupCronHooks(); // Plugin crons
36
  $this->handlePostScanCron();
37
  }
38
 
39
+ public function runHourlyCron() {
40
+ ( new CleanQueue() )
41
+ ->setMod( $this->getMod() )
42
+ ->execute();
43
+ }
44
+
45
  /**
46
  * @return Controller\Base[]
47
  */
59
  }
60
 
61
  /**
 
62
  * @return Controller\Base|mixed
 
63
  */
64
  public function getScanCon( string $slug ) {
65
  if ( !isset( $this->scanCons[ $slug ] ) ) {
69
  $obj = new $class();
70
  $this->scanCons[ $slug ] = $obj->setMod( $this->getMod() );
71
  }
 
 
 
72
  }
73
  return $this->scanCons[ $slug ];
74
  }
75
 
76
+ public function getScanResultsCount() :Results\Counts {
77
+ if ( !isset( $this->scanResultsStatus ) ) {
78
+ $this->scanResultsStatus = ( new Results\Counts() )
79
+ ->setMod( $this->getMod() );
80
+ }
81
+ return $this->scanResultsStatus;
82
+ }
83
+
84
  private function handlePostScanCron() {
85
  add_action( $this->getCon()->prefix( 'post_scan' ), function () {
86
  $this->runAutoRepair();
88
  }
89
 
90
  private function runAutoRepair() {
91
+ /** @var ModCon $mod */
92
  $mod = $this->getMod();
93
+ /** @var Options $opts */
94
  $opts = $this->getOptions();
95
  foreach ( $opts->getScanSlugs() as $slug ) {
96
  $scanCon = $mod->getScanCon( $slug );
97
+ $scanCon->runCronAutoRepair();
98
+ $scanCon->cleanStalesResults();
 
99
  }
100
  }
101
 
 
 
 
102
  public function runCron() {
103
  Services::WpGeneral()->getIfAutoUpdatesInstalled() ? $this->resetCron() : $this->cronScan();
104
  }
105
 
106
  private function cronScan() {
107
+ /** @var ModCon $mod */
108
  $mod = $this->getMod();
109
+ /** @var Options $opts */
110
  $opts = $this->getOptions();
111
 
112
  if ( $this->getCanScansExecute() ) {
120
 
121
  $opts->setIsScanCron( true );
122
  $mod->saveModOptions()
123
+ ->getScansCon()
124
+ ->startNewScans( $scans );
125
  }
126
  else {
127
  error_log( 'Shield scans cannot execute.' );
143
  return $reasons;
144
  }
145
 
146
+ public function startNewScans( array $scans, bool $resetIgnored = false ) :bool {
147
+ /** @var ModCon $mod */
148
+ $mod = $this->getMod();
149
+ /** @var Options $opts */
150
+ $opts = $this->getOptions();
151
+
152
+ $toScan = [];
153
+ foreach ( $scans as $slug ) {
154
+ try {
155
+ $thisScanCon = $this->getScanCon( $slug );
156
+ if ( $thisScanCon->isReady() ) {
157
+ $toScan[] = $slug;
158
+ if ( $resetIgnored ) {
159
+ $thisScanCon->resetIgnoreStatus();
160
+ }
161
+ $opts->addRemoveScanToBuild( $slug );
162
+ }
163
+ }
164
+ catch ( \Exception $e ) {
165
+ }
166
+ }
167
+
168
+ if ( !empty( $toScan ) ) {
169
+ if ( Services::WpGeneral()->isWpCli() ) {
170
+ ( new ProcessQueueWpcli() )
171
+ ->setMod( $this->getMod() )
172
+ ->execute();
173
+ }
174
+ else {
175
+ $mod->getScanQueueController()
176
+ ->getQueueBuilder()
177
+ ->dispatch();
178
+ }
179
+ }
180
+
181
+ return !empty( $toScan );
182
+ }
183
+
184
  public function getCanScansExecute() :bool {
185
  return count( $this->getReasonsScansCantExecute() ) === 0;
186
  }
187
 
188
  protected function getCronFrequency() {
189
+ /** @var Options $opts */
190
  $opts = $this->getOptions();
191
  return $opts->getScanFrequency();
192
  }
193
 
194
  public function getFirstRunTimestamp() :int {
195
+ $defaultStart = rand( 1, 7 );
196
 
197
+ $startHour = (int)apply_filters( 'shield/scan_cron_start_hour', $defaultStart );
198
+ $startMinute = (int)apply_filters( 'shield/scan_cron_start_minute', rand( 0, 59 ) );
199
  if ( $startHour < 0 || $startHour > 23 ) {
200
+ $startHour = $defaultStart;
201
  }
202
  if ( $startMinute < 1 || $startMinute > 59 ) {
203
+ $startMinute = rand( 1, 59 );
204
  }
205
 
206
  $c = Services::Request()->carbon( true );
src/lib/src/Modules/HackGuard/Scan/Utilities/ConvertLegacyResults.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner\EntryVO;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
8
+ DB\ResultItemMeta\Ops as ResultItemMetaDB,
9
+ DB\ResultItems\Ops as ResultItemsDB,
10
+ ModCon,
11
+ Options,
12
+ Scan\Controller\Afs,
13
+ Scan\Controller\Apc,
14
+ Scan\Controller\Mal,
15
+ Scan\Controller\Ptg,
16
+ Scan\Controller\Ufc,
17
+ Scan\Controller\Wcf,
18
+ Scan\Controller\Wpv
19
+ };
20
+ use FernleafSystems\Wordpress\Services\Services;
21
+
22
+ class ConvertLegacyResults extends ExecOnceModConsumer {
23
+
24
+ protected function canRun() :bool {
25
+ /** @var Options $opts */
26
+ $opts = $this->getOptions();
27
+ return (int)$opts->getOpt( 'legacy_db_conversion_at' ) === 0;
28
+ }
29
+
30
+ protected function run() {
31
+ /** @var ModCon $mod */
32
+ $mod = $this->getMod();
33
+ /** @var Options $opts */
34
+ $opts = $this->getOptions();
35
+ /** @var ResultItemsDB\Select $selectResItem */
36
+ $dbhResItems = $mod->getDbH_ResultItems();
37
+ /** @var ResultItemsDB\Select $selectResItem */
38
+ $selectResItem = $dbhResItems->getQuerySelector();
39
+
40
+ $legacyResults = $this->getLegacyResults();
41
+ foreach ( $legacyResults as $e ) {
42
+
43
+ if ( in_array( $e->scan, [ Mal::SCAN_SLUG, Ptg::SCAN_SLUG, Ufc::SCAN_SLUG, Wcf::SCAN_SLUG ] ) ) {
44
+ $selectResItem->filterByItemID( $e->meta[ 'path_fragment' ] )
45
+ ->filterByTypeFile();
46
+ }
47
+ else {
48
+ // Apc::SCAN_SLUG, Wpv::SCAN_SLUG
49
+ $selectResItem->filterByItemID( $e->meta[ 'slug' ] );
50
+ if ( strpos( $e->meta[ 'slug' ], '/' ) ) {
51
+ $selectResItem->filterByTypePlugin();
52
+ }
53
+ else {
54
+ $selectResItem->filterByTypeTheme();
55
+ }
56
+ }
57
+
58
+ $resultItem = $selectResItem->first();
59
+
60
+ if ( empty( $resultItem ) ) {
61
+
62
+ $scanResult = $this->convertResult( $e );
63
+
64
+ if ( !empty( $scanResult ) ) {
65
+ /** @var ResultItemsDB\Insert $selectScans */
66
+ $insertResItem = $dbhResItems->getQueryInserter();
67
+ $insertResItem->insert( $scanResult );
68
+ $resultRecord = $selectResItem->byId( Services::WpDb()->getVar( 'SELECT LAST_INSERT_ID()' ) );
69
+
70
+ /** @var ResultItemMetaDB\Delete $metaDeleter */
71
+ $metaDeleter = $mod->getDbH_ResultItemMeta()->getQueryDeleter();
72
+ $metaDeleter->filterByResultItemRef( $resultRecord->id )->query();
73
+
74
+ foreach ( $scanResult->meta as $metaKey => $metaValue ) {
75
+ /** @var ResultItemMetaDB\Insert $metaInserter */
76
+ $metaInserter = $mod->getDbH_ResultItemMeta()->getQueryInserter();
77
+ $metaInserter->setInsertData( [
78
+ 'ri_ref' => $resultRecord->id,
79
+ 'meta_key' => $metaKey,
80
+ 'meta_value' => is_scalar( $metaValue ) ? $metaValue : json_encode( $metaValue ),
81
+ ] )->query();
82
+ }
83
+ }
84
+ }
85
+
86
+ $mod->getDbHandler_ScanResults()
87
+ ->getQueryDeleter()
88
+ ->deleteById( $e->id );
89
+ }
90
+
91
+ if ( !empty( $legacyResults ) ) {
92
+ $mod->getScansCon()->startNewScans( $opts->getScanSlugs() );
93
+ }
94
+
95
+ $mod->getDbHandler_ScanQueue()->tableDelete();
96
+ if ( $mod->getDbHandler_ScanResults()->getQuerySelector()->count() === 0 ) {
97
+ $mod->getDbHandler_ScanResults()->tableDelete();
98
+ $opts->setOpt( 'legacy_db_conversion_at', Services::Request()->ts() );
99
+ }
100
+ }
101
+
102
+ /**
103
+ * @return ResultItemsDB\Record|null
104
+ */
105
+ private function convertResult( EntryVO $e ) {
106
+ /** @var ModCon $mod */
107
+ $mod = $this->getMod();
108
+
109
+ $raw = $e->meta;
110
+
111
+ switch ( $e->scan ) {
112
+
113
+ case Apc::SCAN_SLUG:
114
+ $raw[ 'is_abandoned' ] = 1;
115
+ $scanResult = $mod->getScanCon( Apc::SCAN_SLUG )->buildScanResult( $raw );
116
+ break;
117
+
118
+ case Wpv::SCAN_SLUG:
119
+ $raw[ 'is_vulnerable' ] = 1;
120
+ $scanResult = $mod->getScanCon( Wpv::SCAN_SLUG )->buildScanResult( $raw );
121
+ unset( $raw[ 'wpvuln_id' ], $raw[ 'wpvuln_vo' ] );
122
+ break;
123
+
124
+ case Mal::SCAN_SLUG:
125
+ $raw[ 'mal_fp_confidence' ] = $raw[ 'fp_confidence' ];
126
+ unset( $raw[ 'fp_confidence' ] );
127
+ $raw[ 'mal_file_lines' ] = base64_encode( json_encode( array_fill_keys( $raw[ 'file_lines' ], '' ) ) );
128
+ $raw[ 'mal_fp_lines' ] = json_encode( array_fill_keys( $raw[ 'file_lines' ], 0 ) );
129
+ unset( $raw[ 'file_lines' ] );
130
+ $scanResult = $mod->getScanCon( Afs::SCAN_SLUG )->buildScanResult( $raw );
131
+ break;
132
+
133
+ case Ptg::SCAN_SLUG:
134
+ if ( strpos( $raw[ 'slug' ], '/' ) ) {
135
+ $raw[ 'is_in_plugin' ] = true;
136
+ }
137
+ else {
138
+ $raw[ 'is_in_theme' ] = true;
139
+ }
140
+
141
+ if ( $raw[ 'is_different' ] ?? false ) {
142
+ $raw[ 'is_checksumfail' ] = true;
143
+ }
144
+ unset( $raw[ 'is_different' ] );
145
+
146
+ if ( empty( $raw[ 'is_unrecognised' ] ) ) {
147
+ unset( $raw[ 'is_unrecognised' ] );
148
+ }
149
+
150
+ if ( empty( $raw[ 'is_missing' ] ) ) {
151
+ unset( $raw[ 'is_missing' ] );
152
+ }
153
+
154
+ unset( $raw[ 'context' ] );
155
+ $scanResult = $mod->getScanCon( Afs::SCAN_SLUG )->buildScanResult( $raw );
156
+ break;
157
+
158
+ case Ufc::SCAN_SLUG:
159
+ $raw[ 'is_in_core' ] = true;
160
+ $raw[ 'is_unrecognised' ] = true;
161
+ $scanResult = $mod->getScanCon( Afs::SCAN_SLUG )->buildScanResult( $raw );
162
+ break;
163
+
164
+ case Wcf::SCAN_SLUG:
165
+ default:
166
+ $raw[ 'is_in_core' ] = true;
167
+
168
+ if ( empty( $raw[ 'is_missing' ] ) ) {
169
+ unset( $raw[ 'is_missing' ] );
170
+ }
171
+
172
+ if ( empty( $raw[ 'is_checksumfail' ] ) ) {
173
+ unset( $raw[ 'is_checksumfail' ] );
174
+ }
175
+
176
+ unset( $raw[ 'is_excluded' ], $raw[ 'md5_file_wp' ] );
177
+
178
+ $scanResult = $mod->getScanCon( Afs::SCAN_SLUG )->buildScanResult( $raw );
179
+ break;
180
+ }
181
+
182
+ $scanResult->created_at = $e->created_at;
183
+ $scanResult->ignored_at = $e->ignored_at;
184
+ $scanResult->notified_at = $e->notified_at;
185
+ $scanResult->attempt_repair_at = $e->attempt_repair_at;
186
+
187
+ return $scanResult;
188
+ }
189
+
190
+ /**
191
+ * @return EntryVO[]
192
+ */
193
+ private function getLegacyResults() :array {
194
+ /** @var ModCon $mod */
195
+ $mod = $this->getMod();
196
+ $res = $mod->getDbHandler_ScanResults()
197
+ ->getQuerySelector()
198
+ ->all();
199
+ return empty( $res ) ? [] : $res;
200
+ }
201
+ }
src/lib/src/Modules/HackGuard/Scan/Utilities/PtgAddReinstallLinks.php CHANGED
@@ -5,7 +5,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Utiliti
5
  use FernleafSystems\Utilities\Logic\ExecOnce;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
8
- use FernleafSystems\Wordpress\Services\Core\VOs\Assets\WpPluginVo;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
  class PtgAddReinstallLinks {
@@ -13,15 +12,12 @@ class PtgAddReinstallLinks {
13
  use Controller\ScanControllerConsumer;
14
  use ExecOnce;
15
 
16
- /**
17
- * @var int
18
- */
19
- private $nColumnsCount;
20
-
21
- /**
22
- * @var int
23
- */
24
- private $vulnCount;
25
 
26
  protected function run() {
27
  add_action( 'plugin_action_links', function ( $links, $file ) {
@@ -58,13 +54,6 @@ class PtgAddReinstallLinks {
58
  }, 10, 2 );
59
  }
60
 
61
- protected function canRun() :bool {
62
- $scanCon = $this->getScanController();
63
- /** @var HackGuard\Options $opts */
64
- $opts = $scanCon->getOptions();
65
- return $scanCon->isReady() && $opts->isPtgReinstallLinks();
66
- }
67
-
68
  private function addActionLinkRefresh( array $links, string $file ) :array {
69
  $WPP = Services::WpPlugins();
70
 
5
  use FernleafSystems\Utilities\Logic\ExecOnce;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
 
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class PtgAddReinstallLinks {
12
  use Controller\ScanControllerConsumer;
13
  use ExecOnce;
14
 
15
+ protected function canRun() :bool {
16
+ $scanCon = $this->getScanController();
17
+ /** @var HackGuard\Options $opts */
18
+ $opts = $scanCon->getOptions();
19
+ return $scanCon->isReady() && $opts->isPtgReinstallLinks();
20
+ }
 
 
 
21
 
22
  protected function run() {
23
  add_action( 'plugin_action_links', function ( $links, $file ) {
54
  }, 10, 2 );
55
  }
56
 
 
 
 
 
 
 
 
57
  private function addActionLinkRefresh( array $links, string $file ) :array {
58
  $WPP = Services::WpPlugins();
59
 
src/lib/src/Modules/HackGuard/Scan/Utilities/WpvAddPluginRows.php CHANGED
@@ -89,7 +89,7 @@ class WpvAddPluginRows {
89
  public function filterPluginsToView( $plugins ) {
90
  if ( Services::Request()->query( 'plugin_status' ) == 'vulnerable' ) {
91
  /** @var Wpv\ResultsSet $oVulnerableRes */
92
- $oVulnerableRes = $this->getScanController()->getAllResults();
93
  global $status;
94
  $status = 'vulnerable';
95
  $plugins = array_intersect_key(
@@ -105,43 +105,33 @@ class WpvAddPluginRows {
105
  * @param array $pData
106
  */
107
  public function attachVulnerabilityWarning( $pluginFile, $pData ) {
 
108
  $scanCon = $this->getScanController();
109
 
110
- $vulns = $scanCon->getPluginVulnerabilities( $pluginFile );
111
- if ( count( $vulns ) > 0 ) {
112
  $name = $scanCon->getCon()->getHumanName();
 
113
  echo $scanCon->getMod()
114
  ->renderTemplate(
115
  '/snippets/plugin_vulnerability.twig',
116
  [
117
  'strings' => [
118
- 'known_vuln' => sprintf( __( '%s has discovered that the currently installed version of the %s plugin has known security vulnerabilities.', 'wp-simple-firewall' ),
 
119
  $name, '<strong>'.$pData[ 'Name' ].'</strong>' ),
120
- 'name' => __( 'Vulnerability Name', 'wp-simple-firewall' ),
121
- 'type' => __( 'Vulnerability Type', 'wp-simple-firewall' ),
122
- 'fixed_versions' => __( 'Fixed Versions', 'wp-simple-firewall' ),
123
- 'more_info' => __( 'More Info', 'wp-simple-firewall' ),
 
 
 
 
 
 
 
124
  ],
125
  'vars' => [
126
- 'vulns' => array_map(
127
- function ( $vuln ) use ( $pluginFile ) {
128
- $data = $vuln->getRawData();
129
-
130
- $plugin = Services::WpPlugins()->getPluginAsVo( $pluginFile );
131
- if ( !empty( $plugin ) ) {
132
- $data[ 'url' ] = add_query_arg(
133
- [
134
- 'type' => $plugin->asset_type,
135
- 'slug' => $plugin->slug,
136
- 'version' => $plugin->Version,
137
- ],
138
- 'https://shsec.io/shieldvulnerabilitylookup'
139
- );
140
- }
141
- return $data;
142
- },
143
- $vulns
144
- ),
145
  'colspan' => $this->nColumnsCount
146
  ],
147
  ],
@@ -164,8 +154,9 @@ class WpvAddPluginRows {
164
  private function countVulnerablePlugins() :int {
165
  if ( !isset( $this->vulnCount ) ) {
166
  $this->vulnCount = $this->getScanController()
167
- ->getAllResults()
168
- ->countUniqueSlugsForPluginsContext();
 
169
  }
170
  return $this->vulnCount;
171
  }
89
  public function filterPluginsToView( $plugins ) {
90
  if ( Services::Request()->query( 'plugin_status' ) == 'vulnerable' ) {
91
  /** @var Wpv\ResultsSet $oVulnerableRes */
92
+ $oVulnerableRes = $this->getScanController()->getResultsForDisplay();
93
  global $status;
94
  $status = 'vulnerable';
95
  $plugins = array_intersect_key(
105
  * @param array $pData
106
  */
107
  public function attachVulnerabilityWarning( $pluginFile, $pData ) {
108
+ /** @var Controller\Wpv $scanCon */
109
  $scanCon = $this->getScanController();
110
 
111
+ if ( $scanCon->hasVulnerabilities( $pluginFile ) ) {
 
112
  $name = $scanCon->getCon()->getHumanName();
113
+ $plugin = Services::WpPlugins()->getPluginAsVo( $pluginFile );
114
  echo $scanCon->getMod()
115
  ->renderTemplate(
116
  '/snippets/plugin_vulnerability.twig',
117
  [
118
  'strings' => [
119
+ 'known_vuln' => sprintf(
120
+ __( '%s has discovered that the currently installed version of the %s plugin has known security vulnerabilities.', 'wp-simple-firewall' ),
121
  $name, '<strong>'.$pData[ 'Name' ].'</strong>' ),
122
+ 'more_info' => __( 'More Info', 'wp-simple-firewall' ),
123
+ ],
124
+ 'hrefs' => [
125
+ 'vuln_lookup' => add_query_arg(
126
+ [
127
+ 'type' => $plugin->asset_type,
128
+ 'slug' => $plugin->slug,
129
+ 'version' => $plugin->Version,
130
+ ],
131
+ 'https://shsec.io/shieldvulnerabilitylookup'
132
+ )
133
  ],
134
  'vars' => [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  'colspan' => $this->nColumnsCount
136
  ],
137
  ],
154
  private function countVulnerablePlugins() :int {
155
  if ( !isset( $this->vulnCount ) ) {
156
  $this->vulnCount = $this->getScanController()
157
+ ->getScansController()
158
+ ->getScanResultsCount()
159
+ ->countVulnerableAssets();
160
  }
161
  return $this->vulnCount;
162
  }
src/lib/src/Modules/HackGuard/Strings.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
@@ -22,7 +22,7 @@ class Strings extends Base\Strings {
22
  'scan_item_delete_success' => [
23
  'name' => __( 'Scan Item Delete Success', 'wp-simple-firewall' ),
24
  'audit' => [
25
- __( 'Deleted item found in the scan.', 'wp-simple-firewall' ),
26
  __( 'Item deleted: "{{path_full}}"', 'wp-simple-firewall' ),
27
  ],
28
  ],
@@ -57,24 +57,15 @@ class Strings extends Base\Strings {
57
  return $this->getScanStrings()[ $slug ][ 'name' ];
58
  }
59
 
60
- /**
61
- * @return string[]
62
- * @deprecated 12.0
63
- */
64
- public function getScanNames() :array {
65
- return array_map(
66
- function ( $strings ) {
67
- return $strings[ 'name' ];
68
- },
69
- $this->getScanStrings()
70
- );
71
- }
72
-
73
  /**
74
  * @return string[]
75
  */
76
  public function getScanStrings() :array {
77
  return [
 
 
 
 
78
  'apc' => [
79
  'name' => __( 'Abandoned Plugins', 'wp-simple-firewall' ),
80
  'subtitle' => __( "Discover plugins that may have been abandoned by their authors", 'wp-simple-firewall' ),
@@ -103,8 +94,6 @@ class Strings extends Base\Strings {
103
  }
104
 
105
  /**
106
- * @param string $section
107
- * @return array
108
  * @throws \Exception
109
  */
110
  public function getSectionStrings( string $section ) :array {
@@ -114,26 +103,26 @@ class Strings extends Base\Strings {
114
  switch ( $section ) {
115
 
116
  case 'section_scan_options' :
117
- $sTitle = __( 'Scan Options', 'wp-simple-firewall' );
118
- $sTitleShort = __( 'Scan Options', 'wp-simple-firewall' );
119
- $aSummary = [
120
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Set how frequently the Hack Guard scans will run.', 'wp-simple-firewall' ) )
121
  ];
122
  break;
123
 
124
  case 'section_enable_plugin_feature_hack_protection_tools' :
125
- $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
126
- $sTitle = sprintf( __( 'Enable Module: %s', 'wp-simple-firewall' ), $sModName );
127
- $aSummary = [
128
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Hack Guard is a set of tools to warn you and protect you against hacks on your site.', 'wp-simple-firewall' ) ),
129
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), __( 'Hack Guard', 'wp-simple-firewall' ) ) )
130
  ];
131
  break;
132
 
133
  case 'section_scan_wpv' :
134
- $sTitleShort = __( 'Vulnerabilities', 'wp-simple-firewall' );
135
- $sTitle = __( 'Vulnerabilities Scanner', 'wp-simple-firewall' );
136
- $aSummary = [
137
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Regularly scan your WordPress plugins and themes for known security vulnerabilities.', 'wp-simple-firewall' ) ),
138
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), __( 'Vulnerabilities Scanner', 'wp-simple-firewall' ) ) ),
139
  __( 'Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities.', 'wp-simple-firewall' )
@@ -141,81 +130,48 @@ class Strings extends Base\Strings {
141
  break;
142
 
143
  case 'section_file_guard' :
144
- $sTitleShort = __( 'File Scans and Malware', 'wp-simple-firewall' );
145
- $sTitle = __( 'File Scanning and Malware Protection', 'wp-simple-firewall' );
146
- $aSummary = [
147
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ),
148
  __( 'Monitor WordPress files and protect against malicious intrusion and hacking.', 'wp-simple-firewall' ) ),
149
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
150
- sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), $sTitle ) )
151
  ];
152
  break;
153
 
154
  case 'section_realtime' :
155
- $sTitleShort = __( 'Realtime Change Detection', 'wp-simple-firewall' );
156
- $sTitle = __( 'Realtime Change Detection', 'wp-simple-firewall' );
157
- $aSummary = [
158
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ),
159
  __( 'Monitor Your WordPress Site For Changes To Critical Components In Realtime.', 'wp-simple-firewall' ) ),
160
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
161
- sprintf( __( 'Enable The Realtime Change Detection Features.', 'wp-simple-firewall' ), $sTitle ) )
162
- ];
163
- break;
164
-
165
- case 'section_scan_ufc' :
166
- $sTitleShort = __( 'Unrecognised Files', 'wp-simple-firewall' );
167
- $sTitle = __( 'Unrecognised Files Scanner', 'wp-simple-firewall' );
168
- $aSummary = [
169
- sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( "Regularly scan your WordPress core folders for files that don't belong.", 'wp-simple-firewall' ) ),
170
- sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), $sTitle ) )
171
  ];
172
  break;
173
 
174
  case 'section_scan_apc' :
175
- $sTitle = __( 'Enable The Abandoned Plugin Scanner', 'wp-simple-firewall' );
176
- $sTitleShort = __( 'Abandoned Plugins', 'wp-simple-firewall' );
177
- $aSummary = [
178
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ),
179
  __( 'Monitor your site for plugins that have been abandoned by their authors and are no longer maintained.', 'wp-simple-firewall' ) ),
180
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Enable this to alert you to your site running unmaintained code.', 'wp-simple-firewall' ) )
181
  ];
182
  break;
183
 
184
- //REMOVED:
185
- case 'section_scan_wcf' :
186
- $sTitleShort = __( 'Core Files', 'wp-simple-firewall' );
187
- $sTitle = __( 'WordPress Core File Scanner', 'wp-simple-firewall' );
188
- $aSummary = [
189
- sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Regularly scan your WordPress core files for changes compared to official WordPress files.', 'wp-simple-firewall' ) ),
190
- sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), $sTitle ) )
191
- ];
192
- break;
193
-
194
- case 'section_scan_mal' :
195
- $sTitleShort = __( 'Malware', 'wp-simple-firewall' );
196
- $sTitle = __( 'Malware Scanner', 'wp-simple-firewall' );
197
- $aSummary = [
198
- sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Monitor and detect presence of Malware signatures.', 'wp-simple-firewall' ) ),
199
- sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Enable this scanner to automatically detect infected files.', 'wp-simple-firewall' ) )
200
- ];
201
- break;
202
-
203
  default:
204
  return parent::getSectionStrings( $section );
205
  }
206
 
207
  return [
208
- 'title' => $sTitle,
209
- 'title_short' => $sTitleShort,
210
- 'summary' => ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : [],
211
  ];
212
  }
213
 
214
- /**
215
- * @param string $key
216
- * @return array
217
- * @throws \Exception
218
- */
219
  public function getOptionStrings( string $key ) :array {
220
  /** @var ModCon $mod */
221
  $mod = $this->getMod();
@@ -257,41 +213,25 @@ class Strings extends Base\Strings {
257
  break;
258
 
259
  case 'enable_core_file_integrity_scan' :
260
- $name = sprintf( __( '%s Core Files', 'wp-simple-firewall' ),
261
  Services::WpGeneral()->isClassicPress() ? 'ClassicPress' : 'WordPress'
262
  );
263
- $summary = sprintf( __( 'Scan And Monitor %s Core Files For Changes', 'wp-simple-firewall' ),
264
  Services::WpGeneral()->isClassicPress() ? 'ClassicPress' : 'WordPress'
265
  );
266
  $desc = [
267
- sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Regularly scan your WordPress core files for changes compared to official WordPress files.', 'wp-simple-firewall' ) ),
268
- sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Keep this feature turned on, at all times.', 'wp-simple-firewall' ) )
269
- ];
270
- break;
271
-
272
- case 'mal_scan_enable' :
273
- $name = __( 'Malware', 'wp-simple-firewall' );
274
- $summary = __( 'Scan And Monitor Files For Malware Infections', 'wp-simple-firewall' );
275
- $desc = [
276
- sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Monitor and detect presence of Malware signatures.', 'wp-simple-firewall' ) ),
277
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Keep this feature turned on, at all times.', 'wp-simple-firewall' ) ),
278
- sprintf( '%s - %s', __( 'Note', 'wp-simple-firewall' ), __( 'Currently files of the following types are supported:', 'wp-simple-firewall' ) )
279
- .' '.implode( ', ', [ 'PHP' ] )
280
  ];
281
- break;
282
-
283
- case 'ptg_enable' :
284
- $name = __( 'Plugins & Themes', 'wp-simple-firewall' );
285
- $summary = __( 'Scan And Monitor Plugin & Theme Files For Changes', 'wp-simple-firewall' );
286
-
287
- $desc = [
288
- __( "Looks for new files added to plugins or themes, and also for changes to existing files.", 'wp-simple-firewall' ),
289
- sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ), __( "Doesn't currently detect missing files.", 'wp-simple-firewall' ) ),
290
- sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Keep this feature turned on, at all times.', 'wp-simple-firewall' ) )
291
- ];
292
- if ( !$this->getCon()->hasCacheDir() ) {
293
- $desc[] = sprintf( __( 'Sorry, this feature is not available because we cannot write to disk at this location: %s', 'wp-simple-firewall' ),
294
- '<code>'.$mod->getPtgSnapsBaseDir().'</code>' );
295
  }
296
  break;
297
 
@@ -299,9 +239,9 @@ class Strings extends Base\Strings {
299
  $name = __( 'Automatic File Repair', 'wp-simple-firewall' );
300
  $summary = __( 'Automatically Repair Files That Have Changes Or Malware Infection', 'wp-simple-firewall' );
301
  $desc = [
302
- __( 'Will attempt to automatically repair files that have been changed or infected with malware.', 'wp-simple-firewall' ),
303
  '- '.__( 'In the case of WordPress, original files will be downloaded from WordPress.org to repair any broken files.', 'wp-simple-firewall' ),
304
- '- '.__( 'In the case of plugins & themes, only those installed from WordPress.org may be repaired.', 'wp-simple-firewall' ),
305
  sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ), __( "Auto-Repair will never automatically delete new or unrecognised files.", 'wp-simple-firewall' ) )
306
  .' '.__( "Unrecognised files will need to be manually deleted.", 'wp-simple-firewall' ),
307
  ];
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
22
  'scan_item_delete_success' => [
23
  'name' => __( 'Scan Item Delete Success', 'wp-simple-firewall' ),
24
  'audit' => [
25
+ __( 'Item found in the scan was deleted.', 'wp-simple-firewall' ),
26
  __( 'Item deleted: "{{path_full}}"', 'wp-simple-firewall' ),
27
  ],
28
  ],
57
  return $this->getScanStrings()[ $slug ][ 'name' ];
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  /**
61
  * @return string[]
62
  */
63
  public function getScanStrings() :array {
64
  return [
65
+ 'afs' => [
66
+ 'name' => __( 'WordPress Filesystem Scan', 'wp-simple-firewall' ),
67
+ 'subtitle' => __( "WordPress Filesystem Scan looking for modified, missing and unrecognised files throughout the entire site", 'wp-simple-firewall' ),
68
+ ],
69
  'apc' => [
70
  'name' => __( 'Abandoned Plugins', 'wp-simple-firewall' ),
71
  'subtitle' => __( "Discover plugins that may have been abandoned by their authors", 'wp-simple-firewall' ),
94
  }
95
 
96
  /**
 
 
97
  * @throws \Exception
98
  */
99
  public function getSectionStrings( string $section ) :array {
103
  switch ( $section ) {
104
 
105
  case 'section_scan_options' :
106
+ $title = __( 'Scan Options', 'wp-simple-firewall' );
107
+ $shortTitle = __( 'Scan Options', 'wp-simple-firewall' );
108
+ $summary = [
109
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Set how frequently the Hack Guard scans will run.', 'wp-simple-firewall' ) )
110
  ];
111
  break;
112
 
113
  case 'section_enable_plugin_feature_hack_protection_tools' :
114
+ $shortTitle = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
115
+ $title = sprintf( __( 'Enable Module: %s', 'wp-simple-firewall' ), $sModName );
116
+ $summary = [
117
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Hack Guard is a set of tools to warn you and protect you against hacks on your site.', 'wp-simple-firewall' ) ),
118
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), __( 'Hack Guard', 'wp-simple-firewall' ) ) )
119
  ];
120
  break;
121
 
122
  case 'section_scan_wpv' :
123
+ $shortTitle = __( 'Vulnerabilities', 'wp-simple-firewall' );
124
+ $title = __( 'Vulnerabilities Scanner', 'wp-simple-firewall' );
125
+ $summary = [
126
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Regularly scan your WordPress plugins and themes for known security vulnerabilities.', 'wp-simple-firewall' ) ),
127
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), __( 'Vulnerabilities Scanner', 'wp-simple-firewall' ) ) ),
128
  __( 'Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities.', 'wp-simple-firewall' )
130
  break;
131
 
132
  case 'section_file_guard' :
133
+ $shortTitle = __( 'File Scans and Malware', 'wp-simple-firewall' );
134
+ $title = __( 'File Scanning and Malware Protection', 'wp-simple-firewall' );
135
+ $summary = [
136
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ),
137
  __( 'Monitor WordPress files and protect against malicious intrusion and hacking.', 'wp-simple-firewall' ) ),
138
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
139
+ sprintf( __( 'Keep the %s feature turned on.', 'wp-simple-firewall' ), $title ) )
140
  ];
141
  break;
142
 
143
  case 'section_realtime' :
144
+ $shortTitle = __( 'Realtime Change Detection', 'wp-simple-firewall' );
145
+ $title = __( 'Realtime Change Detection', 'wp-simple-firewall' );
146
+ $summary = [
147
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ),
148
  __( 'Monitor Your WordPress Site For Changes To Critical Components In Realtime.', 'wp-simple-firewall' ) ),
149
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
150
+ sprintf( __( 'Enable The Realtime Change Detection Features.', 'wp-simple-firewall' ), $title ) )
 
 
 
 
 
 
 
 
 
151
  ];
152
  break;
153
 
154
  case 'section_scan_apc' :
155
+ $title = __( 'Enable The Abandoned Plugin Scanner', 'wp-simple-firewall' );
156
+ $shortTitle = __( 'Abandoned Plugins', 'wp-simple-firewall' );
157
+ $summary = [
158
  sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ),
159
  __( 'Monitor your site for plugins that have been abandoned by their authors and are no longer maintained.', 'wp-simple-firewall' ) ),
160
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Enable this to alert you to your site running unmaintained code.', 'wp-simple-firewall' ) )
161
  ];
162
  break;
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  default:
165
  return parent::getSectionStrings( $section );
166
  }
167
 
168
  return [
169
+ 'title' => $title,
170
+ 'title_short' => $shortTitle,
171
+ 'summary' => $summary,
172
  ];
173
  }
174
 
 
 
 
 
 
175
  public function getOptionStrings( string $key ) :array {
176
  /** @var ModCon $mod */
177
  $mod = $this->getMod();
213
  break;
214
 
215
  case 'enable_core_file_integrity_scan' :
216
+ $name = sprintf( __( 'Automatic %s File Scanner', 'wp-simple-firewall' ),
217
  Services::WpGeneral()->isClassicPress() ? 'ClassicPress' : 'WordPress'
218
  );
219
+ $summary = sprintf( __( 'Scan And Monitor %s Files For Changes', 'wp-simple-firewall' ),
220
  Services::WpGeneral()->isClassicPress() ? 'ClassicPress' : 'WordPress'
221
  );
222
  $desc = [
223
+ sprintf( '%s - %s', __( 'Purpose', 'wp-simple-firewall' ), __( 'Regularly scan all files on your site for changes.', 'wp-simple-firewall' ) ),
 
 
 
 
 
 
 
 
 
224
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Keep this feature turned on, at all times.', 'wp-simple-firewall' ) ),
 
 
225
  ];
226
+ if ( $mod->isPremium() ) {
227
+ $desc[] = sprintf( '%s - %s', __( 'Note', 'wp-simple-firewall' ),
228
+ sprintf( __( 'Scan areas include: WordPress Core Files, Plugin and Themes, and PHP Malware.', 'wp-simple-firewall' ), 'ShieldPRO' ) );
229
+ }
230
+ else {
231
+ $desc[] = sprintf( '%s - %s', __( 'Note', 'wp-simple-firewall' ),
232
+ __( 'Scan areas include: WordPress Core Files.', 'wp-simple-firewall' ) );
233
+ $desc[] = sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ),
234
+ sprintf( __( 'To also include scanning Plugins and Themes, and for PHP Malware, please upgrade to %s.', 'wp-simple-firewall' ), 'ShieldPRO' ) );
 
 
 
 
 
235
  }
236
  break;
237
 
239
  $name = __( 'Automatic File Repair', 'wp-simple-firewall' );
240
  $summary = __( 'Automatically Repair Files That Have Changes Or Malware Infection', 'wp-simple-firewall' );
241
  $desc = [
242
+ __( 'Will attempt to automatically repair files that have been changed, or infected with malware.', 'wp-simple-firewall' ),
243
  '- '.__( 'In the case of WordPress, original files will be downloaded from WordPress.org to repair any broken files.', 'wp-simple-firewall' ),
244
+ '- '.__( 'In the case of plugins & themes, only those installed from WordPress.org can be repaired.', 'wp-simple-firewall' ),
245
  sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ), __( "Auto-Repair will never automatically delete new or unrecognised files.", 'wp-simple-firewall' ) )
246
  .' '.__( "Unrecognised files will need to be manually deleted.", 'wp-simple-firewall' ),
247
  ];
src/lib/src/Modules/HackGuard/UI.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
@@ -14,6 +14,9 @@ class UI extends BaseShield\UI {
14
  /** @var Options $opts */
15
  $opts = $this->getOptions();
16
 
 
 
 
17
  foreach ( $opts->getScanSlugs() as $scan ) {
18
  $mod->getScanCon( $scan )->cleanStalesResults();
19
  }
@@ -22,7 +25,6 @@ class UI extends BaseShield\UI {
22
  $sectionBuilderThemes = ( new Render\ScanResults\SectionThemes() )->setMod( $this->getMod() );
23
  $sectionBuilderWordpress = ( new Render\ScanResults\SectionWordpress() )->setMod( $this->getMod() );
24
  $sectionBuilderMalware = ( new Render\ScanResults\SectionMalware() )->setMod( $this->getMod() );
25
- // $sectionBuilderLog = ( new Render\ScanResults\SectionMalware() )->setMod( $this->getMod() );
26
 
27
  // Can Scan Checks:
28
  $reasonsCantScan = $mod->getScansCon()->getReasonsScansCantExecute();
@@ -41,17 +43,11 @@ class UI extends BaseShield\UI {
41
  'not_available' => __( 'Sorry, this scan is not available.', 'wp-simple-firewall' ),
42
  'not_enabled' => __( 'This scan is not currently enabled.', 'wp-simple-firewall' ),
43
  'please_enable' => __( 'Please turn on this scan in the options.', 'wp-simple-firewall' ),
44
- 'click_see_results' => __( 'Click a scan to see its results', 'wp-simple-firewall' ),
45
- 'title_scan_site_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
46
  'title_scan_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
47
  'subtitle_scan_now' => __( 'Run the selected scans on your site now to get the latest results', 'wp-simple-firewall' ),
48
  'more_items_longer' => __( 'The more scans that are selected, the longer the scan may take.', 'wp-simple-firewall' ),
49
  'scan_options' => __( 'Scan Options', 'wp-simple-firewall' ),
50
- 'scanselect' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
51
- 'scanselect_file_areas' => __( 'Select File Scans To Run', 'wp-simple-firewall' ),
52
- 'scanselect_assets' => __( 'Select Scans For Plugins and Themes', 'wp-simple-firewall' ),
53
  'select_view_results' => __( 'View Scan Results', 'wp-simple-firewall' ),
54
- 'select_what_to_scan' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
55
  'clear_ignore' => __( 'Clear Ignore Flags', 'wp-simple-firewall' ),
56
  'clear_ignore_sub' => __( 'Previously ignored results will be revealed (for the selected scans only)', 'wp-simple-firewall' ),
57
  'clear_suppression' => __( 'Remove Notification Suppression', 'wp-simple-firewall' ),
@@ -103,12 +99,10 @@ class UI extends BaseShield\UI {
103
  public function buildInsightsVars_Run() :array {
104
  /** @var ModCon $mod */
105
  $mod = $this->getMod();
106
- /** @var Options $opts */
107
- $opts = $this->getOptions();
108
 
109
- foreach ( $opts->getScanSlugs() as $scan ) {
110
- $mod->getScanCon( $scan )->cleanStalesResults();
111
- }
112
 
113
  // Can Scan Checks:
114
  $reasonsCantScan = $mod->getScansCon()->getReasonsScansCantExecute();
@@ -127,17 +121,12 @@ class UI extends BaseShield\UI {
127
  'not_available' => __( 'Sorry, this scan is not available.', 'wp-simple-firewall' ),
128
  'not_enabled' => __( 'This scan is not currently enabled.', 'wp-simple-firewall' ),
129
  'please_enable' => __( 'Please turn on this scan in the options.', 'wp-simple-firewall' ),
130
- 'click_see_results' => __( 'Click a scan to see its results', 'wp-simple-firewall' ),
131
- 'title_scan_site_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
132
  'title_scan_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
133
  'subtitle_scan_now' => __( 'Run the selected scans on your site now to get the latest results', 'wp-simple-firewall' ),
134
  'more_items_longer' => __( 'The more scans that are selected, the longer the scan may take.', 'wp-simple-firewall' ),
135
  'scan_options' => __( 'Scan Options', 'wp-simple-firewall' ),
136
  'scanselect' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
137
- 'scanselect_file_areas' => __( 'Select File Scans To Run', 'wp-simple-firewall' ),
138
- 'scanselect_assets' => __( 'Select Scans For Plugins and Themes', 'wp-simple-firewall' ),
139
  'select_view_results' => __( 'View Scan Results', 'wp-simple-firewall' ),
140
- 'select_what_to_scan' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
141
  'clear_ignore' => __( 'Clear Ignore Flags', 'wp-simple-firewall' ),
142
  'clear_ignore_sub' => __( 'Previously ignored results will be revealed (for the selected scans only)', 'wp-simple-firewall' ),
143
  'clear_suppression' => __( 'Remove Notification Suppression', 'wp-simple-firewall' ),
@@ -186,9 +175,6 @@ class UI extends BaseShield\UI {
186
  'is_selected' => $scanCon->isReady()
187
  && in_array( $slug, $mod->getUiTrack()->selected_scans ),
188
  ],
189
- 'hrefs' => [
190
- 'options' => $mod->getUrl_DirectLinkToSection( 'section_scan_'.$slug ),
191
- ],
192
  'strings' => [
193
  'title' => $scanStrings[ $slug ][ 'name' ],
194
  'subtitle' => $scanStrings[ $slug ][ 'subtitle' ],
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
14
  /** @var Options $opts */
15
  $opts = $this->getOptions();
16
 
17
+ ( new Scan\Queue\CleanQueue() )
18
+ ->setMod( $this->getMod() )
19
+ ->execute();
20
  foreach ( $opts->getScanSlugs() as $scan ) {
21
  $mod->getScanCon( $scan )->cleanStalesResults();
22
  }
25
  $sectionBuilderThemes = ( new Render\ScanResults\SectionThemes() )->setMod( $this->getMod() );
26
  $sectionBuilderWordpress = ( new Render\ScanResults\SectionWordpress() )->setMod( $this->getMod() );
27
  $sectionBuilderMalware = ( new Render\ScanResults\SectionMalware() )->setMod( $this->getMod() );
 
28
 
29
  // Can Scan Checks:
30
  $reasonsCantScan = $mod->getScansCon()->getReasonsScansCantExecute();
43
  'not_available' => __( 'Sorry, this scan is not available.', 'wp-simple-firewall' ),
44
  'not_enabled' => __( 'This scan is not currently enabled.', 'wp-simple-firewall' ),
45
  'please_enable' => __( 'Please turn on this scan in the options.', 'wp-simple-firewall' ),
 
 
46
  'title_scan_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
47
  'subtitle_scan_now' => __( 'Run the selected scans on your site now to get the latest results', 'wp-simple-firewall' ),
48
  'more_items_longer' => __( 'The more scans that are selected, the longer the scan may take.', 'wp-simple-firewall' ),
49
  'scan_options' => __( 'Scan Options', 'wp-simple-firewall' ),
 
 
 
50
  'select_view_results' => __( 'View Scan Results', 'wp-simple-firewall' ),
 
51
  'clear_ignore' => __( 'Clear Ignore Flags', 'wp-simple-firewall' ),
52
  'clear_ignore_sub' => __( 'Previously ignored results will be revealed (for the selected scans only)', 'wp-simple-firewall' ),
53
  'clear_suppression' => __( 'Remove Notification Suppression', 'wp-simple-firewall' ),
99
  public function buildInsightsVars_Run() :array {
100
  /** @var ModCon $mod */
101
  $mod = $this->getMod();
 
 
102
 
103
+ ( new Scan\Queue\CleanQueue() )
104
+ ->setMod( $this->getMod() )
105
+ ->execute();
106
 
107
  // Can Scan Checks:
108
  $reasonsCantScan = $mod->getScansCon()->getReasonsScansCantExecute();
121
  'not_available' => __( 'Sorry, this scan is not available.', 'wp-simple-firewall' ),
122
  'not_enabled' => __( 'This scan is not currently enabled.', 'wp-simple-firewall' ),
123
  'please_enable' => __( 'Please turn on this scan in the options.', 'wp-simple-firewall' ),
 
 
124
  'title_scan_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
125
  'subtitle_scan_now' => __( 'Run the selected scans on your site now to get the latest results', 'wp-simple-firewall' ),
126
  'more_items_longer' => __( 'The more scans that are selected, the longer the scan may take.', 'wp-simple-firewall' ),
127
  'scan_options' => __( 'Scan Options', 'wp-simple-firewall' ),
128
  'scanselect' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
 
 
129
  'select_view_results' => __( 'View Scan Results', 'wp-simple-firewall' ),
 
130
  'clear_ignore' => __( 'Clear Ignore Flags', 'wp-simple-firewall' ),
131
  'clear_ignore_sub' => __( 'Previously ignored results will be revealed (for the selected scans only)', 'wp-simple-firewall' ),
132
  'clear_suppression' => __( 'Remove Notification Suppression', 'wp-simple-firewall' ),
175
  'is_selected' => $scanCon->isReady()
176
  && in_array( $slug, $mod->getUiTrack()->selected_scans ),
177
  ],
 
 
 
178
  'strings' => [
179
  'title' => $scanStrings[ $slug ][ 'name' ],
180
  'subtitle' => $scanStrings[ $slug ][ 'subtitle' ],
src/lib/src/Modules/HackGuard/Upgrade.php CHANGED
@@ -3,17 +3,23 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
- use FernleafSystems\Wordpress\Services\Services;
7
 
8
  class Upgrade extends Base\Upgrade {
9
 
10
- protected function upgrade_1021() {
11
  /** @var ModCon $mod */
12
  $mod = $this->getMod();
13
- $schema = $mod->getDbHandler_FileLocker()->getTableSchema();
14
- Services::WpDb()->doSql(
15
- sprintf( "ALTER TABLE `%s` MODIFY `%s` %s;",
16
- $schema->table, 'content', $schema->enumerateColumns()[ 'content' ] )
17
- );
 
 
 
 
 
 
18
  }
19
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Afs;
7
 
8
  class Upgrade extends Base\Upgrade {
9
 
10
+ protected function upgrade_1300() {
11
  /** @var ModCon $mod */
12
  $mod = $this->getMod();
13
+
14
+ ( new Scan\Utilities\ConvertLegacyResults() )
15
+ ->setMod( $mod )
16
+ ->execute();
17
+
18
+ // Ensure AFS scan is selected by default upon upgrade
19
+ $uiTrack = $mod->getUiTrack();
20
+ $selected = $uiTrack->selected_scans;
21
+ $selected[] = Afs::SCAN_SLUG;
22
+ $uiTrack->selected_scans = $selected;
23
+ $mod->setUiTrack( $uiTrack );
24
  }
25
  }
src/lib/src/Modules/HackGuard/WpCli.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class WpCli extends Base\WpCli {
8
+
9
+ /**
10
+ * @inheritDoc
11
+ */
12
+ protected function getCmdHandlers() :array {
13
+ return [
14
+ new WpCli\ScanRun()
15
+ ];
16
+ }
17
+ }
src/lib/src/Modules/HackGuard/WpCli/ScanRun.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\WpCli;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\{
6
+ ModCon,
7
+ Options
8
+ };
9
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
10
+ use WP_CLI;
11
+
12
+ class ScanRun extends Base\WpCli\BaseWpCliCmd {
13
+
14
+ /**
15
+ * @throws \Exception
16
+ */
17
+ protected function addCmds() {
18
+ /** @var ModCon $mod */
19
+ $mod = $this->getMod();
20
+ /** @var Options $opts */
21
+ $opts = $this->getOptions();
22
+
23
+ $params = [];
24
+ foreach ( $opts->getScanSlugs() as $scanSlug ) {
25
+ $sCon = $mod->getScanCon( $scanSlug );
26
+ $params[] = [
27
+ 'type' => 'flag',
28
+ 'name' => $scanSlug,
29
+ 'optional' => true,
30
+ 'description' => sprintf( '%s: %s', __( 'Run Scan' ), $sCon->getScanName() ),
31
+ ];
32
+ }
33
+
34
+ WP_CLI::add_command(
35
+ $this->buildCmd( [ 'scan_run' ] ),
36
+ [ $this, 'cmdScanRun' ], $this->mergeCommonCmdArgs( [
37
+ 'shortdesc' => 'Run All Shield Scans',
38
+ 'synopsis' => array_merge( [
39
+ [
40
+ 'type' => 'flag',
41
+ 'name' => 'all',
42
+ 'optional' => true,
43
+ 'description' => 'Run all available scans.',
44
+ ]
45
+ ], $params )
46
+ ] ) );
47
+ }
48
+
49
+ /**
50
+ * @throws WP_CLI\ExitException
51
+ */
52
+ public function cmdScanRun( array $null, array $args ) {
53
+ /** @var ModCon $mod */
54
+ $mod = $this->getMod();
55
+ /** @var Options $opts */
56
+ $opts = $this->getOptions();
57
+ $availableScans = $opts->getScanSlugs();
58
+
59
+ $scans = ( $args[ 'all' ] ?? false ) ? $availableScans : array_keys( $args );
60
+
61
+ if ( empty( $scans ) ) {
62
+ WP_CLI::error( sprintf( 'Please specify scans to run. Use `--all` or specify any of: `--%s`',
63
+ implode( '`, `--', $availableScans ) ) );
64
+ }
65
+
66
+ $mod->getScansCon()->startNewScans( $scans );
67
+ }
68
+ }
src/lib/src/Modules/IPs/AjaxHandler.php CHANGED
@@ -4,6 +4,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Request\FormParams;
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops;
8
  use FernleafSystems\Wordpress\Services\Services;
9
  use FernleafSystems\Wordpress\Services\Utilities\Net\IpID;
@@ -33,6 +34,10 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
33
  $response = $this->ajaxExec_IpAnalyseAction();
34
  break;
35
 
 
 
 
 
36
  case 'not_bot':
37
  $response = $this->ajaxExec_CaptureNotBot();
38
  break;
@@ -194,6 +199,27 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
194
  ];
195
  }
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  private function ajaxExec_IpAnalyseAction() :array {
198
  $req = Services::Request();
199
 
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Request\FormParams;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\IpAnalyse\FindAllPluginIps;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops;
9
  use FernleafSystems\Wordpress\Services\Services;
10
  use FernleafSystems\Wordpress\Services\Utilities\Net\IpID;
34
  $response = $this->ajaxExec_IpAnalyseAction();
35
  break;
36
 
37
+ case 'ip_review_select':
38
+ $response = $this->ajaxExec_IpReviewSelect();
39
+ break;
40
+
41
  case 'not_bot':
42
  $response = $this->ajaxExec_CaptureNotBot();
43
  break;
199
  ];
200
  }
201
 
202
+ private function ajaxExec_IpReviewSelect() :array {
203
+ $req = Services::Request();
204
+
205
+ $filter = preg_replace( '#[^0-9a-f:.]#', '', strtolower( (string)$req->post( 'search' ) ) );
206
+ $ips = ( new FindAllPluginIps() )
207
+ ->setCon( $this->getCon() )
208
+ ->run( $filter );
209
+
210
+ return [
211
+ 'success' => true,
212
+ 'ips' => array_map( function ( $ip ) {
213
+ return [
214
+ 'id' => $ip,
215
+ 'text' => $ip
216
+ ];
217
+ }, $ips ),
218
+ 'message' => '',
219
+ 'page_reload' => false,
220
+ ];
221
+ }
222
+
223
  private function ajaxExec_IpAnalyseAction() :array {
224
  $req = Services::Request();
225
 
src/lib/src/Modules/IPs/Components/ProcessOffense.php CHANGED
@@ -62,7 +62,15 @@ class ProcessOffense {
62
  if ( $toBlock ) {
63
  $updater = $mod->getDbHandler_IPs()->getQueryUpdater();
64
  $updater->setBlocked( $IP );
65
- $con->fireEvent( 'ip_offense', [ 'suppress_audit' => true ] );
 
 
 
 
 
 
 
 
66
  }
67
  }
68
  }
62
  if ( $toBlock ) {
63
  $updater = $mod->getDbHandler_IPs()->getQueryUpdater();
64
  $updater->setBlocked( $IP );
65
+ $con->fireEvent( 'ip_offense',
66
+ [
67
+ 'suppress_audit' => true,
68
+ 'audit_params' => [
69
+ 'from' => $currentCount,
70
+ 'to' => $newCount,
71
+ ]
72
+ ]
73
+ );
74
  }
75
  }
76
  }
src/lib/src/Modules/IPs/Lib/IpAnalyse/BuildDisplay.php CHANGED
@@ -292,9 +292,6 @@ class BuildDisplay {
292
  $requests[ $key ] = $asArray;
293
  }
294
 
295
- // remove duds after conversion @12.0
296
- $requests = array_filter( $requests );
297
-
298
  return $this->getMod()->renderTemplate(
299
  '/wpadmin_pages/insights/ips/ip_analyse/ip_traffic.twig',
300
  [
292
  $requests[ $key ] = $asArray;
293
  }
294
 
 
 
 
295
  return $this->getMod()->renderTemplate(
296
  '/wpadmin_pages/insights/ips/ip_analyse/ip_traffic.twig',
297
  [
src/lib/src/Modules/IPs/Lib/IpAnalyse/FindAllPluginIps.php CHANGED
@@ -11,7 +11,7 @@ class FindAllPluginIps {
11
 
12
  use PluginControllerConsumer;
13
 
14
- public function run() :array {
15
  $con = $this->getCon();
16
 
17
  // User Sessions
@@ -34,6 +34,12 @@ class FindAllPluginIps {
34
  ->getQuerySelector();
35
  $ips = array_merge( $ips, $sel->getDistinctForColumn( 'ip' ) );
36
 
37
- return IpListSort::Sort( array_unique( $ips ) );
 
 
 
 
 
 
38
  }
39
  }
11
 
12
  use PluginControllerConsumer;
13
 
14
+ public function run( string $ipFilter = '' ) :array {
15
  $con = $this->getCon();
16
 
17
  // User Sessions
34
  ->getQuerySelector();
35
  $ips = array_merge( $ips, $sel->getDistinctForColumn( 'ip' ) );
36
 
37
+ $ips = array_unique( $ips );
38
+ if ( !empty( $ipFilter ) ) {
39
+ $ips = array_filter( $ips, function ( $ip ) use ( $ipFilter ) {
40
+ return is_int( strpos( $ip, $ipFilter ) );
41
+ } );
42
+ }
43
+ return IpListSort::Sort( $ips );
44
  }
45
  }
src/lib/src/Modules/IPs/Lib/OffenseTracker.php CHANGED
@@ -16,12 +16,7 @@ class OffenseTracker extends EventsListener {
16
  */
17
  private $nOffenseCount = 0;
18
 
19
- /**
20
- * @param string $evt
21
- * @param array $meta
22
- * @param array $def
23
- */
24
- protected function captureEvent( string $evt, $meta = [], $def = [] ) {
25
  if ( !empty( $def[ 'offense' ] ) && empty( $meta[ 'suppress_offense' ] ) ) {
26
  $this->incrementCount( (int)( $meta[ 'offense_count' ] ?? 1 ) );
27
  if ( !empty( $meta[ 'block' ] ) ) {
@@ -52,7 +47,6 @@ class OffenseTracker extends EventsListener {
52
  }
53
 
54
  /**
55
- * @param int $increment
56
  * @return $this
57
  */
58
  public function incrementCount( int $increment = 1 ) {
@@ -60,7 +54,6 @@ class OffenseTracker extends EventsListener {
60
  }
61
 
62
  /**
63
- * @param int $offenseCount
64
  * @return $this
65
  */
66
  public function setOffenseCount( int $offenseCount ) {
16
  */
17
  private $nOffenseCount = 0;
18
 
19
+ protected function captureEvent( string $evt, array $meta = [], array $def = [] ) {
 
 
 
 
 
20
  if ( !empty( $def[ 'offense' ] ) && empty( $meta[ 'suppress_offense' ] ) ) {
21
  $this->incrementCount( (int)( $meta[ 'offense_count' ] ?? 1 ) );
22
  if ( !empty( $meta[ 'block' ] ) ) {
47
  }
48
 
49
  /**
 
50
  * @return $this
51
  */
52
  public function incrementCount( int $increment = 1 ) {
54
  }
55
 
56
  /**
 
57
  * @return $this
58
  */
59
  public function setOffenseCount( int $offenseCount ) {
src/lib/src/Modules/IPs/Lib/Ops/ConvertLegacy.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\IPs\IPRecords;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\DB\BotSignal;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
10
- use FernleafSystems\Wordpress\Services\Services;
11
-
12
- class ConvertLegacy {
13
-
14
- use ModConsumer;
15
-
16
- public function run() {
17
- /** @var ModCon $mod */
18
- $mod = $this->getMod();
19
- $opts = $this->getOptions();
20
-
21
- if ( empty( $opts->getOpt( 'legacy_db_deleted_at' ) ) ) {
22
- $this->convert();
23
- $dbh = $mod->getDbHandler_BotSignals();
24
- if ( $dbh->getQuerySelector()->count() === 0 ) {
25
- $opts->setOpt( 'legacy_db_deleted_at', Services::Request()->ts() );
26
- $dbh->tableDelete();
27
- }
28
- }
29
- }
30
-
31
- private function convert() {
32
- /** @var ModCon $mod */
33
- $mod = $this->getMod();
34
- $dbh = $mod->getDbHandler_BotSignals();
35
-
36
- $toDelete = [];
37
-
38
- /** @var BotSignals\EntryVO $entry */
39
- foreach ( $dbh->getIterator() as $entry ) {
40
-
41
- try {
42
- $this->createPrimaryLogRecord( $entry );
43
- }
44
- catch ( \Exception $e ) {
45
- }
46
- finally {
47
- $toDelete[] = $entry->id;
48
- }
49
- }
50
-
51
- if ( !empty( $toDelete ) ) {
52
- $dbh->getQueryDeleter()
53
- ->addWhereIn( 'in', $toDelete )
54
- ->query();
55
- }
56
- }
57
-
58
- /**
59
- * @param BotSignals\EntryVO $entry
60
- * @return bool
61
- * @throws \Exception
62
- */
63
- protected function createPrimaryLogRecord( BotSignals\EntryVO $entry ) :bool {
64
- /** @var ModCon $mod */
65
- $mod = $this->getMod();
66
- $dbh = $mod->getDbH_BotSignal();
67
-
68
- if ( empty( $entry->ip ) ) {
69
- throw new \Exception( 'No IP' );
70
- }
71
-
72
- $ipRecord = ( new IPRecords() )
73
- ->setMod( $this->getCon()->getModule_Data() )
74
- ->loadIP( $entry->ip );
75
- unset( $entry->ip );
76
-
77
- /** @var BotSignal\Ops\Select $selector */
78
- $selector = $dbh->getQuerySelector();
79
- if ( $selector->filterByIP( $ipRecord->id )->count() > 0 ) {
80
- throw new \Exception( 'Record already exists' );
81
- }
82
-
83
- /** @var BotSignal\Ops\Record $record */
84
- $record = $dbh->getRecord()->applyFromArray( $entry->getRawData() );
85
- unset( $record->id );
86
- $record->ip_ref = $ipRecord->id;
87
-
88
- $success = $mod->getDbH_BotSignal()
89
- ->getQueryInserter()
90
- ->insert( $record );
91
- if ( !$success ) {
92
- throw new \Exception( 'Failed to insert' );
93
- }
94
-
95
- return true;
96
- }
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/IPs/ModCon.php CHANGED
@@ -157,7 +157,7 @@ class ModCon extends BaseShield\ModCon {
157
  }
158
 
159
  /**
160
- * @deprecated 12.0
161
  */
162
  protected function cleanupDatabases() {
163
  $dbhIPs = $this->getDbHandler_IPs();
@@ -172,11 +172,4 @@ class ModCon extends BaseShield\ModCon {
172
  )
173
  ->query();
174
  }
175
-
176
- /**
177
- * @deprecated 12.0
178
- */
179
- public function getDbHandler_BotSignals() :Shield\Databases\BotSignals\Handler {
180
- return $this->getDbH( 'botsignals' );
181
- }
182
  }
157
  }
158
 
159
  /**
160
+ * @deprecated 12.1
161
  */
162
  protected function cleanupDatabases() {
163
  $dbhIPs = $this->getDbHandler_IPs();
172
  )
173
  ->query();
174
  }
 
 
 
 
 
 
 
175
  }
src/lib/src/Modules/IPs/UI.php CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot\TestNotBotLoading;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\IpAnalyse\FindAllPluginIps;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\RetrieveIpsForLists;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
@@ -126,6 +125,7 @@ class UI extends BaseShield\UI {
126
  'ajax' => [
127
  'build_ip_analyse' => $mod->getAjaxActionData( 'build_ip_analyse', true ),
128
  'ip_analyse_action' => $mod->getAjaxActionData( 'ip_analyse_action', true ),
 
129
  ],
130
  'strings' => [
131
  'select_ip' => __( 'Select IP To Analyse', 'wp-simple-firewall' ),
@@ -134,9 +134,7 @@ class UI extends BaseShield\UI {
134
  'please_select' => 'Please select an IP address.',
135
  ],
136
  'vars' => [
137
- 'unique_ips' => ( new FindAllPluginIps() )
138
- ->setCon( $this->getCon() )
139
- ->run()
140
  ]
141
  ],
142
  true
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot\TestNotBotLoading;
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\RetrieveIpsForLists;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
125
  'ajax' => [
126
  'build_ip_analyse' => $mod->getAjaxActionData( 'build_ip_analyse', true ),
127
  'ip_analyse_action' => $mod->getAjaxActionData( 'ip_analyse_action', true ),
128
+ 'ip_review_select' => $mod->getAjaxActionData( 'ip_review_select', true ),
129
  ],
130
  'strings' => [
131
  'select_ip' => __( 'Select IP To Analyse', 'wp-simple-firewall' ),
134
  'please_select' => 'Please select an IP address.',
135
  ],
136
  'vars' => [
137
+ 'unique_ips' => []
 
 
138
  ]
139
  ],
140
  true
src/lib/src/Modules/IPs/Upgrade.php CHANGED
@@ -7,17 +7,4 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
 
8
  class Upgrade extends Base\Upgrade {
9
 
10
- protected function upgrade_1201() {
11
- ( new Lib\Ops\ConvertLegacy() )
12
- ->setMod( $this->getMod() )
13
- ->run();
14
- }
15
-
16
- protected function upgrade_1010() {
17
- /** @var ModCon $mod */
18
- $mod = $this->getMod();
19
- /** @var Delete $del */
20
- $del = $mod->getDbHandler_IPs()->getQueryDeleter();
21
- $del->filterByLabel( 'iControlWP' )->query();
22
- }
23
  }
7
 
8
  class Upgrade extends Base\Upgrade {
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
src/lib/src/Modules/Insights/Lib/SummaryCards.php CHANGED
@@ -3,9 +3,7 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\{
7
- Wcf
8
- };
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
10
 
11
  class SummaryCards {
@@ -108,9 +106,9 @@ class SummaryCards {
108
  'href' => $mod->getUrl_DirectLinkToOption( 'enable_hack_protect' ),
109
  ],
110
  'core_files' => [
111
- 'title' => 'Core File Scan',
112
  'enabled' => $mod->isModuleEnabled()
113
- && $mod->getScanCon( Wcf::SCAN_SLUG )->isEnabled(),
114
  'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
115
  ]
116
  ];
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Afs;
 
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
 
9
  class SummaryCards {
106
  'href' => $mod->getUrl_DirectLinkToOption( 'enable_hack_protect' ),
107
  ],
108
  'core_files' => [
109
+ 'title' => 'WordPress File Scan',
110
  'enabled' => $mod->isModuleEnabled()
111
+ && $mod->getScanCon( Afs::SCAN_SLUG )->isEnabled(),
112
  'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
113
  ]
114
  ];
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Yubikey.php CHANGED
@@ -48,70 +48,7 @@ class Yubikey extends BaseProvider {
48
  ];
49
  }
50
 
51
- /**
52
- * @inheritDoc
53
- */
54
- public function handleUserProfileSubmit( \WP_User $user ) {
55
-
56
- // If it's your own account, you CANT do anything without your OTP (except turn off via email).
57
- $sOtpOrDeviceId = trim( (string)$this->fetchCodeFromRequest() );
58
- if ( empty( $sOtpOrDeviceId ) ) {
59
- return;
60
- }
61
-
62
- $bError = true;
63
- $aRegisteredDevices = $this->getYubiIds( $user );
64
-
65
- if ( strlen( $sOtpOrDeviceId ) < self::OTP_LENGTH ) {
66
- $sMsg = __( 'The Yubikey device ID was not valid.', 'wp-simple-firewall' )
67
- .' '.__( 'Please try again.', 'wp-simple-firewall' );
68
- }
69
- else {
70
- $sDeviceId = substr( $sOtpOrDeviceId, 0, self::OTP_LENGTH );
71
- $bDeviceRegistered = in_array( $sDeviceId, $aRegisteredDevices );
72
-
73
- if ( $bDeviceRegistered || strlen( $sOtpOrDeviceId ) == self::OTP_LENGTH ) { // attempt to remove device
74
-
75
- if ( $bDeviceRegistered ) {
76
- $this->addRemoveRegisteredYubiId( $user, $sDeviceId, false );
77
- $sMsg = sprintf(
78
- __( '%s was removed from your profile.', 'wp-simple-firewall' ),
79
- __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $sDeviceId )
80
- );
81
- $bError = false;
82
- }
83
- else {
84
- $sMsg = __( "That Yubikey device ID wasn't found on your profile", 'wp-simple-firewall' );
85
- }
86
- }
87
- elseif ( $this->sendYubiOtpRequest( $sOtpOrDeviceId ) ) { // A full OTP was provided so we're adding a new one
88
- if ( count( $aRegisteredDevices ) == 0 || $this->getCon()->isPremiumActive() ) {
89
- $this->addRemoveRegisteredYubiId( $user, $sDeviceId, true );
90
- $sMsg = sprintf(
91
- __( '%s was added to your profile.', 'wp-simple-firewall' ),
92
- __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $sDeviceId )
93
- );
94
- $bError = false;
95
- }
96
- else {
97
- $sMsg = __( 'No further Yubikey devices may be added to your account at this time.', 'wp-simple-firewall' );
98
- }
99
- }
100
- else {
101
- $sMsg = __( 'One Time Password (OTP) was not valid.', 'wp-simple-firewall' )
102
- .' '.__( 'Please try again.', 'wp-simple-firewall' );
103
- }
104
- }
105
-
106
- $this->setProfileValidated( $user, $this->hasValidSecret( $user ) );
107
- $this->getMod()->setFlashAdminNotice( $sMsg, $bError );
108
- }
109
-
110
- /**
111
- * @param \WP_User $user
112
- * @return array
113
- */
114
- private function getYubiIds( \WP_User $user ) {
115
  return array_filter( array_map( 'trim', explode( ',', $this->getSecret( $user ) ) ) );
116
  }
117
 
@@ -131,11 +68,7 @@ class Yubikey extends BaseProvider {
131
  return $valid;
132
  }
133
 
134
- /**
135
- * @param string $otp
136
- * @return bool
137
- */
138
- private function sendYubiOtpRequest( $otp ) {
139
  /** @var LoginGuard\Options $opts */
140
  $opts = $this->getOptions();
141
  $otp = trim( $otp );
@@ -166,31 +99,51 @@ class Yubikey extends BaseProvider {
166
  return $success;
167
  }
168
 
169
- public function toggleRegisteredYubiID( \WP_User $user, string $key ) :StdResponse {
170
  $response = new StdResponse();
171
  $response->success = true;
172
 
173
- if ( strlen( $key ) > self::OTP_LENGTH ) {
174
- $key = substr( $key, 0, self::OTP_LENGTH );
 
175
  }
176
- $IDs = $this->getYubiIds( $user );
177
-
178
- if ( in_array( $key, $IDs ) ) {
179
- $IDs = Services::DataManipulation()->removeFromArrayByValue( $IDs, $key );
180
- $response->msg_text = sprintf(
181
- __( '%s was removed from your profile.', 'wp-simple-firewall' ),
182
- __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $key )
183
- );
184
  }
185
  else {
186
- $IDs[] = $key;
187
- $response->msg_text = sprintf(
188
- __( '%s was added to your profile.', 'wp-simple-firewall' ),
189
- __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $key )
190
- );
191
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
- $this->setSecret( $user, implode( ',', array_unique( array_filter( $IDs ) ) ) );
 
194
 
195
  return $response;
196
  }
@@ -202,19 +155,6 @@ class Yubikey extends BaseProvider {
202
  * @return $this
203
  */
204
  public function addRemoveRegisteredYubiId( \WP_User $user, string $key, $add = true ) {
205
- $IDs = $this->getYubiIds( $user );
206
-
207
- if ( strlen( $key ) > self::OTP_LENGTH ) {
208
- $key = substr( $key, 0, self::OTP_LENGTH );
209
- }
210
-
211
- if ( $add ) {
212
- $IDs[] = $key;
213
- }
214
- else {
215
- $IDs = Services::DataManipulation()->removeFromArrayByValue( $IDs, $key );
216
- }
217
- return $this->setSecret( $user, implode( ',', array_unique( array_filter( $IDs ) ) ) );
218
  }
219
 
220
  /**
48
  ];
49
  }
50
 
51
+ private function getYubiIds( \WP_User $user ) :array {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  return array_filter( array_map( 'trim', explode( ',', $this->getSecret( $user ) ) ) );
53
  }
54
 
68
  return $valid;
69
  }
70
 
71
+ private function sendYubiOtpRequest( string $otp ) :bool {
 
 
 
 
72
  /** @var LoginGuard\Options $opts */
73
  $opts = $this->getOptions();
74
  $otp = trim( $otp );
99
  return $success;
100
  }
101
 
102
+ public function toggleRegisteredYubiID( \WP_User $user, string $keyOrOTP ) :StdResponse {
103
  $response = new StdResponse();
104
  $response->success = true;
105
 
106
+ if ( empty( $keyOrOTP ) ) {
107
+ $response->success = false;
108
+ $response->error_text = 'One-Time Password was empty';
109
  }
110
+ elseif ( strlen( $keyOrOTP ) < self::OTP_LENGTH ) {
111
+ $response->success = false;
112
+ $response->error_text = 'One-Time Password was too short';
 
 
 
 
 
113
  }
114
  else {
115
+ $keyID = substr( $keyOrOTP, 0, self::OTP_LENGTH );
116
+ $IDs = $this->getYubiIds( $user );
117
+
118
+ if ( in_array( $keyID, $IDs ) ) {
119
+ $response->success = true;
120
+ $IDs = Services::DataManipulation()->removeFromArrayByValue( $IDs, $keyID );
121
+ $response->msg_text = sprintf(
122
+ __( '%s was removed from your profile.', 'wp-simple-firewall' ),
123
+ __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $keyID )
124
+ );
125
+ }
126
+ elseif ( !$this->sendYubiOtpRequest( $keyOrOTP ) ) {
127
+ // If we're going to add the device, we test it
128
+ $response->success = false;
129
+ $response->error_text = 'Failed to verify One-Time Password from device';
130
+ }
131
+ else {
132
+ $IDs[] = $keyID;
133
+ $response->msg_text = sprintf(
134
+ __( '%s was added to your profile.', 'wp-simple-firewall' ),
135
+ __( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $keyID )
136
+ );
137
+ }
138
+
139
+ if ( !$this->sendYubiOtpRequest( $keyOrOTP ) ) {
140
+ $response->success = false;
141
+ $response->error_text = 'One-Time Password verification failed';
142
+ }
143
+ $response->success = true;
144
 
145
+ $this->setSecret( $user, implode( ',', array_unique( array_filter( $IDs ) ) ) );
146
+ }
147
 
148
  return $response;
149
  }
155
  * @return $this
156
  */
157
  public function addRemoveRegisteredYubiId( \WP_User $user, string $key, $add = true ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
159
 
160
  /**
src/lib/src/Modules/Plugin/Lib/Debug/Collate.php CHANGED
@@ -185,7 +185,7 @@ class Collate {
185
  sprintf( '%s (rows: ~%s)', 'Ready', $dbh->getQuerySelector()->count() )
186
  : 'Missing';
187
 
188
- $dbh = $con->getModule_HackGuard()->getDbHandler_ScanResults();
189
  $data[ 'DB Table: Scan Results' ] = $dbh->isReady() ?
190
  sprintf( '%s (rows: ~%s)', 'Ready', $dbh->getQuerySelector()->count() )
191
  : 'Missing';
185
  sprintf( '%s (rows: ~%s)', 'Ready', $dbh->getQuerySelector()->count() )
186
  : 'Missing';
187
 
188
+ $dbh = $con->getModule_HackGuard()->getDbH_ScanResults();
189
  $data[ 'DB Table: Scan Results' ] = $dbh->isReady() ?
190
  sprintf( '%s (rows: ~%s)', 'Ready', $dbh->getQuerySelector()->count() )
191
  : 'Missing';
src/lib/src/Modules/Plugin/WpCli/Import.php CHANGED
@@ -98,8 +98,6 @@ class Import extends Base\WpCli\BaseWpCliCmd {
98
  }
99
 
100
  /**
101
- * @param string $path
102
- * @param bool $deleteFile
103
  * @throws \Exception
104
  */
105
  private function runImportFromFile( string $path, bool $deleteFile = false ) {
@@ -109,7 +107,6 @@ class Import extends Base\WpCli\BaseWpCliCmd {
109
  }
110
 
111
  /**
112
- * @param array $args
113
  * @throws \Exception
114
  */
115
  private function runImportFromSite( array $args ) {
98
  }
99
 
100
  /**
 
 
101
  * @throws \Exception
102
  */
103
  private function runImportFromFile( string $path, bool $deleteFile = false ) {
107
  }
108
 
109
  /**
 
110
  * @throws \Exception
111
  */
112
  private function runImportFromSite( array $args ) {
src/lib/src/Modules/SecurityAdmin/WpCli/Pin.php CHANGED
@@ -40,7 +40,7 @@ class Pin extends BaseWpCliCmd {
40
  */
41
  public function cmdPin( array $null, array $aA ) {
42
 
43
- $newPIN = isset( $aA[ 'set' ] ) ? $aA[ 'set' ] : null;
44
  $isRemove = WP_CLI\Utils\get_flag_value( $aA, 'remove', false );
45
 
46
  if ( !empty( $newPIN ) && !empty( $isRemove ) ) {
40
  */
41
  public function cmdPin( array $null, array $aA ) {
42
 
43
+ $newPIN = $aA[ 'set' ] ?? null;
44
  $isRemove = WP_CLI\Utils\get_flag_value( $aA, 'remove', false );
45
 
46
  if ( !empty( $newPIN ) && !empty( $isRemove ) ) {
src/lib/src/Modules/Sessions/Processor.php CHANGED
@@ -103,11 +103,4 @@ class Processor extends BaseShield\Processor {
103
  protected function getHookPriority() :int {
104
  return 100;
105
  }
106
-
107
- /**
108
- * @deprecated 12.0
109
- */
110
- public function onModuleShutdown() {
111
- parent::onModuleShutdown();
112
- }
113
  }
103
  protected function getHookPriority() :int {
104
  return 100;
105
  }
 
 
 
 
 
 
 
106
  }
src/lib/src/Modules/Traffic/Lib/Logger.php DELETED
@@ -1,84 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic\EntryVO;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
8
- use FernleafSystems\Wordpress\Services\Services;
9
-
10
- /**
11
- * @deprecated 12.0
12
- */
13
- class Logger {
14
-
15
- use ModConsumer;
16
-
17
- public function run() {
18
- /** @var Traffic\Options $opts */
19
- $opts = $this->getOptions();
20
- if ( $opts->isTrafficLoggerEnabled() ) {
21
- add_action( $this->getCon()->prefix( 'plugin_shutdown' ), function () {
22
- if ( $this->isRequestToBeLogged() ) {
23
- $this->logTraffic();
24
- }
25
- } );
26
- }
27
- }
28
-
29
- private function isRequestToBeLogged() :bool {
30
- return !$this->getCon()->plugin_deleting
31
- && apply_filters( 'shield/is_log_traffic',
32
- !$this->isCustomExcluded() && !$this->isRequestTypeExcluded()
33
- );
34
- }
35
-
36
- private function isRequestTypeExcluded() :bool {
37
- /** @var Traffic\Options $opts */
38
- $opts = $this->getOptions();
39
- $excl = $opts->getReqTypeExclusions();
40
- $bLoggedIn = Services::WpUsers()->isUserLoggedIn();
41
-
42
- $exclude = ( in_array( 'simple', $excl ) && count( Services::Request()->getRawRequestParams( false ) ) == 0 )
43
- || ( in_array( 'logged_in', $excl ) && $bLoggedIn )
44
- || ( in_array( 'ajax', $excl ) && Services::WpGeneral()->isAjax() )
45
- || ( in_array( 'cron', $excl ) && Services::WpGeneral()->isCron() );
46
-
47
- if ( !$exclude && !$bLoggedIn ) {
48
- $exclude = ( in_array( 'search', $excl ) && $this->isServiceIp_Search() )
49
- || ( in_array( 'uptime', $excl ) && $this->isServiceIp_Uptime() );
50
- }
51
-
52
- return $exclude;
53
- }
54
-
55
- private function isCustomExcluded() :bool {
56
- /** @var Traffic\Options $opts */
57
- $opts = $this->getOptions();
58
- $req = Services::Request();
59
-
60
- $agent = $req->getUserAgent();
61
- $path = $req->getPath().( empty( $_GET ) ? '' : '?'.http_build_query( $_GET ) );
62
-
63
- $exclude = false;
64
- foreach ( $opts->getCustomExclusions() as $excl ) {
65
- if ( stripos( $agent, $excl ) !== false || stripos( $path, $excl ) !== false ) {
66
- $exclude = true;
67
- }
68
- }
69
- return $exclude;
70
- }
71
-
72
- private function isServiceIp_Search() :bool {
73
- return in_array( Services::IP()->getIpDetector()->getIPIdentity(),
74
- Services::ServiceProviders()->getSearchProviders() );
75
- }
76
-
77
- private function isServiceIp_Uptime() :bool {
78
- return in_array( Services::IP()->getIpDetector()->getIPIdentity(),
79
- Services::ServiceProviders()->getUptimeProviders() );
80
- }
81
-
82
- private function logTraffic() {
83
- }
84
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/Traffic/Lib/Ops/ConvertLegacy.php DELETED
@@ -1,88 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\Ops;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\RequestRecords;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\ModCon;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\IPs\IPRecords;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
10
- use FernleafSystems\Wordpress\Services\Services;
11
-
12
- class ConvertLegacy {
13
-
14
- use ModConsumer;
15
-
16
- public function run() {
17
- /** @var ModCon $mod */
18
- $mod = $this->getMod();
19
- $opts = $this->getOptions();
20
-
21
- if ( empty( $opts->getOpt( 'legacy_db_deleted_at' ) ) ) {
22
- $this->convert();
23
- $dbh = $mod->getDbHandler_Traffic();
24
- if ( $dbh->getQuerySelector()->count() === 0 ) {
25
- $opts->setOpt( 'legacy_db_deleted_at', Services::Request()->ts() );
26
- $dbh->tableDelete();
27
- }
28
- }
29
- }
30
-
31
- private function convert() {
32
- /** @var ModCon $mod */
33
- $mod = $this->getMod();
34
- $dbh = $mod->getDbHandler_Traffic();
35
-
36
- $toDelete = [];
37
-
38
- /** @var Traffic\EntryVO $entry */
39
- foreach ( $dbh->getIterator() as $entry ) {
40
-
41
- try {
42
- $this->createPrimaryLogRecord( $entry );
43
- }
44
- catch ( \Exception $e ) {
45
- }
46
- finally {
47
- $toDelete[] = $entry->id;
48
- }
49
- }
50
-
51
- if ( !empty( $toDelete ) ) {
52
- $dbh->getQueryDeleter()
53
- ->addWhereIn( 'in', $toDelete )
54
- ->query();
55
- }
56
- }
57
-
58
- protected function createPrimaryLogRecord( Traffic\EntryVO $entry ) :bool {
59
- $modData = $this->getCon()->getModule_Data();
60
-
61
- if ( empty( $entry->rid ) || empty( $entry->ip ) ) {
62
- throw new \Exception( 'No RID or IP' );
63
- }
64
-
65
- $meta = [];
66
- foreach ( [ 'uid', 'path', 'code', 'verb', 'ua', 'trans', ] as $metaKey ) {
67
- if ( !empty( $entry->{$metaKey} ) ) {
68
- $meta[ ( $metaKey === 'trans' ) ? 'offense' : $metaKey ] = $entry->{$metaKey};
69
- }
70
- }
71
-
72
- $ipID = ( new IPRecords() )
73
- ->setMod( $modData )
74
- ->loadIP( $entry->ip )
75
- ->id;
76
- $record = ( new RequestRecords() )
77
- ->setMod( $modData )
78
- ->loadReq( $entry->rid, $ipID );
79
- $record->meta = $meta;
80
-
81
- return $modData->getDbH_ReqLogs()
82
- ->getQueryUpdater()
83
- ->updateById( $record->id, [
84
- 'meta' => $record->getRawData()[ 'meta' ],
85
- 'created_at' => $entry->created_at
86
- ] );
87
- }
88
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php CHANGED
@@ -8,7 +8,6 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LoadLogs;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LogRecord;
11
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\Ops\ConvertLegacy;
12
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
13
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseLoadTableData;
14
  use FernleafSystems\Wordpress\Services\Services;
@@ -32,21 +31,10 @@ class LoadRawTableData extends BaseLoadTableData {
32
  private $ipInfo = [];
33
 
34
  public function loadForLogs() :array {
35
- ( new ConvertLegacy() )
36
- ->setMod( $this->getMod() )
37
- ->run();
38
-
39
  $this->users = [ 0 => __( 'No', 'wp-simple-firewall' ) ];
40
 
41
  return array_values( array_filter( array_map(
42
  function ( $log ) {
43
- /**
44
- * @deprecated 12.0 - this just removes dud entries from after the conversion.
45
- */
46
- if ( empty( @$log->meta[ 'path' ] ) ) {
47
- return null;
48
- }
49
-
50
  $WPU = Services::WpUsers();
51
 
52
  $log->meta = array_merge(
@@ -120,13 +108,20 @@ class LoadRawTableData extends BaseLoadTableData {
120
  );
121
  }
122
 
123
- return sprintf( '<div>%s</div>', implode( '</div><div>', [
124
- sprintf( '%s: %s', __( 'IP', 'wp-simple-firewall' ), $this->getIpAnalysisLink( $this->log->ip ) ),
125
- sprintf( '%s: %s', __( 'IP Status', 'wp-simple-firewall' ), $this->getIpInfo( $this->log->ip ) ),
126
- sprintf( '%s: %s', __( 'Logged-In', 'wp-simple-firewall' ), $this->users[ $this->log->meta[ 'uid' ] ] ),
127
- sprintf( '%s: %s', __( 'Location', 'wp-simple-firewall' ), $country ),
128
- esc_html( esc_js( sprintf( '%s - %s', __( 'User Agent', 'wp-simple-firewall' ), $this->log->meta[ 'ua' ] ) ) ),
129
- ] ) );
 
 
 
 
 
 
 
130
  }
131
 
132
  private function getColumnContent_Response() :string {
@@ -154,9 +149,15 @@ class LoadRawTableData extends BaseLoadTableData {
154
  }
155
 
156
  private function getColumnContent_Page() :string {
157
- list( $preQuery, $query ) = explode( '?', $this->log->meta[ 'path' ].'?', 2 );
158
- return strtoupper( $this->log->meta[ 'verb' ] ).': <code>'.$preQuery
159
- .( empty( $query ) ? '' : '?<br/>'.rtrim( $query, '?' ) ).'</code>';
 
 
 
 
 
 
160
  }
161
 
162
  private function getIpInfo( string $ip ) {
@@ -208,4 +209,8 @@ class LoadRawTableData extends BaseLoadTableData {
208
  ->setIP( $ip )
209
  ->lookupIp();
210
  }
 
 
 
 
211
  }
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LoadLogs;
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LogRecord;
 
11
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
12
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\LoadData\BaseLoadTableData;
13
  use FernleafSystems\Wordpress\Services\Services;
31
  private $ipInfo = [];
32
 
33
  public function loadForLogs() :array {
 
 
 
 
34
  $this->users = [ 0 => __( 'No', 'wp-simple-firewall' ) ];
35
 
36
  return array_values( array_filter( array_map(
37
  function ( $log ) {
 
 
 
 
 
 
 
38
  $WPU = Services::WpUsers();
39
 
40
  $log->meta = array_merge(
108
  );
109
  }
110
 
111
+ if ( $this->isWpCli() ) {
112
+ $content = 'WP-CLI';
113
+ }
114
+ else {
115
+ $content = sprintf( '<div>%s</div>', implode( '</div><div>', [
116
+ sprintf( '%s: %s', __( 'IP', 'wp-simple-firewall' ), $this->getIpAnalysisLink( $this->log->ip ) ),
117
+ sprintf( '%s: %s', __( 'IP Status', 'wp-simple-firewall' ), $this->getIpInfo( $this->log->ip ) ),
118
+ sprintf( '%s: %s', __( 'Logged-In', 'wp-simple-firewall' ), $this->users[ $this->log->meta[ 'uid' ] ] ),
119
+ sprintf( '%s: %s', __( 'Location', 'wp-simple-firewall' ), $country ),
120
+ esc_html( esc_js( sprintf( '%s - %s', __( 'User Agent', 'wp-simple-firewall' ), $this->log->meta[ 'ua' ] ) ) ),
121
+ ] ) );
122
+ }
123
+
124
+ return $content;
125
  }
126
 
127
  private function getColumnContent_Response() :string {
149
  }
150
 
151
  private function getColumnContent_Page() :string {
152
+ if ( $this->isWpCli() ) {
153
+ $content = sprintf( '<code>:> %s</code>', esc_html( $this->log->meta[ 'path' ] ) );
154
+ }
155
+ else {
156
+ list( $preQuery, $query ) = explode( '?', $this->log->meta[ 'path' ].'?', 2 );
157
+ $content = strtoupper( $this->log->meta[ 'verb' ] ).': <code>'.$preQuery
158
+ .( empty( $query ) ? '' : '?<br/>'.rtrim( $query, '?' ) ).'</code>';
159
+ }
160
+ return $content;
161
  }
162
 
163
  private function getIpInfo( string $ip ) {
209
  ->setIP( $ip )
210
  ->lookupIp();
211
  }
212
+
213
+ private function isWpCli() :bool {
214
+ return $this->log->meta[ 'ua' ] === 'wpcli';
215
+ }
216
  }
src/lib/src/Modules/Traffic/ModCon.php CHANGED
@@ -43,24 +43,11 @@ class ModCon extends BaseShield\ModCon {
43
  && parent::isReadyToExecute();
44
  }
45
 
46
- /**
47
- * @deprecated 12.0
48
- */
49
- protected function cleanupDatabases() {
50
- }
51
-
52
  /**
53
  * @inheritDoc
54
- * @deprecated 12.0
55
  */
56
  public function getDbHandlers( $bInitAll = false ) {
57
- return [];
58
- }
59
-
60
- /**
61
- * @deprecated 12.0
62
- */
63
- public function getDbHandler_Traffic() :Databases\Traffic\Handler {
64
- return $this->getDbH( 'traffic' );
65
  }
66
  }
43
  && parent::isReadyToExecute();
44
  }
45
 
 
 
 
 
 
 
46
  /**
47
  * @inheritDoc
48
+ * @deprecated 12.1
49
  */
50
  public function getDbHandlers( $bInitAll = false ) {
51
+ return [];
 
 
 
 
 
 
 
52
  }
53
  }
src/lib/src/Modules/Traffic/Options.php CHANGED
@@ -41,11 +41,4 @@ class Options extends BaseShield\Options {
41
  return $this->isPremium() && $this->isTrafficLoggerEnabled() && $this->isOpt( 'enable_limiter', 'Y' )
42
  && ( $this->getLimitTimeSpan() > 0 ) && ( $this->getLimitRequestCount() > 0 );
43
  }
44
-
45
- /**
46
- * @deprecated 12.0
47
- */
48
- public function getMaxEntries() :int {
49
- return PHP_INT_MAX;
50
- }
51
  }
41
  return $this->isPremium() && $this->isTrafficLoggerEnabled() && $this->isOpt( 'enable_limiter', 'Y' )
42
  && ( $this->getLimitTimeSpan() > 0 ) && ( $this->getLimitRequestCount() > 0 );
43
  }
 
 
 
 
 
 
 
44
  }
src/lib/src/Modules/Traffic/UI.php CHANGED
@@ -2,7 +2,6 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Traffic\Select;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Tables\DataTables\Build\Traffic\ForTraffic;
8
  use FernleafSystems\Wordpress\Services\Services;
@@ -15,10 +14,6 @@ class UI extends BaseShield\UI {
15
  /** @var Options $opts */
16
  $opts = $this->getOptions();
17
 
18
- ( new Lib\Ops\ConvertLegacy() )
19
- ->setMod( $this->getMod() )
20
- ->run();
21
-
22
  return $mod->renderTemplate(
23
  '/wpadmin_pages/insights/traffic/traffic_table.twig',
24
  [
2
 
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
  use FernleafSystems\Wordpress\Services\Services;
14
  /** @var Options $opts */
15
  $opts = $this->getOptions();
16
 
 
 
 
 
17
  return $mod->renderTemplate(
18
  '/wpadmin_pages/insights/traffic/traffic_table.twig',
19
  [
src/lib/src/Modules/Traffic/Upgrade.php CHANGED
@@ -4,16 +4,4 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic;
4
 
5
  class Upgrade extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Upgrade {
6
 
7
- protected function upgrade_1200() {
8
- ( new Lib\Ops\ConvertLegacy() )
9
- ->setMod( $this->getMod() )
10
- ->run();
11
-
12
- // Add "This Server" as a default exclusion.
13
- /** @var Options $opts */
14
- $opts = $this->getOptions();
15
- $excl = $opts->getReqTypeExclusions();
16
- $excl[] = 'server';
17
- $opts->setOpt( 'type_exclusions', $excl );
18
- }
19
  }
4
 
5
  class Upgrade extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Upgrade {
6
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  }
src/lib/src/Modules/UserManagement/Strings.php CHANGED
@@ -66,13 +66,13 @@ class Strings extends Base\Strings {
66
  ],
67
  ],
68
  'user_hard_suspended' => [
69
- 'name' => __( 'User Hard-Suspended', 'wp-simple-firewall' ),
70
  'audit' => [
71
  __( 'User "{{user_login}}" suspended by admin ({{admin}})', 'wp-simple-firewall' ),
72
  ],
73
  ],
74
  'user_hard_unsuspended' => [
75
- 'name' => __( 'User Hard-Unsuspended', 'wp-simple-firewall' ),
76
  'audit' => [
77
  __( 'User "{{user_login}}" unsuspended by admin ({{admin}})', 'wp-simple-firewall' ),
78
  ],
66
  ],
67
  ],
68
  'user_hard_suspended' => [
69
+ 'name' => __( 'User Manually Suspended', 'wp-simple-firewall' ),
70
  'audit' => [
71
  __( 'User "{{user_login}}" suspended by admin ({{admin}})', 'wp-simple-firewall' ),
72
  ],
73
  ],
74
  'user_hard_unsuspended' => [
75
+ 'name' => __( 'User Manually Unsuspended', 'wp-simple-firewall' ),
76
  'audit' => [
77
  __( 'User "{{user_login}}" unsuspended by admin ({{admin}})', 'wp-simple-firewall' ),
78
  ],
src/lib/src/Scans/Afs/BuildScanAction.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
7
+
8
+ class BuildScanAction extends Base\BuildScanAction {
9
+
10
+ protected function buildItems() {
11
+ $items = ( new BuildScanItems() )
12
+ ->setMod( $this->getScanController()->getMod() )
13
+ ->setScanActionVO( $this->getScanActionVO() )
14
+ ->run();
15
+ asort( $items );
16
+ $this->getScanActionVO()->items = $items;
17
+ }
18
+
19
+ protected function setCustomFields() {
20
+ /** @var Options $opts */
21
+ $opts = $this->getScanController()->getOptions();
22
+ /** @var ScanActionVO $action */
23
+ $action = $this->getScanActionVO();
24
+ $action->file_exts = $this->getFileExts();
25
+ $action->realtime_scan_last_at = $opts->getLastRealtimeScanAt( true );
26
+ }
27
+ }
src/lib/src/Scans/{Mal/BuildFileMap.php → Afs/BuildScanItems.php} RENAMED
@@ -1,22 +1,50 @@
1
- <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseBuildFileMap;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers\StandardDirectoryIterator;
 
7
 
8
- class BuildFileMap extends BaseBuildFileMap {
9
 
10
  /**
11
  * @return string[]
12
  */
13
  public function build() :array {
14
- $files = [];
15
  $this->preBuild();
 
 
 
 
 
 
 
 
 
 
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  /** @var ScanActionVO $action */
18
  $action = $this->getScanActionVO();
19
 
 
20
  foreach ( $action->scan_root_dirs as $scanDir => $depth ) {
21
  try {
22
  foreach ( StandardDirectoryIterator::create( $scanDir, (int)$depth, $action->file_exts, false ) as $item ) {
@@ -53,9 +81,6 @@ class BuildFileMap extends BaseBuildFileMap {
53
  WP_CONTENT_DIR => 0,
54
  ];
55
  }
56
- if ( empty( $action->file_exts ) ) {
57
- $action->file_exts = [ 'php', 'php5' ];
58
- }
59
  if ( !is_array( $action->paths_whitelisted ) ) {
60
  $action->paths_whitelisted = [];
61
  }
1
+ <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseBuildFileMap;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers\StandardDirectoryIterator;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
 
9
+ class BuildScanItems extends BaseBuildFileMap {
10
 
11
  /**
12
  * @return string[]
13
  */
14
  public function build() :array {
 
15
  $this->preBuild();
16
+ $files = array_unique( array_merge(
17
+ $this->buildFilesFromDisk(),
18
+ $this->buildFilesFromWpHashes()
19
+ ) );
20
+ natsort( $files );
21
+ return $files;
22
+ }
23
+
24
+ private function buildFilesFromWpHashes() :array {
25
+ $files = [];
26
 
27
+ $coreHashes = Services::CoreFileHashes();
28
+ if ( $coreHashes->isReady() ) {
29
+ foreach ( array_keys( $coreHashes->getHashes() ) as $fragment ) {
30
+ // To reduce noise, we exclude plugins and themes (by default)
31
+ if ( strpos( $fragment, 'wp-content/' ) === false ) {
32
+ $fullPath = wp_normalize_path( path_join( ABSPATH, $fragment ) );
33
+ if ( !$this->isWhitelistedPath( $fullPath ) ) {
34
+ $files[] = $fullPath;
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ return $files;
41
+ }
42
+
43
+ private function buildFilesFromDisk() :array {
44
  /** @var ScanActionVO $action */
45
  $action = $this->getScanActionVO();
46
 
47
+ $files = [];
48
  foreach ( $action->scan_root_dirs as $scanDir => $depth ) {
49
  try {
50
  foreach ( StandardDirectoryIterator::create( $scanDir, (int)$depth, $action->file_exts, false ) as $item ) {
81
  WP_CONTENT_DIR => 0,
82
  ];
83
  }
 
 
 
84
  if ( !is_array( $action->paths_whitelisted ) ) {
85
  $action->paths_whitelisted = [];
86
  }
src/lib/src/Scans/Afs/Exceptions/MalwareFileException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class MalwareFileException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/PluginFileChecksumFailException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class PluginFileChecksumFailException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/PluginFileUnrecognisedException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class PluginFileUnrecognisedException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/RealtimeFileDiscoveredException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class RealtimeFileDiscoveredException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/ScanFileException.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class ScanFileException extends \Exception {
6
+
7
+ private $scanFileData = [];
8
+
9
+ public function __construct( string $file, array $data = [] ) {
10
+ parent::__construct( $file );
11
+ $this->scanFileData = $data;
12
+ }
13
+
14
+ public function getScanFileData() :array {
15
+ return $this->scanFileData;
16
+ }
17
+ }
src/lib/src/Scans/Afs/Exceptions/ThemeFileChecksumFailException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class ThemeFileChecksumFailException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/ThemeFileUnrecognisedException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class ThemeFileUnrecognisedException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/WpCoreFileChecksumFailException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class WpCoreFileChecksumFailException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/WpCoreFileMissingException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class WpCoreFileMissingException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/Exceptions/WpCoreFileUnrecognisedException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
4
+
5
+ class WpCoreFileUnrecognisedException extends ScanFileException {
6
+
7
+ }
src/lib/src/Scans/Afs/FileScanner.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs as AfsScan;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\Afs as AfsCon;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib;
9
+
10
+ class FileScanner {
11
+
12
+ use Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
13
+ use Shield\Modules\ModConsumer;
14
+ use Shield\Scans\Common\ScanActionConsumer;
15
+
16
+ /**
17
+ * @return ResultItem|null
18
+ */
19
+ public function scan( string $fullPath ) {
20
+ /** @var AfsCon $scanCon */
21
+ $scanCon = $this->getScanController();
22
+ /** @var ScanActionVO $action */
23
+ $action = $this->getScanActionVO();
24
+
25
+ $item = null;
26
+
27
+ $validFile = false;
28
+ try {
29
+ $validFile =
30
+ ( $scanCon->isEnabled() && ( new Scans\WpCoreFile( $fullPath ) )
31
+ ->setMod( $this->getMod() )
32
+ ->setScanActionVO( $action )
33
+ ->scan() ) ||
34
+ ( $scanCon->isEnabled() && ( new Scans\WpCoreUnrecognisedFile( $fullPath ) )
35
+ ->setMod( $this->getMod() )
36
+ ->setScanActionVO( $action )
37
+ ->scan() ) ||
38
+ ( $scanCon->isEnabledPluginThemeScan() && ( new Scans\PluginFile( $fullPath ) )
39
+ ->setMod( $this->getMod() )
40
+ ->setScanActionVO( $action )
41
+ ->scan() ) ||
42
+ ( $scanCon->isEnabledPluginThemeScan() && ( new Scans\ThemeFile( $fullPath ) )
43
+ ->setMod( $this->getMod() )
44
+ ->setScanActionVO( $action )
45
+ ->scan() );
46
+ }
47
+ catch ( Exceptions\WpCoreFileMissingException $me ) {
48
+ $item = $this->getResultItem( $fullPath );
49
+ $item->is_in_core = true;
50
+ $item->is_missing = true;
51
+ }
52
+ catch ( Exceptions\WpCoreFileChecksumFailException $cfe ) {
53
+ $item = $this->getResultItem( $fullPath );
54
+ $item->is_in_core = true;
55
+ $item->is_checksumfail = true;
56
+ }
57
+ catch ( Exceptions\WpCoreFileUnrecognisedException $ufe ) {
58
+ $item = $this->getResultItem( $fullPath );
59
+ $item->is_in_core = true;
60
+ $item->is_unrecognised = true;
61
+ }
62
+ catch ( Exceptions\PluginFileUnrecognisedException $e ) {
63
+ $item = $this->getResultItem( $fullPath );
64
+ $item->is_in_plugin = true;
65
+ $item->is_unrecognised = true;
66
+ $item->ptg_slug = $e->getScanFileData()[ 'slug' ];
67
+ }
68
+ catch ( Exceptions\PluginFileChecksumFailException $e ) {
69
+ $item = $this->getResultItem( $fullPath );
70
+ $item->is_in_plugin = true;
71
+ $item->is_checksumfail = true;
72
+ $item->ptg_slug = $e->getScanFileData()[ 'slug' ];
73
+ }
74
+ catch ( Exceptions\ThemeFileUnrecognisedException $e ) {
75
+ $item = $this->getResultItem( $fullPath );
76
+ $item->is_in_theme = true;
77
+ $item->is_unrecognised = true;
78
+ $item->ptg_slug = $e->getScanFileData()[ 'slug' ];
79
+ }
80
+ catch ( Exceptions\ThemeFileChecksumFailException $e ) {
81
+ $item = $this->getResultItem( $fullPath );
82
+ $item->is_in_theme = true;
83
+ $item->is_checksumfail = true;
84
+ $item->ptg_slug = $e->getScanFileData()[ 'slug' ];
85
+ }
86
+
87
+ try {
88
+ if ( $scanCon->isEnabledMalwareScan() && ( empty( $item ) || !$item->is_missing ) ) {
89
+ ( new Scans\MalwareFile( $fullPath ) )
90
+ ->setMod( $this->getMod() )
91
+ ->setScanActionVO( $action )
92
+ ->scan();
93
+ }
94
+ }
95
+ catch ( Exceptions\MalwareFileException $mfe ) {
96
+ if ( empty( $item ) ) {
97
+ $item = $this->getResultItem( $fullPath );
98
+ }
99
+ $item->is_mal = true;
100
+
101
+ foreach ( $mfe->getScanFileData() as $malMetaKey => $malMetaValue ) {
102
+ $item->{$malMetaKey} = $malMetaValue;
103
+ }
104
+ if ( $validFile ) {
105
+ $item->mal_fp_confidence = 100;
106
+ }
107
+
108
+ // Updates the FP scores stored within mal_meta
109
+ ( new AfsScan\Processing\MalwareFalsePositive() )
110
+ ->setMod( $this->getMod() )
111
+ ->setScanActionVO( $this->getScanActionVO() )
112
+ ->run( $item );
113
+
114
+ if ( $item->mal_fp_confidence > $action->confidence_threshold ) {
115
+ $item->auto_filter = true;
116
+ }
117
+ }
118
+ catch ( \InvalidArgumentException $e ) {
119
+ }
120
+
121
+ /** TODO */
122
+ if ( false && empty( $item ) && !$validFile ) {
123
+ try {
124
+ ( new AfsScan\Scans\RealtimeFile( $fullPath ) )
125
+ ->setMod( $this->getMod() )
126
+ ->setScanActionVO( $action )
127
+ ->scan();
128
+ }
129
+ catch ( AfsScan\Exceptions\RealtimeFileDiscoveredException $rte ) {
130
+ error_log( $fullPath );
131
+ $item = $this->getResultItem( $fullPath );
132
+ $item->is_realtime = true;
133
+ }
134
+ }
135
+
136
+ return $item;
137
+ }
138
+
139
+ private function getResultItem( string $fullPath ) :ResultItem {
140
+ /** @var ResultItem $item */
141
+ $item = $this->getScanController()->getNewResultItem();
142
+ $item->path_full = wp_normalize_path( $fullPath );
143
+ $item->path_fragment = str_replace( wp_normalize_path( ABSPATH ), '', $item->path_full );
144
+ return $item;
145
+ }
146
+ }
src/lib/src/Scans/{Mal/Utilities/FalsePositiveQuery.php → Afs/Processing/MalFalsePositiveQuery.php} RENAMED
@@ -1,25 +1,20 @@
1
- <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
  use FernleafSystems\Wordpress\Services\Utilities\File\ExtractLinesFromFile;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
8
 
9
- /**
10
- * Class FalsePositiveQuery
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities
12
- */
13
- class FalsePositiveQuery {
14
 
15
  use Modules\ModConsumer;
16
 
17
  /**
18
- * @param string $fullPath
19
  * @param int[] $lines
20
  * @return int[] - key is the file line number, value is the false positive confidence score
21
  */
22
- public function queryFileLines( $fullPath, $lines ) {
23
  $scores = [];
24
  /** @var Modules\HackGuard\Options $opts */
25
  $opts = $this->getOptions();
1
+ <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Processing;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
  use FernleafSystems\Wordpress\Services\Utilities\File\ExtractLinesFromFile;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
8
 
9
+ class MalFalsePositiveQuery {
 
 
 
 
10
 
11
  use Modules\ModConsumer;
12
 
13
  /**
 
14
  * @param int[] $lines
15
  * @return int[] - key is the file line number, value is the false positive confidence score
16
  */
17
+ public function queryFileLines( string $fullPath, array $lines ) :array {
18
  $scores = [];
19
  /** @var Modules\HackGuard\Options $opts */
20
  $opts = $this->getOptions();
src/lib/src/Scans/Afs/Processing/MalFalsePositiveReporter.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Processing;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\ResultItem;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+ use FernleafSystems\Wordpress\Services\Utilities\File\ConvertLineEndings;
9
+ use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
10
+
11
+ class MalFalsePositiveReporter {
12
+
13
+ const HASH_ALGO = 'sha1';
14
+ use Modules\ModConsumer;
15
+
16
+ public function reportResultItem( ResultItem $item, bool $isFalsePositive = true ) {
17
+ $this->reportPath( $item->path_full, $isFalsePositive );
18
+ $this->reportFileLines( $item->path_full, $item->mal_file_lines, $isFalsePositive );
19
+ }
20
+
21
+ public function reportFileLines( string $fullPath, array $lines, bool $isFalsePositive = true ) {
22
+ /** @var Modules\HackGuard\Options $opts */
23
+ $opts = $this->getOptions();
24
+ if ( $opts->isMalUseNetworkIntelligence() ) {
25
+ $fileLines = array_intersect_key(
26
+ explode( "\n", Services::WpFs()->getFileContent( $fullPath ) ),
27
+ $lines
28
+ );
29
+ foreach ( $fileLines as $line ) {
30
+ $this->reportLine( $fullPath, $line, $isFalsePositive );
31
+ }
32
+ }
33
+ }
34
+
35
+ public function reportPath( string $fullPath, bool $isFalsePositive = true ) :bool {
36
+ $reported = false;
37
+
38
+ $reportHash = md5( serialize( [
39
+ basename( $fullPath ),
40
+ sha1( ( new ConvertLineEndings() )->fileDosToLinux( $fullPath ) ),
41
+ $isFalsePositive
42
+ ] ) );
43
+
44
+ if ( $this->canSendReport( $reportHash ) ) {
45
+ $apiToken = $this->getCon()
46
+ ->getModule_License()
47
+ ->getWpHashesTokenManager()
48
+ ->getToken();
49
+ $reported = !empty( $apiToken ) &&
50
+ ( new Malware\Whitelist\ReportFalsePositive( $apiToken ) )
51
+ ->report( $fullPath, static::HASH_ALGO, $isFalsePositive );
52
+ if ( $reported ) {
53
+ $this->getReportCache()
54
+ ->setReportHash( $reportHash )
55
+ ->updateWithReport();
56
+ }
57
+ }
58
+ return $reported;
59
+ }
60
+
61
+ /**
62
+ * Only reports lines if the files has more than 1 line. i.e. 1-liner false positive files are excluded.
63
+ * We still report 1-liner "true positive" files.
64
+ */
65
+ public function reportLine( string $fullPath, string $line, bool $isFalsePositive = true ) :bool {
66
+ $reported = false;
67
+
68
+ $reportHash = md5( $fullPath.$line.( $isFalsePositive ? 'true' : 'false' ) );
69
+ if ( $this->canSendReport( $reportHash ) ) {
70
+ try {
71
+ $token = $this->getCon()
72
+ ->getModule_License()
73
+ ->getWpHashesTokenManager()
74
+ ->getToken();
75
+ if ( !empty( $token ) && !$isFalsePositive || count( file( $fullPath ) ) > 1 ) {
76
+ $reported = ( new Malware\Signatures\ReportFalsePositive( $token ) )
77
+ ->report( $fullPath, $line, $isFalsePositive );
78
+ if ( $reported ) {
79
+ $this->getReportCache()
80
+ ->setReportHash( $reportHash )
81
+ ->updateWithReport();
82
+ }
83
+ }
84
+ }
85
+ catch ( \Exception $e ) {
86
+ }
87
+ }
88
+
89
+ return $reported;
90
+ }
91
+
92
+ private function canSendReport( string $reportHash ) :bool {
93
+ /** @var Modules\HackGuard\Options $opts */
94
+ $opts = $this->getOptions();
95
+ return $this->getCon()->is_mode_live
96
+ && $opts->isMalUseNetworkIntelligence()
97
+ && !$this->getReportCache()
98
+ ->setReportHash( $reportHash )
99
+ ->isReported();
100
+ }
101
+
102
+ private function getReportCache() :MalReportCache {
103
+ return ( new MalReportCache() )->setMod( $this->getMod() );
104
+ }
105
+ }
src/lib/src/Scans/Afs/Processing/MalReportCache.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Processing;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class MalReportCache {
9
+
10
+ use ModConsumer;
11
+
12
+ private $workingReportHash;
13
+
14
+ public function setReportHash( string $reportHash ) :MalReportCache {
15
+ $this->workingReportHash = $reportHash;
16
+ return $this;
17
+ }
18
+
19
+ public function updateWithReport() {
20
+ if ( !$this->isReported() ) {
21
+
22
+ $this->getOptions()->setOpt( 'mal_fp_reports', array_filter(
23
+ array_merge( $this->getMalFalsePositiveReports(), [
24
+ $this->workingReportHash => Services::Request()->ts()
25
+ ] ),
26
+ function ( $ts ) {
27
+ return $ts > Services::Request()->carbon()->subMonth()->timestamp;
28
+ }
29
+ ) );
30
+
31
+ $this->getMod()->saveModOptions(); // important to save immediately due to async nature
32
+ }
33
+ }
34
+
35
+ public function reportedAt() :int {
36
+ return $this->getMalFalsePositiveReports()[ $this->workingReportHash ] ?? 0;
37
+ }
38
+
39
+ public function isReported() :bool {
40
+ return $this->reportedAt() > 0;
41
+ }
42
+
43
+ /**
44
+ * @return int[] - keys are the unique report hash
45
+ */
46
+ private function getMalFalsePositiveReports() :array {
47
+ $FP = $this->getOptions()->getOpt( 'mal_fp_reports', [] );
48
+ return is_array( $FP ) ? $FP : [];
49
+ }
50
+ }
src/lib/src/Scans/Afs/Processing/MalwareFalsePositive.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Processing;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\{
7
+ ResultItem,
8
+ ScanActionVO
9
+ };
10
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib;
11
+
12
+ class MalwareFalsePositive {
13
+
14
+ use Shield\Modules\ModConsumer;
15
+ use Shield\Scans\Common\ScanActionConsumer;
16
+
17
+ public function run( ResultItem $item ) {
18
+ /** @var ScanActionVO $action */
19
+ $action = $this->getScanActionVO();
20
+
21
+ // It's a "valid" file from previous scans we know it's 100% false positive.
22
+ if ( $item->mal_fp_confidence === 100 ) {
23
+ $reporter = ( new MalFalsePositiveReporter() )
24
+ ->setMod( $this->getMod() );
25
+ foreach ( $item->mal_file_lines as $line ) {
26
+ $reporter->reportLine( $item->path_full, $line, true );
27
+ }
28
+ $reporter->reportPath( $item->path_full, true );
29
+ }
30
+ elseif ( $action->confidence_threshold > 0 ) {
31
+
32
+ // 1. First check whether the FP of the whole file means we can filter it
33
+ $item->mal_fp_confidence = ( new MalFalsePositiveQuery() )
34
+ ->setMod( $this->getMod() )
35
+ ->queryPath( $item->path_full );
36
+
37
+ // 2. query each line and filter out fp confident lines
38
+ if ( $item->mal_fp_confidence < $action->confidence_threshold ) {
39
+
40
+ $item->mal_fp_lines = ( new MalFalsePositiveQuery() )
41
+ ->setMod( $this->getMod() )
42
+ ->queryFileLines( $item->path_full, array_keys( $item->mal_file_lines ) );
43
+
44
+ if ( !empty( $item->mal_fp_lines ) ) {
45
+ $filteredLines = array_filter(
46
+ $item->mal_fp_lines,
47
+ function ( $score ) use ( $action ) {
48
+ return $score < $action->confidence_threshold;
49
+ }
50
+ );
51
+
52
+ /**
53
+ * If all lines, individually, have a high FP score, then we can infer
54
+ * that the whole file itself has a high FP score.
55
+ */
56
+ if ( empty( $filteredLines ) ) {
57
+ $item->mal_fp_confidence = (int)( array_sum( $item->mal_fp_lines )/count( $item->mal_fp_lines ) );
58
+ // Send False Positive report for entire file based on all file lines being FPs.
59
+ ( new MalFalsePositiveReporter() )
60
+ ->setMod( $this->getMod() )
61
+ ->reportPath( $item->path_full, true );
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
src/lib/src/Scans/Afs/ResultItem.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
+
7
+ /**
8
+ * @property string $path_full
9
+ * @property string $path_fragment - relative to ABSPATH
10
+ * @property bool $is_in_core
11
+ * @property bool $is_in_plugin
12
+ * @property bool $is_in_theme
13
+ * @property bool $is_checksumfail
14
+ * @property bool $is_unrecognised
15
+ * @property bool $is_missing
16
+ * @property bool $is_mal
17
+ * @property bool $is_realtime
18
+ * @property int $mal_fp_confidence
19
+ * @property array $mal_fp_lines
20
+ * @property array $mal_file_lines
21
+ * @property string $mal_sig
22
+ * @property string $ptg_slug
23
+ */
24
+ class ResultItem extends Base\ResultItem {
25
+
26
+ public function getDescriptionForAudit() :string {
27
+ return $this->path_fragment;
28
+ }
29
+
30
+ public function __get( string $key ) {
31
+ $value = parent::__get( $key );
32
+ switch ( $key ) {
33
+ case 'path_full':
34
+ if ( empty( $value ) ) {
35
+ $value = path_join( wp_normalize_path( ABSPATH ), $this->path_fragment );
36
+ }
37
+ break;
38
+ case 'mal_fp_lines':
39
+ if ( !is_array( $value ) ) {
40
+ $value = json_decode( $value, true );
41
+ }
42
+ break;
43
+ case 'mal_file_lines':
44
+ if ( !is_array( $value ) ) {
45
+ $value = json_decode( base64_decode( $value ), true );
46
+ }
47
+ break;
48
+ case 'mal_sig':
49
+ $value = base64_decode( $value );
50
+ break;
51
+ case 'mal_fp_confidence':
52
+ $value = (int)( $value );
53
+ break;
54
+ default:
55
+ break;
56
+ }
57
+
58
+ if ( preg_match( '/^is_/i', $key ) ) {
59
+ $value = (bool)$value;
60
+ }
61
+
62
+ return $value;
63
+ }
64
+
65
+ /**
66
+ * @inheritDoc
67
+ */
68
+ public function __set( string $key, $value ) {
69
+ switch ( $key ) {
70
+ case 'mal_fp_lines':
71
+ $value = json_encode( $value );
72
+ break;
73
+ case 'mal_file_lines':
74
+ $value = base64_encode( json_encode( $value ) );
75
+ break;
76
+ case 'mal_sig':
77
+ $value = base64_encode( $value );
78
+ break;
79
+ case 'mal_fp_confidence':
80
+ $value = (int)( $value );
81
+ break;
82
+ default:
83
+ break;
84
+ }
85
+
86
+ if ( preg_match( '/^is_/i', $key ) ) {
87
+ $value = (bool)$value;
88
+ }
89
+
90
+ parent::__set( $key, $value );
91
+ }
92
+ }
src/lib/src/Scans/Afs/ResultsSet.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
+
7
+ class ResultsSet extends Base\ResultsSet {
8
+
9
+ public function getForPlugin( string $slug ) :ResultsSet {
10
+ return $this->getPluginGuard()->filterByFieldEquals( 'ptg_slug', $slug );
11
+ }
12
+
13
+ public function getForTheme( string $slug ) :ResultsSet {
14
+ return $this->getThemeGuard()->filterByFieldEquals( 'ptg_slug', $slug );
15
+ }
16
+
17
+ public function getMalware() :ResultsSet {
18
+ return $this->filterByFieldEquals( 'is_mal', true );
19
+ }
20
+
21
+ public function getPluginGuard() :ResultsSet {
22
+ return $this->filterByFieldEquals( 'is_in_plugin', true );
23
+ }
24
+
25
+ public function getThemeGuard() :ResultsSet {
26
+ return $this->filterByFieldEquals( 'is_in_theme', true );
27
+ }
28
+
29
+ public function getWordpressCore() :ResultsSet {
30
+ return $this->filterByFieldEquals( 'is_in_core', true );
31
+ }
32
+
33
+ private function filterByFieldEquals( string $field, $equals ) :ResultsSet {
34
+ $res = new ResultsSet();
35
+ /** @var ResultItem $item */
36
+ foreach ( $this->getItems() as $item ) {
37
+ if ( $item->{$field} == $equals ) {
38
+ $res->addItem( $item );
39
+ }
40
+ }
41
+ return $res;
42
+ }
43
+ }
src/lib/src/Scans/{Mal → Afs}/Scan.php RENAMED
@@ -1,6 +1,6 @@
1
- <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
1
+ <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
src/lib/src/Scans/Afs/ScanActionVO.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
+ /**
8
+ * @property int $realtime_scan_last_at
9
+ * @property string[] $file_exts
10
+ * @property string[] $scan_root_dirs
11
+ * @property string[] $paths_whitelisted
12
+ * @property string[] $patterns_fullregex
13
+ * @property string[] $patterns_regex
14
+ * @property string[] $patterns_simple
15
+ * @property int $confidence_threshold
16
+ */
17
+ class ScanActionVO extends BaseScanActionVO {
18
+
19
+ const QUEUE_GROUP_SIZE_LIMIT = 50;
20
+ const DEFAULT_SLEEP_SECONDS = 0.1;
21
+ }
src/lib/src/Scans/{Mal → Afs}/ScanFromFileMap.php RENAMED
@@ -1,6 +1,6 @@
1
- <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files\BaseScanFromFileMap;
6
 
@@ -10,8 +10,6 @@ class ScanFromFileMap extends BaseScanFromFileMap {
10
  * @return FileScanner
11
  */
12
  protected function getFileScanner() {
13
- return ( new FileScanner() )
14
- ->setMod( $this->getMod() )
15
- ->setScanActionVO( $this->getScanActionVO() );
16
  }
17
  }
1
+ <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files\BaseScanFromFileMap;
6
 
10
  * @return FileScanner
11
  */
12
  protected function getFileScanner() {
13
+ return new FileScanner();
 
 
14
  }
15
  }
src/lib/src/Scans/Afs/Scans/BasePluginThemeFile.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+
7
+ abstract class BasePluginThemeFile extends BaseScan {
8
+
9
+ use ModConsumer;
10
+ }
src/lib/src/Scans/Afs/Scans/BaseScan.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\ScanActionVO;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanActionConsumer;
8
+
9
+ abstract class BaseScan {
10
+
11
+ use ScanActionConsumer;
12
+ use ModConsumer;
13
+
14
+ /**
15
+ * @var string
16
+ */
17
+ protected $pathFragment;
18
+
19
+ /**
20
+ * @var string
21
+ */
22
+ protected $pathFull;
23
+
24
+ public function __construct( string $pathFull ) {
25
+ $this->setPathFull( $pathFull );
26
+ }
27
+
28
+ protected function getSupportedFileExtensions() :array {
29
+ /** @var ScanActionVO $action */
30
+ $action = $this->getScanActionVO();
31
+ return is_array( $action->file_exts ) ? $action->file_exts : [];
32
+ }
33
+
34
+ protected function isSupportedFileExt() :bool {
35
+ $ext = strtolower( (string)pathinfo( $this->pathFull, PATHINFO_EXTENSION ) );
36
+ return !empty( $ext ) && in_array( $ext, $this->getSupportedFileExtensions() );
37
+ }
38
+
39
+ abstract public function scan() :bool;
40
+
41
+ public function setPathFull( string $pathFull ) {
42
+ $this->pathFull = $pathFull;
43
+ $this->pathFragment = str_replace( wp_normalize_path( ABSPATH ), '', $pathFull );
44
+ }
45
+ }
src/lib/src/Scans/Afs/Scans/MalwareFile.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\ScanActionVO;
7
+ use FernleafSystems\Wordpress\Services\Utilities\File\LocateStrInFile;
8
+
9
+ class MalwareFile extends BaseScan {
10
+
11
+ /**
12
+ * @var LocateStrInFile
13
+ */
14
+ private $locator;
15
+
16
+ /**
17
+ * @throws Exceptions\MalwareFileException
18
+ * @throws \InvalidArgumentException
19
+ */
20
+ public function scan() :bool {
21
+ /** @var ScanActionVO $action */
22
+ $action = $this->getScanActionVO();
23
+
24
+ if ( $this->isSupportedFileExt() ) {
25
+
26
+ $this->locator = ( new LocateStrInFile() )->setPath( $this->pathFull );
27
+
28
+ // Simple Patterns first
29
+ $this->locator->setIsRegEx( false );
30
+ foreach ( $action->patterns_simple as $signature ) {
31
+ $this->scanForSig( $signature );
32
+ }
33
+
34
+ // RegEx Patterns
35
+ $this->locator->setIsRegEx( true );
36
+ if ( empty( $action->patterns_fullregex ) ) {
37
+ foreach ( $action->patterns_regex as $signature ) {
38
+ $this->scanForSig( $signature );
39
+ }
40
+ }
41
+ else { // Full regex patterns
42
+ foreach ( $action->patterns_fullregex as $signature ) {
43
+ $this->scanForSig( $signature );
44
+ }
45
+ }
46
+ }
47
+
48
+ return true;
49
+ }
50
+
51
+ /**
52
+ * @throws Exceptions\MalwareFileException
53
+ */
54
+ private function scanForSig( string $signature ) {
55
+ $lines = $this->locator->setNeedle( $signature )->run();
56
+ if ( !empty( $lines ) ) {
57
+ throw new Exceptions\MalwareFileException(
58
+ $this->pathFull,
59
+ [
60
+ // Set FP Confidence for file and lines to ZERO.
61
+ 'mal_fp_confidence' => 0,
62
+ 'mal_fp_lines' => array_fill_keys( array_keys( $lines ), 0 ),
63
+ 'mal_file_lines' => $lines,
64
+ 'mal_sig' => $signature,
65
+ ]
66
+ );
67
+ }
68
+ }
69
+
70
+ protected function getSupportedFileExtensions() :array {
71
+ return [ 'php', 'php5', 'php7' ];
72
+ }
73
+ }
src/lib/src/Scans/Afs/Scans/PluginFile.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\{
6
+ Exceptions\AssetHashesNotFound,
7
+ Exceptions\NoneAssetFileException,
8
+ Exceptions\UnrecognisedAssetFile,
9
+ Query
10
+ };
11
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
12
+ use FernleafSystems\Wordpress\Services\Utilities\WpOrg\Plugin\Files;
13
+
14
+ class PluginFile extends BasePluginThemeFile {
15
+
16
+ /**
17
+ * @throws Exceptions\PluginFileUnrecognisedException
18
+ * @throws Exceptions\PluginFileChecksumFailException
19
+ */
20
+ public function scan() :bool {
21
+ $valid = false;
22
+
23
+ $asset = ( new Files() )->findPluginFromFile( $this->pathFull );
24
+ if ( !empty( $asset ) ) {
25
+
26
+ if ( $this->isSupportedFileExt() ) {
27
+
28
+ try {
29
+ $verifiedHash = ( new Query() )
30
+ ->setMod( $this->getMod() )
31
+ ->verifyHash( $this->pathFull );
32
+ if ( !$verifiedHash ) {
33
+ throw new Exceptions\PluginFileChecksumFailException(
34
+ $this->pathFull,
35
+ [
36
+ 'slug' => $asset->unique_id,
37
+ ]
38
+ );
39
+ }
40
+ $valid = true;
41
+ }
42
+ catch ( AssetHashesNotFound $e ) {
43
+ // We don't have any hashes to use
44
+ }
45
+ catch ( NoneAssetFileException $e ) {
46
+ // Never reached since we've already located the asset
47
+ }
48
+ catch ( UnrecognisedAssetFile $e ) {
49
+ throw new Exceptions\PluginFileUnrecognisedException(
50
+ $this->pathFull,
51
+ [
52
+ 'slug' => $asset->unique_id,
53
+ ]
54
+ );
55
+ }
56
+ catch ( \InvalidArgumentException $e ) {
57
+ }
58
+ }
59
+ else {
60
+ $valid = true;
61
+ }
62
+ }
63
+
64
+ return $valid;
65
+ }
66
+ }
src/lib/src/Scans/Afs/Scans/RealtimeFile.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions\RealtimeFileDiscoveredException;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\ScanActionVO;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class RealtimeFile extends BaseScan {
10
+
11
+ /**
12
+ * @throws RealtimeFileDiscoveredException
13
+ */
14
+ public function scan() :bool {
15
+ /** @var ScanActionVO $action */
16
+ $action = $this->getScanActionVO();
17
+ $FS = Services::WpFs();
18
+
19
+ $mtime = $FS->isFile( $this->pathFull ) ? $FS->getModifiedTime( $this->pathFull ) : 0;
20
+ if ( $mtime > $action->realtime_scan_last_at ) {
21
+ error_log( var_export( $action->realtime_scan_last_at, true ) );
22
+ throw new RealtimeFileDiscoveredException( $this->pathFull, [ 'mtime' => $mtime ] );
23
+ }
24
+ return true;
25
+ }
26
+ }
src/lib/src/Scans/Afs/Scans/ThemeFile.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Hashes\{
6
+ Exceptions\AssetHashesNotFound,
7
+ Exceptions\NoneAssetFileException,
8
+ Exceptions\UnrecognisedAssetFile,
9
+ Query
10
+ };
11
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
12
+ use FernleafSystems\Wordpress\Services\Utilities\WpOrg\Theme\Files;
13
+
14
+ class ThemeFile extends BasePluginThemeFile {
15
+
16
+ /**
17
+ * @throws Exceptions\ThemeFileUnrecognisedException
18
+ * @throws Exceptions\ThemeFileChecksumFailException
19
+ */
20
+ public function scan() :bool {
21
+ $valid = false;
22
+
23
+ $asset = ( new Files() )->findThemeFromFile( $this->pathFull );
24
+ if ( !empty( $asset ) ) {
25
+
26
+ if ( $this->isSupportedFileExt() ) {
27
+ try {
28
+ $verifiedHash = ( new Query() )
29
+ ->setMod( $this->getMod() )
30
+ ->verifyHash( $this->pathFull );
31
+ if ( !$verifiedHash ) {
32
+ throw new Exceptions\ThemeFileChecksumFailException(
33
+ $this->pathFull,
34
+ [
35
+ 'slug' => $asset->unique_id,
36
+ ]
37
+ );
38
+ }
39
+ $valid = true;
40
+ }
41
+ catch ( AssetHashesNotFound $e ) {
42
+ // We don't have any hashes to use
43
+ }
44
+ catch ( NoneAssetFileException $e ) {
45
+ // Never reached since we've already located the asset
46
+ }
47
+ catch ( UnrecognisedAssetFile $e ) {
48
+ throw new Exceptions\ThemeFileUnrecognisedException(
49
+ $this->pathFull,
50
+ [
51
+ 'slug' => $asset->unique_id,
52
+ ]
53
+ );
54
+ }
55
+ catch ( \InvalidArgumentException $e ) {
56
+ }
57
+ }
58
+ else {
59
+ $valid = true;
60
+ }
61
+ }
62
+
63
+ return $valid;
64
+ }
65
+ }
src/lib/src/Scans/Afs/Scans/WpCoreFile.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
7
+
8
+ class WpCoreFile extends BaseScan {
9
+
10
+ /**
11
+ * @throws Exceptions\WpCoreFileChecksumFailException
12
+ * @throws Exceptions\WpCoreFileMissingException
13
+ */
14
+ public function scan() :bool {
15
+ $valid = false;
16
+
17
+ $WPH = Services::CoreFileHashes();
18
+ if ( $WPH->isCoreFile( $this->pathFull ) && !$this->isExcluded( $this->pathFragment ) ) {
19
+ if ( !Services::WpFs()->isFile( $this->pathFull ) ) {
20
+ if ( !$this->isExcludedMissing( $this->pathFragment ) ) {
21
+ throw new Exceptions\WpCoreFileMissingException( $this->pathFull );
22
+ }
23
+ }
24
+ elseif ( !$WPH->isCoreFileHashValid( $this->pathFull ) ) {
25
+ throw new Exceptions\WpCoreFileChecksumFailException( $this->pathFull );
26
+ }
27
+ $valid = true;
28
+ }
29
+
30
+ return $valid;
31
+ }
32
+
33
+ private function isExcluded( string $pathFragment ) :bool {
34
+ $exclusionsRegex = $this->getScanFileExclusions();
35
+ return !empty( $exclusionsRegex ) && preg_match( $exclusionsRegex, $pathFragment );
36
+ }
37
+
38
+ private function isExcludedMissing( string $pathFragment ) :bool {
39
+ $exclusionsRegex = $this->getScanExclusionsForMissingItems();
40
+ return !empty( $exclusionsRegex ) && preg_match( $exclusionsRegex, $pathFragment );
41
+ }
42
+
43
+ private function getScanFileExclusions() :string {
44
+ $pattern = '';
45
+
46
+ $exclusions = $this->getOptions()->getDef( 'wcf_exclusions' );
47
+ if ( !is_array( $exclusions ) ) {
48
+ $exclusions = [];
49
+ }
50
+ // Flywheel specific mods
51
+ if ( defined( 'FLYWHEEL_PLUGIN_DIR' ) ) {
52
+ $exclusions[] = 'wp-settings.php';
53
+ $exclusions[] = 'wp-admin/includes/upgrade.php';
54
+ }
55
+
56
+ if ( !empty( $exclusions ) ) {
57
+ $quoted = array_map(
58
+ function ( $exclusion ) {
59
+ return preg_quote( $exclusion, '#' );
60
+ },
61
+ $exclusions
62
+ );
63
+ $pattern = '#('.implode( '|', $quoted ).')#i';
64
+ }
65
+ return $pattern;
66
+ }
67
+
68
+ /**
69
+ * Builds a regex-ready pattern for matching file names to exclude from scan if they're missing
70
+ */
71
+ private function getScanExclusionsForMissingItems() :string {
72
+ $pattern = '';
73
+ $exclusions = $this->getOptions()->getDef( 'wcf_exclusions_missing_only' );
74
+ if ( !empty( $exclusions ) ) {
75
+ $quoted = array_map(
76
+ function ( $exclusion ) {
77
+ return preg_quote( $exclusion, '#' );
78
+ },
79
+ $exclusions
80
+ );
81
+ $pattern = '#('.implode( '|', $quoted ).')#i';
82
+ }
83
+ return $pattern;
84
+ }
85
+ }
src/lib/src/Scans/Afs/Scans/WpCoreUnrecognisedFile.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Scans;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Exceptions;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class WpCoreUnrecognisedFile extends BaseScan {
9
+
10
+ /**
11
+ * @throws Exceptions\WpCoreFileUnrecognisedException
12
+ */
13
+ public function scan() :bool {
14
+ $valid = false;
15
+ // TODO WP Content?
16
+ if ( strpos( $this->pathFull, path_join( ABSPATH, WPINC ) ) === 0
17
+ || strpos( $this->pathFull, path_join( ABSPATH, 'wp-admin' ) ) === 0 ) {
18
+ if ( !Services::CoreFileHashes()->isCoreFile( $this->pathFull ) && !$this->isExcluded( $this->pathFull ) ) {
19
+ throw new Exceptions\WpCoreFileUnrecognisedException( $this->pathFull );
20
+ }
21
+ $valid = true;
22
+ }
23
+ return $valid;
24
+ }
25
+
26
+ private function isExcluded( string $fullPath ) :bool {
27
+ $path = wp_normalize_path( $fullPath );
28
+ $filename = basename( $path );
29
+
30
+ $excluded = false;
31
+ foreach ( $this->getExcludedFiles() as $exclusion ) {
32
+ $exclusion = wp_normalize_path( $exclusion );
33
+ if ( strpos( $exclusion, '/' ) === false ) { // filename only
34
+ $excluded = $filename === $exclusion;
35
+ }
36
+ else {
37
+ $excluded = strpos( $path, $exclusion ) !== false;
38
+ }
39
+
40
+ if ( $excluded ) {
41
+ break;
42
+ }
43
+ }
44
+ return $excluded;
45
+ }
46
+
47
+ private function getExcludedFiles() :array {
48
+ return [
49
+ 'error_log',
50
+ 'php_error_log',
51
+ '.htaccess',
52
+ '.htpasswd',
53
+ '.user.ini',
54
+ 'php.ini',
55
+ 'web.config',
56
+ 'php_mail.log',
57
+ 'mail.log',
58
+ 'wp-content/uploads/bb-plugin/cache/',
59
+ 'wp-content/uploads/cache/wpml/twig/',
60
+ ];
61
+ }
62
+ }
src/lib/src/Scans/Afs/Utilities/ItemActionHandler.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Processing\MalFalsePositiveReporter;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\ResultItem;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
8
+
9
+ class ItemActionHandler extends Base\Utilities\ItemActionHandler {
10
+
11
+ /**
12
+ * @throws \Exception
13
+ */
14
+ public function ignore() :bool {
15
+ parent::ignore();
16
+
17
+ /** @var ResultItem $scanItem */
18
+ $scanItem = $this->getScanItem();
19
+ if ( $scanItem->is_mal ) {
20
+ ( new MalFalsePositiveReporter() )
21
+ ->setMod( $this->getMod() )
22
+ ->reportResultItem( $this->getScanItem(), true );
23
+ }
24
+
25
+ return true;
26
+ }
27
+
28
+ /**
29
+ * @throws \Exception
30
+ */
31
+ public function repairDelete() :bool {
32
+ return $this->repair( true );
33
+ }
34
+ }
src/lib/src/Scans/{Mal → Afs}/Utilities/Patterns.php RENAMED
@@ -1,15 +1,13 @@
1
- <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
  use FernleafSystems\Wordpress\Services\Utilities\File\Cache;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
8
 
9
- /**
10
- * Class Patterns
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities
12
- */
13
  class Patterns {
14
 
15
  use Modules\ModConsumer;
1
+ <?php declare( strict_types=1 );
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Utilities;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
  use FernleafSystems\Wordpress\Services\Utilities\File\Cache;
7
  use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
8
 
9
+ use const HOUR_IN_SECONDS;
10
+
 
 
11
  class Patterns {
12
 
13
  use Modules\ModConsumer;
src/lib/src/Scans/Afs/Utilities/RepairItem.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Processing\MalFalsePositiveReporter;
8
+ use FernleafSystems\Wordpress\Services\{
9
+ Services,
10
+ Utilities\File\RemoveLineFromFile,
11
+ Utilities\WpOrg
12
+ };
13
+
14
+ class RepairItem extends Shield\Scans\Base\Utilities\RepairItemBase {
15
+
16
+ use Shield\Modules\ModConsumer;
17
+ use Shield\Scans\Common\ScanItemConsumer;
18
+
19
+ public function repairItem() :bool {
20
+ /** @var Afs\ResultItem $item */
21
+ $item = $this->getScanItem();
22
+ /** @var Shield\Modules\HackGuard\Options $opts */
23
+ $opts = $this->getOptions();
24
+ $success = false;
25
+
26
+ try {
27
+ $canRepair = $this->canRepair();
28
+ }
29
+ catch ( \Exception $e ) {
30
+ $canRepair = false;
31
+ }
32
+
33
+ if ( $canRepair ) {
34
+
35
+ if ( Services::CoreFileHashes()->isCoreFile( $item->path_fragment ) ) {
36
+ $success = $this->repairCoreItem();
37
+ }
38
+ else {
39
+ $plugin = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $item->path_full );
40
+ if ( !empty( $plugin ) ) {
41
+ $success = $this->repairItemInPlugin();
42
+ }
43
+ else {
44
+ $theme = ( new WpOrg\Theme\Files() )->findThemeFromFile( $item->path_full );
45
+ if ( !empty( $theme ) && $theme->isWpOrg() ) {
46
+ $success = $this->repairItemInTheme();
47
+ }
48
+ elseif ( $opts->isMalAutoRepairSurgical() ) {
49
+ $success = $this->repairSurgicalItem();
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ if ( $success && $item->is_mal ) {
56
+ ( new MalFalsePositiveReporter() )
57
+ ->setMod( $this->getMod() )
58
+ ->reportResultItem( $item, false );
59
+ }
60
+
61
+ return $success;
62
+ }
63
+
64
+ /**
65
+ * @throws \Exception
66
+ */
67
+ public function canRepair() :bool {
68
+ /** @var Afs\ResultItem $item */
69
+ $item = $this->getScanItem();
70
+
71
+ $canRepair = false;
72
+ if ( $item->is_checksumfail || $item->is_missing ) {
73
+
74
+ if ( $item->is_in_core ) {
75
+ if ( !Services::CoreFileHashes()->isCoreFile( $item->path_fragment ) ) {
76
+ throw new \Exception( __( 'Not a WordPress Core file', 'wp-simple-firewall' ) );
77
+ }
78
+ $canRepair = true;
79
+ }
80
+ elseif ( $item->is_in_plugin ) {
81
+ $asset = Services::WpPlugins()->getPluginAsVo( $item->ptg_slug );
82
+
83
+ if ( empty( $asset ) ) {
84
+ throw new \Exception( sprintf(
85
+ __( "Couldn't load plugin for slug '%s'.", 'wp-simple-firewall' ),
86
+ $item->ptg_slug
87
+ ) );
88
+ }
89
+ if ( !$asset->isWpOrg() ) {
90
+ throw new \Exception( sprintf(
91
+ __( '%s not installed from WordPress.org.', 'wp-simple-firewall' ),
92
+ __( 'Plugin', 'wp-simple-firewall' )
93
+ ) );
94
+ }
95
+ if ( !$asset->svn_uses_tags ) {
96
+ throw new \Exception( __( "Plugin developer doesn't use SVN tags for official releases.", 'wp-simple-firewall' ) );
97
+ }
98
+
99
+ try {
100
+ $canRepair = ( new Shield\Modules\HackGuard\Lib\Hashes\Query() )
101
+ ->setMod( $this->getMod() )
102
+ ->fileExistsInHash( $item->path_fragment );
103
+ }
104
+ catch ( \Exception $e ) {
105
+ $canRepair = false;
106
+ }
107
+ }
108
+ elseif ( $item->is_in_theme ) {
109
+ $asset = Services::WpThemes()->getThemeAsVo( $item->ptg_slug );
110
+
111
+ if ( empty( $asset ) ) {
112
+ throw new \Exception( sprintf(
113
+ __( "Couldn't load theme for slug '%s'.", 'wp-simple-firewall' ),
114
+ $item->ptg_slug
115
+ ) );
116
+ }
117
+ if ( $asset->is_child ) {
118
+ throw new \Exception( sprintf(
119
+ __( "%s is a child of another theme.", 'wp-simple-firewall' ),
120
+ __( 'Theme', 'wp-simple-firewall' )
121
+ ) );
122
+ }
123
+ if ( !$asset->isWpOrg() ) {
124
+ throw new \Exception( sprintf(
125
+ __( '%s not installed from WordPress.org.', 'wp-simple-firewall' ),
126
+ __( 'Theme', 'wp-simple-firewall' )
127
+ ) );
128
+ }
129
+ if ( !( new WpOrg\Theme\Versions() )
130
+ ->setWorkingSlug( $asset->stylesheet )
131
+ ->exists( $asset->version, true ) ) {
132
+ throw new \Exception( __( "Theme version doesn't appear to exist.", 'wp-simple-firewall' ) );
133
+ }
134
+
135
+ try {
136
+ $canRepair = ( new Shield\Modules\HackGuard\Lib\Hashes\Query() )
137
+ ->setMod( $this->getMod() )
138
+ ->fileExistsInHash( $item->path_fragment );
139
+ }
140
+ catch ( \Exception $e ) {
141
+ $canRepair = false;
142
+ }
143
+ }
144
+ }
145
+
146
+ return $canRepair;
147
+ }
148
+
149
+ private function repairCoreItem() :bool {
150
+ /** @var Afs\ResultItem $item */
151
+ $item = $this->getScanItem();
152
+
153
+ $files = Services::WpGeneral()->isClassicPress() ? new WpOrg\Cp\Files() : new WpOrg\Wp\Files();
154
+ try {
155
+ $success = $files->replaceFileFromVcs( $item->path_fragment );
156
+ }
157
+ catch ( \InvalidArgumentException $e ) {
158
+ $success = false;
159
+ }
160
+ return $success;
161
+ }
162
+
163
+ private function repairSurgicalItem() :bool {
164
+ /** @var Afs\ResultItem $item */
165
+ $item = $this->getScanItem();
166
+
167
+ $success = false;
168
+ foreach ( array_keys( $item->mal_fp_lines ) as $lineNumber ) {
169
+ try {
170
+ ( new RemoveLineFromFile() )->run( $item->path_full, $lineNumber );
171
+ $success = true;
172
+ }
173
+ catch ( \Exception $e ) {
174
+ $success = false;
175
+ break;
176
+ }
177
+ }
178
+ return $success;
179
+ }
180
+
181
+ private function repairItemInPlugin() :bool {
182
+ /** @var Afs\ResultItem $item */
183
+ $item = $this->getScanItem();
184
+
185
+ $success = false;
186
+
187
+ $files = new WpOrg\Plugin\Files();
188
+ try {
189
+ if ( $files->isValidFileFromPlugin( $item->path_full ) ) {
190
+ $success = $files->replaceFileFromVcs( $item->path_full );
191
+ }
192
+ }
193
+ catch ( \InvalidArgumentException $e ) {
194
+ }
195
+
196
+ return $success;
197
+ }
198
+
199
+ private function repairItemInTheme() :bool {
200
+ /** @var Afs\ResultItem $item */
201
+ $item = $this->getScanItem();
202
+
203
+ $success = false;
204
+
205
+ $files = new WpOrg\Theme\Files();
206
+ try {
207
+ if ( $files->isValidFileFromTheme( $item->path_full ) ) {
208
+ $success = $files->replaceFileFromVcs( $item->path_full );
209
+ }
210
+ }
211
+ catch ( \InvalidArgumentException $e ) {
212
+ }
213
+
214
+ return $success;
215
+ }
216
+ }
src/lib/src/Scans/Apc/BuildScanAction.php CHANGED
@@ -2,15 +2,14 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
 
8
- class BuildScanAction extends Shield\Scans\Base\BaseBuildScanAction {
9
 
10
  protected function buildItems() {
11
- /** @var ScanActionVO $oAction */
12
- $oAction = $this->getScanActionVO();
13
- $oAction->items = Services::WpPlugins()->getInstalledPluginFiles();
14
  }
15
 
16
  protected function setCustomFields() {
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
 
6
 
7
+ class BuildScanAction extends Base\BuildScanAction {
8
 
9
  protected function buildItems() {
10
+ $this->getScanActionVO()->items = ( new BuildScanItems() )
11
+ ->setMod( $this->getScanController()->getMod() )
12
+ ->run();
13
  }
14
 
15
  protected function setCustomFields() {
src/lib/src/Scans/Apc/BuildScanItems.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class BuildScanItems extends Shield\Scans\Base\Utilities\BuildScanItems {
9
+
10
+ public function run() :array {
11
+ return Services::WpPlugins()->getInstalledPluginFiles();
12
+ }
13
+ }
src/lib/src/Scans/Apc/PluginScanner.php CHANGED
@@ -1,64 +1,55 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
 
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
8
- /**
9
- * Class PluginScanner
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc
11
- */
12
  class PluginScanner {
13
 
 
14
  use Shield\Scans\Common\ScanActionConsumer;
15
 
16
- /**
17
- * @param string $pluginFile
18
- * @return ResultItem|null
19
- */
20
- public function scan( $pluginFile ) {
21
- $oResultItem = null;
22
 
23
- /** @var ScanActionVO $oAction */
24
- $oAction = $this->getScanActionVO();
25
 
26
  $plugin = Services::WpPlugins()->getPluginAsVo( $pluginFile );
27
- if ( $plugin->asset_type === 'plugin' && $plugin->isWpOrg() ) {
28
- $nLastUpdatedAt = $this->getLastUpdateTime( $pluginFile );
29
- if ( $nLastUpdatedAt > 0
30
- && ( Services::Request()->ts() - $nLastUpdatedAt > $oAction->abandoned_limit ) ) {
31
-
32
- $oResultItem = new ResultItem();
33
- $oResultItem->slug = $pluginFile;
34
- $oResultItem->context = 'plugins';
35
- $oResultItem->last_updated_at = $nLastUpdatedAt;
36
  }
37
  }
38
 
39
- return $oResultItem;
40
  }
41
 
42
- /**
43
- * @param string $file
44
- * @return bool
45
- */
46
- private function getLastUpdateTime( $file ) {
47
- $slug = Services::WpPlugins()->getSlug( $file );
48
- if ( empty( $slug ) ) {
49
- $slug = dirname( $file );
50
- }
51
 
52
- if ( !function_exists( 'plugins_api' ) ) {
53
- require_once ABSPATH.'/wp-admin/includes/plugin-install.php';
 
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
- $api = plugins_api( 'plugin_information', [
56
- 'slug' => $slug,
57
- 'fields' => [
58
- 'sections' => false,
59
- ],
60
- ] );
61
 
62
- return isset( $api->last_updated ) ? strtotime( $api->last_updated ) : -1;
63
  }
64
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Core\VOs\Assets\WpPluginVo;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
 
 
 
 
9
  class PluginScanner {
10
 
11
+ use Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
12
  use Shield\Scans\Common\ScanActionConsumer;
13
 
14
+ public function scan( string $pluginFile ) :array {
15
+ $result = [];
 
 
 
 
16
 
17
+ /** @var ScanActionVO $action */
18
+ $action = $this->getScanActionVO();
19
 
20
  $plugin = Services::WpPlugins()->getPluginAsVo( $pluginFile );
21
+ if ( !empty( $plugin ) && $plugin->isWpOrg() ) {
22
+ $lastUpdatedAt = $this->getLastUpdateTime( $plugin );
23
+ if ( $lastUpdatedAt > 0
24
+ && ( Services::Request()->ts() - $lastUpdatedAt > $action->abandoned_limit ) ) {
25
+ $result[ 'slug' ] = $pluginFile;
26
+ $result[ 'is_abandoned' ] = true;
27
+ $result[ 'last_updated_at' ] = $lastUpdatedAt;
 
 
28
  }
29
  }
30
 
31
+ return $result;
32
  }
33
 
34
+ private function getLastUpdateTime( WpPluginVo $plugin ) :int {
35
+ $lastUpdate = -1;
 
 
 
 
 
 
 
36
 
37
+ $slug = $plugin->slug;
38
+ if ( !empty( $slug ) ) {
39
+ if ( !function_exists( 'plugins_api' ) ) {
40
+ require_once ABSPATH.'/wp-admin/includes/plugin-install.php';
41
+ }
42
+ $api = plugins_api( 'plugin_information', [
43
+ 'slug' => $slug,
44
+ 'fields' => [
45
+ 'sections' => false,
46
+ ],
47
+ ] );
48
+ if ( isset( $api->last_updated ) ) {
49
+ $lastUpdate = strtotime( $api->last_updated );
50
+ }
51
  }
 
 
 
 
 
 
52
 
53
+ return (int)$lastUpdate;
54
  }
55
  }
src/lib/src/Scans/Apc/ResultItem.php CHANGED
@@ -3,15 +3,25 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
  /**
6
- * Class ResultItem
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc
8
- * @property string $slug
9
- * @property string $context
10
- * @property int $last_updated_at
11
  */
12
  class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem {
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  public function getDescriptionForAudit() :string {
15
- return sprintf( '%s: %s', $this->context, $this->slug );
16
  }
17
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
  /**
6
+ * @property int $last_updated_at
7
+ * @property bool $is_abandoned
 
 
 
8
  */
9
  class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem {
10
 
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function __get( string $key ) {
15
+ $value = parent::__get( $key );
16
+
17
+ if ( preg_match( '/_at$/i', $key ) ) {
18
+ $value = (int)$value;
19
+ }
20
+
21
+ return $value;
22
+ }
23
+
24
  public function getDescriptionForAudit() :string {
25
+ return sprintf( '%s: %s', ( strpos( $this->VO->item_id, '/' ) ? 'Plugin' : 'Theme' ), $this->VO->item_id );
26
  }
27
  }
src/lib/src/Scans/Apc/ResultsSet.php CHANGED
@@ -4,22 +4,16 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
 
7
- /**
8
- * Class ResultsSet
9
- * @property ResultItem[] $items
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc
11
- */
12
  class ResultsSet extends Base\ResultsSet {
13
 
14
  /**
15
- * @param string $slug
16
  * @return ResultItem|null
17
  */
18
  public function getItemForSlug( string $slug ) {
19
  $theItem = null;
20
  /** @var ResultItem $item */
21
  foreach ( $this->getItems() as $item ) {
22
- if ( $item->slug === $slug ) {
23
  $theItem = $item;
24
  break;
25
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
 
 
 
 
 
 
7
  class ResultsSet extends Base\ResultsSet {
8
 
9
  /**
 
10
  * @return ResultItem|null
11
  */
12
  public function getItemForSlug( string $slug ) {
13
  $theItem = null;
14
  /** @var ResultItem $item */
15
  foreach ( $this->getItems() as $item ) {
16
+ if ( $item->VO->item_id === $slug ) {
17
  $theItem = $item;
18
  break;
19
  }
src/lib/src/Scans/Apc/Scan.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
@@ -7,31 +7,19 @@ use FernleafSystems\Wordpress\Plugin\Shield;
7
  class Scan extends Shield\Scans\Base\BaseScan {
8
 
9
  protected function scanSlice() {
10
- /** @var ScanActionVO $oAction */
11
- $oAction = $this->getScanActionVO();
12
-
13
- $oTempRs = $oAction->getNewResultsSet();
14
-
15
- foreach ( $oAction->items as $nKey => $sItem ) {
16
- $oItem = $this->getItemScanner()->scan( $sItem );
17
- if ( $oItem instanceof Shield\Scans\Base\ResultItem ) {
18
- $oTempRs->addItem( $oItem );
19
- }
20
- }
21
-
22
- $aNewItems = [];
23
- if ( $oTempRs->hasItems() ) {
24
- foreach ( $oTempRs->getAllItems() as $oItem ) {
25
- $aNewItems[] = $oItem->getRawData();
26
- }
27
- }
28
- $oAction->results = $aNewItems;
29
  }
30
 
31
- /**
32
- * @return PluginScanner
33
- */
34
- protected function getItemScanner() {
35
- return ( new PluginScanner() )->setScanActionVO( $this->getScanActionVO() );
36
  }
37
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
7
  class Scan extends Shield\Scans\Base\BaseScan {
8
 
9
  protected function scanSlice() {
10
+ /** @var ScanActionVO $action */
11
+ $action = $this->getScanActionVO();
12
+ $action->results = array_filter( array_map(
13
+ function ( $file ) {
14
+ return $this->getItemScanner()->scan( $file );
15
+ },
16
+ $action->items
17
+ ) );
 
 
 
 
 
 
 
 
 
 
 
18
  }
19
 
20
+ protected function getItemScanner() :PluginScanner {
21
+ return ( new PluginScanner() )
22
+ ->setScanController( $this->getScanController() )
23
+ ->setScanActionVO( $this->getScanActionVO() );
 
24
  }
25
  }
src/lib/src/Scans/Apc/ScanActionVO.php CHANGED
@@ -2,12 +2,12 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
 
 
5
  /**
6
- * Class ScanActionVO
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc
8
  * @property int $abandoned_limit
9
  */
10
- class ScanActionVO extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO {
11
 
12
  const QUEUE_GROUP_SIZE_LIMIT = 3;
13
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
  /**
 
 
8
  * @property int $abandoned_limit
9
  */
10
+ class ScanActionVO extends BaseScanActionVO {
11
 
12
  const QUEUE_GROUP_SIZE_LIMIT = 3;
13
  }
src/lib/src/Scans/Apc/Utilities/ItemActionHandler.php CHANGED
@@ -6,10 +6,4 @@ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
 
7
  class ItemActionHandler extends Base\Utilities\ItemActionHandler {
8
 
9
- /**
10
- * @return Repair
11
- */
12
- public function getRepairer() {
13
- return ( new Repair() )->setScanItem( $this->getScanItem() );
14
- }
15
  }
6
 
7
  class ItemActionHandler extends Base\Utilities\ItemActionHandler {
8
 
 
 
 
 
 
 
9
  }
src/lib/src/Scans/Apc/Utilities/Repair.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
-
7
- /**
8
- * Class Repair
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Apc\Utilities
10
- */
11
- class Repair extends Scans\Base\Utilities\BaseRepair {
12
-
13
- /**
14
- * @return bool
15
- * @throws \Exception
16
- */
17
- public function repairItem() :bool {
18
- throw new \Exception( 'Repair action is not supported' );
19
- }
20
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Base/BaseBuildFileMap.php CHANGED
@@ -7,18 +7,20 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanActionConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\ScanActionVO;
9
 
10
- abstract class BaseBuildFileMap {
11
 
12
- use Shield\Modules\ModConsumer;
13
  use ScanActionConsumer;
14
 
 
 
 
 
15
  abstract public function build() :array;
16
 
17
  protected function isAutoFilterFile( \SplFileInfo $file ) :bool {
18
  /** @var Options $opts */
19
  $opts = $this->getOptions();
20
- return $opts->isAutoFilterResults()
21
- && $file->getSize() === 0;
22
  }
23
 
24
  protected function isWhitelistedPath( string $path ) :bool {
7
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanActionConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\ScanActionVO;
9
 
10
+ abstract class BaseBuildFileMap extends Shield\Scans\Base\Utilities\BuildScanItems {
11
 
 
12
  use ScanActionConsumer;
13
 
14
+ public function run() :array {
15
+ return $this->build();
16
+ }
17
+
18
  abstract public function build() :array;
19
 
20
  protected function isAutoFilterFile( \SplFileInfo $file ) :bool {
21
  /** @var Options $opts */
22
  $opts = $this->getOptions();
23
+ return $opts->isAutoFilterResults() && $file->getSize() === 0;
 
24
  }
25
 
26
  protected function isWhitelistedPath( string $path ) :bool {
src/lib/src/Scans/Base/BaseScan.php CHANGED
@@ -7,6 +7,7 @@ use FernleafSystems\Wordpress\Services\Services;
7
 
8
  abstract class BaseScan {
9
 
 
10
  use Shield\Modules\ModConsumer;
11
  use Shield\Scans\Common\ScanActionConsumer;
12
 
@@ -25,11 +26,11 @@ abstract class BaseScan {
25
  * @throws \Exception
26
  */
27
  protected function preScan() {
28
- $oAction = $this->getScanActionVO();
29
- if ( !$oAction instanceof BaseScanActionVO ) {
30
  throw new \Exception( 'Action VO not provided.' );
31
  }
32
- if ( empty( $oAction->scan ) ) {
33
  throw new \Exception( 'Action Slug not provided.' );
34
  }
35
  }
7
 
8
  abstract class BaseScan {
9
 
10
+ use Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
11
  use Shield\Modules\ModConsumer;
12
  use Shield\Scans\Common\ScanActionConsumer;
13
 
26
  * @throws \Exception
27
  */
28
  protected function preScan() {
29
+ $action = $this->getScanActionVO();
30
+ if ( !$action instanceof BaseScanActionVO ) {
31
  throw new \Exception( 'Action VO not provided.' );
32
  }
33
+ if ( empty( $action->scan ) ) {
34
  throw new \Exception( 'Action Slug not provided.' );
35
  }
36
  }
src/lib/src/Scans/Base/BaseScanActionVO.php CHANGED
@@ -5,14 +5,10 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
5
  use FernleafSystems\Utilities\Data\Adapter\DynProperties;
6
 
7
  /**
8
- * Class ScanActionVO
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Base
10
  * @property string $scan
11
  * @property int $created_at
12
  * @property int $started_at
13
  * @property int $finished_at
14
- * @property bool $is_async
15
- * @property int $total_items
16
  * @property string[] $items
17
  * @property array[] $results
18
  * @property int $usleep
@@ -24,22 +20,6 @@ abstract class BaseScanActionVO {
24
  const QUEUE_GROUP_SIZE_LIMIT = 1;
25
  const DEFAULT_SLEEP_SECONDS = 0;
26
 
27
- /**
28
- * @return ResultItem|mixed
29
- */
30
- public function getNewResultItem() {
31
- $class = $this->getScanNamespace().'ResultItem';
32
- return new $class();
33
- }
34
-
35
- /**
36
- * @return ResultsSet|mixed
37
- */
38
- public function getNewResultsSet() {
39
- $class = $this->getScanNamespace().'ResultsSet';
40
- return new $class();
41
- }
42
-
43
  public function getScanNamespace() :string {
44
  try {
45
  $namespace = ( new \ReflectionClass( $this ) )->getNamespaceName();
5
  use FernleafSystems\Utilities\Data\Adapter\DynProperties;
6
 
7
  /**
 
 
8
  * @property string $scan
9
  * @property int $created_at
10
  * @property int $started_at
11
  * @property int $finished_at
 
 
12
  * @property string[] $items
13
  * @property array[] $results
14
  * @property int $usleep
20
  const QUEUE_GROUP_SIZE_LIMIT = 1;
21
  const DEFAULT_SLEEP_SECONDS = 0;
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  public function getScanNamespace() :string {
24
  try {
25
  $namespace = ( new \ReflectionClass( $this ) )->getNamespaceName();
src/lib/src/Scans/Base/{BaseBuildScanAction.php → BuildScanAction.php} RENAMED
@@ -3,42 +3,45 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
 
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
8
- abstract class BaseBuildScanAction {
9
 
10
- use Shield\Modules\ModConsumer;
11
  use Shield\Scans\Common\ScanActionConsumer;
12
 
13
  /**
 
14
  * @throws \Exception
15
  */
16
  public function build() {
17
- $action = $this->getScanActionVO();
18
- if ( !$action instanceof BaseScanActionVO ) {
19
- throw new \Exception( 'Scan Action VO not provided.' );
20
- }
21
- if ( empty( $action->scan ) ) {
22
- throw new \Exception( 'Scan Slug not provided.' );
23
- }
24
 
25
  $this->setWhitelists();
26
  $this->setCustomFields();
27
  $this->buildScanItems();
28
  $this->setStandardFields();
 
 
29
  }
30
 
31
  /**
32
  * @throws \Exception
33
  */
34
  protected function buildScanItems() {
35
- $action = $this->getScanActionVO();
36
  $this->buildItems();
37
- $action->total_items = count( $action->items );
38
  }
39
 
40
  abstract protected function buildItems();
41
 
 
 
 
 
 
 
42
  protected function setStandardFields() {
43
  $action = $this->getScanActionVO();
44
  if ( empty( $action->created_at ) ) {
@@ -46,7 +49,7 @@ abstract class BaseBuildScanAction {
46
  $action->started_at = 0;
47
  $action->finished_at = 0;
48
  $action->usleep = (int)( 1000000*max( 0, apply_filters(
49
- $this->getCon()->prefix( 'scan_block_sleep' ),
50
  $action::DEFAULT_SLEEP_SECONDS, $action->scan
51
  ) ) );
52
  }
@@ -57,7 +60,7 @@ abstract class BaseBuildScanAction {
57
 
58
  protected function setWhitelists() {
59
  /** @var Shield\Modules\HackGuard\Options $opts */
60
- $opts = $this->getOptions();
61
  $action = $this->getScanActionVO();
62
  $action->paths_whitelisted = $opts->getWhitelistedPathsAsRegex();
63
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
+ abstract class BuildScanAction {
10
 
11
+ use HackGuard\Scan\Controller\ScanControllerConsumer;
12
  use Shield\Scans\Common\ScanActionConsumer;
13
 
14
  /**
15
+ * @return static
16
  * @throws \Exception
17
  */
18
  public function build() {
19
+ $scanCon = $this->getScanController();
20
+ $this->setScanActionVO( $scanCon->getScanActionVO() );
 
 
 
 
 
21
 
22
  $this->setWhitelists();
23
  $this->setCustomFields();
24
  $this->buildScanItems();
25
  $this->setStandardFields();
26
+
27
+ return $this;
28
  }
29
 
30
  /**
31
  * @throws \Exception
32
  */
33
  protected function buildScanItems() {
 
34
  $this->buildItems();
 
35
  }
36
 
37
  abstract protected function buildItems();
38
 
39
+ protected function getFileExts() :array {
40
+ $scanCon = $this->getScanController();
41
+ $ext = apply_filters( 'shield/scan_ptg_file_exts', $scanCon->getOptions()->getDef( 'file_scan_extensions' ) );
42
+ return is_array( $ext ) ? $ext : $scanCon->getOptions()->getDef( 'file_scan_extensions' );
43
+ }
44
+
45
  protected function setStandardFields() {
46
  $action = $this->getScanActionVO();
47
  if ( empty( $action->created_at ) ) {
49
  $action->started_at = 0;
50
  $action->finished_at = 0;
51
  $action->usleep = (int)( 1000000*max( 0, apply_filters(
52
+ $this->getScanController()->getCon()->prefix( 'scan_block_sleep' ),
53
  $action::DEFAULT_SLEEP_SECONDS, $action->scan
54
  ) ) );
55
  }
60
 
61
  protected function setWhitelists() {
62
  /** @var Shield\Modules\HackGuard\Options $opts */
63
+ $opts = $this->getScanController()->getOptions();
64
  $action = $this->getScanActionVO();
65
  $action->paths_whitelisted = $opts->getWhitelistedPathsAsRegex();
66
  }
src/lib/src/Scans/Base/DiffResultForStorage.php DELETED
@@ -1,42 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
-
7
- /**
8
- * Class DiffResultForStorage
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
10
- */
11
- class DiffResultForStorage {
12
-
13
- /**
14
- * The Existing set will be updated to reflect the new current status of the scan
15
- * @param ResultsSet $existingResults - will be updated with all items to DB Update
16
- * @param ResultsSet $newResults - will be adjusted with all item to DB Insert
17
- * @return ResultsSet - A results set of all out-of-date records that need to be deleted.
18
- */
19
- public function diff( $existingResults, $newResults ) {
20
-
21
- $toDelete = new ResultsSet();
22
- $merger = new Scans\Base\BaseMergeItems();
23
-
24
- // 1 Remove items in EXISTING that are not in NEW
25
- foreach ( $existingResults->getAllItems() as $oExistItem ) {
26
- if ( !$newResults->getItemExists( $oExistItem->hash ) ) {
27
- $existingResults->removeItemByHash( $oExistItem->hash );
28
- $toDelete->addItem( $oExistItem );
29
- }
30
- }
31
-
32
- // 2 Merge NEW items into Existing items
33
- foreach ( $newResults->getAllItems() as $oNewItem ) {
34
- if ( $existingResults->getItemExists( $oNewItem->hash ) ) {
35
- $merger->mergeItemTo( $existingResults->getItemByHash( $oNewItem->hash ), $oNewItem );
36
- $newResults->removeItemByHash( $oNewItem->hash );
37
- }
38
- }
39
-
40
- return $toDelete;
41
- }
42
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Base/FileResultItem.php CHANGED
@@ -3,18 +3,12 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
 
5
  /**
6
- * Class FileResultItem
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Base
8
  * @property string $path_full
9
  * @property string $path_fragment - relative to ABSPATH
10
  */
11
  class FileResultItem extends ResultItem {
12
 
13
- public function generateHash() :string {
14
- return md5( $this->path_full );
15
- }
16
-
17
  public function getDescriptionForAudit() :string {
18
- return $this->path_full;
19
  }
20
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
 
5
  /**
 
 
6
  * @property string $path_full
7
  * @property string $path_fragment - relative to ABSPATH
8
  */
9
  class FileResultItem extends ResultItem {
10
 
 
 
 
 
11
  public function getDescriptionForAudit() :string {
12
+ return $this->path_fragment;
13
  }
14
  }
src/lib/src/Scans/Base/Files/BaseFileMapScan.php CHANGED
@@ -18,6 +18,7 @@ abstract class BaseFileMapScan extends Base\BaseScan {
18
  },
19
  // run the scan and get results:
20
  $this->getScanFromFileMap()
 
21
  ->setScanActionVO( $action )
22
  ->run()
23
  ->getAllItems()
18
  },
19
  // run the scan and get results:
20
  $this->getScanFromFileMap()
21
+ ->setScanController( $this->getScanController() )
22
  ->setScanActionVO( $action )
23
  ->run()
24
  ->getAllItems()
src/lib/src/Scans/Base/Files/BaseFileScanner.php CHANGED
@@ -1,15 +1,12 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
 
7
- /**
8
- * Class BaseFileScanner
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files
10
- */
11
  abstract class BaseFileScanner {
12
 
 
13
  use Shield\Modules\ModConsumer;
14
  use Shield\Scans\Common\ScanActionConsumer;
15
 
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
 
 
 
 
 
7
  abstract class BaseFileScanner {
8
 
9
+ use Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
10
  use Shield\Modules\ModConsumer;
11
  use Shield\Scans\Common\ScanActionConsumer;
12
 
src/lib/src/Scans/Base/Files/BaseScanFromFileMap.php CHANGED
@@ -4,16 +4,14 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Utility\VerifyFileByHash;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
 
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
9
  use FernleafSystems\Wordpress\Services\Utilities\Code\AssessPhpFile;
10
 
11
- /**
12
- * Class BaseScanFromFileMap
13
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files
14
- */
15
  abstract class BaseScanFromFileMap {
16
 
 
17
  use ModConsumer;
18
  use Scans\Common\ScanActionConsumer;
19
 
@@ -25,22 +23,23 @@ abstract class BaseScanFromFileMap {
25
  $opts = $this->getOptions();
26
 
27
  $action = $this->getScanActionVO();
28
- $results = $action->getNewResultsSet();
29
 
30
  $isAutoFilter = $opts->isAutoFilterResults();
31
 
32
  if ( is_array( $action->items ) ) {
33
- $hashVerifier = ( new VerifyFileByHash() )->setMod( $this->getMod() );
34
  foreach ( $action->items as $key => $fullPath ) {
35
 
 
36
  if ( !$isAutoFilter || !$this->isEmptyOfCode( $fullPath ) ) {
37
 
38
- if ( !$hashVerifier->verify( $fullPath ) ) {
39
- $item = $this->getFileScanner()->scan( $fullPath );
40
- // We can exclude files that are empty of relevant code
41
- if ( !empty( $item ) ) {
42
- $results->addItem( $item );
43
- }
 
44
  }
45
  }
46
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Utility\VerifyFileByHash;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\ScanControllerConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Scans;
10
  use FernleafSystems\Wordpress\Services\Utilities\Code\AssessPhpFile;
11
 
 
 
 
 
12
  abstract class BaseScanFromFileMap {
13
 
14
+ use ScanControllerConsumer;
15
  use ModConsumer;
16
  use Scans\Common\ScanActionConsumer;
17
 
23
  $opts = $this->getOptions();
24
 
25
  $action = $this->getScanActionVO();
26
+ $results = $this->getScanController()->getNewResultsSet();
27
 
28
  $isAutoFilter = $opts->isAutoFilterResults();
29
 
30
  if ( is_array( $action->items ) ) {
 
31
  foreach ( $action->items as $key => $fullPath ) {
32
 
33
+ // We can exclude files that are empty of relevant code
34
  if ( !$isAutoFilter || !$this->isEmptyOfCode( $fullPath ) ) {
35
 
36
+ $item = $this->getFileScanner()
37
+ ->setScanController( $this->getScanController() )
38
+ ->setMod( $this->getMod() )
39
+ ->setScanActionVO( $action )
40
+ ->scan( $fullPath );
41
+ if ( !empty( $item ) ) {
42
+ $results->addItem( $item );
43
  }
44
  }
45
  }
src/lib/src/Scans/Base/ResultItem.php CHANGED
@@ -2,43 +2,23 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
 
5
- use FernleafSystems\Utilities\Data\Adapter\DynProperties;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner\EntryVO;
7
 
8
  /**
9
- * Class BaseResultItem
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Base
11
- * @property string $hash
12
- * @property bool $is_excluded
13
- * @property string $scan
14
  * @property bool $repaired
15
  * @property string $repair_event_status
 
16
  */
17
- class ResultItem {
18
-
19
- use DynProperties;
20
 
21
  /**
22
- * @var EntryVO
23
  */
24
  public $VO;
25
 
26
- public function isReady() :bool {
27
- return false;
28
- }
29
-
30
- public function generateHash() :string {
31
- return md5( json_encode( $this->getRawData() ) );
32
- }
33
-
34
  public function getDescriptionForAudit() :string {
35
  return 'No description';
36
  }
37
-
38
- /**
39
- * @return mixed
40
- */
41
- public function getData() {
42
- return $this->data ?? $this->getRawData();
43
- }
44
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
4
 
5
+ use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Results\ScanResultVO;
7
 
8
  /**
9
+ * @property bool $deleted
 
 
 
 
10
  * @property bool $repaired
11
  * @property string $repair_event_status
12
+ * @property bool $auto_filter
13
  */
14
+ class ResultItem extends DynPropertiesClass {
 
 
15
 
16
  /**
17
+ * @var ScanResultVO
18
  */
19
  public $VO;
20
 
 
 
 
 
 
 
 
 
21
  public function getDescriptionForAudit() :string {
22
  return 'No description';
23
  }
 
 
 
 
 
 
 
24
  }
src/lib/src/Scans/Base/ResultsSet.php CHANGED
@@ -9,21 +9,13 @@ class ResultsSet {
9
  */
10
  protected $items;
11
 
12
- /**
13
- * @var bool
14
- */
15
- protected $bFilterExcluded = true;
16
-
17
  /**
18
  * @param ResultItem $item
19
  * @return $this
20
  */
21
  public function addItem( $item ) {
22
  $all = $this->getAllItems();
23
- if ( !isset( $item->hash ) ) {
24
- $item->hash = $item->generateHash();
25
- }
26
- $all[ $item->hash ] = $item;
27
  $this->items = $all;
28
  return $this;
29
  }
@@ -40,12 +32,11 @@ class ResultsSet {
40
  * @param string $hash
41
  * @return bool
42
  */
43
- public function getItemExists( $hash ) {
44
  return isset( $this->getAllItems()[ $hash ] );
45
  }
46
 
47
  /**
48
- * Ignores the "is_excluded" property on the items
49
  * @return ResultItem[]
50
  */
51
  public function getAllItems() :array {
@@ -58,26 +49,23 @@ class ResultsSet {
58
  /**
59
  * @return ResultItem[]
60
  */
61
- public function getExcludedItems() :array {
62
- return array_values( array_filter(
63
- $this->getAllItems(),
64
- function ( $item ) {
65
- return $item->is_excluded;
66
- }
67
- ) );
68
  }
69
 
70
  /**
71
- * Honours the exclusion flags
72
- * @return ResultItem[]
73
  */
74
- public function getItems() :array {
75
- return array_values( array_filter(
76
- $this->getAllItems(),
77
- function ( $item ) {
78
- return !$this->isFilterExcludedItems() || !$item->is_excluded;
 
 
79
  }
80
- ) );
 
81
  }
82
 
83
  public function countItems() :int {
@@ -89,39 +77,10 @@ class ResultsSet {
89
  }
90
 
91
  /**
92
- * @return bool
93
- */
94
- public function isFilterExcludedItems() {
95
- return (bool)$this->bFilterExcluded;
96
- }
97
-
98
- /**
99
- * @param ResultItem $item
100
- * @return $this
101
- */
102
- public function removeItem( $item ) {
103
- return $this->removeItemByHash( $item->hash );
104
- }
105
-
106
- /**
107
- * @param string $hash
108
- * @return $this
109
- */
110
- public function removeItemByHash( $hash ) {
111
- if ( $this->getItemExists( $hash ) ) {
112
- $items = $this->getAllItems();
113
- unset( $items[ $hash ] );
114
- $this->items = $items;
115
- }
116
- return $this;
117
- }
118
-
119
- /**
120
- * @param bool $bFilterExcluded
121
- * @return $this
122
  */
123
- public function setFilterExcludedItems( $bFilterExcluded ) {
124
- $this->bFilterExcluded = $bFilterExcluded;
125
  return $this;
126
  }
127
  }
9
  */
10
  protected $items;
11
 
 
 
 
 
 
12
  /**
13
  * @param ResultItem $item
14
  * @return $this
15
  */
16
  public function addItem( $item ) {
17
  $all = $this->getAllItems();
18
+ $all[] = $item;
 
 
 
19
  $this->items = $all;
20
  return $this;
21
  }
32
  * @param string $hash
33
  * @return bool
34
  */
35
+ public function getItemExists( $hash ) :bool {
36
  return isset( $this->getAllItems()[ $hash ] );
37
  }
38
 
39
  /**
 
40
  * @return ResultItem[]
41
  */
42
  public function getAllItems() :array {
49
  /**
50
  * @return ResultItem[]
51
  */
52
+ public function getItems() :array {
53
+ return $this->getAllItems();
 
 
 
 
 
54
  }
55
 
56
  /**
57
+ * @return static
 
58
  */
59
+ public function getNotIgnored() {
60
+ $res = clone $this;
61
+ $res->setItems( [] );
62
+ /** @var ResultItem $item */
63
+ foreach ( $this->getItems() as $item ) {
64
+ if ( $item->VO->ignored_at == 0 ) {
65
+ $res->addItem( $item );
66
  }
67
+ }
68
+ return $res;
69
  }
70
 
71
  public function countItems() :int {
77
  }
78
 
79
  /**
80
+ * @return static
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  */
82
+ public function setItems( array $items ) {
83
+ $this->items = $items;
84
  return $this;
85
  }
86
  }
src/lib/src/Scans/Base/Utilities/BaseRepair.php CHANGED
@@ -13,14 +13,8 @@ abstract class BaseRepair {
13
  * @return bool
14
  * @throws \Exception
15
  */
16
- abstract public function repairItem() :bool;
17
-
18
- /**
19
- * @return bool
20
- * @throws \Exception
21
- */
22
- public function deleteItem() :bool {
23
- throw new \Exception( 'Delete is not supported' );
24
  }
25
 
26
  /**
13
  * @return bool
14
  * @throws \Exception
15
  */
16
+ public function repairItem() :bool {
17
+ throw new \Exception( 'Item Repair is not supported' );
 
 
 
 
 
 
18
  }
19
 
20
  /**
src/lib/src/Scans/Base/Utilities/BuildScanItems.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+
7
+ abstract class BuildScanItems {
8
+
9
+ use Shield\Modules\ModConsumer;
10
+
11
+ abstract public function run() :array;
12
+ }
src/lib/src/Scans/Base/Utilities/ItemActionHandler.php CHANGED
@@ -1,8 +1,7 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Utilities;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem;
@@ -16,11 +15,9 @@ abstract class ItemActionHandler {
16
  use HackGuard\Scan\Controller\ScanControllerConsumer;
17
 
18
  /**
19
- * @param string $action
20
- * @return bool
21
  * @throws \Exception
22
  */
23
- public function process( $action ) {
24
  switch ( $action ) {
25
  case 'delete':
26
  $success = $this->delete();
@@ -45,32 +42,41 @@ abstract class ItemActionHandler {
45
  }
46
 
47
  /**
48
- * @return bool
49
  * @throws \Exception
50
  */
51
- public function delete() {
 
 
52
  $item = $this->getScanItem();
53
- if ( $this->getRepairer()->deleteItem() ) {
54
- $item->repaired = true;
 
 
 
 
 
 
 
 
 
55
  $item->repair_event_status = 'delete_success';
56
  }
 
57
  $this->fireRepairEvent();
58
- return $item->repaired;
59
  }
60
 
61
  /**
62
- * @return bool
63
  * @throws \Exception
64
  */
65
- public function ignore() {
66
- return ( new IgnoreItem() )
67
  ->setMod( $this->getMod() )
68
  ->setScanItem( $this->getScanItem() )
69
  ->ignore();
70
  }
71
 
72
  /**
73
- * @return bool
74
  * @throws \Exception
75
  */
76
  public function repairDelete() :bool {
@@ -78,57 +84,54 @@ abstract class ItemActionHandler {
78
  }
79
 
80
  /**
81
- * @param bool $allowDelete
82
- * @return bool
83
  * @throws \Exception
84
  */
85
- public function repair( bool $allowDelete = false ) {
86
- $repairer = $this->getRepairer();
87
-
88
  $item = $this->getScanItem();
89
 
90
- try {
91
- $item->repaired = $repairer->repairItem();
92
- }
93
- catch ( \Exception $e ) {
94
- $item->repaired = false;
95
- }
96
- $item->repair_event_status = $item->repaired ? 'repair_success' : 'repair_fail';
97
-
98
- if ( $allowDelete && !$item->repaired && $repairer->deleteItem() ) {
99
- $item->repaired = true;
100
- $item->repair_event_status = 'delete_success';
101
- }
 
 
 
 
 
 
102
 
103
- $this->fireRepairEvent();
104
 
105
- /** @var HackGuard\ModCon $mod */
106
- $mod = $this->getMod();
107
- if ( $item->repaired ) {
108
- /** @var Scanner\Delete $deleter */
109
- $mod->getDbHandler_ScanResults()
110
- ->getQueryDeleter()
111
- ->deleteById( $item->VO->id );
112
  }
113
- else {
114
- $mod->getDbHandler_ScanResults()
115
- ->getQueryUpdater()
116
- ->updateById( $item->VO->id, [ 'attempt_repair_at' => Services::Request()->ts() ] );
117
  }
118
 
119
- return $item->repaired;
120
  }
121
 
122
- /**
123
- * @return BaseRepair|mixed
124
- */
125
- abstract public function getRepairer();
 
126
 
127
  protected function fireRepairEvent() {
128
  /** @var ResultItem $item */
129
  $item = $this->getScanItem();
130
 
131
- if ( !empty( $item->path_full ) && !empty( $item->repair_event_status ) ) {
132
  $this->getCon()->fireEvent(
133
  sprintf( 'scan_item_%s', $item->repair_event_status ),
134
  [ 'audit_params' => [ 'path_full' => $item->path_full ] ]
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Utilities;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem;
15
  use HackGuard\Scan\Controller\ScanControllerConsumer;
16
 
17
  /**
 
 
18
  * @throws \Exception
19
  */
20
+ public function process( string $action ) :bool {
21
  switch ( $action ) {
22
  case 'delete':
23
  $success = $this->delete();
42
  }
43
 
44
  /**
 
45
  * @throws \Exception
46
  */
47
+ public function delete() :bool {
48
+ /** @var HackGuard\ModCon $mod */
49
+ $mod = $this->getMod();
50
  $item = $this->getScanItem();
51
+
52
+ $item->deleted = ( new ItemDeleteHandler() )
53
+ ->setMod( $this->getMod() )
54
+ ->setScanItem( $this->getScanItem() )
55
+ ->delete(); // Exception if can't delete
56
+ if ( $item->deleted ) {
57
+ $mod->getDbH_ResultItems()
58
+ ->getQueryUpdater()
59
+ ->updateById( $item->VO->resultitem_id, [
60
+ 'item_deleted_at' => Services::Request()->ts()
61
+ ] );
62
  $item->repair_event_status = 'delete_success';
63
  }
64
+
65
  $this->fireRepairEvent();
66
+ return $item->deleted;
67
  }
68
 
69
  /**
 
70
  * @throws \Exception
71
  */
72
+ public function ignore() :bool {
73
+ return ( new ItemIgnoreHandler() )
74
  ->setMod( $this->getMod() )
75
  ->setScanItem( $this->getScanItem() )
76
  ->ignore();
77
  }
78
 
79
  /**
 
80
  * @throws \Exception
81
  */
82
  public function repairDelete() :bool {
84
  }
85
 
86
  /**
 
 
87
  * @throws \Exception
88
  */
89
+ public function repair( bool $allowDelete = false ) :bool {
90
+ /** @var HackGuard\ModCon $mod */
91
+ $mod = $this->getMod();
92
  $item = $this->getScanItem();
93
 
94
+ $repairer = $this->getRepairHandler();
95
+ if ( $repairer->canRepairItem() ) {
96
+ try {
97
+ $item->repaired = $repairer->repairItem();
98
+ }
99
+ catch ( \Exception $e ) {
100
+ $item->repaired = false;
101
+ }
102
+
103
+ $updateInfo = [
104
+ 'attempt_repair_at' => Services::Request()->ts()
105
+ ];
106
+ if ( $item->repaired ) {
107
+ $updateInfo[ 'item_repaired_at' ] = Services::Request()->ts();
108
+ }
109
+ $mod->getDbH_ResultItems()
110
+ ->getQueryUpdater()
111
+ ->updateById( $item->VO->resultitem_id, $updateInfo );
112
 
113
+ $item->repair_event_status = $item->repaired ? 'repair_success' : 'repair_fail';
114
 
115
+ $this->fireRepairEvent();
 
 
 
 
 
 
116
  }
117
+ elseif ( $allowDelete ) {
118
+ $this->delete();
 
 
119
  }
120
 
121
+ return $item->repaired || $item->deleted;
122
  }
123
 
124
+ public function getRepairHandler() :ItemRepairHandler {
125
+ return ( new ItemRepairHandler() )
126
+ ->setMod( $this->getMod() )
127
+ ->setScanItem( $this->getScanItem() );
128
+ }
129
 
130
  protected function fireRepairEvent() {
131
  /** @var ResultItem $item */
132
  $item = $this->getScanItem();
133
 
134
+ if ( !empty( $item->path_fragment ) && !empty( $item->repair_event_status ) ) {
135
  $this->getCon()->fireEvent(
136
  sprintf( 'scan_item_%s', $item->repair_event_status ),
137
  [ 'audit_params' => [ 'path_full' => $item->path_full ] ]
src/lib/src/Scans/Base/Utilities/ItemActionHandlerAssets.php CHANGED
@@ -17,7 +17,7 @@ abstract class ItemActionHandlerAssets extends ItemActionHandler {
17
  * @return bool
18
  * @throws \Exception
19
  */
20
- public function process( $action ) {
21
  switch ( $action ) {
22
 
23
  case 'asset_deactivate':
17
  * @return bool
18
  * @throws \Exception
19
  */
20
+ public function process( string $action ) :bool {
21
  switch ( $action ) {
22
 
23
  case 'asset_deactivate':
src/lib/src/Scans/Base/Utilities/ItemDeleteHandler.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanItemConsumer;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\{
9
+ Afs\ResultItem,
10
+ Base\FileResultItem
11
+ };
12
+ use FernleafSystems\Wordpress\Services\Services;
13
+
14
+ class ItemDeleteHandler {
15
+
16
+ use ModConsumer;
17
+ use ScanItemConsumer;
18
+
19
+ /**
20
+ * @throws \Exception
21
+ */
22
+ public function delete() :bool {
23
+ $FS = Services::WpFs();
24
+ $success = false;
25
+
26
+ /** @var FileResultItem $item */
27
+ $item = $this->getScanItem();
28
+ if ( $this->canDelete() ) {
29
+ $FS->deleteFile( $item->path_full );
30
+ $success = !$FS->isFile( $item->path_full );
31
+ }
32
+
33
+ return $success;
34
+ }
35
+
36
+ protected function deleteSupported() :bool {
37
+ return in_array( $this->getScanItem()->VO->scan, [
38
+ Controller\Afs::SCAN_SLUG,
39
+ ] );
40
+ }
41
+
42
+ /**
43
+ * @return true
44
+ * @throws \Exception
45
+ */
46
+ public function canDelete() :bool {
47
+ /** @var ResultItem $item */
48
+ $item = $this->getScanItem();
49
+
50
+ if ( !$this->deleteSupported() ) {
51
+ throw new \Exception( sprintf( "Deletion isn't support for scan %s", $item->VO->scan ) );
52
+ }
53
+ if ( !$item->is_unrecognised ) {
54
+ throw new \Exception( sprintf( "File '%s' isn't unrecognised.", $item->path_fragment ) );
55
+ }
56
+ if ( !Services::WpFs()->isFile( $item->path_full ) ) {
57
+ throw new \Exception( sprintf( "File '%s' doesn't exist.", $item->path_fragment ) );
58
+ }
59
+
60
+ return true;
61
+ }
62
+ }
src/lib/src/Scans/Base/Utilities/{IgnoreItem.php → ItemIgnoreHandler.php} RENAMED
@@ -8,7 +8,7 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanItemConsumer;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
- class IgnoreItem {
12
 
13
  use ModConsumer;
14
  use ScanItemConsumer;
@@ -18,21 +18,18 @@ class IgnoreItem {
18
  * @throws \Exception
19
  */
20
  public function ignore() :bool {
21
- if ( empty( $this->getScanItem()->VO ) ) {
 
22
  throw new \Exception( 'Item could not be found to ignore.' );
23
  }
24
 
25
  /** @var HackGuard\ModCon $mod */
26
  $mod = $this->getMod();
27
- $updated = $mod->getDbHandler_ScanResults()
28
  ->getQueryUpdater()
29
- ->setUpdateWheres( [
30
- 'hash' => $this->getScanItem()->hash
31
- ] )
32
- ->setUpdateData( [
33
  'ignored_at' => Services::Request()->ts()
34
- ] )
35
- ->query();
36
  if ( !$updated ) {
37
  throw new \Exception( 'Item could not be ignored at this time.' );
38
  }
8
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanItemConsumer;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
+ class ItemIgnoreHandler {
12
 
13
  use ModConsumer;
14
  use ScanItemConsumer;
18
  * @throws \Exception
19
  */
20
  public function ignore() :bool {
21
+ $item = $this->getScanItem();
22
+ if ( empty( $item->VO ) ) {
23
  throw new \Exception( 'Item could not be found to ignore.' );
24
  }
25
 
26
  /** @var HackGuard\ModCon $mod */
27
  $mod = $this->getMod();
28
+ $updated = $mod->getDbH_ResultItems()
29
  ->getQueryUpdater()
30
+ ->updateById( $item->VO->resultitem_id, [
 
 
 
31
  'ignored_at' => Services::Request()->ts()
32
+ ] );
 
33
  if ( !$updated ) {
34
  throw new \Exception( 'Item could not be ignored at this time.' );
35
  }
src/lib/src/Scans/Base/Utilities/ItemRepairHandler.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller as ScanController;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\{
8
+ Common\ScanItemConsumer,
9
+ Afs,
10
+ Mal,
11
+ Ptg,
12
+ Wcf
13
+ };
14
+
15
+ class ItemRepairHandler {
16
+
17
+ use ModConsumer;
18
+ use ScanItemConsumer;
19
+
20
+ /**
21
+ * @throws \Exception
22
+ */
23
+ public function repairItem() :bool {
24
+ return $this->getRepairer()->repairItem();
25
+ }
26
+
27
+ /**
28
+ * @throws \Exception
29
+ */
30
+ public function canRepairItem() :bool {
31
+ return $this->isRepairSupported() && $this->getRepairer()->canRepair();
32
+ }
33
+
34
+ public function isRepairSupported() :bool {
35
+ return in_array(
36
+ $this->getScanItem()->VO->scan,
37
+ [ ScanController\Afs::SCAN_SLUG ]
38
+ );
39
+ }
40
+
41
+ /**
42
+ * @return RepairItemBase
43
+ * @throws \Exception
44
+ */
45
+ private function getRepairer() {
46
+
47
+ switch ( $this->getScanItem()->VO->scan ) {
48
+
49
+ case ScanController\Afs::SCAN_SLUG:
50
+ $rep = new Afs\Utilities\RepairItem();
51
+ break;
52
+
53
+ default:
54
+ throw new \Exception( 'We never reach this point' );
55
+ }
56
+ return $rep->setMod( $this->getMod() )
57
+ ->setScanItem( $this->getScanItem() );
58
+ }
59
+ }
src/lib/src/Scans/Base/Utilities/RepairItemBase.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanItemConsumer;
7
+
8
+ abstract class RepairItemBase {
9
+
10
+ use ModConsumer;
11
+ use ScanItemConsumer;
12
+
13
+ /**
14
+ * @return bool
15
+ * @throws \Exception
16
+ */
17
+ abstract public function repairItem() :bool;
18
+
19
+ /**
20
+ * @return bool
21
+ * @throws \Exception
22
+ */
23
+ abstract public function canRepair() :bool;
24
+ }
src/lib/src/Scans/Common/Exceptions/ItemMayBeExcludedException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\Exceptions;
4
+
5
+ class ItemMayBeExcludedException extends \Exception {
6
+
7
+ }
src/lib/src/Scans/Helpers/WpCoreFile.php CHANGED
@@ -5,10 +5,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers;
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
7
 
8
- /**
9
- * Class WpCoreFileDownload
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers
11
- */
12
  class WpCoreFile {
13
 
14
  const URL_WP_CORE = 'https://core.svn.wordpress.org';
@@ -40,23 +36,23 @@ class WpCoreFile {
40
  }
41
 
42
  /**
43
- * @param string $sPath
44
- * @param bool $bUseLocale
45
  * @return string - path to downloaded file
46
  * @throws \InvalidArgumentException
47
  */
48
- public function download( $sPath, $bUseLocale = true ) {
49
- $oHashes = Services::CoreFileHashes();
50
- if ( !$oHashes->isCoreFile( $sPath ) ) {
51
- throw new \InvalidArgumentException( sprintf( 'Core file "%s" is not an official WordPress core file.', $sPath ) );
52
  }
53
 
54
  $sLocale = Services::WpGeneral()->getLocaleForChecksums();
55
- $bUseInternational = $bUseLocale && ( $sLocale != 'en_US' );
56
 
57
- $sTmpFile = download_url( $this->getFileUrl( $sPath, $bUseLocale ) );
58
  if ( $bUseInternational && empty( $sTmpFile ) ) {
59
- $sTmpFile = $this->download( $sPath, false );
60
  } // try international retrieval and if it fails, we resort to en_US.
61
 
62
  return ( !is_wp_error( $sTmpFile ) && Services::WpFs()->exists( $sTmpFile ) ) ? $sTmpFile : null;
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
7
 
 
 
 
 
8
  class WpCoreFile {
9
 
10
  const URL_WP_CORE = 'https://core.svn.wordpress.org';
36
  }
37
 
38
  /**
39
+ * @param string $path
40
+ * @param bool $useLocale
41
  * @return string - path to downloaded file
42
  * @throws \InvalidArgumentException
43
  */
44
+ public function download( string $path, bool $useLocale = true ) {
45
+ $hashes = Services::CoreFileHashes();
46
+ if ( !$hashes->isCoreFile( $path ) ) {
47
+ throw new \InvalidArgumentException( sprintf( 'Core file "%s" is not an official WordPress core file.', $path ) );
48
  }
49
 
50
  $sLocale = Services::WpGeneral()->getLocaleForChecksums();
51
+ $bUseInternational = $useLocale && ( $sLocale != 'en_US' );
52
 
53
+ $sTmpFile = download_url( $this->getFileUrl( $path, $useLocale ) );
54
  if ( $bUseInternational && empty( $sTmpFile ) ) {
55
+ $sTmpFile = $this->download( $path, false );
56
  } // try international retrieval and if it fails, we resort to en_US.
57
 
58
  return ( !is_wp_error( $sTmpFile ) && Services::WpFs()->exists( $sTmpFile ) ) ? $sTmpFile : null;
src/lib/src/Scans/Mal/BuildScanAction.php DELETED
@@ -1,23 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- class BuildScanAction extends Shield\Scans\Base\BaseBuildScanAction {
8
-
9
- protected function buildItems() {
10
- $items = ( new BuildFileMap() )
11
- ->setMod( $this->getMod() )
12
- ->setScanActionVO( $this->getScanActionVO() )
13
- ->build();
14
- asort( $items );
15
- $this->getScanActionVO()->items = $items;
16
- }
17
-
18
- protected function setCustomFields() {
19
- /** @var ScanActionVO $action */
20
- $action = $this->getScanActionVO();
21
- $action->file_exts = [ 'php', 'php5', 'php7' ];
22
- }
23
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Mal/FileScanner.php DELETED
@@ -1,225 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib;
7
- use FernleafSystems\Wordpress\Services\Core\VOs\Assets\{
8
- WpPluginVo,
9
- WpThemeVo
10
- };
11
- use FernleafSystems\Wordpress\Services\Services;
12
- use FernleafSystems\Wordpress\Services\Utilities;
13
-
14
- class FileScanner extends Shield\Scans\Base\Files\BaseFileScanner {
15
-
16
- /**
17
- * @var Utilities\File\LocateStrInFile
18
- */
19
- private $locator;
20
-
21
- public function __construct() {
22
- $this->locator = new Utilities\File\LocateStrInFile();
23
- }
24
-
25
- /**
26
- * @param string $fullPath
27
- * @return ResultItem|null
28
- */
29
- public function scan( string $fullPath ) {
30
- $item = null;
31
-
32
- /** @var ScanActionVO $action */
33
- $action = $this->getScanActionVO();
34
-
35
- try {
36
- $this->locator->setPath( $fullPath );
37
- { // Simple Patterns first
38
- $this->locator->setIsRegEx( false );
39
- foreach ( $action->patterns_simple as $signature ) {
40
- $item = $this->scanForSig( $signature );
41
- if ( !empty( $item ) ) {
42
- break;
43
- }
44
- }
45
- }
46
-
47
- if ( empty( $item ) ) {
48
- // RegEx Patterns
49
- $this->locator->setIsRegEx( true );
50
- if ( empty( $action->patterns_fullregex ) ) {
51
- foreach ( $action->patterns_regex as $signature ) {
52
- $item = $this->scanForSig( $signature );
53
- if ( !empty( $item ) ) {
54
- break;
55
- }
56
- }
57
- }
58
- else { // Full regex patterns
59
- foreach ( $action->patterns_fullregex as $signature ) {
60
- $item = $this->scanForSig( $signature );
61
- if ( !empty( $item ) ) {
62
- break;
63
- }
64
- }
65
- }
66
- }
67
- }
68
- catch ( \Exception $e ) {
69
- }
70
-
71
- return $item;
72
- }
73
-
74
- /**
75
- * @param string $signature
76
- * @return ResultItem|null
77
- */
78
- private function scanForSig( string $signature ) {
79
- $resultItem = null;
80
- $lines = $this->locator->setNeedle( $signature )->run();
81
-
82
- if ( !empty( $lines ) ) {
83
-
84
- $fullPath = $this->locator->getPath();
85
-
86
- if ( $this->canExcludeFile( $fullPath ) ) { // we report false positives: file and lines
87
- $reporter = ( new Shield\Scans\Mal\Utilities\FalsePositiveReporter() )
88
- ->setMod( $this->getMod() );
89
- foreach ( $lines as $line ) {
90
- $reporter->reportLine( $fullPath, $line, true );
91
- }
92
- $reporter->reportPath( $fullPath, true );
93
- }
94
- else {
95
- /** @var ScanActionVO $action */
96
- $action = $this->getScanActionVO();
97
-
98
- if ( $action->confidence_threshold > 0 ) {
99
- $reportItem = false;
100
- // 1. First check whether the FP of the whole file means we can filter it
101
- $nFalsePositiveConfidence = ( new Shield\Scans\Mal\Utilities\FalsePositiveQuery() )
102
- ->setMod( $this->getMod() )
103
- ->queryPath( $fullPath );
104
- if ( $nFalsePositiveConfidence < $action->confidence_threshold ) {
105
- // 2. Check each line and filter out fp confident lines
106
- $lineScores = ( new Shield\Scans\Mal\Utilities\FalsePositiveQuery() )
107
- ->setMod( $this->getMod() )
108
- ->queryFileLines( $fullPath, array_keys( $lines ) );
109
- $lines = array_filter(
110
- $lineScores,
111
- function ( $score ) use ( $action ) {
112
- return $score < $action->confidence_threshold;
113
- }
114
- );
115
-
116
- if ( empty( $lines ) ) {
117
- // Now send False Positive report for entire file based on all file lines being FPs.
118
- ( new Shield\Scans\Mal\Utilities\FalsePositiveReporter() )
119
- ->setMod( $this->getMod() )
120
- ->reportPath( $fullPath, true );
121
- }
122
- else {
123
- $reportItem = true;
124
- }
125
- }
126
- }
127
- else {
128
- $reportItem = true;
129
- }
130
-
131
- if ( $reportItem ) {
132
- $resultItem = $this->getResultItemFromLines( array_keys( $lines ), $fullPath, $signature );
133
- }
134
- }
135
- }
136
- return $resultItem;
137
- }
138
-
139
- /**
140
- * @param string[] $lines
141
- * @param string $fullPath
142
- * @param string $signature
143
- * @return ResultItem
144
- */
145
- private function getResultItemFromLines( array $lines, string $fullPath, string $signature ) :ResultItem {
146
- $item = new ResultItem();
147
- $item->path_full = wp_normalize_path( $fullPath );
148
- $item->path_fragment = str_replace( wp_normalize_path( ABSPATH ), '', $item->path_full );
149
- $item->is_mal = true;
150
- $item->mal_sig = base64_encode( $signature );
151
- $item->fp_confidence = 0;
152
- $item->file_lines = $lines;
153
- return $item;
154
- }
155
-
156
- private function canExcludeFile( string $fullPath ) :bool {
157
- return $this->isValidCoreFile( $fullPath )
158
- || $this->isPluginFileValid( $fullPath )
159
- || $this->isThemeFileValid( $fullPath );
160
- }
161
-
162
- private function isPluginFileValid( string $fullPath ) :bool {
163
- $valid = false;
164
- try {
165
- $oPluginFiles = new Utilities\WpOrg\Plugin\Files();
166
- $plugin = $oPluginFiles->findPluginFromFile( $fullPath );
167
- if ( !empty( $plugin ) && $plugin->asset_type === 'plugin' ) {
168
- $valid = $plugin->isWpOrg() ?
169
- $oPluginFiles->verifyFileContents( $fullPath )
170
- : $this->verifyPremiumAssetFile( $fullPath, $plugin );
171
- }
172
- }
173
- catch ( \Exception $e ) {
174
- }
175
-
176
- return $valid;
177
- }
178
-
179
- private function isThemeFileValid( string $fullPath ) :bool {
180
- $valid = false;
181
- try {
182
- $oThemeFiles = new Utilities\WpOrg\Theme\Files();
183
- $theme = $oThemeFiles->findThemeFromFile( $fullPath );
184
- if ( !empty( $theme ) && $theme->asset_type === 'theme' ) {
185
- $valid = $theme->isWpOrg() ?
186
- $oThemeFiles->verifyFileContents( $fullPath )
187
- : $this->verifyPremiumAssetFile( $fullPath, $theme );
188
- }
189
- }
190
- catch ( \Exception $e ) {
191
- }
192
-
193
- return $valid;
194
- }
195
-
196
- /**
197
- * @param string $fullPath
198
- * @param WpPluginVo|WpThemeVo $oPluginOrTheme
199
- * @return bool
200
- * @throws \Exception
201
- */
202
- private function verifyPremiumAssetFile( string $fullPath, $oPluginOrTheme ) :bool {
203
- $valid = false;
204
- $hashes = ( new Lib\Snapshots\Build\BuildHashesFromApi() )
205
- ->build( $oPluginOrTheme );
206
- $fragment = str_replace( $oPluginOrTheme->getInstallDir(), '', $fullPath );
207
- if ( !empty( $hashes ) && !empty( $hashes[ $fragment ] ) ) {
208
- $valid = ( new Utilities\File\Compare\CompareHash() )
209
- ->isEqualFileMd5( $fullPath, $hashes[ $fragment ] );
210
- }
211
- return $valid;
212
- }
213
-
214
- private function isValidCoreFile( string $fullPath ) :bool {
215
- $hash = Services::CoreFileHashes()->getFileHash( $fullPath );
216
- try {
217
- $valid = !empty( $hash )
218
- && ( new Utilities\File\Compare\CompareHash() )->isEqualFileMd5( $fullPath, $hash );
219
- }
220
- catch ( \Exception $e ) {
221
- $valid = false;
222
- }
223
- return $valid;
224
- }
225
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Mal/ResultItem.php DELETED
@@ -1,18 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
-
5
- /**
6
- * Class ResultItem
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal
8
- * @property bool $is_mal
9
- * @property string $mal_sig
10
- * @property int[] $file_lines
11
- * @property int $fp_confidence - false positive confidence level
12
- */
13
- class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\FileResultItem {
14
-
15
- public function isReady() :bool {
16
- return !empty( $this->path_full ) && !empty( $this->md5_file_wp ) && !empty( $this->path_fragment );
17
- }
18
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Mal/ResultsSet.php DELETED
@@ -1,27 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
-
7
- /**
8
- * Class ResultsSet
9
- * @property ResultItem[] $items
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal
11
- */
12
- class ResultsSet extends Base\ResultsSet {
13
-
14
- /**
15
- * @param ResultItem[] $aItems
16
- * @return string[]
17
- */
18
- public function filterItemsForPaths( $aItems ) {
19
- return array_map(
20
- function ( $oItem ) {
21
- /** @var ResultItem $oItem */
22
- return $oItem->path_fragment;
23
- },
24
- $aItems
25
- );
26
- }
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Mal/ScanActionVO.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
 
 
 
5
  /**
6
  * Class ScanActionVO
7
  * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal
@@ -13,7 +15,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
13
  * @property string[] $patterns_simple
14
  * @property int $confidence_threshold
15
  */
16
- class ScanActionVO extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO {
17
 
18
  const QUEUE_GROUP_SIZE_LIMIT = 50;
19
  const DEFAULT_SLEEP_SECONDS = 0.1;
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
  /**
8
  * Class ScanActionVO
9
  * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal
15
  * @property string[] $patterns_simple
16
  * @property int $confidence_threshold
17
  */
18
+ class ScanActionVO extends BaseScanActionVO {
19
 
20
  const QUEUE_GROUP_SIZE_LIMIT = 50;
21
  const DEFAULT_SLEEP_SECONDS = 0.1;
src/lib/src/Scans/Mal/Utilities/FalsePositiveReporter.php DELETED
@@ -1,130 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\ResultItem;
7
- use FernleafSystems\Wordpress\Services\Services;
8
- use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malware;
9
-
10
- /**
11
- * Class FalsePositiveReporter
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities
13
- */
14
- class FalsePositiveReporter {
15
-
16
- const HASH_ALGO = 'sha1';
17
- use Modules\ModConsumer;
18
-
19
- /**
20
- * @param ResultItem $oIt
21
- * @param bool $bIsFalsePositive
22
- */
23
- public function reportResultItem( ResultItem $oIt, $bIsFalsePositive = true ) {
24
- $this->reportPath( $oIt->path_full, $bIsFalsePositive );
25
- $this->reportFileLines( $oIt->path_full, $oIt->file_lines, $bIsFalsePositive );
26
- }
27
-
28
- /**
29
- * @param string $sFullPath
30
- * @param int[] $aLines
31
- * @param bool $bIsFalsePositive
32
- */
33
- public function reportFileLines( $sFullPath, $aLines, $bIsFalsePositive = true ) {
34
- /** @var Modules\HackGuard\Options $oOpts */
35
- $oOpts = $this->getOptions();
36
- if ( $oOpts->isMalUseNetworkIntelligence() ) {
37
- $aFile = array_intersect_key(
38
- explode( "\n", Services::WpFs()->getFileContent( $sFullPath ) ),
39
- array_flip( $aLines )
40
- );
41
- foreach ( $aFile as $sLine ) {
42
- $this->reportLine( $sFullPath, $sLine, $bIsFalsePositive );
43
- }
44
- }
45
- }
46
-
47
- /**
48
- * To prevent duplicate reports, we cache what we report and only send the report
49
- * if we've never sent this before.
50
- * @param string $sFullPath
51
- * @param bool $bIsFalsePositive
52
- * @return mixed
53
- */
54
- public function reportPath( $sFullPath, $bIsFalsePositive = true ) {
55
- $bReported = false;
56
-
57
- /** @var Modules\HackGuard\Options $opts */
58
- $opts = $this->getOptions();
59
- if ( $opts->isMalUseNetworkIntelligence() ) {
60
-
61
- $reportHash = md5( serialize( [
62
- basename( $sFullPath ),
63
- sha1( Services::DataManipulation()->convertLineEndingsDosToLinux( $sFullPath ) ),
64
- $bIsFalsePositive
65
- ] ) );
66
-
67
- if ( !$opts->isMalFalsePositiveReported( $reportHash ) ) {
68
- $sApiToken = $this->getCon()
69
- ->getModule_License()
70
- ->getWpHashesTokenManager()
71
- ->getToken();
72
- $bReported = !empty( $sApiToken ) &&
73
- ( new Malware\Whitelist\ReportFalsePositive( $sApiToken ) )
74
- ->report( $sFullPath, static::HASH_ALGO, $bIsFalsePositive );
75
- }
76
- $this->updateReportedCache( $reportHash );
77
- }
78
- return $bReported;
79
- }
80
-
81
- /**
82
- * Only reports lines if the files has more than 1 line. i.e. 1-liner false positive files are excluded.
83
- * We still report 1-liner "true positive" files.
84
- *
85
- * @param string $sFile - path to file containing line
86
- * @param string $sLine
87
- * @param bool $bIsFalsePositive
88
- * @return mixed
89
- */
90
- public function reportLine( $sFile, $sLine, $bIsFalsePositive = true ) {
91
- $bReported = false;
92
-
93
- /** @var Modules\HackGuard\Options $oOpts */
94
- $oOpts = $this->getOptions();
95
- if ( $oOpts->isMalUseNetworkIntelligence() ) {
96
-
97
- $sReportHash = md5( $sFile.$sLine.( $bIsFalsePositive ? 'true' : 'false' ) );
98
- if ( !$oOpts->isMalFalsePositiveReported( $sReportHash ) ) {
99
- try {
100
- $sApiToken = $this->getCon()
101
- ->getModule_License()
102
- ->getWpHashesTokenManager()
103
- ->getToken();
104
- if ( !empty( $sApiToken ) && !$bIsFalsePositive || count( file( $sFile ) ) > 1 ) {
105
- $bReported = ( new Malware\Signatures\ReportFalsePositive( $sApiToken ) )
106
- ->report( $sFile, $sLine, $bIsFalsePositive );
107
- }
108
- }
109
- catch ( \Exception $e ) {
110
- }
111
- }
112
- $this->updateReportedCache( $sReportHash );
113
- }
114
- return $bReported;
115
- }
116
-
117
- /**
118
- * @param string $sReportHash
119
- */
120
- private function updateReportedCache( $sReportHash ) {
121
- /** @var Modules\HackGuard\Options $oOpts */
122
- $oOpts = $this->getOptions();
123
-
124
- $aReported = $oOpts->getMalFalsePositiveReports();
125
- $aReported[ $sReportHash ] = Services::Request()->ts();
126
- $oOpts->setMalFalsePositiveReports( $aReported );
127
-
128
- $this->getMod()->saveModOptions(); // important to save immediately due to async nature
129
- }
130
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Mal/Utilities/ItemActionHandler.php DELETED
@@ -1,39 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
-
7
- class ItemActionHandler extends Base\Utilities\ItemActionHandler {
8
-
9
- /**
10
- * @return bool
11
- * @throws \Exception
12
- */
13
- public function ignore() {
14
- parent::ignore();
15
-
16
- ( new FalsePositiveReporter() )
17
- ->setMod( $this->getMod() )
18
- ->reportResultItem( $this->getScanItem(), true );
19
-
20
- return true;
21
- }
22
-
23
- /**
24
- * @return bool
25
- * @throws \Exception
26
- */
27
- public function repairDelete() :bool {
28
- return $this->repair( true );
29
- }
30
-
31
- /**
32
- * @return Repair
33
- */
34
- public function getRepairer() {
35
- return ( new Repair() )
36
- ->setScanItem( $this->getScanItem() )
37
- ->setMod( $this->getMod() );
38
- }
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Mal/Utilities/Repair.php DELETED
@@ -1,204 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal\ResultItem;
7
- use FernleafSystems\Wordpress\Services;
8
- use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
9
-
10
- /**
11
- * Class Repair
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal
13
- */
14
- class Repair extends Shield\Scans\Base\Utilities\BaseRepair {
15
-
16
- use Shield\Modules\ModConsumer;
17
-
18
- public function repairItem() :bool {
19
- /** @var ResultItem $item */
20
- $item = $this->getScanItem();
21
- /** @var Shield\Modules\HackGuard\Options $opts */
22
- $opts = $this->getOptions();
23
- $success = false;
24
-
25
- try {
26
- $canRepair = $this->canRepair();
27
- }
28
- catch ( \Exception $e ) {
29
- $canRepair = false;
30
- }
31
-
32
- if ( $canRepair ) {
33
-
34
- if ( Services\Services::CoreFileHashes()->isCoreFile( $item->path_fragment ) ) {
35
- $success = $this->repairCoreItem();
36
- }
37
- else {
38
- $plugin = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $item->path_full );
39
- if ( $plugin instanceof Services\Core\VOs\Assets\WpPluginVo && $plugin->isWpOrg() ) {
40
-
41
- $success = $this->repairItemInPlugin();
42
- }
43
- else {
44
- $theme = ( new WpOrg\Theme\Files() )->findThemeFromFile( $item->path_full );
45
- if ( $theme instanceof Services\Core\VOs\Assets\WpThemeVo && $theme->isWpOrg() ) {
46
-
47
- $success = $this->repairItemInTheme();
48
- }
49
- elseif ( $opts->isMalAutoRepairSurgical() ) {
50
- $success = $this->repairSurgicalItem();
51
- }
52
- }
53
- }
54
- }
55
-
56
- if ( $success ) {
57
- ( new Shield\Scans\Mal\Utilities\FalsePositiveReporter() )
58
- ->setMod( $this->getMod() )
59
- ->reportResultItem( $item, false );
60
- }
61
-
62
- return $success;
63
- }
64
-
65
- public function deleteItem() :bool {
66
- /** @var ResultItem $item */
67
- $item = $this->getScanItem();
68
- return (bool)Services\Services::WpFs()->deleteFile( $item->path_full );
69
- }
70
-
71
- /**
72
- * @return bool
73
- * @throws \Exception
74
- */
75
- public function canRepair() :bool {
76
- return $this->canAutoRepairFromSource( $this->getScanItem() );
77
- }
78
-
79
- /**
80
- * Can only repair a WP Core file, or a plugin that is WP.org, has no update available
81
- * and the latest version uses SVN tags.
82
- * @param ResultItem $item
83
- * @return bool
84
- * @throws \Exception
85
- */
86
- public function canAutoRepairFromSource( ResultItem $item ) :bool {
87
-
88
- $canRepair = Services\Services::CoreFileHashes()->isCoreFile( $item->path_fragment );
89
- if ( !$canRepair ) {
90
-
91
- $plugin = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $item->path_full );
92
- if ( !empty( $plugin ) ) {
93
- if ( !$plugin->isWpOrg() ) {
94
- throw new \Exception( sprintf(
95
- __( "%s not installed from WordPress.org.", 'wp-simple-firewall' ),
96
- __( 'Plugin', 'wp-simple-firewall' )
97
- )
98
- );
99
- }
100
- if ( !$plugin->svn_uses_tags ) {
101
- throw new \Exception( __( "Plugin developer doesn't use SVN tags for official releases.", 'wp-simple-firewall' ) );
102
- }
103
-
104
- $canRepair = true;
105
- }
106
- else {
107
- $theme = ( new WpOrg\Theme\Files() )->findThemeFromFile( $item->path_full );
108
- if ( !empty( $theme ) ) {
109
- if ( $theme->is_child ) {
110
- throw new \Exception( sprintf(
111
- __( "%s is a child of another theme.", 'wp-simple-firewall' ),
112
- __( 'Theme', 'wp-simple-firewall' )
113
- )
114
- );
115
- }
116
- if ( !$theme->isWpOrg() ) {
117
- throw new \Exception( sprintf(
118
- __( "%s not installed from WordPress.org.", 'wp-simple-firewall' ),
119
- __( 'Theme', 'wp-simple-firewall' )
120
- )
121
- );
122
- }
123
- if ( !( new WpOrg\Theme\Versions() )
124
- ->setWorkingSlug( $theme->stylesheet )
125
- ->exists( $theme->version, true ) ) {
126
- throw new \Exception( __( "Theme version doesn't appear to exist.", 'wp-simple-firewall' ) );
127
- }
128
-
129
- $canRepair = true;
130
- }
131
- }
132
- }
133
-
134
- return $canRepair;
135
- }
136
-
137
- private function repairCoreItem() :bool {
138
- /** @var ResultItem $item */
139
- $item = $this->getScanItem();
140
-
141
- $files = Services\Services::WpGeneral()->isClassicPress() ? new WpOrg\Cp\Files() : new WpOrg\Wp\Files();
142
- try {
143
- $success = $files->replaceFileFromVcs( $item->path_fragment );
144
- }
145
- catch ( \InvalidArgumentException $e ) {
146
- $success = false;
147
- }
148
- return $success;
149
- }
150
-
151
- private function repairSurgicalItem() :bool {
152
- /** @var ResultItem $item */
153
- $item = $this->getScanItem();
154
-
155
- $success = false;
156
- foreach ( $item->file_lines as $nLine ) {
157
- try {
158
- ( new Services\Utilities\File\RemoveLineFromFile() )->run( $item->path_full, $nLine );
159
- $success = true;
160
- }
161
- catch ( \Exception $e ) {
162
- $success = false;
163
- break;
164
- }
165
- }
166
- return $success;
167
- }
168
-
169
- private function repairItemInPlugin() :bool {
170
- /** @var ResultItem $item */
171
- $item = $this->getScanItem();
172
-
173
- $success = false;
174
-
175
- $files = new WpOrg\Plugin\Files();
176
- try {
177
- if ( $files->isValidFileFromPlugin( $item->path_full ) ) {
178
- $success = $files->replaceFileFromVcs( $item->path_full );
179
- }
180
- }
181
- catch ( \InvalidArgumentException $e ) {
182
- }
183
-
184
- return $success;
185
- }
186
-
187
- private function repairItemInTheme() :bool {
188
- /** @var ResultItem $item */
189
- $item = $this->getScanItem();
190
-
191
- $success = false;
192
-
193
- $files = new WpOrg\Theme\Files();
194
- try {
195
- if ( $files->isValidFileFromTheme( $item->path_full ) ) {
196
- $success = $files->replaceFileFromVcs( $item->path_full );
197
- }
198
- }
199
- catch ( \InvalidArgumentException $e ) {
200
- }
201
-
202
- return $success;
203
- }
204
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/BuildFileMap.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseBuildFileMap;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers\StandardDirectoryIterator;
7
- use FernleafSystems\Wordpress\Services\Services;
8
-
9
- class BuildFileMap extends BaseBuildFileMap {
10
-
11
- /**
12
- * @return string[]
13
- */
14
- public function build() :array {
15
- $files = [];
16
-
17
- /** @var ScanActionVO $action */
18
- $action = $this->getScanActionVO();
19
-
20
- $abspath = wp_normalize_path( ABSPATH );
21
- foreach ( $this->getScanRoots() as $dir ) {
22
- try {
23
- foreach ( StandardDirectoryIterator::create( $dir, 0, $action->file_exts ) as $item ) {
24
- /** @var \SplFileInfo $item */
25
- $path = wp_normalize_path( $item->getPathname() );
26
- try {
27
- if ( !$this->isWhitelistedPath( $path ) && !$this->isAutoFilterFile( $item ) ) {
28
- $files[] = str_replace( $abspath, '', $path );
29
- }
30
- }
31
- catch ( \Exception $e ) {
32
- }
33
- }
34
- }
35
- catch ( \Exception $e ) {
36
- error_log(
37
- sprintf( 'Shield file scanner (%s) attempted to read directory (%s) but there was error: "%s".',
38
- $action->scan, $dir, $e->getMessage() )
39
- );
40
- }
41
- }
42
-
43
- return $files;
44
- }
45
-
46
- private function getScanRoots() :array {
47
- $roots = [];
48
-
49
- $WPP = Services::WpPlugins();
50
- foreach ( $WPP->getPluginsAsVo() as $plugin ) {
51
- if ( $plugin->active ) {
52
- $roots[] = $plugin->getInstallDir();
53
- }
54
- }
55
-
56
- $WPT = Services::WpThemes();
57
- $current = $WPT->getCurrent();
58
- $roots[] = $current->get_stylesheet_directory();
59
- if ( $WPT->isActiveThemeAChild() ) {
60
- $roots[] = $current->get_template_directory();
61
- }
62
-
63
- return $roots;
64
- }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/BuildScanAction.php DELETED
@@ -1,28 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- class BuildScanAction extends Shield\Scans\Base\BaseBuildScanAction {
8
-
9
- protected function buildItems() {
10
- /** @var ScanActionVO $action */
11
- $action = $this->getScanActionVO();
12
- $action->items = ( new BuildFileMap() )
13
- ->setMod( $this->getMod() )
14
- ->setScanActionVO( $action )
15
- ->build();
16
- }
17
-
18
- protected function setCustomFields() {
19
- /** @var ScanActionVO $action */
20
- $action = $this->getScanActionVO();
21
- $action->file_exts = $this->getFileExts();
22
- }
23
-
24
- private function getFileExts() :array {
25
- $ext = apply_filters( 'shield/scan_ptg_file_exts', $this->getOptions()->getDef( 'file_scan_extensions' ) );
26
- return is_array( $ext ) ? $ext : $this->getOptions()->getDef( 'file_scan_extensions' );
27
- }
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/FileScanner.php DELETED
@@ -1,225 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib;
7
- use FernleafSystems\Wordpress\Services\Core\VOs\Assets;
8
- use FernleafSystems\Wordpress\Services\Utilities\File\Compare\CompareHash;
9
- use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes;
10
- use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\CrowdSourcedHashes\Query;
11
- use FernleafSystems\Wordpress\Services\Utilities\WpOrg\Plugin;
12
- use FernleafSystems\Wordpress\Services\Utilities\WpOrg\Theme;
13
-
14
- /**
15
- * Class FileScanner
16
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg
17
- */
18
- class FileScanner extends Shield\Scans\Base\Files\BaseFileScanner {
19
-
20
- /**
21
- * @var Lib\Snapshots\Store
22
- */
23
- private $assetStore;
24
-
25
- private $csHashes;
26
-
27
- /**
28
- * @param string $fullPath - in this case it's relative to ABSPATH
29
- * @return ResultItem|null
30
- */
31
- public function scan( string $fullPath ) {
32
- $item = null;
33
- $fullPath = path_join( wp_normalize_path( ABSPATH ), $fullPath );
34
- try {
35
- $asset = ( new Plugin\Files() )->findPluginFromFile( $fullPath );
36
- if ( empty( $asset ) ) {
37
- $asset = ( new Theme\Files() )->findThemeFromFile( $fullPath );
38
- }
39
- if ( empty( $asset ) ) {
40
- throw new \Exception( sprintf( 'Could not load asset for: %s', $fullPath ) );
41
- }
42
-
43
- try {
44
- $item = $this->scanWithCsHashes( $fullPath, $asset );
45
- }
46
- catch ( \Exception $eScan ) {
47
- $item = $this->scanWithStore( $fullPath, $asset );
48
- }
49
- }
50
- catch ( \Exception $e ) {
51
- error_log( $e->getMessage() );
52
- }
53
-
54
- return $item;
55
- }
56
-
57
- /**
58
- * @param string $fullPath
59
- * @param Assets\WpPluginVo|Assets\WpThemeVo $asset
60
- * @return ResultItem|null
61
- * @throws \InvalidArgumentException|\Exception
62
- */
63
- private function scanWithStore( string $fullPath, $asset ) {
64
- $assetHashes = $this->getStore( $asset )->getSnapData();
65
- if ( empty( $assetHashes ) ) {
66
- throw new \Exception( 'File hashes from store is empty' );
67
- }
68
- $pathFragment = str_replace( $asset->getInstallDir(), '', $fullPath );
69
- $hash = $assetHashes[ $pathFragment ] ?? ( $assetHashes[ strtolower( $pathFragment ) ] ?? null );
70
- if ( empty( $hash ) ) {
71
- $item = $this->getNewItem( $asset, $fullPath );
72
- $item->path_fragment = $pathFragment;
73
- $item->is_unrecognised = true;
74
- }
75
- elseif ( !( new CompareHash() )->isEqualFileMd5( $fullPath, $hash ) ) {
76
- $item = $this->getNewItem( $asset, $fullPath );
77
- $item->path_fragment = $pathFragment;
78
- $item->is_different = true;
79
- }
80
- else {
81
- $item = null;
82
- }
83
- return $item;
84
- }
85
-
86
- /**
87
- * @param string $fullPath
88
- * @param Assets\WpPluginVo|Assets\WpThemeVo $asset
89
- * @return ResultItem|null
90
- * @throws \InvalidArgumentException|\Exception
91
- */
92
- private function scanWithHashes( string $fullPath, $asset ) {
93
- $assetHashes = ( $asset->asset_type === 'plugin' ) ?
94
- ( new WpHashes\Hashes\Plugin() )->getPluginHashes( $asset )
95
- : ( new WpHashes\Hashes\Theme() )->getThemeHashes( $asset );
96
- if ( empty( $assetHashes ) ) {
97
- throw new \Exception( 'File hashes from WPHashes is empty' );
98
- }
99
- $pathFragment = str_replace( $asset->getInstallDir(), '', $fullPath );
100
- if ( empty( $assetHashes[ $pathFragment ] ) ) {
101
- $item = $this->getNewItem( $asset, $fullPath );
102
- $item->path_fragment = $pathFragment;
103
- $item->is_unrecognised = true;
104
- }
105
- elseif ( !( new CompareHash() )->isEqualFileMd5( $fullPath, $assetHashes[ $pathFragment ] ) ) {
106
- $item = $this->getNewItem( $asset, $fullPath );
107
- $item->path_fragment = $pathFragment;
108
- $item->is_different = true;
109
- }
110
- else {
111
- $item = null;
112
- }
113
- return $item;
114
- }
115
-
116
- /**
117
- * CSHashes path fragments are all lower-case
118
- * We need to main the true, unchanged fullpath to the file, while looking up with the lower-case path fragment.
119
- * @param string $fullPath
120
- * @param Assets\WpPluginVo|Assets\WpThemeVo $asset
121
- * @return ResultItem|null
122
- * @throws \InvalidArgumentException|\Exception
123
- */
124
- private function scanWithCsHashes( string $fullPath, $asset ) {
125
- $assetHashes = $this->loadCsHashes( $asset );
126
- if ( empty( $assetHashes ) ) {
127
- throw new \Exception( 'Could not retrieve CS Hashes' );
128
- }
129
-
130
- $item = null;
131
-
132
- $trueFragment = str_replace( $asset->getInstallDir(), '', $fullPath );
133
-
134
- // we must use a lower-case key for "scan", but can't use this anywhere else.
135
- $scanFragment = strtolower( $trueFragment );
136
- if ( empty( $assetHashes[ $scanFragment ] ) ) {
137
- $item = $this->getNewItem( $asset, $fullPath );
138
- $item->path_fragment = $trueFragment;
139
- $item->is_unrecognised = true;
140
- }
141
- else {
142
- $found = false;
143
- foreach ( $assetHashes[ $scanFragment ] as $hash ) {
144
- if ( ( new CompareHash() )->isEqualFileSha1( $fullPath, $hash ) ) {
145
- $found = true;
146
- break;
147
- }
148
- }
149
-
150
- if ( !$found ) {
151
- $item = $this->getNewItem( $asset, $fullPath );
152
- $item->path_fragment = $trueFragment;
153
- $item->is_different = true;
154
- }
155
- }
156
-
157
- return $item;
158
- }
159
-
160
- /**
161
- * We "cache" the hashes temporarily in this current load
162
- * @param Assets\WpPluginVo|Assets\WpThemeVo $asset
163
- * @return string[][]
164
- */
165
- private function loadCsHashes( $asset ) :array {
166
-
167
- if ( is_array( $this->csHashes ) && $asset->unique_id !== $this->csHashes[ 0 ] ) {
168
- unset( $this->csHashes );
169
- }
170
-
171
- if ( empty( $this->csHashes ) ) {
172
-
173
- $hashes = ( $asset->asset_type === 'plugin' ? new Query\Plugin() : new Query\Theme() )
174
- ->getHashesFromVO( $asset );
175
-
176
- $this->csHashes = [ $asset->unique_id, is_array( $hashes ) ? $hashes : [] ];
177
- }
178
-
179
- return $this->csHashes[ 1 ];
180
- }
181
-
182
- /**
183
- * @param Assets\WpPluginVo|Assets\WpThemeVo $asset
184
- * @return Lib\Snapshots\Store
185
- * @throws \Exception
186
- */
187
- private function getStore( $asset ) {
188
-
189
- // Re-Use the previous store if it's for the same Asset.
190
- if ( !empty( $this->assetStore ) ) {
191
- $uniqueId = ( $asset instanceof Assets\WpPluginVo ) ? $asset->file : $asset->stylesheet;
192
- $meta = $this->assetStore->getSnapMeta();
193
- if ( $uniqueId !== $meta[ 'unique_id' ] ) {
194
- unset( $this->assetStore );
195
- }
196
- }
197
-
198
- if ( empty( $this->assetStore ) ) {
199
- $this->assetStore = ( new Lib\Snapshots\StoreAction\Load() )
200
- ->setMod( $this->getMod() )
201
- ->setAsset( $asset )
202
- ->run();
203
- }
204
-
205
- return $this->assetStore;
206
- }
207
-
208
- /**
209
- * @param Assets\WpPluginVo|Assets\WpThemeVo $asset
210
- * @param string $file
211
- * @return ResultItem
212
- */
213
- private function getNewItem( $asset, $file ) {
214
- /** @var ResultItem $item */
215
- $item = $this->getScanActionVO()->getNewResultItem();
216
- $item->path_full = $file;
217
- $item->path_fragment = $file; // will eventually be overwritten
218
- $item->is_unrecognised = false;
219
- $item->is_different = false;
220
- $item->is_missing = false;
221
- $item->context = ( $asset instanceof Assets\WpPluginVo ) ? 'plugins' : 'themes';
222
- $item->slug = ( $asset instanceof Assets\WpPluginVo ) ? $asset->file : $asset->stylesheet;
223
- return $item;
224
- }
225
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/ResultItem.php DELETED
@@ -1,16 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- /**
6
- * Class ResultItem
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg
8
- * @property string $slug
9
- * @property string $context
10
- * @property string $is_unrecognised
11
- * @property string $is_different
12
- * @property string $is_missing
13
- */
14
- class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\FileResultItem {
15
-
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/ResultsSet.php DELETED
@@ -1,258 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
-
7
- /**
8
- * Class ResultsSet
9
- * @property ResultItem[] $items
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg
11
- */
12
- class ResultsSet extends Base\ResultsSet {
13
-
14
- /**
15
- * @var string
16
- */
17
- protected $sContext;
18
-
19
- /**
20
- * @return int
21
- */
22
- public function countDifferent() {
23
- return count( $this->getDifferentItems() );
24
- }
25
-
26
- /**
27
- * @return int
28
- */
29
- public function countMissing() {
30
- return count( $this->getMissingItems() );
31
- }
32
-
33
- /**
34
- * @return int
35
- */
36
- public function countUnrecognised() {
37
- return count( $this->getUnrecognisedItems() );
38
- }
39
-
40
- /**
41
- * @param string $slug
42
- * @return ResultItem[]
43
- */
44
- public function getItemsForSlug( $slug ) {
45
- return array_values( array_filter(
46
- $this->getItems(),
47
- function ( $item ) use ( $slug ) {
48
- /** @var ResultItem $item */
49
- return $item->slug == $slug;
50
- }
51
- ) );
52
- }
53
-
54
- /**
55
- * @param string $slug
56
- * @return ResultsSet
57
- */
58
- public function getResultsSetForSlug( $slug ) {
59
- $results = new ResultsSet();
60
- array_map(
61
- function ( $item ) use ( $results ) {
62
- /** @var ResultItem $item */
63
- $results->addItem( $item );
64
- },
65
- $this->getItemsForSlug( $slug )
66
- );
67
- return $results;
68
- }
69
-
70
- /**
71
- * Tried using array_map() but this DID NOT work
72
- * Provides an array of Results Sets for each unique slug. Array keys are the slugs.
73
- * @return ResultsSet[]
74
- */
75
- public function getAllResultsSetsForUniqueSlugs() {
76
- $collection = [];
77
- foreach ( $this->getUniqueSlugs() as $slug ) {
78
- $results = $this->getResultsSetForSlug( $slug );
79
- if ( $results->hasItems() ) {
80
- $collection[ $slug ] = $results;
81
- }
82
- }
83
- ksort( $collection, SORT_NATURAL );
84
- return $collection;
85
- }
86
-
87
- /**
88
- * Provides a collection of ResultsSets for Plugins.
89
- * @return ResultsSet[]
90
- */
91
- public function getAllResultsSetsForPluginsContext() {
92
- return $this->getAllResultsSetsForContext( ScanActionVO::CONTEXT_PLUGINS );
93
- }
94
-
95
- /**
96
- * @param string $context
97
- * @return ResultsSet
98
- */
99
- public function getResultsForContext( $context ) {
100
- $results = new ResultsSet();
101
- foreach ( $this->getAllItems() as $item ) {
102
- /** @var ResultItem $item */
103
- if ( $item->context == $context ) {
104
- $results->addItem( $item );
105
- }
106
- }
107
- return $results;
108
- }
109
-
110
- /**
111
- * @return ResultsSet
112
- */
113
- public function getResultsForPluginsContext() {
114
- return $this->getResultsForContext( ScanActionVO::CONTEXT_PLUGINS );
115
- }
116
-
117
- /**
118
- * @return ResultsSet
119
- */
120
- public function getResultsForThemesContext() {
121
- return $this->getResultsForContext( ScanActionVO::CONTEXT_THEMES );
122
- }
123
-
124
- /**
125
- * Provides a collection of ResultsSets for Themes.
126
- * @return ResultsSet[]
127
- */
128
- public function getAllResultsSetsForThemesContext() {
129
- return $this->getAllResultsSetsForContext( ScanActionVO::CONTEXT_THEMES );
130
- }
131
-
132
- /**
133
- * Tried using array_filter() but this DID NOT work
134
- * Provides a collection of ResultsSets for a particular context.
135
- * @param string $sContext
136
- * @return ResultsSet[]
137
- */
138
- public function getAllResultsSetsForContext( $sContext ) {
139
- $aCollection = [];
140
- foreach ( $this->getAllResultsSetsForUniqueSlugs() as $sSlug => $oRS ) {
141
- if ( $oRS->getItems()[ 0 ]->context == $sContext ) {
142
- $aCollection[ $sSlug ] = $oRS;
143
- }
144
- }
145
- return $aCollection;
146
- }
147
-
148
- /**
149
- * @return string[]
150
- */
151
- public function getUniqueSlugs() {
152
- return array_unique( array_map(
153
- function ( $item ) {
154
- /** @var ResultItem $item */
155
- return $item->slug;
156
- },
157
- $this->getItems()
158
- ) );
159
- }
160
-
161
- /**
162
- * @param ResultItem[] $aItems
163
- * @return string[]
164
- */
165
- public function filterItemsForPaths( $aItems ) {
166
- return array_map(
167
- function ( $oItem ) {
168
- /** @var ResultItem $oItem */
169
- return $oItem->path_full;
170
- },
171
- $aItems
172
- );
173
- }
174
-
175
- /**
176
- * @return ResultItem[]
177
- */
178
- public function getDifferentItems() {
179
- return array_values( array_filter(
180
- $this->getItems(),
181
- function ( $oItem ) {
182
- /** @var ResultItem $oItem */
183
- return $oItem->is_different;
184
- }
185
- ) );
186
- }
187
-
188
- /**
189
- * @return ResultItem[]
190
- */
191
- public function getMissingItems() {
192
- return array_values( array_filter(
193
- $this->getItems(),
194
- function ( $oItem ) {
195
- /** @var ResultItem $oItem */
196
- return $oItem->is_missing;
197
- }
198
- ) );
199
- }
200
-
201
- /**
202
- * @return ResultItem[]
203
- */
204
- public function getUnrecognisedItems() {
205
- return array_values( array_filter(
206
- $this->getItems(),
207
- function ( $oItem ) {
208
- /** @var ResultItem $oItem */
209
- return $oItem->is_unrecognised;
210
- }
211
- ) );
212
- }
213
-
214
- /**
215
- * @return string[]
216
- */
217
- public function getItemsPathsFull() {
218
- return array_map(
219
- function ( $oItem ) {
220
- /** @var ResultItem $oItem */
221
- return $oItem->path_full;
222
- },
223
- $this->getItems()
224
- );
225
- }
226
-
227
- /**
228
- * @param string $sProperty
229
- * @param string $mValue
230
- * @return $this
231
- */
232
- public function setPropertyOnAllItems( $sProperty, $mValue ) {
233
- array_map(
234
- function ( $oItem ) use ( $sProperty, $mValue ) {
235
- /** @var ResultItem $oItem */
236
- $oItem->{$sProperty} = $mValue;
237
- },
238
- $this->getAllItems()
239
- );
240
- return $this;
241
- }
242
-
243
- /**
244
- * @param string $sContext
245
- * @return $this
246
- */
247
- public function setContextOnAllItems( $sContext ) {
248
- return $this->setPropertyOnAllItems( 'context', $sContext );
249
- }
250
-
251
- /**
252
- * @param string $sSlug
253
- * @return $this
254
- */
255
- public function setSlugOnAllItems( $sSlug ) {
256
- return $this->setPropertyOnAllItems( 'slug', $sSlug );
257
- }
258
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/Scan.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- class Scan extends Shield\Scans\Base\Files\BaseFileMapScan {
8
-
9
- /**
10
- * @return ScanFromFileMap
11
- */
12
- protected function getScanFromFileMap() {
13
- return ( new ScanFromFileMap() )
14
- ->setMod( $this->getMod() )
15
- ->setScanActionVO( $this->getScanActionVO() );
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/ScanActionVO.php CHANGED
@@ -2,13 +2,12 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
 
 
 
5
  /**
6
- * Class ScanActionVO
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg
8
- * @property string[] $scan_root_dirs
9
  * @property string[] $file_exts
10
  */
11
- class ScanActionVO extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO {
12
 
13
  const CONTEXT_PLUGINS = 'plugins';
14
  const CONTEXT_THEMES = 'themes';
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
  /**
 
 
 
8
  * @property string[] $file_exts
9
  */
10
+ class ScanActionVO extends BaseScanActionVO {
11
 
12
  const CONTEXT_PLUGINS = 'plugins';
13
  const CONTEXT_THEMES = 'themes';
src/lib/src/Scans/Ptg/ScanFromFileMap.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files\BaseScanFromFileMap;
6
-
7
- /**
8
- * Class ScanFromFileMap
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Mal
10
- */
11
- class ScanFromFileMap extends BaseScanFromFileMap {
12
-
13
- /**
14
- * @var FileScanner
15
- */
16
- private $fileScanner;
17
-
18
- /**
19
- * @return FileScanner
20
- */
21
- protected function getFileScanner() {
22
- if ( empty( $this->fileScanner ) ) {
23
- $this->fileScanner = ( new FileScanner() )
24
- ->setMod( $this->getMod() )
25
- ->setScanActionVO( $this->getScanActionVO() );
26
- }
27
- return $this->fileScanner;
28
- }
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/Utilities/ItemActionHandler.php DELETED
@@ -1,116 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg\ResultItem;
9
- use FernleafSystems\Wordpress\Services\Services;
10
-
11
- class ItemActionHandler extends Base\Utilities\ItemActionHandlerAssets {
12
-
13
- /**
14
- * @param string $action
15
- * @return bool
16
- * @throws \Exception
17
- */
18
- public function process( $action ) {
19
- switch ( $action ) {
20
-
21
- case 'asset_accept':
22
- $success = $this->assetAccept();
23
- break;
24
-
25
- case 'asset_reinstall':
26
- $success = $this->assetReinstall();
27
- break;
28
-
29
- default:
30
- $success = parent::process( $action );
31
- break;
32
- }
33
-
34
- return $success;
35
- }
36
-
37
- /**
38
- * @return true
39
- * @throws \Exception
40
- */
41
- private function assetAccept() {
42
- /** @var Ptg\ResultsSet $results */
43
- $results = $this->getScanController()->getAllResults();
44
-
45
- /** @var Ptg\ResultItem $item */
46
- $item = $this->getScanItem();
47
-
48
- foreach ( $results->getItemsForSlug( $item->slug ) as $item ) {
49
- $tmpHandler = clone $this;
50
- $tmpHandler->setScanItem( $item )
51
- ->ignore();
52
- }
53
-
54
- ( new Snapshots\StoreAction\Build() )
55
- ->setMod( $this->getMod() )
56
- ->setAsset( $this->getAssetFromSlug( $item->slug ) )
57
- ->run();
58
-
59
- return true;
60
- }
61
-
62
- /**
63
- * @return bool
64
- * @throws \Exception
65
- */
66
- protected function assetReinstall() {
67
- /** @var ResultItem $item */
68
- $item = $this->getScanItem();
69
-
70
- $success = false;
71
-
72
- $WPP = Services::WpPlugins();
73
- $WPT = Services::WpThemes();
74
- if ( $WPP->isInstalled( $item->slug ) ) {
75
- $asset = $WPP->getPluginAsVo( $item->slug );
76
- if ( $asset->isWpOrg() ) {
77
- $success = $WPP->reinstall( $item->slug );
78
- }
79
- }
80
- elseif ( $WPT->isInstalled( $item->slug ) ) {
81
- $asset = $WPT->getThemeAsVo( $item->slug );
82
- if ( $asset->isWpOrg() ) {
83
- $success = $WPT->reinstall( $item->slug );
84
- }
85
- }
86
-
87
- if ( $success ) {
88
- try {
89
- ( new Snapshots\StoreAction\Build() )
90
- ->setMod( $this->getMod() )
91
- ->setAsset( $this->getAssetFromSlug( $item->slug ) )
92
- ->run();
93
- }
94
- catch ( \Exception $e ) {
95
- }
96
- }
97
-
98
- return $success;
99
- }
100
-
101
- /**
102
- * Repair PTG item if it's repairable, or it's unrecognised (i.e. delete)
103
- * @return bool
104
- * @throws \Exception
105
- */
106
- public function repairDelete() :bool {
107
- return $this->repair( true );
108
- }
109
-
110
- /**
111
- * @return Repair
112
- */
113
- public function getRepairer() {
114
- return ( new Repair() )->setScanItem( $this->getScanItem() );
115
- }
116
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ptg/Utilities/Repair.php DELETED
@@ -1,82 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg;
7
- use FernleafSystems\Wordpress\Services\Services;
8
- use FernleafSystems\Wordpress\Services\Utilities\WpOrg;
9
-
10
- /**
11
- * Class Repair
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg
13
- */
14
- class Repair extends Scans\Base\Utilities\BaseRepair {
15
-
16
- public function deleteItem() :bool {
17
- /** @var Ptg\ResultItem $item */
18
- $item = $this->getScanItem();
19
- return $item->is_unrecognised && (bool)Services::WpFs()->deleteFile( $item->path_full );
20
- }
21
-
22
- /**
23
- * @return bool
24
- * @throws \Exception
25
- */
26
- public function repairItem() :bool {
27
- /** @var Ptg\ResultItem $item */
28
- $item = $this->getScanItem();
29
-
30
- if ( $this->canRepair() ) {
31
- $success = ( $item->context == 'plugins' ) ?
32
- $this->repairPluginFile( $item->path_full )
33
- : $this->repairThemeFile( $item->path_full );
34
- }
35
- else {
36
- $success = false;
37
- }
38
-
39
- return $success;
40
- }
41
-
42
- private function repairPluginFile( string $path ) :bool {
43
- $success = false;
44
- $files = new WpOrg\Plugin\Files();
45
- try {
46
- if ( $files->isValidFileFromPlugin( $path ) ) {
47
- $success = $files->replaceFileFromVcs( $path );
48
- }
49
- }
50
- catch ( \InvalidArgumentException $e ) {
51
- }
52
- return $success;
53
- }
54
-
55
- private function repairThemeFile( string $path ) :bool {
56
- $success = false;
57
- $files = new WpOrg\Theme\Files();
58
- try {
59
- if ( $files->isValidFileFromTheme( $path ) ) {
60
- $success = $files->replaceFileFromVcs( $path );
61
- }
62
- }
63
- catch ( \InvalidArgumentException $e ) {
64
- }
65
- return $success;
66
- }
67
-
68
- public function canRepair() :bool {
69
- /** @var Ptg\ResultItem $item */
70
- $item = $this->getScanItem();
71
- if ( $item->context == 'plugins' ) {
72
- $asset = Services::WpPlugins()->getPluginAsVo( $item->slug );
73
- $canRepair = $asset->asset_type === 'plugin'
74
- && $asset->isWpOrg() && $asset->svn_uses_tags;
75
- }
76
- else {
77
- $asset = Services::WpThemes()->getThemeAsVo( $item->slug );
78
- $canRepair = $asset->asset_type === 'theme' && $asset->isWpOrg();
79
- }
80
- return $canRepair;
81
- }
82
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/BuildFileMap.php DELETED
@@ -1,52 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseBuildFileMap;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Common\ScanActionConsumer;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Helpers\StandardDirectoryIterator;
9
- use FernleafSystems\Wordpress\Services\Services;
10
-
11
- class BuildFileMap extends BaseBuildFileMap {
12
-
13
- /**
14
- * @return string[]
15
- */
16
- public function build() :array {
17
- $files = [];
18
- $coreHashes = Services::CoreFileHashes();
19
- if ( !$coreHashes->isReady() ) {
20
- return $files;
21
- }
22
-
23
- /** @var ScanActionVO $action */
24
- $action = $this->getScanActionVO();
25
-
26
- foreach ( $action->scan_dirs as $dir => $fileExts ) {
27
- try {
28
- /**
29
- * The filter handles the bulk of the file inclusions and exclusions
30
- * We can set the types (extensions) of the files to include
31
- * useful for the upload directory where we're only interested in JS and PHP
32
- * The filter will also be responsible (in this case) for filtering out
33
- * WP Core files from the collection of files to be assessed
34
- */
35
- foreach ( StandardDirectoryIterator::create( $dir, 0, $fileExts, true ) as $file ) {
36
- /** @var \SplFileInfo $file */
37
- $path = wp_normalize_path( $file->getPathname() );
38
- if ( !$coreHashes->isCoreFile( $path ) && !$this->isWhitelistedPath( $path ) && !$this->isAutoFilterFile( $file ) ) {
39
- $files[] = wp_normalize_path( $path );
40
- }
41
- }
42
- }
43
- catch ( \Exception $e ) {
44
- error_log(
45
- sprintf( 'Shield file scanner (%s) attempted to read directory (%s) but there was error: "%s".',
46
- $action->scan, $dir, $e->getMessage() )
47
- );
48
- }
49
- }
50
- return $files;
51
- }
52
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/BuildScanAction.php DELETED
@@ -1,32 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- /**
8
- * Class BuildScanAction
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc
10
- */
11
- class BuildScanAction extends Shield\Scans\Base\BaseBuildScanAction {
12
-
13
- protected function buildItems() {
14
- /** @var ScanActionVO $action */
15
- $action = $this->getScanActionVO();
16
- $action->items = ( new Shield\Scans\Ufc\BuildFileMap() )
17
- ->setMod( $this->getMod() )
18
- ->setScanActionVO( $action )
19
- ->build();
20
- }
21
-
22
- protected function setCustomFields() {
23
- /** @var ScanActionVO $action */
24
- $action = $this->getScanActionVO();
25
- /** @var Shield\Modules\HackGuard\Options $opts */
26
- $opts = $this->getOptions();
27
-
28
- $exclusions = $opts->getOpt( 'ufc_exclusions', [] );
29
- $action->exclusions = is_array( $exclusions ) ? $exclusions : [];
30
- $action->scan_dirs = $opts->getUfcScanDirectories();
31
- }
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/FileScanner.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
-
8
- class FileScanner extends Shield\Scans\Base\Files\BaseFileScanner {
9
-
10
- /**
11
- * @param string $fullPath
12
- * @return ResultItem|null
13
- */
14
- public function scan( string $fullPath ) {
15
- $item = null;
16
-
17
- $fullPath = wp_normalize_path( $fullPath );
18
- if ( !$this->isExcluded( $fullPath ) ) {
19
- /** @var ResultItem $item */
20
- $item = $this->getScanActionVO()->getNewResultItem();
21
- $item->path_full = $fullPath;
22
- $item->path_fragment = Services::CoreFileHashes()->getFileFragment( $fullPath );
23
- }
24
-
25
- return $item;
26
- }
27
-
28
- private function isExcluded( string $fullPath ) :bool {
29
- /** @var ScanActionVO $action */
30
- $action = $this->getScanActionVO();
31
-
32
- $path = wp_normalize_path( $fullPath );
33
- $filename = basename( $path );
34
-
35
- $excluded = false;
36
-
37
- foreach ( $action->exclusions as $exclusion ) {
38
-
39
- if ( preg_match( '/^#(.+)#[a-z]*$/i', $exclusion, $aMatches ) ) { // it's regex
40
- $excluded = @preg_match( stripslashes( $exclusion ), $path );
41
- }
42
- else {
43
- $exclusion = wp_normalize_path( $exclusion );
44
- if ( strpos( $exclusion, '/' ) === false ) { // filename only
45
- $excluded = $filename === $exclusion;
46
- }
47
- else {
48
- $excluded = strpos( $path, $exclusion ) !== false;
49
- }
50
- }
51
-
52
- if ( $excluded ) {
53
- break;
54
- }
55
- }
56
- return (bool)$excluded;
57
- }
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/ResultItem.php DELETED
@@ -1,7 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\FileResultItem {
6
-
7
- }
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/ResultsSet.php DELETED
@@ -1,39 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
-
7
- /**
8
- * Class ResultsSet
9
- * @property ResultItem[] $items
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc
11
- */
12
- class ResultsSet extends Base\ResultsSet {
13
-
14
- /**
15
- * @return string[]
16
- */
17
- public function getItemsPathsFull() {
18
- return array_map(
19
- function ( $oItem ) {
20
- /** @var ResultItem $oItem */
21
- return $oItem->path_full;
22
- },
23
- $this->getItems()
24
- );
25
- }
26
-
27
- /**
28
- * @return string[]
29
- */
30
- public function getItemsPathsFragments() {
31
- return array_map(
32
- function ( $oItem ) {
33
- /** @var ResultItem $oItem */
34
- return $oItem->path_fragment;
35
- },
36
- $this->getItems()
37
- );
38
- }
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/Scan.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- class Scan extends Shield\Scans\Base\Files\BaseFileMapScan {
8
-
9
- /**
10
- * @return ScanFromFileMap
11
- */
12
- protected function getScanFromFileMap() {
13
- return ( new ScanFromFileMap() )
14
- ->setMod( $this->getMod() )
15
- ->setScanActionVO( $this->getScanActionVO() );
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/ScanActionVO.php CHANGED
@@ -2,13 +2,12 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
 
 
 
5
  /**
6
- * Class ScanActionVO
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc
8
  * @property string[] $scan_dirs
9
- * @property string[] $exclusions
10
  */
11
- class ScanActionVO extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO {
12
 
13
  const QUEUE_GROUP_SIZE_LIMIT = 100;
14
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
  /**
 
 
8
  * @property string[] $scan_dirs
 
9
  */
10
+ class ScanActionVO extends BaseScanActionVO {
11
 
12
  const QUEUE_GROUP_SIZE_LIMIT = 100;
13
  }
src/lib/src/Scans/Ufc/ScanFromFileMap.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files\BaseScanFromFileMap;
6
-
7
- /**
8
- * Class ScanFromFileMap
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc
10
- */
11
- class ScanFromFileMap extends BaseScanFromFileMap {
12
-
13
- /**
14
- * @return FileScanner
15
- */
16
- protected function getFileScanner() {
17
- return ( new FileScanner() )
18
- ->setMod( $this->getMod() )
19
- ->setScanActionVO( $this->getScanActionVO() );
20
- }
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/Utilities/ItemActionHandler.php DELETED
@@ -1,24 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
7
-
8
- class ItemActionHandler extends Base\Utilities\ItemActionHandler {
9
-
10
- /**
11
- * @return bool
12
- * @throws \Exception
13
- */
14
- public function repairDelete() :bool {
15
- return $this->delete();
16
- }
17
-
18
- /**
19
- * @return Repair
20
- */
21
- public function getRepairer() {
22
- return ( new Repair() )->setScanItem( $this->getScanItem() );
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Ufc/Utilities/Repair.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Reports\ScanRepairs;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc;
8
- use FernleafSystems\Wordpress\Services\Services;
9
-
10
- /**
11
- * Class Repair
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Ufc
13
- */
14
- class Repair extends Scans\Base\Utilities\BaseRepair {
15
-
16
- /**
17
- * @inheritDoc
18
- */
19
- public function repairItem() :bool {
20
- throw new \Exception( 'Repair action is not supported' );
21
- }
22
-
23
- public function deleteItem() :bool {
24
- /** @var Ufc\ResultItem $item */
25
- $item = $this->getScanItem();
26
-
27
- $coreHashes = Services::CoreFileHashes();
28
- if ( $coreHashes->isCoreFile( $item->path_fragment ) ) {
29
- throw new \Exception( sprintf( 'File "%s" is an official WordPress core file.', $item->path_fragment ) );
30
- }
31
-
32
- $FS = Services::WpFs();
33
- return !$FS->isFile( $item->path_full ) || (bool)$FS->deleteFile( $item->path_full );
34
- }
35
-
36
- /**
37
- * @return bool
38
- * @throws \Exception
39
- */
40
- public function canRepair() :bool {
41
- /** @var Ufc\ResultItem $item */
42
- $item = $this->getScanItem();
43
- return (bool)Services::WpFs()->exists( $item->path_full );
44
- }
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/BuildFileMap.php DELETED
@@ -1,35 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseBuildFileMap;
6
- use FernleafSystems\Wordpress\Services\Services;
7
-
8
- /**
9
- * Class BuildFileMap
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
11
- */
12
- class BuildFileMap extends BaseBuildFileMap {
13
-
14
- /**
15
- * @return string[]
16
- */
17
- public function build() :array {
18
- $files = [];
19
-
20
- $coreHashes = Services::CoreFileHashes();
21
- if ( $coreHashes->isReady() ) {
22
- foreach ( array_keys( $coreHashes->getHashes() ) as $fragment ) {
23
- // To reduce noise, we exclude plugins and themes (by default)
24
- if ( strpos( $fragment, 'wp-content/' ) === 0 ) {
25
- continue;
26
- }
27
- $fullPath = wp_normalize_path( path_join( ABSPATH, $fragment ) );
28
- if ( !$this->isWhitelistedPath( $fullPath ) ) {
29
- $files[] = $fullPath;
30
- }
31
- }
32
- }
33
- return $files;
34
- }
35
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/BuildScanAction.php DELETED
@@ -1,27 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- class BuildScanAction extends Shield\Scans\Base\BaseBuildScanAction {
8
-
9
- protected function buildItems() {
10
- /** @var ScanActionVO $action */
11
- $action = $this->getScanActionVO();
12
- $action->items = ( new Shield\Scans\Wcf\BuildFileMap() )
13
- ->setMod( $this->getMod() )
14
- ->setScanActionVO( $action )
15
- ->build();
16
- }
17
-
18
- protected function setCustomFields() {
19
- /** @var ScanActionVO $action */
20
- $action = $this->getScanActionVO();
21
- /** @var Shield\Modules\HackGuard\Options $opts */
22
- $opts = $this->getOptions();
23
-
24
- $action->exclusions_missing_regex = $opts->getWcfMissingExclusions();
25
- $action->exclusions_files_regex = $opts->getWcfFileExclusions();
26
- }
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/FileScanner.php DELETED
@@ -1,76 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
- use FernleafSystems\Wordpress\Services\Utilities\File\Compare\CompareHash;
8
-
9
- /**
10
- * Class FileScanner
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
12
- */
13
- class FileScanner extends Shield\Scans\Base\Files\BaseFileScanner {
14
-
15
- /**
16
- * @param string $fullPath
17
- * @return ResultItem|null
18
- */
19
- public function scan( string $fullPath ) {
20
- $results = null;
21
- $oHashes = Services::CoreFileHashes();
22
-
23
- /** @var ResultItem $item */
24
- $item = $this->getScanActionVO()->getNewResultItem();
25
- $item->path_full = $fullPath;
26
- $item->path_fragment = $oHashes->getFileFragment( $fullPath );
27
- $item->md5_file_wp = $oHashes->getFileHash( $item->path_fragment );
28
- $item->is_missing = !Services::WpFs()->exists( $item->path_full );
29
- $item->is_checksumfail = !$item->is_missing && $this->isChecksumFail( $item );
30
- $item->is_excluded = $this->isExcluded( $item->path_fragment )
31
- || ( $item->is_missing && $this->isExcludedMissing( $item->path_fragment ) );
32
-
33
- if ( !$item->is_excluded && ( $item->is_missing || $item->is_checksumfail ) ) {
34
- $results = $item;
35
- }
36
-
37
- return $results;
38
- }
39
-
40
- /**
41
- * @param $sPathFragment
42
- * @return false|int
43
- */
44
- private function isExcluded( $sPathFragment ) {
45
- /** @var ScanActionVO $oAction */
46
- $oAction = $this->getScanActionVO();
47
- return !empty( $oAction->exclusions_files_regex ) && preg_match( $oAction->exclusions_files_regex, $sPathFragment );
48
- }
49
-
50
- /**
51
- * @param $sPathFragment
52
- * @return false|int
53
- */
54
- private function isExcludedMissing( $sPathFragment ) {
55
- /** @var ScanActionVO $oAction */
56
- $oAction = $this->getScanActionVO();
57
- return !empty( $oAction->exclusions_missing_regex ) && preg_match( $oAction->exclusions_missing_regex, $sPathFragment );
58
- }
59
-
60
- /**
61
- * @param ResultItem $item
62
- * @return bool
63
- */
64
- private function isChecksumFail( $item ) {
65
- $fail = false;
66
- if ( !$item->is_missing ) {
67
- try {
68
- $fail = ( strpos( $item->path_full, '.php' ) > 0 )
69
- && !( new CompareHash() )->isEqualFileMd5( $item->path_full, $item->md5_file_wp );
70
- }
71
- catch ( \Exception $e ) {
72
- }
73
- }
74
- return $fail;
75
- }
76
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/ResultItem.php DELETED
@@ -1,17 +0,0 @@
1
- <?php declare( strict_types=1 );
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- /**
6
- * Class ResultItem
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
8
- * @property string $md5_file_wp
9
- * @property bool $is_checksumfail
10
- * @property bool $is_missing
11
- */
12
- class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\FileResultItem {
13
-
14
- public function isReady() :bool {
15
- return !empty( $this->path_full ) && !empty( $this->md5_file_wp ) && !empty( $this->path_fragment );
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/ResultsSet.php DELETED
@@ -1,94 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
-
7
- /**
8
- * Class ResultsSet
9
- * @property ResultItem[] $items
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
11
- */
12
- class ResultsSet extends Base\ResultsSet {
13
-
14
- /**
15
- * @param ResultItem[] $items
16
- * @return string[]
17
- */
18
- public function filterItemsForPaths( $items ) {
19
- return array_map(
20
- function ( $item ) {
21
- return $item->path_fragment;
22
- },
23
- $items
24
- );
25
- }
26
-
27
- /**
28
- * @return ResultItem[]
29
- */
30
- public function getChecksumFailedItems() {
31
- return array_values( array_filter(
32
- $this->getItems(),
33
- function ( $oItem ) {
34
- /** @var ResultItem $oItem */
35
- return $oItem->is_checksumfail;
36
- }
37
- ) );
38
- }
39
-
40
- /**
41
- * @return string[]
42
- */
43
- public function getChecksumFailedPaths() {
44
- return $this->filterItemsForPaths( $this->getChecksumFailedItems() );
45
- }
46
-
47
- /**
48
- * @return ResultItem[]
49
- */
50
- public function getMissingItems() {
51
- return array_values( array_filter(
52
- $this->getItems(),
53
- function ( $oItem ) {
54
- /** @var ResultItem $oItem */
55
- return $oItem->is_missing;
56
- }
57
- ) );
58
- }
59
-
60
- /**
61
- * @return string[]
62
- */
63
- public function getMissingPaths() {
64
- return $this->filterItemsForPaths( $this->getMissingItems() );
65
- }
66
-
67
- /**
68
- * @return int
69
- */
70
- public function countChecksumFailed() {
71
- return count( $this->getChecksumFailedItems() );
72
- }
73
-
74
- /**
75
- * @return int
76
- */
77
- public function countMissing() {
78
- return count( $this->getMissingItems() );
79
- }
80
-
81
- /**
82
- * @return bool
83
- */
84
- public function hasChecksumFailed() {
85
- return $this->countChecksumFailed() > 0;
86
- }
87
-
88
- /**
89
- * @return bool
90
- */
91
- public function hasMissing() {
92
- return $this->countMissing() > 0;
93
- }
94
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/Scan.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
-
7
- class Scan extends Shield\Scans\Base\Files\BaseFileMapScan {
8
-
9
- /**
10
- * @return ScanFromFileMap
11
- */
12
- protected function getScanFromFileMap() {
13
- return ( new ScanFromFileMap() )
14
- ->setMod( $this->getMod() )
15
- ->setScanActionVO( $this->getScanActionVO() );
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/ScanActionVO.php CHANGED
@@ -2,13 +2,15 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
 
 
 
5
  /**
6
  * Class ScanActionVO
7
  * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
8
  * @property string $exclusions_missing_regex
9
  * @property string $exclusions_files_regex
10
  */
11
- class ScanActionVO extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO {
12
 
13
  const QUEUE_GROUP_SIZE_LIMIT = 100;
14
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
  /**
8
  * Class ScanActionVO
9
  * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
10
  * @property string $exclusions_missing_regex
11
  * @property string $exclusions_files_regex
12
  */
13
+ class ScanActionVO extends BaseScanActionVO {
14
 
15
  const QUEUE_GROUP_SIZE_LIMIT = 100;
16
  }
src/lib/src/Scans/Wcf/ScanFromFileMap.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Files\BaseScanFromFileMap;
6
-
7
- /**
8
- * Class ScanFromFileMap
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf
10
- */
11
- class ScanFromFileMap extends BaseScanFromFileMap {
12
-
13
- /**
14
- * @return FileScanner
15
- */
16
- protected function getFileScanner() {
17
- return ( new FileScanner() )
18
- ->setMod( $this->getMod() )
19
- ->setScanActionVO( $this->getScanActionVO() );
20
- }
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/Utilities/ItemActionHandler.php DELETED
@@ -1,24 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
7
-
8
- class ItemActionHandler extends Base\Utilities\ItemActionHandler {
9
-
10
- /**
11
- * @return Repair
12
- */
13
- public function getRepairer() {
14
- return ( new Repair() )->setScanItem( $this->getScanItem() );
15
- }
16
-
17
- /**
18
- * @return bool
19
- * @throws \Exception
20
- */
21
- public function repairDelete() :bool {
22
- return $this->repair();
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wcf/Utilities/Repair.php DELETED
@@ -1,31 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf;
7
- use FernleafSystems\Wordpress\Services\Services;
8
-
9
- /**
10
- * Class Repair
11
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wcf\Utilities
12
- */
13
- class Repair extends Scans\Base\Utilities\BaseRepair {
14
-
15
- public function repairItem() :bool {
16
- /** @var Wcf\ResultItem $item */
17
- $item = $this->getScanItem();
18
- $path = trim( wp_normalize_path( $item->path_fragment ), '/' );
19
- return ( new Scans\Helpers\WpCoreFile() )->replace( $path );
20
- }
21
-
22
- /**
23
- * @return bool
24
- * @throws \Exception
25
- */
26
- public function canRepair() :bool {
27
- /** @var Wcf\ResultItem $item */
28
- $item = $this->getScanItem();
29
- return Services::CoreFileHashes()->isCoreFile( $item->path_full );
30
- }
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wpv/BuildScanAction.php CHANGED
@@ -1,27 +1,14 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
 
8
- class BuildScanAction extends Shield\Scans\Base\BaseBuildScanAction {
9
 
10
  protected function buildItems() {
11
- /** @var ScanActionVO $action */
12
- $action = $this->getScanActionVO();
13
-
14
- $items = array_map(
15
- function ( $nKey ) {
16
- return 'plugins';
17
- },
18
- array_flip( Services::WpPlugins()->getInstalledPluginFiles() )
19
- );
20
-
21
- $WPT = Services::WpThemes();
22
- $theme = $WPT->isActiveThemeAChild() ? $WPT->getCurrentParent() : $WPT->getCurrent();
23
- $items[ $theme->get_stylesheet() ] = 'themes';
24
-
25
- $action->items = $items;
26
  }
27
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
 
6
 
7
+ class BuildScanAction extends Base\BuildScanAction {
8
 
9
  protected function buildItems() {
10
+ $this->getScanActionVO()->items = ( new BuildScanItems() )
11
+ ->setMod( $this->getScanController()->getMod() )
12
+ ->run();
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
  }
src/lib/src/Scans/Wpv/BuildScanItems.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class BuildScanItems extends Shield\Scans\Base\Utilities\BuildScanItems {
9
+
10
+ public function run() :array {
11
+ $items = Services::WpPlugins()->getInstalledPluginFiles();
12
+
13
+ $WPT = Services::WpThemes();
14
+ $items[] = ( $WPT->isActiveThemeAChild() ? $WPT->getCurrentParent() : $WPT->getCurrent() )->get_stylesheet();
15
+
16
+ return $items;
17
+ }
18
+ }
src/lib/src/Scans/Wpv/ResultItem.php CHANGED
@@ -5,21 +5,12 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv\WpVulnDb\VulnVO;
6
 
7
  /**
8
- * Class ResultItem
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv
10
- * @property string $slug
11
- * @property string $context
12
- * @property int $wpvuln_id
13
- * @property array $wpvuln_vo
14
  */
15
  class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem {
16
 
17
- public function generateHash() :string {
18
- return md5( $this->slug.$this->wpvuln_id );
19
- }
20
-
21
  public function getDescriptionForAudit() :string {
22
- return sprintf( '%s: %s', $this->context, $this->slug );
23
  }
24
 
25
  public function getVulnVo() :VulnVO {
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv\WpVulnDb\VulnVO;
6
 
7
  /**
8
+ * @property bool $is_vulnerable
 
 
 
 
 
9
  */
10
  class ResultItem extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\ResultItem {
11
 
 
 
 
 
12
  public function getDescriptionForAudit() :string {
13
+ return sprintf( '%s: %s', ( strpos( $this->VO->item_id, '/' ) ? 'Plugin' : 'Theme' ), $this->VO->item_id );
14
  }
15
 
16
  public function getVulnVo() :VulnVO {
src/lib/src/Scans/Wpv/ResultsSet.php CHANGED
@@ -1,117 +1,32 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
 
7
- /**
8
- * Class ResultsSet
9
- * @property ResultItem[] $items
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv
11
- */
12
  class ResultsSet extends Base\ResultsSet {
13
 
14
  /**
15
- * @return int
16
- */
17
- public function countUniqueSlugs() {
18
- return count( $this->getAllResultsSetsForUniqueSlugs() );
19
- }
20
-
21
- public function countUniqueSlugsForPluginsContext() :int {
22
- return count( $this->getAllResultsSetsForPluginsContext() );
23
- }
24
-
25
- /**
26
- * @return int
27
- */
28
- public function countUniqueSlugsForThemesContext() {
29
- return count( $this->getAllResultsSetsForThemesContext() );
30
- }
31
-
32
- /**
33
- * Provides a collection of ResultsSets for Plugins.
34
- * @return ResultsSet[]
35
- */
36
- public function getAllResultsSetsForPluginsContext() :array {
37
- return $this->getAllResultsSetsForContext( 'plugins' );
38
- }
39
-
40
- /**
41
- * Provides a collection of ResultsSets for Themes.
42
- * @return ResultsSet[]
43
- */
44
- public function getAllResultsSetsForThemesContext() :array {
45
- return $this->getAllResultsSetsForContext( 'themes' );
46
- }
47
-
48
- /**
49
- * @param string $sContext
50
- * @return ResultsSet[]
51
- */
52
- public function getAllResultsSetsForContext( $sContext ) :array {
53
- $aCollection = [];
54
- foreach ( $this->getAllResultsSetsForUniqueSlugs() as $sSlug => $oRS ) {
55
- if ( $oRS->getItems()[ 0 ]->context == $sContext ) {
56
- $aCollection[ $sSlug ] = $oRS;
57
- }
58
- }
59
- return $aCollection;
60
- }
61
-
62
- /**
63
- * @return ResultsSet[]
64
- */
65
- public function getAllResultsSetsForUniqueSlugs() {
66
- $aCollection = [];
67
- foreach ( $this->getUniqueSlugs() as $sSlug ) {
68
- $oRS = $this->getResultsSetForSlug( $sSlug );
69
- if ( $oRS->hasItems() ) {
70
- $aCollection[ $sSlug ] = $oRS;
71
- }
72
- }
73
- ksort( $aCollection, SORT_NATURAL );
74
- return $aCollection;
75
- }
76
-
77
- /**
78
- * @param string $sSlug
79
  * @return ResultItem[]
80
  */
81
- public function getItemsForSlug( $sSlug ) {
82
  return array_values( array_filter(
83
  $this->getItems(),
84
- function ( $oItem ) use ( $sSlug ) {
85
- /** @var ResultItem $oItem */
86
- return $oItem->slug == $sSlug;
87
  }
88
  ) );
89
  }
90
 
91
- /**
92
- * @param string $sSlug
93
- * @return ResultsSet
94
- */
95
- public function getResultsSetForSlug( $sSlug ) {
96
- $oRes = new ResultsSet();
97
- array_map(
98
- function ( $oItem ) use ( $oRes ) {
99
- /** @var ResultItem $oItem */
100
- $oRes->addItem( $oItem );
101
- },
102
- $this->getItemsForSlug( $sSlug )
103
- );
104
- return $oRes;
105
- }
106
-
107
  /**
108
  * @return string[]
109
  */
110
  public function getUniqueSlugs() {
111
  return array_unique( array_map(
112
- function ( $oItem ) {
113
- /** @var ResultItem $oItem */
114
- return $oItem->slug;
115
  },
116
  $this->getItems()
117
  ) );
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
 
 
 
 
 
 
7
  class ResultsSet extends Base\ResultsSet {
8
 
9
  /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  * @return ResultItem[]
11
  */
12
+ public function getItemsForSlug( string $slug ) :array {
13
  return array_values( array_filter(
14
  $this->getItems(),
15
+ function ( $item ) use ( $slug ) {
16
+ /** @var ResultItem $item */
17
+ return $item->VO->item_id == $slug;
18
  }
19
  ) );
20
  }
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  /**
23
  * @return string[]
24
  */
25
  public function getUniqueSlugs() {
26
  return array_unique( array_map(
27
+ function ( $item ) {
28
+ /** @var ResultItem $item */
29
+ return $item->VO->item_id;
30
  },
31
  $this->getItems()
32
  ) );
src/lib/src/Scans/Wpv/Scan.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
@@ -11,69 +11,45 @@ class Scan extends Shield\Scans\Base\BaseScan {
11
  protected function scanSlice() {
12
  /** @var ScanActionVO $action */
13
  $action = $this->getScanActionVO();
14
- $tmpResults = $action->getNewResultsSet();
15
 
16
- $copier = new Shield\Scans\Helpers\CopyResultsSets();
17
- foreach ( $action->items as $file => $context ) {
18
- $results = $this->scanItem( $context, $file );
19
- if ( $results instanceof Shield\Scans\Base\ResultsSet ) {
20
- $copier->copyTo( $results, $tmpResults );
21
- }
22
  }
23
 
24
- $action->results = array_map(
25
- function ( $item ) {
26
- return $item->getRawData();
27
- },
28
- $tmpResults->getAllItems()
29
- );
30
  }
31
 
32
- /**
33
- * @param string $context
34
- * @param string $file
35
- * @return ResultsSet
36
- */
37
- protected function scanItem( $context, $file ) {
38
- $results = new ResultsSet();
39
-
40
- $sApiToken = $this->getCon()
41
- ->getModule_License()
42
- ->getWpHashesTokenManager()
43
- ->getToken();
44
 
45
- if ( $context == 'plugins' ) {
46
  $WPP = Services::WpPlugins();
47
- $slug = $WPP->getSlug( $file );
48
  if ( empty( $slug ) ) {
49
- $slug = dirname( $file );
50
  }
51
- $version = $WPP->getPluginAsVo( $file )->Version;
52
- $lookerUpper = new Vulnerabilities\Plugin( $sApiToken );
53
  }
54
- else {
55
- $slug = $file;
56
  $version = Services::WpThemes()->getTheme( $slug )->get( 'Version' );
57
- $lookerUpper = new Vulnerabilities\Theme( $sApiToken );
58
  }
59
 
 
 
60
  $rawVuls = $lookerUpper->getVulnerabilities( $slug, $version );
61
  if ( is_array( $rawVuls ) && !empty( $rawVuls[ 'meta' ] ) && $rawVuls[ 'meta' ][ 'total' ] > 0 ) {
62
-
63
- foreach ( array_filter( $rawVuls[ 'vulnerabilities' ] ) as $vul ) {
64
- $VO = ( new Shield\Scans\Wpv\WpVulnDb\VulnVO() )->applyFromArray( $vul );
65
- $VO->provider = $rawVuls[ 'meta' ][ 'provider' ];
66
-
67
- $item = new ResultItem();
68
- $item->slug = $file;
69
- $item->context = $context;
70
- $item->wpvuln_id = $VO->id;
71
- $item->wpvuln_vo = $VO->getRawData();
72
-
73
- $results->addItem( $item );
74
- }
75
  }
76
 
77
- return $results;
78
  }
79
  }
1
+ <?php declare( strict_types=1 );
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
11
  protected function scanSlice() {
12
  /** @var ScanActionVO $action */
13
  $action = $this->getScanActionVO();
 
14
 
15
+ $results = [];
16
+ foreach ( $action->items as $file ) {
17
+ $results[] = $this->scanItem( $file );
 
 
 
18
  }
19
 
20
+ $action->results = array_filter( $results );
 
 
 
 
 
21
  }
22
 
23
+ private function scanItem( string $scanItem ) :array {
24
+ $apiToken = $this->getCon()
25
+ ->getModule_License()
26
+ ->getWpHashesTokenManager()
27
+ ->getToken();
 
 
 
 
 
 
 
28
 
29
+ if ( strpos( $scanItem, '/' ) ) { // plugin file
30
  $WPP = Services::WpPlugins();
31
+ $slug = $WPP->getSlug( $scanItem );
32
  if ( empty( $slug ) ) {
33
+ $slug = dirname( $scanItem );
34
  }
35
+ $version = $WPP->getPluginAsVo( $scanItem )->Version;
36
+ $lookerUpper = new Vulnerabilities\Plugin( $apiToken );
37
  }
38
+ else { // theme dir
39
+ $slug = $scanItem;
40
  $version = Services::WpThemes()->getTheme( $slug )->get( 'Version' );
41
+ $lookerUpper = new Vulnerabilities\Theme( $apiToken );
42
  }
43
 
44
+ $result = [];
45
+
46
  $rawVuls = $lookerUpper->getVulnerabilities( $slug, $version );
47
  if ( is_array( $rawVuls ) && !empty( $rawVuls[ 'meta' ] ) && $rawVuls[ 'meta' ][ 'total' ] > 0 ) {
48
+ $result[ 'slug' ] = $scanItem;
49
+ $result[ 'is_vulnerable' ] = true;
50
+ $result[ 'vulnerability_total' ] = $rawVuls[ 'meta' ][ 'total' ];
 
 
 
 
 
 
 
 
 
 
51
  }
52
 
53
+ return $result;
54
  }
55
  }
src/lib/src/Scans/Wpv/ScanActionVO.php CHANGED
@@ -2,10 +2,8 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
5
- /**
6
- * Class ScanActionVO
7
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv
8
- */
9
- class ScanActionVO extends \FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO {
10
 
11
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
6
+
7
+ class ScanActionVO extends BaseScanActionVO {
 
 
8
 
9
  }
src/lib/src/Scans/Wpv/Utilities/ItemActionHandler.php CHANGED
@@ -6,10 +6,4 @@ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base;
6
 
7
  class ItemActionHandler extends Base\Utilities\ItemActionHandlerAssets {
8
 
9
- /**
10
- * @return Repair
11
- */
12
- public function getRepairer() {
13
- return ( new Repair() )->setScanItem( $this->getScanItem() );
14
- }
15
  }
6
 
7
  class ItemActionHandler extends Base\Utilities\ItemActionHandlerAssets {
8
 
 
 
 
 
 
 
9
  }
src/lib/src/Scans/Wpv/Utilities/Repair.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv\Utilities;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv;
7
- use FernleafSystems\Wordpress\Services\Core\VOs\Assets;
8
- use FernleafSystems\Wordpress\Services\Services;
9
-
10
- /**
11
- * Class Repair
12
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv
13
- */
14
- class Repair extends Scans\Base\Utilities\BaseRepair {
15
-
16
- /**
17
- * @return bool
18
- * @throws \Exception
19
- */
20
- public function repairItem() :bool {
21
- if ( !$this->canRepair() ) {
22
- throw new \Exception( 'An update is not currently available.' );
23
- }
24
-
25
- /** @var Wpv\ResultItem $item */
26
- $item = $this->getScanItem();
27
-
28
- $data = ( $item->context == 'plugins' ) ?
29
- Services::WpPlugins()->update( $item->slug )
30
- : Services::WpThemes()->update( $item->slug );
31
-
32
- return (bool)$data[ 'successful' ];
33
- }
34
-
35
- public function canRepair() :bool {
36
- /** @var Wpv\ResultItem $item */
37
- $item = $this->getScanItem();
38
-
39
- if ( $item->context == 'plugins' ) {
40
- $asset = Services::WpPlugins()->getPluginAsVo( $item->slug );
41
- }
42
- else {
43
- $asset = Services::WpThemes()->getThemeAsVo( $item->slug );
44
- }
45
- return ( $asset instanceof Assets\WpPluginVo && $asset->hasUpdate() );
46
- }
47
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Scans/Wpv/WpVulnDb/VulnVO.php CHANGED
@@ -5,8 +5,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv\WpVulnDb;
5
  use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
 
7
  /**
8
- * Class VulnVO
9
- * @package FernleafSystems\Wordpress\Plugin\Shield\Scans\Wpv\WpVulnDb
10
  * @property string|int $id
11
  * @property string $title
12
  * @property string $description
5
  use FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass;
6
 
7
  /**
 
 
8
  * @property string|int $id
9
  * @property string $title
10
  * @property string $description
src/lib/src/ShieldNetApi/FileLocker/DecryptFile.php CHANGED
@@ -10,11 +10,9 @@ class DecryptFile extends BaseShieldNetApi {
10
  const API_ACTION = 'filelocker/decrypt';
11
 
12
  /**
13
- * @param OpenSslEncryptVo $openSslVO
14
- * @param int $publicKeyId
15
- * @return string|null
16
  */
17
- public function retrieve( OpenSslEncryptVo $openSslVO, $publicKeyId ) {
18
  $content = null;
19
 
20
  $this->request_method = 'post';
@@ -29,6 +27,6 @@ class DecryptFile extends BaseShieldNetApi {
29
  if ( is_array( $raw ) && !empty( $raw[ 'data' ] ) ) {
30
  $content = base64_decode( $raw[ 'data' ][ 'opened_data' ] );
31
  }
32
- return $content;
33
  }
34
  }
10
  const API_ACTION = 'filelocker/decrypt';
11
 
12
  /**
13
+ * @param int $publicKeyId
 
 
14
  */
15
+ public function retrieve( OpenSslEncryptVo $openSslVO, $publicKeyId ) :string {
16
  $content = null;
17
 
18
  $this->request_method = 'post';
27
  if ( is_array( $raw ) && !empty( $raw[ 'data' ] ) ) {
28
  $content = base64_decode( $raw[ 'data' ][ 'opened_data' ] );
29
  }
30
+ return (string)$content;
31
  }
32
  }
src/lib/src/Tables/Build/AuditTrail.php DELETED
@@ -1,149 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Build;
4
-
5
- use FernleafSystems\Wordpress\Plugin\Shield;
6
- use FernleafSystems\Wordpress\Services\Services;
7
-
8
- /**
9
- * Class AuditTrail
10
- * @package FernleafSystems\Wordpress\Plugin\Shield\Tables\Build
11
- */
12
- class AuditTrail extends BaseBuild {
13
-
14
- /**
15
- * Override this to apply table-specific query filters.
16
- * @return $this
17
- */
18
- protected function applyCustomQueryFilters() {
19
- $params = $this->getParams();
20
- /** @var Shield\Databases\AuditTrail\Select $selector */
21
- $selector = $this->getWorkingSelector();
22
-
23
- if ( !empty( $params[ 'fEvent' ] ) ) {
24
- $selector->filterByEvent( $params[ 'fEvent' ] );
25
- }
26
-
27
- // If an IP is specified, it takes priority
28
- if ( Services::IP()->isValidIp( $params[ 'fIp' ] ) ) {
29
- $selector->filterByIp( $params[ 'fIp' ] );
30
- }
31
- elseif ( $params[ 'fExcludeYou' ] == 'Y' ) {
32
- $selector->filterByNotIp( Services::IP()->getRequestIp() );
33
- }
34
-
35
- /**
36
- * put this date stuff in the base so we can filter anything
37
- */
38
- if ( !empty( $params[ 'fDateFrom' ] ) && preg_match( '#^\d{4}-\d{2}-\d{2}$#', $params[ 'fDateFrom' ] ) ) {
39
- $aParts = explode( '-', $params[ 'fDateFrom' ] );
40
- $ts = Services::Request()->carbon()
41
- ->setDate( $aParts[ 0 ], $aParts[ 1 ], $aParts[ 2 ] )
42
- ->setTime( 0, 0 )->timestamp;
43
- $selector->filterByCreatedAt( $ts, '>' );
44
- }
45
-
46
- if ( !empty( $params[ 'fDateTo' ] ) && preg_match( '#^\d{4}-\d{2}-\d{2}$#', $params[ 'fDateTo' ] ) ) {
47
- $aParts = explode( '-', $params[ 'fDateTo' ] );
48
- $ts = Services::Request()->carbon()
49
- ->setDate( $aParts[ 0 ], $aParts[ 1 ], $aParts[ 2 ] )
50
- ->setTime( 0, 0 )
51
- ->addDay()->timestamp;
52
- $selector->filterByCreatedAt( $ts, '<' );
53
- }
54
-
55
- // if username is provided, this takes priority over "logged-in" (even if it's invalid)
56
- if ( !empty( $params[ 'fUsername' ] ) ) {
57
- $selector->filterByUsername( $params[ 'fUsername' ] );
58
- }
59
- elseif ( $params[ 'fLoggedIn' ] >= 0 ) {
60
- $selector->filterByIsLoggedIn( $params[ 'fLoggedIn' ] );
61
- }
62
-
63
- $selector->setOrderBy( 'updated_at', 'DESC', true )
64
- ->setOrderBy( 'created_at' );
65
-
66
- return $this;
67
- }
68
-
69
- protected function getCustomParams() :array {
70
- return [
71
- 'fIp' => '',
72
- 'fUsername' => '',
73
- 'fEvent' => '',
74
- 'fLoggedIn' => -1,
75
- 'fExcludeYou' => '',
76
- 'fDateFrom' => '',
77
- 'fDateTo' => '',
78
- ];
79
- }
80
-
81
- /**
82
- * @return array[]
83
- */
84
- public function getEntriesFormatted() :array {
85
- $entries = [];
86
-
87
- $srvIP = Services::IP();
88
- $you = $srvIP->getRequestIp();
89
- foreach ( $this->getEntriesRaw() as $entry ) {
90
- /** @var Shield\Databases\AuditTrail\EntryVO $entry */
91
-
92
- if ( empty( $entry->message ) ) {
93
- $msg = Shield\Modules\AuditTrail\Lib\AuditMessageBuilder::Build( $entry->event, $entry->meta );
94
- }
95
- else {
96
- $msg = $entry->message;
97
- }
98
-
99
- if ( !isset( $entries[ $entry->rid ] ) ) {
100
- $ent = $entry->getRawData();
101
- $ent[ 'meta' ] = $entry->meta;
102
- $ent[ 'event' ] = str_replace( '_', ' ', sanitize_text_field( $entry->event ) );
103
- $ent[ 'message' ] = $msg;
104
- $ent[ 'created_at' ] = $this->formatTimestampField( $entry->created_at );
105
- if ( $entry->wp_username == '-' ) {
106
- $ent[ 'wp_username' ] = __( 'Not logged-in', 'wp-simple-firewall' );
107
- }
108
-
109
- try {
110
- $ent[ 'is_you' ] = $srvIP->checkIp( $you, $entry->ip );
111
- }
112
- catch ( \Exception $e ) {
113
- $ent[ 'is_you' ] = false;
114
- }
115
-
116
- if ( empty( $entry->ip ) ) {
117
- $ent[ 'ip' ] = '';
118
- }
119
- else {
120
- $ent[ 'ip' ] = sprintf( '%s%s',
121
- $this->getIpAnalysisLink( $entry->ip ),
122
- $ent[ 'is_you' ] ? ' <small>('.__( 'You', 'wp-simple-firewall' ).')</small>' : ''
123
- );
124
- }
125
- }
126
- else {
127
- $ent = $entries[ $entry->rid ];
128
- $ent[ 'meta' ] = Services::DataManipulation()->mergeArraysRecursive( $ent[ 'meta' ], $entry->meta );
129
- $ent[ 'message' ] .= "\n".$msg;
130
- $ent[ 'category' ] = max( $ent[ 'category' ], $entry->category );
131
- }
132
-
133
- if ( $entry->count > 1 ) {
134
- $ent[ 'message' ] = $msg."\n"
135
- .sprintf( __( 'This event repeated %s times in the last 24hrs.', 'wp-simple-firewall' ), $entry->count );
136
- }
137
-
138
- $entries[ $entry->rid ] = $ent;
139
- }
140
- return $entries;
141
- }
142
-
143
- /**
144
- * @return Shield\Tables\Render\WpListTable\AuditTrail
145
- */
146
- protected function getTableRenderer() {
147
- return new Shield\Tables\Render\WpListTable\AuditTrail();
148
- }
149
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Tables/DataTables/Build/Scans/BaseForScan.php CHANGED
@@ -82,10 +82,10 @@ class BaseForScan extends Base {
82
  'searchable' => false,
83
  'visible' => true,
84
  ],
85
- 'fp_confidence' => [
86
- 'data' => 'fp_confidence',
87
  'title' => __( 'False Positive Confidence' ),
88
- 'className' => 'fp_confidence',
89
  'orderable' => true,
90
  'searchable' => false,
91
  'visible' => true,
82
  'searchable' => false,
83
  'visible' => true,
84
  ],
85
+ 'mal_fp_confidence' => [
86
+ 'data' => 'mal_fp_confidence',
87
  'title' => __( 'False Positive Confidence' ),
88
+ 'className' => 'mal_fp_confidence',
89
  'orderable' => true,
90
  'searchable' => false,
91
  'visible' => true,
src/lib/src/Tables/DataTables/Build/Scans/ForMalware.php CHANGED
@@ -11,7 +11,7 @@ class ForMalware extends BaseForScan {
11
  'rid',
12
  'file_as_href',
13
  'status',
14
- 'fp_confidence',
15
  'line_numbers',
16
  'mal_sig',
17
  'detected',
@@ -21,10 +21,10 @@ class ForMalware extends BaseForScan {
21
 
22
  protected function getColumnDefs() :array {
23
  $colDefs = parent::getColumnDefs();
24
- $colDefs[ 'fp_confidence' ] = [
25
- 'data' => 'fp_confidence',
26
  'title' => __( 'False Positive Confidence' ),
27
- 'className' => 'fp_confidence',
28
  'orderable' => true,
29
  'searchable' => false,
30
  'visible' => true,
11
  'rid',
12
  'file_as_href',
13
  'status',
14
+ 'mal_fp_confidence',
15
  'line_numbers',
16
  'mal_sig',
17
  'detected',
21
 
22
  protected function getColumnDefs() :array {
23
  $colDefs = parent::getColumnDefs();
24
+ $colDefs[ 'mal_fp_confidence' ] = [
25
+ 'data' => 'mal_fp_confidence',
26
  'title' => __( 'False Positive Confidence' ),
27
+ 'className' => 'mal_fp_confidence',
28
  'orderable' => true,
29
  'searchable' => false,
30
  'visible' => true,
src/lib/src/Tables/Render/WpListTable/AuditTrail.php DELETED
@@ -1,50 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\WpListTable;
4
-
5
- class AuditTrail extends Base {
6
-
7
- /**
8
- * Generates content for a single row of the table
9
- *
10
- * @param object $item The current item
11
- * @since 3.1.0
12
- *
13
- */
14
- public function single_row( $item ) {
15
- echo sprintf( '<tr class="audit-cat-%s">', $item[ 'category' ] );
16
- $this->single_row_columns( $item );
17
- echo '</tr>';
18
- }
19
-
20
- /**
21
- * @param array $aItem
22
- * @return string
23
- */
24
- public function column_message( $aItem ) {
25
- return sprintf( '<textarea readonly rows="%s">%s</textarea>',
26
- max( 2, (int)( strlen( $aItem[ 'message' ] )/50 ) ),
27
- sanitize_textarea_field( $aItem[ 'message' ] )
28
- );
29
- }
30
-
31
- /**
32
- * @param array $item
33
- * @return string
34
- */
35
- public function column_user( $item ) {
36
- return $item[ 'wp_username' ];
37
- }
38
-
39
- /**
40
- * @return array
41
- */
42
- public function get_columns() {
43
- return [
44
- 'user' => __( 'User' ),
45
- 'ip' => __( 'IP' ),
46
- 'message' => __( 'Message', 'wp-simple-firewall' ),
47
- 'created_at' => __( 'Date' ),
48
- ];
49
- }
50
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Tables/Render/WpListTable/Traffic.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\WpListTable;
4
-
5
- class Traffic extends Base {
6
-
7
- /**
8
- * @return array
9
- */
10
- public function get_columns() {
11
- return [
12
- 'path' => __( 'Page' ),
13
- 'visitor' => __( 'Details' ),
14
- 'request_info' => __( 'Response', 'wp-simple-firewall' ),
15
- 'created_at' => __( 'Date' ),
16
- ];
17
- }
18
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/src/Utilities/CacheDir.php CHANGED
@@ -59,6 +59,9 @@ class CacheDir {
59
  return true;
60
  }
61
 
 
 
 
62
  private function addProtections() :bool {
63
  $FS = Services::WpFs();
64
  $cacheDir = $this->getDir();
59
  return true;
60
  }
61
 
62
+ /**
63
+ * @throws \Exception
64
+ */
65
  private function addProtections() :bool {
66
  $FS = Services::WpFs();
67
  $cacheDir = $this->getDir();
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -92,10 +92,12 @@ return array(
92
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Controller' => $baseDir . '/src/Controller/Controller.php',
93
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\GetAllAvailableLocales' => $baseDir . '/src/Controller/I18n/GetAllAvailableLocales.php',
94
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\LoadTextDomain' => $baseDir . '/src/Controller/I18n/LoadTextDomain.php',
 
 
 
95
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDeactivate' => $baseDir . '/src/Controller/Plugin/PluginDeactivate.php',
96
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDelete' => $baseDir . '/src/Controller/Plugin/PluginDelete.php',
97
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\CaptureMyUpgrade' => $baseDir . '/src/Controller/Utilities/CaptureMyUpgrade.php',
98
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\DebugMode' => $baseDir . '/src/Controller/Utilities/DebugMode.php',
99
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\Upgrade' => $baseDir . '/src/Controller/Utilities/Upgrade.php',
100
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\BaseCron' => $baseDir . '/src/Crons/BaseCron.php',
101
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\DailyCron' => $baseDir . '/src/Crons/DailyCron.php',
@@ -107,12 +109,8 @@ return array(
107
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Handler' => $baseDir . '/src/Databases/AdminNotes/Handler.php',
108
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Insert' => $baseDir . '/src/Databases/AdminNotes/Insert.php',
109
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Select' => $baseDir . '/src/Databases/AdminNotes/Select.php',
110
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Delete' => $baseDir . '/src/Databases/AuditTrail/Delete.php',
111
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\EntryVO' => $baseDir . '/src/Databases/AuditTrail/EntryVO.php',
112
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Handler' => $baseDir . '/src/Databases/AuditTrail/Handler.php',
113
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Insert' => $baseDir . '/src/Databases/AuditTrail/Insert.php',
114
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Select' => $baseDir . '/src/Databases/AuditTrail/Select.php',
115
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Update' => $baseDir . '/src/Databases/AuditTrail/Update.php',
116
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\BaseQuery' => $baseDir . '/src/Databases/Base/BaseQuery.php',
117
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Delete' => $baseDir . '/src/Databases/Base/Delete.php',
118
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\EntryVO' => $baseDir . '/src/Databases/Base/EntryVO.php',
@@ -124,13 +122,6 @@ return array(
124
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => $baseDir . '/src/Databases/Base/Select.php',
125
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Traits\\Select_IPTable' => $baseDir . '/src/Databases/Base/Traits/Select_IPTable.php',
126
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => $baseDir . '/src/Databases/Base/Update.php',
127
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Common' => $baseDir . '/src/Databases/BotSignals/Common.php',
128
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Delete' => $baseDir . '/src/Databases/BotSignals/Delete.php',
129
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\EntryVO' => $baseDir . '/src/Databases/BotSignals/EntryVO.php',
130
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Handler' => $baseDir . '/src/Databases/BotSignals/Handler.php',
131
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Insert' => $baseDir . '/src/Databases/BotSignals/Insert.php',
132
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Select' => $baseDir . '/src/Databases/BotSignals/Select.php',
133
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Update' => $baseDir . '/src/Databases/BotSignals/Update.php',
134
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Delete' => $baseDir . '/src/Databases/ChangeTracking/Delete.php',
135
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\EntryVO' => $baseDir . '/src/Databases/ChangeTracking/EntryVO.php',
136
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Handler' => $baseDir . '/src/Databases/ChangeTracking/Handler.php',
@@ -187,12 +178,6 @@ return array(
187
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Insert' => $baseDir . '/src/Databases/Session/Insert.php',
188
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Select' => $baseDir . '/src/Databases/Session/Select.php',
189
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Update' => $baseDir . '/src/Databases/Session/Update.php',
190
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\BaseTraffic' => $baseDir . '/src/Databases/Traffic/BaseTraffic.php',
191
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Delete' => $baseDir . '/src/Databases/Traffic/Delete.php',
192
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\EntryVO' => $baseDir . '/src/Databases/Traffic/EntryVO.php',
193
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Handler' => $baseDir . '/src/Databases/Traffic/Handler.php',
194
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Insert' => $baseDir . '/src/Databases/Traffic/Insert.php',
195
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => $baseDir . '/src/Databases/Traffic/Select.php',
196
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Helpers\\QuickAccess' => $baseDir . '/src/Helpers/QuickAccess.php',
197
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => $baseDir . '/src/License/EddLicenseVO.php',
198
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Logging\\Processors\\RequestMetaProcessor' => $baseDir . '/src/Logging/Processors/RequestMetaProcessor.php',
@@ -225,15 +210,12 @@ return array(
225
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Insights\\OverviewCards' => $baseDir . '/src/Modules/AuditTrail/Insights/OverviewCards.php',
226
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditLogger' => $baseDir . '/src/Modules/AuditTrail/Lib/AuditLogger.php',
227
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditMessageBuilder' => $baseDir . '/src/Modules/AuditTrail/Lib/AuditMessageBuilder.php',
228
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditWriter' => $baseDir . '/src/Modules/AuditTrail/Lib/AuditWriter.php',
229
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LocalDbWriter' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/LocalDbWriter.php',
230
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LogFileHandler' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/LogFileHandler.php',
231
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileDirCreate' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php',
232
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileRotate' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileRotate.php',
233
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\DelegateAjaxHandler' => $baseDir . '/src/Modules/AuditTrail/Lib/LogTable/DelegateAjaxHandler.php',
234
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\LoadRawTableData' => $baseDir . '/src/Modules/AuditTrail/Lib/LogTable/LoadRawTableData.php',
235
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Ops\\Commit' => $baseDir . '/src/Modules/AuditTrail/Lib/Ops/Commit.php',
236
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Ops\\ConvertLegacy' => $baseDir . '/src/Modules/AuditTrail/Lib/Ops/ConvertLegacy.php',
237
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Utility\\GetLogFileContent' => $baseDir . '/src/Modules/AuditTrail/Lib/Utility/GetLogFileContent.php',
238
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\ModCon' => $baseDir . '/src/Modules/AuditTrail/ModCon.php',
239
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Options' => $baseDir . '/src/Modules/AuditTrail/Options.php',
@@ -371,6 +353,40 @@ return array(
371
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\Strings' => $baseDir . '/src/Modules/Firewall/Strings.php',
372
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\UI' => $baseDir . '/src/Modules/Firewall/UI.php',
373
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\AjaxHandler' => $baseDir . '/src/Modules/HackGuard/AjaxHandler.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Debug' => $baseDir . '/src/Modules/HackGuard/Debug.php',
375
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Insights\\OverviewCards' => $baseDir . '/src/Modules/HackGuard/Insights/OverviewCards.php',
376
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\File' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/File.php',
@@ -389,13 +405,21 @@ return array(
389
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\ReadOriginalFileContent' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/Ops/ReadOriginalFileContent.php',
390
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Restore' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Restore.php',
391
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Verify' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Verify.php',
 
 
 
 
 
392
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\FileLockerAlerts' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/FileLockerAlerts.php',
393
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\Query\\ScanCounts' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/Query/ScanCounts.php',
394
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanAlerts' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php',
395
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanRepairs' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/ScanRepairs.php',
396
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\DelegateAjaxHandler' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/DelegateAjaxHandler.php',
397
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\LoadRawTableData' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/LoadRawTableData.php',
398
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\RetrieveFileContents' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/RetrieveFileContents.php',
 
 
 
399
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForAsset' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForAsset.php',
400
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForCrowdSource' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForCrowdSource.php',
401
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromApi' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromApi.php',
@@ -419,47 +443,57 @@ return array(
419
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => $baseDir . '/src/Modules/HackGuard/Options.php',
420
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Processor' => $baseDir . '/src/Modules/HackGuard/Processor.php',
421
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionBase' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionBase.php',
422
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionLogs' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionLogs.php',
423
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionMalware' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionMalware.php',
424
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPluginThemesBase' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionPluginThemesBase.php',
425
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPlugins' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionPlugins.php',
426
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionThemes' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionThemes.php',
427
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionWordpress' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionWordpress.php',
428
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Reporting' => $baseDir . '/src/Modules/HackGuard/Reporting.php',
 
429
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Apc' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Apc.php',
430
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Base' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Base.php',
431
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\BaseForAssets' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/BaseForAssets.php',
 
432
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Mal' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Mal.php',
433
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ptg' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Ptg.php',
434
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\ScanControllerConsumer' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/ScanControllerConsumer.php',
435
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ufc' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Ufc.php',
436
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wcf' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Wcf.php',
437
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wpv' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Wpv.php',
438
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\BuildScanAction' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/BuildScanAction.php',
 
 
 
 
 
 
439
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilder' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilder.php',
440
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilderConsumer' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilderConsumer.php',
441
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CollateResults' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/CollateResults.php',
442
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CompleteQueue' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php',
443
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Controller' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/Controller.php',
444
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ConvertBetweenTypes' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ConvertBetweenTypes.php',
445
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\IsScanEnqueued' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/IsScanEnqueued.php',
 
 
 
446
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessor' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php',
447
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessorConsumer' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueProcessorConsumer.php',
448
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanEnqueue' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php',
449
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanExecute' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanExecute.php',
450
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanInitiate' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php',
451
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ConvertBetweenTypes' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php',
452
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsDelete' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsDelete.php',
453
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsRetrieve' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php',
454
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsStore' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsStore.php',
455
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsUpdate' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ResultsUpdate.php',
456
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScanActionFromSlug' => $baseDir . '/src/Modules/HackGuard/Scan/ScanActionFromSlug.php',
457
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScansController' => $baseDir . '/src/Modules/HackGuard/Scan/ScansController.php',
 
458
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\PtgAddReinstallLinks' => $baseDir . '/src/Modules/HackGuard/Scan/Utilities/PtgAddReinstallLinks.php',
459
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\WpvAddPluginRows' => $baseDir . '/src/Modules/HackGuard/Scan/Utilities/WpvAddPluginRows.php',
460
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Strings' => $baseDir . '/src/Modules/HackGuard/Strings.php',
461
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\UI' => $baseDir . '/src/Modules/HackGuard/UI.php',
462
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Upgrade' => $baseDir . '/src/Modules/HackGuard/Upgrade.php',
 
 
463
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Insights\\OverviewCards' => $baseDir . '/src/Modules/Headers/Insights/OverviewCards.php',
464
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\ModCon' => $baseDir . '/src/Modules/Headers/ModCon.php',
465
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Options' => $baseDir . '/src/Modules/Headers/Options.php',
@@ -511,7 +545,6 @@ return array(
511
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\IpAnalyse\\FindAllPluginIps' => $baseDir . '/src/Modules/IPs/Lib/IpAnalyse/FindAllPluginIps.php',
512
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\OffenseTracker' => $baseDir . '/src/Modules/IPs/Lib/OffenseTracker.php',
513
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\AddIp' => $baseDir . '/src/Modules/IPs/Lib/Ops/AddIp.php',
514
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\ConvertLegacy' => $baseDir . '/src/Modules/IPs/Lib/Ops/ConvertLegacy.php',
515
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\DeleteIp' => $baseDir . '/src/Modules/IPs/Lib/Ops/DeleteIp.php',
516
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\LookupIpOnList' => $baseDir . '/src/Modules/IPs/Lib/Ops/LookupIpOnList.php',
517
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\RetrieveIpsForLists' => $baseDir . '/src/Modules/IPs/Lib/Ops/RetrieveIpsForLists.php',
@@ -769,8 +802,6 @@ return array(
769
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\RateLimitExceededException' => $baseDir . '/src/Modules/Traffic/Lib/Limit/RateLimitExceededException.php',
770
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\TestIpLimit' => $baseDir . '/src/Modules/Traffic/Lib/Limit/TestIpLimit.php',
771
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\LogHandlers\\LocalDbWriter' => $baseDir . '/src/Modules/Traffic/Lib/LogHandlers/LocalDbWriter.php',
772
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Logger' => $baseDir . '/src/Modules/Traffic/Lib/Logger.php',
773
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Ops\\ConvertLegacy' => $baseDir . '/src/Modules/Traffic/Lib/Ops/ConvertLegacy.php',
774
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\RequestLogger' => $baseDir . '/src/Modules/Traffic/Lib/RequestLogger.php',
775
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\DelegateAjaxHandler' => $baseDir . '/src/Modules/Traffic/Lib/TrafficTable/DelegateAjaxHandler.php',
776
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\LoadRawTableData' => $baseDir . '/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php',
@@ -802,21 +833,53 @@ return array(
802
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli' => $baseDir . '/src/Modules/UserManagement/WpCli.php',
803
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli\\SessionTerminate' => $baseDir . '/src/Modules/UserManagement/WpCli/SessionTerminate.php',
804
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Render\\LocateTemplateDirs' => $baseDir . '/src/Render/LocateTemplateDirs.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
805
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\BuildScanAction' => $baseDir . '/src/Scans/Apc/BuildScanAction.php',
 
806
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\PluginScanner' => $baseDir . '/src/Scans/Apc/PluginScanner.php',
807
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => $baseDir . '/src/Scans/Apc/ResultItem.php',
808
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultsSet' => $baseDir . '/src/Scans/Apc/ResultsSet.php',
809
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Scan' => $baseDir . '/src/Scans/Apc/Scan.php',
810
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ScanActionVO' => $baseDir . '/src/Scans/Apc/ScanActionVO.php',
811
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Apc/Utilities/ItemActionHandler.php',
812
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Utilities\\Repair' => $baseDir . '/src/Scans/Apc/Utilities/Repair.php',
813
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseBuildFileMap' => $baseDir . '/src/Scans/Base/BaseBuildFileMap.php',
814
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseBuildScanAction' => $baseDir . '/src/Scans/Base/BaseBuildScanAction.php',
815
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseFileScanActionVO' => $baseDir . '/src/Scans/Base/BaseFileScanActionVO.php',
816
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseMergeItems' => $baseDir . '/src/Scans/Base/BaseMergeItems.php',
817
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScan' => $baseDir . '/src/Scans/Base/BaseScan.php',
818
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScanActionVO' => $baseDir . '/src/Scans/Base/BaseScanActionVO.php',
819
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\DiffResultForStorage' => $baseDir . '/src/Scans/Base/DiffResultForStorage.php',
820
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\FileResultItem' => $baseDir . '/src/Scans/Base/FileResultItem.php',
821
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileMapScan' => $baseDir . '/src/Scans/Base/Files/BaseFileMapScan.php',
822
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileScanner' => $baseDir . '/src/Scans/Base/Files/BaseFileScanner.php',
@@ -824,9 +887,14 @@ return array(
824
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultItem' => $baseDir . '/src/Scans/Base/ResultItem.php',
825
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultsSet' => $baseDir . '/src/Scans/Base/ResultsSet.php',
826
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\BaseRepair' => $baseDir . '/src/Scans/Base/Utilities/BaseRepair.php',
827
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\IgnoreItem' => $baseDir . '/src/Scans/Base/Utilities/IgnoreItem.php',
828
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Base/Utilities/ItemActionHandler.php',
829
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandlerAssets' => $baseDir . '/src/Scans/Base/Utilities/ItemActionHandlerAssets.php',
 
 
 
 
 
830
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanActionConsumer' => $baseDir . '/src/Scans/Common/ScanActionConsumer.php',
831
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanItemConsumer' => $baseDir . '/src/Scans/Common/ScanItemConsumer.php',
832
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\BuildHashesFromDir' => $baseDir . '/src/Scans/Helpers/BuildHashesFromDir.php',
@@ -835,56 +903,17 @@ return array(
835
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\ScannerRecursiveFilterIterator' => $baseDir . '/src/Scans/Helpers/ScannerRecursiveFilterIterator.php',
836
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\StandardDirectoryIterator' => $baseDir . '/src/Scans/Helpers/StandardDirectoryIterator.php',
837
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\WpCoreFile' => $baseDir . '/src/Scans/Helpers/WpCoreFile.php',
838
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\BuildFileMap' => $baseDir . '/src/Scans/Mal/BuildFileMap.php',
839
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\BuildScanAction' => $baseDir . '/src/Scans/Mal/BuildScanAction.php',
840
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\FileScanner' => $baseDir . '/src/Scans/Mal/FileScanner.php',
841
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ResultItem' => $baseDir . '/src/Scans/Mal/ResultItem.php',
842
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ResultsSet' => $baseDir . '/src/Scans/Mal/ResultsSet.php',
843
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Scan' => $baseDir . '/src/Scans/Mal/Scan.php',
844
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ScanActionVO' => $baseDir . '/src/Scans/Mal/ScanActionVO.php',
845
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ScanFromFileMap' => $baseDir . '/src/Scans/Mal/ScanFromFileMap.php',
846
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\FalsePositiveQuery' => $baseDir . '/src/Scans/Mal/Utilities/FalsePositiveQuery.php',
847
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\FalsePositiveReporter' => $baseDir . '/src/Scans/Mal/Utilities/FalsePositiveReporter.php',
848
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Mal/Utilities/ItemActionHandler.php',
849
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\Patterns' => $baseDir . '/src/Scans/Mal/Utilities/Patterns.php',
850
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\Repair' => $baseDir . '/src/Scans/Mal/Utilities/Repair.php',
851
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\BuildFileMap' => $baseDir . '/src/Scans/Ptg/BuildFileMap.php',
852
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\BuildScanAction' => $baseDir . '/src/Scans/Ptg/BuildScanAction.php',
853
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\FileScanner' => $baseDir . '/src/Scans/Ptg/FileScanner.php',
854
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ResultItem' => $baseDir . '/src/Scans/Ptg/ResultItem.php',
855
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ResultsSet' => $baseDir . '/src/Scans/Ptg/ResultsSet.php',
856
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\Scan' => $baseDir . '/src/Scans/Ptg/Scan.php',
857
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ScanActionVO' => $baseDir . '/src/Scans/Ptg/ScanActionVO.php',
858
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ScanFromFileMap' => $baseDir . '/src/Scans/Ptg/ScanFromFileMap.php',
859
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Ptg/Utilities/ItemActionHandler.php',
860
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\Utilities\\Repair' => $baseDir . '/src/Scans/Ptg/Utilities/Repair.php',
861
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\BuildFileMap' => $baseDir . '/src/Scans/Ufc/BuildFileMap.php',
862
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\BuildScanAction' => $baseDir . '/src/Scans/Ufc/BuildScanAction.php',
863
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\FileScanner' => $baseDir . '/src/Scans/Ufc/FileScanner.php',
864
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ResultItem' => $baseDir . '/src/Scans/Ufc/ResultItem.php',
865
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ResultsSet' => $baseDir . '/src/Scans/Ufc/ResultsSet.php',
866
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\Scan' => $baseDir . '/src/Scans/Ufc/Scan.php',
867
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ScanActionVO' => $baseDir . '/src/Scans/Ufc/ScanActionVO.php',
868
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ScanFromFileMap' => $baseDir . '/src/Scans/Ufc/ScanFromFileMap.php',
869
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Ufc/Utilities/ItemActionHandler.php',
870
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\Utilities\\Repair' => $baseDir . '/src/Scans/Ufc/Utilities/Repair.php',
871
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\BuildFileMap' => $baseDir . '/src/Scans/Wcf/BuildFileMap.php',
872
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\BuildScanAction' => $baseDir . '/src/Scans/Wcf/BuildScanAction.php',
873
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\FileScanner' => $baseDir . '/src/Scans/Wcf/FileScanner.php',
874
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ResultItem' => $baseDir . '/src/Scans/Wcf/ResultItem.php',
875
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ResultsSet' => $baseDir . '/src/Scans/Wcf/ResultsSet.php',
876
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\Scan' => $baseDir . '/src/Scans/Wcf/Scan.php',
877
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ScanActionVO' => $baseDir . '/src/Scans/Wcf/ScanActionVO.php',
878
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ScanFromFileMap' => $baseDir . '/src/Scans/Wcf/ScanFromFileMap.php',
879
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Wcf/Utilities/ItemActionHandler.php',
880
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\Utilities\\Repair' => $baseDir . '/src/Scans/Wcf/Utilities/Repair.php',
881
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\BuildScanAction' => $baseDir . '/src/Scans/Wpv/BuildScanAction.php',
 
882
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultItem' => $baseDir . '/src/Scans/Wpv/ResultItem.php',
883
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultsSet' => $baseDir . '/src/Scans/Wpv/ResultsSet.php',
884
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Scan' => $baseDir . '/src/Scans/Wpv/Scan.php',
885
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ScanActionVO' => $baseDir . '/src/Scans/Wpv/ScanActionVO.php',
886
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Wpv/Utilities/ItemActionHandler.php',
887
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Utilities\\Repair' => $baseDir . '/src/Scans/Wpv/Utilities/Repair.php',
888
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\WpVulnDb\\VulnVO' => $baseDir . '/src/Scans/Wpv/WpVulnDb/VulnVO.php',
889
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseApi' => $baseDir . '/src/ShieldNetApi/Common/BaseApi.php',
890
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseShieldNetApi' => $baseDir . '/src/ShieldNetApi/Common/BaseShieldNetApi.php',
@@ -903,7 +932,6 @@ return array(
903
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Tools\\GenerateGoogleAuthQrCode' => $baseDir . '/src/ShieldNetApi/Tools/GenerateGoogleAuthQrCode.php',
904
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\WPHashes\\SolicitToken' => $baseDir . '/src/ShieldNetApi/WPHashes/SolicitToken.php',
905
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => $baseDir . '/src/Tables/Build/AdminNotes.php',
906
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AuditTrail' => $baseDir . '/src/Tables/Build/AuditTrail.php',
907
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => $baseDir . '/src/Tables/Build/BaseBuild.php',
908
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Ip' => $baseDir . '/src/Tables/Build/Ip.php',
909
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => $baseDir . '/src/Tables/Build/Sessions.php',
@@ -918,13 +946,11 @@ return array(
918
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => $baseDir . '/src/Tables/Render/Common/BaseTable.php',
919
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpCliTable/AuditTrail.php',
920
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => $baseDir . '/src/Tables/Render/WpListTable/AdminNotes.php',
921
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpListTable/AuditTrail.php',
922
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Base' => $baseDir . '/src/Tables/Render/WpListTable/Base.php',
923
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBase' => $baseDir . '/src/Tables/Render/WpListTable/IpBase.php',
924
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBlack' => $baseDir . '/src/Tables/Render/WpListTable/IpBlack.php',
925
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpWhite' => $baseDir . '/src/Tables/Render/WpListTable/IpWhite.php',
926
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Sessions' => $baseDir . '/src/Tables/Render/WpListTable/Sessions.php',
927
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Traffic' => $baseDir . '/src/Tables/Render/WpListTable/Traffic.php',
928
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\RunTests' => $baseDir . '/src/Tests/RunTests.php',
929
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyConfig' => $baseDir . '/src/Tests/VerifyConfig.php',
930
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyEvents' => $baseDir . '/src/Tests/VerifyEvents.php',
92
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Controller' => $baseDir . '/src/Controller/Controller.php',
93
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\GetAllAvailableLocales' => $baseDir . '/src/Controller/I18n/GetAllAvailableLocales.php',
94
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\LoadTextDomain' => $baseDir . '/src/Controller/I18n/LoadTextDomain.php',
95
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Modes\\BaseMode' => $baseDir . '/src/Controller/Modes/BaseMode.php',
96
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Modes\\DebugMode' => $baseDir . '/src/Controller/Modes/DebugMode.php',
97
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Modes\\StagingMode' => $baseDir . '/src/Controller/Modes/StagingMode.php',
98
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDeactivate' => $baseDir . '/src/Controller/Plugin/PluginDeactivate.php',
99
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDelete' => $baseDir . '/src/Controller/Plugin/PluginDelete.php',
100
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\CaptureMyUpgrade' => $baseDir . '/src/Controller/Utilities/CaptureMyUpgrade.php',
 
101
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\Upgrade' => $baseDir . '/src/Controller/Utilities/Upgrade.php',
102
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\BaseCron' => $baseDir . '/src/Crons/BaseCron.php',
103
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\DailyCron' => $baseDir . '/src/Crons/DailyCron.php',
109
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Handler' => $baseDir . '/src/Databases/AdminNotes/Handler.php',
110
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Insert' => $baseDir . '/src/Databases/AdminNotes/Insert.php',
111
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Select' => $baseDir . '/src/Databases/AdminNotes/Select.php',
 
112
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\EntryVO' => $baseDir . '/src/Databases/AuditTrail/EntryVO.php',
113
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Handler' => $baseDir . '/src/Databases/AuditTrail/Handler.php',
 
 
 
114
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\BaseQuery' => $baseDir . '/src/Databases/Base/BaseQuery.php',
115
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Delete' => $baseDir . '/src/Databases/Base/Delete.php',
116
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\EntryVO' => $baseDir . '/src/Databases/Base/EntryVO.php',
122
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => $baseDir . '/src/Databases/Base/Select.php',
123
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Traits\\Select_IPTable' => $baseDir . '/src/Databases/Base/Traits/Select_IPTable.php',
124
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => $baseDir . '/src/Databases/Base/Update.php',
 
 
 
 
 
 
 
125
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Delete' => $baseDir . '/src/Databases/ChangeTracking/Delete.php',
126
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\EntryVO' => $baseDir . '/src/Databases/ChangeTracking/EntryVO.php',
127
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Handler' => $baseDir . '/src/Databases/ChangeTracking/Handler.php',
178
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Insert' => $baseDir . '/src/Databases/Session/Insert.php',
179
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Select' => $baseDir . '/src/Databases/Session/Select.php',
180
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Update' => $baseDir . '/src/Databases/Session/Update.php',
 
 
 
 
 
 
181
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Helpers\\QuickAccess' => $baseDir . '/src/Helpers/QuickAccess.php',
182
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => $baseDir . '/src/License/EddLicenseVO.php',
183
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Logging\\Processors\\RequestMetaProcessor' => $baseDir . '/src/Logging/Processors/RequestMetaProcessor.php',
210
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Insights\\OverviewCards' => $baseDir . '/src/Modules/AuditTrail/Insights/OverviewCards.php',
211
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditLogger' => $baseDir . '/src/Modules/AuditTrail/Lib/AuditLogger.php',
212
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditMessageBuilder' => $baseDir . '/src/Modules/AuditTrail/Lib/AuditMessageBuilder.php',
 
213
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LocalDbWriter' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/LocalDbWriter.php',
214
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LogFileHandler' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/LogFileHandler.php',
215
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileDirCreate' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php',
216
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileRotate' => $baseDir . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileRotate.php',
217
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\DelegateAjaxHandler' => $baseDir . '/src/Modules/AuditTrail/Lib/LogTable/DelegateAjaxHandler.php',
218
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\LoadRawTableData' => $baseDir . '/src/Modules/AuditTrail/Lib/LogTable/LoadRawTableData.php',
 
 
219
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Utility\\GetLogFileContent' => $baseDir . '/src/Modules/AuditTrail/Lib/Utility/GetLogFileContent.php',
220
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\ModCon' => $baseDir . '/src/Modules/AuditTrail/ModCon.php',
221
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Options' => $baseDir . '/src/Modules/AuditTrail/Options.php',
353
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\Strings' => $baseDir . '/src/Modules/Firewall/Strings.php',
354
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\UI' => $baseDir . '/src/Modules/Firewall/UI.php',
355
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\AjaxHandler' => $baseDir . '/src/Modules/HackGuard/AjaxHandler.php',
356
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Common' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Common.php',
357
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Delete' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Delete.php',
358
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Handler' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Handler.php',
359
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Insert' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Insert.php',
360
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Record' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Record.php',
361
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Select' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Select.php',
362
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Update' => $baseDir . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Update.php',
363
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Common' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Common.php',
364
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Delete' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Delete.php',
365
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Handler' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Handler.php',
366
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Insert' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Insert.php',
367
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Record' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Record.php',
368
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Select' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Select.php',
369
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Update' => $baseDir . '/src/Modules/HackGuard/DB/ResultItems/Ops/Update.php',
370
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Common' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Common.php',
371
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Delete' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Delete.php',
372
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Handler' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Handler.php',
373
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Insert' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Insert.php',
374
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Record' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Record.php',
375
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Select' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Select.php',
376
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Update' => $baseDir . '/src/Modules/HackGuard/DB/ScanItems/Ops/Update.php',
377
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Common' => $baseDir . '/src/Modules/HackGuard/DB/ScanResults/Ops/Common.php',
378
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Delete' => $baseDir . '/src/Modules/HackGuard/DB/ScanResults/Ops/Delete.php',
379
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Handler' => $baseDir . '/src/Modules/HackGuard/DB/ScanResults/Ops/Handler.php',
380
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Insert' => $baseDir . '/src/Modules/HackGuard/DB/ScanResults/Ops/Insert.php',
381
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Record' => $baseDir . '/src/Modules/HackGuard/DB/ScanResults/Ops/Record.php',
382
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Select' => $baseDir . '/src/Modules/HackGuard/DB/ScanResults/Ops/Select.php',
383
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Common' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Common.php',
384
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Delete' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Delete.php',
385
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Handler' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Handler.php',
386
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Insert' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Insert.php',
387
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Record' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Record.php',
388
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Select' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Select.php',
389
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Update' => $baseDir . '/src/Modules/HackGuard/DB/Scans/Ops/Update.php',
390
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Debug' => $baseDir . '/src/Modules/HackGuard/Debug.php',
391
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Insights\\OverviewCards' => $baseDir . '/src/Modules/HackGuard/Insights/OverviewCards.php',
392
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\File' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/File.php',
405
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\ReadOriginalFileContent' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/Ops/ReadOriginalFileContent.php',
406
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Restore' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Restore.php',
407
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Verify' => $baseDir . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Verify.php',
408
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Exceptions\\AssetHashesNotFound' => $baseDir . '/src/Modules/HackGuard/Lib/Hashes/Exceptions/AssetHashesNotFound.php',
409
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Exceptions\\NoneAssetFileException' => $baseDir . '/src/Modules/HackGuard/Lib/Hashes/Exceptions/NoneAssetFileException.php',
410
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Exceptions\\UnrecognisedAssetFile' => $baseDir . '/src/Modules/HackGuard/Lib/Hashes/Exceptions/UnrecognisedAssetFile.php',
411
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Query' => $baseDir . '/src/Modules/HackGuard/Lib/Hashes/Query.php',
412
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Retrieve' => $baseDir . '/src/Modules/HackGuard/Lib/Hashes/Retrieve.php',
413
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\FileLockerAlerts' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/FileLockerAlerts.php',
414
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\Query\\ScanCounts' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/Query/ScanCounts.php',
415
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanAlerts' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php',
416
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanRepairs' => $baseDir . '/src/Modules/HackGuard/Lib/Reports/ScanRepairs.php',
417
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\DelegateAjaxHandler' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/DelegateAjaxHandler.php',
418
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\LoadRawTableData' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/LoadRawTableData.php',
419
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\BuildHistory' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildHistory.php',
420
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\BuildInfo' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildInfo.php',
421
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\FileContents' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/Modals/FileContents.php',
422
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\ScanItemView' => $baseDir . '/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php',
423
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForAsset' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForAsset.php',
424
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForCrowdSource' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForCrowdSource.php',
425
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromApi' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromApi.php',
443
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => $baseDir . '/src/Modules/HackGuard/Options.php',
444
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Processor' => $baseDir . '/src/Modules/HackGuard/Processor.php',
445
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionBase' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionBase.php',
 
446
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionMalware' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionMalware.php',
447
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPluginThemesBase' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionPluginThemesBase.php',
448
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPlugins' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionPlugins.php',
449
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionThemes' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionThemes.php',
450
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionWordpress' => $baseDir . '/src/Modules/HackGuard/Render/ScanResults/SectionWordpress.php',
451
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Reporting' => $baseDir . '/src/Modules/HackGuard/Reporting.php',
452
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Afs' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Afs.php',
453
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Apc' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Apc.php',
454
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Base' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Base.php',
455
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\BaseForAssets' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/BaseForAssets.php',
456
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\BaseForFiles' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/BaseForFiles.php',
457
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Mal' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Mal.php',
458
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ptg' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Ptg.php',
459
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\ScanControllerConsumer' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/ScanControllerConsumer.php',
460
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ufc' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Ufc.php',
461
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wcf' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Wcf.php',
462
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wpv' => $baseDir . '/src/Modules/HackGuard/Scan/Controller/Wpv.php',
463
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Exceptions\\NoQueueItems' => $baseDir . '/src/Modules/HackGuard/Scan/Exceptions/NoQueueItems.php',
464
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Exceptions\\ScanException' => $baseDir . '/src/Modules/HackGuard/Scan/Exceptions/ScanException.php',
465
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Exceptions\\ScanExistsException' => $baseDir . '/src/Modules/HackGuard/Scan/Exceptions/ScanExistsException.php',
466
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\CreateNewScan' => $baseDir . '/src/Modules/HackGuard/Scan/Init/CreateNewScan.php',
467
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\PopulateScanItems' => $baseDir . '/src/Modules/HackGuard/Scan/Init/PopulateScanItems.php',
468
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\ScansStatus' => $baseDir . '/src/Modules/HackGuard/Scan/Init/ScansStatus.php',
469
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\SetScanCompleted' => $baseDir . '/src/Modules/HackGuard/Scan/Init/SetScanCompleted.php',
470
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilder' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilder.php',
471
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilderConsumer' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilderConsumer.php',
472
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CleanQueue' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/CleanQueue.php',
473
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CompleteQueue' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php',
474
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Controller' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/Controller.php',
475
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ProcessQueueItem' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ProcessQueueItem.php',
476
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ProcessQueueWpcli' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/ProcessQueueWpcli.php',
477
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueInit' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueInit.php',
478
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueItemVO' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueItemVO.php',
479
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueItems' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueItems.php',
480
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessor' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php',
481
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessorConsumer' => $baseDir . '/src/Modules/HackGuard/Scan/Queue/QueueProcessorConsumer.php',
482
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Counts' => $baseDir . '/src/Modules/HackGuard/Scan/Results/Counts.php',
483
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Retrieve' => $baseDir . '/src/Modules/HackGuard/Scan/Results/Retrieve.php',
484
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ScanResultVO' => $baseDir . '/src/Modules/HackGuard/Scan/Results/ScanResultVO.php',
485
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Store' => $baseDir . '/src/Modules/HackGuard/Scan/Results/Store.php',
486
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Update' => $baseDir . '/src/Modules/HackGuard/Scan/Results/Update.php',
 
 
 
487
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScanActionFromSlug' => $baseDir . '/src/Modules/HackGuard/Scan/ScanActionFromSlug.php',
488
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScansController' => $baseDir . '/src/Modules/HackGuard/Scan/ScansController.php',
489
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\ConvertLegacyResults' => $baseDir . '/src/Modules/HackGuard/Scan/Utilities/ConvertLegacyResults.php',
490
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\PtgAddReinstallLinks' => $baseDir . '/src/Modules/HackGuard/Scan/Utilities/PtgAddReinstallLinks.php',
491
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\WpvAddPluginRows' => $baseDir . '/src/Modules/HackGuard/Scan/Utilities/WpvAddPluginRows.php',
492
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Strings' => $baseDir . '/src/Modules/HackGuard/Strings.php',
493
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\UI' => $baseDir . '/src/Modules/HackGuard/UI.php',
494
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Upgrade' => $baseDir . '/src/Modules/HackGuard/Upgrade.php',
495
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\WpCli' => $baseDir . '/src/Modules/HackGuard/WpCli.php',
496
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\WpCli\\ScanRun' => $baseDir . '/src/Modules/HackGuard/WpCli/ScanRun.php',
497
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Insights\\OverviewCards' => $baseDir . '/src/Modules/Headers/Insights/OverviewCards.php',
498
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\ModCon' => $baseDir . '/src/Modules/Headers/ModCon.php',
499
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Options' => $baseDir . '/src/Modules/Headers/Options.php',
545
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\IpAnalyse\\FindAllPluginIps' => $baseDir . '/src/Modules/IPs/Lib/IpAnalyse/FindAllPluginIps.php',
546
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\OffenseTracker' => $baseDir . '/src/Modules/IPs/Lib/OffenseTracker.php',
547
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\AddIp' => $baseDir . '/src/Modules/IPs/Lib/Ops/AddIp.php',
 
548
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\DeleteIp' => $baseDir . '/src/Modules/IPs/Lib/Ops/DeleteIp.php',
549
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\LookupIpOnList' => $baseDir . '/src/Modules/IPs/Lib/Ops/LookupIpOnList.php',
550
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\RetrieveIpsForLists' => $baseDir . '/src/Modules/IPs/Lib/Ops/RetrieveIpsForLists.php',
802
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\RateLimitExceededException' => $baseDir . '/src/Modules/Traffic/Lib/Limit/RateLimitExceededException.php',
803
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\TestIpLimit' => $baseDir . '/src/Modules/Traffic/Lib/Limit/TestIpLimit.php',
804
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\LogHandlers\\LocalDbWriter' => $baseDir . '/src/Modules/Traffic/Lib/LogHandlers/LocalDbWriter.php',
 
 
805
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\RequestLogger' => $baseDir . '/src/Modules/Traffic/Lib/RequestLogger.php',
806
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\DelegateAjaxHandler' => $baseDir . '/src/Modules/Traffic/Lib/TrafficTable/DelegateAjaxHandler.php',
807
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\LoadRawTableData' => $baseDir . '/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php',
833
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli' => $baseDir . '/src/Modules/UserManagement/WpCli.php',
834
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli\\SessionTerminate' => $baseDir . '/src/Modules/UserManagement/WpCli/SessionTerminate.php',
835
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Render\\LocateTemplateDirs' => $baseDir . '/src/Render/LocateTemplateDirs.php',
836
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\BuildScanAction' => $baseDir . '/src/Scans/Afs/BuildScanAction.php',
837
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\BuildScanItems' => $baseDir . '/src/Scans/Afs/BuildScanItems.php',
838
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\MalwareFileException' => $baseDir . '/src/Scans/Afs/Exceptions/MalwareFileException.php',
839
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\PluginFileChecksumFailException' => $baseDir . '/src/Scans/Afs/Exceptions/PluginFileChecksumFailException.php',
840
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\PluginFileUnrecognisedException' => $baseDir . '/src/Scans/Afs/Exceptions/PluginFileUnrecognisedException.php',
841
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\RealtimeFileDiscoveredException' => $baseDir . '/src/Scans/Afs/Exceptions/RealtimeFileDiscoveredException.php',
842
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\ScanFileException' => $baseDir . '/src/Scans/Afs/Exceptions/ScanFileException.php',
843
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\ThemeFileChecksumFailException' => $baseDir . '/src/Scans/Afs/Exceptions/ThemeFileChecksumFailException.php',
844
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\ThemeFileUnrecognisedException' => $baseDir . '/src/Scans/Afs/Exceptions/ThemeFileUnrecognisedException.php',
845
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\WpCoreFileChecksumFailException' => $baseDir . '/src/Scans/Afs/Exceptions/WpCoreFileChecksumFailException.php',
846
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\WpCoreFileMissingException' => $baseDir . '/src/Scans/Afs/Exceptions/WpCoreFileMissingException.php',
847
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\WpCoreFileUnrecognisedException' => $baseDir . '/src/Scans/Afs/Exceptions/WpCoreFileUnrecognisedException.php',
848
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\FileScanner' => $baseDir . '/src/Scans/Afs/FileScanner.php',
849
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalFalsePositiveQuery' => $baseDir . '/src/Scans/Afs/Processing/MalFalsePositiveQuery.php',
850
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalFalsePositiveReporter' => $baseDir . '/src/Scans/Afs/Processing/MalFalsePositiveReporter.php',
851
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalReportCache' => $baseDir . '/src/Scans/Afs/Processing/MalReportCache.php',
852
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalwareFalsePositive' => $baseDir . '/src/Scans/Afs/Processing/MalwareFalsePositive.php',
853
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ResultItem' => $baseDir . '/src/Scans/Afs/ResultItem.php',
854
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ResultsSet' => $baseDir . '/src/Scans/Afs/ResultsSet.php',
855
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scan' => $baseDir . '/src/Scans/Afs/Scan.php',
856
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ScanActionVO' => $baseDir . '/src/Scans/Afs/ScanActionVO.php',
857
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ScanFromFileMap' => $baseDir . '/src/Scans/Afs/ScanFromFileMap.php',
858
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\BasePluginThemeFile' => $baseDir . '/src/Scans/Afs/Scans/BasePluginThemeFile.php',
859
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\BaseScan' => $baseDir . '/src/Scans/Afs/Scans/BaseScan.php',
860
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\MalwareFile' => $baseDir . '/src/Scans/Afs/Scans/MalwareFile.php',
861
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\PluginFile' => $baseDir . '/src/Scans/Afs/Scans/PluginFile.php',
862
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\RealtimeFile' => $baseDir . '/src/Scans/Afs/Scans/RealtimeFile.php',
863
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\ThemeFile' => $baseDir . '/src/Scans/Afs/Scans/ThemeFile.php',
864
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\WpCoreFile' => $baseDir . '/src/Scans/Afs/Scans/WpCoreFile.php',
865
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\WpCoreUnrecognisedFile' => $baseDir . '/src/Scans/Afs/Scans/WpCoreUnrecognisedFile.php',
866
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Afs/Utilities/ItemActionHandler.php',
867
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Utilities\\Patterns' => $baseDir . '/src/Scans/Afs/Utilities/Patterns.php',
868
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Utilities\\RepairItem' => $baseDir . '/src/Scans/Afs/Utilities/RepairItem.php',
869
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\BuildScanAction' => $baseDir . '/src/Scans/Apc/BuildScanAction.php',
870
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\BuildScanItems' => $baseDir . '/src/Scans/Apc/BuildScanItems.php',
871
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\PluginScanner' => $baseDir . '/src/Scans/Apc/PluginScanner.php',
872
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => $baseDir . '/src/Scans/Apc/ResultItem.php',
873
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultsSet' => $baseDir . '/src/Scans/Apc/ResultsSet.php',
874
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Scan' => $baseDir . '/src/Scans/Apc/Scan.php',
875
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ScanActionVO' => $baseDir . '/src/Scans/Apc/ScanActionVO.php',
876
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Apc/Utilities/ItemActionHandler.php',
 
877
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseBuildFileMap' => $baseDir . '/src/Scans/Base/BaseBuildFileMap.php',
 
878
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseFileScanActionVO' => $baseDir . '/src/Scans/Base/BaseFileScanActionVO.php',
879
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseMergeItems' => $baseDir . '/src/Scans/Base/BaseMergeItems.php',
880
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScan' => $baseDir . '/src/Scans/Base/BaseScan.php',
881
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScanActionVO' => $baseDir . '/src/Scans/Base/BaseScanActionVO.php',
882
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BuildScanAction' => $baseDir . '/src/Scans/Base/BuildScanAction.php',
883
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\FileResultItem' => $baseDir . '/src/Scans/Base/FileResultItem.php',
884
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileMapScan' => $baseDir . '/src/Scans/Base/Files/BaseFileMapScan.php',
885
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileScanner' => $baseDir . '/src/Scans/Base/Files/BaseFileScanner.php',
887
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultItem' => $baseDir . '/src/Scans/Base/ResultItem.php',
888
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultsSet' => $baseDir . '/src/Scans/Base/ResultsSet.php',
889
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\BaseRepair' => $baseDir . '/src/Scans/Base/Utilities/BaseRepair.php',
890
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\BuildScanItems' => $baseDir . '/src/Scans/Base/Utilities/BuildScanItems.php',
891
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Base/Utilities/ItemActionHandler.php',
892
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandlerAssets' => $baseDir . '/src/Scans/Base/Utilities/ItemActionHandlerAssets.php',
893
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemDeleteHandler' => $baseDir . '/src/Scans/Base/Utilities/ItemDeleteHandler.php',
894
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemIgnoreHandler' => $baseDir . '/src/Scans/Base/Utilities/ItemIgnoreHandler.php',
895
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemRepairHandler' => $baseDir . '/src/Scans/Base/Utilities/ItemRepairHandler.php',
896
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\RepairItemBase' => $baseDir . '/src/Scans/Base/Utilities/RepairItemBase.php',
897
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\Exceptions\\ItemMayBeExcludedException' => $baseDir . '/src/Scans/Common/Exceptions/ItemMayBeExcludedException.php',
898
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanActionConsumer' => $baseDir . '/src/Scans/Common/ScanActionConsumer.php',
899
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanItemConsumer' => $baseDir . '/src/Scans/Common/ScanItemConsumer.php',
900
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\BuildHashesFromDir' => $baseDir . '/src/Scans/Helpers/BuildHashesFromDir.php',
903
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\ScannerRecursiveFilterIterator' => $baseDir . '/src/Scans/Helpers/ScannerRecursiveFilterIterator.php',
904
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\StandardDirectoryIterator' => $baseDir . '/src/Scans/Helpers/StandardDirectoryIterator.php',
905
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\WpCoreFile' => $baseDir . '/src/Scans/Helpers/WpCoreFile.php',
 
 
 
 
 
 
906
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ScanActionVO' => $baseDir . '/src/Scans/Mal/ScanActionVO.php',
 
 
 
 
 
 
 
 
 
 
 
 
907
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ScanActionVO' => $baseDir . '/src/Scans/Ptg/ScanActionVO.php',
 
 
 
 
 
 
 
 
 
908
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ScanActionVO' => $baseDir . '/src/Scans/Ufc/ScanActionVO.php',
 
 
 
 
 
 
 
 
 
909
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ScanActionVO' => $baseDir . '/src/Scans/Wcf/ScanActionVO.php',
 
 
 
910
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\BuildScanAction' => $baseDir . '/src/Scans/Wpv/BuildScanAction.php',
911
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\BuildScanItems' => $baseDir . '/src/Scans/Wpv/BuildScanItems.php',
912
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultItem' => $baseDir . '/src/Scans/Wpv/ResultItem.php',
913
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultsSet' => $baseDir . '/src/Scans/Wpv/ResultsSet.php',
914
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Scan' => $baseDir . '/src/Scans/Wpv/Scan.php',
915
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ScanActionVO' => $baseDir . '/src/Scans/Wpv/ScanActionVO.php',
916
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Utilities\\ItemActionHandler' => $baseDir . '/src/Scans/Wpv/Utilities/ItemActionHandler.php',
 
917
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\WpVulnDb\\VulnVO' => $baseDir . '/src/Scans/Wpv/WpVulnDb/VulnVO.php',
918
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseApi' => $baseDir . '/src/ShieldNetApi/Common/BaseApi.php',
919
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseShieldNetApi' => $baseDir . '/src/ShieldNetApi/Common/BaseShieldNetApi.php',
932
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Tools\\GenerateGoogleAuthQrCode' => $baseDir . '/src/ShieldNetApi/Tools/GenerateGoogleAuthQrCode.php',
933
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\WPHashes\\SolicitToken' => $baseDir . '/src/ShieldNetApi/WPHashes/SolicitToken.php',
934
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => $baseDir . '/src/Tables/Build/AdminNotes.php',
 
935
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => $baseDir . '/src/Tables/Build/BaseBuild.php',
936
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Ip' => $baseDir . '/src/Tables/Build/Ip.php',
937
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => $baseDir . '/src/Tables/Build/Sessions.php',
946
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => $baseDir . '/src/Tables/Render/Common/BaseTable.php',
947
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpCliTable/AuditTrail.php',
948
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => $baseDir . '/src/Tables/Render/WpListTable/AdminNotes.php',
 
949
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Base' => $baseDir . '/src/Tables/Render/WpListTable/Base.php',
950
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBase' => $baseDir . '/src/Tables/Render/WpListTable/IpBase.php',
951
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBlack' => $baseDir . '/src/Tables/Render/WpListTable/IpBlack.php',
952
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpWhite' => $baseDir . '/src/Tables/Render/WpListTable/IpWhite.php',
953
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Sessions' => $baseDir . '/src/Tables/Render/WpListTable/Sessions.php',
 
954
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\RunTests' => $baseDir . '/src/Tests/RunTests.php',
955
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyConfig' => $baseDir . '/src/Tests/VerifyConfig.php',
956
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyEvents' => $baseDir . '/src/Tests/VerifyEvents.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -278,10 +278,12 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
278
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Controller' => __DIR__ . '/../..' . '/src/Controller/Controller.php',
279
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\GetAllAvailableLocales' => __DIR__ . '/../..' . '/src/Controller/I18n/GetAllAvailableLocales.php',
280
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\LoadTextDomain' => __DIR__ . '/../..' . '/src/Controller/I18n/LoadTextDomain.php',
 
 
 
281
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDeactivate' => __DIR__ . '/../..' . '/src/Controller/Plugin/PluginDeactivate.php',
282
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDelete' => __DIR__ . '/../..' . '/src/Controller/Plugin/PluginDelete.php',
283
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\CaptureMyUpgrade' => __DIR__ . '/../..' . '/src/Controller/Utilities/CaptureMyUpgrade.php',
284
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\DebugMode' => __DIR__ . '/../..' . '/src/Controller/Utilities/DebugMode.php',
285
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\Upgrade' => __DIR__ . '/../..' . '/src/Controller/Utilities/Upgrade.php',
286
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\BaseCron' => __DIR__ . '/../..' . '/src/Crons/BaseCron.php',
287
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\DailyCron' => __DIR__ . '/../..' . '/src/Crons/DailyCron.php',
@@ -293,12 +295,8 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
293
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Handler' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Handler.php',
294
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Insert' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Insert.php',
295
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Select' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Select.php',
296
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Delete' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/Delete.php',
297
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/EntryVO.php',
298
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Handler' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/Handler.php',
299
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Insert' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/Insert.php',
300
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Select' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/Select.php',
301
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Update' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/Update.php',
302
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\BaseQuery' => __DIR__ . '/../..' . '/src/Databases/Base/BaseQuery.php',
303
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Delete' => __DIR__ . '/../..' . '/src/Databases/Base/Delete.php',
304
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/Base/EntryVO.php',
@@ -310,13 +308,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
310
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => __DIR__ . '/../..' . '/src/Databases/Base/Select.php',
311
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Traits\\Select_IPTable' => __DIR__ . '/../..' . '/src/Databases/Base/Traits/Select_IPTable.php',
312
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => __DIR__ . '/../..' . '/src/Databases/Base/Update.php',
313
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Common' => __DIR__ . '/../..' . '/src/Databases/BotSignals/Common.php',
314
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Delete' => __DIR__ . '/../..' . '/src/Databases/BotSignals/Delete.php',
315
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/BotSignals/EntryVO.php',
316
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Handler' => __DIR__ . '/../..' . '/src/Databases/BotSignals/Handler.php',
317
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Insert' => __DIR__ . '/../..' . '/src/Databases/BotSignals/Insert.php',
318
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Select' => __DIR__ . '/../..' . '/src/Databases/BotSignals/Select.php',
319
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\BotSignals\\Update' => __DIR__ . '/../..' . '/src/Databases/BotSignals/Update.php',
320
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Delete' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Delete.php',
321
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/EntryVO.php',
322
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Handler' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Handler.php',
@@ -373,12 +364,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
373
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Insert' => __DIR__ . '/../..' . '/src/Databases/Session/Insert.php',
374
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Select' => __DIR__ . '/../..' . '/src/Databases/Session/Select.php',
375
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Update' => __DIR__ . '/../..' . '/src/Databases/Session/Update.php',
376
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\BaseTraffic' => __DIR__ . '/../..' . '/src/Databases/Traffic/BaseTraffic.php',
377
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Delete' => __DIR__ . '/../..' . '/src/Databases/Traffic/Delete.php',
378
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/Traffic/EntryVO.php',
379
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Handler' => __DIR__ . '/../..' . '/src/Databases/Traffic/Handler.php',
380
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Insert' => __DIR__ . '/../..' . '/src/Databases/Traffic/Insert.php',
381
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => __DIR__ . '/../..' . '/src/Databases/Traffic/Select.php',
382
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Helpers\\QuickAccess' => __DIR__ . '/../..' . '/src/Helpers/QuickAccess.php',
383
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => __DIR__ . '/../..' . '/src/License/EddLicenseVO.php',
384
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Logging\\Processors\\RequestMetaProcessor' => __DIR__ . '/../..' . '/src/Logging/Processors/RequestMetaProcessor.php',
@@ -411,15 +396,12 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
411
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Insights/OverviewCards.php',
412
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditLogger' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/AuditLogger.php',
413
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditMessageBuilder' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/AuditMessageBuilder.php',
414
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditWriter' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/AuditWriter.php',
415
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LocalDbWriter' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/LocalDbWriter.php',
416
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LogFileHandler' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/LogFileHandler.php',
417
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileDirCreate' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php',
418
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileRotate' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileRotate.php',
419
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\DelegateAjaxHandler' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogTable/DelegateAjaxHandler.php',
420
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\LoadRawTableData' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogTable/LoadRawTableData.php',
421
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Ops\\Commit' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/Ops/Commit.php',
422
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Ops\\ConvertLegacy' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/Ops/ConvertLegacy.php',
423
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Utility\\GetLogFileContent' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/Utility/GetLogFileContent.php',
424
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\ModCon' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/ModCon.php',
425
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Options' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Options.php',
@@ -557,6 +539,40 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
557
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\Strings' => __DIR__ . '/../..' . '/src/Modules/Firewall/Strings.php',
558
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\UI' => __DIR__ . '/../..' . '/src/Modules/Firewall/UI.php',
559
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/AjaxHandler.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Debug' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Debug.php',
561
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Insights/OverviewCards.php',
562
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\File' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/File.php',
@@ -575,13 +591,21 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
575
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\ReadOriginalFileContent' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/Ops/ReadOriginalFileContent.php',
576
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Restore' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Restore.php',
577
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Verify' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Verify.php',
 
 
 
 
 
578
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\FileLockerAlerts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/FileLockerAlerts.php',
579
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\Query\\ScanCounts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/Query/ScanCounts.php',
580
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanAlerts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php',
581
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanRepairs' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/ScanRepairs.php',
582
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\DelegateAjaxHandler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/DelegateAjaxHandler.php',
583
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\LoadRawTableData' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/LoadRawTableData.php',
584
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\RetrieveFileContents' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/RetrieveFileContents.php',
 
 
 
585
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForAsset' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForAsset.php',
586
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForCrowdSource' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForCrowdSource.php',
587
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromApi' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromApi.php',
@@ -605,47 +629,57 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
605
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Options.php',
606
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Processor' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Processor.php',
607
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionBase' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionBase.php',
608
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionLogs' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionLogs.php',
609
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionMalware' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionMalware.php',
610
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPluginThemesBase' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionPluginThemesBase.php',
611
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPlugins' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionPlugins.php',
612
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionThemes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionThemes.php',
613
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionWordpress' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionWordpress.php',
614
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Reporting' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Reporting.php',
 
615
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Apc' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Apc.php',
616
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Base' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Base.php',
617
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\BaseForAssets' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/BaseForAssets.php',
 
618
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Mal' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Mal.php',
619
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ptg' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Ptg.php',
620
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\ScanControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/ScanControllerConsumer.php',
621
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ufc' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Ufc.php',
622
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wcf' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Wcf.php',
623
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wpv' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Wpv.php',
624
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\BuildScanAction' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/BuildScanAction.php',
 
 
 
 
 
 
625
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilder' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilder.php',
626
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilderConsumer' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilderConsumer.php',
627
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CollateResults' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/CollateResults.php',
628
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CompleteQueue' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php',
629
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Controller' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/Controller.php',
630
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ConvertBetweenTypes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ConvertBetweenTypes.php',
631
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\IsScanEnqueued' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/IsScanEnqueued.php',
 
 
 
632
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessor' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php',
633
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessorConsumer' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueProcessorConsumer.php',
634
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanEnqueue' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanEnqueue.php',
635
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanExecute' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanExecute.php',
636
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ScanInitiate' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ScanInitiate.php',
637
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ConvertBetweenTypes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ConvertBetweenTypes.php',
638
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsDelete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsDelete.php',
639
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsRetrieve' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsRetrieve.php',
640
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsStore' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsStore.php',
641
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ResultsUpdate' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ResultsUpdate.php',
642
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScanActionFromSlug' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/ScanActionFromSlug.php',
643
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScansController' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/ScansController.php',
 
644
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\PtgAddReinstallLinks' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Utilities/PtgAddReinstallLinks.php',
645
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\WpvAddPluginRows' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Utilities/WpvAddPluginRows.php',
646
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Strings' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Strings.php',
647
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\UI' => __DIR__ . '/../..' . '/src/Modules/HackGuard/UI.php',
648
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Upgrade' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Upgrade.php',
 
 
649
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/Headers/Insights/OverviewCards.php',
650
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Headers/ModCon.php',
651
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Options' => __DIR__ . '/../..' . '/src/Modules/Headers/Options.php',
@@ -697,7 +731,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
697
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\IpAnalyse\\FindAllPluginIps' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/IpAnalyse/FindAllPluginIps.php',
698
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\OffenseTracker' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/OffenseTracker.php',
699
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\AddIp' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/AddIp.php',
700
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\ConvertLegacy' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/ConvertLegacy.php',
701
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\DeleteIp' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/DeleteIp.php',
702
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\LookupIpOnList' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/LookupIpOnList.php',
703
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\RetrieveIpsForLists' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/RetrieveIpsForLists.php',
@@ -955,8 +988,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
955
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\RateLimitExceededException' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Limit/RateLimitExceededException.php',
956
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\TestIpLimit' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Limit/TestIpLimit.php',
957
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\LogHandlers\\LocalDbWriter' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/LogHandlers/LocalDbWriter.php',
958
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Logger' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Logger.php',
959
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Ops\\ConvertLegacy' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Ops/ConvertLegacy.php',
960
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\RequestLogger' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/RequestLogger.php',
961
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\DelegateAjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/TrafficTable/DelegateAjaxHandler.php',
962
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\LoadRawTableData' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php',
@@ -988,21 +1019,53 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
988
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli' => __DIR__ . '/../..' . '/src/Modules/UserManagement/WpCli.php',
989
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli\\SessionTerminate' => __DIR__ . '/../..' . '/src/Modules/UserManagement/WpCli/SessionTerminate.php',
990
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Render\\LocateTemplateDirs' => __DIR__ . '/../..' . '/src/Render/LocateTemplateDirs.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
991
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Apc/BuildScanAction.php',
 
992
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\PluginScanner' => __DIR__ . '/../..' . '/src/Scans/Apc/PluginScanner.php',
993
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Apc/ResultItem.php',
994
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Apc/ResultsSet.php',
995
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Scan' => __DIR__ . '/../..' . '/src/Scans/Apc/Scan.php',
996
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Apc/ScanActionVO.php',
997
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Apc/Utilities/ItemActionHandler.php',
998
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Utilities\\Repair' => __DIR__ . '/../..' . '/src/Scans/Apc/Utilities/Repair.php',
999
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseBuildFileMap' => __DIR__ . '/../..' . '/src/Scans/Base/BaseBuildFileMap.php',
1000
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseBuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Base/BaseBuildScanAction.php',
1001
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseFileScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Base/BaseFileScanActionVO.php',
1002
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseMergeItems' => __DIR__ . '/../..' . '/src/Scans/Base/BaseMergeItems.php',
1003
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScan' => __DIR__ . '/../..' . '/src/Scans/Base/BaseScan.php',
1004
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Base/BaseScanActionVO.php',
1005
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\DiffResultForStorage' => __DIR__ . '/../..' . '/src/Scans/Base/DiffResultForStorage.php',
1006
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\FileResultItem' => __DIR__ . '/../..' . '/src/Scans/Base/FileResultItem.php',
1007
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileMapScan' => __DIR__ . '/../..' . '/src/Scans/Base/Files/BaseFileMapScan.php',
1008
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileScanner' => __DIR__ . '/../..' . '/src/Scans/Base/Files/BaseFileScanner.php',
@@ -1010,9 +1073,14 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1010
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Base/ResultItem.php',
1011
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Base/ResultsSet.php',
1012
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\BaseRepair' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/BaseRepair.php',
1013
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\IgnoreItem' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/IgnoreItem.php',
1014
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemActionHandler.php',
1015
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandlerAssets' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemActionHandlerAssets.php',
 
 
 
 
 
1016
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanActionConsumer' => __DIR__ . '/../..' . '/src/Scans/Common/ScanActionConsumer.php',
1017
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanItemConsumer' => __DIR__ . '/../..' . '/src/Scans/Common/ScanItemConsumer.php',
1018
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\BuildHashesFromDir' => __DIR__ . '/../..' . '/src/Scans/Helpers/BuildHashesFromDir.php',
@@ -1021,56 +1089,17 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1021
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\ScannerRecursiveFilterIterator' => __DIR__ . '/../..' . '/src/Scans/Helpers/ScannerRecursiveFilterIterator.php',
1022
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\StandardDirectoryIterator' => __DIR__ . '/../..' . '/src/Scans/Helpers/StandardDirectoryIterator.php',
1023
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\WpCoreFile' => __DIR__ . '/../..' . '/src/Scans/Helpers/WpCoreFile.php',
1024
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\BuildFileMap' => __DIR__ . '/../..' . '/src/Scans/Mal/BuildFileMap.php',
1025
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Mal/BuildScanAction.php',
1026
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\FileScanner' => __DIR__ . '/../..' . '/src/Scans/Mal/FileScanner.php',
1027
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Mal/ResultItem.php',
1028
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Mal/ResultsSet.php',
1029
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Scan' => __DIR__ . '/../..' . '/src/Scans/Mal/Scan.php',
1030
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Mal/ScanActionVO.php',
1031
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ScanFromFileMap' => __DIR__ . '/../..' . '/src/Scans/Mal/ScanFromFileMap.php',
1032
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\FalsePositiveQuery' => __DIR__ . '/../..' . '/src/Scans/Mal/Utilities/FalsePositiveQuery.php',
1033
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\FalsePositiveReporter' => __DIR__ . '/../..' . '/src/Scans/Mal/Utilities/FalsePositiveReporter.php',
1034
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Mal/Utilities/ItemActionHandler.php',
1035
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\Patterns' => __DIR__ . '/../..' . '/src/Scans/Mal/Utilities/Patterns.php',
1036
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\Utilities\\Repair' => __DIR__ . '/../..' . '/src/Scans/Mal/Utilities/Repair.php',
1037
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\BuildFileMap' => __DIR__ . '/../..' . '/src/Scans/Ptg/BuildFileMap.php',
1038
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Ptg/BuildScanAction.php',
1039
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\FileScanner' => __DIR__ . '/../..' . '/src/Scans/Ptg/FileScanner.php',
1040
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Ptg/ResultItem.php',
1041
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Ptg/ResultsSet.php',
1042
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\Scan' => __DIR__ . '/../..' . '/src/Scans/Ptg/Scan.php',
1043
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Ptg/ScanActionVO.php',
1044
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ScanFromFileMap' => __DIR__ . '/../..' . '/src/Scans/Ptg/ScanFromFileMap.php',
1045
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Ptg/Utilities/ItemActionHandler.php',
1046
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\Utilities\\Repair' => __DIR__ . '/../..' . '/src/Scans/Ptg/Utilities/Repair.php',
1047
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\BuildFileMap' => __DIR__ . '/../..' . '/src/Scans/Ufc/BuildFileMap.php',
1048
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Ufc/BuildScanAction.php',
1049
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\FileScanner' => __DIR__ . '/../..' . '/src/Scans/Ufc/FileScanner.php',
1050
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Ufc/ResultItem.php',
1051
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Ufc/ResultsSet.php',
1052
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\Scan' => __DIR__ . '/../..' . '/src/Scans/Ufc/Scan.php',
1053
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Ufc/ScanActionVO.php',
1054
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ScanFromFileMap' => __DIR__ . '/../..' . '/src/Scans/Ufc/ScanFromFileMap.php',
1055
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Ufc/Utilities/ItemActionHandler.php',
1056
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\Utilities\\Repair' => __DIR__ . '/../..' . '/src/Scans/Ufc/Utilities/Repair.php',
1057
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\BuildFileMap' => __DIR__ . '/../..' . '/src/Scans/Wcf/BuildFileMap.php',
1058
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Wcf/BuildScanAction.php',
1059
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\FileScanner' => __DIR__ . '/../..' . '/src/Scans/Wcf/FileScanner.php',
1060
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Wcf/ResultItem.php',
1061
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Wcf/ResultsSet.php',
1062
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\Scan' => __DIR__ . '/../..' . '/src/Scans/Wcf/Scan.php',
1063
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Wcf/ScanActionVO.php',
1064
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ScanFromFileMap' => __DIR__ . '/../..' . '/src/Scans/Wcf/ScanFromFileMap.php',
1065
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Wcf/Utilities/ItemActionHandler.php',
1066
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\Utilities\\Repair' => __DIR__ . '/../..' . '/src/Scans/Wcf/Utilities/Repair.php',
1067
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Wpv/BuildScanAction.php',
 
1068
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Wpv/ResultItem.php',
1069
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Wpv/ResultsSet.php',
1070
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Scan' => __DIR__ . '/../..' . '/src/Scans/Wpv/Scan.php',
1071
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Wpv/ScanActionVO.php',
1072
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Wpv/Utilities/ItemActionHandler.php',
1073
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Utilities\\Repair' => __DIR__ . '/../..' . '/src/Scans/Wpv/Utilities/Repair.php',
1074
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\WpVulnDb\\VulnVO' => __DIR__ . '/../..' . '/src/Scans/Wpv/WpVulnDb/VulnVO.php',
1075
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseApi' => __DIR__ . '/../..' . '/src/ShieldNetApi/Common/BaseApi.php',
1076
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseShieldNetApi' => __DIR__ . '/../..' . '/src/ShieldNetApi/Common/BaseShieldNetApi.php',
@@ -1089,7 +1118,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1089
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Tools\\GenerateGoogleAuthQrCode' => __DIR__ . '/../..' . '/src/ShieldNetApi/Tools/GenerateGoogleAuthQrCode.php',
1090
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\WPHashes\\SolicitToken' => __DIR__ . '/../..' . '/src/ShieldNetApi/WPHashes/SolicitToken.php',
1091
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Build/AdminNotes.php',
1092
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Build/AuditTrail.php',
1093
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => __DIR__ . '/../..' . '/src/Tables/Build/BaseBuild.php',
1094
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Ip' => __DIR__ . '/../..' . '/src/Tables/Build/Ip.php',
1095
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Build/Sessions.php',
@@ -1104,13 +1132,11 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1104
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => __DIR__ . '/../..' . '/src/Tables/Render/Common/BaseTable.php',
1105
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/AuditTrail.php',
1106
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/AdminNotes.php',
1107
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/AuditTrail.php',
1108
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Base' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/Base.php',
1109
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBase' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/IpBase.php',
1110
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBlack' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/IpBlack.php',
1111
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpWhite' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/IpWhite.php',
1112
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/Sessions.php',
1113
- 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Traffic' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/Traffic.php',
1114
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\RunTests' => __DIR__ . '/../..' . '/src/Tests/RunTests.php',
1115
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyConfig' => __DIR__ . '/../..' . '/src/Tests/VerifyConfig.php',
1116
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyEvents' => __DIR__ . '/../..' . '/src/Tests/VerifyEvents.php',
278
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Controller' => __DIR__ . '/../..' . '/src/Controller/Controller.php',
279
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\GetAllAvailableLocales' => __DIR__ . '/../..' . '/src/Controller/I18n/GetAllAvailableLocales.php',
280
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\I18n\\LoadTextDomain' => __DIR__ . '/../..' . '/src/Controller/I18n/LoadTextDomain.php',
281
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Modes\\BaseMode' => __DIR__ . '/../..' . '/src/Controller/Modes/BaseMode.php',
282
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Modes\\DebugMode' => __DIR__ . '/../..' . '/src/Controller/Modes/DebugMode.php',
283
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Modes\\StagingMode' => __DIR__ . '/../..' . '/src/Controller/Modes/StagingMode.php',
284
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDeactivate' => __DIR__ . '/../..' . '/src/Controller/Plugin/PluginDeactivate.php',
285
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Plugin\\PluginDelete' => __DIR__ . '/../..' . '/src/Controller/Plugin/PluginDelete.php',
286
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\CaptureMyUpgrade' => __DIR__ . '/../..' . '/src/Controller/Utilities/CaptureMyUpgrade.php',
 
287
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Utilities\\Upgrade' => __DIR__ . '/../..' . '/src/Controller/Utilities/Upgrade.php',
288
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\BaseCron' => __DIR__ . '/../..' . '/src/Crons/BaseCron.php',
289
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\DailyCron' => __DIR__ . '/../..' . '/src/Crons/DailyCron.php',
295
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Handler' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Handler.php',
296
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Insert' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Insert.php',
297
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Select' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Select.php',
 
298
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/EntryVO.php',
299
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AuditTrail\\Handler' => __DIR__ . '/../..' . '/src/Databases/AuditTrail/Handler.php',
 
 
 
300
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\BaseQuery' => __DIR__ . '/../..' . '/src/Databases/Base/BaseQuery.php',
301
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Delete' => __DIR__ . '/../..' . '/src/Databases/Base/Delete.php',
302
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/Base/EntryVO.php',
308
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => __DIR__ . '/../..' . '/src/Databases/Base/Select.php',
309
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Traits\\Select_IPTable' => __DIR__ . '/../..' . '/src/Databases/Base/Traits/Select_IPTable.php',
310
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => __DIR__ . '/../..' . '/src/Databases/Base/Update.php',
 
 
 
 
 
 
 
311
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Delete' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Delete.php',
312
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/EntryVO.php',
313
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Handler' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Handler.php',
364
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Insert' => __DIR__ . '/../..' . '/src/Databases/Session/Insert.php',
365
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Select' => __DIR__ . '/../..' . '/src/Databases/Session/Select.php',
366
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Session\\Update' => __DIR__ . '/../..' . '/src/Databases/Session/Update.php',
 
 
 
 
 
 
367
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Helpers\\QuickAccess' => __DIR__ . '/../..' . '/src/Helpers/QuickAccess.php',
368
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => __DIR__ . '/../..' . '/src/License/EddLicenseVO.php',
369
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Logging\\Processors\\RequestMetaProcessor' => __DIR__ . '/../..' . '/src/Logging/Processors/RequestMetaProcessor.php',
396
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Insights/OverviewCards.php',
397
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditLogger' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/AuditLogger.php',
398
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\AuditMessageBuilder' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/AuditMessageBuilder.php',
 
399
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LocalDbWriter' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/LocalDbWriter.php',
400
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\LogFileHandler' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/LogFileHandler.php',
401
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileDirCreate' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php',
402
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogHandlers\\Utility\\LogFileRotate' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileRotate.php',
403
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\DelegateAjaxHandler' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogTable/DelegateAjaxHandler.php',
404
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\LogTable\\LoadRawTableData' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/LogTable/LoadRawTableData.php',
 
 
405
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Lib\\Utility\\GetLogFileContent' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Lib/Utility/GetLogFileContent.php',
406
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\ModCon' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/ModCon.php',
407
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\AuditTrail\\Options' => __DIR__ . '/../..' . '/src/Modules/AuditTrail/Options.php',
539
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\Strings' => __DIR__ . '/../..' . '/src/Modules/Firewall/Strings.php',
540
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Firewall\\UI' => __DIR__ . '/../..' . '/src/Modules/Firewall/UI.php',
541
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/AjaxHandler.php',
542
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Common' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Common.php',
543
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Delete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Delete.php',
544
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Handler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Handler.php',
545
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Insert' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Insert.php',
546
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Record' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Record.php',
547
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Select' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Select.php',
548
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItemMeta\\Ops\\Update' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItemMeta/Ops/Update.php',
549
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Common' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Common.php',
550
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Delete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Delete.php',
551
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Handler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Handler.php',
552
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Insert' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Insert.php',
553
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Record' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Record.php',
554
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Select' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Select.php',
555
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ResultItems\\Ops\\Update' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ResultItems/Ops/Update.php',
556
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Common' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Common.php',
557
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Delete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Delete.php',
558
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Handler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Handler.php',
559
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Insert' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Insert.php',
560
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Record' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Record.php',
561
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Select' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Select.php',
562
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanItems\\Ops\\Update' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanItems/Ops/Update.php',
563
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Common' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanResults/Ops/Common.php',
564
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Delete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanResults/Ops/Delete.php',
565
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Handler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanResults/Ops/Handler.php',
566
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Insert' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanResults/Ops/Insert.php',
567
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Record' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanResults/Ops/Record.php',
568
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\ScanResults\\Ops\\Select' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/ScanResults/Ops/Select.php',
569
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Common' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Common.php',
570
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Delete' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Delete.php',
571
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Handler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Handler.php',
572
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Insert' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Insert.php',
573
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Record' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Record.php',
574
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Select' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Select.php',
575
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\DB\\Scans\\Ops\\Update' => __DIR__ . '/../..' . '/src/Modules/HackGuard/DB/Scans/Ops/Update.php',
576
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Debug' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Debug.php',
577
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Insights/OverviewCards.php',
578
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\File' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/File.php',
591
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\ReadOriginalFileContent' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/Ops/ReadOriginalFileContent.php',
592
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Restore' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Restore.php',
593
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\FileLocker\\Ops\\Verify' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/FileLocker/Ops/Verify.php',
594
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Exceptions\\AssetHashesNotFound' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Hashes/Exceptions/AssetHashesNotFound.php',
595
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Exceptions\\NoneAssetFileException' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Hashes/Exceptions/NoneAssetFileException.php',
596
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Exceptions\\UnrecognisedAssetFile' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Hashes/Exceptions/UnrecognisedAssetFile.php',
597
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Query' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Hashes/Query.php',
598
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Hashes\\Retrieve' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Hashes/Retrieve.php',
599
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\FileLockerAlerts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/FileLockerAlerts.php',
600
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\Query\\ScanCounts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/Query/ScanCounts.php',
601
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanAlerts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php',
602
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Reports\\ScanRepairs' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Reports/ScanRepairs.php',
603
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\DelegateAjaxHandler' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/DelegateAjaxHandler.php',
604
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\LoadRawTableData' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/LoadRawTableData.php',
605
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\BuildHistory' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildHistory.php',
606
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\BuildInfo' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/Modals/BuildInfo.php',
607
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\FileContents' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/Modals/FileContents.php',
608
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\ScanTables\\Modals\\ScanItemView' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php',
609
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForAsset' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForAsset.php',
610
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesForCrowdSource' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesForCrowdSource.php',
611
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromApi' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromApi.php',
629
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Options' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Options.php',
630
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Processor' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Processor.php',
631
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionBase' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionBase.php',
 
632
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionMalware' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionMalware.php',
633
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPluginThemesBase' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionPluginThemesBase.php',
634
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionPlugins' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionPlugins.php',
635
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionThemes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionThemes.php',
636
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Render\\ScanResults\\SectionWordpress' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Render/ScanResults/SectionWordpress.php',
637
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Reporting' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Reporting.php',
638
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Afs' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Afs.php',
639
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Apc' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Apc.php',
640
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Base' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Base.php',
641
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\BaseForAssets' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/BaseForAssets.php',
642
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\BaseForFiles' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/BaseForFiles.php',
643
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Mal' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Mal.php',
644
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ptg' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Ptg.php',
645
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\ScanControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/ScanControllerConsumer.php',
646
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Ufc' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Ufc.php',
647
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wcf' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Wcf.php',
648
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Controller\\Wpv' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Controller/Wpv.php',
649
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Exceptions\\NoQueueItems' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Exceptions/NoQueueItems.php',
650
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Exceptions\\ScanException' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Exceptions/ScanException.php',
651
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Exceptions\\ScanExistsException' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Exceptions/ScanExistsException.php',
652
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\CreateNewScan' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Init/CreateNewScan.php',
653
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\PopulateScanItems' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Init/PopulateScanItems.php',
654
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\ScansStatus' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Init/ScansStatus.php',
655
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Init\\SetScanCompleted' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Init/SetScanCompleted.php',
656
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilder' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilder.php',
657
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Build\\QueueBuilderConsumer' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/Build/QueueBuilderConsumer.php',
658
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CleanQueue' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/CleanQueue.php',
659
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\CompleteQueue' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php',
660
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\Controller' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/Controller.php',
661
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ProcessQueueItem' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ProcessQueueItem.php',
662
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\ProcessQueueWpcli' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/ProcessQueueWpcli.php',
663
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueInit' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueInit.php',
664
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueItemVO' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueItemVO.php',
665
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueItems' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueItems.php',
666
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessor' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php',
667
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Queue\\QueueProcessorConsumer' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Queue/QueueProcessorConsumer.php',
668
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Counts' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/Counts.php',
669
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Retrieve' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/Retrieve.php',
670
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\ScanResultVO' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/ScanResultVO.php',
671
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Store' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/Store.php',
672
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Results\\Update' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Results/Update.php',
 
 
 
673
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScanActionFromSlug' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/ScanActionFromSlug.php',
674
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\ScansController' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/ScansController.php',
675
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\ConvertLegacyResults' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Utilities/ConvertLegacyResults.php',
676
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\PtgAddReinstallLinks' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Utilities/PtgAddReinstallLinks.php',
677
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Scan\\Utilities\\WpvAddPluginRows' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Scan/Utilities/WpvAddPluginRows.php',
678
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Strings' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Strings.php',
679
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\UI' => __DIR__ . '/../..' . '/src/Modules/HackGuard/UI.php',
680
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Upgrade' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Upgrade.php',
681
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\WpCli' => __DIR__ . '/../..' . '/src/Modules/HackGuard/WpCli.php',
682
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\WpCli\\ScanRun' => __DIR__ . '/../..' . '/src/Modules/HackGuard/WpCli/ScanRun.php',
683
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/Headers/Insights/OverviewCards.php',
684
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Headers/ModCon.php',
685
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Headers\\Options' => __DIR__ . '/../..' . '/src/Modules/Headers/Options.php',
731
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\IpAnalyse\\FindAllPluginIps' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/IpAnalyse/FindAllPluginIps.php',
732
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\OffenseTracker' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/OffenseTracker.php',
733
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\AddIp' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/AddIp.php',
 
734
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\DeleteIp' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/DeleteIp.php',
735
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\LookupIpOnList' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/LookupIpOnList.php',
736
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\Lib\\Ops\\RetrieveIpsForLists' => __DIR__ . '/../..' . '/src/Modules/IPs/Lib/Ops/RetrieveIpsForLists.php',
988
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\RateLimitExceededException' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Limit/RateLimitExceededException.php',
989
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\Limit\\TestIpLimit' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/Limit/TestIpLimit.php',
990
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\LogHandlers\\LocalDbWriter' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/LogHandlers/LocalDbWriter.php',
 
 
991
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\RequestLogger' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/RequestLogger.php',
992
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\DelegateAjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/TrafficTable/DelegateAjaxHandler.php',
993
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Traffic\\Lib\\TrafficTable\\LoadRawTableData' => __DIR__ . '/../..' . '/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php',
1019
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli' => __DIR__ . '/../..' . '/src/Modules/UserManagement/WpCli.php',
1020
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\WpCli\\SessionTerminate' => __DIR__ . '/../..' . '/src/Modules/UserManagement/WpCli/SessionTerminate.php',
1021
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Render\\LocateTemplateDirs' => __DIR__ . '/../..' . '/src/Render/LocateTemplateDirs.php',
1022
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Afs/BuildScanAction.php',
1023
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\BuildScanItems' => __DIR__ . '/../..' . '/src/Scans/Afs/BuildScanItems.php',
1024
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\MalwareFileException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/MalwareFileException.php',
1025
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\PluginFileChecksumFailException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/PluginFileChecksumFailException.php',
1026
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\PluginFileUnrecognisedException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/PluginFileUnrecognisedException.php',
1027
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\RealtimeFileDiscoveredException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/RealtimeFileDiscoveredException.php',
1028
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\ScanFileException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/ScanFileException.php',
1029
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\ThemeFileChecksumFailException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/ThemeFileChecksumFailException.php',
1030
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\ThemeFileUnrecognisedException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/ThemeFileUnrecognisedException.php',
1031
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\WpCoreFileChecksumFailException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/WpCoreFileChecksumFailException.php',
1032
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\WpCoreFileMissingException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/WpCoreFileMissingException.php',
1033
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Exceptions\\WpCoreFileUnrecognisedException' => __DIR__ . '/../..' . '/src/Scans/Afs/Exceptions/WpCoreFileUnrecognisedException.php',
1034
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\FileScanner' => __DIR__ . '/../..' . '/src/Scans/Afs/FileScanner.php',
1035
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalFalsePositiveQuery' => __DIR__ . '/../..' . '/src/Scans/Afs/Processing/MalFalsePositiveQuery.php',
1036
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalFalsePositiveReporter' => __DIR__ . '/../..' . '/src/Scans/Afs/Processing/MalFalsePositiveReporter.php',
1037
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalReportCache' => __DIR__ . '/../..' . '/src/Scans/Afs/Processing/MalReportCache.php',
1038
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Processing\\MalwareFalsePositive' => __DIR__ . '/../..' . '/src/Scans/Afs/Processing/MalwareFalsePositive.php',
1039
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Afs/ResultItem.php',
1040
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Afs/ResultsSet.php',
1041
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scan' => __DIR__ . '/../..' . '/src/Scans/Afs/Scan.php',
1042
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Afs/ScanActionVO.php',
1043
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\ScanFromFileMap' => __DIR__ . '/../..' . '/src/Scans/Afs/ScanFromFileMap.php',
1044
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\BasePluginThemeFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/BasePluginThemeFile.php',
1045
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\BaseScan' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/BaseScan.php',
1046
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\MalwareFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/MalwareFile.php',
1047
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\PluginFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/PluginFile.php',
1048
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\RealtimeFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/RealtimeFile.php',
1049
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\ThemeFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/ThemeFile.php',
1050
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\WpCoreFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/WpCoreFile.php',
1051
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Scans\\WpCoreUnrecognisedFile' => __DIR__ . '/../..' . '/src/Scans/Afs/Scans/WpCoreUnrecognisedFile.php',
1052
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Afs/Utilities/ItemActionHandler.php',
1053
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Utilities\\Patterns' => __DIR__ . '/../..' . '/src/Scans/Afs/Utilities/Patterns.php',
1054
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Afs\\Utilities\\RepairItem' => __DIR__ . '/../..' . '/src/Scans/Afs/Utilities/RepairItem.php',
1055
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Apc/BuildScanAction.php',
1056
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\BuildScanItems' => __DIR__ . '/../..' . '/src/Scans/Apc/BuildScanItems.php',
1057
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\PluginScanner' => __DIR__ . '/../..' . '/src/Scans/Apc/PluginScanner.php',
1058
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Apc/ResultItem.php',
1059
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Apc/ResultsSet.php',
1060
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Scan' => __DIR__ . '/../..' . '/src/Scans/Apc/Scan.php',
1061
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Apc/ScanActionVO.php',
1062
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Apc/Utilities/ItemActionHandler.php',
 
1063
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseBuildFileMap' => __DIR__ . '/../..' . '/src/Scans/Base/BaseBuildFileMap.php',
 
1064
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseFileScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Base/BaseFileScanActionVO.php',
1065
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseMergeItems' => __DIR__ . '/../..' . '/src/Scans/Base/BaseMergeItems.php',
1066
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScan' => __DIR__ . '/../..' . '/src/Scans/Base/BaseScan.php',
1067
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BaseScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Base/BaseScanActionVO.php',
1068
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Base/BuildScanAction.php',
1069
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\FileResultItem' => __DIR__ . '/../..' . '/src/Scans/Base/FileResultItem.php',
1070
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileMapScan' => __DIR__ . '/../..' . '/src/Scans/Base/Files/BaseFileMapScan.php',
1071
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Files\\BaseFileScanner' => __DIR__ . '/../..' . '/src/Scans/Base/Files/BaseFileScanner.php',
1073
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Base/ResultItem.php',
1074
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Base/ResultsSet.php',
1075
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\BaseRepair' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/BaseRepair.php',
1076
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\BuildScanItems' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/BuildScanItems.php',
1077
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemActionHandler.php',
1078
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemActionHandlerAssets' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemActionHandlerAssets.php',
1079
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemDeleteHandler' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemDeleteHandler.php',
1080
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemIgnoreHandler' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemIgnoreHandler.php',
1081
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\ItemRepairHandler' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/ItemRepairHandler.php',
1082
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Base\\Utilities\\RepairItemBase' => __DIR__ . '/../..' . '/src/Scans/Base/Utilities/RepairItemBase.php',
1083
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\Exceptions\\ItemMayBeExcludedException' => __DIR__ . '/../..' . '/src/Scans/Common/Exceptions/ItemMayBeExcludedException.php',
1084
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanActionConsumer' => __DIR__ . '/../..' . '/src/Scans/Common/ScanActionConsumer.php',
1085
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Common\\ScanItemConsumer' => __DIR__ . '/../..' . '/src/Scans/Common/ScanItemConsumer.php',
1086
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\BuildHashesFromDir' => __DIR__ . '/../..' . '/src/Scans/Helpers/BuildHashesFromDir.php',
1089
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\ScannerRecursiveFilterIterator' => __DIR__ . '/../..' . '/src/Scans/Helpers/ScannerRecursiveFilterIterator.php',
1090
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\StandardDirectoryIterator' => __DIR__ . '/../..' . '/src/Scans/Helpers/StandardDirectoryIterator.php',
1091
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Helpers\\WpCoreFile' => __DIR__ . '/../..' . '/src/Scans/Helpers/WpCoreFile.php',
 
 
 
 
 
 
1092
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Mal\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Mal/ScanActionVO.php',
 
 
 
 
 
 
 
 
 
 
 
 
1093
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ptg\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Ptg/ScanActionVO.php',
 
 
 
 
 
 
 
 
 
1094
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Ufc\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Ufc/ScanActionVO.php',
 
 
 
 
 
 
 
 
 
1095
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wcf\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Wcf/ScanActionVO.php',
 
 
 
1096
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\BuildScanAction' => __DIR__ . '/../..' . '/src/Scans/Wpv/BuildScanAction.php',
1097
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\BuildScanItems' => __DIR__ . '/../..' . '/src/Scans/Wpv/BuildScanItems.php',
1098
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Wpv/ResultItem.php',
1099
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ResultsSet' => __DIR__ . '/../..' . '/src/Scans/Wpv/ResultsSet.php',
1100
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Scan' => __DIR__ . '/../..' . '/src/Scans/Wpv/Scan.php',
1101
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\ScanActionVO' => __DIR__ . '/../..' . '/src/Scans/Wpv/ScanActionVO.php',
1102
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\Utilities\\ItemActionHandler' => __DIR__ . '/../..' . '/src/Scans/Wpv/Utilities/ItemActionHandler.php',
 
1103
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Wpv\\WpVulnDb\\VulnVO' => __DIR__ . '/../..' . '/src/Scans/Wpv/WpVulnDb/VulnVO.php',
1104
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseApi' => __DIR__ . '/../..' . '/src/ShieldNetApi/Common/BaseApi.php',
1105
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Common\\BaseShieldNetApi' => __DIR__ . '/../..' . '/src/ShieldNetApi/Common/BaseShieldNetApi.php',
1118
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\Tools\\GenerateGoogleAuthQrCode' => __DIR__ . '/../..' . '/src/ShieldNetApi/Tools/GenerateGoogleAuthQrCode.php',
1119
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\ShieldNetApi\\WPHashes\\SolicitToken' => __DIR__ . '/../..' . '/src/ShieldNetApi/WPHashes/SolicitToken.php',
1120
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Build/AdminNotes.php',
 
1121
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\BaseBuild' => __DIR__ . '/../..' . '/src/Tables/Build/BaseBuild.php',
1122
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Ip' => __DIR__ . '/../..' . '/src/Tables/Build/Ip.php',
1123
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Build/Sessions.php',
1132
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => __DIR__ . '/../..' . '/src/Tables/Render/Common/BaseTable.php',
1133
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/AuditTrail.php',
1134
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/AdminNotes.php',
 
1135
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Base' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/Base.php',
1136
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBase' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/IpBase.php',
1137
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpBlack' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/IpBlack.php',
1138
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\IpWhite' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/IpWhite.php',
1139
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/Sessions.php',
 
1140
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\RunTests' => __DIR__ . '/../..' . '/src/Tests/RunTests.php',
1141
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyConfig' => __DIR__ . '/../..' . '/src/Tests/VerifyConfig.php',
1142
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tests\\VerifyEvents' => __DIR__ . '/../..' . '/src/Tests/VerifyEvents.php',
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Select.php CHANGED
@@ -48,7 +48,7 @@ class Select extends BaseQuery {
48
 
49
  /**
50
  * @param int $ID
51
- * @return \stdClass|mixed
52
  */
53
  public function byId( $ID ) {
54
  $items = $this->reset()
48
 
49
  /**
50
  * @param int $ID
51
+ * @return \stdClass
52
  */
53
  public function byId( $ID ) {
54
  $items = $this->reset()
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/CoreFileHashes.php CHANGED
@@ -5,10 +5,6 @@ namespace FernleafSystems\Wordpress\Services\Core;
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities\File\Compare\CompareHash;
7
 
8
- /**
9
- * Class CoreFileHashes
10
- * @package FernleafSystems\Wordpress\Services\Core
11
- */
12
  class CoreFileHashes {
13
 
14
  /**
@@ -42,8 +38,8 @@ class CoreFileHashes {
42
  * @return string|null
43
  */
44
  public function getFileHash( $file ) {
45
- $sNorm = $this->getFileFragment( $file );
46
- return $this->isCoreFile( $sNorm ) ? $this->getHashes()[ $sNorm ] : null;
47
  }
48
 
49
  /**
@@ -77,7 +73,7 @@ class CoreFileHashes {
77
  public function isCoreFileHashValid( $fullPath ) :bool {
78
  try {
79
  $valid = $this->isCoreFile( $fullPath )
80
- && ( new CompareHash() )->isEqualFileMd5( $fullPath, $this->getFileHash( $fullPath ) );
81
  }
82
  catch ( \Exception $oE ) {
83
  $valid = false;
5
  use FernleafSystems\Wordpress\Services\Services;
6
  use FernleafSystems\Wordpress\Services\Utilities\File\Compare\CompareHash;
7
 
 
 
 
 
8
  class CoreFileHashes {
9
 
10
  /**
38
  * @return string|null
39
  */
40
  public function getFileHash( $file ) {
41
+ $normalised = $this->getFileFragment( $file );
42
+ return $this->isCoreFile( $normalised ) ? $this->getHashes()[ $normalised ] : null;
43
  }
44
 
45
  /**
73
  public function isCoreFileHashValid( $fullPath ) :bool {
74
  try {
75
  $valid = $this->isCoreFile( $fullPath )
76
+ && ( new CompareHash() )->isEqualFile( $fullPath, $this->getFileHash( $fullPath ) );
77
  }
78
  catch ( \Exception $oE ) {
79
  $valid = false;
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/BackgroundProcessing/BackgroundProcess.php CHANGED
@@ -4,16 +4,12 @@ namespace FernleafSystems\Wordpress\Services\Utilities\BackgroundProcessing;
4
 
5
  use FernleafSystems\Wordpress\Services\Services;
6
 
7
- /**
8
- * Class BackgroundProcess
9
- * @package FernleafSystems\Wordpress\Services\Utilities\BackgroundProcessing
10
- */
11
  abstract class BackgroundProcess extends \WP_Background_Process {
12
 
13
  /**
14
  * @var int
15
  */
16
- private $nExpirationInterval;
17
 
18
  /**
19
  * Expired Cron_hook_identifier
@@ -24,12 +20,12 @@ abstract class BackgroundProcess extends \WP_Background_Process {
24
  protected $expired_cron_hook_identifier;
25
 
26
  /**
27
- * @param string $sAction
28
- * @param string $sPrefix
29
  */
30
- public function __construct( $sAction = '', $sPrefix = 'apto' ) {
31
- $this->setPrefix( $sPrefix )
32
- ->setAction( $sAction );
33
 
34
  parent::__construct();
35
 
@@ -47,7 +43,7 @@ abstract class BackgroundProcess extends \WP_Background_Process {
47
  // A cron that automatically cleans up expired items
48
  $this->scheduleExpiredCleanup();
49
 
50
- return parent::dispatch();
51
  }
52
 
53
  /**
@@ -73,13 +69,17 @@ abstract class BackgroundProcess extends \WP_Background_Process {
73
  * @return array
74
  */
75
  protected function get_post_args() {
76
- $aArgs = parent::get_post_args();
77
 
78
- if ( isset( $aArgs[ 'body' ] ) ) {
79
- $aArgs[ 'body' ] = '';
80
  }
81
 
82
- return $aArgs;
 
 
 
 
83
  }
84
 
85
  protected function scheduleExpiredCleanup() {
@@ -99,46 +99,41 @@ abstract class BackgroundProcess extends \WP_Background_Process {
99
  }
100
  }
101
 
102
- /**
103
- */
104
  public function handleExpiredItems() {
105
  // override to handle expired items according to Expiration Interval
106
  }
107
 
108
- /**
109
- * @return int
110
- */
111
- public function getExpirationInterval() {
112
- return (int)$this->nExpirationInterval;
113
  }
114
 
115
  /**
116
- * @param int $sAction
117
  * @return $this
118
  */
119
- public function setAction( $sAction ) {
120
- if ( !empty( $sAction ) ) {
121
- $this->action = $sAction;
122
  }
123
  return $this;
124
  }
125
 
126
  /**
127
- * @param int $nExpirationInterval - seconds
128
  * @return $this
129
  */
130
- public function setExpirationInterval( $nExpirationInterval ) {
131
- $this->nExpirationInterval = $nExpirationInterval;
132
  return $this;
133
  }
134
 
135
  /**
136
- * @param int $sPrefix
137
  * @return $this
138
  */
139
- public function setPrefix( $sPrefix ) {
140
- if ( !empty( $sPrefix ) ) {
141
- $this->prefix = $sPrefix;
142
  }
143
  return $this;
144
  }
4
 
5
  use FernleafSystems\Wordpress\Services\Services;
6
 
 
 
 
 
7
  abstract class BackgroundProcess extends \WP_Background_Process {
8
 
9
  /**
10
  * @var int
11
  */
12
+ private $expirationInterval;
13
 
14
  /**
15
  * Expired Cron_hook_identifier
20
  protected $expired_cron_hook_identifier;
21
 
22
  /**
23
+ * @param string $action
24
+ * @param string $prefix
25
  */
26
+ public function __construct( $action = '', $prefix = 'apto' ) {
27
+ $this->setPrefix( $prefix )
28
+ ->setAction( $action );
29
 
30
  parent::__construct();
31
 
43
  // A cron that automatically cleans up expired items
44
  $this->scheduleExpiredCleanup();
45
 
46
+ parent::dispatch();
47
  }
48
 
49
  /**
69
  * @return array
70
  */
71
  protected function get_post_args() {
72
+ $args = parent::get_post_args();
73
 
74
+ if ( isset( $args[ 'body' ] ) ) {
75
+ $args[ 'body' ] = '';
76
  }
77
 
78
+ return $args;
79
+ }
80
+
81
+ protected function time_exceeded() {
82
+ return !Services::WpGeneral()->isWpCli() && parent::time_exceeded();
83
  }
84
 
85
  protected function scheduleExpiredCleanup() {
99
  }
100
  }
101
 
 
 
102
  public function handleExpiredItems() {
103
  // override to handle expired items according to Expiration Interval
104
  }
105
 
106
+ public function getExpirationInterval() :int {
107
+ return (int)$this->expirationInterval;
 
 
 
108
  }
109
 
110
  /**
111
+ * @param int $action
112
  * @return $this
113
  */
114
+ public function setAction( $action ) {
115
+ if ( !empty( $action ) ) {
116
+ $this->action = $action;
117
  }
118
  return $this;
119
  }
120
 
121
  /**
122
+ * @param int $expirationInterval - seconds
123
  * @return $this
124
  */
125
+ public function setExpirationInterval( $expirationInterval ) {
126
+ $this->expirationInterval = $expirationInterval;
127
  return $this;
128
  }
129
 
130
  /**
131
+ * @param string $prefix
132
  * @return $this
133
  */
134
+ public function setPrefix( $prefix ) {
135
+ if ( !empty( $prefix ) ) {
136
+ $this->prefix = $prefix;
137
  }
138
  return $this;
139
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Base/RepoBase.php CHANGED
@@ -1,76 +1,76 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Base;
4
-
5
- use FernleafSystems\Wordpress\Services;
6
-
7
- abstract class RepoBase {
8
-
9
- /**
10
- * @param string $fileFragment
11
- * @param string $version
12
- * @param bool $useSiteLocale
13
- * @return string|null
14
- */
15
- public function downloadFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
16
- $url = $this->getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale );
17
- try {
18
- $tmpFile = ( new Services\Utilities\HttpUtil() )
19
- ->checkUrl( $url )
20
- ->downloadUrl( $url );
21
- }
22
- catch ( \Exception $e ) {
23
- $tmpFile = null;
24
- }
25
- return $tmpFile;
26
- }
27
-
28
- /**
29
- * @param string $fileFragment
30
- * @param string $version
31
- * @param bool $useSiteLocale
32
- * @return string|null
33
- */
34
- public function getContentFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
35
- $url = $this->getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale );
36
- $content = null;
37
- try {
38
- $downloadedFile = ( new Services\Utilities\HttpUtil() )
39
- ->checkUrl( $url )
40
- ->downloadUrl( $url );
41
- if ( is_string( $downloadedFile ) ) {
42
- $content = Services\Services::WpFs()->getFileContent( $downloadedFile );
43
- }
44
- }
45
- catch ( \Exception $e ) {
46
- }
47
- return $content;
48
- }
49
-
50
- /**
51
- * @param string $fileFragment - path relative to the root dir of the object being tested. E.g. ABSPATH for
52
- * WordPress or the plugin dir if it's a plugin.
53
- * @param string $version - leave empty to use the current version
54
- * @param bool $useSiteLocale
55
- * @return bool
56
- */
57
- public function existsInVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
58
- $url = $this->getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale );
59
- try {
60
- ( new Services\Utilities\HttpUtil() )->checkUrl( $url );
61
- $exists = true;
62
- }
63
- catch ( \Exception $e ) {
64
- $exists = false;
65
- }
66
- return $exists;
67
- }
68
-
69
- /**
70
- * @param string $fileFragment
71
- * @param string $version
72
- * @param bool $useSiteLocale
73
- * @return string
74
- */
75
- abstract public function getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale = true );
76
  }
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Base;
4
+
5
+ use FernleafSystems\Wordpress\Services;
6
+
7
+ abstract class RepoBase {
8
+
9
+ /**
10
+ * @param string $fileFragment
11
+ * @param string $version
12
+ * @param bool $useSiteLocale
13
+ * @return string|null
14
+ */
15
+ public function downloadFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
16
+ $url = $this->getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale );
17
+ try {
18
+ $tmpFile = ( new Services\Utilities\HttpUtil() )
19
+ ->checkUrl( $url )
20
+ ->downloadUrl( $url );
21
+ }
22
+ catch ( \Exception $e ) {
23
+ $tmpFile = null;
24
+ }
25
+ return $tmpFile;
26
+ }
27
+
28
+ /**
29
+ * @param string $fileFragment
30
+ * @param string $version
31
+ * @param bool $useSiteLocale
32
+ * @return string|null
33
+ */
34
+ public function getContentFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
35
+ $url = $this->getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale );
36
+ $content = null;
37
+ try {
38
+ $downloadedFile = ( new Services\Utilities\HttpUtil() )
39
+ ->checkUrl( $url )
40
+ ->downloadUrl( $url );
41
+ if ( is_string( $downloadedFile ) ) {
42
+ $content = Services\Services::WpFs()->getFileContent( $downloadedFile );
43
+ }
44
+ }
45
+ catch ( \Exception $e ) {
46
+ }
47
+ return $content;
48
+ }
49
+
50
+ /**
51
+ * @param string $fileFragment - path relative to the root dir of the object being tested. E.g. ABSPATH for
52
+ * WordPress or the plugin dir if it's a plugin.
53
+ * @param string $version - leave empty to use the current version
54
+ * @param bool $useSiteLocale
55
+ * @return bool
56
+ */
57
+ public function existsInVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
58
+ $url = $this->getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale );
59
+ try {
60
+ ( new Services\Utilities\HttpUtil() )->checkUrl( $url );
61
+ $exists = true;
62
+ }
63
+ catch ( \Exception $e ) {
64
+ $exists = false;
65
+ }
66
+ return $exists;
67
+ }
68
+
69
+ /**
70
+ * @param string $fileFragment
71
+ * @param string $version
72
+ * @param bool $useSiteLocale
73
+ * @return string
74
+ */
75
+ abstract public function getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale = true );
76
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Cp/Repo.php CHANGED
@@ -1,77 +1,77 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Cp;
4
-
5
- use FernleafSystems\Wordpress\Services;
6
-
7
- class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
-
9
- const URL_VCS_ROOT = 'https://raw.githubusercontent.com/ClassicPress/ClassicPress-release';
10
- const URL_VCS_ROOT_IL8N = self::URL_VCS_ROOT;
11
- const URL_VCS_VERSIONS = 'https://api.github.com/repos/ClassicPress/ClassicPress-release/releases';
12
- const URL_VCS_VERSION = 'https://github.com/ClassicPress/ClassicPress-release/releases/tag';
13
-
14
- /**
15
- * @param string $sVersion
16
- * @return string
17
- */
18
- public static function GetUrlForVersion( $sVersion ) {
19
- return sprintf( '%s/%s', static::URL_VCS_VERSION, $sVersion );
20
- }
21
-
22
- /**
23
- * @param string $sVersion
24
- * @return string
25
- */
26
- public static function GetUrlForFiles( $sVersion ) {
27
- return sprintf( '%s/%s', static::URL_VCS_ROOT, $sVersion );
28
- }
29
-
30
- /**
31
- * @return string
32
- */
33
- public static function GetUrlForVersions() {
34
- return static::URL_VCS_VERSIONS;
35
- }
36
-
37
- /**
38
- * @param string $fileFragment
39
- * @param string $version
40
- * @param bool $useSiteLocale
41
- * @return string|null
42
- */
43
- public function downloadFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
44
- $sFile = parent::downloadFromVcs( $fileFragment, $version, $useSiteLocale );
45
- if ( $useSiteLocale && empty( $sFile ) ) {
46
- $sFile = parent::downloadFromVcs( $fileFragment, $version, false );
47
- }
48
- return $sFile;
49
- }
50
-
51
- /**
52
- * @param string $fileFragment
53
- * @param string $version - leave empty to use the current version
54
- * @param bool $useSiteLocale
55
- * @return bool
56
- */
57
- public function existsInVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
58
- $sFile = parent::existsInVcs( $fileFragment, $version, $useSiteLocale );
59
- if ( $useSiteLocale && empty( $sFile ) ) {
60
- $sFile = parent::existsInVcs( $fileFragment, $version, false );
61
- }
62
- return $sFile;
63
- }
64
-
65
- /**
66
- * @param string $fileFragment
67
- * @param string $version
68
- * @param bool $useSiteLocale - not yet used for ClassicPress
69
- * @return string
70
- */
71
- public function getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale = true ) {
72
- if ( empty( $version ) ) {
73
- $version = Services\Services::WpGeneral()->getVersion();
74
- }
75
- return sprintf( '%s/%s', static::GetUrlForFiles( $version ), ltrim( $fileFragment, '/' ) );
76
- }
77
  }
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Cp;
4
+
5
+ use FernleafSystems\Wordpress\Services;
6
+
7
+ class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
+
9
+ const URL_VCS_ROOT = 'https://raw.githubusercontent.com/ClassicPress/ClassicPress-release';
10
+ const URL_VCS_ROOT_IL8N = self::URL_VCS_ROOT;
11
+ const URL_VCS_VERSIONS = 'https://api.github.com/repos/ClassicPress/ClassicPress-release/releases';
12
+ const URL_VCS_VERSION = 'https://github.com/ClassicPress/ClassicPress-release/releases/tag';
13
+
14
+ /**
15
+ * @param string $sVersion
16
+ * @return string
17
+ */
18
+ public static function GetUrlForVersion( $sVersion ) {
19
+ return sprintf( '%s/%s', static::URL_VCS_VERSION, $sVersion );
20
+ }
21
+
22
+ /**
23
+ * @param string $sVersion
24
+ * @return string
25
+ */
26
+ public static function GetUrlForFiles( $sVersion ) {
27
+ return sprintf( '%s/%s', static::URL_VCS_ROOT, $sVersion );
28
+ }
29
+
30
+ /**
31
+ * @return string
32
+ */
33
+ public static function GetUrlForVersions() {
34
+ return static::URL_VCS_VERSIONS;
35
+ }
36
+
37
+ /**
38
+ * @param string $fileFragment
39
+ * @param string $version
40
+ * @param bool $useSiteLocale
41
+ * @return string|null
42
+ */
43
+ public function downloadFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
44
+ $sFile = parent::downloadFromVcs( $fileFragment, $version, $useSiteLocale );
45
+ if ( $useSiteLocale && empty( $sFile ) ) {
46
+ $sFile = parent::downloadFromVcs( $fileFragment, $version, false );
47
+ }
48
+ return $sFile;
49
+ }
50
+
51
+ /**
52
+ * @param string $fileFragment
53
+ * @param string $version - leave empty to use the current version
54
+ * @param bool $useSiteLocale
55
+ * @return bool
56
+ */
57
+ public function existsInVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
58
+ $sFile = parent::existsInVcs( $fileFragment, $version, $useSiteLocale );
59
+ if ( $useSiteLocale && empty( $sFile ) ) {
60
+ $sFile = parent::existsInVcs( $fileFragment, $version, false );
61
+ }
62
+ return $sFile;
63
+ }
64
+
65
+ /**
66
+ * @param string $fileFragment
67
+ * @param string $version
68
+ * @param bool $useSiteLocale - not yet used for ClassicPress
69
+ * @return string
70
+ */
71
+ public function getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale = true ) {
72
+ if ( empty( $version ) ) {
73
+ $version = Services\Services::WpGeneral()->getVersion();
74
+ }
75
+ return sprintf( '%s/%s', static::GetUrlForFiles( $version ), ltrim( $fileFragment, '/' ) );
76
+ }
77
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Plugin/Repo.php CHANGED
@@ -1,66 +1,66 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Plugin;
4
-
5
- use FernleafSystems\Wordpress\Services;
6
-
7
- class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
-
9
- use Base;
10
- const URL_VCS_ROOT = 'https://plugins.svn.wordpress.org';
11
- const URL_VCS_DOWNLOAD_VERSIONS = 'https://plugins.svn.wordpress.org/%s/tags/';
12
- const URL_DOWNLOAD_SVN_FILE = 'https://plugins.svn.wordpress.org/%s/tags/%s/%s';
13
-
14
- /**
15
- * @param string $slug
16
- * @return string
17
- */
18
- public static function GetUrlForPlugin( $slug ) {
19
- return sprintf( '%s/%s', static::URL_VCS_ROOT, $slug );
20
- }
21
-
22
- /**
23
- * @param string $slug
24
- * @param string $version
25
- * @return string
26
- */
27
- public static function GetUrlForPluginVersion( $slug, $version ) {
28
- if ( $version != 'trunk' ) {
29
- $version = sprintf( 'tags/%s', $version );
30
- }
31
- return sprintf( '%s/%s', static::GetUrlForPlugin( $slug ), $version );
32
- }
33
-
34
- /**
35
- * @param string $slug
36
- * @return string
37
- */
38
- public static function GetUrlForPluginVersions( $slug ) {
39
- return static::GetUrlForPluginVersion( $slug, '' );
40
- }
41
-
42
- /**
43
- * @param string $fileFragment - relative to the working plugin directory
44
- * @param string $version
45
- * @param bool $useSiteLocale - unused
46
- * @return string
47
- * @throws \Exception
48
- */
49
- public function getVcsUrlForFileAndVersion( $fileFragment, $version = null, $useSiteLocale = true ) {
50
- if ( empty( $fileFragment ) ) {
51
- throw new \InvalidArgumentException( 'Plugin file fragment path provided is empty' );
52
- }
53
- if ( empty( $version ) ) {
54
- $version = $this->getWorkingVersion();
55
- }
56
- if ( empty( $version ) ) {
57
- $version = ( new Versions() )
58
- ->setWorkingSlug( $this->getWorkingSlug() )
59
- ->latest();
60
- }
61
- return sprintf( '%s/%s',
62
- rtrim( static::GetUrlForPluginVersion( $this->getWorkingSlug(), $version ), '/' ),
63
- ltrim( $fileFragment, '/' )
64
- );
65
- }
66
  }
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Plugin;
4
+
5
+ use FernleafSystems\Wordpress\Services;
6
+
7
+ class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
+
9
+ use Base;
10
+ const URL_VCS_ROOT = 'https://plugins.svn.wordpress.org';
11
+ const URL_VCS_DOWNLOAD_VERSIONS = 'https://plugins.svn.wordpress.org/%s/tags/';
12
+ const URL_DOWNLOAD_SVN_FILE = 'https://plugins.svn.wordpress.org/%s/tags/%s/%s';
13
+
14
+ /**
15
+ * @param string $slug
16
+ * @return string
17
+ */
18
+ public static function GetUrlForPlugin( $slug ) {
19
+ return sprintf( '%s/%s', static::URL_VCS_ROOT, $slug );
20
+ }
21
+
22
+ /**
23
+ * @param string $slug
24
+ * @param string $version
25
+ * @return string
26
+ */
27
+ public static function GetUrlForPluginVersion( $slug, $version ) {
28
+ if ( $version != 'trunk' ) {
29
+ $version = sprintf( 'tags/%s', $version );
30
+ }
31
+ return sprintf( '%s/%s', static::GetUrlForPlugin( $slug ), $version );
32
+ }
33
+
34
+ /**
35
+ * @param string $slug
36
+ * @return string
37
+ */
38
+ public static function GetUrlForPluginVersions( $slug ) {
39
+ return static::GetUrlForPluginVersion( $slug, '' );
40
+ }
41
+
42
+ /**
43
+ * @param string $fileFragment - relative to the working plugin directory
44
+ * @param string $version
45
+ * @param bool $useSiteLocale - unused
46
+ * @return string
47
+ * @throws \Exception
48
+ */
49
+ public function getVcsUrlForFileAndVersion( $fileFragment, $version = null, $useSiteLocale = true ) {
50
+ if ( empty( $fileFragment ) ) {
51
+ throw new \InvalidArgumentException( 'Plugin file fragment path provided is empty' );
52
+ }
53
+ if ( empty( $version ) ) {
54
+ $version = $this->getWorkingVersion();
55
+ }
56
+ if ( empty( $version ) ) {
57
+ $version = ( new Versions() )
58
+ ->setWorkingSlug( $this->getWorkingSlug() )
59
+ ->latest();
60
+ }
61
+ return sprintf( '%s/%s',
62
+ rtrim( static::GetUrlForPluginVersion( $this->getWorkingSlug(), $version ), '/' ),
63
+ ltrim( $fileFragment, '/' )
64
+ );
65
+ }
66
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Theme/Files.php CHANGED
@@ -1,123 +1,123 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Theme;
4
-
5
- use FernleafSystems\Wordpress\Services;
6
-
7
- class Files extends Services\Utilities\WpOrg\Base\PluginThemeFilesBase {
8
-
9
- use Base;
10
-
11
- /**
12
- * Given a full root path on the file system for a file, locate the plugin to which this file belongs.
13
- * @param string $fullPath
14
- * @return Services\Core\VOs\Assets\WpThemeVo|null
15
- */
16
- public function findThemeFromFile( string $fullPath ) {
17
- $theTheme = null;
18
-
19
- $fragment = $this->getThemePathFragmentFromPath( $fullPath );
20
-
21
- if ( !empty( $fragment ) && strpos( $fragment, '/' ) > 0 ) {
22
- $WPT = Services\Services::WpThemes();
23
- $dir = substr( $fragment, 0, strpos( $fragment, '/' ) );
24
- foreach ( $WPT->getThemes() as $theme ) {
25
- if ( $dir == $theme->get_stylesheet() ) {
26
- $theTheme = $WPT->getThemeAsVo( $dir );
27
- break;
28
- }
29
- }
30
- }
31
- return $theTheme;
32
- }
33
-
34
- /**
35
- * Verifies the file exists on the SVN repository for the particular version that's installed.
36
- * @param string $sFullFilePath
37
- * @return bool
38
- * @throws \InvalidArgumentException
39
- */
40
- public function isValidFileFromTheme( $sFullFilePath ) {
41
-
42
- $theTheme = $this->findThemeFromFile( $sFullFilePath );
43
- if ( !$theTheme instanceof Services\Core\VOs\Assets\WpThemeVo ) {
44
- throw new \InvalidArgumentException( 'Not actually a theme file.', 1 );
45
- }
46
- if ( !$theTheme->isWpOrg() ) {
47
- throw new \InvalidArgumentException( 'Not a WordPress.org theme.', 2 );
48
- }
49
-
50
- // if uses SVN tags, use that version. Otherwise trunk.
51
- return ( new Repo() )
52
- ->setWorkingSlug( $theTheme->stylesheet )
53
- ->setWorkingVersion( $theTheme->version )
54
- ->existsInVcs( $this->getRelativeFilePathFromItsInstallDir( $sFullFilePath ) );
55
- }
56
-
57
- /**
58
- * @param string $fullPath
59
- * @return bool
60
- */
61
- public function replaceFileFromVcs( $fullPath ) :bool {
62
- $tmpFile = $this->getOriginalFileFromVcs( $fullPath );
63
- return !empty( $tmpFile ) && Services\Services::WpFs()->move( $tmpFile, $fullPath );
64
- }
65
-
66
- /**
67
- * Verifies the file exists on the SVN repository for the particular version that's installed.
68
- * @param string $fullPath
69
- * @return bool
70
- * @throws \InvalidArgumentException
71
- */
72
- public function verifyFileContents( $fullPath ) :bool {
73
- $tmpFile = $this->getOriginalFileFromVcs( $fullPath );
74
- return !empty( $tmpFile )
75
- && ( new Services\Utilities\File\Compare\CompareHash() )->isEqualFiles( $tmpFile, $fullPath );
76
- }
77
-
78
- /**
79
- * @param string $fullPath
80
- * @return string|null
81
- */
82
- public function getOriginalFileFromVcs( $fullPath ) {
83
- $tmpFile = null;
84
- $theTheme = $this->findThemeFromFile( $fullPath );
85
- if ( !empty( $theTheme ) ) {
86
- $tmpFile = ( new Repo() )
87
- ->setWorkingSlug( $theTheme->stylesheet )
88
- ->setWorkingVersion( $theTheme->version )
89
- ->downloadFromVcs( $this->getRelativeFilePathFromItsInstallDir( $fullPath ) );
90
- }
91
- return $tmpFile;
92
- }
93
-
94
- /**
95
- * @param string $sFile - can either be absolute, or relative to ABSPATH
96
- * @return string|null - the path to the file relative to Plugins Dir.
97
- */
98
- public function getThemePathFragmentFromPath( $sFile ) {
99
- $sFragment = null;
100
-
101
- if ( !Services\Services::WpFs()->isAbsPath( $sFile ) ) { // assume it's relative to ABSPATH
102
- $sFile = path_join( ABSPATH, $sFile );
103
- }
104
- $sFile = wp_normalize_path( $sFile );
105
- $sThemesDir = wp_normalize_path( get_theme_root() );
106
-
107
- if ( strpos( $sFile, $sThemesDir ) === 0 ) {
108
- $sFragment = ltrim( str_replace( $sThemesDir, '', $sFile ), '/' );
109
- }
110
-
111
- return $sFragment;
112
- }
113
-
114
- /**
115
- * Gets the path of the plugin file relative to its own home plugin dir. (not wp-content/plugins/)
116
- * @param string $file
117
- * @return string
118
- */
119
- public function getRelativeFilePathFromItsInstallDir( $file ) {
120
- $sRelDirFragment = $this->getThemePathFragmentFromPath( $file );
121
- return substr( $sRelDirFragment, strpos( $sRelDirFragment, '/' ) + 1 );
122
- }
123
  }
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Theme;
4
+
5
+ use FernleafSystems\Wordpress\Services;
6
+
7
+ class Files extends Services\Utilities\WpOrg\Base\PluginThemeFilesBase {
8
+
9
+ use Base;
10
+
11
+ /**
12
+ * Given a full root path on the file system for a file, locate the plugin to which this file belongs.
13
+ * @param string $fullPath
14
+ * @return Services\Core\VOs\Assets\WpThemeVo|null
15
+ */
16
+ public function findThemeFromFile( string $fullPath ) {
17
+ $theTheme = null;
18
+
19
+ $fragment = $this->getThemePathFragmentFromPath( $fullPath );
20
+
21
+ if ( !empty( $fragment ) && strpos( $fragment, '/' ) > 0 ) {
22
+ $WPT = Services\Services::WpThemes();
23
+ $dir = substr( $fragment, 0, strpos( $fragment, '/' ) );
24
+ foreach ( $WPT->getThemes() as $theme ) {
25
+ if ( $dir == $theme->get_stylesheet() ) {
26
+ $theTheme = $WPT->getThemeAsVo( $dir );
27
+ break;
28
+ }
29
+ }
30
+ }
31
+ return $theTheme;
32
+ }
33
+
34
+ /**
35
+ * Verifies the file exists on the SVN repository for the particular version that's installed.
36
+ * @param string $sFullFilePath
37
+ * @return bool
38
+ * @throws \InvalidArgumentException
39
+ */
40
+ public function isValidFileFromTheme( $sFullFilePath ) {
41
+
42
+ $theTheme = $this->findThemeFromFile( $sFullFilePath );
43
+ if ( !$theTheme instanceof Services\Core\VOs\Assets\WpThemeVo ) {
44
+ throw new \InvalidArgumentException( 'Not actually a theme file.', 1 );
45
+ }
46
+ if ( !$theTheme->isWpOrg() ) {
47
+ throw new \InvalidArgumentException( 'Not a WordPress.org theme.', 2 );
48
+ }
49
+
50
+ // if uses SVN tags, use that version. Otherwise trunk.
51
+ return ( new Repo() )
52
+ ->setWorkingSlug( $theTheme->stylesheet )
53
+ ->setWorkingVersion( $theTheme->version )
54
+ ->existsInVcs( $this->getRelativeFilePathFromItsInstallDir( $sFullFilePath ) );
55
+ }
56
+
57
+ /**
58
+ * @param string $fullPath
59
+ * @return bool
60
+ */
61
+ public function replaceFileFromVcs( $fullPath ) :bool {
62
+ $tmpFile = $this->getOriginalFileFromVcs( $fullPath );
63
+ return !empty( $tmpFile ) && Services\Services::WpFs()->move( $tmpFile, $fullPath );
64
+ }
65
+
66
+ /**
67
+ * Verifies the file exists on the SVN repository for the particular version that's installed.
68
+ * @param string $fullPath
69
+ * @return bool
70
+ * @throws \InvalidArgumentException
71
+ */
72
+ public function verifyFileContents( $fullPath ) :bool {
73
+ $tmpFile = $this->getOriginalFileFromVcs( $fullPath );
74
+ return !empty( $tmpFile )
75
+ && ( new Services\Utilities\File\Compare\CompareHash() )->isEqualFiles( $tmpFile, $fullPath );
76
+ }
77
+
78
+ /**
79
+ * @param string $fullPath
80
+ * @return string|null
81
+ */
82
+ public function getOriginalFileFromVcs( $fullPath ) {
83
+ $tmpFile = null;
84
+ $theTheme = $this->findThemeFromFile( $fullPath );
85
+ if ( !empty( $theTheme ) ) {
86
+ $tmpFile = ( new Repo() )
87
+ ->setWorkingSlug( $theTheme->stylesheet )
88
+ ->setWorkingVersion( $theTheme->version )
89
+ ->downloadFromVcs( $this->getRelativeFilePathFromItsInstallDir( $fullPath ) );
90
+ }
91
+ return $tmpFile;
92
+ }
93
+
94
+ /**
95
+ * @param string $sFile - can either be absolute, or relative to ABSPATH
96
+ * @return string|null - the path to the file relative to Plugins Dir.
97
+ */
98
+ public function getThemePathFragmentFromPath( $sFile ) {
99
+ $sFragment = null;
100
+
101
+ if ( !Services\Services::WpFs()->isAbsPath( $sFile ) ) { // assume it's relative to ABSPATH
102
+ $sFile = path_join( ABSPATH, $sFile );
103
+ }
104
+ $sFile = wp_normalize_path( $sFile );
105
+ $sThemesDir = wp_normalize_path( get_theme_root() );
106
+
107
+ if ( strpos( $sFile, $sThemesDir ) === 0 ) {
108
+ $sFragment = ltrim( str_replace( $sThemesDir, '', $sFile ), '/' );
109
+ }
110
+
111
+ return $sFragment;
112
+ }
113
+
114
+ /**
115
+ * Gets the path of the plugin file relative to its own home plugin dir. (not wp-content/plugins/)
116
+ * @param string $file
117
+ * @return string
118
+ */
119
+ public function getRelativeFilePathFromItsInstallDir( $file ) {
120
+ $sRelDirFragment = $this->getThemePathFragmentFromPath( $file );
121
+ return substr( $sRelDirFragment, strpos( $sRelDirFragment, '/' ) + 1 );
122
+ }
123
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Theme/Repo.php CHANGED
@@ -1,59 +1,59 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Theme;
4
-
5
- use FernleafSystems\Wordpress\Services;
6
-
7
- class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
-
9
- use Base;
10
- const URL_VCS_ROOT = 'https://themes.svn.wordpress.org';
11
-
12
- /**
13
- * @param string $slug
14
- * @return string
15
- */
16
- public static function GetUrlForTheme( $slug ) {
17
- return sprintf( '%s/%s', static::URL_VCS_ROOT, $slug );
18
- }
19
-
20
- /**
21
- * @param string $slug
22
- * @param string $version
23
- * @return string
24
- */
25
- public static function GetUrlForThemeVersion( $slug, $version ) {
26
- return sprintf( '%s/%s', static::GetUrlForTheme( $slug ), $version );
27
- }
28
-
29
- /**
30
- * @param string $slug
31
- * @return string
32
- */
33
- public static function GetUrlForThemeVersions( $slug ) {
34
- return static::GetUrlForThemeVersion( $slug, '' );
35
- }
36
-
37
- /**
38
- * @param string $fileFragment - relative to the working plugin directory
39
- * @param string $version
40
- * @param bool $useSiteLocale - unused
41
- * @return string
42
- * @throws \Exception
43
- */
44
- public function getVcsUrlForFileAndVersion( $fileFragment, $version = null, $useSiteLocale = true ) {
45
- if ( empty( $fileFragment ) ) {
46
- throw new \InvalidArgumentException( 'Theme file fragment path provided is empty' );
47
- }
48
- if ( empty( $version ) ) {
49
- $version = $this->getWorkingVersion();
50
- }
51
- if ( empty( $version ) ) {
52
- $version = ( new Versions() )
53
- ->setWorkingSlug( $this->getWorkingSlug() )
54
- ->latest();
55
- }
56
- return sprintf( '%s/%s',
57
- static::GetUrlForThemeVersion( $this->getWorkingSlug(), $version ), ltrim( $fileFragment, '/' ) );
58
- }
59
  }
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Theme;
4
+
5
+ use FernleafSystems\Wordpress\Services;
6
+
7
+ class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
+
9
+ use Base;
10
+ const URL_VCS_ROOT = 'https://themes.svn.wordpress.org';
11
+
12
+ /**
13
+ * @param string $slug
14
+ * @return string
15
+ */
16
+ public static function GetUrlForTheme( $slug ) {
17
+ return sprintf( '%s/%s', static::URL_VCS_ROOT, $slug );
18
+ }
19
+
20
+ /**
21
+ * @param string $slug
22
+ * @param string $version
23
+ * @return string
24
+ */
25
+ public static function GetUrlForThemeVersion( $slug, $version ) {
26
+ return sprintf( '%s/%s', static::GetUrlForTheme( $slug ), $version );
27
+ }
28
+
29
+ /**
30
+ * @param string $slug
31
+ * @return string
32
+ */
33
+ public static function GetUrlForThemeVersions( $slug ) {
34
+ return static::GetUrlForThemeVersion( $slug, '' );
35
+ }
36
+
37
+ /**
38
+ * @param string $fileFragment - relative to the working plugin directory
39
+ * @param string $version
40
+ * @param bool $useSiteLocale - unused
41
+ * @return string
42
+ * @throws \Exception
43
+ */
44
+ public function getVcsUrlForFileAndVersion( $fileFragment, $version = null, $useSiteLocale = true ) {
45
+ if ( empty( $fileFragment ) ) {
46
+ throw new \InvalidArgumentException( 'Theme file fragment path provided is empty' );
47
+ }
48
+ if ( empty( $version ) ) {
49
+ $version = $this->getWorkingVersion();
50
+ }
51
+ if ( empty( $version ) ) {
52
+ $version = ( new Versions() )
53
+ ->setWorkingSlug( $this->getWorkingSlug() )
54
+ ->latest();
55
+ }
56
+ return sprintf( '%s/%s',
57
+ static::GetUrlForThemeVersion( $this->getWorkingSlug(), $version ), ltrim( $fileFragment, '/' ) );
58
+ }
59
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/WpOrg/Wp/Repo.php CHANGED
@@ -1,72 +1,72 @@
1
- <?php
2
-
3
- namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Wp;
4
-
5
- use FernleafSystems\Wordpress\Services;
6
-
7
- class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
-
9
- const URL_VCS_ROOT = 'https://core.svn.wordpress.org';
10
- const URL_VCS_ROOT_IL8N = 'https://i18n.svn.wordpress.org';
11
-
12
- /**
13
- * @param string $version
14
- * @param bool $useLocale
15
- * @return string
16
- */
17
- public static function GetUrlForVersion( $version, $useLocale = true ) {
18
- return sprintf(
19
- '%s/tags/%s',
20
- $useLocale ? static::URL_VCS_ROOT_IL8N : static::URL_VCS_ROOT,
21
- $useLocale ? $version.'/dist' : $version
22
- );
23
- }
24
-
25
- /**
26
- * @return string
27
- */
28
- public static function GetUrlForVersions() {
29
- return static::GetUrlForVersion( '' );
30
- }
31
-
32
- /**
33
- * @param string $fileFragment
34
- * @param string $version
35
- * @param bool $useSiteLocale
36
- * @return string|null
37
- */
38
- public function downloadFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
39
- $file = parent::downloadFromVcs( $fileFragment, $version, $useSiteLocale );
40
- if ( $useSiteLocale && empty( $file ) ) {
41
- $file = parent::downloadFromVcs( $fileFragment, $version, false );
42
- }
43
- return $file;
44
- }
45
-
46
- /**
47
- * @param string $fileFragment
48
- * @param string $version - leave empty to use the current version
49
- * @param bool $useSiteLocale
50
- * @return bool
51
- */
52
- public function existsInVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
53
- $file = parent::existsInVcs( $fileFragment, $version, $useSiteLocale );
54
- if ( $useSiteLocale && empty( $file ) ) {
55
- $file = parent::existsInVcs( $fileFragment, $version, false );
56
- }
57
- return $file;
58
- }
59
-
60
- /**
61
- * @param string $fileFragment
62
- * @param string $version
63
- * @param bool $useSiteLocale
64
- * @return string
65
- */
66
- public function getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale = true ) {
67
- if ( empty( $version ) ) {
68
- $version = Services\Services::WpGeneral()->getVersion();
69
- }
70
- return sprintf( '%s/%s', static::GetUrlForVersion( $version, $useSiteLocale ), ltrim( $fileFragment, '/' ) );
71
- }
72
  }
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\WpOrg\Wp;
4
+
5
+ use FernleafSystems\Wordpress\Services;
6
+
7
+ class Repo extends Services\Utilities\WpOrg\Base\RepoBase {
8
+
9
+ const URL_VCS_ROOT = 'https://core.svn.wordpress.org';
10
+ const URL_VCS_ROOT_IL8N = 'https://i18n.svn.wordpress.org';
11
+
12
+ /**
13
+ * @param string $version
14
+ * @param bool $useLocale
15
+ * @return string
16
+ */
17
+ public static function GetUrlForVersion( $version, $useLocale = true ) {
18
+ return sprintf(
19
+ '%s/tags/%s',
20
+ $useLocale ? static::URL_VCS_ROOT_IL8N : static::URL_VCS_ROOT,
21
+ $useLocale ? $version.'/dist' : $version
22
+ );
23
+ }
24
+
25
+ /**
26
+ * @return string
27
+ */
28
+ public static function GetUrlForVersions() {
29
+ return static::GetUrlForVersion( '' );
30
+ }
31
+
32
+ /**
33
+ * @param string $fileFragment
34
+ * @param string $version
35
+ * @param bool $useSiteLocale
36
+ * @return string|null
37
+ */
38
+ public function downloadFromVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
39
+ $file = parent::downloadFromVcs( $fileFragment, $version, $useSiteLocale );
40
+ if ( $useSiteLocale && empty( $file ) ) {
41
+ $file = parent::downloadFromVcs( $fileFragment, $version, false );
42
+ }
43
+ return $file;
44
+ }
45
+
46
+ /**
47
+ * @param string $fileFragment
48
+ * @param string $version - leave empty to use the current version
49
+ * @param bool $useSiteLocale
50
+ * @return bool
51
+ */
52
+ public function existsInVcs( $fileFragment, $version = null, $useSiteLocale = true ) {
53
+ $file = parent::existsInVcs( $fileFragment, $version, $useSiteLocale );
54
+ if ( $useSiteLocale && empty( $file ) ) {
55
+ $file = parent::existsInVcs( $fileFragment, $version, false );
56
+ }
57
+ return $file;
58
+ }
59
+
60
+ /**
61
+ * @param string $fileFragment
62
+ * @param string $version
63
+ * @param bool $useSiteLocale
64
+ * @return string
65
+ */
66
+ public function getVcsUrlForFileAndVersion( $fileFragment, $version, $useSiteLocale = true ) {
67
+ if ( empty( $version ) ) {
68
+ $version = Services\Services::WpGeneral()->getVersion();
69
+ }
70
+ return sprintf( '%s/%s', static::GetUrlForVersion( $version, $useSiteLocale ), ltrim( $fileFragment, '/' ) );
71
+ }
72
  }
templates/twig/admin/user/profile/mfa/mfa_yubi.twig CHANGED
@@ -41,7 +41,7 @@
41
  {% if flags.is_profile_active %}
42
  <p class="description">{{ strings.to_remove_device }}</p>
43
  {% endif %}
44
- <p class="description">{{ strings.multiple_for_pro }}</p>
45
  {% endif %}
46
  </td>
47
  </tr>
41
  {% if flags.is_profile_active %}
42
  <p class="description">{{ strings.to_remove_device }}</p>
43
  {% endif %}
44
+ <p class="description">{{ strings.multiple_for_pro }}</p>
45
  {% endif %}
46
  </td>
47
  </tr>
templates/twig/snippets/plugin_vulnerability.twig CHANGED
@@ -1,25 +1,8 @@
1
  <tr class="icwp-plugin-vulnerability plugin-update-tr">
2
  <td colspan="{{ vars.colspan }}" class="colspanchange">
3
- <p class="vuln-title">{{ strings.known_vuln|raw }}</p>
4
- <table>
5
- <tr>
6
- <th>{{ strings.name }}</th>
7
- <th>{{ strings.type }}</th>
8
- <th>{{ strings.fixed_versions }}</th>
9
- <th>{{ strings.more_info }}</th>
10
- </tr>
11
- {% for vuln in vars.vulns %}
12
- <tr>
13
- <td>{{ vuln.title }}</td>
14
- <td>{{ vuln.vuln_type }}</td>
15
- <td>{{ vuln.fixed_in }}</td>
16
- <td>
17
- {% if vuln.url|default('') is not empty %}
18
- <a href="{{ vuln.url }}" target="_blank">{{ strings.more_info }}</a>
19
- {% endif %}
20
- </td>
21
- </tr>
22
- {% endfor %}
23
- </table>
24
  </td>
25
  </tr>
1
  <tr class="icwp-plugin-vulnerability plugin-update-tr">
2
  <td colspan="{{ vars.colspan }}" class="colspanchange">
3
+ <p class="vuln-title">
4
+ {{ strings.known_vuln|raw }}
5
+ <a href="{{ hrefs.vuln_lookup }}" target="_blank">{{ strings.more_info }}</a>
6
+ </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  </td>
8
  </tr>
templates/twig/wpadmin_pages/components/page/nav_sidebar.twig CHANGED
@@ -28,7 +28,7 @@
28
  </div>
29
  {% endif %}
30
 
31
- <a class="nav-link p-0 mb-0 {{ mitem.classes|default([])|join( ' ' ) }} text-center"
32
  href="{{ mitem.sub_items|default([]) is empty ? mitem.href|default('javascript:{}') : 'javascript:{}' }}"
33
  {% for data_key,data_val in mitem.data|default([]) %}
34
  data-{{ data_key }}="{{ data_val }}"
@@ -43,7 +43,7 @@
43
  >
44
 
45
  {% if mitem.img|default('') is not empty %}
46
- <span class="nav-icon mb-1 d-block" style="vertical-align: text-bottom;">
47
  {{ mitem.img|raw }}
48
  </span>
49
  {% endif %}
28
  </div>
29
  {% endif %}
30
 
31
+ <a class="nav-link p-0 mb-1 {{ mitem.classes|default([])|join( ' ' ) }} text-left"
32
  href="{{ mitem.sub_items|default([]) is empty ? mitem.href|default('javascript:{}') : 'javascript:{}' }}"
33
  {% for data_key,data_val in mitem.data|default([]) %}
34
  data-{{ data_key }}="{{ data_val }}"
43
  >
44
 
45
  {% if mitem.img|default('') is not empty %}
46
+ <span class="nav-icon mr-1" style="vertical-align: text-bottom;">
47
  {{ mitem.img|raw }}
48
  </span>
49
  {% endif %}
templates/twig/wpadmin_pages/insights/ips/ip_analyse/index.twig CHANGED
@@ -6,7 +6,8 @@
6
  <div class="form-group row">
7
  <div class="col mb-2">
8
  <select id="IpReviewSelect" name="fIp"
9
- class="select2picker form-control mb-2"
 
10
  style="min-width: 300px;">
11
  <option value="">-- {{ strings.select_ip }} --</option>
12
  {% for unique_ip in vars.unique_ips %}
6
  <div class="form-group row">
7
  <div class="col mb-2">
8
  <select id="IpReviewSelect" name="fIp"
9
+ data-ajaxparams="{{ ajax.ip_review_select }}"
10
+ class="select2picker dynamic form-control mb-2"
11
  style="min-width: 300px;">
12
  <option value="">-- {{ strings.select_ip }} --</option>
13
  {% for unique_ip in vars.unique_ips %}
templates/twig/wpadmin_pages/insights/ips/ips_black.twig CHANGED
@@ -11,7 +11,7 @@
11
  <div class="form-row">
12
  <div class="col mb-2">
13
  <select id="_fIpBlack" name="fIp"
14
- class="select2picker form-control"
15
  style="width: 100%">
16
  <option value="">-- {{ strings.select }} --</option>
17
  {% for unique_ip in vars.unique_ips_black %}
11
  <div class="form-row">
12
  <div class="col mb-2">
13
  <select id="_fIpBlack" name="fIp"
14
+ class="select2picker static form-control"
15
  style="width: 100%">
16
  <option value="">-- {{ strings.select }} --</option>
17
  {% for unique_ip in vars.unique_ips_black %}
templates/twig/wpadmin_pages/insights/ips/ips_white.twig CHANGED
@@ -10,7 +10,7 @@
10
  <div class="form-row">
11
  <div class="col mb-2">
12
  <select id="_fIpWhite" name="fIp"
13
- class="select2picker form-control mb-2"
14
  style="width: 100%">
15
  <option value="">-- {{ strings.select }} --</option>
16
  {% for unique_ip in vars.unique_ips_white %}
10
  <div class="form-row">
11
  <div class="col mb-2">
12
  <select id="_fIpWhite" name="fIp"
13
+ class="select2picker static form-control mb-2"
14
  style="width: 100%">
15
  <option value="">-- {{ strings.select }} --</option>
16
  {% for unique_ip in vars.unique_ips_white %}
templates/twig/wpadmin_pages/insights/license/license.twig CHANGED
@@ -146,12 +146,23 @@
146
  {{ icwp_macros.shieldpro }} control panel and get Pro features enabled on your site automatically.
147
  </dd>
148
 
149
- <dt>Powerful, Auto-Learning Malware Scanner</dt>
 
 
 
 
 
 
 
150
  <dd>Detects common and uncommon malware patterns in PHP files and alerts you immediately.
151
  <br />With ShieldNET crowd-sourcing intelligence, Shield automatically hides false-positives
152
  so you can focus on risks that matter, and can ignore the noise that wastes your time.
153
  </dd>
154
 
 
 
 
 
155
  <dt>Traffic Rate Limiting</dt>
156
  <dd>Prevent abuse of your web hosting resources by detecting and blocking bots that send
157
  too many requests to your site.
146
  {{ icwp_macros.shieldpro }} control panel and get Pro features enabled on your site automatically.
147
  </dd>
148
 
149
+ <dt>Protect your <code>wp-config.php</code> files</dt>
150
+ <dd>The only WordPress security plugin to add monitoring of your
151
+ <code>wp-config.php</code> files with automatic rollback and recovery.</dd>
152
+
153
+ <dt>MainWP Integration (no extra extension plugins required)</dt>
154
+ <dd>Use MainWP to manage and monitor the security of all your WordPress sites.</dd>
155
+
156
+ <dt>Malware Scanner: Auto-learning and Detects Never-Before-Seen Malware</dt>
157
  <dd>Detects common and uncommon malware patterns in PHP files and alerts you immediately.
158
  <br />With ShieldNET crowd-sourcing intelligence, Shield automatically hides false-positives
159
  so you can focus on risks that matter, and can ignore the noise that wastes your time.
160
  </dd>
161
 
162
+ <dt>ShieldNET Integration</dt>
163
+ <dd>Take advantage of the intelligence gathered throughout the entire Shield network to protect
164
+ your WordPress sites.</dd>
165
+
166
  <dt>Traffic Rate Limiting</dt>
167
  <dd>Prevent abuse of your web hosting resources by detecting and blocking bots that send
168
  too many requests to your site.
templates/twig/wpadmin_pages/insights/reports/charts_custom.twig CHANGED
@@ -7,7 +7,7 @@
7
 
8
  <div class="col-auto mb-3">
9
  <label class="sr-only" for="_events">{{ strings.select_events }}</label>
10
- <select multiple="multiple" name="events[]" id="_events" class="select2picker">
11
  {% for event_key,event_name in vars.events %}
12
  <option value="{{ event_key }}">{{ event_name }}</option>
13
  {% endfor %}
7
 
8
  <div class="col-auto mb-3">
9
  <label class="sr-only" for="_events">{{ strings.select_events }}</label>
10
+ <select multiple="multiple" name="events[]" id="_events" class="select2picker static">
11
  {% for event_key,event_name in vars.events %}
12
  <option value="{{ event_key }}">{{ event_name }}</option>
13
  {% endfor %}
templates/twig/wpadmin_pages/insights/scans/modal/base_modal_content.twig ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="modal-header">
2
+ {% block modal_header %}
3
+ <h5 class="modal-title">
4
+ {% block modal_title %}
5
+ {{ strings.modal_title|default('Shield Modal Title') }}
6
+ {% endblock %}
7
+ </h5>
8
+ {% block modal_title_button_close %}
9
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
10
+ <span aria-hidden="true">&times;</span>
11
+ </button>
12
+ {% endblock %}
13
+ {% endblock %}
14
+ </div>
15
+ <div class="modal-body">
16
+ {% block modal_body %}
17
+ {{ strings.modal_title|default('No modal body yet') }}
18
+ {% endblock %}
19
+ </div>
20
+ <div class="modal-footer">
21
+ {% block modal_footer %}
22
+ {% endblock %}
23
+ </div>
templates/twig/wpadmin_pages/insights/scans/modal/code_render.twig CHANGED
@@ -1,7 +1,7 @@
1
  <div class="modal" id="CodeRenderModal" tabindex="-1" role="dialog" aria-labelledby=""
2
  style="z-index: 10000000;"
3
  aria-hidden="true">
4
- <div class="modal-dialog modal-dialog-centered modal-xl modal-dialog-scrollable" role="document" style="z-index: 10000001;">
5
  <div class="modal-content">
6
  <div class="modal-header">
7
  <h5 class="modal-title">
1
  <div class="modal" id="CodeRenderModal" tabindex="-1" role="dialog" aria-labelledby=""
2
  style="z-index: 10000000;"
3
  aria-hidden="true">
4
+ <div class="modal-dialog modal-xl modal-dialog-scrollable" role="document" style="z-index: 10000001;">
5
  <div class="modal-content">
6
  <div class="modal-header">
7
  <h5 class="modal-title">
templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view.twig ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="modal" id="ScanItemViewModal" tabindex="-1" role="dialog" aria-labelledby=""
2
+ style="z-index: 10000000;"
3
+ aria-hidden="true">
4
+ <div class="modal-dialog modal-xl modal-dialog-scrollable"
5
+ role="document" style="z-index: 10000001;">
6
+ <div class="modal-content">
7
+ <div class="modal-header">
8
+ <h5 class="modal-title">
9
+ code
10
+ </h5>
11
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
12
+ <span aria-hidden="true">&times;</span>
13
+ </button>
14
+ </div>
15
+ <div class="modal-body">
16
+ </div>
17
+ <div class="modal-footer">
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </div>
templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/item_history.twig ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <div class="col scan-item-history">
3
+ {% if flags.has_history %}
4
+ {% for ts,ts_history in vars.history %}
5
+ <p class="font-weight-bold">{{ ts }}</p>
6
+ <ul>
7
+ {% for line in ts_history %}
8
+ <li>{{ line|raw }}</li>
9
+ {% endfor %}
10
+ </ul>
11
+ {% endfor %}
12
+ {% else %}
13
+ <p>No history could be loaded.</p>
14
+ {% endif %}
15
+ </div>
16
+ </div>
templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/item_info.twig ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <div class="col scan-item-history">
3
+ <h4 class="mb-3">File: <span style="font-family: monospace">
4
+ {{ vars.path_fragment }}</span></h4>
5
+ <ul style="list-style: inside disc">
6
+ <li>{{ strings.file_full_path|raw }}</li>
7
+ <li>{{ strings.file_status|raw }}</li>
8
+ </ul>
9
+ <h6>{{ strings.file_description }}</h6>
10
+ <ul>
11
+ {% for line in vars.file_description %}
12
+ <li>{{ line|raw }}</li>
13
+ {% endfor %}
14
+ </ul>
15
+ </div>
16
+ </div>
templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/modal_content.twig ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends '/wpadmin_pages/insights/scans/modal/base_modal_content.twig' %}
2
+
3
+ {% block modal_body %}
4
+ {% include '/wpadmin_pages/insights/scans/modal/scan_item_view/tabpanel.twig' %}
5
+ {% endblock %}
6
+ {% block modal_footer %}
7
+
8
+ <a href="{{ flags.can_download ? hrefs.file_download : '#' }}"
9
+ class="btn btn-dark href-download{% if not flags.can_download %} disabled{% endif %}"
10
+ {% if not flags.can_download %}disabled="disabled"{% endif %}
11
+ >
12
+ {{ imgs.svgs.file_download|raw }}
13
+ {{ strings.file_download }}
14
+ </a>
15
+
16
+ {% endblock %}
templates/twig/wpadmin_pages/insights/scans/modal/scan_item_view/tabpanel.twig ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <div class="col insights-sub-nav insights_section">
3
+ <ul class="nav nav-tabs">
4
+
5
+ <li class="nav-item">
6
+ <a class="nav-link active" data-toggle="tab" role="tab" href="#tabInfo"
7
+ data-bs-toggle="tab">
8
+ {{ strings.tab_info }}
9
+ </a>
10
+ </li>
11
+
12
+ <li class="nav-item">
13
+ <a class="nav-link" data-toggle="tab" role="tab" href="#tabHistory"
14
+ data-bs-toggle="tab">
15
+ {{ strings.tab_history }}
16
+ </a>
17
+ </li>
18
+
19
+ <li class="nav-item">
20
+ <a class="nav-link" data-toggle="tab" role="tab" href="#tabContents"
21
+ data-bs-toggle="tab">
22
+ {{ strings.tab_filecontents }}
23
+ </a>
24
+ </li>
25
+
26
+ <li class="nav-item">
27
+ <a class="nav-link" data-toggle="tab" role="tab" href="#tabDiff"
28
+ data-bs-toggle="tab">
29
+ {{ strings.tab_diff }}
30
+ </a>
31
+ </li>
32
+ </ul>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="tab-content">
37
+
38
+ <div class="tab-pane show active" id="tabInfo" role="tabpanel" aria-labelledby="tabInfo">
39
+ <div class="row">
40
+ <div class="col pt-3">
41
+ {{ content.tab_info|raw }}
42
+ </div>
43
+ </div>
44
+ </div>
45
+
46
+ <div class="tab-pane" id="tabHistory" role="tabpanel" aria-labelledby="tabHistory">
47
+ <div class="row">
48
+ <div class="col pt-3" id="TabHistory">
49
+ {{ content.tab_history|raw }}
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <div class="tab-pane" id="tabContents" role="tabpanel" aria-labelledby="tabContents">
55
+ <div class="row">
56
+ <div class="col pt-3">
57
+ {{ content.tab_filecontents|raw }}
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ <div class="tab-pane" id="tabDiff" role="tabpanel" aria-labelledby="tabDiff">
63
+ <div class="row">
64
+ <div class="col pt-3" id="TabHistory">
65
+ {% if flags.has_diff %}
66
+ {{ content.tab_diff|raw }}
67
+ {% else %}
68
+ <p>{{ content.tab_diff }}</p>
69
+ {% endif %}
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </div>
templates/twig/wpadmin_pages/insights/scans/modal/shield_modal_container.twig ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="modal" id="ShieldModalContainer" tabindex="-1" role="dialog" aria-labelledby=""
2
+ style="z-index: 10000000;"
3
+ aria-hidden="true">
4
+ <div class="modal-dialog modal-xl modal-dialog-scrollable"
5
+ role="document"
6
+ style="z-index: 10000001;">
7
+ <div class="modal-content">
8
+ Fill with response data
9
+ </div>
10
+ </div>
11
+ </div>
templates/twig/wpadmin_pages/insights/scans/results/index.twig CHANGED
@@ -6,6 +6,6 @@
6
  {% include '/wpadmin_pages/insights/scans/results/scan_results.twig' %}
7
  </div>
8
  </div>
9
- {% include '/wpadmin_pages/insights/scans/modal/code_render.twig' %}
10
  {% include '/wpadmin_pages/insights/scans/modal/progress.twig' %}
11
  {% endblock %}
6
  {% include '/wpadmin_pages/insights/scans/results/scan_results.twig' %}
7
  </div>
8
  </div>
9
+ {% include '/wpadmin_pages/insights/scans/modal/shield_modal_container.twig' %}
10
  {% include '/wpadmin_pages/insights/scans/modal/progress.twig' %}
11
  {% endblock %}
templates/twig/wpadmin_pages/insights/scans/run/scan_areas.twig CHANGED
@@ -10,75 +10,24 @@
10
 
11
  <div class="row mb-3">
12
  <div class="col-12">
13
- <h6 class="mt-0 mb-2">{{ strings.scanselect_file_areas }}</h6>
14
  </div>
15
 
16
  <div class="col-xl-3 col-lg-6 col-md-6">
17
  <div class="scan-select pl-2 text-nowrap">
18
- <label for="_wcf" class="col-form-label">
19
  <input type="checkbox" class="form-control text-right"
20
- name="wcf" id="_wcf" value="Y"
21
- {% if not scans.wcf.flags.is_available %}disabled="disabled"{% endif %}
22
- {% if scans.wcf.flags.is_selected %}checked="checked" aria-selected="true"{% endif %}
23
  />
24
- {{ scans.wcf.strings.title }}
25
  <br />
26
- <small class="form-text">{{ scans.wcf.strings.subtitle }}</small>
27
  </label>
28
  </div>
29
  </div>
30
 
31
- <div class="col-xl-3 col-lg-6 col-md-6">
32
- <div class="scan-select pl-2 text-nowrap">
33
- <label for="_ufc" class="col-form-label">
34
- <input type="checkbox" class="form-control text-right"
35
- name="ufc" id="_ufc" value="Y"
36
- {% if not scans.ufc.flags.is_available %}disabled="disabled"{% endif %}
37
- {% if scans.ufc.flags.is_selected %}checked="checked" aria-selected="true"{% endif %}
38
- />
39
- {{ scans.ufc.strings.title }}
40
- <br />
41
- <small class="form-text">{{ scans.ufc.strings.subtitle }}</small>
42
- </label>
43
- </div>
44
- </div>
45
-
46
- <div class="col-xl-3 col-lg-6 col-md-6">
47
- <div class="scan-select pl-2 text-nowrap">
48
- <label for="_ptg" class="col-form-label">
49
- <input type="checkbox" class="form-control text-right"
50
- name="ptg" id="_ptg" value="Y"
51
- {% if not scans.ptg.flags.is_available %}disabled="disabled"{% endif %}
52
- {% if scans.ptg.flags.is_selected %}checked="checked" aria-selected="true"{% endif %}
53
- />
54
- {{ scans.ptg.strings.title }}
55
- <br />
56
- <small class="form-text">{{ scans.ptg.strings.subtitle }}</small>
57
- </label>
58
- </div>
59
- </div>
60
-
61
- <div class="col-xl-3 col-lg-6 col-md-6">
62
- <div class="scan-select pl-2 text-nowrap">
63
- <label for="_mal" class="col-form-label">
64
- <input type="checkbox" class="form-control text-right"
65
- name="mal" id="_mal" value="Y"
66
- {% if not scans.mal.flags.is_available %}disabled="disabled"{% endif %}
67
- {% if scans.mal.flags.is_selected %}checked="checked" aria-selected="true"{% endif %}
68
- />
69
- {{ scans.mal.strings.title }}
70
- <br />
71
- <small class="form-text">{{ scans.mal.strings.subtitle }}</small>
72
- </label>
73
- </div>
74
- </div>
75
- </div>
76
-
77
- <div class="row">
78
-
79
- <div class="col-12">
80
- <h6 class="mt-0 mb-2">{{ strings.scanselect_assets }}</h6>
81
- </div>
82
 
83
  <div class="col-xl-3 col-lg-6 col-md-6">
84
  <div class="scan-select pl-2 text-nowrap">
@@ -129,18 +78,6 @@
129
  </div>
130
  </div>
131
 
132
- <div class="col-xl-3 col-lg-6 col-md-6">
133
- <div class="scan-select pl-2 text-nowrap">
134
- <label for="_opt_clear_notification" class="col-form-label">
135
- <input type="checkbox" class="form-control text-right"
136
- name="opt_clear_notification" id="_opt_clear_notification" value="Y" />
137
- {{ strings.clear_suppression }}
138
- <br />
139
- <small class="form-text">{{ strings.clear_suppression_sub }}</small>
140
- </label>
141
- </div>
142
- </div>
143
-
144
  </div>
145
  </div>
146
  <div class="card-footer">
10
 
11
  <div class="row mb-3">
12
  <div class="col-12">
13
+ <h6 class="mt-0 mb-2">{{ strings.scanselect }}</h6>
14
  </div>
15
 
16
  <div class="col-xl-3 col-lg-6 col-md-6">
17
  <div class="scan-select pl-2 text-nowrap">
18
+ <label for="_afs" class="col-form-label">
19
  <input type="checkbox" class="form-control text-right"
20
+ name="afs" id="_afs" value="Y"
21
+ {% if not scans.afs.flags.is_available %}disabled="disabled"{% endif %}
22
+ {% if scans.afs.flags.is_selected %}checked="checked" aria-selected="true"{% endif %}
23
  />
24
+ {{ scans.afs.strings.title }}
25
  <br />
26
+ <small class="form-text">{{ scans.afs.strings.subtitle }}</small>
27
  </label>
28
  </div>
29
  </div>
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  <div class="col-xl-3 col-lg-6 col-md-6">
33
  <div class="scan-select pl-2 text-nowrap">
78
  </div>
79
  </div>
80
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </div>
82
  </div>
83
  <div class="card-footer">