From d1d120e56bef40888385d16437ef43f67d4f7e14 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Sun, 30 Aug 2026 11:11:25 +0300 Subject: [PATCH 1/7] Fix. SFW. Priority fixed. --- lib/Cleantalk/Common/Firewall.php | 51 +++++++++++++++++-- .../Common/Firewall/FirewallModule.php | 8 +++ .../Firewall/FirewallModuleAbstract.php | 2 + 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/lib/Cleantalk/Common/Firewall.php b/lib/Cleantalk/Common/Firewall.php index 1360f2796..6fae1f4e0 100644 --- a/lib/Cleantalk/Common/Firewall.php +++ b/lib/Cleantalk/Common/Firewall.php @@ -3,6 +3,7 @@ namespace Cleantalk\Common; use Cleantalk\ApbctWP\Variables\Cookie; +use Cleantalk\ApbctWP\Variables\Server; use Cleantalk\Common\Firewall\FirewallModule; use Cleantalk\ApbctWP\Variables\Get; @@ -26,6 +27,11 @@ class Firewall { public $ip_array = array(); + /** + * @var array example array ( 'ua', 'ua_id', 'ua_status') + */ + public $user_agent_data = array(); + // Database protected $db; @@ -64,6 +70,7 @@ public function __construct($db) $this->db = $db; $this->debug = (bool)Get::get('debug'); $this->ip_array = $this->ipGet(); + $this->user_agent_data = $this->getUserAgentData(); } /** @@ -81,6 +88,40 @@ public function ipGet($ips_input = 'real', $v4_only = true) return ! empty($result) ? array('real' => $result) : array(); } + public function getUserAgentData() + { + $server_ua = TT::toString(Server::get('HTTP_USER_AGENT')); + $ua_table = defined('APBCT_TBL_AC_UA_BL') ? APBCT_TBL_AC_UA_BL : null; + + if ( $ua_table ) { + $ua_bl_query = "SELECT * FROM $ua_table ORDER BY `ua_status` DESC;"; + $ua_bl_results = $this->db->fetchAll($ua_bl_query); + foreach ( $ua_bl_results as $ua_bl_result ) { + if ( + ! empty($ua_bl_result['ua_template']) && + preg_match( + '%' . str_replace(array('"', '%'), array('', '\%'), $ua_bl_result['ua_template']) . '%i', + $server_ua + ) && + ! in_array(preg_last_error(), array(PREG_BACKTRACK_LIMIT_ERROR, PREG_RECURSION_LIMIT_ERROR), true) + ) { + $ua_id = TT::getArrayValueAsString($ua_bl_result, 'id'); + + return array( + 'ua' => $server_ua, + 'ua_id' => $ua_id, + 'ua_status' => TT::getArrayValueAsString($ua_bl_result, 'ua_status'), + ); + } + } + } + return array( + 'ua' => $server_ua, + 'ua_id' => null, + 'ua_status' => null, + ); + } + /** * Loads the FireWall module to the array. * For inner usage only. @@ -90,11 +131,12 @@ public function ipGet($ips_input = 'real', $v4_only = true) */ public function loadFwModule(FirewallModule $module) { - if ( ! in_array($module, $this->fw_modules)) { + if ( ! in_array($module, $this->fw_modules) ) { $module->setDb($this->db); $module->ipAppendAdditional($this->ip_array); $this->fw_modules[$module->module_name] = $module; $module->setIpArray($this->ip_array); + $module->setUserAgentData($this->user_agent_data); } } @@ -120,8 +162,11 @@ public function run() $results[$module->module_name] = $module_results; } - if ($this->isWhitelisted($results)) { - // Break protection logic if it whitelisted or trusted network. + if ( + $this->isWhitelisted($results) && + ( isset($this->user_agent_data['ua_status']) && (int) $this->user_agent_data['ua_status'] !== 0 ) + ) { + // Break protection logic if it whitelisted, or trusted network, or user-agent not blocked. break; } } diff --git a/lib/Cleantalk/Common/Firewall/FirewallModule.php b/lib/Cleantalk/Common/Firewall/FirewallModule.php index 0734cb7db..fdd49459d 100644 --- a/lib/Cleantalk/Common/Firewall/FirewallModule.php +++ b/lib/Cleantalk/Common/Firewall/FirewallModule.php @@ -79,6 +79,14 @@ public function setIpArray($ip_array) $this->ip_array = $ip_array; } + /** + * @param array $user_agent_data + */ + public function setUserAgentData($user_agent_data) + { + $this->user_agent_data = $user_agent_data; + } + /** * @param $result * diff --git a/lib/Cleantalk/Common/Firewall/FirewallModuleAbstract.php b/lib/Cleantalk/Common/Firewall/FirewallModuleAbstract.php index 11418da76..14024262a 100644 --- a/lib/Cleantalk/Common/Firewall/FirewallModuleAbstract.php +++ b/lib/Cleantalk/Common/Firewall/FirewallModuleAbstract.php @@ -40,6 +40,8 @@ abstract class FirewallModuleAbstract protected $ip_array = array(); + protected $user_agent_data = array(); + protected $test_ip; protected $passed_ip; From 9c4cc6f61439ef16fd5dd892d0975e5a5e88ce9a Mon Sep 17 00:00:00 2001 From: Glomberg Date: Mon, 31 Aug 2026 12:27:35 +0300 Subject: [PATCH 2/7] Fix. SFW. AC UA checking fixed. --- lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php b/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php index bc3e267e9..d24e89ce3 100644 --- a/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php +++ b/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php @@ -253,9 +253,9 @@ private function runLogSearchForIpPool($ip_array) * @param string $status * @return array */ - private function makeResult($ip, $status) + private function makeResult($ip, $status, $is_personal = false) { - return array('ip' => $ip, 'is_personal' => false, 'status' => $status); + return array('ip' => $ip, 'is_personal' => $is_personal, 'status' => $status); } /** @@ -294,9 +294,12 @@ private function performUaCheck($current_ip) } // Blacklisted — record but continue to cookie check + // HardCode - write AC dined by UA as personal: blacklisted user-agent may be only personally + // `is_personal` makes priority bigger, but we don't have a personal flag in the AC module yet, so this fix is needed + $is_personal = true; return array( - 'entries' => array($this->makeResult($current_ip, 'DENY_ANTICRAWLER_UA')), - 'early_return' => false, + 'entries' => array($this->makeResult($current_ip, 'DENY_ANTICRAWLER_UA', $is_personal)), + 'early_return' => true, ); } } From 6ba43cf179e75bc4671df07f5a498afb932edec9 Mon Sep 17 00:00:00 2001 From: Viktor Date: Tue, 1 Sep 2026 10:44:41 +0300 Subject: [PATCH 3/7] Fix. Code. Copilot suggestion applied. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- lib/Cleantalk/Common/Firewall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cleantalk/Common/Firewall.php b/lib/Cleantalk/Common/Firewall.php index 6fae1f4e0..77b8d0a80 100644 --- a/lib/Cleantalk/Common/Firewall.php +++ b/lib/Cleantalk/Common/Firewall.php @@ -164,7 +164,7 @@ public function run() if ( $this->isWhitelisted($results) && - ( isset($this->user_agent_data['ua_status']) && (int) $this->user_agent_data['ua_status'] !== 0 ) + ( ! isset($this->user_agent_data['ua_status']) || (int) $this->user_agent_data['ua_status'] !== 0 ) ) { // Break protection logic if it whitelisted, or trusted network, or user-agent not blocked. break; From 199828b1d081c18d81e4e0d38c06fd19e602e2dd Mon Sep 17 00:00:00 2001 From: Viktor Date: Tue, 1 Sep 2026 10:48:10 +0300 Subject: [PATCH 4/7] Fix. Code. Copilot suggestion applied. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- lib/Cleantalk/Common/Firewall.php | 33 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/Cleantalk/Common/Firewall.php b/lib/Cleantalk/Common/Firewall.php index 77b8d0a80..5aaf33be0 100644 --- a/lib/Cleantalk/Common/Firewall.php +++ b/lib/Cleantalk/Common/Firewall.php @@ -97,23 +97,24 @@ public function getUserAgentData() $ua_bl_query = "SELECT * FROM $ua_table ORDER BY `ua_status` DESC;"; $ua_bl_results = $this->db->fetchAll($ua_bl_query); foreach ( $ua_bl_results as $ua_bl_result ) { - if ( - ! empty($ua_bl_result['ua_template']) && - preg_match( - '%' . str_replace(array('"', '%'), array('', '\%'), $ua_bl_result['ua_template']) . '%i', - $server_ua - ) && - ! in_array(preg_last_error(), array(PREG_BACKTRACK_LIMIT_ERROR, PREG_RECURSION_LIMIT_ERROR), true) - ) { - $ua_id = TT::getArrayValueAsString($ua_bl_result, 'id'); - - return array( - 'ua' => $server_ua, - 'ua_id' => $ua_id, - 'ua_status' => TT::getArrayValueAsString($ua_bl_result, 'ua_status'), - ); + if ( ! empty($ua_bl_result['ua_template']) ) { + $pattern = '%' . str_replace(array('"', '%'), array('', '\%'), $ua_bl_result['ua_template']) . '%i'; + $match = preg_match($pattern, $server_ua); + + if ( $match === false && in_array(preg_last_error(), array(PREG_BACKTRACK_LIMIT_ERROR, PREG_RECURSION_LIMIT_ERROR), true) ) { + continue; + } + + if ( $match === 1 ) { + $ua_id = TT::getArrayValueAsString($ua_bl_result, 'id'); + + return array( + 'ua' => $server_ua, + 'ua_id' => $ua_id, + 'ua_status' => TT::getArrayValueAsString($ua_bl_result, 'ua_status'), + ); + } } - } } return array( 'ua' => $server_ua, From a74e5a9d2f083001f060de43dab77a6ecd1d8bb2 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Tue, 1 Sep 2026 10:46:23 +0300 Subject: [PATCH 5/7] Fix. Code. Docblock fixed. --- lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php b/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php index d24e89ce3..9c82db2b3 100644 --- a/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php +++ b/lib/Cleantalk/ApbctWP/Firewall/AntiCrawler.php @@ -251,6 +251,7 @@ private function runLogSearchForIpPool($ip_array) * * @param string $ip * @param string $status + * @param bool $is_personal * @return array */ private function makeResult($ip, $status, $is_personal = false) From a4d7198f0ede3696aa61bbd6aec19ba5364ef33d Mon Sep 17 00:00:00 2001 From: Glomberg Date: Tue, 1 Sep 2026 10:50:41 +0300 Subject: [PATCH 6/7] Fix. Code. Code review fixed #1. --- lib/Cleantalk/Common/Firewall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cleantalk/Common/Firewall.php b/lib/Cleantalk/Common/Firewall.php index 5aaf33be0..7a7598dce 100644 --- a/lib/Cleantalk/Common/Firewall.php +++ b/lib/Cleantalk/Common/Firewall.php @@ -90,7 +90,7 @@ public function ipGet($ips_input = 'real', $v4_only = true) public function getUserAgentData() { - $server_ua = TT::toString(Server::get('HTTP_USER_AGENT')); + $server_ua = Server::getString('HTTP_USER_AGENT'); $ua_table = defined('APBCT_TBL_AC_UA_BL') ? APBCT_TBL_AC_UA_BL : null; if ( $ua_table ) { From db795adee74e713b4d5960e1c8f10671ff7dec25 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Tue, 1 Sep 2026 10:56:38 +0300 Subject: [PATCH 7/7] Fix. Code. Code error fixed. --- lib/Cleantalk/Common/Firewall.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cleantalk/Common/Firewall.php b/lib/Cleantalk/Common/Firewall.php index 7a7598dce..628fa91a8 100644 --- a/lib/Cleantalk/Common/Firewall.php +++ b/lib/Cleantalk/Common/Firewall.php @@ -115,6 +115,7 @@ public function getUserAgentData() ); } } + } } return array( 'ua' => $server_ua,