Version Description
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 16.1.14 |
Comparing to | |
See all releases |
Code changes from version 16.1.13 to 16.1.14
- cl.json +28 -2
- icwp-wpsf.php +1 -1
- plugin-spec.php +5 -4
- plugin.json +5 -4
- readme.txt +11 -11
- src/lib/src/Modules/Data/Lib/CleanDatabases.php +22 -0
- src/lib/src/Modules/HackGuard/Lib/Snapshots/StorageDir.php +46 -0
- src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Base.php +15 -17
- src/lib/src/Modules/HackGuard/Lib/Utility/CleanOutOldGuardFiles.php +41 -0
- src/lib/src/Modules/HackGuard/ModCon.php +4 -0
- src/lib/src/Modules/HackGuard/Upgrade.php +14 -0
- src/lib/src/Modules/IPs/Lib/CrowdSec/Signals/EventsToSignals.php +2 -3
- src/lib/src/Modules/LoginGuard/Strings.php +13 -4
- src/lib/src/Modules/Plugin/Lib/Debug/Collate.php +6 -6
- src/lib/src/Modules/UserManagement/Lib/Session/FindSessions.php +7 -8
- src/lib/src/Modules/UserManagement/Lib/Suspend/UserSuspendController.php +78 -115
- src/lib/vendor/composer/autoload_classmap.php +1 -0
- src/lib/vendor/composer/autoload_static.php +1 -0
- src/lib/vendor/composer/installed.json +6 -6
- src/lib/vendor/composer/installed.php +9 -9
- src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/BaseQuery.php +1 -19
- src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Delete.php +4 -6
- src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Insert.php +1 -1
- src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Update.php +1 -3
- src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Common/Iterator.php +6 -5
- src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Common/SubQueryLoader.php +1 -1
- src/lib/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php +148 -0
- src/lib/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php +67 -0
- src/lib/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php +45 -0
- src/lib/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php +191 -0
cl.json
CHANGED
@@ -128,14 +128,40 @@
|
|
128 |
],
|
129 |
"patches": [
|
130 |
{
|
131 |
-
"version": "
|
132 |
-
"released_at":
|
133 |
"items": [
|
134 |
{
|
135 |
"title": "Marks Shield 16.x as the final series supporting PHP 7.0 and 7.1. Shield 17 will require PHP 7.2.",
|
136 |
"type": "changed",
|
137 |
"href": "https://shsec.io/l8"
|
138 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
{
|
140 |
"title": "Attempt to eliminate CrowdSec API issues.",
|
141 |
"type": "improved"
|
128 |
],
|
129 |
"patches": [
|
130 |
{
|
131 |
+
"version": "14",
|
132 |
+
"released_at": 1669197000,
|
133 |
"items": [
|
134 |
{
|
135 |
"title": "Marks Shield 16.x as the final series supporting PHP 7.0 and 7.1. Shield 17 will require PHP 7.2.",
|
136 |
"type": "changed",
|
137 |
"href": "https://shsec.io/l8"
|
138 |
},
|
139 |
+
{
|
140 |
+
"title": "Performance improved when loading the WordPress Users page for sites with large users counts.",
|
141 |
+
"type": "improved"
|
142 |
+
},
|
143 |
+
{
|
144 |
+
"title": "Dashboard widget showing incorrect dates for user last login if it's never been recorded.",
|
145 |
+
"type": "fixed"
|
146 |
+
},
|
147 |
+
{
|
148 |
+
"title": "Tweaks to CrowdSec Signals map.",
|
149 |
+
"type": "fixed"
|
150 |
+
},
|
151 |
+
{
|
152 |
+
"title": "Plugin/Theme file scanner bug fixes.",
|
153 |
+
"type": "fixed"
|
154 |
+
},
|
155 |
+
{
|
156 |
+
"title": "Minor bug fixes.",
|
157 |
+
"type": "fixed"
|
158 |
+
}
|
159 |
+
]
|
160 |
+
},
|
161 |
+
{
|
162 |
+
"version": "13",
|
163 |
+
"released_at": 1667298000,
|
164 |
+
"items": [
|
165 |
{
|
166 |
"title": "Attempt to eliminate CrowdSec API issues.",
|
167 |
"type": "improved"
|
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: 16.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: 16.1.14
|
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": "16.1.
|
4 |
-
"release_timestamp":
|
5 |
-
"build": "202211.
|
6 |
"slug_parent": "icwp",
|
7 |
"slug_plugin": "wpsf",
|
8 |
"text_domain": "wp-simple-firewall",
|
@@ -407,7 +407,8 @@
|
|
407 |
"14.1.1",
|
408 |
"14.1.4",
|
409 |
"16.1.2",
|
410 |
-
"16.1.7"
|
|
|
411 |
],
|
412 |
"action_links": {
|
413 |
"remove": null,
|
1 |
{
|
2 |
"properties": {
|
3 |
+
"version": "16.1.14",
|
4 |
+
"release_timestamp": 1669197000,
|
5 |
+
"build": "202211.2301",
|
6 |
"slug_parent": "icwp",
|
7 |
"slug_plugin": "wpsf",
|
8 |
"text_domain": "wp-simple-firewall",
|
407 |
"14.1.1",
|
408 |
"14.1.4",
|
409 |
"16.1.2",
|
410 |
+
"16.1.7",
|
411 |
+
"16.1.14"
|
412 |
],
|
413 |
"action_links": {
|
414 |
"remove": null,
|
plugin.json
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
{
|
2 |
"properties": {
|
3 |
-
"version": "16.1.
|
4 |
-
"release_timestamp":
|
5 |
-
"build": "202211.
|
6 |
"slug_parent": "icwp",
|
7 |
"slug_plugin": "wpsf",
|
8 |
"text_domain": "wp-simple-firewall",
|
@@ -407,7 +407,8 @@
|
|
407 |
"14.1.1",
|
408 |
"14.1.4",
|
409 |
"16.1.2",
|
410 |
-
"16.1.7"
|
|
|
411 |
],
|
412 |
"action_links": {
|
413 |
"remove": null,
|
1 |
{
|
2 |
"properties": {
|
3 |
+
"version": "16.1.14",
|
4 |
+
"release_timestamp": 1669197000,
|
5 |
+
"build": "202211.2301",
|
6 |
"slug_parent": "icwp",
|
7 |
"slug_plugin": "wpsf",
|
8 |
"text_domain": "wp-simple-firewall",
|
407 |
"14.1.1",
|
408 |
"14.1.4",
|
409 |
"16.1.2",
|
410 |
+
"16.1.7",
|
411 |
+
"16.1.14"
|
412 |
],
|
413 |
"action_links": {
|
414 |
"remove": null,
|
readme.txt
CHANGED
@@ -3,12 +3,12 @@ Contributors: paultgoodchild, getshieldsecurity
|
|
3 |
Donate link: https://shsec.io/bw
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
-
Tags: limit login, malware scan, firewall, two factor authentication, login protection
|
7 |
Requires at least: 3.7
|
8 |
Requires PHP: 7.0
|
9 |
Recommended PHP: 7.4
|
10 |
Tested up to: 6.1
|
11 |
-
Stable tag: 16.1.
|
12 |
|
13 |
Bad Bots Are Your #1 Security Risk. Are you playing whack-a-mole with malware & vulnerabilities? Discover the real security before marketing hype.
|
14 |
|
@@ -18,13 +18,13 @@ Shield is [now partnered with CrowdSec](https://shsec.io/l5) for global, crowd-s
|
|
18 |
|
19 |
**We need to stop our obsession with malware**. Malware scanning is important *after* your site is hacked. Get a security plugin that [prioritises security *protection* before the worst happens](https://shsec.io/ky).
|
20 |
|
21 |
-
Shield is the only security plugin for WordPress that fully prioritises protection over repair.
|
22 |
|
23 |
-
**No
|
24 |
|
25 |
Our mission is to block bad IPs and requests before they can do any damage. Shield will block all automated Comment SPAM, brute force logins, plugin-vulnerability exploitation, malware injection, vulnerability scanning, password stuffing, contact form spam, and so much more. If you're disappointed with the performance of your current solution, give Shield a try - we promise that you won't be disappointed.
|
26 |
|
27 |
-
**Use the power of the network**. ShieldNET is our new and exclusive network-based intelligence platform that draws-in information from all around the globe to help Shield Security plugins be smarter when assessing security threats and taking appropriate action. And with our new [Crowdsec partnership](https://shsec.io/l5) you've got even more data.
|
28 |
|
29 |
#### Get the highest rated 5* Security Plugin for WordPress
|
30 |
|
@@ -36,19 +36,19 @@ Our Security solution isn't designed to scare you and make you feel unsafe.
|
|
36 |
|
37 |
We're all about delivering powerful security without the scary stories and fear-based marketing. We're all about WordPress security without the marketing hype.
|
38 |
|
39 |
-
Shield Security is full of
|
40 |
|
41 |
## Your Goal And Ours: Peace Of Mind and Freedom From Hackers
|
42 |
|
43 |
-
Bots are the #1 cause of WordPress security
|
44 |
|
45 |
-
|
46 |
|
47 |
### 2 Key WordPress Security Strategies
|
48 |
|
49 |
Shield Security uses 2 simple key strategies to protect your WordPress sites:
|
50 |
|
51 |
-
1. Prevention - Detect Bots, Intrusions, and Hacks
|
52 |
1. Cure - Block Bad Bots and Repair Hacks
|
53 |
|
54 |
#### Key Security Strategy #1: Hacking Prevention
|
@@ -209,9 +209,9 @@ Easy - we're just better! ;)
|
|
209 |
|
210 |
Firstly, we don't modify any core WordPress or web hosting file. This is important and explains why randomly you upgrade your security plugin and your site dies.
|
211 |
|
212 |
-
Ideally you shouldn't use this
|
213 |
|
214 |
-
= My server has a
|
215 |
|
216 |
This plugin is an application layer firewall, not a server/network security firewall. It is designed to interpret web calls to your site to look for attempts to circumvent it and gain unauthorized access.
|
217 |
|
3 |
Donate link: https://shsec.io/bw
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
+
Tags: limit login, malware scan, firewall, file scan, two factor authentication, intrusion prevention, security, login protection
|
7 |
Requires at least: 3.7
|
8 |
Requires PHP: 7.0
|
9 |
Recommended PHP: 7.4
|
10 |
Tested up to: 6.1
|
11 |
+
Stable tag: 16.1.14
|
12 |
|
13 |
Bad Bots Are Your #1 Security Risk. Are you playing whack-a-mole with malware & vulnerabilities? Discover the real security before marketing hype.
|
14 |
|
18 |
|
19 |
**We need to stop our obsession with malware**. Malware scanning is important *after* your site is hacked. Get a security plugin that [prioritises security *protection* before the worst happens](https://shsec.io/ky).
|
20 |
|
21 |
+
Shield is the only security plugin for WordPress that fully prioritises protection over repair. With Shield, your site will start to block visitors as they probe your site looking for vulnerabilities, and before they can begin to do any damage.
|
22 |
|
23 |
+
**No other standalone WordPress security plugin** (including Wordfence, WP Cerber, Ninja Firewall, All-In-One Security) approaches security in this way. The 1st step in any good security system is Intrusion Detection/Prevention, the 2nd step is repair. Shield does both.
|
24 |
|
25 |
Our mission is to block bad IPs and requests before they can do any damage. Shield will block all automated Comment SPAM, brute force logins, plugin-vulnerability exploitation, malware injection, vulnerability scanning, password stuffing, contact form spam, and so much more. If you're disappointed with the performance of your current solution, give Shield a try - we promise that you won't be disappointed.
|
26 |
|
27 |
+
**Use the power of the network**. ShieldNET is our new and exclusive network-based intelligence platform that draws-in information from all around the globe to help Shield Security plugins be smarter when assessing security threats and taking appropriate action. And with our new [Crowdsec partnership](https://shsec.io/l5) you've got even more data to make smarter decision.
|
28 |
|
29 |
#### Get the highest rated 5* Security Plugin for WordPress
|
30 |
|
36 |
|
37 |
We're all about delivering powerful security without the scary stories and fear-based marketing. We're all about WordPress security without the marketing hype.
|
38 |
|
39 |
+
Shield Security is full of powerful security mechanisms, making intelligent decisions to protect your site and maintain security and integrity, so *you don't have to*.
|
40 |
|
41 |
## Your Goal And Ours: Peace Of Mind and Freedom From Hackers
|
42 |
|
43 |
+
Bots are the #1 cause of WordPress security hacks and malware exploitation.
|
44 |
|
45 |
+
Better WordPress Security protection is smarter and uncomplicated.
|
46 |
|
47 |
### 2 Key WordPress Security Strategies
|
48 |
|
49 |
Shield Security uses 2 simple key strategies to protect your WordPress sites:
|
50 |
|
51 |
+
1. Prevention - Intrusion Prevention System: Detect Bots/Malicious IPs, WordPress Intrusions, and WordPress Hacks and Malware
|
52 |
1. Cure - Block Bad Bots and Repair Hacks
|
53 |
|
54 |
#### Key Security Strategy #1: Hacking Prevention
|
209 |
|
210 |
Firstly, we don't modify any core WordPress or web hosting file. This is important and explains why randomly you upgrade your security plugin and your site dies.
|
211 |
|
212 |
+
Ideally you shouldn't use this alongside other Anti-SPAM plugins or security plugins. If there is a feature you need, please feel free to suggest it in the support forums.
|
213 |
|
214 |
+
= My server has a security firewall, why do I need this plugin? =
|
215 |
|
216 |
This plugin is an application layer firewall, not a server/network security firewall. It is designed to interpret web calls to your site to look for attempts to circumvent it and gain unauthorized access.
|
217 |
|
src/lib/src/Modules/Data/Lib/CleanDatabases.php
CHANGED
@@ -9,6 +9,7 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\{
|
|
9 |
Traffic
|
10 |
};
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
12 |
|
13 |
class CleanDatabases extends ExecOnceModConsumer {
|
14 |
|
@@ -52,6 +53,27 @@ class CleanDatabases extends ExecOnceModConsumer {
|
|
52 |
->query();
|
53 |
}
|
54 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
}
|
56 |
|
57 |
private function cleanRequestLogs() {
|
9 |
Traffic
|
10 |
};
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
12 |
+
use FernleafSystems\Wordpress\Services\Services;
|
13 |
|
14 |
class CleanDatabases extends ExecOnceModConsumer {
|
15 |
|
53 |
->query();
|
54 |
}
|
55 |
}
|
56 |
+
|
57 |
+
$this->cleanUserMeta();
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Delete all the user meta rows where there is no corresponding User ID.
|
62 |
+
* WARNING: GREAT CARE MUST ALWAYS BE TAKEN WHEN EDITING THIS QUERY TO ENSURE WE DELETE ONLY FROM `meta`
|
63 |
+
*/
|
64 |
+
private function cleanUserMeta() {
|
65 |
+
Services::WpDb()->doSql( sprintf(
|
66 |
+
'DELETE `meta` FROM `%s` as `meta`
|
67 |
+
LEFT JOIN `%s` as `users` on `users`.`ID`=`meta`.`user_id` WHERE `users`.`ID` IS NULL',
|
68 |
+
$this->getCon()->getModule_Data()->getDbH_UserMeta()->getTableSchema()->table,
|
69 |
+
Services::WpDb()->getTable_Users()
|
70 |
+
) );
|
71 |
+
// $res = Services::WpDb()->selectCustom( sprintf(
|
72 |
+
// 'SELECT `meta`.`user_id` as `meta_user_id`, `users`.`ID` as `wp_user_id` FROM `%s` as `meta`
|
73 |
+
// LEFT JOIN `%s` as `users` on `users`.`ID`=`meta`.`user_id` WHERE `users`.`ID` IS NULL',
|
74 |
+
// $userMetaData->getTableSchema()->table,
|
75 |
+
// Services::WpDb()->getTable_Users()
|
76 |
+
// ) );
|
77 |
}
|
78 |
|
79 |
private function cleanRequestLogs() {
|
src/lib/src/Modules/HackGuard/Lib/Snapshots/StorageDir.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
|
8 |
+
class StorageDir {
|
9 |
+
|
10 |
+
use PluginControllerConsumer;
|
11 |
+
|
12 |
+
const SUFFIX_LENGTH = 16;
|
13 |
+
|
14 |
+
private $tempDir;
|
15 |
+
|
16 |
+
public function getTempDir() :string {
|
17 |
+
if ( is_null( $this->tempDir ) ) {
|
18 |
+
try {
|
19 |
+
$dir = $this->locateTempDir();
|
20 |
+
}
|
21 |
+
catch ( \Exception $e ) {
|
22 |
+
$dir = $this->getCon()->cache_dir_handler->buildSubDir( 'ptguard-'.wp_generate_password( self::SUFFIX_LENGTH, false ) );
|
23 |
+
}
|
24 |
+
$this->tempDir = $dir;
|
25 |
+
}
|
26 |
+
return $this->tempDir;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @throws \Exception
|
31 |
+
*/
|
32 |
+
private function locateTempDir() :string {
|
33 |
+
$FS = Services::WpFs();
|
34 |
+
$dir = null;
|
35 |
+
foreach ( $FS->getAllFilesInDir( $this->getCon()->cache_dir_handler->dir() ) as $fileItem ) {
|
36 |
+
if ( $FS->isDir( $fileItem ) && preg_match( sprintf( '#^ptguard-[a-z0-9]{%s}$#i', self::SUFFIX_LENGTH ), basename( $fileItem ) ) ) {
|
37 |
+
$dir = $fileItem;
|
38 |
+
break;
|
39 |
+
}
|
40 |
+
}
|
41 |
+
if ( empty( $dir ) ) {
|
42 |
+
throw new \Exception( "Dir doesn't exist" );
|
43 |
+
}
|
44 |
+
return $dir;
|
45 |
+
}
|
46 |
+
}
|
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Base.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
6 |
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
@@ -11,38 +12,35 @@ class Base {
|
|
11 |
|
12 |
private static $tempDir;
|
13 |
|
|
|
|
|
14 |
protected function isTempDirAvailable() :bool {
|
15 |
return !empty( $this->getTempDir() );
|
16 |
}
|
17 |
|
18 |
protected function getTempDir() :string {
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
$dir = $this->findTempDir();
|
23 |
-
if ( basename( $dir ) === 'ptguard' ) {
|
24 |
-
$oldDir = $dir;
|
25 |
-
$dir = $this->generateNewDirName();
|
26 |
-
foreach ( [ 'plugins', 'themes' ] as $type ) {
|
27 |
-
$FS->moveDirContents( path_join( $oldDir, $type ), path_join( $dir, $type ) );
|
28 |
-
}
|
29 |
-
$FS->deleteDir( $oldDir );
|
30 |
-
}
|
31 |
-
}
|
32 |
-
catch ( \Exception $e ) {
|
33 |
-
$dir = $this->generateNewDirName();
|
34 |
}
|
35 |
-
self::$tempDir = $dir;
|
36 |
}
|
37 |
-
|
|
|
|
|
|
|
|
|
38 |
}
|
39 |
|
|
|
|
|
|
|
40 |
private function generateNewDirName() :string {
|
41 |
return $this->getCon()->cache_dir_handler->buildSubDir( 'ptguard-'.wp_generate_password( 16, false ) );
|
42 |
}
|
43 |
|
44 |
/**
|
45 |
* @throws \Exception
|
|
|
46 |
*/
|
47 |
private function findTempDir() :string {
|
48 |
$FS = Services::WpFs();
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StorageDir;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
12 |
|
13 |
private static $tempDir;
|
14 |
|
15 |
+
private static $storageDir;
|
16 |
+
|
17 |
protected function isTempDirAvailable() :bool {
|
18 |
return !empty( $this->getTempDir() );
|
19 |
}
|
20 |
|
21 |
protected function getTempDir() :string {
|
22 |
+
{ // TODO: remove this
|
23 |
+
if ( !empty( self::$tempDir ) ) {
|
24 |
+
return self::$tempDir;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
|
|
26 |
}
|
27 |
+
|
28 |
+
if ( empty( self::$storageDir ) ) {
|
29 |
+
self::$storageDir = ( new StorageDir() )->setCon( $this->getCon() );
|
30 |
+
}
|
31 |
+
return self::$storageDir->getTempDir();
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @deprecated 16.1.14
|
36 |
+
*/
|
37 |
private function generateNewDirName() :string {
|
38 |
return $this->getCon()->cache_dir_handler->buildSubDir( 'ptguard-'.wp_generate_password( 16, false ) );
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
* @throws \Exception
|
43 |
+
* @deprecated 16.1.14
|
44 |
*/
|
45 |
private function findTempDir() :string {
|
46 |
$FS = Services::WpFs();
|
src/lib/src/Modules/HackGuard/Lib/Utility/CleanOutOldGuardFiles.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Utility;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StorageDir;
|
7 |
+
use FernleafSystems\Wordpress\Services\Services;
|
8 |
+
|
9 |
+
class CleanOutOldGuardFiles extends ExecOnceModConsumer {
|
10 |
+
|
11 |
+
protected function run( int $limit = 50 ) {
|
12 |
+
$FS = Services::WpFs();
|
13 |
+
|
14 |
+
$firstAcceptableDir = null;
|
15 |
+
$count = 0;
|
16 |
+
$root = $this->getCon()->cache_dir_handler->dir();
|
17 |
+
if ( !empty( $root ) ) {
|
18 |
+
foreach ( $FS->getAllFilesInDir( $root ) as $fileItem ) {
|
19 |
+
if ( $FS->isDir( $fileItem ) ) {
|
20 |
+
$dirBase = basename( $fileItem );
|
21 |
+
if ( $dirBase === 'ptguard' ) {
|
22 |
+
$FS->deleteDir( $fileItem );
|
23 |
+
}
|
24 |
+
elseif ( preg_match( sprintf( '#^ptguard-[a-z0-9]{%s}$#i', StorageDir::SUFFIX_LENGTH ), $dirBase ) ) {
|
25 |
+
if ( empty( $firstAcceptableDir ) ) {
|
26 |
+
$firstAcceptableDir = $fileItem;
|
27 |
+
}
|
28 |
+
else {
|
29 |
+
$count++;
|
30 |
+
$FS->deleteDir( $fileItem );
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
if ( $count > $limit ) {
|
36 |
+
break;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
src/lib/src/Modules/HackGuard/ModCon.php
CHANGED
@@ -220,6 +220,10 @@ class ModCon extends BaseShield\ModCon {
|
|
220 |
->setMod( $this )
|
221 |
->cleanStaleHashesOlderThan( $carbon->subWeek()->timestamp );
|
222 |
}
|
|
|
|
|
|
|
|
|
223 |
}
|
224 |
|
225 |
/**
|
220 |
->setMod( $this )
|
221 |
->cleanStaleHashesOlderThan( $carbon->subWeek()->timestamp );
|
222 |
}
|
223 |
+
|
224 |
+
( new Lib\Utility\CleanOutOldGuardFiles() )
|
225 |
+
->setMod( $this )
|
226 |
+
->execute();
|
227 |
}
|
228 |
|
229 |
/**
|
src/lib/src/Modules/HackGuard/Upgrade.php
CHANGED
@@ -3,9 +3,23 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction\MoveHashFiles;
|
|
|
6 |
|
7 |
class Upgrade extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Upgrade {
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
protected function upgrade_1617() {
|
10 |
( new MoveHashFiles() )
|
11 |
->setMod( $this->getMod() )
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Snapshots\StoreAction\MoveHashFiles;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\Utility\CleanOutOldGuardFiles;
|
7 |
|
8 |
class Upgrade extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Upgrade {
|
9 |
|
10 |
+
/**
|
11 |
+
* Repairs the state where the PTGuard was recreating multiple directories for the ptguard files.
|
12 |
+
* Here we delete everything except the first valid PTGuard dir we find.
|
13 |
+
*
|
14 |
+
* Going forward from 16.1.14, we don't attempt to migrate. We should never have been repeatedly trying to migrate
|
15 |
+
* in the first place - it should have been an upgrade process.
|
16 |
+
*/
|
17 |
+
protected function upgrade_16114() {
|
18 |
+
( new CleanOutOldGuardFiles() )
|
19 |
+
->setMod( $this->getMod() )
|
20 |
+
->execute();
|
21 |
+
}
|
22 |
+
|
23 |
protected function upgrade_1617() {
|
24 |
( new MoveHashFiles() )
|
25 |
->setMod( $this->getMod() )
|
src/lib/src/Modules/IPs/Lib/CrowdSec/Signals/EventsToSignals.php
CHANGED
@@ -139,7 +139,7 @@ class EventsToSignals extends EventsListener {
|
|
139 |
'scenario' => 'btloginfail',
|
140 |
],
|
141 |
'bottrack_logininvalid' => [
|
142 |
-
'scenario' => '
|
143 |
],
|
144 |
'block_lostpassword' => [
|
145 |
'scenario' => 'lostpasswordfail',
|
@@ -149,7 +149,6 @@ class EventsToSignals extends EventsListener {
|
|
149 |
'scenario' => 'registerfail',
|
150 |
'only_send_on_notbot_fail' => true,
|
151 |
],
|
152 |
-
|
153 |
'bottrack_404' => [
|
154 |
'scenario' => 'bt404',
|
155 |
],
|
@@ -160,7 +159,7 @@ class EventsToSignals extends EventsListener {
|
|
160 |
'scenario' => 'btcheese',
|
161 |
],
|
162 |
'bottrack_invalidscript' => [
|
163 |
-
'scenario' => '
|
164 |
],
|
165 |
'bottrack_useragent' => [
|
166 |
'scenario' => 'btua',
|
139 |
'scenario' => 'btloginfail',
|
140 |
],
|
141 |
'bottrack_logininvalid' => [
|
142 |
+
'scenario' => 'btlogininvalid',
|
143 |
],
|
144 |
'block_lostpassword' => [
|
145 |
'scenario' => 'lostpasswordfail',
|
149 |
'scenario' => 'registerfail',
|
150 |
'only_send_on_notbot_fail' => true,
|
151 |
],
|
|
|
152 |
'bottrack_404' => [
|
153 |
'scenario' => 'bt404',
|
154 |
],
|
159 |
'scenario' => 'btcheese',
|
160 |
],
|
161 |
'bottrack_invalidscript' => [
|
162 |
+
'scenario' => 'btinvalidscript',
|
163 |
],
|
164 |
'bottrack_useragent' => [
|
165 |
'scenario' => 'btua',
|
src/lib/src/Modules/LoginGuard/Strings.php
CHANGED
@@ -186,7 +186,13 @@ class Strings extends Base\Strings {
|
|
186 |
$name = __( 'Hide WP Login & Admin', 'wp-simple-firewall' );
|
187 |
$summary = __( 'Hide The WordPress Login And Admin Areas', 'wp-simple-firewall' );
|
188 |
$desc = [
|
189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
sprintf( __( 'Only letters and numbers are permitted: %s', 'wp-simple-firewall' ), '<strong>abc123</strong>' ),
|
191 |
sprintf( __( 'Your current login URL is: %s', 'wp-simple-firewall' ), '<br /><strong> '.wp_login_url().'</strong>' )
|
192 |
];
|
@@ -196,14 +202,17 @@ class Strings extends Base\Strings {
|
|
196 |
$name = __( 'WP Login & Admin Redirect', 'wp-simple-firewall' );
|
197 |
$summary = __( 'Automatic Redirect URL For Hidden Pages', 'wp-simple-firewall' );
|
198 |
$desc = [
|
199 |
-
__( 'Automatically redirect
|
200 |
sprintf( '%s: %s',
|
201 |
__( 'Note', 'wp-simple-firewall' ),
|
202 |
-
__( 'Leave this blank to serve a standard "
|
203 |
),
|
204 |
sprintf( '%s: %s',
|
205 |
__( 'Important', 'wp-simple-firewall' ),
|
206 |
-
sprintf( __( 'Use relative paths e.g. %s redirects to your homepage.', 'wp-simple-firewall' ),
|
|
|
|
|
|
|
207 |
),
|
208 |
];
|
209 |
break;
|
186 |
$name = __( 'Hide WP Login & Admin', 'wp-simple-firewall' );
|
187 |
$summary = __( 'Hide The WordPress Login And Admin Areas', 'wp-simple-firewall' );
|
188 |
$desc = [
|
189 |
+
sprintf( '%s: %s',
|
190 |
+
__( 'Important', 'wp-simple-firewall' ),
|
191 |
+
sprintf( __( "This will cause %s and %s URLs to return HTTP 404 errors while you're not logged-in.", 'wp-simple-firewall' ),
|
192 |
+
'<code>/wp-admin/</code>',
|
193 |
+
'<code>/wp-login.php</code>'
|
194 |
+
)
|
195 |
+
),
|
196 |
sprintf( __( 'Only letters and numbers are permitted: %s', 'wp-simple-firewall' ), '<strong>abc123</strong>' ),
|
197 |
sprintf( __( 'Your current login URL is: %s', 'wp-simple-firewall' ), '<br /><strong> '.wp_login_url().'</strong>' )
|
198 |
];
|
202 |
$name = __( 'WP Login & Admin Redirect', 'wp-simple-firewall' );
|
203 |
$summary = __( 'Automatic Redirect URL For Hidden Pages', 'wp-simple-firewall' );
|
204 |
$desc = [
|
205 |
+
__( 'Automatically redirect here for any requests made to hidden pages.', 'wp-simple-firewall' ),
|
206 |
sprintf( '%s: %s',
|
207 |
__( 'Note', 'wp-simple-firewall' ),
|
208 |
+
sprintf( __( 'Leave this blank to serve a standard "%s" error page.', 'wp-simple-firewall' ), 'HTTP 404 Not Found' )
|
209 |
),
|
210 |
sprintf( '%s: %s',
|
211 |
__( 'Important', 'wp-simple-firewall' ),
|
212 |
+
sprintf( __( 'Use relative paths from your homepage URL e.g. %s redirects to your homepage (%s).', 'wp-simple-firewall' ),
|
213 |
+
'<code>/</code>',
|
214 |
+
sprintf( '<code>%s</code>', Services::WpGeneral()->getHomeUrl() )
|
215 |
+
)
|
216 |
),
|
217 |
];
|
218 |
break;
|
src/lib/src/Modules/Plugin/Lib/Debug/Collate.php
CHANGED
@@ -59,8 +59,8 @@ class Collate {
|
|
59 |
}
|
60 |
}
|
61 |
|
62 |
-
$totalDisk = disk_total_space( ABSPATH );
|
63 |
-
$freeDisk = disk_free_space( ABSPATH );
|
64 |
try {
|
65 |
$diff = ( new WorldTimeApi() )->diffServerWithReal();
|
66 |
}
|
@@ -78,10 +78,10 @@ class Collate {
|
|
78 |
'Server Name' => $req->server( 'SERVER_NAME' ),
|
79 |
'Server Signature' => empty( $sig ) ? '-' : $sig,
|
80 |
'Server Software' => empty( $soft ) ? '-' : $soft,
|
81 |
-
'Disk Space
|
82 |
-
FormatBytes::Format( $totalDisk - $freeDisk, 2, '' ),
|
83 |
-
FormatBytes::Format( $totalDisk, 2, '' ),
|
84 |
-
FormatBytes::Format( $freeDisk, 2, '' )
|
85 |
)
|
86 |
];
|
87 |
}
|
59 |
}
|
60 |
}
|
61 |
|
62 |
+
$totalDisk = function_exists( '\disk_total_space' ) ? \disk_total_space( ABSPATH ) : '-';
|
63 |
+
$freeDisk = function_exists( '\disk_free_space' ) ? \disk_free_space( ABSPATH ) : '-';
|
64 |
try {
|
65 |
$diff = ( new WorldTimeApi() )->diffServerWithReal();
|
66 |
}
|
78 |
'Server Name' => $req->server( 'SERVER_NAME' ),
|
79 |
'Server Signature' => empty( $sig ) ? '-' : $sig,
|
80 |
'Server Software' => empty( $soft ) ? '-' : $soft,
|
81 |
+
'Disk Space' => sprintf( '%s used out of %s (unused: %s)',
|
82 |
+
( is_numeric( $totalDisk ) && is_numeric( $freeDisk ) ) ? FormatBytes::Format( $totalDisk - $freeDisk, 2, '' ) : '-',
|
83 |
+
is_numeric( $totalDisk ) ? FormatBytes::Format( $totalDisk, 2, '' ) : '-',
|
84 |
+
is_numeric( $freeDisk ) ? FormatBytes::Format( $freeDisk, 2, '' ) : '-'
|
85 |
)
|
86 |
];
|
87 |
}
|
src/lib/src/Modules/UserManagement/Lib/Session/FindSessions.php
CHANGED
@@ -10,12 +10,12 @@ class FindSessions {
|
|
10 |
use ModConsumer;
|
11 |
|
12 |
public function mostRecent() :array {
|
13 |
-
return $this->lookupFromUserMeta();
|
14 |
}
|
15 |
|
16 |
public function byIP( string $ip ) :array {
|
17 |
$sessions = [];
|
18 |
-
foreach ( $this->lookupFromUserMeta( $ip ) as $userID => $userAtIP ) {
|
19 |
$sessions[ $userID ] = array_map(
|
20 |
function ( $sess ) use ( $userAtIP ) {
|
21 |
$sess[ 'user_login' ] = $userAtIP[ 'user_login' ];
|
@@ -27,14 +27,9 @@ class FindSessions {
|
|
27 |
return $sessions;
|
28 |
}
|
29 |
|
30 |
-
public function lookupFromUserMeta(
|
31 |
$modData = $this->getCon()->getModule_Data();
|
32 |
|
33 |
-
$wheres = [];
|
34 |
-
if ( !empty( $ip ) ) {
|
35 |
-
$wheres[] = sprintf( "`ips`.ip=INET6_ATON('%s')", $ip );
|
36 |
-
}
|
37 |
-
|
38 |
$DB = Services::WpDb();
|
39 |
$results = $DB->selectCustom(
|
40 |
sprintf( 'SELECT `user_meta`.user_id as user_id,
|
@@ -66,4 +61,8 @@ class FindSessions {
|
|
66 |
|
67 |
return $byUserIDs;
|
68 |
}
|
|
|
|
|
|
|
|
|
69 |
}
|
10 |
use ModConsumer;
|
11 |
|
12 |
public function mostRecent() :array {
|
13 |
+
return $this->lookupFromUserMeta( [ "`user_meta`.`last_login_at`!=0" ] );
|
14 |
}
|
15 |
|
16 |
public function byIP( string $ip ) :array {
|
17 |
$sessions = [];
|
18 |
+
foreach ( $this->lookupFromUserMeta( [ $this->getWhere_IPEquals( $ip ) ] ) as $userID => $userAtIP ) {
|
19 |
$sessions[ $userID ] = array_map(
|
20 |
function ( $sess ) use ( $userAtIP ) {
|
21 |
$sess[ 'user_login' ] = $userAtIP[ 'user_login' ];
|
27 |
return $sessions;
|
28 |
}
|
29 |
|
30 |
+
public function lookupFromUserMeta( array $wheres = [], int $limit = 10, string $orderBy = '`user_meta`.`last_login_at`' ) :array {
|
31 |
$modData = $this->getCon()->getModule_Data();
|
32 |
|
|
|
|
|
|
|
|
|
|
|
33 |
$DB = Services::WpDb();
|
34 |
$results = $DB->selectCustom(
|
35 |
sprintf( 'SELECT `user_meta`.user_id as user_id,
|
61 |
|
62 |
return $byUserIDs;
|
63 |
}
|
64 |
+
|
65 |
+
private function getWhere_IPEquals( string $ip ) :string {
|
66 |
+
return sprintf( "`ips`.ip=INET6_ATON('%s')", $ip );
|
67 |
+
}
|
68 |
}
|
src/lib/src/Modules/UserManagement/Lib/Suspend/UserSuspendController.php
CHANGED
@@ -83,127 +83,90 @@ class UserSuspendController extends ExecOnceModConsumer {
|
|
83 |
/** @var Select $metaSelect */
|
84 |
$metaSelect = $userMetaDB->getQuerySelector();
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
$manual = array_diff( $manual, $cleaned );
|
137 |
-
$passwords = array_diff( $passwords, $cleaned );
|
138 |
-
$idle = array_diff( $idle, $cleaned );
|
139 |
-
}
|
140 |
-
|
141 |
-
// Filter the user list database query
|
142 |
-
add_filter( 'users_list_table_query_args', function ( $args ) use ( $manual, $idle, $passwords ) {
|
143 |
-
$req = Services::Request();
|
144 |
-
if ( is_array( $args ) ) {
|
145 |
-
if ( !empty( $manual ) && $req->query( 'shield_users_suspended' ) ) {
|
146 |
-
$args[ 'include' ] = $manual;
|
147 |
}
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
}
|
154 |
-
}
|
155 |
-
return $args;
|
156 |
-
} );
|
157 |
-
|
158 |
-
// Provide the links above the table.
|
159 |
-
add_filter( 'views_users', function ( $views ) use ( $manual, $idle, $passwords ) {
|
160 |
-
$WP = Services::WpGeneral();
|
161 |
-
if ( !empty( $manual ) ) {
|
162 |
-
$views[ 'shield_users_suspended' ] = sprintf(
|
163 |
-
'<a href="%s">%s <span class="count">(%s)</span></a>',
|
164 |
-
URL::Build( $WP->getUrl_CurrentAdminPage(), [ 'shield_users_suspended' => 1 ] ),
|
165 |
-
__( 'Manually Suspended', 'wp-simple-firewall' ), count( $manual )
|
166 |
-
);
|
167 |
-
}
|
168 |
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
if ( !empty( $passwords ) ) {
|
178 |
-
$views[ 'shield_users_pass' ] = sprintf(
|
179 |
-
'<a href="%s">%s <span class="count">(%s)</span></a>',
|
180 |
-
URL::Build( $WP->getUrl_CurrentAdminPage(), [ 'shield_users_pass' => 1 ] ),
|
181 |
-
__( 'Password Expired', 'wp-simple-firewall' ), count( $passwords )
|
182 |
-
);
|
183 |
-
}
|
184 |
|
185 |
-
|
186 |
-
|
187 |
-
|
|
|
|
|
|
|
|
|
188 |
|
189 |
-
|
190 |
-
|
191 |
-
array_unique( $IDs ),
|
192 |
-
function ( $userID ) {
|
193 |
-
return empty( Services::WpUsers()->getUserById( (int)$userID ) );
|
194 |
-
}
|
195 |
-
);
|
196 |
-
|
197 |
-
if ( !empty( $toClean ) ) {
|
198 |
-
$this->getCon()
|
199 |
-
->getModule_Data()
|
200 |
-
->getDbH_UserMeta()
|
201 |
-
->getQueryDeleter()
|
202 |
-
->addWhereIn( 'user_id', $toClean )
|
203 |
-
->query();
|
204 |
}
|
205 |
-
|
206 |
-
return $toClean;
|
207 |
}
|
208 |
|
209 |
public function addUserBlockOption( \WP_User $user ) {
|
83 |
/** @var Select $metaSelect */
|
84 |
$metaSelect = $userMetaDB->getQuerySelector();
|
85 |
|
86 |
+
$manual = $opts->isSuspendManualEnabled() ? $metaSelect->reset()->filterByHardSuspended()->count() : 0;
|
87 |
+
$passwords = $opts->isSuspendAutoPasswordEnabled() ?
|
88 |
+
$metaSelect->reset()->filterByPassExpired( $ts - $opts->getPassExpireTimeout() )->count() : 0;
|
89 |
+
$idle = $opts->isSuspendAutoPasswordEnabled() ?
|
90 |
+
$metaSelect->reset()->filterByPassExpired( $ts - $opts->getSuspendAutoIdleTime() )->count() : 0;
|
91 |
+
|
92 |
+
if ( $manual + $passwords + $idle > 0 ) {
|
93 |
+
// Filter the user list database query
|
94 |
+
add_filter( 'users_list_table_query_args', function ( $args ) use ( $manual, $idle, $passwords ) {
|
95 |
+
$req = Services::Request();
|
96 |
+
if ( is_array( $args ) ) {
|
97 |
+
/** @var UserManagement\Options $opts */
|
98 |
+
$opts = $this->getOptions();
|
99 |
+
|
100 |
+
/** @var Select $metaSelect */
|
101 |
+
$metaSelect = $this->getCon()
|
102 |
+
->getModule_Data()
|
103 |
+
->getDbH_UserMeta()
|
104 |
+
->getQuerySelector();
|
105 |
+
|
106 |
+
if ( $manual > 0 && $req->query( 'shield_users_suspended' ) ) {
|
107 |
+
$filtered = true;
|
108 |
+
$metaSelect->filterByHardSuspended();
|
109 |
+
}
|
110 |
+
elseif ( $idle > 0 && $req->query( 'shield_users_idle' ) ) {
|
111 |
+
$filtered = true;
|
112 |
+
$metaSelect->filterByPassExpired( Services::Request()->ts() - $opts->getPassExpireTimeout() );
|
113 |
+
}
|
114 |
+
elseif ( $passwords > 0 && $req->query( 'shield_users_pass' ) ) {
|
115 |
+
$filtered = true;
|
116 |
+
$metaSelect->filterByIdle( Services::Request()->ts() - $opts->getSuspendAutoIdleTime() );
|
117 |
+
}
|
118 |
+
else {
|
119 |
+
$filtered = false;
|
120 |
+
}
|
121 |
+
|
122 |
+
if ( $filtered ) {
|
123 |
+
$idsToInclude = array_map(
|
124 |
+
function ( $res ) {
|
125 |
+
return (int)array_pop( $res );
|
126 |
+
},
|
127 |
+
$metaSelect->setResultsAsVo( false )
|
128 |
+
->setSelectResultsFormat( ARRAY_A )
|
129 |
+
->setColumnsToSelect( [ 'user_id' ] )
|
130 |
+
->queryWithResult()
|
131 |
+
);
|
132 |
+
if ( !empty( $idsToInclude ) ) {
|
133 |
+
$args[ 'include' ] = $idsToInclude;
|
134 |
+
}
|
135 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
137 |
+
return $args;
|
138 |
+
} );
|
139 |
+
|
140 |
+
// Provide the links above the table.
|
141 |
+
add_filter( 'views_users', function ( $views ) use ( $manual, $idle, $passwords ) {
|
142 |
+
$WP = Services::WpGeneral();
|
143 |
+
if ( $manual > 0 ) {
|
144 |
+
$views[ 'shield_users_suspended' ] = sprintf(
|
145 |
+
'<a href="%s">%s <span class="count">(%s)</span></a>',
|
146 |
+
URL::Build( $WP->getUrl_CurrentAdminPage(), [ 'shield_users_suspended' => 1 ] ),
|
147 |
+
__( 'Manually Suspended', 'wp-simple-firewall' ), $manual
|
148 |
+
);
|
149 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
+
if ( $idle > 0 ) {
|
152 |
+
$views[ 'shield_idle_users' ] = sprintf(
|
153 |
+
'<a href="%s">%s <span class="count">(%s)</span></a>',
|
154 |
+
URL::Build( $WP->getUrl_CurrentAdminPage(), [ 'shield_users_idle' => 1 ] ),
|
155 |
+
__( 'Idle', 'wp-simple-firewall' ), $idle
|
156 |
+
);
|
157 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
+
if ( $passwords > 0 ) {
|
160 |
+
$views[ 'shield_users_pass' ] = sprintf(
|
161 |
+
'<a href="%s">%s <span class="count">(%s)</span></a>',
|
162 |
+
URL::Build( $WP->getUrl_CurrentAdminPage(), [ 'shield_users_pass' => 1 ] ),
|
163 |
+
__( 'Password Expired', 'wp-simple-firewall' ), $passwords
|
164 |
+
);
|
165 |
+
}
|
166 |
|
167 |
+
return $views;
|
168 |
+
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
}
|
|
|
|
|
170 |
}
|
171 |
|
172 |
public function addUserBlockOption( \WP_User $user ) {
|
src/lib/vendor/composer/autoload_classmap.php
CHANGED
@@ -452,6 +452,7 @@ return array(
|
|
452 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromDir' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromDir.php',
|
453 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\CrowdSourced\\SubmitHashes' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/CrowdSourced/SubmitHashes.php',
|
454 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\FindAssetsToSnap' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/FindAssetsToSnap.php',
|
|
|
455 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Store' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Store.php',
|
456 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Base' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Base.php',
|
457 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\BaseAction' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/BaseAction.php',
|
452 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromDir' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromDir.php',
|
453 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\CrowdSourced\\SubmitHashes' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/CrowdSourced/SubmitHashes.php',
|
454 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\FindAssetsToSnap' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/FindAssetsToSnap.php',
|
455 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StorageDir' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StorageDir.php',
|
456 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Store' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/Store.php',
|
457 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Base' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Base.php',
|
458 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\BaseAction' => $baseDir . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/BaseAction.php',
|
src/lib/vendor/composer/autoload_static.php
CHANGED
@@ -647,6 +647,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
647 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromDir' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromDir.php',
|
648 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\CrowdSourced\\SubmitHashes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/CrowdSourced/SubmitHashes.php',
|
649 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\FindAssetsToSnap' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/FindAssetsToSnap.php',
|
|
|
650 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Store' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Store.php',
|
651 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Base' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Base.php',
|
652 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\BaseAction' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/BaseAction.php',
|
647 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Build\\BuildHashesFromDir' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Build/BuildHashesFromDir.php',
|
648 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\CrowdSourced\\SubmitHashes' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/CrowdSourced/SubmitHashes.php',
|
649 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\FindAssetsToSnap' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/FindAssetsToSnap.php',
|
650 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StorageDir' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StorageDir.php',
|
651 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\Store' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/Store.php',
|
652 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\Base' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Base.php',
|
653 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\HackGuard\\Lib\\Snapshots\\StoreAction\\BaseAction' => __DIR__ . '/../..' . '/src/Modules/HackGuard/Lib/Snapshots/StoreAction/BaseAction.php',
|
src/lib/vendor/composer/installed.json
CHANGED
@@ -245,17 +245,17 @@
|
|
245 |
},
|
246 |
{
|
247 |
"name": "fernleafsystems/wordpress-plugin-core",
|
248 |
-
"version": "1.1.
|
249 |
-
"version_normalized": "1.1.
|
250 |
"source": {
|
251 |
"type": "git",
|
252 |
"url": "git@gitlab.com:fernleafsystems/wordpress/wordpress-plugin-core.git",
|
253 |
-
"reference": "
|
254 |
},
|
255 |
"dist": {
|
256 |
"type": "zip",
|
257 |
-
"url": "https://gitlab.com/api/v4/projects/fernleafsystems%2Fwordpress%2Fwordpress-plugin-core/repository/archive.zip?sha=
|
258 |
-
"reference": "
|
259 |
"shasum": ""
|
260 |
},
|
261 |
"require": {
|
@@ -265,7 +265,7 @@
|
|
265 |
"nullpunkt/lz-string-php": "^1.3",
|
266 |
"php": ">=7.0"
|
267 |
},
|
268 |
-
"time": "2022-
|
269 |
"type": "library",
|
270 |
"installation-source": "dist",
|
271 |
"autoload": {
|
245 |
},
|
246 |
{
|
247 |
"name": "fernleafsystems/wordpress-plugin-core",
|
248 |
+
"version": "1.1.1",
|
249 |
+
"version_normalized": "1.1.1.0",
|
250 |
"source": {
|
251 |
"type": "git",
|
252 |
"url": "git@gitlab.com:fernleafsystems/wordpress/wordpress-plugin-core.git",
|
253 |
+
"reference": "8156e7de0ea7315dfa6f9b6ddd9e47e2806dd928"
|
254 |
},
|
255 |
"dist": {
|
256 |
"type": "zip",
|
257 |
+
"url": "https://gitlab.com/api/v4/projects/fernleafsystems%2Fwordpress%2Fwordpress-plugin-core/repository/archive.zip?sha=8156e7de0ea7315dfa6f9b6ddd9e47e2806dd928",
|
258 |
+
"reference": "8156e7de0ea7315dfa6f9b6ddd9e47e2806dd928",
|
259 |
"shasum": ""
|
260 |
},
|
261 |
"require": {
|
265 |
"nullpunkt/lz-string-php": "^1.3",
|
266 |
"php": ">=7.0"
|
267 |
},
|
268 |
+
"time": "2022-10-28T12:25:35+00:00",
|
269 |
"type": "library",
|
270 |
"installation-source": "dist",
|
271 |
"autoload": {
|
src/lib/vendor/composer/installed.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php return array(
|
2 |
'root' => array(
|
3 |
-
'pretty_version' => 'dev-
|
4 |
-
'version' => 'dev-
|
5 |
'type' => 'library',
|
6 |
'install_path' => __DIR__ . '/../../',
|
7 |
'aliases' => array(),
|
8 |
-
'reference' => '
|
9 |
'name' => 'apto-shield/requirements',
|
10 |
'dev' => true,
|
11 |
),
|
@@ -20,12 +20,12 @@
|
|
20 |
'dev_requirement' => false,
|
21 |
),
|
22 |
'apto-shield/requirements' => array(
|
23 |
-
'pretty_version' => 'dev-
|
24 |
-
'version' => 'dev-
|
25 |
'type' => 'library',
|
26 |
'install_path' => __DIR__ . '/../../',
|
27 |
'aliases' => array(),
|
28 |
-
'reference' => '
|
29 |
'dev_requirement' => false,
|
30 |
),
|
31 |
'christian-riesen/base32' => array(
|
@@ -65,12 +65,12 @@
|
|
65 |
'dev_requirement' => false,
|
66 |
),
|
67 |
'fernleafsystems/wordpress-plugin-core' => array(
|
68 |
-
'pretty_version' => '1.1.
|
69 |
-
'version' => '1.1.
|
70 |
'type' => 'library',
|
71 |
'install_path' => __DIR__ . '/../fernleafsystems/wordpress-plugin-core',
|
72 |
'aliases' => array(),
|
73 |
-
'reference' => '
|
74 |
'dev_requirement' => false,
|
75 |
),
|
76 |
'fernleafsystems/wordpress-services' => array(
|
1 |
<?php return array(
|
2 |
'root' => array(
|
3 |
+
'pretty_version' => 'dev-develop',
|
4 |
+
'version' => 'dev-develop',
|
5 |
'type' => 'library',
|
6 |
'install_path' => __DIR__ . '/../../',
|
7 |
'aliases' => array(),
|
8 |
+
'reference' => '936fbb48ff742962d5034676fa847161e34d202c',
|
9 |
'name' => 'apto-shield/requirements',
|
10 |
'dev' => true,
|
11 |
),
|
20 |
'dev_requirement' => false,
|
21 |
),
|
22 |
'apto-shield/requirements' => array(
|
23 |
+
'pretty_version' => 'dev-develop',
|
24 |
+
'version' => 'dev-develop',
|
25 |
'type' => 'library',
|
26 |
'install_path' => __DIR__ . '/../../',
|
27 |
'aliases' => array(),
|
28 |
+
'reference' => '936fbb48ff742962d5034676fa847161e34d202c',
|
29 |
'dev_requirement' => false,
|
30 |
),
|
31 |
'christian-riesen/base32' => array(
|
65 |
'dev_requirement' => false,
|
66 |
),
|
67 |
'fernleafsystems/wordpress-plugin-core' => array(
|
68 |
+
'pretty_version' => '1.1.1',
|
69 |
+
'version' => '1.1.1.0',
|
70 |
'type' => 'library',
|
71 |
'install_path' => __DIR__ . '/../fernleafsystems/wordpress-plugin-core',
|
72 |
'aliases' => array(),
|
73 |
+
'reference' => '8156e7de0ea7315dfa6f9b6ddd9e47e2806dd928',
|
74 |
'dev_requirement' => false,
|
75 |
),
|
76 |
'fernleafsystems/wordpress-services' => array(
|
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/BaseQuery.php
CHANGED
@@ -55,11 +55,6 @@ abstract class BaseQuery {
|
|
55 |
protected function customInit() {
|
56 |
}
|
57 |
|
58 |
-
/**
|
59 |
-
* @param string $columnLeft
|
60 |
-
* @param string $columnRight
|
61 |
-
* @param string $operator
|
62 |
-
*/
|
63 |
public function addWhereCompareColumns( string $columnLeft, string $columnRight, string $operator = '=' ) {
|
64 |
$schema = $this->getDbH()->getTableSchema();
|
65 |
if ( !$schema->hasColumn( $columnLeft ) ) {
|
@@ -73,9 +68,7 @@ abstract class BaseQuery {
|
|
73 |
}
|
74 |
|
75 |
/**
|
76 |
-
* @param string $column
|
77 |
* @param string|array $value
|
78 |
-
* @param string $operator
|
79 |
* @return $this
|
80 |
*/
|
81 |
public function addWhere( string $column, $value, string $operator = '=' ) {
|
@@ -104,7 +97,6 @@ abstract class BaseQuery {
|
|
104 |
}
|
105 |
|
106 |
/**
|
107 |
-
* @param array $where
|
108 |
* @return $this
|
109 |
*/
|
110 |
public function addRawWhere( array $where ) {
|
@@ -114,7 +106,6 @@ abstract class BaseQuery {
|
|
114 |
}
|
115 |
|
116 |
/**
|
117 |
-
* @param string $column
|
118 |
* @param mixed $mValue
|
119 |
* @return $this
|
120 |
*/
|
@@ -123,7 +114,6 @@ abstract class BaseQuery {
|
|
123 |
}
|
124 |
|
125 |
/**
|
126 |
-
* @param string $column
|
127 |
* @param array $values
|
128 |
* @return $this
|
129 |
*/
|
@@ -135,7 +125,6 @@ abstract class BaseQuery {
|
|
135 |
}
|
136 |
|
137 |
/**
|
138 |
-
* @param string $column
|
139 |
* @param array $values
|
140 |
* @return $this
|
141 |
*/
|
@@ -147,7 +136,6 @@ abstract class BaseQuery {
|
|
147 |
}
|
148 |
|
149 |
/**
|
150 |
-
* @param string $column
|
151 |
* @param string $like
|
152 |
* @param string $left
|
153 |
* @param string $right
|
@@ -215,7 +203,7 @@ abstract class BaseQuery {
|
|
215 |
* @return int
|
216 |
*/
|
217 |
protected function getOffset() {
|
218 |
-
return
|
219 |
}
|
220 |
|
221 |
public function buildWhere() :string {
|
@@ -262,7 +250,6 @@ abstract class BaseQuery {
|
|
262 |
}
|
263 |
|
264 |
/**
|
265 |
-
* @param int $ts
|
266 |
* @return $this
|
267 |
*/
|
268 |
public function filterByBoundary_Day( int $ts ) {
|
@@ -271,7 +258,6 @@ abstract class BaseQuery {
|
|
271 |
}
|
272 |
|
273 |
/**
|
274 |
-
* @param int $ts
|
275 |
* @return $this
|
276 |
*/
|
277 |
public function filterByBoundary_Hour( int $ts ) {
|
@@ -280,7 +266,6 @@ abstract class BaseQuery {
|
|
280 |
}
|
281 |
|
282 |
/**
|
283 |
-
* @param int $ts
|
284 |
* @return $this
|
285 |
*/
|
286 |
public function filterByBoundary_Month( int $ts ) {
|
@@ -289,7 +274,6 @@ abstract class BaseQuery {
|
|
289 |
}
|
290 |
|
291 |
/**
|
292 |
-
* @param int $ts
|
293 |
* @return $this
|
294 |
*/
|
295 |
public function filterByBoundary_Week( int $ts ) {
|
@@ -298,7 +282,6 @@ abstract class BaseQuery {
|
|
298 |
}
|
299 |
|
300 |
/**
|
301 |
-
* @param int $ts
|
302 |
* @return $this
|
303 |
*/
|
304 |
public function filterByBoundary_Year( int $ts ) {
|
@@ -307,7 +290,6 @@ abstract class BaseQuery {
|
|
307 |
}
|
308 |
|
309 |
/**
|
310 |
-
* @param array $ids
|
311 |
* @return $this
|
312 |
*/
|
313 |
public function filterByIDs( array $ids ) {
|
55 |
protected function customInit() {
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
58 |
public function addWhereCompareColumns( string $columnLeft, string $columnRight, string $operator = '=' ) {
|
59 |
$schema = $this->getDbH()->getTableSchema();
|
60 |
if ( !$schema->hasColumn( $columnLeft ) ) {
|
68 |
}
|
69 |
|
70 |
/**
|
|
|
71 |
* @param string|array $value
|
|
|
72 |
* @return $this
|
73 |
*/
|
74 |
public function addWhere( string $column, $value, string $operator = '=' ) {
|
97 |
}
|
98 |
|
99 |
/**
|
|
|
100 |
* @return $this
|
101 |
*/
|
102 |
public function addRawWhere( array $where ) {
|
106 |
}
|
107 |
|
108 |
/**
|
|
|
109 |
* @param mixed $mValue
|
110 |
* @return $this
|
111 |
*/
|
114 |
}
|
115 |
|
116 |
/**
|
|
|
117 |
* @param array $values
|
118 |
* @return $this
|
119 |
*/
|
125 |
}
|
126 |
|
127 |
/**
|
|
|
128 |
* @param array $values
|
129 |
* @return $this
|
130 |
*/
|
136 |
}
|
137 |
|
138 |
/**
|
|
|
139 |
* @param string $like
|
140 |
* @param string $left
|
141 |
* @param string $right
|
203 |
* @return int
|
204 |
*/
|
205 |
protected function getOffset() {
|
206 |
+
return $this->getLimit()*( $this->getPage() - 1 );
|
207 |
}
|
208 |
|
209 |
public function buildWhere() :string {
|
250 |
}
|
251 |
|
252 |
/**
|
|
|
253 |
* @return $this
|
254 |
*/
|
255 |
public function filterByBoundary_Day( int $ts ) {
|
258 |
}
|
259 |
|
260 |
/**
|
|
|
261 |
* @return $this
|
262 |
*/
|
263 |
public function filterByBoundary_Hour( int $ts ) {
|
266 |
}
|
267 |
|
268 |
/**
|
|
|
269 |
* @return $this
|
270 |
*/
|
271 |
public function filterByBoundary_Month( int $ts ) {
|
274 |
}
|
275 |
|
276 |
/**
|
|
|
277 |
* @return $this
|
278 |
*/
|
279 |
public function filterByBoundary_Week( int $ts ) {
|
282 |
}
|
283 |
|
284 |
/**
|
|
|
285 |
* @return $this
|
286 |
*/
|
287 |
public function filterByBoundary_Year( int $ts ) {
|
290 |
}
|
291 |
|
292 |
/**
|
|
|
293 |
* @return $this
|
294 |
*/
|
295 |
public function filterByIDs( array $ids ) {
|
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Delete.php
CHANGED
@@ -26,13 +26,11 @@ class Delete extends BaseQuery {
|
|
26 |
$success = $updater->query();
|
27 |
$this->lastQueryResult = $updater->getLastQueryResult();
|
28 |
}
|
|
|
|
|
|
|
29 |
else {
|
30 |
-
|
31 |
-
error_log( sprintf( 'Attempt to DELETE with empty WHERE with query: "%s"', $this->buildQuery() ) );
|
32 |
-
}
|
33 |
-
else {
|
34 |
-
$success = parent::execQuerySql();
|
35 |
-
}
|
36 |
}
|
37 |
return $success;
|
38 |
}
|
26 |
$success = $updater->query();
|
27 |
$this->lastQueryResult = $updater->getLastQueryResult();
|
28 |
}
|
29 |
+
elseif ( empty( $this->buildWhere() ) && !$this->allowEmptyWhere ) {
|
30 |
+
error_log( sprintf( 'Attempt to DELETE with empty WHERE with query: "%s"', $this->buildQuery() ) );
|
31 |
+
}
|
32 |
else {
|
33 |
+
$success = parent::execQuerySql();
|
|
|
|
|
|
|
|
|
|
|
34 |
}
|
35 |
return $success;
|
36 |
}
|
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Insert.php
CHANGED
@@ -70,7 +70,7 @@ class Insert extends BaseQuery {
|
|
70 |
*/
|
71 |
public function setInsertData( array $data ) {
|
72 |
$this->insertData = array_intersect_key(
|
73 |
-
|
74 |
array_flip( $this->getDbH()->getTableSchema()->getColumnNames() )
|
75 |
);
|
76 |
return $this;
|
70 |
*/
|
71 |
public function setInsertData( array $data ) {
|
72 |
$this->insertData = array_intersect_key(
|
73 |
+
$data,
|
74 |
array_flip( $this->getDbH()->getTableSchema()->getColumnNames() )
|
75 |
);
|
76 |
return $this;
|
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Base/Update.php
CHANGED
@@ -93,11 +93,9 @@ class Update extends Insert {
|
|
93 |
}
|
94 |
|
95 |
/**
|
96 |
-
* @param int $id
|
97 |
-
* @param array $updateData
|
98 |
* @return bool true is success or no update necessary
|
99 |
*/
|
100 |
-
public function updateById( int $id, array $updateData = [] ) {
|
101 |
return $this->setUpdateId( $id )
|
102 |
->setUpdateData( $updateData )
|
103 |
->query();
|
93 |
}
|
94 |
|
95 |
/**
|
|
|
|
|
96 |
* @return bool true is success or no update necessary
|
97 |
*/
|
98 |
+
public function updateById( int $id, array $updateData = [] ) :bool {
|
99 |
return $this->setUpdateId( $id )
|
100 |
->setUpdateData( $updateData )
|
101 |
->query();
|
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Common/Iterator.php
CHANGED
@@ -8,9 +8,10 @@ use FernleafSystems\Wordpress\Plugin\Core\Databases\Base\Select;
|
|
8 |
|
9 |
class Iterator extends AbstractPagedIterator {
|
10 |
|
11 |
-
const PAGE_LIMIT = 50;
|
12 |
use HandlerConsumer;
|
13 |
|
|
|
|
|
14 |
/**
|
15 |
* @var Select|mixed
|
16 |
*/
|
@@ -53,13 +54,13 @@ class Iterator extends AbstractPagedIterator {
|
|
53 |
* @return array
|
54 |
*/
|
55 |
public function getPage( $page ) {
|
56 |
-
$
|
57 |
|
58 |
$this->getSelector()
|
59 |
->setResultsAsVo( true )
|
60 |
->setPage( $page + 1 ) // Pages start at 1, not zero.
|
61 |
->setLimit( $this->getPageSize() )
|
62 |
-
->setOrderBy( $
|
63 |
|
64 |
return $this->runQuery();
|
65 |
}
|
@@ -95,11 +96,11 @@ class Iterator extends AbstractPagedIterator {
|
|
95 |
* @return Record[]|mixed[]
|
96 |
*/
|
97 |
protected function runQuery() {
|
98 |
-
return ( clone $this->getSelector() )->
|
99 |
}
|
100 |
|
101 |
protected function runQueryCount() :int {
|
102 |
-
return (
|
103 |
}
|
104 |
|
105 |
/**
|
8 |
|
9 |
class Iterator extends AbstractPagedIterator {
|
10 |
|
|
|
11 |
use HandlerConsumer;
|
12 |
|
13 |
+
const PAGE_LIMIT = 50;
|
14 |
+
|
15 |
/**
|
16 |
* @var Select|mixed
|
17 |
*/
|
54 |
* @return array
|
55 |
*/
|
56 |
public function getPage( $page ) {
|
57 |
+
$params = $this->getFinalQueryFilters();
|
58 |
|
59 |
$this->getSelector()
|
60 |
->setResultsAsVo( true )
|
61 |
->setPage( $page + 1 ) // Pages start at 1, not zero.
|
62 |
->setLimit( $this->getPageSize() )
|
63 |
+
->setOrderBy( $params[ 'orderby' ], $params[ 'order' ] );
|
64 |
|
65 |
return $this->runQuery();
|
66 |
}
|
96 |
* @return Record[]|mixed[]
|
97 |
*/
|
98 |
protected function runQuery() {
|
99 |
+
return ( clone $this->getSelector() )->queryWithResult();
|
100 |
}
|
101 |
|
102 |
protected function runQueryCount() :int {
|
103 |
+
return ( clone $this->getSelector() )->count();
|
104 |
}
|
105 |
|
106 |
/**
|
src/lib/vendor/fernleafsystems/wordpress-plugin-core/src/Databases/Common/SubQueryLoader.php
CHANGED
@@ -18,7 +18,7 @@ class SubQueryLoader {
|
|
18 |
|
19 |
public function loadClass( string $class ) {
|
20 |
/** @var BaseQuery $o */
|
21 |
-
$o = new $class;
|
22 |
return method_exists( $o, 'setDbH' ) ? $o->setDbH( $this->getDbHandler() ) : $o;
|
23 |
}
|
24 |
|
18 |
|
19 |
public function loadClass( string $class ) {
|
20 |
/** @var BaseQuery $o */
|
21 |
+
$o = new $class();
|
22 |
return method_exists( $o, 'setDbH' ) ? $o->setDbH( $this->getDbHandler() ) : $o;
|
23 |
}
|
24 |
|
src/lib/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of the Monolog package.
|
5 |
+
*
|
6 |
+
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace Monolog\Handler;
|
13 |
+
|
14 |
+
use Monolog\Logger;
|
15 |
+
use Monolog\ResettableInterface;
|
16 |
+
use Monolog\Formatter\FormatterInterface;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Buffers all records until closing the handler and then pass them as batch.
|
20 |
+
*
|
21 |
+
* This is useful for a MailHandler to send only one mail per request instead of
|
22 |
+
* sending one per log message.
|
23 |
+
*
|
24 |
+
* @author Christophe Coevoet <stof@notk.org>
|
25 |
+
*/
|
26 |
+
class BufferHandler extends AbstractHandler
|
27 |
+
{
|
28 |
+
protected $handler;
|
29 |
+
protected $bufferSize = 0;
|
30 |
+
protected $bufferLimit;
|
31 |
+
protected $flushOnOverflow;
|
32 |
+
protected $buffer = array();
|
33 |
+
protected $initialized = false;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @param HandlerInterface $handler Handler.
|
37 |
+
* @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
|
38 |
+
* @param int $level The minimum logging level at which this handler will be triggered
|
39 |
+
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
40 |
+
* @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
|
41 |
+
*/
|
42 |
+
public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
|
43 |
+
{
|
44 |
+
parent::__construct($level, $bubble);
|
45 |
+
$this->handler = $handler;
|
46 |
+
$this->bufferLimit = (int) $bufferLimit;
|
47 |
+
$this->flushOnOverflow = $flushOnOverflow;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* {@inheritdoc}
|
52 |
+
*/
|
53 |
+
public function handle(array $record)
|
54 |
+
{
|
55 |
+
if ($record['level'] < $this->level) {
|
56 |
+
return false;
|
57 |
+
}
|
58 |
+
|
59 |
+
if (!$this->initialized) {
|
60 |
+
// __destructor() doesn't get called on Fatal errors
|
61 |
+
register_shutdown_function(array($this, 'close'));
|
62 |
+
$this->initialized = true;
|
63 |
+
}
|
64 |
+
|
65 |
+
if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
|
66 |
+
if ($this->flushOnOverflow) {
|
67 |
+
$this->flush();
|
68 |
+
} else {
|
69 |
+
array_shift($this->buffer);
|
70 |
+
$this->bufferSize--;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
if ($this->processors) {
|
75 |
+
foreach ($this->processors as $processor) {
|
76 |
+
$record = call_user_func($processor, $record);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
$this->buffer[] = $record;
|
81 |
+
$this->bufferSize++;
|
82 |
+
|
83 |
+
return false === $this->bubble;
|
84 |
+
}
|
85 |
+
|
86 |
+
public function flush()
|
87 |
+
{
|
88 |
+
if ($this->bufferSize === 0) {
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
|
92 |
+
$this->handler->handleBatch($this->buffer);
|
93 |
+
$this->clear();
|
94 |
+
}
|
95 |
+
|
96 |
+
public function __destruct()
|
97 |
+
{
|
98 |
+
// suppress the parent behavior since we already have register_shutdown_function()
|
99 |
+
// to call close(), and the reference contained there will prevent this from being
|
100 |
+
// GC'd until the end of the request
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* {@inheritdoc}
|
105 |
+
*/
|
106 |
+
public function close()
|
107 |
+
{
|
108 |
+
$this->flush();
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Clears the buffer without flushing any messages down to the wrapped handler.
|
113 |
+
*/
|
114 |
+
public function clear()
|
115 |
+
{
|
116 |
+
$this->bufferSize = 0;
|
117 |
+
$this->buffer = array();
|
118 |
+
}
|
119 |
+
|
120 |
+
public function reset()
|
121 |
+
{
|
122 |
+
$this->flush();
|
123 |
+
|
124 |
+
parent::reset();
|
125 |
+
|
126 |
+
if ($this->handler instanceof ResettableInterface) {
|
127 |
+
$this->handler->reset();
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* {@inheritdoc}
|
133 |
+
*/
|
134 |
+
public function setFormatter(FormatterInterface $formatter)
|
135 |
+
{
|
136 |
+
$this->handler->setFormatter($formatter);
|
137 |
+
|
138 |
+
return $this;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* {@inheritdoc}
|
143 |
+
*/
|
144 |
+
public function getFormatter()
|
145 |
+
{
|
146 |
+
return $this->handler->getFormatter();
|
147 |
+
}
|
148 |
+
}
|
src/lib/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of the Monolog package.
|
5 |
+
*
|
6 |
+
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace Monolog\Handler;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Base class for all mail handlers
|
16 |
+
*
|
17 |
+
* @author Gyula Sallai
|
18 |
+
*/
|
19 |
+
abstract class MailHandler extends AbstractProcessingHandler
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* {@inheritdoc}
|
23 |
+
*/
|
24 |
+
public function handleBatch(array $records)
|
25 |
+
{
|
26 |
+
$messages = array();
|
27 |
+
|
28 |
+
foreach ($records as $record) {
|
29 |
+
if ($record['level'] < $this->level) {
|
30 |
+
continue;
|
31 |
+
}
|
32 |
+
$messages[] = $this->processRecord($record);
|
33 |
+
}
|
34 |
+
|
35 |
+
if (!empty($messages)) {
|
36 |
+
$this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Send a mail with the given content
|
42 |
+
*
|
43 |
+
* @param string $content formatted email body to be sent
|
44 |
+
* @param array $records the array of log records that formed this content
|
45 |
+
*/
|
46 |
+
abstract protected function send($content, array $records);
|
47 |
+
|
48 |
+
/**
|
49 |
+
* {@inheritdoc}
|
50 |
+
*/
|
51 |
+
protected function write(array $record)
|
52 |
+
{
|
53 |
+
$this->send((string) $record['formatted'], array($record));
|
54 |
+
}
|
55 |
+
|
56 |
+
protected function getHighestRecord(array $records)
|
57 |
+
{
|
58 |
+
$highestRecord = null;
|
59 |
+
foreach ($records as $record) {
|
60 |
+
if ($highestRecord === null || $highestRecord['level'] < $record['level']) {
|
61 |
+
$highestRecord = $record;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
return $highestRecord;
|
66 |
+
}
|
67 |
+
}
|
src/lib/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of the Monolog package.
|
5 |
+
*
|
6 |
+
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace Monolog\Handler;
|
13 |
+
|
14 |
+
use Monolog\Logger;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Blackhole
|
18 |
+
*
|
19 |
+
* Any record it can handle will be thrown away. This can be used
|
20 |
+
* to put on top of an existing stack to override it temporarily.
|
21 |
+
*
|
22 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
23 |
+
*/
|
24 |
+
class NullHandler extends AbstractHandler
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* @param int $level The minimum logging level at which this handler will be triggered
|
28 |
+
*/
|
29 |
+
public function __construct($level = Logger::DEBUG)
|
30 |
+
{
|
31 |
+
parent::__construct($level, false);
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* {@inheritdoc}
|
36 |
+
*/
|
37 |
+
public function handle(array $record)
|
38 |
+
{
|
39 |
+
if ($record['level'] < $this->level) {
|
40 |
+
return false;
|
41 |
+
}
|
42 |
+
|
43 |
+
return true;
|
44 |
+
}
|
45 |
+
}
|
src/lib/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php
ADDED
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of the Monolog package.
|
5 |
+
*
|
6 |
+
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace Monolog\Handler;
|
13 |
+
|
14 |
+
use Monolog\Logger;
|
15 |
+
use Monolog\Utils;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Stores logs to files that are rotated every day and a limited number of files are kept.
|
19 |
+
*
|
20 |
+
* This rotation is only intended to be used as a workaround. Using logrotate to
|
21 |
+
* handle the rotation is strongly encouraged when you can use it.
|
22 |
+
*
|
23 |
+
* @author Christophe Coevoet <stof@notk.org>
|
24 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
25 |
+
*/
|
26 |
+
class RotatingFileHandler extends StreamHandler
|
27 |
+
{
|
28 |
+
const FILE_PER_DAY = 'Y-m-d';
|
29 |
+
const FILE_PER_MONTH = 'Y-m';
|
30 |
+
const FILE_PER_YEAR = 'Y';
|
31 |
+
|
32 |
+
protected $filename;
|
33 |
+
protected $maxFiles;
|
34 |
+
protected $mustRotate;
|
35 |
+
protected $nextRotation;
|
36 |
+
protected $filenameFormat;
|
37 |
+
protected $dateFormat;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param string $filename
|
41 |
+
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
|
42 |
+
* @param int $level The minimum logging level at which this handler will be triggered
|
43 |
+
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
44 |
+
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
|
45 |
+
* @param bool $useLocking Try to lock log file before doing any writes
|
46 |
+
*/
|
47 |
+
public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
|
48 |
+
{
|
49 |
+
$this->filename = Utils::canonicalizePath($filename);
|
50 |
+
$this->maxFiles = (int) $maxFiles;
|
51 |
+
$this->nextRotation = new \DateTime('tomorrow');
|
52 |
+
$this->filenameFormat = '{filename}-{date}';
|
53 |
+
$this->dateFormat = 'Y-m-d';
|
54 |
+
|
55 |
+
parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* {@inheritdoc}
|
60 |
+
*/
|
61 |
+
public function close()
|
62 |
+
{
|
63 |
+
parent::close();
|
64 |
+
|
65 |
+
if (true === $this->mustRotate) {
|
66 |
+
$this->rotate();
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* {@inheritdoc}
|
72 |
+
*/
|
73 |
+
public function reset()
|
74 |
+
{
|
75 |
+
parent::reset();
|
76 |
+
|
77 |
+
if (true === $this->mustRotate) {
|
78 |
+
$this->rotate();
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
public function setFilenameFormat($filenameFormat, $dateFormat)
|
83 |
+
{
|
84 |
+
if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
|
85 |
+
trigger_error(
|
86 |
+
'Invalid date format - format must be one of '.
|
87 |
+
'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '.
|
88 |
+
'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '.
|
89 |
+
'date formats using slashes, underscores and/or dots instead of dashes.',
|
90 |
+
E_USER_DEPRECATED
|
91 |
+
);
|
92 |
+
}
|
93 |
+
if (substr_count($filenameFormat, '{date}') === 0) {
|
94 |
+
trigger_error(
|
95 |
+
'Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.',
|
96 |
+
E_USER_DEPRECATED
|
97 |
+
);
|
98 |
+
}
|
99 |
+
$this->filenameFormat = $filenameFormat;
|
100 |
+
$this->dateFormat = $dateFormat;
|
101 |
+
$this->url = $this->getTimedFilename();
|
102 |
+
$this->close();
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* {@inheritdoc}
|
107 |
+
*/
|
108 |
+
protected function write(array $record)
|
109 |
+
{
|
110 |
+
// on the first record written, if the log is new, we should rotate (once per day)
|
111 |
+
if (null === $this->mustRotate) {
|
112 |
+
$this->mustRotate = !file_exists($this->url);
|
113 |
+
}
|
114 |
+
|
115 |
+
if ($this->nextRotation < $record['datetime']) {
|
116 |
+
$this->mustRotate = true;
|
117 |
+
$this->close();
|
118 |
+
}
|
119 |
+
|
120 |
+
parent::write($record);
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Rotates the files.
|
125 |
+
*/
|
126 |
+
protected function rotate()
|
127 |
+
{
|
128 |
+
// update filename
|
129 |
+
$this->url = $this->getTimedFilename();
|
130 |
+
$this->nextRotation = new \DateTime('tomorrow');
|
131 |
+
|
132 |
+
// skip GC of old logs if files are unlimited
|
133 |
+
if (0 === $this->maxFiles) {
|
134 |
+
return;
|
135 |
+
}
|
136 |
+
|
137 |
+
$logFiles = glob($this->getGlobPattern());
|
138 |
+
if ($this->maxFiles >= count($logFiles)) {
|
139 |
+
// no files to remove
|
140 |
+
return;
|
141 |
+
}
|
142 |
+
|
143 |
+
// Sorting the files by name to remove the older ones
|
144 |
+
usort($logFiles, function ($a, $b) {
|
145 |
+
return strcmp($b, $a);
|
146 |
+
});
|
147 |
+
|
148 |
+
foreach (array_slice($logFiles, $this->maxFiles) as $file) {
|
149 |
+
if (is_writable($file)) {
|
150 |
+
// suppress errors here as unlink() might fail if two processes
|
151 |
+
// are cleaning up/rotating at the same time
|
152 |
+
set_error_handler(function ($errno, $errstr, $errfile, $errline) {});
|
153 |
+
unlink($file);
|
154 |
+
restore_error_handler();
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
$this->mustRotate = false;
|
159 |
+
}
|
160 |
+
|
161 |
+
protected function getTimedFilename()
|
162 |
+
{
|
163 |
+
$fileInfo = pathinfo($this->filename);
|
164 |
+
$timedFilename = str_replace(
|
165 |
+
array('{filename}', '{date}'),
|
166 |
+
array($fileInfo['filename'], date($this->dateFormat)),
|
167 |
+
$fileInfo['dirname'] . '/' . $this->filenameFormat
|
168 |
+
);
|
169 |
+
|
170 |
+
if (!empty($fileInfo['extension'])) {
|
171 |
+
$timedFilename .= '.'.$fileInfo['extension'];
|
172 |
+
}
|
173 |
+
|
174 |
+
return $timedFilename;
|
175 |
+
}
|
176 |
+
|
177 |
+
protected function getGlobPattern()
|
178 |
+
{
|
179 |
+
$fileInfo = pathinfo($this->filename);
|
180 |
+
$glob = str_replace(
|
181 |
+
array('{filename}', '{date}'),
|
182 |
+
array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'),
|
183 |
+
$fileInfo['dirname'] . '/' . $this->filenameFormat
|
184 |
+
);
|
185 |
+
if (!empty($fileInfo['extension'])) {
|
186 |
+
$glob .= '.'.$fileInfo['extension'];
|
187 |
+
}
|
188 |
+
|
189 |
+
return $glob;
|
190 |
+
}
|
191 |
+
}
|