From 9f499ba4ce5e37f45e09213efbf344f1b66c8341 Mon Sep 17 00:00:00 2001
From: svfcode
Date: Tue, 28 Jul 2026 08:50:37 +0300
Subject: [PATCH 1/4] New. Settings. Add option to protect selected pages.
---
inc/cleantalk-common.php | 42 +++++++++++++++++++++++++
inc/cleantalk-public.php | 10 ++++--
inc/cleantalk-settings.php | 32 +++++++++++++++++++
js/cleantalk-admin-settings-page.min.js | 3 +-
js/src/cleantalk-admin-settings-page.js | 33 +++++++++++++++++++
lib/Cleantalk/ApbctWP/RemoteCalls.php | 2 ++
lib/Cleantalk/ApbctWP/State.php | 3 ++
7 files changed, 120 insertions(+), 5 deletions(-)
diff --git a/inc/cleantalk-common.php b/inc/cleantalk-common.php
index 54cf6d4ea..27668b72b 100644
--- a/inc/cleantalk-common.php
+++ b/inc/cleantalk-common.php
@@ -475,6 +475,48 @@ function apbct_exclusions_check__url()
return false;
}
+/**
+ * Whether public JS/CSS assets are allowed on the current page.
+ * Full mode — always. Lite mode — only if REQUEST_URI matches listed pages (substring or regexp).
+ *
+ * @return bool
+ */
+function apbct_is_assets_allowed_on_current_page()
+{
+ global $apbct;
+
+ // Full mode (0) or unset
+ if ( empty($apbct->settings['data__protection_mode']) ) {
+ return true;
+ }
+
+ if ( empty($apbct->settings['data__protection_mode__urls']) ) {
+ return false;
+ }
+
+ if ( strpos($apbct->settings['data__protection_mode__urls'], "\r\n") !== false ) {
+ $patterns = explode("\r\n", $apbct->settings['data__protection_mode__urls']);
+ } elseif ( strpos($apbct->settings['data__protection_mode__urls'], "\n") !== false ) {
+ $patterns = explode("\n", $apbct->settings['data__protection_mode__urls']);
+ } else {
+ $patterns = explode(',', $apbct->settings['data__protection_mode__urls']);
+ }
+
+ $url_haystack = TT::toString(Server::getString('REQUEST_URI'));
+
+ foreach ( $patterns as $pattern ) {
+ $pattern = trim($pattern);
+ if ( $pattern === '' ) {
+ continue;
+ }
+ if ( @preg_match('@' . $pattern . '@', $url_haystack) === 1 || stripos($url_haystack, $pattern) !== false ) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* Check POST array for the exclusion form signs. Listen for array keys or for value in case if key is "action".
* @param array $form_data The POST array or another filtered array of form data.
diff --git a/inc/cleantalk-public.php b/inc/cleantalk-public.php
index 007f6983e..6c024c0a4 100644
--- a/inc/cleantalk-public.php
+++ b/inc/cleantalk-public.php
@@ -40,7 +40,7 @@ function apbct_init()
}
// Localize data
- if ( ! apbct_exclusions_check__url() ) {
+ if ( ! apbct_exclusions_check__url() && apbct_is_assets_allowed_on_current_page() ) {
if (defined('CLEANTALK_PLACE_PUBLIC_JS_SCRIPTS_IN_FOOTER') && CLEANTALK_PLACE_PUBLIC_JS_SCRIPTS_IN_FOOTER) {
add_action('wp_footer', array(LocalizeHandler::class, 'handle'), 1);
add_action('login_footer', array(LocalizeHandler::class, 'handle'), 1);
@@ -1138,6 +1138,10 @@ function apbct_login__scripts()
{
global $apbct;
+ if ( ! apbct_is_assets_allowed_on_current_page() ) {
+ return;
+ }
+
apbct_enqueue_and_localize_public_scripts();
$apbct->public_script_loaded = true;
@@ -1205,7 +1209,7 @@ function ct_enqueue_scripts_public($_hook)
{
global $current_user, $apbct;
- if ( apbct_exclusions_check__url() || apbct_is_amp_request() ) {
+ if ( apbct_exclusions_check__url() || apbct_is_amp_request() || ! apbct_is_assets_allowed_on_current_page() ) {
return;
}
@@ -1232,7 +1236,7 @@ function ct_enqueue_styles_public()
{
global $apbct, $current_user;
- if ( apbct_exclusions_check__url() ) {
+ if ( apbct_exclusions_check__url() || ! apbct_is_assets_allowed_on_current_page() ) {
return;
}
diff --git a/inc/cleantalk-settings.php b/inc/cleantalk-settings.php
index 8aacc9a3a..4dc38cb9f 100644
--- a/inc/cleantalk-settings.php
+++ b/inc/cleantalk-settings.php
@@ -481,6 +481,28 @@ function apbct_settings__set_fields()
'title' => __('Data Processing', 'cleantalk-spam-protect'),
'section' => 'hidden_section',
'fields' => array(
+ 'data__protection_mode' => array(
+ 'title' => __('Protection mode', 'cleantalk-spam-protect'),
+ 'description' => __(
+ 'Full — load Anti-Spam scripts and styles on all pages. Lite — load them only on the pages listed below. Regular expressions are allowed.',
+ 'cleantalk-spam-protect'
+ ),
+ 'options' => array(
+ array('val' => 0, 'label' => __('Full', 'cleantalk-spam-protect'), 'childrens_enable' => 0,),
+ array('val' => 1, 'label' => __('Lite', 'cleantalk-spam-protect'), 'childrens_enable' => 1,),
+ ),
+ 'childrens' => array('data__protection_mode__urls'),
+ ),
+ 'data__protection_mode__urls' => array(
+ 'type' => 'textarea',
+ 'title' => __('Pages to protect (Lite mode)', 'cleantalk-spam-protect'),
+ 'description' => __(
+ 'List pages where Anti-Spam assets should be loaded. One value per line or comma-separated. Plain URL parts and regular expressions are allowed. Example: /contact, /checkout, /wp-login\\.php',
+ 'cleantalk-spam-protect'
+ ),
+ 'parent' => 'data__protection_mode',
+ 'class' => 'apbct_settings-field_wrapper--sub',
+ ),
'data__protect_logged_in' => array(
'title' => __("Protect logged in Users", 'cleantalk-spam-protect'),
'description' => __(
@@ -1795,6 +1817,7 @@ function apbct_settings__error__output($return = false)
'settings_validate' => 'Validate Settings',
'exclusions_urls' => 'URL Exclusions',
'exclusions_fields' => 'Field Exclusions',
+ 'protection_mode_urls' => 'Pages to protect (Lite mode)',
// Unknown
'unknown' => __('Unknown error type: ', 'cleantalk-spam-protect'),
@@ -2369,6 +2392,7 @@ function apbct_settings__validate($incoming_settings)
'data__email_decoder_obfuscation_mode',
'data__email_decoder_obfuscation_custom_text',
'data__email_decoder_buffer',
+ 'data__protection_mode__urls',
);
$incoming_settings = apbct_settings__keep_settings_state_values(
$incoming_settings,
@@ -2448,6 +2472,14 @@ function apbct_settings__validate($incoming_settings)
} // Make HTML code inactive
}
+ // Sanitize Protection mode pages (Lite) — plain URL parts and regexps both allowed
+ $result = apbct_settings__sanitize__exclusions(
+ isset($incoming_settings['data__protection_mode__urls']) ? $incoming_settings['data__protection_mode__urls'] : '',
+ false
+ );
+ $incoming_settings['data__protection_mode__urls'] = $result ? $result : '';
+ $apbct->errorDelete('protection_mode_urls', true, 'settings_validate');
+
// Validate Exclusions
// URLs
$is_exclusions_url_like = apbct_settings__sanitize__exclusions(
diff --git a/js/cleantalk-admin-settings-page.min.js b/js/cleantalk-admin-settings-page.min.js
index 023526a67..a19a5cb8c 100644
--- a/js/cleantalk-admin-settings-page.min.js
+++ b/js/cleantalk-admin-settings-page.min.js
@@ -1,2 +1 @@
-function handleAnchorDetection(t){"none"===document.querySelector("#apbct_settings__advanced_settings").style.display&&apbctExceptedShowHide("apbct_settings__advanced_settings"),scrollToAnchor("#"+t)}function scrollToAnchor(t){t=document.querySelector(t);t&&t.scrollIntoView({block:"end"})}function apbctManageEmailEncoderCustomTextField(){var t=document.querySelector("#apbct_setting_data__email_decoder_obfuscation_custom_text");let e;null!==t&&(e=void 0!==t.parentElement?t.parentElement:null),document.querySelectorAll(".apbct_setting---data__email_decoder_obfuscation_mode").forEach(t=>{e&&t.checked&&"replace"!==t.value&&e.classList.add("hidden"),t.addEventListener("click",t=>{void 0!==e&&("replace"===t.target.value?e.classList.remove("hidden"):e.classList.add("hidden"))})})}function apbctBannerCheck(){let c=setInterval(function(){apbct_admin_sendAJAX({action:"apbct_settings__check_renew_banner"},{callback:function(t,e,n,a){t.close_renew_banner&&(jQuery("#cleantalk_notice_renew").length&&jQuery("#cleantalk_notice_renew").hide("slow"),jQuery("#cleantalk_notice_trial").length&&jQuery("#cleantalk_notice_trial").hide("slow"),clearInterval(c))}})},9e5)}function apbctGetElems(a){for(let t=0,e=(a=a.split(",")).length,n;t{document.getElementById(t)&&"none"!==document.getElementById(t).style.display&&apbctShowHideElem(t)})}function apbctShowRequiredGroups(t,e){var n=document.getElementById("apbct_settings__dwpms_settings");n&&"none"===n.style.display&&((n=t).preventDefault(),apbctShowHideElem("apbct_settings__dwpms_settings"),document.getElementById(e).dispatchEvent(new n.constructor(n.type,n)))}function apbctSettingsDependencies(t,c){c=isNaN(c)?null:c,apbctGetElemsNative(t).forEach(function(t,e,n){var a;1===(c=null===c?null===t.getAttribute("disabled")?0:1:c)?t.removeAttribute("disabled"):t.setAttribute("disabled","disabled"),null!==t.getAttribute("apbct_children")&&null!==(a=apbctSettingsDependenciesGetState(t)&&c)&&apbctSettingsDependencies(t.getAttribute("apbct_children"),a)})}function apbctSettingsDependenciesGetState(t){let e;switch(t.getAttribute("type")){case"checkbox":e=+t.checked;break;case"radio":e=+(1==+t.getAttribute("value"));break;default:e=null}return e}function apbctSettingsShowDescription(t,e){function c(t){var e=0!=jQuery(t.target).parent(".apbct_long_desc").length,t=jQuery(t.target).hasClass("apbct_long_desc__cancel");(0");var n=jQuery("#apbct_long_desc__"+e);n.append("").append("").css({top:t.position().top-5,left:t.position().left+25}),apbct_admin_sendAJAX({action:"apbct_settings__get__long_description",setting_id:e},{spinner:n.children("img"),callback:function(t,e,n,a){t&&t.title&&t.desc&&(a.empty().append("").append("").append(""+t.title+"
").append(""+t.desc+"
"),jQuery(document).on("click",c))}},n)}function apbctNavigationMenuPosition(){var t,e,n=document.querySelector("#apbct_hidden_section_nav ul"),a=document.querySelector("#apbct_settings__button_section");n&&a&&(t=window.scrollY,e=window.innerWidth,1e3"+t.data+"
").insertAfter(jQuery(c)),jQuery("#apbct_settings_templates_import_button .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_settings_templates_import_button .apbct_success").hide(300)},2e3),document.addEventListener("cleantalkModalClosed",function(t){document.location.reload()}),setTimeout(function(){cleantalkModal.close()},2e3)):jQuery(""+t.data+"
").insertAfter(jQuery(c))}})}}),jQuery(document).on("click","#apbct_settings_templates_export_button",function(){jQuery("#apbct-ajax-result").remove();var t=jQuery("option:selected",jQuery("#apbct_settings_templates_export")),e=jQuery("#apbct_settings_templates_export_name");let n={};if(e.css("border-color","inherit"),void 0===t.data("id"))console.log('Attribute "data-id" not set for the option.');else{if("new_template"===t.data("id")){var a=e.val();if(""===a)return void e.css("border-color","red");n={template_name:a}}else n={template_id:t.data("id")};let c=this;apbct_admin_sendAJAX({action:"settings_templates_export",data:n},{timeout:25e3,button:c,spinner:jQuery("#apbct_settings_templates_export_button .apbct_preloader_button"),notJson:!0,callback:function(t,e,n,a){t.success?(jQuery(""+t.data+"
").insertAfter(jQuery(c)),jQuery("#apbct_settings_templates_export_button .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_settings_templates_export_button .apbct_success").hide(300)},2e3),document.addEventListener("cleantalkModalClosed",function(t){document.location.reload()}),setTimeout(function(){cleantalkModal.close()},2e3)):jQuery(""+t.data+"
").insertAfter(jQuery(c))}})}}),jQuery(document).on("click","#apbct_settings_templates_reset_button",function(){let c=this;apbct_admin_sendAJAX({action:"settings_templates_reset"},{timeout:25e3,button:c,spinner:jQuery("#apbct_settings_templates_reset_button .apbct_preloader_button"),notJson:!0,callback:function(t,e,n,a){t.success?(jQuery(""+t.data+"
").insertAfter(jQuery(c)),jQuery("#apbct_settings_templates_reset_button .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_settings_templates_reset_button .apbct_success").hide(300)},2e3),document.addEventListener("cleantalkModalClosed",function(t){document.location.reload()}),setTimeout(function(){cleantalkModal.close()},2e3)):jQuery(""+t.data+"
").insertAfter(jQuery(c))}})}),jQuery("#apbct_button__sync").on("click",function(){apbct_admin_sendAJAX({action:"apbct_sync"},{timeout:25e3,button:document.getElementById("apbct_button__sync"),spinner:jQuery("#apbct_button__sync .apbct_preloader_button"),callback:function(t,e,n,a){jQuery("#apbct_button__sync .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_button__sync .apbct_success").hide(300)},2e3),t.reload&&(ctSettingsPage.key_changed?(jQuery(".key_changed_sync").hide(300),jQuery(".key_changed_success").show(300),setTimeout(function(){document.location.reload()},3e3)):document.location.reload())}})}),ctSettingsPage.key_changed&&jQuery("#apbct_button__sync").click(),jQuery(document).on("click",".apbct_settings-long_description---show",function(){apbctSettingsShowDescription(self=jQuery(this),self.attr("setting"))}),(jQuery("#cleantalk_notice_renew").length||jQuery("#cleantalk_notice_trial").length)&&apbctBannerCheck(),jQuery(document).on("change","#apbct_settings_templates_export",function(){"new_template"===jQuery("option:selected",this).data("id")?jQuery(this).parent().parent().find("#apbct_settings_templates_export_name").show():jQuery(this).parent().parent().find("#apbct_settings_templates_export_name").hide()}),apbctSaveButtonPosition();let t;window.addEventListener("scroll",function(){clearTimeout(t),t=setTimeout(function(){apbctSaveButtonPosition()},50),apbctNavigationMenuPosition()}),jQuery("#ct_adv_showhide a").on("click",apbctSaveButtonPosition),jQuery("#apbct-change-account-email").on("click",function(t){t.preventDefault();var t=jQuery(this),e=jQuery("#apbct-account-email"),n=e.text();t.toggleClass("active"),t.hasClass("active")?(t.text(t.data("save-text")),e.attr("contenteditable","true"),e.on("keydown",function(t){"Enter"===t.code&&t.preventDefault()}),e.on("input",function(t){"insertParagraph"===t.inputType&&t.preventDefault()})):(apbct_admin_sendAJAX({action:"apbct_update_account_email",accountEmail:n},{timeout:5e3,callback:function(t,e,n,a){void 0!==t.error&&jQuery("#apbct-account-email").css("border-color","red")}}),e.attr("contenteditable","false"),t.text(t.data("default-text")))}),jQuery("#apbct_setting_apikey").on("input",function(){var t=jQuery(this).val(),e=(jQuery("#apbct_settings__key_line__save_settings").off("click"),""!==t&&null===t.match(/^[a-z\d]{8,30}\s*$/));jQuery("#apbct_settings__key_is_bad").hide(),jQuery("#apbct_showApiKey").hide(),jQuery("#apbct_settings__account_name_ob").hide(),""===t?(jQuery("#apbct_button__key_line__save_changes_wrapper").hide(),jQuery("#apbct_button__get_key_auto").length&&jQuery("#apbct_button__get_key_auto__wrapper").show()):(jQuery("#apbct_button__key_line__save_changes_wrapper").show(),jQuery("#apbct_button__get_key_auto__wrapper").hide(),e&&jQuery("#apbct_settings__key_line__save_settings").on("click",function(t){t.preventDefault(),jQuery("#apbct_settings__key_is_bad").show(),apbctHighlightElement("apbct_setting_apikey",3)}))}),jQuery("#apbct_setting_apikey").val()&&ctSettingsPage.key_is_ok&&jQuery("#apbct_button__get_key_auto__wrapper").hide(),ctSettingsPage.key_is_ok||ctSettingsPage.ip_license||jQuery('button.cleantalk_link[value="save_changes"]').on("click",function(t){t.preventDefault(),jQuery("#sync_required_notice").length||jQuery("Synchronization process failed. Please, check the acces key and restart the synch.
").insertAfter(jQuery("#apbct_button__sync")),apbctHighlightElement("apbct_setting_apikey",3),apbctHighlightElement("apbct_button__sync",3),jQuery("#apbct_button__get_key_auto__wrapper").show()}),jQuery("#apbct-custom-logo-open-gallery").click(function(t){t.preventDefault();let e=jQuery(this),n=wp.media({library:{type:"image"},multiple:!1});n.on("select",function(){var t=n.state().get("selection").first().toJSON();e.parent().prev().attr("src",t.url),jQuery("#cleantalk_custom_logo").val(t.id)}),n.open()}),jQuery("#apbct-custom-logo-remove-image").click(function(t){t.preventDefault(),!0===confirm("Sure?")&&(t=jQuery(this).parent().prev().data("src"),jQuery(this).parent().prev().attr("src",t),jQuery(this).prev().prev().val(""))}),jQuery('button[id*="apbct-action-adjust-change-"]').click(function(t){t.preventDefault();var t={action:"apbct_action_adjust_change"},e=(t.adjust=jQuery(this).data("adjust"),{});e.button=document.getElementById("apbct-action-adjust-change-"+t.adjust),e.notJson=!0,e.callback=function(){document.location.reload()},apbct_admin_sendAJAX(t,e)}),jQuery('button[id*="apbct-action-adjust-reverse-"]').click(function(t){t.preventDefault();var t={action:"apbct_action_adjust_reverse"},e=(t.adjust=jQuery(this).data("adjust"),{});e.button=document.getElementById("apbct-action-adjust-reverse-"+t.adjust),e.notJson=!0,e.callback=function(){document.location.reload()},apbct_admin_sendAJAX(t,e)}),document.querySelector(".apbct_hidden_section_nav_mob_btn")?.addEventListener("click",()=>{document.querySelector("#apbct_hidden_section_nav ul").style.display="block",document.querySelector(".apbct_hidden_section_nav_mob_btn").style.display="none"}),document.querySelector(".apbct_hidden_section_nav_mob_btn-close")?.addEventListener("click",()=>{document.querySelector("#apbct_hidden_section_nav ul").style.display="none",document.querySelector(".apbct_hidden_section_nav_mob_btn").style.display="block"}),apbctManageEmailEncoderCustomTextField(),window.location.hash&&handleAnchorDetection(window.location.hash.substring(1))});
-//# sourceMappingURL=cleantalk-admin-settings-page.min.js.map
+function handleAnchorDetection(t){"none"===document.querySelector("#apbct_settings__advanced_settings").style.display&&apbctExceptedShowHide("apbct_settings__advanced_settings"),scrollToAnchor("#"+t)}function scrollToAnchor(t){t=document.querySelector(t);t&&t.scrollIntoView({block:"end"})}function apbctManageEmailEncoderCustomTextField(){var t=document.querySelector("#apbct_setting_data__email_decoder_obfuscation_custom_text");let e;null!==t&&(e=void 0!==t.parentElement?t.parentElement:null),document.querySelectorAll(".apbct_setting---data__email_decoder_obfuscation_mode").forEach(t=>{e&&t.checked&&"replace"!==t.value&&e.classList.add("hidden"),t.addEventListener("click",t=>{void 0!==e&&("replace"===t.target.value?e.classList.remove("hidden"):e.classList.add("hidden"))})})}function apbctManageProtectionModeUrlsField(){var t=document.querySelector("#apbct_setting_data__protection_mode__urls");let e;null!==t&&(e=void 0!==t.parentElement?t.parentElement:null),document.querySelectorAll(".apbct_setting---data__protection_mode").forEach(t=>{e&&t.checked&&"0"===t.value&&e.classList.add("hidden"),t.addEventListener("click",t=>{null!=e&&("1"===t.target.value?e.classList.remove("hidden"):e.classList.add("hidden"))})})}function apbctBannerCheck(){let c=setInterval(function(){apbct_admin_sendAJAX({action:"apbct_settings__check_renew_banner"},{callback:function(t,e,n,a){t.close_renew_banner&&(jQuery("#cleantalk_notice_renew").length&&jQuery("#cleantalk_notice_renew").hide("slow"),jQuery("#cleantalk_notice_trial").length&&jQuery("#cleantalk_notice_trial").hide("slow"),clearInterval(c))}})},9e5)}function apbctGetElems(a){for(let t=0,e=(a=a.split(",")).length,n;t{document.getElementById(t)&&"none"!==document.getElementById(t).style.display&&apbctShowHideElem(t)})}function apbctShowRequiredGroups(t,e){var n=document.getElementById("apbct_settings__dwpms_settings");n&&"none"===n.style.display&&((n=t).preventDefault(),apbctShowHideElem("apbct_settings__dwpms_settings"),document.getElementById(e).dispatchEvent(new n.constructor(n.type,n)))}function apbctSettingsDependencies(t,c){c=isNaN(c)?null:c,apbctGetElemsNative(t).forEach(function(t,e,n){var a;1===(c=null===c?null===t.getAttribute("disabled")?0:1:c)?t.removeAttribute("disabled"):t.setAttribute("disabled","disabled"),null!==t.getAttribute("apbct_children")&&null!==(a=apbctSettingsDependenciesGetState(t)&&c)&&apbctSettingsDependencies(t.getAttribute("apbct_children"),a)})}function apbctSettingsDependenciesGetState(t){let e;switch(t.getAttribute("type")){case"checkbox":e=+t.checked;break;case"radio":e=+(1==+t.getAttribute("value"));break;default:e=null}return e}function apbctSettingsShowDescription(t,e){function c(t){var e=0!=jQuery(t.target).parent(".apbct_long_desc").length,t=jQuery(t.target).hasClass("apbct_long_desc__cancel");(0");var n=jQuery("#apbct_long_desc__"+e);n.append("").append("").css({top:t.position().top-5,left:t.position().left+25}),apbct_admin_sendAJAX({action:"apbct_settings__get__long_description",setting_id:e},{spinner:n.children("img"),callback:function(t,e,n,a){t&&t.title&&t.desc&&(a.empty().append("").append("").append(""+t.title+"
").append(""+t.desc+"
"),jQuery(document).on("click",c))}},n)}function apbctNavigationMenuPosition(){var t,e,n=document.querySelector("#apbct_hidden_section_nav ul"),a=document.querySelector("#apbct_settings__button_section");n&&a&&(t=window.scrollY,e=window.innerWidth,1e3"+t.data+"").insertAfter(jQuery(c)),jQuery("#apbct_settings_templates_import_button .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_settings_templates_import_button .apbct_success").hide(300)},2e3),document.addEventListener("cleantalkModalClosed",function(t){document.location.reload()}),setTimeout(function(){cleantalkModal.close()},2e3)):jQuery(""+t.data+"
").insertAfter(jQuery(c))}})}}),jQuery(document).on("click","#apbct_settings_templates_export_button",function(){jQuery("#apbct-ajax-result").remove();var t=jQuery("option:selected",jQuery("#apbct_settings_templates_export")),e=jQuery("#apbct_settings_templates_export_name");let n={};if(e.css("border-color","inherit"),void 0===t.data("id"))console.log('Attribute "data-id" not set for the option.');else{if("new_template"===t.data("id")){var a=e.val();if(""===a)return void e.css("border-color","red");n={template_name:a}}else n={template_id:t.data("id")};let c=this;apbct_admin_sendAJAX({action:"settings_templates_export",data:n},{timeout:25e3,button:c,spinner:jQuery("#apbct_settings_templates_export_button .apbct_preloader_button"),notJson:!0,callback:function(t,e,n,a){t.success?(jQuery(""+t.data+"
").insertAfter(jQuery(c)),jQuery("#apbct_settings_templates_export_button .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_settings_templates_export_button .apbct_success").hide(300)},2e3),document.addEventListener("cleantalkModalClosed",function(t){document.location.reload()}),setTimeout(function(){cleantalkModal.close()},2e3)):jQuery(""+t.data+"
").insertAfter(jQuery(c))}})}}),jQuery(document).on("click","#apbct_settings_templates_reset_button",function(){let c=this;apbct_admin_sendAJAX({action:"settings_templates_reset"},{timeout:25e3,button:c,spinner:jQuery("#apbct_settings_templates_reset_button .apbct_preloader_button"),notJson:!0,callback:function(t,e,n,a){t.success?(jQuery(""+t.data+"
").insertAfter(jQuery(c)),jQuery("#apbct_settings_templates_reset_button .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_settings_templates_reset_button .apbct_success").hide(300)},2e3),document.addEventListener("cleantalkModalClosed",function(t){document.location.reload()}),setTimeout(function(){cleantalkModal.close()},2e3)):jQuery(""+t.data+"
").insertAfter(jQuery(c))}})}),jQuery("#apbct_button__sync").on("click",function(){apbct_admin_sendAJAX({action:"apbct_sync"},{timeout:25e3,button:document.getElementById("apbct_button__sync"),spinner:jQuery("#apbct_button__sync .apbct_preloader_button"),callback:function(t,e,n,a){jQuery("#apbct_button__sync .apbct_success").show(300),setTimeout(function(){jQuery("#apbct_button__sync .apbct_success").hide(300)},2e3),t.reload&&(ctSettingsPage.key_changed?(jQuery(".key_changed_sync").hide(300),jQuery(".key_changed_success").show(300),setTimeout(function(){document.location.reload()},3e3)):document.location.reload())}})}),ctSettingsPage.key_changed&&jQuery("#apbct_button__sync").click(),jQuery(document).on("click",".apbct_settings-long_description---show",function(){apbctSettingsShowDescription(self=jQuery(this),self.attr("setting"))}),(jQuery("#cleantalk_notice_renew").length||jQuery("#cleantalk_notice_trial").length)&&apbctBannerCheck(),jQuery(document).on("change","#apbct_settings_templates_export",function(){"new_template"===jQuery("option:selected",this).data("id")?jQuery(this).parent().parent().find("#apbct_settings_templates_export_name").show():jQuery(this).parent().parent().find("#apbct_settings_templates_export_name").hide()}),apbctSaveButtonPosition();let t;window.addEventListener("scroll",function(){clearTimeout(t),t=setTimeout(function(){apbctSaveButtonPosition()},50),apbctNavigationMenuPosition()}),jQuery("#ct_adv_showhide a").on("click",apbctSaveButtonPosition),jQuery("#apbct-change-account-email").on("click",function(t){t.preventDefault();var t=jQuery(this),e=jQuery("#apbct-account-email"),n=e.text();t.toggleClass("active"),t.hasClass("active")?(t.text(t.data("save-text")),e.attr("contenteditable","true"),e.on("keydown",function(t){"Enter"===t.code&&t.preventDefault()}),e.on("input",function(t){"insertParagraph"===t.inputType&&t.preventDefault()})):(apbct_admin_sendAJAX({action:"apbct_update_account_email",accountEmail:n},{timeout:5e3,callback:function(t,e,n,a){void 0!==t.error&&jQuery("#apbct-account-email").css("border-color","red")}}),e.attr("contenteditable","false"),t.text(t.data("default-text")))}),jQuery("#apbct_setting_apikey").on("input",function(){var t=jQuery(this).val(),e=(jQuery("#apbct_settings__key_line__save_settings").off("click"),""!==t&&null===t.match(/^[a-z\d]{8,30}\s*$/));jQuery("#apbct_settings__key_is_bad").hide(),jQuery("#apbct_showApiKey").hide(),jQuery("#apbct_settings__account_name_ob").hide(),""===t?(jQuery("#apbct_button__key_line__save_changes_wrapper").hide(),jQuery("#apbct_button__get_key_auto").length&&jQuery("#apbct_button__get_key_auto__wrapper").show()):(jQuery("#apbct_button__key_line__save_changes_wrapper").show(),jQuery("#apbct_button__get_key_auto__wrapper").hide(),e&&jQuery("#apbct_settings__key_line__save_settings").on("click",function(t){t.preventDefault(),jQuery("#apbct_settings__key_is_bad").show(),apbctHighlightElement("apbct_setting_apikey",3)}))}),jQuery("#apbct_setting_apikey").val()&&ctSettingsPage.key_is_ok&&jQuery("#apbct_button__get_key_auto__wrapper").hide(),ctSettingsPage.key_is_ok||ctSettingsPage.ip_license||jQuery('button.cleantalk_link[value="save_changes"]').on("click",function(t){t.preventDefault(),jQuery("#sync_required_notice").length||jQuery("Synchronization process failed. Please, check the acces key and restart the synch.
").insertAfter(jQuery("#apbct_button__sync")),apbctHighlightElement("apbct_setting_apikey",3),apbctHighlightElement("apbct_button__sync",3),jQuery("#apbct_button__get_key_auto__wrapper").show()}),jQuery("#apbct-custom-logo-open-gallery").click(function(t){t.preventDefault();let e=jQuery(this),n=wp.media({library:{type:"image"},multiple:!1});n.on("select",function(){var t=n.state().get("selection").first().toJSON();e.parent().prev().attr("src",t.url),jQuery("#cleantalk_custom_logo").val(t.id)}),n.open()}),jQuery("#apbct-custom-logo-remove-image").click(function(t){t.preventDefault(),!0===confirm("Sure?")&&(t=jQuery(this).parent().prev().data("src"),jQuery(this).parent().prev().attr("src",t),jQuery(this).prev().prev().val(""))}),jQuery('button[id*="apbct-action-adjust-change-"]').click(function(t){t.preventDefault();var t={action:"apbct_action_adjust_change"},e=(t.adjust=jQuery(this).data("adjust"),{});e.button=document.getElementById("apbct-action-adjust-change-"+t.adjust),e.notJson=!0,e.callback=function(){document.location.reload()},apbct_admin_sendAJAX(t,e)}),jQuery('button[id*="apbct-action-adjust-reverse-"]').click(function(t){t.preventDefault();var t={action:"apbct_action_adjust_reverse"},e=(t.adjust=jQuery(this).data("adjust"),{});e.button=document.getElementById("apbct-action-adjust-reverse-"+t.adjust),e.notJson=!0,e.callback=function(){document.location.reload()},apbct_admin_sendAJAX(t,e)}),document.querySelector(".apbct_hidden_section_nav_mob_btn")?.addEventListener("click",()=>{document.querySelector("#apbct_hidden_section_nav ul").style.display="block",document.querySelector(".apbct_hidden_section_nav_mob_btn").style.display="none"}),document.querySelector(".apbct_hidden_section_nav_mob_btn-close")?.addEventListener("click",()=>{document.querySelector("#apbct_hidden_section_nav ul").style.display="none",document.querySelector(".apbct_hidden_section_nav_mob_btn").style.display="block"}),apbctManageEmailEncoderCustomTextField(),apbctManageProtectionModeUrlsField(),window.location.hash&&handleAnchorDetection(window.location.hash.substring(1))});
\ No newline at end of file
diff --git a/js/src/cleantalk-admin-settings-page.js b/js/src/cleantalk-admin-settings-page.js
index d83612a77..38c0645d0 100644
--- a/js/src/cleantalk-admin-settings-page.js
+++ b/js/src/cleantalk-admin-settings-page.js
@@ -400,6 +400,9 @@ jQuery(document).ready(function() {
// Hide/show EmailEncoder replacing text textarea
apbctManageEmailEncoderCustomTextField();
+ // Hide/show Lite mode pages textarea
+ apbctManageProtectionModeUrlsField();
+
if (window.location.hash) {
const anchor = window.location.hash.substring(1);
handleAnchorDetection(anchor);
@@ -461,6 +464,36 @@ function apbctManageEmailEncoderCustomTextField() {
});
}
+/**
+ * Hide/show Lite mode pages textarea
+ */
+function apbctManageProtectionModeUrlsField() {
+ const urlsField = document
+ .querySelector('#apbct_setting_data__protection_mode__urls');
+ let urlsFieldWrapper;
+ if (urlsField !== null) {
+ urlsFieldWrapper = typeof urlsField.parentElement !== 'undefined' ?
+ urlsField.parentElement :
+ null;
+ }
+ document.querySelectorAll('.apbct_setting---data__protection_mode').forEach((elem) => {
+ // visibility set on saved settings: hide when Full (0)
+ if (urlsFieldWrapper && elem.checked && elem.value === '0') {
+ urlsFieldWrapper.classList.add('hidden');
+ }
+ // visibility set on change
+ elem.addEventListener('click', (event) => {
+ if (typeof urlsFieldWrapper !== 'undefined' && urlsFieldWrapper !== null) {
+ if (event.target.value === '1') {
+ urlsFieldWrapper.classList.remove('hidden');
+ } else {
+ urlsFieldWrapper.classList.add('hidden');
+ }
+ }
+ });
+ });
+}
+
/**
* Checking current account status for renew notice
*/
diff --git a/lib/Cleantalk/ApbctWP/RemoteCalls.php b/lib/Cleantalk/ApbctWP/RemoteCalls.php
index bead9ee7b..3839cba90 100644
--- a/lib/Cleantalk/ApbctWP/RemoteCalls.php
+++ b/lib/Cleantalk/ApbctWP/RemoteCalls.php
@@ -539,6 +539,8 @@ private static function getSettings($settings)
'data__email_check_before_post' => 'Check email before POST request',
'data__email_check_exist_post' => 'Check email before POST request',
'data__honeypot_field' => 'Add a honeypot field',
+ 'data__protection_mode' => 'Protection mode',
+ 'data__protection_mode__urls' => 'Pages to protect (Lite mode)',
'data__email_decoder' => 'Encode contact data',
'data__email_decoder_encode_phone_numbers' => 'Encode phones',
'data__email_decoder_encode_email_addresses' => 'Encode emails',
diff --git a/lib/Cleantalk/ApbctWP/State.php b/lib/Cleantalk/ApbctWP/State.php
index 4c2fc7e97..5a3436e41 100644
--- a/lib/Cleantalk/ApbctWP/State.php
+++ b/lib/Cleantalk/ApbctWP/State.php
@@ -95,6 +95,9 @@ class State extends \Cleantalk\Common\State
'data__email_decoder_encode_phone_numbers' => 0,
'data__email_decoder_encode_email_addresses' => 1,
'data__wc_store_blocked_orders' => 0,
+ // Protection mode: 0 - Full / 1 - Lite (assets only on listed pages)
+ 'data__protection_mode' => 0,
+ 'data__protection_mode__urls' => '',
// Exclusions
// Send to the cloud some excepted requests
From 86658a4bc86a3c431ff9c46a54944dcb3f68d61e Mon Sep 17 00:00:00 2001
From: svfcode
Date: Tue, 28 Jul 2026 09:20:29 +0300
Subject: [PATCH 2/4] fix cp
---
inc/cleantalk-common.php | 122 ++++++++++++++++++++++++++++++++-----
inc/cleantalk-settings.php | 32 +++++++---
2 files changed, 133 insertions(+), 21 deletions(-)
diff --git a/inc/cleantalk-common.php b/inc/cleantalk-common.php
index 27668b72b..4b864f9f4 100644
--- a/inc/cleantalk-common.php
+++ b/inc/cleantalk-common.php
@@ -475,6 +475,112 @@ function apbct_exclusions_check__url()
return false;
}
+/**
+ * Split Protection mode (Lite) pages list into patterns.
+ *
+ * @param string $urls_setting
+ *
+ * @return string[]
+ */
+function apbct_protection_mode__parse_url_patterns($urls_setting)
+{
+ if ( $urls_setting === '' ) {
+ return array();
+ }
+
+ if ( strpos($urls_setting, "\r\n") !== false ) {
+ $patterns = explode("\r\n", $urls_setting);
+ } elseif ( strpos($urls_setting, "\n") !== false ) {
+ $patterns = explode("\n", $urls_setting);
+ } else {
+ $patterns = explode(',', $urls_setting);
+ }
+
+ $result = array();
+ foreach ( $patterns as $pattern ) {
+ $pattern = trim($pattern);
+ if ( $pattern !== '' ) {
+ $result[] = $pattern;
+ }
+ }
+
+ return $result;
+}
+
+/**
+ * Build a regexp from a user pattern with a safe delimiter.
+ *
+ * @param string $pattern
+ *
+ * @return string
+ */
+function apbct_protection_mode__build_regexp($pattern)
+{
+ $delimiter = '#';
+
+ return $delimiter . str_replace($delimiter, '\\' . $delimiter, $pattern) . $delimiter;
+}
+
+/**
+ * Whether the pattern compiles as a regular expression (same delimiter as runtime).
+ *
+ * @param string $pattern
+ *
+ * @return bool
+ */
+function apbct_protection_mode__is_regexp_compilable($pattern)
+{
+ return @preg_match(apbct_protection_mode__build_regexp($pattern), '') !== false;
+}
+
+/**
+ * Whether the pattern looks like an intentional regular expression.
+ *
+ * @param string $pattern
+ *
+ * @return bool
+ */
+function apbct_protection_mode__looks_like_regexp($pattern)
+{
+ return (bool) preg_match('/[.*+?\[\](){}|^$\\\\]/', $pattern);
+}
+
+/**
+ * Return the first invalid regexp-like pattern, or null if all are ok.
+ *
+ * @param string $urls_setting
+ *
+ * @return string|null
+ */
+function apbct_protection_mode__get_invalid_regexp_pattern($urls_setting)
+{
+ foreach ( apbct_protection_mode__parse_url_patterns($urls_setting) as $pattern ) {
+ if ( apbct_protection_mode__looks_like_regexp($pattern) && ! apbct_protection_mode__is_regexp_compilable($pattern) ) {
+ return $pattern;
+ }
+ }
+
+ return null;
+}
+
+/**
+ * Match a single Protection mode pattern against a URL haystack.
+ * Substring first, then regexp with escaped delimiter.
+ *
+ * @param string $pattern
+ * @param string $url_haystack
+ *
+ * @return bool
+ */
+function apbct_protection_mode__pattern_matches($pattern, $url_haystack)
+{
+ if ( stripos($url_haystack, $pattern) !== false ) {
+ return true;
+ }
+
+ return @preg_match(apbct_protection_mode__build_regexp($pattern), $url_haystack) === 1;
+}
+
/**
* Whether public JS/CSS assets are allowed on the current page.
* Full mode — always. Lite mode — only if REQUEST_URI matches listed pages (substring or regexp).
@@ -494,22 +600,10 @@ function apbct_is_assets_allowed_on_current_page()
return false;
}
- if ( strpos($apbct->settings['data__protection_mode__urls'], "\r\n") !== false ) {
- $patterns = explode("\r\n", $apbct->settings['data__protection_mode__urls']);
- } elseif ( strpos($apbct->settings['data__protection_mode__urls'], "\n") !== false ) {
- $patterns = explode("\n", $apbct->settings['data__protection_mode__urls']);
- } else {
- $patterns = explode(',', $apbct->settings['data__protection_mode__urls']);
- }
-
$url_haystack = TT::toString(Server::getString('REQUEST_URI'));
- foreach ( $patterns as $pattern ) {
- $pattern = trim($pattern);
- if ( $pattern === '' ) {
- continue;
- }
- if ( @preg_match('@' . $pattern . '@', $url_haystack) === 1 || stripos($url_haystack, $pattern) !== false ) {
+ foreach ( apbct_protection_mode__parse_url_patterns($apbct->settings['data__protection_mode__urls']) as $pattern ) {
+ if ( apbct_protection_mode__pattern_matches($pattern, $url_haystack) ) {
return true;
}
}
diff --git a/inc/cleantalk-settings.php b/inc/cleantalk-settings.php
index 4dc38cb9f..a2ba66bbc 100644
--- a/inc/cleantalk-settings.php
+++ b/inc/cleantalk-settings.php
@@ -2472,13 +2472,31 @@ function apbct_settings__validate($incoming_settings)
} // Make HTML code inactive
}
- // Sanitize Protection mode pages (Lite) — plain URL parts and regexps both allowed
- $result = apbct_settings__sanitize__exclusions(
- isset($incoming_settings['data__protection_mode__urls']) ? $incoming_settings['data__protection_mode__urls'] : '',
- false
- );
- $incoming_settings['data__protection_mode__urls'] = $result ? $result : '';
- $apbct->errorDelete('protection_mode_urls', true, 'settings_validate');
+ // Sanitize / validate Protection mode pages (Lite) — plain URL parts and regexps both allowed
+ $raw_protection_mode_urls = isset($incoming_settings['data__protection_mode__urls'])
+ ? $incoming_settings['data__protection_mode__urls']
+ : '';
+ $result = apbct_settings__sanitize__exclusions($raw_protection_mode_urls, false);
+ if ( $result === false ) {
+ $incoming_settings['data__protection_mode__urls'] = '';
+ $apbct->errorAdd(
+ 'protection_mode_urls',
+ 'is not valid: "' . $raw_protection_mode_urls . '"',
+ 'settings_validate'
+ );
+ } else {
+ $incoming_settings['data__protection_mode__urls'] = $result;
+ $invalid_pattern = apbct_protection_mode__get_invalid_regexp_pattern($result);
+ if ( $invalid_pattern !== null ) {
+ $apbct->errorAdd(
+ 'protection_mode_urls',
+ 'contains invalid regular expression: "' . $invalid_pattern . '"',
+ 'settings_validate'
+ );
+ } else {
+ $apbct->errorDelete('protection_mode_urls', true, 'settings_validate');
+ }
+ }
// Validate Exclusions
// URLs
From b4298e6ca7ec853862367a38aff0231ffe0ac306 Mon Sep 17 00:00:00 2001
From: svfcode
Date: Tue, 28 Jul 2026 09:36:40 +0300
Subject: [PATCH 3/4] fix psalm
---
inc/cleantalk-settings.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/inc/cleantalk-settings.php b/inc/cleantalk-settings.php
index a2ba66bbc..cdc3e073d 100644
--- a/inc/cleantalk-settings.php
+++ b/inc/cleantalk-settings.php
@@ -2477,7 +2477,7 @@ function apbct_settings__validate($incoming_settings)
? $incoming_settings['data__protection_mode__urls']
: '';
$result = apbct_settings__sanitize__exclusions($raw_protection_mode_urls, false);
- if ( $result === false ) {
+ if ( ! is_string($result) ) {
$incoming_settings['data__protection_mode__urls'] = '';
$apbct->errorAdd(
'protection_mode_urls',
From 57eb4164a91c92cab81b1fddf9c1ffa99767c56d Mon Sep 17 00:00:00 2001
From: svfcode
Date: Tue, 28 Jul 2026 09:51:47 +0300
Subject: [PATCH 4/4] fix cp
---
inc/cleantalk-common.php | 6 +++++-
inc/cleantalk-settings.php | 8 ++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/inc/cleantalk-common.php b/inc/cleantalk-common.php
index 4b864f9f4..6797dd6c2 100644
--- a/inc/cleantalk-common.php
+++ b/inc/cleantalk-common.php
@@ -565,7 +565,7 @@ function apbct_protection_mode__get_invalid_regexp_pattern($urls_setting)
/**
* Match a single Protection mode pattern against a URL haystack.
- * Substring first, then regexp with escaped delimiter.
+ * Substring first; regexp only when the pattern looks like a regular expression.
*
* @param string $pattern
* @param string $url_haystack
@@ -578,6 +578,10 @@ function apbct_protection_mode__pattern_matches($pattern, $url_haystack)
return true;
}
+ if ( ! apbct_protection_mode__looks_like_regexp($pattern) ) {
+ return false;
+ }
+
return @preg_match(apbct_protection_mode__build_regexp($pattern), $url_haystack) === 1;
}
diff --git a/inc/cleantalk-settings.php b/inc/cleantalk-settings.php
index cdc3e073d..112bb1256 100644
--- a/inc/cleantalk-settings.php
+++ b/inc/cleantalk-settings.php
@@ -2498,6 +2498,14 @@ function apbct_settings__validate($incoming_settings)
}
}
+ // Lite without pages would disable assets everywhere — fall back to Full
+ if (
+ ! empty($incoming_settings['data__protection_mode']) &&
+ empty($incoming_settings['data__protection_mode__urls'])
+ ) {
+ $incoming_settings['data__protection_mode'] = 0;
+ }
+
// Validate Exclusions
// URLs
$is_exclusions_url_like = apbct_settings__sanitize__exclusions(