fix: CF7 bypass, auto-flush, layout, contrast, IP geo v2.4.0

CF7:
- Add wpcf7_spam filter registered before is_admin() early-return so
  CF7 AJAX submissions (admin-ajax.php) are properly validated
- Exclude CF7 posts from generic catch-all (prevent double-checking)

Auto-flush:
- Add maybe_flush_overdue() with 5-min transient lock, hooked to
  shutdown action so every PHP request can trigger a flush if overdue
- No longer depends solely on WP-Cron firing

Dashboard layout:
- Top Attackers moved into right column below live feed
- Viewport-fill layout: body/main use flex+overflow:hidden so content
  stays in view; left col scrolls independently if needed
- Feed panel takes flex:1, attackers panel capped at 260px

Colors:
- --dim: #006600 → #44bb77 (legible secondary text, ~5:1 contrast)
- --dim2: #228844 added for slightly darker secondary use
- --muted kept dark for backgrounds only; border lightened slightly

IP geo (server-side, async, non-blocking):
- country + asn columns added to blocks table (migration-safe)
- enrichIP() calls ip-api.com free HTTP API per unique IP, cached 1h
- Background job enriches historic rows missing country (5 per 20s)
- Stats and live feed now include country code + ASN
- Dashboard shows country flag emoji in feed rows and attackers table
- Full AS name shown as tooltip on ASN column

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 07:57:16 +01:00
parent 01a15007cb
commit 07b5025b0b
3 changed files with 437 additions and 414 deletions

View File

@@ -3,7 +3,7 @@
* Plugin Name: Honeypot Fields
* Plugin URI: https://informatiq.services
* Description: Adds invisible honeypot fields to all forms to block spam bots. Works with WordPress core forms, Elementor, Gravity Forms, Contact Form 7, WooCommerce, and more.
* Version: 2.3.0
* Version: 2.4.0
* Author: Malin
* Author URI: https://malin.ro
* License: GPL v2 or later
@@ -378,6 +378,20 @@ class SmartHoneypotAPIClient {
return count((array) get_option(self::OPT_QUEUE, []));
}
/**
* Fallback flush triggered on every PHP shutdown.
* A transient lock ensures we attempt at most once per 5 minutes
* regardless of traffic volume, so WP-Cron is not the sole trigger.
*/
public static function maybe_flush_overdue(): void {
$s = self::settings();
if (!$s['enabled'] || empty($s['api_url'])) return;
if (self::queue_size() === 0) return;
if (get_transient('hp_flush_lock')) return;
set_transient('hp_flush_lock', 1, 300); // 5-min lock
self::flush();
}
/**
* Returns the API token.
* Checks the HP_API_TOKEN constant (defined in wp-config.php) first,
@@ -1181,6 +1195,10 @@ class SmartHoneypotAntiSpam {
/* ── Init ──────────────────────────────────────────────────────── */
public function init() {
// CF7 submits via admin-ajax.php where is_admin()=true, so hook here
// before the early return so spam validation still runs.
add_filter('wpcf7_spam', [$this, 'validate_cf7_spam'], 10, 2);
if (is_admin()) {
add_action('admin_notices', [$this, 'activation_notice']);
return;
@@ -1423,6 +1441,13 @@ class SmartHoneypotAntiSpam {
}
}
/* ── Contact Form 7 ────────────────────────────────────────────── */
public function validate_cf7_spam($spam, $submission) {
if ($spam) return true; // already flagged
$this->current_form_type = 'Contact Form 7';
return !$this->check_submission(true);
}
/* ── Generic catch-all ─────────────────────────────────────────── */
public function validate_generic_post() {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
@@ -1436,6 +1461,7 @@ class SmartHoneypotAntiSpam {
isset($_POST['woocommerce-login-nonce']) ||
isset($_POST['woocommerce-process-checkout-nonce']) ||
isset($_POST['comment_post_ID']) ||
isset($_POST['_wpcf7']) || // CF7: handled by wpcf7_spam filter
(isset($_POST['action']) && $_POST['action'] === 'elementor_pro_forms_send_form')
) {
return;
@@ -1514,6 +1540,8 @@ add_action('plugins_loaded', function () {
}
new SmartHoneypotAntiSpam();
SmartHoneypotAdmin::register();
// Fallback: flush queue on every request's shutdown (rate-limited via transient)
add_action('shutdown', ['SmartHoneypotAPIClient', 'maybe_flush_overdue']);
});
// Custom cron interval (5 minutes)