Shield Security for WordPress - Version 15.1.3

Version Description

Download this release

Release Info

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

Code changes from version 15.1.2 to 15.1.3

Files changed (38) hide show
  1. cl.json +18 -0
  2. config/plugin.json +7 -0
  3. icwp-wpsf.php +1 -1
  4. plugin-spec.php +3 -3
  5. plugin.json +3 -3
  6. readme.txt +1 -1
  7. src/lib/src/Blocks/RenderBlockPages/RenderBlockIP.php +2 -3
  8. src/lib/src/Controller/Assets/Paths.php +6 -0
  9. src/lib/src/Controller/Controller.php +11 -6
  10. src/lib/src/Controller/Plugin/PluginDelete.php +4 -1
  11. src/lib/src/Controller/Utilities/Upgrade.php +18 -7
  12. src/lib/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php +15 -5
  13. src/lib/src/Modules/CommentsFilter/ModCon.php +0 -4
  14. src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php +7 -10
  15. src/lib/src/Modules/HackGuard/ModCon.php +1 -4
  16. src/lib/src/Modules/HackGuard/Options.php +1 -1
  17. src/lib/src/Modules/HackGuard/Scan/Controller/Afs.php +1 -1
  18. src/lib/src/Modules/HackGuard/UI.php +1 -1
  19. src/lib/src/Modules/IPs/Lib/AutoUnblock.php +20 -30
  20. src/lib/src/Modules/IPs/Lib/BlockRequest.php +1 -0
  21. src/lib/src/Modules/IPs/Options.php +20 -12
  22. src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php +1 -1
  23. src/lib/src/Modules/LoginGuard/Lib/CooldownFlagFile.php +1 -1
  24. src/lib/src/Modules/Plugin/Lib/Debug/Collate.php +3 -2
  25. src/lib/src/Modules/Plugin/Lib/TestCacheDirWrite.php +3 -0
  26. src/lib/src/Modules/Plugin/ModCon.php +19 -0
  27. src/lib/src/Rules/RulesStorageHandler.php +16 -32
  28. src/lib/src/Scans/Afs/Processing/FileScanOptimiser.php +1 -1
  29. src/lib/src/Utilities/CacheDir.php +4 -0
  30. src/lib/src/Utilities/CacheDirHandler.php +171 -0
  31. src/lib/src/Utilities/HumanSpam/TestContent.php +18 -14
  32. src/lib/src/Utilities/Tool/AssessDirWrite.php +72 -0
  33. src/lib/src/Utilities/Tool/TmpFileStore.php +2 -5
  34. src/lib/vendor/composer/autoload_classmap.php +2 -0
  35. src/lib/vendor/composer/autoload_static.php +2 -0
  36. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php +2 -2
  37. src/lib/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php +15 -0
  38. templates/twig/pages/block/autorecover.twig +66 -15
cl.json CHANGED
@@ -55,6 +55,24 @@
55
  }
56
  ],
57
  "patches": [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  ]
59
  },
60
  "15.0": {
55
  }
56
  ],
57
  "patches": [
58
+ {
59
+ "version": "3",
60
+ "released_at": 1655108600,
61
+ "items": [
62
+ {
63
+ "title": "Yet another complete rewrite of the Shield Cache Dir builder to work around restrictive web hosts.",
64
+ "type": "improved"
65
+ },
66
+ {
67
+ "title": "Restore the event 'Connection Killed' that explicitly states that a request was terminated for a blocked IP.",
68
+ "type": "improved"
69
+ },
70
+ {
71
+ "title": "File diff UI display was broken when comparing modified WordPress Core files with the originals.",
72
+ "type": "fixed"
73
+ }
74
+ ]
75
+ }
76
  ]
77
  },
78
  "15.0": {
config/plugin.json CHANGED
@@ -541,6 +541,13 @@
541
  "type": "array",
542
  "default": []
543
  },
 
 
 
 
 
 
 
544
  {
545
  "key": "ipdetect_at",
546
  "transferable": false,
541
  "type": "array",
542
  "default": []
543
  },
544
+ {
545
+ "key": "last_known_cache_basedirs",
546
+ "transferable": false,
547
+ "section": "section_non_ui",
548
+ "type": "array",
549
+ "default": []
550
+ },
551
  {
552
  "key": "ipdetect_at",
553
  "transferable": false,
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: 15.1.2
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: 15.1.3
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": "15.1.2",
4
- "release_timestamp": 1654596067,
5
- "build": "202206.0701",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
1
  {
2
  "properties": {
3
+ "version": "15.1.3",
4
+ "release_timestamp": 1655108600,
5
+ "build": "202206.1301",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
plugin.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "15.1.2",
4
- "release_timestamp": 1654596067,
5
- "build": "202206.0701",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
1
  {
2
  "properties": {
3
+ "version": "15.1.3",
4
+ "release_timestamp": 1655108600,
5
+ "build": "202206.1301",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "text_domain": "wp-simple-firewall",
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: 6.0
11
- Stable tag: 15.1.2
12
 
13
  Bad Bots Are Your #1 Security Risk. Malware is a symptom of poor security, not the cause. Discover the advantage of powerful security over marketing.
14
 
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 6.0
11
+ Stable tag: 15.1.3
12
 
13
  Bad Bots Are Your #1 Security Risk. Malware is a symptom of poor security, not the cause. Discover the advantage of powerful security over marketing.
14
 
src/lib/src/Blocks/RenderBlockPages/RenderBlockIP.php CHANGED
@@ -45,8 +45,7 @@ class RenderBlockIP extends BaseBlockPage {
45
  $opts = $this->getOptions();
46
 
47
  $ip = Services::IP()->getRequestIp();
48
- $canAutoRecover = $opts->isEnabledAutoVisitorRecover()
49
- && $opts->getCanIpRequestAutoUnblock( $ip );
50
 
51
  $content = '';
52
 
@@ -106,7 +105,7 @@ class RenderBlockIP extends BaseBlockPage {
106
  $user = Services::WpUsers()->getCurrentWpUser();
107
  if ( $user instanceof \WP_User &&
108
  $opts->isEnabledMagicEmailLinkRecover()
109
- && $opts->getCanRequestAutoUnblockEmailLink( $user )
110
  ) {
111
 
112
  if ( apply_filters( $con->prefix( 'can_user_magic_link' ), true ) ) {
45
  $opts = $this->getOptions();
46
 
47
  $ip = Services::IP()->getRequestIp();
48
+ $canAutoRecover = $opts->isEnabledAutoVisitorRecover() && $opts->canIpRequestAutoUnblock( $ip );
 
49
 
50
  $content = '';
51
 
105
  $user = Services::WpUsers()->getCurrentWpUser();
106
  if ( $user instanceof \WP_User &&
107
  $opts->isEnabledMagicEmailLinkRecover()
108
+ && $opts->canRequestAutoUnblockEmailLink( $user )
109
  ) {
110
 
111
  if ( apply_filters( $con->prefix( 'can_user_magic_link' ), true ) ) {
src/lib/src/Controller/Assets/Paths.php CHANGED
@@ -41,6 +41,9 @@ class Paths {
41
  return $this->forPluginItem( $this->getCon()->cfg->paths[ 'templates' ].'/'.ltrim( $item, '/' ) );
42
  }
43
 
 
 
 
44
  public function cacheDir() :string {
45
  $FS = Services::WpFs();
46
  $wpContent = path_join( ABSPATH, 'wp-content' );
@@ -50,6 +53,9 @@ class Paths {
50
  return wp_normalize_path( path_join( $wpContent, $this->getCon()->cfg->paths[ 'cache' ] ) );
51
  }
52
 
 
 
 
53
  public function forCacheItem( string $item = '' ) :string {
54
  return path_join( $this->cacheDir(), $item );
55
  }
41
  return $this->forPluginItem( $this->getCon()->cfg->paths[ 'templates' ].'/'.ltrim( $item, '/' ) );
42
  }
43
 
44
+ /**
45
+ * @deprecated 15.1
46
+ */
47
  public function cacheDir() :string {
48
  $FS = Services::WpFs();
49
  $wpContent = path_join( ABSPATH, 'wp-content' );
53
  return wp_normalize_path( path_join( $wpContent, $this->getCon()->cfg->paths[ 'cache' ] ) );
54
  }
55
 
56
+ /**
57
+ * @deprecated 15.1
58
+ */
59
  public function forCacheItem( string $item = '' ) :string {
60
  return path_join( $this->cacheDir(), $item );
61
  }
src/lib/src/Controller/Controller.php CHANGED
@@ -30,7 +30,7 @@ use FernleafSystems\Wordpress\Services\Utilities\Options\Transient;
30
  * @property bool $plugin_deactivating
31
  * @property bool $plugin_deleting
32
  * @property bool $plugin_reset
33
- * @property Shield\Utilities\CacheDir $cache_dir_handler
34
  * @property bool $user_can_base_permissions
35
  * @property false|string $file_forceoff
36
  * @property string $base_file
@@ -174,8 +174,7 @@ class Controller extends DynPropertiesClass {
174
 
175
  case 'cache_dir_handler':
176
  if ( empty( $val ) ) {
177
- $val = ( new Shield\Utilities\CacheDir() )->setCon( $this );
178
- $this->cache_dir_handler = $val;
179
  }
180
  break;
181
 
@@ -462,10 +461,16 @@ class Controller extends DynPropertiesClass {
462
  do_action( 'shield/plugin_activated' );
463
  }
464
 
 
 
 
465
  public function getPluginCachePath( string $subPath = '' ) :string {
466
- $path = $this->cache_dir_handler->build();
467
- if ( !empty( $path ) && !empty( $subPath ) ) {
468
- $path = path_join( $path, $subPath );
 
 
 
469
  }
470
  return $path;
471
  }
30
  * @property bool $plugin_deactivating
31
  * @property bool $plugin_deleting
32
  * @property bool $plugin_reset
33
+ * @property Shield\Utilities\CacheDirHandler $cache_dir_handler
34
  * @property bool $user_can_base_permissions
35
  * @property false|string $file_forceoff
36
  * @property string $base_file
174
 
175
  case 'cache_dir_handler':
176
  if ( empty( $val ) ) {
177
+ throw new \Exception( 'Accessing Cache Dir Handler too early.' );
 
178
  }
179
  break;
180
 
461
  do_action( 'shield/plugin_activated' );
462
  }
463
 
464
+ /**
465
+ * @deprecated 15.1
466
+ */
467
  public function getPluginCachePath( string $subPath = '' ) :string {
468
+ $handler = $this->cache_dir_handler;
469
+ if ( method_exists( $handler, 'cacheItemPath' ) ) {
470
+ $path = $handler->cacheItemPath( $subPath );
471
+ }
472
+ else {
473
+ $path = path_join( $handler->build(), $subPath );
474
  }
475
  return $path;
476
  }
src/lib/src/Controller/Plugin/PluginDelete.php CHANGED
@@ -18,7 +18,10 @@ class PluginDelete {
18
  }
19
 
20
  private function deleteTmpDir() {
21
- Services::WpFs()->deleteDir( $this->getCon()->getPluginCachePath() );
 
 
 
22
  }
23
 
24
  private function deleteDatabases() {
18
  }
19
 
20
  private function deleteTmpDir() {
21
+ $path = $this->getCon()->cache_dir_handler->dir();
22
+ if ( !empty( $path ) ) {
23
+ Services::WpFs()->deleteDir( $path );
24
+ }
25
  }
26
 
27
  private function deleteDatabases() {
src/lib/src/Controller/Utilities/Upgrade.php CHANGED
@@ -13,13 +13,12 @@ class Upgrade {
13
 
14
  protected function canRun() :bool {
15
  $con = $this->getCon();
16
- return $con->cfg->previous_version !== $con->getVersion()
17
- && !$this->isAlreadyUpgrading();
18
  }
19
 
20
  protected function isAlreadyUpgrading() :bool {
21
  $FS = Services::WpFs();
22
- $upgradeFlag = $this->getCon()->getPluginCachePath( 'upgrading.flag' );
23
  return !empty( $upgradeFlag )
24
  && $FS->isFile( $upgradeFlag )
25
  && ( Services::Request()->ts() - 600 ) < $FS->getModifiedTime( $upgradeFlag );
@@ -27,16 +26,28 @@ class Upgrade {
27
 
28
  protected function run() {
29
  $con = $this->getCon();
 
 
 
 
 
30
 
31
- Services::WpFs()->touch( $con->getPluginCachePath( 'upgrading.flag' ), Services::Request()->ts() );
32
 
33
  $this->upgradeModules();
34
 
35
  $con->cfg->previous_version = $con->getVersion();
36
 
37
- add_action( $con->prefix( 'plugin_shutdown' ), function () {
38
- Services::WpFs()->deleteFile( $this->getCon()->getPluginCachePath( 'upgrading.flag' ) );
39
- } );
 
 
 
 
 
 
 
40
  }
41
 
42
  private function upgradeModules() {
13
 
14
  protected function canRun() :bool {
15
  $con = $this->getCon();
16
+ return ( $con->cfg->previous_version !== $con->getVersion() ) && !$this->isAlreadyUpgrading();
 
17
  }
18
 
19
  protected function isAlreadyUpgrading() :bool {
20
  $FS = Services::WpFs();
21
+ $upgradeFlag = $this->getCon()->cache_dir_handler->cacheItemPath( 'upgrading.flag' );
22
  return !empty( $upgradeFlag )
23
  && $FS->isFile( $upgradeFlag )
24
  && ( Services::Request()->ts() - 600 ) < $FS->getModifiedTime( $upgradeFlag );
26
 
27
  protected function run() {
28
  $con = $this->getCon();
29
+ $FS = Services::WpFs();
30
+
31
+ $filePath = method_exists( $con->cache_dir_handler, 'cacheItemPath' ) ?
32
+ $con->cache_dir_handler->cacheItemPath( 'upgrading.flag' )
33
+ : $con->getPluginCachePath( 'upgrading.flag' );
34
 
35
+ $FS->touch( $filePath, Services::Request()->ts() );
36
 
37
  $this->upgradeModules();
38
 
39
  $con->cfg->previous_version = $con->getVersion();
40
 
41
+ if ( $FS->isFile( $filePath ) ) {
42
+ add_action( $con->prefix( 'plugin_shutdown' ), function () {
43
+ $con = $this->getCon();
44
+ Services::WpFs()->deleteFile(
45
+ method_exists( $con->cache_dir_handler, 'cacheItemPath' ) ?
46
+ $con->cache_dir_handler->cacheItemPath( 'upgrading.flag' )
47
+ : $con->getPluginCachePath( 'upgrading.flag' )
48
+ );
49
+ } );
50
+ }
51
  }
52
 
53
  private function upgradeModules() {
src/lib/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php CHANGED
@@ -9,16 +9,26 @@ class LogFileDirCreate {
9
 
10
  use ModConsumer;
11
 
 
 
 
12
  public function run() :string {
13
  $FS = Services::WpFs();
14
- $baseDir = $this->getCon()->getPluginCachePath();
15
- if ( empty( $baseDir ) ) {
 
 
 
 
 
 
 
16
  throw new \Exception( "Plugin TMP Dir is unavailable." );
17
  }
18
 
19
  $theLogsDir = null;
20
- foreach ( $FS->getAllFilesInDir( $baseDir, true ) as $possibleDir ) {
21
- $possibleFullPath = path_join( $baseDir, $possibleDir );
22
  if ( strpos( basename( $possibleDir ), 'logs-' ) === 0 && $FS->isDir( $possibleDir ) ) {
23
  $theLogsDir = $possibleFullPath;
24
  break;
@@ -26,7 +36,7 @@ class LogFileDirCreate {
26
  }
27
 
28
  if ( empty( $theLogsDir ) ) {
29
- $theLogsDir = path_join( $baseDir, str_replace( '.', '', uniqid( 'logs-', true ) ) );
30
  $FS->mkdir( $theLogsDir );
31
  }
32
 
9
 
10
  use ModConsumer;
11
 
12
+ /**
13
+ * @throws \Exception
14
+ */
15
  public function run() :string {
16
  $FS = Services::WpFs();
17
+
18
+ $handler = $this->getCon()->cache_dir_handler;
19
+ if ( method_exists( $handler, 'dir' ) ) {
20
+ $cacheDir = $handler->dir();
21
+ }
22
+ else {
23
+ $cacheDir = $this->getCon()->getPluginCachePath();
24
+ }
25
+ if ( empty( $cacheDir ) ) {
26
  throw new \Exception( "Plugin TMP Dir is unavailable." );
27
  }
28
 
29
  $theLogsDir = null;
30
+ foreach ( $FS->getAllFilesInDir( $cacheDir, true ) as $possibleDir ) {
31
+ $possibleFullPath = path_join( $cacheDir, $possibleDir );
32
  if ( strpos( basename( $possibleDir ), 'logs-' ) === 0 && $FS->isDir( $possibleDir ) ) {
33
  $theLogsDir = $possibleFullPath;
34
  break;
36
  }
37
 
38
  if ( empty( $theLogsDir ) ) {
39
+ $theLogsDir = path_join( $cacheDir, str_replace( '.', '', uniqid( 'logs-', true ) ) );
40
  $FS->mkdir( $theLogsDir );
41
  }
42
 
src/lib/src/Modules/CommentsFilter/ModCon.php CHANGED
@@ -20,8 +20,4 @@ class ModCon extends BaseShield\ModCon {
20
  ) ) )
21
  );
22
  }
23
-
24
- public function getSpamBlacklistFile() :string {
25
- return $this->getCon()->paths->forCacheItem( 'spamblacklist.txt' );
26
- }
27
  }
20
  ) ) )
21
  );
22
  }
 
 
 
 
23
  }
src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php CHANGED
@@ -121,36 +121,33 @@ class ScanItemView {
121
  throw new \Exception( 'Diff is unavailable for missing files.' );
122
  }
123
 
124
- $original = '';
125
  $coreHashes = Services::CoreFileHashes();
126
  if ( $coreHashes->isCoreFile( $pathFull ) ) {
127
- $original = ( new WpOrg\Wp\Files() )->getOriginalFileFromVcs( $pathFull );
128
  }
129
  else {
130
  $plugin = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $pathFull );
131
  if ( !empty( $plugin ) && $plugin->isWpOrg() && $plugin->svn_uses_tags ) {
132
  $originalFileDownload = ( new WpOrg\Plugin\Files() )->getOriginalFileFromVcs( $pathFull );
133
- if ( !empty( $originalFileDownload ) ) {
134
- $original = Services::WpFs()->getFileContent( $originalFileDownload );
135
- }
136
  }
137
  else {
138
  $theme = ( new WpOrg\Theme\Files() )->findThemeFromFile( $pathFull );
139
  if ( !empty( $theme ) && $theme->isWpOrg() ) {
140
  $originalFileDownload = ( new WpOrg\Theme\Files() )->getOriginalFileFromVcs( $pathFull );
141
- if ( !empty( $originalFileDownload ) ) {
142
- $original = Services::WpFs()->getFileContent( $originalFileDownload );
143
- }
144
  }
145
  }
146
  }
147
 
148
- if ( empty( $original ) ) {
 
149
  throw new \Exception( 'There is no original file available to create a diff.' );
150
  }
151
 
152
  $conv = new ConvertLineEndings();
153
- $res = ( new Diff() )->getDiff( $conv->dosToLinux( $original ), $conv->fileDosToLinux( $pathFull ) );
 
 
 
154
 
155
  if ( !is_array( $res ) || empty( $res[ 'html' ] ) ) {
156
  throw new \Exception( 'Could not get a valid diff for this file.' );
121
  throw new \Exception( 'Diff is unavailable for missing files.' );
122
  }
123
 
 
124
  $coreHashes = Services::CoreFileHashes();
125
  if ( $coreHashes->isCoreFile( $pathFull ) ) {
126
+ $originalFileDownload = ( new WpOrg\Wp\Files() )->getOriginalFileFromVcs( $pathFull );
127
  }
128
  else {
129
  $plugin = ( new WpOrg\Plugin\Files() )->findPluginFromFile( $pathFull );
130
  if ( !empty( $plugin ) && $plugin->isWpOrg() && $plugin->svn_uses_tags ) {
131
  $originalFileDownload = ( new WpOrg\Plugin\Files() )->getOriginalFileFromVcs( $pathFull );
 
 
 
132
  }
133
  else {
134
  $theme = ( new WpOrg\Theme\Files() )->findThemeFromFile( $pathFull );
135
  if ( !empty( $theme ) && $theme->isWpOrg() ) {
136
  $originalFileDownload = ( new WpOrg\Theme\Files() )->getOriginalFileFromVcs( $pathFull );
 
 
 
137
  }
138
  }
139
  }
140
 
141
+ $FS = Services::WpFs();
142
+ if ( empty( $originalFileDownload ) || !$FS->isFile($originalFileDownload)) {
143
  throw new \Exception( 'There is no original file available to create a diff.' );
144
  }
145
 
146
  $conv = new ConvertLineEndings();
147
+ $res = ( new Diff() )->getDiff(
148
+ $conv->dosToLinux( (string)$FS->getFileContent( $originalFileDownload ) ),
149
+ $conv->fileDosToLinux( $pathFull )
150
+ );
151
 
152
  if ( !is_array( $res ) || empty( $res[ 'html' ] ) ) {
153
  throw new \Exception( 'Could not get a valid diff for this file.' );
src/lib/src/Modules/HackGuard/ModCon.php CHANGED
@@ -5,7 +5,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
8
- use FernleafSystems\Wordpress\Plugin\Shield\Utilities\CacheDir;
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
  class ModCon extends BaseShield\ModCon {
@@ -187,9 +186,7 @@ class ModCon extends BaseShield\ModCon {
187
  }
188
 
189
  public function getScansTempDir() :string {
190
- return ( new CacheDir() )
191
- ->setCon( $this->getCon() )
192
- ->buildSubDir( 'scans' );
193
  }
194
 
195
  public function getDbHandler_FileLocker() :Databases\FileLocker\Handler {
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
 
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class ModCon extends BaseShield\ModCon {
186
  }
187
 
188
  public function getScansTempDir() :string {
189
+ return $this->getCon()->cache_dir_handler->buildSubDir( 'scans' );
 
 
190
  }
191
 
192
  public function getDbHandler_FileLocker() :Databases\FileLocker\Handler {
src/lib/src/Modules/HackGuard/Options.php CHANGED
@@ -69,7 +69,7 @@ class Options extends BaseShield\Options {
69
  */
70
  private function getMalSignatures( string $fileName, string $url ) :array {
71
  $FS = Services::WpFs();
72
- $file = $this->getCon()->paths->forCacheItem( $fileName );
73
  if ( !empty( $file ) && $FS->exists( $file ) ) {
74
  $sigs = explode( "\n", $FS->getFileContent( $file, true ) );
75
  }
69
  */
70
  private function getMalSignatures( string $fileName, string $url ) :array {
71
  $FS = Services::WpFs();
72
+ $file = $this->getCon()->cache_dir_handler->cacheItemPath( $fileName );
73
  if ( !empty( $file ) && $FS->exists( $file ) ) {
74
  $sigs = explode( "\n", $FS->getFileContent( $file, true ) );
75
  }
src/lib/src/Modules/HackGuard/Scan/Controller/Afs.php CHANGED
@@ -216,7 +216,7 @@ class Afs extends BaseForFiles {
216
 
217
  public function isEnabledPluginThemeScan() :bool {
218
  return $this->isEnabled() && !$this->isRestrictedPluginThemeScan()
219
- && $this->getCon()->cache_dir_handler->dirExists();
220
  }
221
 
222
  public function isRestrictedMalwareScan() :bool {
216
 
217
  public function isEnabledPluginThemeScan() :bool {
218
  return $this->isEnabled() && !$this->isRestrictedPluginThemeScan()
219
+ && $this->getCon()->cache_dir_handler->exists();
220
  }
221
 
222
  public function isRestrictedMalwareScan() :bool {
src/lib/src/Modules/HackGuard/UI.php CHANGED
@@ -233,7 +233,7 @@ class UI extends BaseShield\UI {
233
  switch ( $section ) {
234
 
235
  case 'section_file_guard':
236
- if ( !$this->getCon()->cache_dir_handler->dirExists() ) {
237
  $warnings[] = __( "Plugin/Theme file scanners are unavailable because we couldn't create a temporary directory to store files.", 'wp-simple-firewall' );
238
  }
239
 
233
  switch ( $section ) {
234
 
235
  case 'section_file_guard':
236
+ if ( !$this->getCon()->cache_dir_handler->exists() ) {
237
  $warnings[] = __( "Plugin/Theme file scanners are unavailable because we couldn't create a temporary directory to store files.", 'wp-simple-firewall' );
238
  }
239
 
src/lib/src/Modules/IPs/Lib/AutoUnblock.php CHANGED
@@ -58,27 +58,23 @@ class AutoUnblock extends ExecOnceModConsumer {
58
  && $req->post( 'action' ) == $mod->getCon()->prefix()
59
  && $req->post( 'exec' ) == 'uau-'.$ip ) {
60
 
61
- if ( check_admin_referer( 'uau-'.$ip, 'exec_nonce' ) !== 1 ) {
62
- throw new \Exception( 'Nonce failed' );
63
- }
64
- if ( strlen( (string)$req->post( 'icwp_wpsf_login_email' ) ) > 0 ) {
65
- throw new \Exception( 'Email should not be provided in honeypot' );
66
- }
67
-
68
- if ( !$opts->getCanIpRequestAutoUnblock( $ip ) ) {
69
  throw new \Exception( 'IP already processed in the last 1hr' );
70
  }
71
 
72
- {
73
- $existing = $opts->getAutoUnblockIps();
74
- $existing[ $ip ] = Services::Request()->ts();
75
- $opts->setOpt( 'autounblock_ips',
76
- array_filter( $existing, function ( $ts ) {
77
- return Services::Request()
78
- ->carbon()
79
- ->subHours( 1 )->timestamp < $ts;
80
- } )
81
- );
 
 
 
82
  }
83
 
84
  ( new IPs\Lib\Ops\DeleteIp() )
@@ -131,22 +127,16 @@ class AutoUnblock extends ExecOnceModConsumer {
131
  }
132
 
133
  if ( $linkParts[ 1 ] === 'init' ) {
134
- if ( !$opts->getCanRequestAutoUnblockEmailLink( $user ) ) {
135
  throw new \Exception( 'User already processed recently.' );
136
  }
137
 
 
 
 
 
138
  $this->sendMagicLinkEmail();
139
- {
140
- $existing = $opts->getAutoUnblockEmailIDs();
141
- $existing[ $user->ID ] = Services::Request()->ts();
142
- $opts->setOpt( 'autounblock_emailids',
143
- array_filter( $existing, function ( $ts ) {
144
- return Services::Request()
145
- ->carbon()
146
- ->subHours( 1 )->timestamp < $ts;
147
- } )
148
- );
149
- }
150
  http_response_code( 200 );
151
  die();
152
  }
58
  && $req->post( 'action' ) == $mod->getCon()->prefix()
59
  && $req->post( 'exec' ) == 'uau-'.$ip ) {
60
 
61
+ if ( !$opts->canIpRequestAutoUnblock( $ip ) ) {
 
 
 
 
 
 
 
62
  throw new \Exception( 'IP already processed in the last 1hr' );
63
  }
64
 
65
+ // mark IP as having used up it's autounblock option.
66
+ $existing = $opts->getAutoUnblockIps();
67
+ $existing[ $ip ] = Services::Request()->ts();
68
+ $opts->setOpt( 'autounblock_ips', $existing );
69
+
70
+ if ( $req->post( '_confirm' ) !== 'Y' ) {
71
+ throw new \Exception( 'No confirmation checkbox.' );
72
+ }
73
+ if ( !empty( $req->post( 'email' ) ) || !empty( $req->post( 'name' ) ) ) {
74
+ throw new \Exception( 'Oh so yummy honey.' );
75
+ }
76
+ if ( wp_verify_nonce( $req->post( 'exec_nonce' ), 'uau-'.$ip ) !== 1 ) {
77
+ throw new \Exception( 'Nonce failed' );
78
  }
79
 
80
  ( new IPs\Lib\Ops\DeleteIp() )
127
  }
128
 
129
  if ( $linkParts[ 1 ] === 'init' ) {
130
+ if ( !$opts->canRequestAutoUnblockEmailLink( $user ) ) {
131
  throw new \Exception( 'User already processed recently.' );
132
  }
133
 
134
+ $existing = $opts->getAutoUnblockEmailIDs();
135
+ $existing[ $user->ID ] = Services::Request()->ts();
136
+ $opts->setOpt( 'autounblock_emailids', $existing );
137
+
138
  $this->sendMagicLinkEmail();
139
+
 
 
 
 
 
 
 
 
 
 
140
  http_response_code( 200 );
141
  die();
142
  }
src/lib/src/Modules/IPs/Lib/BlockRequest.php CHANGED
@@ -13,6 +13,7 @@ class BlockRequest extends ExecOnceModConsumer {
13
  }
14
 
15
  protected function run() {
 
16
  ( new RenderBlockIP() )
17
  ->setMod( $this->getMod() )
18
  ->display();
13
  }
14
 
15
  protected function run() {
16
+ $this->getCon()->fireEvent( 'conn_kill' );
17
  ( new RenderBlockIP() )
18
  ->setMod( $this->getMod() )
19
  ->display();
src/lib/src/Modules/IPs/Options.php CHANGED
@@ -16,25 +16,33 @@ class Options extends BaseShield\Options {
16
  }
17
 
18
  public function getAutoUnblockIps() :array {
19
- $ips = $this->getOpt( 'autounblock_ips', [] );
20
- return is_array( $ips ) ? $ips : [];
 
 
 
 
 
 
21
  }
22
 
23
  public function getAutoUnblockEmailIDs() :array {
24
- $ips = $this->getOpt( 'autounblock_emailids', [] );
25
- return is_array( $ips ) ? $ips : [];
 
 
 
 
 
 
26
  }
27
 
28
- public function getCanIpRequestAutoUnblock( string $ip ) :bool {
29
- $existing = $this->getAutoUnblockIps();
30
- return !array_key_exists( $ip, $existing )
31
- || ( Services::Request()->carbon()->subHours( 1 )->timestamp > $existing[ $ip ] );
32
  }
33
 
34
- public function getCanRequestAutoUnblockEmailLink( \WP_User $user ) :bool {
35
- $existing = $this->getAutoUnblockEmailIDs();
36
- return !array_key_exists( $user->ID, $existing )
37
- || ( Services::Request()->carbon()->subHours( 1 )->timestamp > $existing[ $user->ID ] );
38
  }
39
 
40
  public function getOffenseLimit() :int {
16
  }
17
 
18
  public function getAutoUnblockIps() :array {
19
+ $ips = is_array( $this->getOpt( 'autounblock_ips', [] ) ) ? $this->getOpt( 'autounblock_ips', [] ) : [];
20
+ $ips = array_filter( $ips, function ( $ts ) {
21
+ return Services::Request()
22
+ ->carbon()
23
+ ->subHours( 1 )->timestamp < $ts;
24
+ } );
25
+ $this->setOpt( 'autounblock_ips', $ips );
26
+ return $ips;
27
  }
28
 
29
  public function getAutoUnblockEmailIDs() :array {
30
+ $ids = is_array( $this->getOpt( 'autounblock_emailids', [] ) ) ? $this->getOpt( 'autounblock_emailids', [] ) : [];
31
+ $ids = array_filter( $ids, function ( $ts ) {
32
+ return Services::Request()
33
+ ->carbon()
34
+ ->subHours( 1 )->timestamp < $ts;
35
+ } );
36
+ $this->setOpt( 'autounblock_emailids', $ids );
37
+ return $ids;
38
  }
39
 
40
+ public function canIpRequestAutoUnblock( string $ip ) :bool {
41
+ return !array_key_exists( $ip, $this->getAutoUnblockIps() );
 
 
42
  }
43
 
44
+ public function canRequestAutoUnblockEmailLink( \WP_User $user ) :bool {
45
+ return !array_key_exists( $user->ID, $this->getAutoUnblockEmailIDs() );
 
 
46
  }
47
 
48
  public function getOffenseLimit() :int {
src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php CHANGED
@@ -21,7 +21,7 @@ class AntibotSetup extends ExecOnceModConsumer {
21
  $opts = $this->getOptions();
22
 
23
  $providers = [];
24
- if ( $opts->isEnabledCooldown() && $this->getCon()->cache_dir_handler->dirExists() ) {
25
  $providers[] = ( new AntiBot\ProtectionProviders\CoolDown() )
26
  ->setMod( $mod );
27
  }
21
  $opts = $this->getOptions();
22
 
23
  $providers = [];
24
+ if ( $opts->isEnabledCooldown() && $this->getCon()->cache_dir_handler->exists() ) {
25
  $providers[] = ( new AntiBot\ProtectionProviders\CoolDown() )
26
  ->setMod( $mod );
27
  }
src/lib/src/Modules/LoginGuard/Lib/CooldownFlagFile.php CHANGED
@@ -20,7 +20,7 @@ class CooldownFlagFile {
20
  }
21
 
22
  public function getFlagFilePath() :string {
23
- return $this->getCon()->paths->forCacheItem( 'mode.login_throttled' );
24
  }
25
 
26
  public function getSecondsSinceLastLogin() :int {
20
  }
21
 
22
  public function getFlagFilePath() :string {
23
+ return $this->getCon()->cache_dir_handler->cacheItemPath( 'mode.login_throttled' );
24
  }
25
 
26
  public function getSecondsSinceLastLogin() :int {
src/lib/src/Modules/Plugin/Lib/Debug/Collate.php CHANGED
@@ -220,7 +220,7 @@ class Collate {
220
 
221
  $data[ 'Ping License Server' ] = ( new Licenses\Keyless\Ping() )->ping() ? 'Yes' : 'No';
222
 
223
- $data[ 'Write TMP/Cache DIR' ] = $con->cache_dir_handler->dirExists() ? 'Yes: '.$con->getPluginCachePath() : 'No';
224
 
225
  return $data;
226
  }
@@ -254,7 +254,8 @@ class Collate {
254
  /** @var Options $oOptsIP */
255
  $optsPlugin = $modPlugin->getOptions();
256
  $source = $optsPlugin->getSelectOptionValueText( 'visitor_address_source' );
257
- $data[ 'Visitor IP Source' ] = $source.': '.var_export( Services::IP()->getRequestIp(), true );
 
258
 
259
  return $data;
260
  }
220
 
221
  $data[ 'Ping License Server' ] = ( new Licenses\Keyless\Ping() )->ping() ? 'Yes' : 'No';
222
 
223
+ $data[ 'Write TMP/Cache DIR' ] = $con->cache_dir_handler->exists() ? 'Yes: '.$con->cache_dir_handler->dir() : 'No';
224
 
225
  return $data;
226
  }
254
  /** @var Options $oOptsIP */
255
  $optsPlugin = $modPlugin->getOptions();
256
  $source = $optsPlugin->getSelectOptionValueText( 'visitor_address_source' );
257
+ $ip = Services::IP()->getRequestIp();
258
+ $data[ 'Visitor IP Source' ] = $source.': '.( empty( $ip ) ? 'n/a' : $ip );
259
 
260
  return $data;
261
  }
src/lib/src/Modules/Plugin/Lib/TestCacheDirWrite.php CHANGED
@@ -5,6 +5,9 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib;
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
 
 
 
8
  class TestCacheDirWrite {
9
 
10
  use ModConsumer;
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
  use FernleafSystems\Wordpress\Services\Services;
7
 
8
+ /**
9
+ * @deprecated 15.1
10
+ */
11
  class TestCacheDirWrite {
12
 
13
  use ModConsumer;
src/lib/src/Modules/Plugin/ModCon.php CHANGED
@@ -57,6 +57,25 @@ class ModCon extends BaseShield\ModCon {
57
 
58
  protected function doPostConstruction() {
59
  $this->setVisitorIpSource();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  }
61
 
62
  protected function enumRuleBuilders() :array {
57
 
58
  protected function doPostConstruction() {
59
  $this->setVisitorIpSource();
60
+ $this->setupCacheDir();
61
+ }
62
+
63
+ protected function setupCacheDir() {
64
+ $opts = $this->getOptions();
65
+ $url = Services::WpGeneral()->getWpUrl();
66
+ $lastKnownDirs = $opts->getOpt( 'last_known_cache_basedirs' );
67
+ if ( empty( $lastKnownDirs ) || !is_array( $lastKnownDirs ) ) {
68
+ $lastKnownDirs = [
69
+ $url => ''
70
+ ];
71
+ }
72
+
73
+ $cacheDirFinder = ( new Shield\Utilities\CacheDirHandler( $lastKnownDirs[ $url ] ?? '' ) )->setCon( $this->getCon() );
74
+ $workableDir = $cacheDirFinder->dir();
75
+ $lastKnownDirs[ $url ] = empty( $workableDir ) ? '' : dirname( $workableDir );
76
+
77
+ $opts->setOpt( 'last_known_cache_basedirs', $lastKnownDirs );
78
+ $this->getCon()->cache_dir_handler = $cacheDirFinder;
79
  }
80
 
81
  protected function enumRuleBuilders() :array {
src/lib/src/Rules/RulesStorageHandler.php CHANGED
@@ -16,10 +16,6 @@ class RulesStorageHandler {
16
  public function loadRules( bool $attemptRebuild = true ) :array {
17
 
18
  $rules = $this->loadRawFromWP();
19
- if ( empty( $rules ) ) {
20
- $rules = $this->loadRawFromFile();
21
- }
22
-
23
  if ( $attemptRebuild && ( empty( $rules ) || empty( $rules[ 'rules' ] ) ) ) {
24
  $this->buildAndStore();
25
  $rules = $this->loadRules( false );
@@ -46,20 +42,15 @@ class RulesStorageHandler {
46
  ->run();
47
  }
48
 
49
- public function store( array $rules ) :bool {
50
  $WP = Services::WpGeneral();
51
- $req = Services::Request();
52
-
53
- $data = [
54
- 'ts' => $req->ts(),
55
- 'time' => $WP->getTimeStampForDisplay( $req->ts() ),
56
  'rules' => array_map( function ( RuleVO $rule ) {
57
  return $rule->getRawData();
58
  }, $rules ),
59
- ];
60
-
61
- $WP->updateOption( $this->getWpStorageKey(), $data );
62
- return Services::WpFs()->putFileContent( $this->getPathToRules(), wp_json_encode( $data ) );
63
  }
64
 
65
  private function loadRawFromWP() :array {
@@ -67,28 +58,21 @@ class RulesStorageHandler {
67
  return is_array( $raw ) ? $raw : [];
68
  }
69
 
70
- private function loadRawFromFile() :array {
71
- $rules = [];
72
-
73
- $FS = Services::WpFs();
74
- if ( $FS->exists( $this->getPathToRules() ) ) {
75
- $content = $FS->getFileContent( $this->getPathToRules() );
76
- if ( !empty( $content ) ) {
77
- $decoded = @json_decode( $content, true );
78
- if ( is_array( $decoded ) ) {
79
- $rules = $decoded;
80
- }
81
- }
82
- }
83
 
84
- return $rules;
 
 
 
 
85
  }
86
 
 
 
 
87
  private function getPathToRules() :string {
88
  return path_join( $this->getRulesCon()->getCon()->cache_dir_handler->build(), 'rules.json' );
89
  }
90
-
91
- private function getWpStorageKey() :string {
92
- return $this->getRulesCon()->getCon()->prefix( 'rules' );
93
- }
94
  }
16
  public function loadRules( bool $attemptRebuild = true ) :array {
17
 
18
  $rules = $this->loadRawFromWP();
 
 
 
 
19
  if ( $attemptRebuild && ( empty( $rules ) || empty( $rules[ 'rules' ] ) ) ) {
20
  $this->buildAndStore();
21
  $rules = $this->loadRules( false );
42
  ->run();
43
  }
44
 
45
+ public function store( array $rules ) {
46
  $WP = Services::WpGeneral();
47
+ $WP->updateOption( $this->getWpStorageKey(), [
48
+ 'ts' => Services::Request()->ts(),
49
+ 'time' => $WP->getTimeStampForDisplay( Services::Request()->ts() ),
 
 
50
  'rules' => array_map( function ( RuleVO $rule ) {
51
  return $rule->getRawData();
52
  }, $rules ),
53
+ ] );
 
 
 
54
  }
55
 
56
  private function loadRawFromWP() :array {
58
  return is_array( $raw ) ? $raw : [];
59
  }
60
 
61
+ private function getWpStorageKey() :string {
62
+ return $this->getRulesCon()->getCon()->prefix( 'rules' );
63
+ }
 
 
 
 
 
 
 
 
 
 
64
 
65
+ /**
66
+ * @deprecated 15.1
67
+ */
68
+ private function loadRawFromFile() :array {
69
+ return [];
70
  }
71
 
72
+ /**
73
+ * @deprecated 15.1
74
+ */
75
  private function getPathToRules() :string {
76
  return path_join( $this->getRulesCon()->getCon()->cache_dir_handler->build(), 'rules.json' );
77
  }
 
 
 
 
78
  }
src/lib/src/Scans/Afs/Processing/FileScanOptimiser.php CHANGED
@@ -146,6 +146,6 @@ class FileScanOptimiser {
146
  }
147
 
148
  public function pathToHashes() :string {
149
- return path_join( $this->getCon()->cache_dir_handler->build(), 'file_scan_hashes.txt' );
150
  }
151
  }
146
  }
147
 
148
  public function pathToHashes() :string {
149
+ return path_join( $this->getCon()->cache_dir_handler->dir(), 'file_scan_hashes.txt' );
150
  }
151
  }
src/lib/src/Utilities/CacheDir.php CHANGED
@@ -6,6 +6,9 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib\TestCacheDirWrite
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
 
 
 
9
  class CacheDir {
10
 
11
  use PluginControllerConsumer;
@@ -30,6 +33,7 @@ class CacheDir {
30
  $this->cacheDir = $maybeDir;
31
  }
32
  catch ( \Exception $e ) {
 
33
  }
34
  }
35
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
+ /**
10
+ * @deprecated 15.1
11
+ */
12
  class CacheDir {
13
 
14
  use PluginControllerConsumer;
33
  $this->cacheDir = $maybeDir;
34
  }
35
  catch ( \Exception $e ) {
36
+ /* error_log( sprintf( 'Exception making the cache dir: %s; Exception: %s', $maybeDir ?? 'emptydir', $e->getMessage() ) ); */
37
  }
38
  }
39
 
src/lib/src/Utilities/CacheDirHandler.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Utilities;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool\AssessDirWrite;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class CacheDirHandler {
10
+
11
+ use PluginControllerConsumer;
12
+
13
+ private $cacheDir;
14
+
15
+ private $lastKnownBaseDir;
16
+
17
+ public function __construct( string $lastKnownBaseDir = '' ) {
18
+ $this->lastKnownBaseDir = $lastKnownBaseDir;
19
+ }
20
+
21
+ public function exists() :bool {
22
+ $dir = $this->dir();
23
+ return !empty( $dir ) && Services::WpFs()->isDir( $dir );
24
+ }
25
+
26
+ public function findWorkableDir( bool $retest = false ) :string {
27
+ $FS = Services::WpFs();
28
+
29
+ if ( !isset( $this->cacheDir ) || $retest ) {
30
+
31
+ $this->cacheDir = '';
32
+ foreach ( $this->getBaseDirCandidates() as $baseDir ) {
33
+ $maybeDir = path_join( $baseDir, $this->getCon()->cfg->paths[ 'cache' ] );
34
+ try {
35
+ if ( $maybeDir === '/' ) {
36
+ throw new \Exception( 'Should never have the root as the cache dir.' ); // just to be ultra safe.
37
+ }
38
+ if ( !$FS->mkdir( $maybeDir ) || !$FS->isDir( $maybeDir ) ) {
39
+ throw new \Exception( sprintf( 'Failed to mkdir cache dir: %s', $maybeDir ) );
40
+ }
41
+
42
+ $assessedFlag = path_join( $maybeDir, 'assessed.flag' );
43
+ if ( !$FS->isFile( $assessedFlag )
44
+ || Services::Request()->ts() - $FS->getModifiedTime( $assessedFlag ) > HOUR_IN_SECONDS ) {
45
+
46
+ $assess = ( new AssessDirWrite( $maybeDir ) )->test();
47
+ if ( count( array_filter( $assess ) ) !== 3 ) {
48
+ throw new \Exception( sprintf( 'Failed writeable assessment for cache dir: "%s"; Results: %s ',
49
+ $maybeDir, var_export( $assess, true ) ) );
50
+ }
51
+
52
+ if ( $maybeDir !== '/tmp' ) {
53
+ $this->addProtections( $maybeDir );
54
+ }
55
+
56
+ $FS->touch( path_join( $maybeDir, 'assessed.flag' ) );
57
+ }
58
+
59
+ $this->cacheDir = $maybeDir;
60
+ break;
61
+ }
62
+ catch ( \Exception $e ) {
63
+ }
64
+ }
65
+ }
66
+
67
+ return $this->cacheDir;
68
+ }
69
+
70
+ public function dir() :string {
71
+ return $this->findWorkableDir();
72
+ }
73
+
74
+ public function buildSubDir( string $subDir ) :string {
75
+ $finalDir = '';
76
+ if ( $this->exists() ) {
77
+ $finalDir = path_join( $this->dir(), $subDir );
78
+ if ( !Services::WpFs()->mkdir( $finalDir ) ) {
79
+ $finalDir = '';
80
+ }
81
+ }
82
+ return $finalDir;
83
+ }
84
+
85
+ public function cacheItemPath( string $itemPath ) :string {
86
+ $rootDir = $this->dir();
87
+ if ( empty( $rootDir ) ) {
88
+ $path = '';
89
+ }
90
+ elseif ( empty( $itemPath ) ) {
91
+ $path = $rootDir;
92
+ }
93
+ else {
94
+ $path = path_join( $rootDir, $itemPath );
95
+ }
96
+ return $path;
97
+ }
98
+
99
+ /**
100
+ * @throws \Exception
101
+ */
102
+ private function addProtections( string $cacheDir ) :bool {
103
+ $FS = Services::WpFs();
104
+
105
+ $htFile = path_join( $cacheDir, '.htaccess' );
106
+ $htContent = implode( "\n", [
107
+ "# BEGIN SHIELD",
108
+ "Options -Indexes",
109
+ "Order allow,deny",
110
+ "Deny from all",
111
+ '<FilesMatch "^.*\.(css|js)$">',
112
+ " Allow from all",
113
+ '</FilesMatch>',
114
+ "# END SHIELD"
115
+ ] );
116
+ if ( !$FS->exists( $htFile ) || ( md5_file( $htFile ) !== md5( $htContent ) ) ) {
117
+ $FS->putFileContent( $htFile, $htContent );
118
+ }
119
+ $index = path_join( $cacheDir, 'index.php' );
120
+ $indexContent = "<?php\nhttp_response_code(404);";
121
+ if ( !$FS->exists( $index ) || ( md5_file( $index ) !== md5( $indexContent ) ) ) {
122
+ $FS->putFileContent( $index, $indexContent );
123
+ }
124
+
125
+ $FS->putFileContent( path_join( $cacheDir, 'README.txt' ),
126
+ "This is a temporary caching folder used by the Shield Security plugin. You can safely delete it, but it'll be recreated if required.\n" );
127
+
128
+ return true;
129
+ }
130
+
131
+ private function getBaseDirCandidates() :array {
132
+ $candidates = [
133
+ WP_CONTENT_DIR,
134
+ path_join( ABSPATH, 'wp-content' ),
135
+ path_join( WP_CONTENT_DIR, 'tmp' ),
136
+ path_join( WP_CONTENT_DIR, 'cache' ),
137
+ path_join( WP_CONTENT_DIR, 'uploads' ),
138
+ '/tmp'
139
+ ];
140
+
141
+ if ( !empty( $this->lastKnownBaseDir ) ) {
142
+ array_unshift( $candidates, $this->lastKnownBaseDir );
143
+ }
144
+
145
+ return array_filter(
146
+ array_unique( array_map(
147
+ function ( $path ) {
148
+ return wp_normalize_path( $path );
149
+ },
150
+ $candidates
151
+ ) ),
152
+ function ( $path ) {
153
+ return Services::WpFs()->isDir( $path ) && wp_is_writable( $path );
154
+ }
155
+ );
156
+ }
157
+
158
+ /**
159
+ * @deprecated 15.1
160
+ */
161
+ public function dirExists() :bool {
162
+ return $this->exists();
163
+ }
164
+
165
+ /**
166
+ * @deprecated 15.1
167
+ */
168
+ public function build() :string {
169
+ return $this->dir();
170
+ }
171
+ }
src/lib/src/Utilities/HumanSpam/TestContent.php CHANGED
@@ -20,9 +20,8 @@ class TestContent {
20
  public function findSpam( array $itemsToTest, bool $finishAfterFirst = true ) :array {
21
  $spamFound = [];
22
 
23
- $itemsToTest = array_map( 'strval', array_filter( $itemsToTest ) );
24
  foreach ( $this->getSpamList() as $word ) {
25
- foreach ( $itemsToTest as $key => $item ) {
26
  if ( stripos( $item, $word ) !== false ) {
27
 
28
  if ( !isset( $spamFound[ $word ] ) ) {
@@ -41,33 +40,38 @@ class TestContent {
41
  }
42
 
43
  private function getSpamList() :array {
44
- if ( empty( $this->list ) ) {
45
  $FS = Services::WpFs();
46
  $file = $this->getFile();
47
- if ( !$FS->exists( $file )
48
- || Services::Request()->ts() - $FS->getModifiedTime( $file ) > MONTH_IN_SECONDS ) {
49
- $this->importBlacklist();
 
 
 
 
50
  }
51
- $this->list = array_map( 'base64_decode', explode( "\n", $FS->getFileContent( $file, true ) ) );
52
  }
53
  return $this->list;
54
  }
55
 
56
- private function importBlacklist() :bool {
57
- $success = false;
58
  $mod = $this->getCon()->getModule_Comments();
59
  $rawList = Services::HttpRequest()->getContent( $mod->getOptions()->getDef( 'url_spam_blacklist_terms' ) );
60
- if ( !empty( $rawList ) && !empty( $this->getFile() ) ) {
61
- $success = Services::WpFs()->putFileContent(
 
 
 
 
62
  $this->getFile(),
63
- implode( "\n", array_map( 'base64_encode', array_filter( array_map( 'trim', explode( "\n", $rawList ) ) ) ) ),
64
  true
65
  );
66
  }
67
- return $success;
68
  }
69
 
70
  private function getFile() :string {
71
- return $this->getCon()->paths->forCacheItem( 'spamblacklist.txt' );
72
  }
73
  }
20
  public function findSpam( array $itemsToTest, bool $finishAfterFirst = true ) :array {
21
  $spamFound = [];
22
 
 
23
  foreach ( $this->getSpamList() as $word ) {
24
+ foreach ( array_map( 'strval', array_filter( $itemsToTest ) ) as $key => $item ) {
25
  if ( stripos( $item, $word ) !== false ) {
26
 
27
  if ( !isset( $spamFound[ $word ] ) ) {
40
  }
41
 
42
  private function getSpamList() :array {
43
+ if ( !is_array( $this->list ) ) {
44
  $FS = Services::WpFs();
45
  $file = $this->getFile();
46
+ if ( $FS->exists( $file )
47
+ && Services::Request()->ts() - $FS->getModifiedTime( $file ) < MONTH_IN_SECONDS ) {
48
+ $this->list = array_map( 'base64_decode', explode( "\n", (string)$FS->getFileContent( $file, true ) ) );
49
+ }
50
+ else {
51
+ $this->list = $this->downloadBlacklist();
52
+ $this->storeList( $this->list );
53
  }
 
54
  }
55
  return $this->list;
56
  }
57
 
58
+ private function downloadBlacklist() :array {
 
59
  $mod = $this->getCon()->getModule_Comments();
60
  $rawList = Services::HttpRequest()->getContent( $mod->getOptions()->getDef( 'url_spam_blacklist_terms' ) );
61
+ return array_filter( array_map( 'trim', explode( "\n", $rawList ) ) );
62
+ }
63
+
64
+ private function storeList( array $list ) {
65
+ if ( !empty( $list ) && !empty( $this->getFile() ) ) {
66
+ Services::WpFs()->putFileContent(
67
  $this->getFile(),
68
+ implode( "\n", array_map( 'base64_encode', $list ) ),
69
  true
70
  );
71
  }
 
72
  }
73
 
74
  private function getFile() :string {
75
+ return $this->getCon()->cache_dir_handler->cacheItemPath( 'spamblacklist.txt' );
76
  }
77
  }
src/lib/src/Utilities/Tool/AssessDirWrite.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare( strict_types=1 );
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class AssessDirWrite {
8
+
9
+ private $dir;
10
+
11
+ /**
12
+ * @throws \Exception
13
+ */
14
+ public function __construct( string $dir ) {
15
+ if ( !path_is_absolute( $dir ) ) {
16
+ throw new \Exception( 'Not an absolute path' );
17
+ }
18
+ $this->dir = wp_normalize_path( $dir );
19
+ if ( $this->dir === '/' ) {
20
+ throw new \Exception( "We don't test root dirs" );
21
+ }
22
+ }
23
+
24
+ public function test() :array {
25
+ $FS = Services::WpFs();
26
+ $create = ( $FS->isDir( $this->dir ) || ( $FS->mkdir( $this->dir ) && $FS->isDir( $this->dir ) ) );
27
+ return [
28
+ 'create_dir' => $create,
29
+ 'writeable_file' => $create && $this->canCreateWriteDeleteFile(),
30
+ 'writeable' => $create && $this->canCreateWriteDeleteDir(),
31
+ ];
32
+ }
33
+
34
+ private function canCreateWriteDeleteDir() :bool {
35
+ $canWrite = false;
36
+
37
+ $FS = Services::WpFs();
38
+
39
+ $testDir = path_join( $this->dir, 'test-dir' );
40
+ if ( $FS->isFile( $testDir ) ) {
41
+ $FS->deleteFile( $testDir );
42
+ }
43
+
44
+ $FS->mkdir( $testDir );
45
+ if ( $FS->isDir( $testDir ) ) {
46
+ $file = path_join( $testDir, uniqid() );
47
+ $FS->touch( $file );
48
+ $canTouchFile = $FS->isFile( $file );
49
+ $FS->deleteFile( $file );
50
+ $FS->deleteDir( $testDir );
51
+ clearstatcache();
52
+ $canWrite = $canTouchFile && !$FS->isDir( $testDir );
53
+ }
54
+ return $canWrite;
55
+ }
56
+
57
+ private function canCreateWriteDeleteFile() :bool {
58
+ $FS = Services::WpFs();
59
+
60
+ $canWrite = false;
61
+ $testFile = path_join( $this->dir, 'test_write_file.txt' );
62
+ $uniq = uniqid();
63
+ $FS->putFileContent( $testFile, $uniq );
64
+ if ( $FS->isFile( $testFile ) ) {
65
+ $canWrite = $FS->getFileContent( $testFile ) == $uniq;
66
+ $FS->deleteFile( $testFile );
67
+ $canWrite = $canWrite && !$FS->exists( $testFile );
68
+ }
69
+
70
+ return $canWrite;
71
+ }
72
+ }
src/lib/src/Utilities/Tool/TmpFileStore.php CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Utilities\Tool;
4
 
5
  use FernleafSystems\Utilities\Logic\ExecOnce;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Utilities\CacheDir;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class TmpFileStore {
@@ -15,7 +14,7 @@ class TmpFileStore {
15
  private static $slugs = [];
16
 
17
  protected function run() {
18
- if ( $this->getCon()->cache_dir_handler->dirExists() ) {
19
  add_action( $this->getCon()->prefix( 'plugin_shutdown' ), function () {
20
  $FS = Services::WpFs();
21
  foreach ( self::$slugs as $file ) {
@@ -47,8 +46,6 @@ class TmpFileStore {
47
  }
48
 
49
  private function getTmpDir() :string {
50
- return ( new CacheDir() )
51
- ->setCon( $this->getCon() )
52
- ->buildSubDir( 'tmp_files' );
53
  }
54
  }
4
 
5
  use FernleafSystems\Utilities\Logic\ExecOnce;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
 
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class TmpFileStore {
14
  private static $slugs = [];
15
 
16
  protected function run() {
17
+ if ( $this->getCon()->cache_dir_handler->exists() ) {
18
  add_action( $this->getCon()->prefix( 'plugin_shutdown' ), function () {
19
  $FS = Services::WpFs();
20
  foreach ( self::$slugs as $file ) {
46
  }
47
 
48
  private function getTmpDir() :string {
49
+ return $this->getCon()->cache_dir_handler->buildSubDir( 'tmp_files' );
 
 
50
  }
51
  }
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -1130,6 +1130,7 @@ return array(
1130
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\Controller' => $baseDir . '/src/Utilities/AdminNotices/Controller.php',
1131
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\NoticeVO' => $baseDir . '/src/Utilities/AdminNotices/NoticeVO.php',
1132
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\CacheDir' => $baseDir . '/src/Utilities/CacheDir.php',
 
1133
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Changelog\\Retrieve' => $baseDir . '/src/Utilities/Changelog/Retrieve.php',
1134
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Collate\\RecentStats' => $baseDir . '/src/Utilities/Collate/RecentStats.php',
1135
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpLoginCapture' => $baseDir . '/src/Utilities/Consumer/WpLoginCapture.php',
@@ -1147,6 +1148,7 @@ return array(
1147
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => $baseDir . '/src/Utilities/Render/BasePageDisplay.php',
1148
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => $baseDir . '/src/Utilities/Render/BaseTemplateRenderer.php',
1149
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => $baseDir . '/src/Utilities/Time/WorldTimeApi.php',
 
1150
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => $baseDir . '/src/Utilities/Tool/DbTableExport.php',
1151
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\FormatBytes' => $baseDir . '/src/Utilities/Tool/FormatBytes.php',
1152
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\IpListSort' => $baseDir . '/src/Utilities/Tool/IpListSort.php',
1130
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\Controller' => $baseDir . '/src/Utilities/AdminNotices/Controller.php',
1131
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\NoticeVO' => $baseDir . '/src/Utilities/AdminNotices/NoticeVO.php',
1132
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\CacheDir' => $baseDir . '/src/Utilities/CacheDir.php',
1133
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\CacheDirHandler' => $baseDir . '/src/Utilities/CacheDirHandler.php',
1134
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Changelog\\Retrieve' => $baseDir . '/src/Utilities/Changelog/Retrieve.php',
1135
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Collate\\RecentStats' => $baseDir . '/src/Utilities/Collate/RecentStats.php',
1136
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpLoginCapture' => $baseDir . '/src/Utilities/Consumer/WpLoginCapture.php',
1148
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => $baseDir . '/src/Utilities/Render/BasePageDisplay.php',
1149
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => $baseDir . '/src/Utilities/Render/BaseTemplateRenderer.php',
1150
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => $baseDir . '/src/Utilities/Time/WorldTimeApi.php',
1151
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\AssessDirWrite' => $baseDir . '/src/Utilities/Tool/AssessDirWrite.php',
1152
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => $baseDir . '/src/Utilities/Tool/DbTableExport.php',
1153
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\FormatBytes' => $baseDir . '/src/Utilities/Tool/FormatBytes.php',
1154
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\IpListSort' => $baseDir . '/src/Utilities/Tool/IpListSort.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -1317,6 +1317,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1317
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\Controller' => __DIR__ . '/../..' . '/src/Utilities/AdminNotices/Controller.php',
1318
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\NoticeVO' => __DIR__ . '/../..' . '/src/Utilities/AdminNotices/NoticeVO.php',
1319
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\CacheDir' => __DIR__ . '/../..' . '/src/Utilities/CacheDir.php',
 
1320
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Changelog\\Retrieve' => __DIR__ . '/../..' . '/src/Utilities/Changelog/Retrieve.php',
1321
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Collate\\RecentStats' => __DIR__ . '/../..' . '/src/Utilities/Collate/RecentStats.php',
1322
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpLoginCapture' => __DIR__ . '/../..' . '/src/Utilities/Consumer/WpLoginCapture.php',
@@ -1334,6 +1335,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
1334
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => __DIR__ . '/../..' . '/src/Utilities/Render/BasePageDisplay.php',
1335
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => __DIR__ . '/../..' . '/src/Utilities/Render/BaseTemplateRenderer.php',
1336
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => __DIR__ . '/../..' . '/src/Utilities/Time/WorldTimeApi.php',
 
1337
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => __DIR__ . '/../..' . '/src/Utilities/Tool/DbTableExport.php',
1338
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\FormatBytes' => __DIR__ . '/../..' . '/src/Utilities/Tool/FormatBytes.php',
1339
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\IpListSort' => __DIR__ . '/../..' . '/src/Utilities/Tool/IpListSort.php',
1317
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\Controller' => __DIR__ . '/../..' . '/src/Utilities/AdminNotices/Controller.php',
1318
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\AdminNotices\\NoticeVO' => __DIR__ . '/../..' . '/src/Utilities/AdminNotices/NoticeVO.php',
1319
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\CacheDir' => __DIR__ . '/../..' . '/src/Utilities/CacheDir.php',
1320
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\CacheDirHandler' => __DIR__ . '/../..' . '/src/Utilities/CacheDirHandler.php',
1321
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Changelog\\Retrieve' => __DIR__ . '/../..' . '/src/Utilities/Changelog/Retrieve.php',
1322
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Collate\\RecentStats' => __DIR__ . '/../..' . '/src/Utilities/Collate/RecentStats.php',
1323
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Consumer\\WpLoginCapture' => __DIR__ . '/../..' . '/src/Utilities/Consumer/WpLoginCapture.php',
1335
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BasePageDisplay' => __DIR__ . '/../..' . '/src/Utilities/Render/BasePageDisplay.php',
1336
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Render\\BaseTemplateRenderer' => __DIR__ . '/../..' . '/src/Utilities/Render/BaseTemplateRenderer.php',
1337
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Time\\WorldTimeApi' => __DIR__ . '/../..' . '/src/Utilities/Time/WorldTimeApi.php',
1338
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\AssessDirWrite' => __DIR__ . '/../..' . '/src/Utilities/Tool/AssessDirWrite.php',
1339
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\DbTableExport' => __DIR__ . '/../..' . '/src/Utilities/Tool/DbTableExport.php',
1340
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\FormatBytes' => __DIR__ . '/../..' . '/src/Utilities/Tool/FormatBytes.php',
1341
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Utilities\\Tool\\IpListSort' => __DIR__ . '/../..' . '/src/Utilities/Tool/IpListSort.php',
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php CHANGED
@@ -414,7 +414,7 @@ class Fs {
414
  }
415
 
416
  if ( function_exists( 'file_put_contents' ) ) {
417
- return file_put_contents( $sFilePath, $sContents ) !== false;
418
  }
419
  return false;
420
  }
@@ -441,7 +441,7 @@ class Fs {
441
  if ( $oFs && $oFs->delete( $sFilePath ) ) {
442
  return true;
443
  }
444
- return function_exists( 'unlink' ) ? @unlink( $sFilePath ) : null;
445
  }
446
 
447
  /**
414
  }
415
 
416
  if ( function_exists( 'file_put_contents' ) ) {
417
+ // return file_put_contents( $sFilePath, $sContents ) !== false;
418
  }
419
  return false;
420
  }
441
  if ( $oFs && $oFs->delete( $sFilePath ) ) {
442
  return true;
443
  }
444
+ // return function_exists( 'unlink' ) ? @unlink( $sFilePath ) : null;
445
  }
446
 
447
  /**
src/lib/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php CHANGED
@@ -23,6 +23,10 @@ use Monolog\Utils;
23
  */
24
  class StreamHandler extends AbstractProcessingHandler
25
  {
 
 
 
 
26
  protected $stream;
27
  protected $url;
28
  private $errorMessage;
@@ -45,6 +49,7 @@ class StreamHandler extends AbstractProcessingHandler
45
  parent::__construct($level, $bubble);
46
  if (is_resource($stream)) {
47
  $this->stream = $stream;
 
48
  } elseif (is_string($stream)) {
49
  $this->url = Utils::canonicalizePath($stream);
50
  } else {
@@ -109,6 +114,7 @@ class StreamHandler extends AbstractProcessingHandler
109
 
110
  throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $this->url));
111
  }
 
112
  }
113
 
114
  if ($this->useLocking) {
@@ -133,6 +139,15 @@ class StreamHandler extends AbstractProcessingHandler
133
  fwrite($stream, (string) $record['formatted']);
134
  }
135
 
 
 
 
 
 
 
 
 
 
136
  private function customErrorHandler($code, $msg)
137
  {
138
  $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
23
  */
24
  class StreamHandler extends AbstractProcessingHandler
25
  {
26
+ /** @private 512KB */
27
+ const CHUNK_SIZE = 524288;
28
+
29
+ /** @var resource|null */
30
  protected $stream;
31
  protected $url;
32
  private $errorMessage;
49
  parent::__construct($level, $bubble);
50
  if (is_resource($stream)) {
51
  $this->stream = $stream;
52
+ $this->streamSetChunkSize();
53
  } elseif (is_string($stream)) {
54
  $this->url = Utils::canonicalizePath($stream);
55
  } else {
114
 
115
  throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $this->url));
116
  }
117
+ $this->streamSetChunkSize();
118
  }
119
 
120
  if ($this->useLocking) {
139
  fwrite($stream, (string) $record['formatted']);
140
  }
141
 
142
+ protected function streamSetChunkSize()
143
+ {
144
+ if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
145
+ return stream_set_chunk_size($this->stream, self::CHUNK_SIZE);
146
+ }
147
+
148
+ return false;
149
+ }
150
+
151
  private function customErrorHandler($code, $msg)
152
  {
153
  $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
templates/twig/pages/block/autorecover.twig CHANGED
@@ -1,26 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <div class="auto-recover">
2
  <div class="uaug uau">
3
  <p>{{ strings.you_can }}</p>
4
  <form method="post" action="{{ hrefs.home }}">
5
  <input type="hidden" name="email" value="" />
6
  {% for key,val in vars.nonce %}
7
- <input type="hidden" name="{{ key }}" value="{{ val }}" />
8
  {% endfor %}
9
- <p><button type="submit" class="btn btn-warning">{{ strings.button }}</button></p>
 
 
 
 
 
 
 
 
 
 
 
 
10
  </form>
11
  </div>
12
  </div>
13
 
14
- {#<script>#}
15
- {# let sendEmail = function () {#}
16
- {# let xmlHttp = new XMLHttpRequest();#}
17
- {# xmlHttp.open( "GET", '{{ hrefs.unblock|raw }}', false ); // false for synchronous request#}
18
- {# xmlHttp.send( null );#}
19
- {# if ( xmlHttp.status === 200 ) {#}
20
- {# alert( 'Please check your email for a link to confirm.' );#}
21
- {# }#}
22
- {# else {#}
23
- {# alert( 'Request Failed. Likely you have tried to request an email too soon after the previous attempt.' );#}
24
- {# }#}
25
- {# };#}
26
- {#</script>#}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <style>
2
+ .address label,
3
+ .address input {
4
+ opacity: 0;
5
+ position: absolute;
6
+ top: 0;
7
+ left: 0;
8
+ height: 0;
9
+ width: 0;
10
+ z-index: -1;
11
+ }
12
+ p#unblock_confirm input[type=checkbox] {
13
+ margin-right: 4px;
14
+ }
15
+ </style>
16
  <div class="auto-recover">
17
  <div class="uaug uau">
18
  <p>{{ strings.you_can }}</p>
19
  <form method="post" action="{{ hrefs.home }}">
20
  <input type="hidden" name="email" value="" />
21
  {% for key,val in vars.nonce %}
22
+ <input type="hidden" name="{{ key }}" value="{{ val }}" autocomplete="off" />
23
  {% endfor %}
24
+ <fieldset aria-hidden="true" class="address">
25
+ <label for="firstname">
26
+ <input autocomplete="off" type="text" id="firstname" name="firstname" placeholder="Your name here">
27
+ </label>
28
+ <label for="email">
29
+ <input autocomplete="off" type="email" id="email" name="email" placeholder="Your e-mail here">
30
+ </label>
31
+ </fieldset>
32
+ <fieldset aria-hidden="false" class="submit">
33
+ <p id="unblock_confirm"></p>
34
+ <button type="submit" class="btn btn-warning" id="submitUnblock"
35
+ disabled="disabled">{{ strings.button }}</button>
36
+ </fieldset>
37
  </form>
38
  </div>
39
  </div>
40
 
41
+ <script type="text/javascript">
42
+
43
+ var bRun = false;
44
+
45
+ window.addEventListener( 'load', function () {
46
+
47
+ let the_p = document.getElementById( "unblock_confirm" );
48
+ if ( typeof the_p === 'undefined' ) {
49
+ console.log( '[Shield Security] GASP Checkbox: Problem on your page and perhaps Javascript is breaking.' );
50
+ return;
51
+ }
52
+ let thisForm = the_p.form;
53
+
54
+ let the_cb = document.createElement( "input" );
55
+ let the_lab = document.createElement( "label" );
56
+ let the_txt = document.createTextNode( "I confirm that I'm accessing this site legitimately" );
57
+ the_cb.type = "checkbox";
58
+ the_cb.id = "_confirm";
59
+ the_cb.name = "_confirm";
60
+ the_cb.value = "Y";
61
+ the_p.appendChild( the_lab );
62
+ the_lab.appendChild( the_cb );
63
+ the_lab.appendChild( the_txt );
64
+
65
+ the_cb.onchange = function ( evt ) {
66
+ const button = document.getElementById( "submitUnblock" );
67
+ if ( evt.target.checked ) {
68
+ button.removeAttribute( 'disabled' );
69
+ }
70
+ else {
71
+ button.setAttribute( 'disabled', 'disabled' );
72
+ }
73
+ };
74
+
75
+ }, false );
76
+
77
+ </script>