Version Description
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 15.1.3 |
Comparing to | |
See all releases |
Code changes from version 15.1.2 to 15.1.3
- cl.json +18 -0
- config/plugin.json +7 -0
- icwp-wpsf.php +1 -1
- plugin-spec.php +3 -3
- plugin.json +3 -3
- readme.txt +1 -1
- src/lib/src/Blocks/RenderBlockPages/RenderBlockIP.php +2 -3
- src/lib/src/Controller/Assets/Paths.php +6 -0
- src/lib/src/Controller/Controller.php +11 -6
- src/lib/src/Controller/Plugin/PluginDelete.php +4 -1
- src/lib/src/Controller/Utilities/Upgrade.php +18 -7
- src/lib/src/Modules/AuditTrail/Lib/LogHandlers/Utility/LogFileDirCreate.php +15 -5
- src/lib/src/Modules/CommentsFilter/ModCon.php +0 -4
- src/lib/src/Modules/HackGuard/Lib/ScanTables/Modals/ScanItemView.php +7 -10
- src/lib/src/Modules/HackGuard/ModCon.php +1 -4
- src/lib/src/Modules/HackGuard/Options.php +1 -1
- src/lib/src/Modules/HackGuard/Scan/Controller/Afs.php +1 -1
- src/lib/src/Modules/HackGuard/UI.php +1 -1
- src/lib/src/Modules/IPs/Lib/AutoUnblock.php +20 -30
- src/lib/src/Modules/IPs/Lib/BlockRequest.php +1 -0
- src/lib/src/Modules/IPs/Options.php +20 -12
- src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php +1 -1
- src/lib/src/Modules/LoginGuard/Lib/CooldownFlagFile.php +1 -1
- src/lib/src/Modules/Plugin/Lib/Debug/Collate.php +3 -2
- src/lib/src/Modules/Plugin/Lib/TestCacheDirWrite.php +3 -0
- src/lib/src/Modules/Plugin/ModCon.php +19 -0
- src/lib/src/Rules/RulesStorageHandler.php +16 -32
- src/lib/src/Scans/Afs/Processing/FileScanOptimiser.php +1 -1
- src/lib/src/Utilities/CacheDir.php +4 -0
- src/lib/src/Utilities/CacheDirHandler.php +171 -0
- src/lib/src/Utilities/HumanSpam/TestContent.php +18 -14
- src/lib/src/Utilities/Tool/AssessDirWrite.php +72 -0
- src/lib/src/Utilities/Tool/TmpFileStore.php +2 -5
- src/lib/vendor/composer/autoload_classmap.php +2 -0
- src/lib/vendor/composer/autoload_static.php +2 -0
- src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php +2 -2
- src/lib/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php +15 -0
- 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.
|
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.
|
4 |
-
"release_timestamp":
|
5 |
-
"build": "202206.
|
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.
|
4 |
-
"release_timestamp":
|
5 |
-
"build": "202206.
|
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.
|
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->
|
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\
|
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 |
-
|
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 |
-
$
|
467 |
-
if (
|
468 |
-
$path =
|
|
|
|
|
|
|
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 |
-
|
|
|
|
|
|
|
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()->
|
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 |
-
|
32 |
|
33 |
$this->upgradeModules();
|
34 |
|
35 |
$con->cfg->previous_version = $con->getVersion();
|
36 |
|
37 |
-
|
38 |
-
|
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 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
throw new \Exception( "Plugin TMP Dir is unavailable." );
|
17 |
}
|
18 |
|
19 |
$theLogsDir = null;
|
20 |
-
foreach ( $FS->getAllFilesInDir( $
|
21 |
-
$possibleFullPath = path_join( $
|
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( $
|
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 |
-
$
|
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 |
-
|
|
|
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(
|
|
|
|
|
|
|
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 (
|
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()->
|
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->
|
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->
|
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 (
|
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 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
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->
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
}
|
22 |
|
23 |
public function getAutoUnblockEmailIDs() :array {
|
24 |
-
$
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
}
|
27 |
|
28 |
-
public function
|
29 |
-
|
30 |
-
return !array_key_exists( $ip, $existing )
|
31 |
-
|| ( Services::Request()->carbon()->subHours( 1 )->timestamp > $existing[ $ip ] );
|
32 |
}
|
33 |
|
34 |
-
public function
|
35 |
-
|
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->
|
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()->
|
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->
|
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 |
-
$
|
|
|
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 )
|
50 |
$WP = Services::WpGeneral();
|
51 |
-
$
|
52 |
-
|
53 |
-
|
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
|
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 |
-
|
|
|
|
|
|
|
|
|
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->
|
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 (
|
45 |
$FS = Services::WpFs();
|
46 |
$file = $this->getFile();
|
47 |
-
if (
|
48 |
-
|
49 |
-
$this->
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
-
$this->list = array_map( 'base64_decode', explode( "\n", $FS->getFileContent( $file, true ) ) );
|
52 |
}
|
53 |
return $this->list;
|
54 |
}
|
55 |
|
56 |
-
private function
|
57 |
-
$success = false;
|
58 |
$mod = $this->getCon()->getModule_Comments();
|
59 |
$rawList = Services::HttpRequest()->getContent( $mod->getOptions()->getDef( 'url_spam_blacklist_terms' ) );
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
62 |
$this->getFile(),
|
63 |
-
implode( "\n", array_map( 'base64_encode',
|
64 |
true
|
65 |
);
|
66 |
}
|
67 |
-
return $success;
|
68 |
}
|
69 |
|
70 |
private function getFile() :string {
|
71 |
-
return $this->getCon()->
|
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->
|
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 (
|
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 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
</form>
|
11 |
</div>
|
12 |
</div>
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
{
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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>
|