Plugin Directory

Changeset 3545826


Ignore:
Timestamp:
05/24/2026 05:31:39 AM (5 months ago)
Author:
rabbitbuilds
Message:

Release 2.0.6 — WP 7.0 compatibility, cache-friendly honeypot/time-check fix, refactor to init-time hook registration

Location:
rabbitbuilds-anti-spam-comment-shield
Files:
2 edited
8 copied

Legend:

Unmodified
Added
Removed
  • rabbitbuilds-anti-spam-comment-shield/tags/2.0.6/README.txt

    r3490773 r3545826  
    55Requires at least: 5.0
    66Requires PHP: 7.4
    7 Tested up to: 6.9
    8 Stable tag: 2.0.5
     7Tested up to: 7.0
     8Stable tag: 2.0.6
    99License: GPL-2.0-or-later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    2626* 🍯 **Honeypot Trap** — Hidden field that catches bots filling every input
    2727* ⏱️ **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)
    2929* 📊 **Spam Statistics Dashboard** — Real-time total & daily blocked spam counter
    3030* ⚙️ **Modern Settings Page** — Beautiful card-based UI with toggle switches
    … …  
    8484
    8585== 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
    8696
    8797= 2.0.5 =
    … …  
    187197== Upgrade Notice ==
    188198
     199= 2.0.6 =
     200WordPress 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
    189202= 2.0.5 =
    190203Refreshed 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  
    66 * Author:            Rabbit Builds
    77 * Author URI:        https://rabbitbuilds.com/
    8  * Version:           2.0.5
     8 * Version:           2.0.6
    99 * Text Domain:       rabbitbuilds-anti-spam-comment-shield
    1010 * Domain Path:       /languages
    … …  
    2121 * ─── Constants ───────────────────────────────────────────────────────────────
    2222 */
    23 define('RBASCS_VERSION', '2.0.5');
     23define('RBASCS_VERSION', '2.0.6');
    2424define('RBASCS_URL', plugin_dir_url(__FILE__));
    2525
    … …  
    4040        'enable_time_check' => 1,
    4141        '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' => '',
    4343        'enable_rest_protect' => 1,
    4444    );
    … …  
    7272        $stats['blocked_today'] = 0;
    7373        $stats['blocked_date'] = current_time('Y-m-d');
    74         update_option('rbascs_stats', $stats);
     74        update_option('rbascs_stats', $stats, false);
    7575    }
    7676
    … …  
    8787    set_transient('rbascs_activation_notice', true, 5);
    8888
    89     // Initialize stats if not existing
     89    // Initialize stats if not existing (non-autoloaded — read only on the settings page)
    9090    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);
    9292    }
    9393
    … …  
    306306                    <span class="wpasc-stat-last-time">
    307307                        <?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']);
    309309                        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'));
    311311                        } else {
    312312                            esc_html_e('No spam yet', 'rabbitbuilds-anti-spam-comment-shield');
    … …  
    413413                            </label>
    414414                            <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'); ?>
    416416                            </p>
    417417                        </div>
    … …  
    664664 */
    665665
    666 $rbascs_options = rbascs_get_options();
     666add_action('init', 'rbascs_maybe_upgrade');
     667add_action('init', 'rbascs_register_frontend_hooks');
     668
     669function 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
     684function 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}
    667708
    668709/**
    669710 * ─── 1. Remove Comment Action URL from HTML ─────────────────────────────────
    670711 */
    671 if ($rbascs_options['enable_hash_check']) {
    672     add_filter('comment_form_defaults', 'rbascs_remove_action_url');
    673 }
    674712
    675713function rbascs_remove_action_url($defaults)
    … …  
    682720 * ─── 2. Inject JavaScript to Restore Action URL on User Interaction ─────────
    683721 */
    684 if ($rbascs_options['enable_hash_check']) {
    685     add_action('wp_enqueue_scripts', 'rbascs_enqueue_frontend_js');
    686 }
    687 
    688722function rbascs_enqueue_frontend_js()
    689723{
    … …  
    732766 * ─── 3. Honeypot Field ──────────────────────────────────────────────────────
    733767 */
    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 
    739768function rbascs_honeypot_field()
    740769{
    741770    echo '<p style="position:absolute;left:-9999px;height:0;width:0;overflow:hidden;" aria-hidden="true">';
    742771    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')) . '" />';
    744772    echo '<input type="text" name="wpasc_website_url" id="wpasc_website_url" value="" tabindex="-1" autocomplete="off" />';
    745773    echo '</p>';
    … …  
    749777 * ─── 4. Validate Honeypot on Comment Pre-Process ────────────────────────────
    750778 */
    751 if ($rbascs_options['enable_honeypot']) {
    752     add_filter('preprocess_comment', 'rbascs_check_honeypot', 1);
    753 }
    754 
    755779function rbascs_check_honeypot($commentdata)
    756780{
    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 
    762781    $honeypot_value = isset($_POST['wpasc_website_url'])
    763782        ? sanitize_text_field(trim((string) wp_unslash($_POST['wpasc_website_url'])))
    … …  
    774793 * ─── 5. Validate Time-Based Check ───────────────────────────────────────────
    775794 */
    776 if ($rbascs_options['enable_time_check']) {
    777     add_filter('preprocess_comment', 'rbascs_check_time', 2);
    778 }
    779 
    780795function rbascs_check_time($commentdata)
    781796{
    782797    $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     }
    787798
    788799    if (!isset($_POST['_wpasc_ts'])) {
    … …  
    811822 * ─── 6. REST API Comment Protection ─────────────────────────────────────────
    812823 */
    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 {
     824function rbascs_rest_protect($prepared_comment, $request)
     825{
     826    unset($request);
    819827    if (!is_user_logged_in()) {
    820828        rbascs_record_block();
    … …  
    831839 * ─── 7. Hash-Based Verification on POST ─────────────────────────────────────
    832840 */
    833 if ($rbascs_options['enable_hash_check']) {
    834     add_action('pre_comment_on_post', 'rbascs_validate_hash_request');
    835 }
    836 
    837841function rbascs_validate_hash_request()
    838842{
    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    }
    841855
    842856    $referrer = wp_get_raw_referer();
    … …  
    890904    $stats['blocked_total']++;
    891905    $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 */
     915function 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;
    895926}
    896927
  • rabbitbuilds-anti-spam-comment-shield/trunk/README.txt

    r3490773 r3545826  
    55Requires at least: 5.0
    66Requires PHP: 7.4
    7 Tested up to: 6.9
    8 Stable tag: 2.0.5
     7Tested up to: 7.0
     8Stable tag: 2.0.6
    99License: GPL-2.0-or-later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    2626* 🍯 **Honeypot Trap** — Hidden field that catches bots filling every input
    2727* ⏱️ **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)
    2929* 📊 **Spam Statistics Dashboard** — Real-time total & daily blocked spam counter
    3030* ⚙️ **Modern Settings Page** — Beautiful card-based UI with toggle switches
    … …  
    8484
    8585== 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
    8696
    8797= 2.0.5 =
    … …  
    187197== Upgrade Notice ==
    188198
     199= 2.0.6 =
     200WordPress 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
    189202= 2.0.5 =
    190203Refreshed 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  
    66 * Author:            Rabbit Builds
    77 * Author URI:        https://rabbitbuilds.com/
    8  * Version:           2.0.5
     8 * Version:           2.0.6
    99 * Text Domain:       rabbitbuilds-anti-spam-comment-shield
    1010 * Domain Path:       /languages
    … …  
    2121 * ─── Constants ───────────────────────────────────────────────────────────────
    2222 */
    23 define('RBASCS_VERSION', '2.0.5');
     23define('RBASCS_VERSION', '2.0.6');
    2424define('RBASCS_URL', plugin_dir_url(__FILE__));
    2525
    … …  
    4040        'enable_time_check' => 1,
    4141        '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' => '',
    4343        'enable_rest_protect' => 1,
    4444    );
    … …  
    7272        $stats['blocked_today'] = 0;
    7373        $stats['blocked_date'] = current_time('Y-m-d');
    74         update_option('rbascs_stats', $stats);
     74        update_option('rbascs_stats', $stats, false);
    7575    }
    7676
    … …  
    8787    set_transient('rbascs_activation_notice', true, 5);
    8888
    89     // Initialize stats if not existing
     89    // Initialize stats if not existing (non-autoloaded — read only on the settings page)
    9090    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);
    9292    }
    9393
    … …  
    306306                    <span class="wpasc-stat-last-time">
    307307                        <?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']);
    309309                        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'));
    311311                        } else {
    312312                            esc_html_e('No spam yet', 'rabbitbuilds-anti-spam-comment-shield');
    … …  
    413413                            </label>
    414414                            <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'); ?>
    416416                            </p>
    417417                        </div>
    … …  
    664664 */
    665665
    666 $rbascs_options = rbascs_get_options();
     666add_action('init', 'rbascs_maybe_upgrade');
     667add_action('init', 'rbascs_register_frontend_hooks');
     668
     669function 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
     684function 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}
    667708
    668709/**
    669710 * ─── 1. Remove Comment Action URL from HTML ─────────────────────────────────
    670711 */
    671 if ($rbascs_options['enable_hash_check']) {
    672     add_filter('comment_form_defaults', 'rbascs_remove_action_url');
    673 }
    674712
    675713function rbascs_remove_action_url($defaults)
    … …  
    682720 * ─── 2. Inject JavaScript to Restore Action URL on User Interaction ─────────
    683721 */
    684 if ($rbascs_options['enable_hash_check']) {
    685     add_action('wp_enqueue_scripts', 'rbascs_enqueue_frontend_js');
    686 }
    687 
    688722function rbascs_enqueue_frontend_js()
    689723{
    … …  
    732766 * ─── 3. Honeypot Field ──────────────────────────────────────────────────────
    733767 */
    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 
    739768function rbascs_honeypot_field()
    740769{
    741770    echo '<p style="position:absolute;left:-9999px;height:0;width:0;overflow:hidden;" aria-hidden="true">';
    742771    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')) . '" />';
    744772    echo '<input type="text" name="wpasc_website_url" id="wpasc_website_url" value="" tabindex="-1" autocomplete="off" />';
    745773    echo '</p>';
    … …  
    749777 * ─── 4. Validate Honeypot on Comment Pre-Process ────────────────────────────
    750778 */
    751 if ($rbascs_options['enable_honeypot']) {
    752     add_filter('preprocess_comment', 'rbascs_check_honeypot', 1);
    753 }
    754 
    755779function rbascs_check_honeypot($commentdata)
    756780{
    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 
    762781    $honeypot_value = isset($_POST['wpasc_website_url'])
    763782        ? sanitize_text_field(trim((string) wp_unslash($_POST['wpasc_website_url'])))
    … …  
    774793 * ─── 5. Validate Time-Based Check ───────────────────────────────────────────
    775794 */
    776 if ($rbascs_options['enable_time_check']) {
    777     add_filter('preprocess_comment', 'rbascs_check_time', 2);
    778 }
    779 
    780795function rbascs_check_time($commentdata)
    781796{
    782797    $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     }
    787798
    788799    if (!isset($_POST['_wpasc_ts'])) {
    … …  
    811822 * ─── 6. REST API Comment Protection ─────────────────────────────────────────
    812823 */
    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 {
     824function rbascs_rest_protect($prepared_comment, $request)
     825{
     826    unset($request);
    819827    if (!is_user_logged_in()) {
    820828        rbascs_record_block();
    … …  
    831839 * ─── 7. Hash-Based Verification on POST ─────────────────────────────────────
    832840 */
    833 if ($rbascs_options['enable_hash_check']) {
    834     add_action('pre_comment_on_post', 'rbascs_validate_hash_request');
    835 }
    836 
    837841function rbascs_validate_hash_request()
    838842{
    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    }
    841855
    842856    $referrer = wp_get_raw_referer();
    … …  
    890904    $stats['blocked_total']++;
    891905    $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 */
     915function 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;
    895926}
    896927
Note: See TracChangeset for help on using the changeset viewer.