Changeset 3545826
- Timestamp:
- 05/24/2026 05:31:39 AM (5 months ago)
- Location:
- rabbitbuilds-anti-spam-comment-shield
- Files:
-
- 2 edited
- 8 copied
-
tags/2.0.6 (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk )
-
tags/2.0.6/LICENSE (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/LICENSE )
-
tags/2.0.6/README.md (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/README.md )
-
tags/2.0.6/README.txt (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/README.txt ) (4 diffs)
-
tags/2.0.6/admin (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/admin )
-
tags/2.0.6/admin/css/admin-style.css (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/admin/css/admin-style.css )
-
tags/2.0.6/anti-spam-comment-shield.php (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/anti-spam-comment-shield.php ) (15 diffs)
-
tags/2.0.6/languages (copied) (copied from rabbitbuilds-anti-spam-comment-shield/trunk/languages )
-
trunk/README.txt (modified) (4 diffs)
-
trunk/anti-spam-comment-shield.php (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
rabbitbuilds-anti-spam-comment-shield/tags/2.0.6/README.txt
r3490773 r3545826 5 5 Requires at least: 5.0 6 6 Requires PHP: 7.4 7 Tested up to: 6.98 Stable tag: 2.0. 57 Tested up to: 7.0 8 Stable tag: 2.0.6 9 9 License: GPL-2.0-or-later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 26 26 * 🍯 **Honeypot Trap** — Hidden field that catches bots filling every input 27 27 * ⏱️ **Time-Based Check** — Rejects comments submitted too quickly 28 * 🔒 **REST API Protection** — Blocks unauthenticated REST API comments 28 * 🔒 **REST API Protection** — Blocks unauthenticated REST API comments (disable for headless setups) 29 29 * 📊 **Spam Statistics Dashboard** — Real-time total & daily blocked spam counter 30 30 * ⚙️ **Modern Settings Page** — Beautiful card-based UI with toggle switches … … 84 84 85 85 == Changelog == 86 87 = 2.0.6 = 88 * Tested with WordPress 7.0 "Armstrong" 89 * Fixed: honeypot and time-based checks no longer fail-open on sites with long-lived page caches (the 24-hour nonce gate has been dropped — the honeypot field's presence is itself the spam signal) 90 * Fixed: hash-based verification now tolerates extra query-string parameters (e.g. CDN/tracking params appended to wp-comments-post.php) 91 * Fixed: replaced deprecated `current_time('timestamp')` usage; "last blocked" time is now stored as a Unix timestamp and computed timezone-correctly on the settings page 92 * Improved: protection hooks now register on `init` instead of at file load — removes work from admin/AJAX/REST/CLI requests that don't involve commenting 93 * Improved: `rbascs_stats` option is now non-autoloaded (one-time migration runs automatically on upgrade) 94 * Improved: REST API Protection setting now explicitly warns headless/decoupled sites that it will block their REST comment flow 95 * Improved: deferred default-message translation to display time to avoid the WP 6.7+ "translations loaded too early" notice 86 96 87 97 = 2.0.5 = … … 187 197 == Upgrade Notice == 188 198 199 = 2.0.6 = 200 WordPress 7.0 compatibility. Important fix for sites running long-lived page caches: honeypot and time-based checks no longer silently fail open. Recommended upgrade. 201 189 202 = 2.0.5 = 190 203 Refreshed dashboard UI with trust-themed emerald green color scheme. Code audit and cleanup. -
rabbitbuilds-anti-spam-comment-shield/tags/2.0.6/anti-spam-comment-shield.php
r3490773 r3545826 6 6 * Author: Rabbit Builds 7 7 * Author URI: https://rabbitbuilds.com/ 8 * Version: 2.0. 58 * Version: 2.0.6 9 9 * Text Domain: rabbitbuilds-anti-spam-comment-shield 10 10 * Domain Path: /languages … … 21 21 * ─── Constants ─────────────────────────────────────────────────────────────── 22 22 */ 23 define('RBASCS_VERSION', '2.0. 5');23 define('RBASCS_VERSION', '2.0.6'); 24 24 define('RBASCS_URL', plugin_dir_url(__FILE__)); 25 25 … … 40 40 'enable_time_check' => 1, 41 41 'min_submit_time' => 3, 42 'blocked_message' => __('Your comment was blocked by our anti-spam protection. If you believe this is an error, please try again.', 'rabbitbuilds-anti-spam-comment-shield'),42 'blocked_message' => '', 43 43 'enable_rest_protect' => 1, 44 44 ); … … 72 72 $stats['blocked_today'] = 0; 73 73 $stats['blocked_date'] = current_time('Y-m-d'); 74 update_option('rbascs_stats', $stats );74 update_option('rbascs_stats', $stats, false); 75 75 } 76 76 … … 87 87 set_transient('rbascs_activation_notice', true, 5); 88 88 89 // Initialize stats if not existing 89 // Initialize stats if not existing (non-autoloaded — read only on the settings page) 90 90 if (false === get_option('rbascs_stats')) { 91 update_option('rbascs_stats', rbascs_get_default_stats());91 add_option('rbascs_stats', rbascs_get_default_stats(), '', false); 92 92 } 93 93 … … 306 306 <span class="wpasc-stat-last-time"> 307 307 <?php 308 $last_blocked_ts = !empty($stats['last_blocked_at']) ? strtotime($stats['last_blocked_at']) : false;308 $last_blocked_ts = rbascs_normalize_block_ts($stats['last_blocked_at']); 309 309 if ($last_blocked_ts) { 310 echo esc_html(human_time_diff($last_blocked_ts, current_time('timestamp')) . ' ' . __('ago', 'rabbitbuilds-anti-spam-comment-shield'));310 echo esc_html(human_time_diff($last_blocked_ts, time()) . ' ' . __('ago', 'rabbitbuilds-anti-spam-comment-shield')); 311 311 } else { 312 312 esc_html_e('No spam yet', 'rabbitbuilds-anti-spam-comment-shield'); … … 413 413 </label> 414 414 <p class="wpasc-setting-desc"> 415 <?php esc_html_e('Blocks unauthenticated comment creation through the WordPress REST API endpoint.', 'rabbitbuilds-anti-spam-comment-shield'); ?>415 <?php esc_html_e('Blocks ALL unauthenticated comment creation through the WordPress REST API endpoint. Disable this if your site is headless/decoupled and accepts comments via REST from logged-out visitors.', 'rabbitbuilds-anti-spam-comment-shield'); ?> 416 416 </p> 417 417 </div> … … 664 664 */ 665 665 666 $rbascs_options = rbascs_get_options(); 666 add_action('init', 'rbascs_maybe_upgrade'); 667 add_action('init', 'rbascs_register_frontend_hooks'); 668 669 function rbascs_maybe_upgrade() 670 { 671 $installed_version = get_option('rbascs_db_version'); 672 if ($installed_version === RBASCS_VERSION) { 673 return; 674 } 675 676 // 2.0.6: switch rbascs_stats to non-autoloaded. 677 if (function_exists('wp_set_option_autoload')) { 678 wp_set_option_autoload('rbascs_stats', false); 679 } 680 681 update_option('rbascs_db_version', RBASCS_VERSION, false); 682 } 683 684 function rbascs_register_frontend_hooks() 685 { 686 $options = rbascs_get_options(); 687 688 if ($options['enable_hash_check']) { 689 add_filter('comment_form_defaults', 'rbascs_remove_action_url'); 690 add_action('wp_enqueue_scripts', 'rbascs_enqueue_frontend_js'); 691 add_action('pre_comment_on_post', 'rbascs_validate_hash_request'); 692 } 693 694 if ($options['enable_honeypot']) { 695 add_action('comment_form_after_fields', 'rbascs_honeypot_field'); 696 add_action('comment_form_logged_in_after', 'rbascs_honeypot_field'); 697 add_filter('preprocess_comment', 'rbascs_check_honeypot', 1); 698 } 699 700 if ($options['enable_time_check']) { 701 add_filter('preprocess_comment', 'rbascs_check_time', 2); 702 } 703 704 if ($options['enable_rest_protect']) { 705 add_filter('rest_pre_insert_comment', 'rbascs_rest_protect', 10, 2); 706 } 707 } 667 708 668 709 /** 669 710 * ─── 1. Remove Comment Action URL from HTML ───────────────────────────────── 670 711 */ 671 if ($rbascs_options['enable_hash_check']) {672 add_filter('comment_form_defaults', 'rbascs_remove_action_url');673 }674 712 675 713 function rbascs_remove_action_url($defaults) … … 682 720 * ─── 2. Inject JavaScript to Restore Action URL on User Interaction ───────── 683 721 */ 684 if ($rbascs_options['enable_hash_check']) {685 add_action('wp_enqueue_scripts', 'rbascs_enqueue_frontend_js');686 }687 688 722 function rbascs_enqueue_frontend_js() 689 723 { … … 732 766 * ─── 3. Honeypot Field ────────────────────────────────────────────────────── 733 767 */ 734 if ($rbascs_options['enable_honeypot']) {735 add_action('comment_form_after_fields', 'rbascs_honeypot_field');736 add_action('comment_form_logged_in_after', 'rbascs_honeypot_field');737 }738 739 768 function rbascs_honeypot_field() 740 769 { 741 770 echo '<p style="position:absolute;left:-9999px;height:0;width:0;overflow:hidden;" aria-hidden="true">'; 742 771 echo '<label for="wpasc_website_url">' . esc_html__('Website URL', 'rabbitbuilds-anti-spam-comment-shield') . '</label>'; 743 echo '<input type="hidden" name="_wpasc_nonce" value="' . esc_attr(wp_create_nonce('wpasc_comment_nonce')) . '" />';744 772 echo '<input type="text" name="wpasc_website_url" id="wpasc_website_url" value="" tabindex="-1" autocomplete="off" />'; 745 773 echo '</p>'; … … 749 777 * ─── 4. Validate Honeypot on Comment Pre-Process ──────────────────────────── 750 778 */ 751 if ($rbascs_options['enable_honeypot']) {752 add_filter('preprocess_comment', 'rbascs_check_honeypot', 1);753 }754 755 779 function rbascs_check_honeypot($commentdata) 756 780 { 757 $nonce = isset($_POST['_wpasc_nonce']) ? sanitize_text_field(wp_unslash($_POST['_wpasc_nonce'])) : '';758 if (!wp_verify_nonce($nonce, 'wpasc_comment_nonce')) {759 return $commentdata;760 }761 762 781 $honeypot_value = isset($_POST['wpasc_website_url']) 763 782 ? sanitize_text_field(trim((string) wp_unslash($_POST['wpasc_website_url']))) … … 774 793 * ─── 5. Validate Time-Based Check ─────────────────────────────────────────── 775 794 */ 776 if ($rbascs_options['enable_time_check']) {777 add_filter('preprocess_comment', 'rbascs_check_time', 2);778 }779 780 795 function rbascs_check_time($commentdata) 781 796 { 782 797 $options = rbascs_get_options(); 783 $nonce = isset($_POST['_wpasc_nonce']) ? sanitize_text_field(wp_unslash($_POST['_wpasc_nonce'])) : '';784 if (!wp_verify_nonce($nonce, 'wpasc_comment_nonce')) {785 return $commentdata;786 }787 798 788 799 if (!isset($_POST['_wpasc_ts'])) { … … 811 822 * ─── 6. REST API Comment Protection ───────────────────────────────────────── 812 823 */ 813 if ($rbascs_options['enable_rest_protect']) { 814 add_filter('rest_pre_insert_comment', 'rbascs_rest_protect', 10, 2); 815 } 816 817 function rbascs_rest_protect($prepared_comment, $_request) 818 { 824 function rbascs_rest_protect($prepared_comment, $request) 825 { 826 unset($request); 819 827 if (!is_user_logged_in()) { 820 828 rbascs_record_block(); … … 831 839 * ─── 7. Hash-Based Verification on POST ───────────────────────────────────── 832 840 */ 833 if ($rbascs_options['enable_hash_check']) {834 add_action('pre_comment_on_post', 'rbascs_validate_hash_request');835 }836 837 841 function rbascs_validate_hash_request() 838 842 { 839 $query_string = isset($_SERVER['QUERY_STRING']) ? sanitize_text_field(wp_unslash($_SERVER['QUERY_STRING'])) : ''; 840 $has_key = hash_equals(RBASCS_UNIQUE_KEY, $query_string); 843 $query_string = isset($_SERVER['QUERY_STRING']) ? (string) wp_unslash($_SERVER['QUERY_STRING']) : ''; 844 845 // Tolerate extra query params (CDN/tracking) by looking for the key anywhere. 846 $parsed = array(); 847 parse_str($query_string, $parsed); 848 $has_key = false; 849 foreach (array_keys($parsed) as $param_name) { 850 if (hash_equals(RBASCS_UNIQUE_KEY, (string) $param_name)) { 851 $has_key = true; 852 break; 853 } 854 } 841 855 842 856 $referrer = wp_get_raw_referer(); … … 890 904 $stats['blocked_total']++; 891 905 $stats['blocked_today']++; 892 $stats['last_blocked_at'] = current_time('mysql'); 893 894 update_option('rbascs_stats', $stats); 906 $stats['last_blocked_at'] = time(); 907 908 update_option('rbascs_stats', $stats, false); 909 } 910 911 /** 912 * Normalize stored last-blocked value to a Unix timestamp. 913 * Pre-2.0.6 stored a mysql-format site-local string; new code stores time(). 914 */ 915 function rbascs_normalize_block_ts($value) 916 { 917 if (empty($value)) { 918 return 0; 919 } 920 if (is_numeric($value)) { 921 return (int) $value; 922 } 923 // Legacy: current_time('mysql') string in site timezone. 924 $ts = strtotime((string) $value . ' ' . wp_timezone_string()); 925 return $ts ? (int) $ts : 0; 895 926 } 896 927 -
rabbitbuilds-anti-spam-comment-shield/trunk/README.txt
r3490773 r3545826 5 5 Requires at least: 5.0 6 6 Requires PHP: 7.4 7 Tested up to: 6.98 Stable tag: 2.0. 57 Tested up to: 7.0 8 Stable tag: 2.0.6 9 9 License: GPL-2.0-or-later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 26 26 * 🍯 **Honeypot Trap** — Hidden field that catches bots filling every input 27 27 * ⏱️ **Time-Based Check** — Rejects comments submitted too quickly 28 * 🔒 **REST API Protection** — Blocks unauthenticated REST API comments 28 * 🔒 **REST API Protection** — Blocks unauthenticated REST API comments (disable for headless setups) 29 29 * 📊 **Spam Statistics Dashboard** — Real-time total & daily blocked spam counter 30 30 * ⚙️ **Modern Settings Page** — Beautiful card-based UI with toggle switches … … 84 84 85 85 == Changelog == 86 87 = 2.0.6 = 88 * Tested with WordPress 7.0 "Armstrong" 89 * Fixed: honeypot and time-based checks no longer fail-open on sites with long-lived page caches (the 24-hour nonce gate has been dropped — the honeypot field's presence is itself the spam signal) 90 * Fixed: hash-based verification now tolerates extra query-string parameters (e.g. CDN/tracking params appended to wp-comments-post.php) 91 * Fixed: replaced deprecated `current_time('timestamp')` usage; "last blocked" time is now stored as a Unix timestamp and computed timezone-correctly on the settings page 92 * Improved: protection hooks now register on `init` instead of at file load — removes work from admin/AJAX/REST/CLI requests that don't involve commenting 93 * Improved: `rbascs_stats` option is now non-autoloaded (one-time migration runs automatically on upgrade) 94 * Improved: REST API Protection setting now explicitly warns headless/decoupled sites that it will block their REST comment flow 95 * Improved: deferred default-message translation to display time to avoid the WP 6.7+ "translations loaded too early" notice 86 96 87 97 = 2.0.5 = … … 187 197 == Upgrade Notice == 188 198 199 = 2.0.6 = 200 WordPress 7.0 compatibility. Important fix for sites running long-lived page caches: honeypot and time-based checks no longer silently fail open. Recommended upgrade. 201 189 202 = 2.0.5 = 190 203 Refreshed dashboard UI with trust-themed emerald green color scheme. Code audit and cleanup. -
rabbitbuilds-anti-spam-comment-shield/trunk/anti-spam-comment-shield.php
r3490773 r3545826 6 6 * Author: Rabbit Builds 7 7 * Author URI: https://rabbitbuilds.com/ 8 * Version: 2.0. 58 * Version: 2.0.6 9 9 * Text Domain: rabbitbuilds-anti-spam-comment-shield 10 10 * Domain Path: /languages … … 21 21 * ─── Constants ─────────────────────────────────────────────────────────────── 22 22 */ 23 define('RBASCS_VERSION', '2.0. 5');23 define('RBASCS_VERSION', '2.0.6'); 24 24 define('RBASCS_URL', plugin_dir_url(__FILE__)); 25 25 … … 40 40 'enable_time_check' => 1, 41 41 'min_submit_time' => 3, 42 'blocked_message' => __('Your comment was blocked by our anti-spam protection. If you believe this is an error, please try again.', 'rabbitbuilds-anti-spam-comment-shield'),42 'blocked_message' => '', 43 43 'enable_rest_protect' => 1, 44 44 ); … … 72 72 $stats['blocked_today'] = 0; 73 73 $stats['blocked_date'] = current_time('Y-m-d'); 74 update_option('rbascs_stats', $stats );74 update_option('rbascs_stats', $stats, false); 75 75 } 76 76 … … 87 87 set_transient('rbascs_activation_notice', true, 5); 88 88 89 // Initialize stats if not existing 89 // Initialize stats if not existing (non-autoloaded — read only on the settings page) 90 90 if (false === get_option('rbascs_stats')) { 91 update_option('rbascs_stats', rbascs_get_default_stats());91 add_option('rbascs_stats', rbascs_get_default_stats(), '', false); 92 92 } 93 93 … … 306 306 <span class="wpasc-stat-last-time"> 307 307 <?php 308 $last_blocked_ts = !empty($stats['last_blocked_at']) ? strtotime($stats['last_blocked_at']) : false;308 $last_blocked_ts = rbascs_normalize_block_ts($stats['last_blocked_at']); 309 309 if ($last_blocked_ts) { 310 echo esc_html(human_time_diff($last_blocked_ts, current_time('timestamp')) . ' ' . __('ago', 'rabbitbuilds-anti-spam-comment-shield'));310 echo esc_html(human_time_diff($last_blocked_ts, time()) . ' ' . __('ago', 'rabbitbuilds-anti-spam-comment-shield')); 311 311 } else { 312 312 esc_html_e('No spam yet', 'rabbitbuilds-anti-spam-comment-shield'); … … 413 413 </label> 414 414 <p class="wpasc-setting-desc"> 415 <?php esc_html_e('Blocks unauthenticated comment creation through the WordPress REST API endpoint.', 'rabbitbuilds-anti-spam-comment-shield'); ?>415 <?php esc_html_e('Blocks ALL unauthenticated comment creation through the WordPress REST API endpoint. Disable this if your site is headless/decoupled and accepts comments via REST from logged-out visitors.', 'rabbitbuilds-anti-spam-comment-shield'); ?> 416 416 </p> 417 417 </div> … … 664 664 */ 665 665 666 $rbascs_options = rbascs_get_options(); 666 add_action('init', 'rbascs_maybe_upgrade'); 667 add_action('init', 'rbascs_register_frontend_hooks'); 668 669 function rbascs_maybe_upgrade() 670 { 671 $installed_version = get_option('rbascs_db_version'); 672 if ($installed_version === RBASCS_VERSION) { 673 return; 674 } 675 676 // 2.0.6: switch rbascs_stats to non-autoloaded. 677 if (function_exists('wp_set_option_autoload')) { 678 wp_set_option_autoload('rbascs_stats', false); 679 } 680 681 update_option('rbascs_db_version', RBASCS_VERSION, false); 682 } 683 684 function rbascs_register_frontend_hooks() 685 { 686 $options = rbascs_get_options(); 687 688 if ($options['enable_hash_check']) { 689 add_filter('comment_form_defaults', 'rbascs_remove_action_url'); 690 add_action('wp_enqueue_scripts', 'rbascs_enqueue_frontend_js'); 691 add_action('pre_comment_on_post', 'rbascs_validate_hash_request'); 692 } 693 694 if ($options['enable_honeypot']) { 695 add_action('comment_form_after_fields', 'rbascs_honeypot_field'); 696 add_action('comment_form_logged_in_after', 'rbascs_honeypot_field'); 697 add_filter('preprocess_comment', 'rbascs_check_honeypot', 1); 698 } 699 700 if ($options['enable_time_check']) { 701 add_filter('preprocess_comment', 'rbascs_check_time', 2); 702 } 703 704 if ($options['enable_rest_protect']) { 705 add_filter('rest_pre_insert_comment', 'rbascs_rest_protect', 10, 2); 706 } 707 } 667 708 668 709 /** 669 710 * ─── 1. Remove Comment Action URL from HTML ───────────────────────────────── 670 711 */ 671 if ($rbascs_options['enable_hash_check']) {672 add_filter('comment_form_defaults', 'rbascs_remove_action_url');673 }674 712 675 713 function rbascs_remove_action_url($defaults) … … 682 720 * ─── 2. Inject JavaScript to Restore Action URL on User Interaction ───────── 683 721 */ 684 if ($rbascs_options['enable_hash_check']) {685 add_action('wp_enqueue_scripts', 'rbascs_enqueue_frontend_js');686 }687 688 722 function rbascs_enqueue_frontend_js() 689 723 { … … 732 766 * ─── 3. Honeypot Field ────────────────────────────────────────────────────── 733 767 */ 734 if ($rbascs_options['enable_honeypot']) {735 add_action('comment_form_after_fields', 'rbascs_honeypot_field');736 add_action('comment_form_logged_in_after', 'rbascs_honeypot_field');737 }738 739 768 function rbascs_honeypot_field() 740 769 { 741 770 echo '<p style="position:absolute;left:-9999px;height:0;width:0;overflow:hidden;" aria-hidden="true">'; 742 771 echo '<label for="wpasc_website_url">' . esc_html__('Website URL', 'rabbitbuilds-anti-spam-comment-shield') . '</label>'; 743 echo '<input type="hidden" name="_wpasc_nonce" value="' . esc_attr(wp_create_nonce('wpasc_comment_nonce')) . '" />';744 772 echo '<input type="text" name="wpasc_website_url" id="wpasc_website_url" value="" tabindex="-1" autocomplete="off" />'; 745 773 echo '</p>'; … … 749 777 * ─── 4. Validate Honeypot on Comment Pre-Process ──────────────────────────── 750 778 */ 751 if ($rbascs_options['enable_honeypot']) {752 add_filter('preprocess_comment', 'rbascs_check_honeypot', 1);753 }754 755 779 function rbascs_check_honeypot($commentdata) 756 780 { 757 $nonce = isset($_POST['_wpasc_nonce']) ? sanitize_text_field(wp_unslash($_POST['_wpasc_nonce'])) : '';758 if (!wp_verify_nonce($nonce, 'wpasc_comment_nonce')) {759 return $commentdata;760 }761 762 781 $honeypot_value = isset($_POST['wpasc_website_url']) 763 782 ? sanitize_text_field(trim((string) wp_unslash($_POST['wpasc_website_url']))) … … 774 793 * ─── 5. Validate Time-Based Check ─────────────────────────────────────────── 775 794 */ 776 if ($rbascs_options['enable_time_check']) {777 add_filter('preprocess_comment', 'rbascs_check_time', 2);778 }779 780 795 function rbascs_check_time($commentdata) 781 796 { 782 797 $options = rbascs_get_options(); 783 $nonce = isset($_POST['_wpasc_nonce']) ? sanitize_text_field(wp_unslash($_POST['_wpasc_nonce'])) : '';784 if (!wp_verify_nonce($nonce, 'wpasc_comment_nonce')) {785 return $commentdata;786 }787 798 788 799 if (!isset($_POST['_wpasc_ts'])) { … … 811 822 * ─── 6. REST API Comment Protection ───────────────────────────────────────── 812 823 */ 813 if ($rbascs_options['enable_rest_protect']) { 814 add_filter('rest_pre_insert_comment', 'rbascs_rest_protect', 10, 2); 815 } 816 817 function rbascs_rest_protect($prepared_comment, $_request) 818 { 824 function rbascs_rest_protect($prepared_comment, $request) 825 { 826 unset($request); 819 827 if (!is_user_logged_in()) { 820 828 rbascs_record_block(); … … 831 839 * ─── 7. Hash-Based Verification on POST ───────────────────────────────────── 832 840 */ 833 if ($rbascs_options['enable_hash_check']) {834 add_action('pre_comment_on_post', 'rbascs_validate_hash_request');835 }836 837 841 function rbascs_validate_hash_request() 838 842 { 839 $query_string = isset($_SERVER['QUERY_STRING']) ? sanitize_text_field(wp_unslash($_SERVER['QUERY_STRING'])) : ''; 840 $has_key = hash_equals(RBASCS_UNIQUE_KEY, $query_string); 843 $query_string = isset($_SERVER['QUERY_STRING']) ? (string) wp_unslash($_SERVER['QUERY_STRING']) : ''; 844 845 // Tolerate extra query params (CDN/tracking) by looking for the key anywhere. 846 $parsed = array(); 847 parse_str($query_string, $parsed); 848 $has_key = false; 849 foreach (array_keys($parsed) as $param_name) { 850 if (hash_equals(RBASCS_UNIQUE_KEY, (string) $param_name)) { 851 $has_key = true; 852 break; 853 } 854 } 841 855 842 856 $referrer = wp_get_raw_referer(); … … 890 904 $stats['blocked_total']++; 891 905 $stats['blocked_today']++; 892 $stats['last_blocked_at'] = current_time('mysql'); 893 894 update_option('rbascs_stats', $stats); 906 $stats['last_blocked_at'] = time(); 907 908 update_option('rbascs_stats', $stats, false); 909 } 910 911 /** 912 * Normalize stored last-blocked value to a Unix timestamp. 913 * Pre-2.0.6 stored a mysql-format site-local string; new code stores time(). 914 */ 915 function rbascs_normalize_block_ts($value) 916 { 917 if (empty($value)) { 918 return 0; 919 } 920 if (is_numeric($value)) { 921 return (int) $value; 922 } 923 // Legacy: current_time('mysql') string in site timezone. 924 $ts = strtotime((string) $value . ' ' . wp_timezone_string()); 925 return $ts ? (int) $ts : 0; 895 926 } 896 927
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)