2026-02-16 09:54:17 +01:00
< ? php
/**
* 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 .
2026-03-09 20:34:35 +01:00
* Version : 2.3 . 0
2026-02-16 09:54:17 +01:00
* Author : Malin
* Author URI : https :// malin . ro
* License : GPL v2 or later
* Text Domain : smart - honeypot
*/
if ( ! defined ( 'ABSPATH' )) {
exit ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
/* ======================================================================
* DATABASE HELPER
* ====================================================================*/
class SmartHoneypotDB {
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
const TABLE_VERSION = 1 ;
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
const TABLE_VERSION_OPTION = 'hp_db_version' ;
public static function table () : string {
global $wpdb ;
return $wpdb -> prefix . 'honeypot_log' ;
}
public static function install () {
global $wpdb ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$table = self :: table ();
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$charset_collate = $wpdb -> get_charset_collate ();
$sql = " CREATE TABLE { $table } (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
blocked_at DATETIME NOT NULL ,
ip_address VARCHAR ( 45 ) NOT NULL DEFAULT '' ,
form_type VARCHAR ( 100 ) NOT NULL DEFAULT '' ,
reason VARCHAR ( 255 ) NOT NULL DEFAULT '' ,
request_uri VARCHAR ( 1000 ) NOT NULL DEFAULT '' ,
user_agent TEXT NOT NULL ,
PRIMARY KEY ( id ),
KEY ip_address ( ip_address ),
KEY blocked_at ( blocked_at ),
KEY form_type ( form_type )
) { $charset_collate }; " ;
require_once ABSPATH . 'wp-admin/includes/upgrade.php' ;
dbDelta ( $sql );
update_option ( self :: TABLE_VERSION_OPTION , self :: TABLE_VERSION );
}
public static function insert ( array $data ) {
global $wpdb ;
$wpdb -> insert (
self :: table (),
[
'blocked_at' => current_time ( 'mysql' ),
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
'ip_address' => sanitize_text_field ( $data [ 'ip' ] ? ? '' ),
'form_type' => sanitize_text_field ( $data [ 'form' ] ? ? 'Unknown' ),
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
'reason' => sanitize_text_field ( $data [ 'reason' ] ? ? '' ),
'request_uri' => esc_url_raw ( substr ( $data [ 'uri' ] ? ? '' , 0 , 1000 )),
'user_agent' => sanitize_textarea_field ( $data [ 'ua' ] ? ? '' ),
],
[ '%s' , '%s' , '%s' , '%s' , '%s' , '%s' ]
);
}
public static function get_rows ( array $args = []) : array {
global $wpdb ;
$table = self :: table ();
$limit = max ( 1 , intval ( $args [ 'per_page' ] ? ? 25 ));
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$offset = max ( 0 , intval ( $args [ 'offset' ] ? ? 0 ));
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$where = '1=1' ;
$params = [];
if ( ! empty ( $args [ 'ip' ])) {
$where .= ' AND ip_address = %s' ;
$params [] = sanitize_text_field ( $args [ 'ip' ]);
}
if ( ! empty ( $args [ 'form' ])) {
$where .= ' AND form_type = %s' ;
$params [] = sanitize_text_field ( $args [ 'form' ]);
}
if ( ! empty ( $args [ 'search' ])) {
$like = '%' . $wpdb -> esc_like ( $args [ 'search' ]) . '%' ;
$where .= ' AND (ip_address LIKE %s OR user_agent LIKE %s OR reason LIKE %s)' ;
$params [] = $like ;
$params [] = $like ;
$params [] = $like ;
}
$params [] = $limit ;
$params [] = $offset ;
$sql = " SELECT * FROM { $table } WHERE { $where } ORDER BY blocked_at DESC LIMIT %d OFFSET %d " ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
return $wpdb -> get_results ( $wpdb -> prepare ( $sql , $params )) ? : [];
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
}
public static function count ( array $args = []) : int {
global $wpdb ;
$table = self :: table ();
$where = '1=1' ;
$params = [];
if ( ! empty ( $args [ 'ip' ])) {
$where .= ' AND ip_address = %s' ;
$params [] = sanitize_text_field ( $args [ 'ip' ]);
}
if ( ! empty ( $args [ 'form' ])) {
$where .= ' AND form_type = %s' ;
$params [] = sanitize_text_field ( $args [ 'form' ]);
}
if ( ! empty ( $args [ 'search' ])) {
$like = '%' . $wpdb -> esc_like ( $args [ 'search' ]) . '%' ;
$where .= ' AND (ip_address LIKE %s OR user_agent LIKE %s OR reason LIKE %s)' ;
$params [] = $like ;
$params [] = $like ;
$params [] = $like ;
}
$sql = " SELECT COUNT(*) FROM { $table } WHERE { $where } " ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
return ( int ) $wpdb -> get_var ( $params ? $wpdb -> prepare ( $sql , $params ) : $sql );
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
}
public static function get_form_types () : array {
global $wpdb ;
return $wpdb -> get_col ( " SELECT DISTINCT form_type FROM " . self :: table () . " ORDER BY form_type ASC " ) ? : [];
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
public static function clear () : void {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
global $wpdb ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$wpdb -> query ( " TRUNCATE TABLE " . self :: table ());
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
public static function delete_older_than_days ( int $days ) : void {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
global $wpdb ;
$wpdb -> query (
$wpdb -> prepare (
" DELETE FROM " . self :: table () . " WHERE blocked_at < DATE_SUB(NOW(), INTERVAL %d DAY) " ,
$days
)
);
}
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ======================================================================
* CENTRAL API CLIENT
* Queues blocked submissions and batch - sends to a central dashboard .
* ====================================================================*/
class SmartHoneypotAPIClient {
const OPT_SETTINGS = 'hp_api_settings' ;
const OPT_QUEUE = 'hp_api_queue' ;
const QUEUE_MAX = 500 ;
const BATCH_SIZE = 50 ;
public static function defaults () : array {
return [
2026-03-09 19:40:18 +01:00
'enabled' => false ,
'api_url' => '' ,
'api_token' => '' ,
'last_sync' => 0 ,
'sent_total' => 0 ,
'connection_ok' => null , // null=untested, true=ok, false=failed
'last_verified' => 0 ,
'last_error' => '' ,
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
];
}
2026-03-09 19:40:18 +01:00
/**
* Tests reachability ( health endpoint ) and auth ( submit with bad payload ) .
* Returns [ 'ok' => bool , 'message' => string ]
*/
public static function test_connection () : array {
$s = self :: settings ();
if ( empty ( $s [ 'api_url' ])) {
return [ 'ok' => false , 'message' => 'No API URL configured.' ];
}
$base = trailingslashit ( esc_url_raw ( $s [ 'api_url' ]));
$headers = [ 'Content-Type' => 'application/json' ];
2026-03-09 20:34:35 +01:00
$token = self :: resolve_token ();
if ( $token !== '' ) {
$headers [ 'Authorization' ] = 'Bearer ' . $token ;
2026-03-09 19:40:18 +01:00
}
// Step 1 — reachability
$health = wp_remote_get ( $base . 'api/v1/health' , [ 'timeout' => 8 ]);
if ( is_wp_error ( $health )) {
return [ 'ok' => false , 'message' => 'Cannot reach API: ' . $health -> get_error_message ()];
}
$code = wp_remote_retrieve_response_code ( $health );
if ( $code !== 200 ) {
return [ 'ok' => false , 'message' => " API returned HTTP { $code } . Verify the URL is correct. " ];
}
// Step 2 — token validation: POST with an intentionally invalid payload.
// Auth passes → 400 (bad payload). Wrong/missing token → 403.
$auth = wp_remote_post ( $base . 'api/v1/submit' , [
'timeout' => 8 ,
'headers' => $headers ,
'body' => wp_json_encode ([ 'site_hash' => 'connectivity_test' , 'blocks' => []]),
]);
if ( is_wp_error ( $auth )) {
return [ 'ok' => false , 'message' => 'Token check request failed: ' . $auth -> get_error_message ()];
}
$auth_code = wp_remote_retrieve_response_code ( $auth );
if ( $auth_code === 403 ) {
return [ 'ok' => false , 'message' => 'API reachable but token rejected (HTTP 403). Check the token matches API_TOKEN in Docker.' ];
}
// 400 = auth passed, payload correctly rejected — exactly what we expect
return [ 'ok' => true , 'message' => 'Connection verified. API is reachable and token is accepted.' ];
}
2026-03-09 19:54:50 +01:00
/**
* Sends one batch of existing local log records to the central API .
* Picks up from where it left off using the hp_history_last_id option .
*
* Returns [ 'ok' , 'sent' , 'remaining' , 'has_more' , 'message' ]
*/
public static function send_history_batch ( int $batch_size = 50 ) : array {
$s = self :: settings ();
if ( empty ( $s [ 'api_url' ])) {
return [ 'ok' => false , 'message' => 'No API URL configured.' ];
}
global $wpdb ;
$table = SmartHoneypotDB :: table ();
$last_id = ( int ) get_option ( 'hp_history_last_id' , 0 );
$total = SmartHoneypotDB :: count ();
$rows = $wpdb -> get_results (
$wpdb -> prepare (
" SELECT * FROM { $table } WHERE id > %d ORDER BY id ASC LIMIT %d " ,
$last_id , $batch_size
),
ARRAY_A
);
if ( empty ( $rows )) {
return [ 'ok' => true , 'sent' => 0 , 'remaining' => 0 , 'has_more' => false ,
'message' => 'All records have already been sent.' ];
}
$blocks = array_map ( fn ( $r ) => [
'ip' => $r [ 'ip_address' ],
'form_type' => $r [ 'form_type' ],
'reason' => $r [ 'reason' ],
'user_agent' => $r [ 'user_agent' ],
'blocked_at' => $r [ 'blocked_at' ],
], $rows );
$headers = [ 'Content-Type' => 'application/json' ];
2026-03-09 20:34:35 +01:00
$token = self :: resolve_token ();
if ( $token !== '' ) {
$headers [ 'Authorization' ] = 'Bearer ' . $token ;
2026-03-09 19:54:50 +01:00
}
$response = wp_remote_post (
trailingslashit ( esc_url_raw ( $s [ 'api_url' ])) . 'api/v1/submit' ,
[
'timeout' => 30 ,
'headers' => $headers ,
'body' => wp_json_encode ([
'site_hash' => hash ( 'sha256' , home_url ()),
'blocks' => $blocks ,
]),
]
);
if ( is_wp_error ( $response )) {
return [ 'ok' => false , 'message' => 'Request failed: ' . $response -> get_error_message ()];
}
$code = wp_remote_retrieve_response_code ( $response );
if ( $code !== 200 ) {
return [ 'ok' => false , 'message' => " API returned HTTP { $code } . Check connection settings. " ];
}
$new_last_id = ( int ) end ( $rows )[ 'id' ];
$sent_total = ( int ) get_option ( 'hp_history_total_sent' , 0 ) + count ( $rows );
update_option ( 'hp_history_last_id' , $new_last_id );
update_option ( 'hp_history_total_sent' , $sent_total );
$remaining = max ( 0 , $total - $sent_total );
return [
'ok' => true ,
'sent' => count ( $rows ),
'remaining' => $remaining ,
'has_more' => $remaining > 0 ,
'message' => sprintf ( 'Sent %d records. %d remaining.' , count ( $rows ), $remaining ),
];
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
public static function settings () : array {
return wp_parse_args ( get_option ( self :: OPT_SETTINGS , []), self :: defaults ());
}
/** Called from log_spam() — very fast, just appends to option. */
public static function enqueue ( array $data ) : void {
$s = self :: settings ();
if ( ! $s [ 'enabled' ] || empty ( $s [ 'api_url' ])) {
return ;
}
$queue = ( array ) get_option ( self :: OPT_QUEUE , []);
if ( count ( $queue ) >= self :: QUEUE_MAX ) {
array_shift ( $queue ); // drop oldest when full
}
$queue [] = $data ;
update_option ( self :: OPT_QUEUE , $queue , false ); // no autoload
}
/** Called by WP-cron every 5 minutes. Sends pending batch to the API. */
public static function flush () : void {
$s = self :: settings ();
if ( ! $s [ 'enabled' ] || empty ( $s [ 'api_url' ])) {
return ;
}
$queue = ( array ) get_option ( self :: OPT_QUEUE , []);
if ( empty ( $queue )) {
return ;
}
$batch = array_splice ( $queue , 0 , self :: BATCH_SIZE );
$site_hash = hash ( 'sha256' , home_url ());
2026-03-09 19:26:23 +01:00
$headers = [ 'Content-Type' => 'application/json' ];
2026-03-09 20:34:35 +01:00
$token = self :: resolve_token ();
if ( $token !== '' ) {
$headers [ 'Authorization' ] = 'Bearer ' . $token ;
2026-03-09 19:26:23 +01:00
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$response = wp_remote_post (
trailingslashit ( esc_url_raw ( $s [ 'api_url' ])) . 'api/v1/submit' ,
[
'timeout' => 15 ,
'blocking' => true ,
2026-03-09 19:26:23 +01:00
'headers' => $headers ,
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
'body' => wp_json_encode ([
'site_hash' => $site_hash ,
'blocks' => $batch ,
]),
]
);
if ( ! is_wp_error ( $response ) && wp_remote_retrieve_response_code ( $response ) === 200 ) {
update_option ( self :: OPT_QUEUE , $queue , false );
$s [ 'last_sync' ] = time ();
$s [ 'sent_total' ] = ( $s [ 'sent_total' ] ? ? 0 ) + count ( $batch );
update_option ( self :: OPT_SETTINGS , $s );
}
}
/** Number of items currently waiting to be sent. */
public static function queue_size () : int {
return count (( array ) get_option ( self :: OPT_QUEUE , []));
}
2026-03-09 20:34:35 +01:00
/**
* Returns the API token .
* Checks the HP_API_TOKEN constant ( defined in wp - config . php ) first ,
* then falls back to the value stored in the database .
*/
private static function resolve_token () : string {
if ( defined ( 'HP_API_TOKEN' ) && HP_API_TOKEN !== '' ) {
return ( string ) HP_API_TOKEN ;
}
return self :: settings ()[ 'api_token' ] ? ? '' ;
}
}
/* ======================================================================
* INTERNATIONALISATION
* ====================================================================*/
class SmartHoneypotI18n {
const USER_META = 'hp_lang' ;
// phpcs:disable Generic.Files.LineLength
const STRINGS = [
'en' => [
'tab_logs' => 'Blocked Logs' ,
'tab_api' => 'Central API' ,
'cleared' => 'Logs cleared.' ,
'saved' => 'API settings saved.' ,
'flushed' => 'Queue flushed to central API.' ,
'history_reset_msg' => 'History sync progress has been reset. You can re-send from the beginning.' ,
'click_next' => 'Click "Send Next Batch" to continue.' ,
'total_blocked' => 'Total Blocked' ,
'today' => 'Today' ,
'unique_ips' => 'Unique IPs' ,
'form_types_hit' => 'Form Types Hit' ,
'search_ph' => 'Search IP, UA, reason…' ,
'filter_ip_ph' => 'Filter by IP' ,
'all_forms' => 'All form types' ,
'filter_btn' => 'Filter' ,
'reset_btn' => 'Reset' ,
'clear_logs' => 'Clear All Logs' ,
'clear_confirm' => 'Delete ALL log entries permanently?' ,
'col_date' => 'Date / Time' ,
'col_ip' => 'IP Address' ,
'col_form' => 'Form Type' ,
'col_reason' => 'Reason' ,
'col_uri' => 'URI' ,
'col_ua' => 'User Agent' ,
'no_results' => 'No blocked attempts recorded yet.' ,
'filter_link' => 'filter' ,
'lookup_link' => 'lookup ↗' ,
'prev' => '← Prev' ,
'next' => 'Next →' ,
'showing' => 'Showing' ,
'results' => 'result(s)' ,
'page_of' => 'page %d of %d' ,
'settings_title' => 'Central API Settings' ,
'settings_desc' => 'Submit blocked attempts to a central dashboard for aggregate threat intelligence. Data sent: full IP address, form type, block reason, UA family, and timestamp. No site URL or usernames are ever sent.' ,
'enable_label' => 'Enable Submission' ,
'enable_cb' => 'Send blocked attempts to the central API' ,
'url_label' => 'API Endpoint URL' ,
'url_desc' => 'Base URL of your Honeypot API Docker container.' ,
'token_label' => 'API Token' ,
'token_desc' => 'Must match the <code>API_TOKEN</code> set in your Docker container\'s environment. Leave empty only if the API runs without a token (not recommended).' ,
'token_const_note' => 'Token is set via the <code>HP_API_TOKEN</code> constant in <code>wp-config.php</code>.' ,
'save_settings' => 'Save Settings' ,
'conn_status' => 'Connection Status' ,
'conn_label' => 'Connection' ,
'conn_ok' => 'Verified — connected and token accepted' ,
'conn_fail' => 'Connection failed' ,
'conn_untested' => 'Not tested yet' ,
'last_verified' => 'Last Verified' ,
'enabled_lbl' => 'Enabled' ,
'yes' => 'Yes' ,
'no' => 'No' ,
'last_sync' => 'Last Sync' ,
'never' => 'Never' ,
'total_sent' => 'Total Sent' ,
'blocks_unit' => 'blocks' ,
'queue_size' => 'Queue Size' ,
'pending_unit' => 'pending' ,
'next_flush' => 'Next Auto-Flush' ,
'not_scheduled' => 'Not scheduled' ,
'test_conn' => 'Test Connection' ,
'flush_queue' => 'Flush Queue Now' ,
'history_title' => 'Send History to API' ,
'history_desc' => 'Populate the central dashboard with your existing log so charts and stats are meaningful right away, without waiting for new attacks. Records are sent in batches of 50.' ,
'local_log' => 'Local Log' ,
'local_log_val' => '%s records in this site\'s database' ,
'sent_api' => 'Sent to API' ,
'remaining_lbl' => 'Remaining' ,
'remaining_val' => '%s records not yet sent' ,
'send_history' => 'Send History' ,
'send_next' => 'Send Next Batch' ,
'all_sent' => '✓ All history sent' ,
'reset_progress' => 'Reset Progress' ,
],
'es' => [
'tab_logs' => 'Registros Bloqueados' ,
'tab_api' => 'API Central' ,
'cleared' => 'Registros eliminados.' ,
'saved' => 'Configuración de API guardada.' ,
'flushed' => 'Cola enviada a la API central.' ,
'history_reset_msg' => 'El progreso de sincronización se ha restablecido. Puedes reenviar desde el principio.' ,
'click_next' => 'Haz clic en "Enviar Siguiente Lote" para continuar.' ,
'total_blocked' => 'Total Bloqueados' ,
'today' => 'Hoy' ,
'unique_ips' => 'IPs Únicas' ,
'form_types_hit' => 'Tipos de Formulario' ,
'search_ph' => 'Buscar IP, UA, razón…' ,
'filter_ip_ph' => 'Filtrar por IP' ,
'all_forms' => 'Todos los tipos' ,
'filter_btn' => 'Filtrar' ,
'reset_btn' => 'Reiniciar' ,
'clear_logs' => 'Borrar Todos los Registros' ,
'clear_confirm' => '¿Eliminar TODOS los registros permanentemente?' ,
'col_date' => 'Fecha / Hora' ,
'col_ip' => 'Dirección IP' ,
'col_form' => 'Tipo de Formulario' ,
'col_reason' => 'Razón' ,
'col_uri' => 'URI' ,
'col_ua' => 'User Agent' ,
'no_results' => 'No hay intentos bloqueados aún.' ,
'filter_link' => 'filtrar' ,
'lookup_link' => 'consultar ↗' ,
'prev' => '← Anterior' ,
'next' => 'Siguiente →' ,
'showing' => 'Mostrando' ,
'results' => 'resultado(s)' ,
'page_of' => 'página %d de %d' ,
'settings_title' => 'Configuración de la API Central' ,
'settings_desc' => 'Envía intentos bloqueados a un panel central de inteligencia de amenazas. Se envía: IP completa, tipo de formulario, razón de bloqueo, familia de UA y marca de tiempo. Nunca se envían URLs del sitio ni nombres de usuario.' ,
'enable_label' => 'Activar Envío' ,
'enable_cb' => 'Enviar intentos bloqueados a la API central' ,
'url_label' => 'URL del Endpoint de la API' ,
'url_desc' => 'URL base del contenedor Docker de la API Honeypot.' ,
'token_label' => 'Token de la API' ,
'token_desc' => 'Debe coincidir con <code>API_TOKEN</code> en el entorno del contenedor Docker.' ,
'token_const_note' => 'El token está definido mediante la constante <code>HP_API_TOKEN</code> en <code>wp-config.php</code>.' ,
'save_settings' => 'Guardar Configuración' ,
'conn_status' => 'Estado de la Conexión' ,
'conn_label' => 'Conexión' ,
'conn_ok' => 'Verificada — conectada y token aceptado' ,
'conn_fail' => 'Error de conexión' ,
'conn_untested' => 'No probada todavía' ,
'last_verified' => 'Última Verificación' ,
'enabled_lbl' => 'Activado' ,
'yes' => 'Sí' ,
'no' => 'No' ,
'last_sync' => 'Última Sincronización' ,
'never' => 'Nunca' ,
'total_sent' => 'Total Enviados' ,
'blocks_unit' => 'bloqueos' ,
'queue_size' => 'Tamaño de Cola' ,
'pending_unit' => 'pendientes' ,
'next_flush' => 'Próximo Envío Automático' ,
'not_scheduled' => 'No programado' ,
'test_conn' => 'Probar Conexión' ,
'flush_queue' => 'Enviar Cola Ahora' ,
'history_title' => 'Enviar Historial a la API' ,
'history_desc' => 'Rellena el panel central con tu registro existente para que las estadísticas sean significativas de inmediato, sin esperar nuevos ataques. Los registros se envían en lotes de 50.' ,
'local_log' => 'Registro Local' ,
'local_log_val' => '%s registros en la base de datos de este sitio' ,
'sent_api' => 'Enviados a la API' ,
'remaining_lbl' => 'Restantes' ,
'remaining_val' => '%s registros aún no enviados' ,
'send_history' => 'Enviar Historial' ,
'send_next' => 'Enviar Siguiente Lote' ,
'all_sent' => '✓ Todo el historial enviado' ,
'reset_progress' => 'Reiniciar Progreso' ,
],
'ro' => [
'tab_logs' => 'Jurnale Blocate' ,
'tab_api' => 'API Central' ,
'cleared' => 'Jurnale șterse.' ,
'saved' => 'Setări API salvate.' ,
'flushed' => 'Coada trimisă la API-ul central.' ,
'history_reset_msg' => 'Progresul sincronizării a fost resetat. Poți retrimite de la început.' ,
'click_next' => 'Apasă „Trimite Lotul Următor" pentru a continua.' ,
'total_blocked' => 'Total Blocate' ,
'today' => 'Azi' ,
'unique_ips' => 'IP-uri Unice' ,
'form_types_hit' => 'Tipuri de Formulare Atacate' ,
'search_ph' => 'Caută IP, UA, motiv…' ,
'filter_ip_ph' => 'Filtrează după IP' ,
'all_forms' => 'Toate tipurile' ,
'filter_btn' => 'Filtrează' ,
'reset_btn' => 'Resetează' ,
'clear_logs' => 'Șterge Toate Jurnalele' ,
'clear_confirm' => 'Ștergi TOATE înregistrările permanent?' ,
'col_date' => 'Dată / Oră' ,
'col_ip' => 'Adresă IP' ,
'col_form' => 'Tip Formular' ,
'col_reason' => 'Motiv' ,
'col_uri' => 'URI' ,
'col_ua' => 'User Agent' ,
'no_results' => 'Nu există tentative blocate încă.' ,
'filter_link' => 'filtrează' ,
'lookup_link' => 'caută ↗' ,
'prev' => '← Anterior' ,
'next' => 'Următor →' ,
'showing' => 'Afișând' ,
'results' => 'rezultat(e)' ,
'page_of' => 'pagina %d din %d' ,
'settings_title' => 'Setări API Central' ,
'settings_desc' => 'Trimite tentativele blocate la un panou central de informații despre amenințări. Date trimise: IP complet, tip formular, motiv blocare, familie UA și marcă temporală. Nu se trimit niciodată URL-ul site-ului sau nume de utilizatori.' ,
'enable_label' => 'Activează Trimiterea' ,
'enable_cb' => 'Trimite tentativele blocate la API-ul central' ,
'url_label' => 'URL Endpoint API' ,
'url_desc' => 'URL-ul de bază al containerului Docker API Honeypot.' ,
'token_label' => 'Token API' ,
'token_desc' => 'Trebuie să coincidă cu <code>API_TOKEN</code> din mediul containerului Docker.' ,
'token_const_note' => 'Tokenul este setat prin constanta <code>HP_API_TOKEN</code> în <code>wp-config.php</code>.' ,
'save_settings' => 'Salvează Setările' ,
'conn_status' => 'Status Conexiune' ,
'conn_label' => 'Conexiune' ,
'conn_ok' => 'Verificată — conectată și token acceptat' ,
'conn_fail' => 'Conexiune eșuată' ,
'conn_untested' => 'Netestată încă' ,
'last_verified' => 'Ultima Verificare' ,
'enabled_lbl' => 'Activat' ,
'yes' => 'Da' ,
'no' => 'Nu' ,
'last_sync' => 'Ultima Sincronizare' ,
'never' => 'Niciodată' ,
'total_sent' => 'Total Trimise' ,
'blocks_unit' => 'blocări' ,
'queue_size' => 'Dimensiune Coadă' ,
'pending_unit' => 'în așteptare' ,
'next_flush' => 'Următoarea Trimitere Automată' ,
'not_scheduled' => 'Neprogramată' ,
'test_conn' => 'Testează Conexiunea' ,
'flush_queue' => 'Trimite Coada Acum' ,
'history_title' => 'Trimite Istoricul la API' ,
'history_desc' => 'Populează panoul central cu jurnalul existent pentru ca statisticile să fie relevante imediat, fără a aștepta noi atacuri. Înregistrările se trimit în loturi de 50.' ,
'local_log' => 'Jurnal Local' ,
'local_log_val' => '%s înregistrări în baza de date a acestui site' ,
'sent_api' => 'Trimise la API' ,
'remaining_lbl' => 'Rămase' ,
'remaining_val' => '%s înregistrări netrimise' ,
'send_history' => 'Trimite Istoricul' ,
'send_next' => 'Trimite Lotul Următor' ,
'all_sent' => '✓ Tot istoricul a fost trimis' ,
'reset_progress' => 'Resetează Progresul' ,
],
];
// phpcs:enable
public static function get_lang () : string {
$user_id = get_current_user_id ();
$lang = $user_id ? ( string ) get_user_meta ( $user_id , self :: USER_META , true ) : '' ;
return in_array ( $lang , [ 'en' , 'es' , 'ro' ], true ) ? $lang : 'en' ;
}
public static function t ( string $key ) : string {
$lang = self :: get_lang ();
$strings = self :: STRINGS [ $lang ] ? ? self :: STRINGS [ 'en' ];
return $strings [ $key ] ? ? ( self :: STRINGS [ 'en' ][ $key ] ? ? $key );
}
public static function flag_switcher () : string {
$lang = self :: get_lang ();
$nonce = wp_nonce_field ( 'hp_admin_action' , '_wpnonce' , true , false );
$tab = sanitize_key ( $_GET [ 'tab' ] ? ? 'logs' );
$html = '<div style="display:inline-flex;gap:4px;align-items:center">' ;
foreach ([ 'en' => '🇬🇧' , 'es' => '🇪🇸' , 'ro' => '🇷🇴' ] as $code => $flag ) {
$style = $lang === $code
? 'background:none;border:none;cursor:pointer;padding:2px;font-size:22px;opacity:1'
: 'background:none;border:none;cursor:pointer;padding:2px;font-size:16px;opacity:0.45' ;
$html .= sprintf (
'<form method="post" style="margin:0">%s'
. '<input type="hidden" name="tab" value="%s">'
. '<input type="hidden" name="hp_action" value="set_language">'
. '<input type="hidden" name="hp_lang" value="%s">'
. '<button type="submit" title="%s" style="%s">%s</button></form>' ,
$nonce ,
esc_attr ( $tab ),
esc_attr ( $code ),
esc_attr ( strtoupper ( $code )),
esc_attr ( $style ),
$flag
);
}
$html .= '</div>' ;
return $html ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
/* ======================================================================
* ADMIN PAGE
* ====================================================================*/
class SmartHoneypotAdmin {
const MENU_SLUG = 'honeypot-logs' ;
const NONCE_ACTION = 'hp_admin_action' ;
const PER_PAGE = 25 ;
public static function register () {
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
add_action ( 'admin_menu' , [ self :: class , 'add_menu' ]);
add_action ( 'admin_init' , [ self :: class , 'handle_actions' ]);
add_action ( 'admin_enqueue_scripts' , [ self :: class , 'enqueue_styles' ]);
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
add_filter ( 'plugin_action_links_' . plugin_basename ( HP_PLUGIN_FILE ), [ self :: class , 'plugin_links' ]);
}
public static function plugin_links ( $links ) {
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
array_unshift ( $links , '<a href="' . admin_url ( 'admin.php?page=' . self :: MENU_SLUG ) . '">View Logs</a>' );
$links [] = '<a href="https://informatiq.services" target="_blank">Documentation</a>' ;
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
return $links ;
}
public static function add_menu () {
add_menu_page (
'Honeypot Logs' ,
'Honeypot Logs' ,
'manage_options' ,
self :: MENU_SLUG ,
[ self :: class , 'render_page' ],
'dashicons-shield-alt' ,
81
);
}
public static function enqueue_styles ( $hook ) {
if ( $hook !== 'toplevel_page_' . self :: MENU_SLUG ) {
return ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
wp_add_inline_style ( 'common' , '
#hp-wrap { max-width:1400px; }
#hp-wrap .hp-tabs { margin:16px 0 0; }
#hp-wrap .hp-stats { display:flex; gap:14px; margin:16px 0; flex-wrap:wrap; }
#hp-wrap .hp-stat-card { background:#fff; border:1px solid #c3c4c7; border-radius:4px; padding:14px 22px; min-width:130px; text-align:center; }
#hp-wrap .hp-stat-num { font-size:2em; font-weight:700; color:#2271b1; line-height:1.2; }
#hp-wrap .hp-stat-lbl { color:#646970; font-size:12px; }
#hp-wrap .hp-filters { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-bottom:12px; }
#hp-wrap .hp-filters input, #hp-wrap .hp-filters select { height:32px; }
#hp-wrap table.hp-log { width:100%; border-collapse:collapse; background:#fff; }
#hp-wrap table.hp-log th { background:#f0f0f1; padding:8px 12px; text-align:left; border-bottom:2px solid #c3c4c7; white-space:nowrap; }
#hp-wrap table.hp-log td { padding:8px 12px; border-bottom:1px solid #f0f0f1; vertical-align:top; }
#hp-wrap table.hp-log tr:hover td { background:#f6f7f7; }
#hp-wrap .hp-ua { font-size:11px; color:#646970; max-width:300px; word-break:break-all; }
#hp-wrap .hp-badge { display:inline-block; padding:2px 8px; border-radius:3px; font-size:11px; font-weight:600; background:#ffecec; color:#b32d2e; border:1px solid #f7c5c5; }
#hp-wrap .hp-pager { margin:12px 0; display:flex; align-items:center; gap:8px; }
#hp-wrap .hp-pager a, #hp-wrap .hp-pager span { display:inline-block; padding:4px 10px; border:1px solid #c3c4c7; border-radius:3px; background:#fff; text-decoration:none; color:#2271b1; }
#hp-wrap .hp-pager span.current { background:#2271b1; color:#fff; border-color:#2271b1; }
#hp-wrap .hp-red { color:#b32d2e; }
#hp-wrap .hp-api-status { display:inline-flex; align-items:center; gap:6px; font-weight:600; }
#hp-wrap .hp-api-status .dot { width:10px; height:10px; border-radius:50%; display:inline-block; }
#hp-wrap .dot-on { background:#00a32a; }
#hp-wrap .dot-off { background:#646970; }
' );
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
}
public static function handle_actions () {
if ( ! isset ( $_POST [ 'hp_action' ]) || ! check_admin_referer ( self :: NONCE_ACTION )) {
return ;
}
if ( ! current_user_can ( 'manage_options' )) {
wp_die ( 'Unauthorized' );
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
if ( $_POST [ 'hp_action' ] === 'clear_logs' ) {
SmartHoneypotDB :: clear ();
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => 'logs' , 'cleared' => 1 ], admin_url ( 'admin.php' )));
exit ;
}
if ( $_POST [ 'hp_action' ] === 'save_api_settings' ) {
2026-03-09 19:40:18 +01:00
$current = SmartHoneypotAPIClient :: settings ();
$new_url = esc_url_raw ( trim ( $_POST [ 'hp_api_url' ] ? ? '' ));
2026-03-09 20:34:35 +01:00
$new_token = defined ( 'HP_API_TOKEN' ) ? $current [ 'api_token' ] : sanitize_text_field ( $_POST [ 'hp_api_token' ] ? ? '' );
2026-03-09 19:40:18 +01:00
$url_changed = $new_url !== $current [ 'api_url' ];
$tok_changed = $new_token !== $current [ 'api_token' ];
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$new = [
2026-03-09 19:40:18 +01:00
'enabled' => ! empty ( $_POST [ 'hp_api_enabled' ]),
'api_url' => $new_url ,
'api_token' => $new_token ,
'last_sync' => $current [ 'last_sync' ],
'sent_total' => $current [ 'sent_total' ],
// Reset verification if URL or token changed
'connection_ok' => ( $url_changed || $tok_changed ) ? null : $current [ 'connection_ok' ],
'last_verified' => ( $url_changed || $tok_changed ) ? 0 : $current [ 'last_verified' ],
'last_error' => ( $url_changed || $tok_changed ) ? '' : $current [ 'last_error' ],
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
];
update_option ( SmartHoneypotAPIClient :: OPT_SETTINGS , $new );
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => 'settings' , 'saved' => 1 ], admin_url ( 'admin.php' )));
exit ;
}
2026-03-09 19:40:18 +01:00
if ( $_POST [ 'hp_action' ] === 'test_connection' ) {
$result = SmartHoneypotAPIClient :: test_connection ();
$s = SmartHoneypotAPIClient :: settings ();
$s [ 'connection_ok' ] = $result [ 'ok' ];
$s [ 'last_verified' ] = time ();
$s [ 'last_error' ] = $result [ 'ok' ] ? '' : $result [ 'message' ];
update_option ( SmartHoneypotAPIClient :: OPT_SETTINGS , $s );
set_transient ( 'hp_conn_result' , $result , 60 );
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => 'settings' , 'tested' => 1 ], admin_url ( 'admin.php' )));
exit ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
if ( $_POST [ 'hp_action' ] === 'flush_queue' ) {
SmartHoneypotAPIClient :: flush ();
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => 'settings' , 'flushed' => 1 ], admin_url ( 'admin.php' )));
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
exit ;
}
2026-03-09 19:54:50 +01:00
if ( $_POST [ 'hp_action' ] === 'send_history' ) {
$result = SmartHoneypotAPIClient :: send_history_batch ();
set_transient ( 'hp_history_result' , $result , 60 );
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => 'settings' , 'history' => 1 ], admin_url ( 'admin.php' )));
exit ;
}
if ( $_POST [ 'hp_action' ] === 'reset_history' ) {
delete_option ( 'hp_history_last_id' );
delete_option ( 'hp_history_total_sent' );
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => 'settings' , 'history_reset' => 1 ], admin_url ( 'admin.php' )));
exit ;
}
2026-03-09 20:34:35 +01:00
if ( $_POST [ 'hp_action' ] === 'set_language' ) {
$lang = sanitize_key ( $_POST [ 'hp_lang' ] ? ? 'en' );
if ( in_array ( $lang , [ 'en' , 'es' , 'ro' ], true )) {
update_user_meta ( get_current_user_id (), SmartHoneypotI18n :: USER_META , $lang );
}
$tab = sanitize_key ( $_GET [ 'tab' ] ? ? 'logs' );
wp_redirect ( add_query_arg ([ 'page' => self :: MENU_SLUG , 'tab' => $tab ], admin_url ( 'admin.php' )));
exit ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
}
public static function render_page () {
if ( ! current_user_can ( 'manage_options' )) {
return ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$tab = sanitize_key ( $_GET [ 'tab' ] ? ? 'logs' );
?>
< div class = " wrap " id = " hp-wrap " >
< h1 class = " wp-heading-inline " > Honeypot Fields </ h1 >
2026-03-09 20:34:35 +01:00
< span style = " margin-left:14px;vertical-align:middle " >< ? = SmartHoneypotI18n :: flag_switcher () ?> </span>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php if ( ! empty ( $_GET [ 'cleared' ])) : ?>
2026-03-09 20:34:35 +01:00
< div class = " notice notice-success is-dismissible " >< p >< ? = SmartHoneypotI18n :: t ( 'cleared' ) ?> </p></div>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php endif ; ?>
< ? php if ( ! empty ( $_GET [ 'saved' ])) : ?>
2026-03-09 20:34:35 +01:00
< div class = " notice notice-success is-dismissible " >< p >< ? = SmartHoneypotI18n :: t ( 'saved' ) ?> </p></div>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php endif ; ?>
< ? php if ( ! empty ( $_GET [ 'flushed' ])) : ?>
2026-03-09 20:34:35 +01:00
< div class = " notice notice-success is-dismissible " >< p >< ? = SmartHoneypotI18n :: t ( 'flushed' ) ?> </p></div>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php endif ; ?>
2026-03-09 19:40:18 +01:00
< ? php if ( ! empty ( $_GET [ 'tested' ])) :
$res = get_transient ( 'hp_conn_result' );
if ( $res ) :
$cls = $res [ 'ok' ] ? 'notice-success' : 'notice-error' ; ?>
< div class = " notice <?= $cls ?> is-dismissible " >< p >< ? = esc_html ( $res [ 'message' ]) ?> </p></div>
< ? php endif ;
endif ; ?>
2026-03-09 19:54:50 +01:00
< ? php if ( ! empty ( $_GET [ 'history' ])) :
$res = get_transient ( 'hp_history_result' );
if ( $res ) :
$cls = $res [ 'ok' ] ? 'notice-success' : 'notice-error' ; ?>
< div class = " notice <?= $cls ?> is-dismissible " >
< p >< ? = esc_html ( $res [ 'message' ]) ?>
< ? php if ( ! empty ( $res [ 'has_more' ])) : ?>
2026-03-09 20:34:35 +01:00
& nbsp ; < strong >< ? = SmartHoneypotI18n :: t ( 'click_next' ) ?> </strong>
2026-03-09 19:54:50 +01:00
< ? php endif ; ?>
</ p >
</ div >
< ? php endif ;
endif ; ?>
< ? php if ( ! empty ( $_GET [ 'history_reset' ])) : ?>
2026-03-09 20:34:35 +01:00
< div class = " notice notice-info is-dismissible " >< p >< ? = SmartHoneypotI18n :: t ( 'history_reset_msg' ) ?> </p></div>
2026-03-09 19:54:50 +01:00
< ? php endif ; ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< nav class = " nav-tab-wrapper hp-tabs " >
< a href = " <?= esc_url(admin_url('admin.php?page=' . self::MENU_SLUG . '&tab=logs')) ?> "
class = " nav-tab <?= $tab === 'logs' ? 'nav-tab-active' : '' ?> " >
2026-03-09 20:34:35 +01:00
< ? = SmartHoneypotI18n :: t ( 'tab_logs' ) ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ a >
< a href = " <?= esc_url(admin_url('admin.php?page=' . self::MENU_SLUG . '&tab=settings')) ?> "
class = " nav-tab <?= $tab === 'settings' ? 'nav-tab-active' : '' ?> " >
2026-03-09 20:34:35 +01:00
< ? = SmartHoneypotI18n :: t ( 'tab_api' ) ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ a >
</ nav >
< ? php if ( $tab === 'settings' ) : ?>
< ? php self :: render_settings_tab (); ?>
< ? php else : ?>
< ? php self :: render_logs_tab (); ?>
< ? php endif ; ?>
</ div >
< ? php
}
/* ── Logs tab ─────────────────────────────────────────────────── */
private static function render_logs_tab () {
2026-03-09 20:34:35 +01:00
$T = fn ( string $k ) : string => SmartHoneypotI18n :: t ( $k );
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$search = sanitize_text_field ( $_GET [ 'hp_search' ] ? ? '' );
$filter_ip = sanitize_text_field ( $_GET [ 'hp_ip' ] ? ? '' );
$filter_form = sanitize_text_field ( $_GET [ 'hp_form' ] ? ? '' );
$paged = max ( 1 , intval ( $_GET [ 'paged' ] ? ? 1 ));
$per_page = self :: PER_PAGE ;
$offset = ( $paged - 1 ) * $per_page ;
$qargs = array_filter ([
'ip' => $filter_ip , 'form' => $filter_form ,
'search' => $search , 'per_page' => $per_page , 'offset' => $offset ,
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
]);
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$rows = SmartHoneypotDB :: get_rows ( $qargs );
$total = SmartHoneypotDB :: count ( $qargs );
$total_ever = SmartHoneypotDB :: count ();
$form_types = SmartHoneypotDB :: get_form_types ();
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$total_pages = max ( 1 , ceil ( $total / $per_page ));
global $wpdb ;
$unique_ips = ( int ) $wpdb -> get_var ( " SELECT COUNT(DISTINCT ip_address) FROM " . SmartHoneypotDB :: table ());
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$today = ( int ) $wpdb -> get_var ( " SELECT COUNT(*) FROM " . SmartHoneypotDB :: table () . " WHERE blocked_at >= CURDATE() " );
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$base = admin_url ( 'admin.php?page=' . self :: MENU_SLUG . '&tab=logs' );
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
<!-- Stats -->
< div class = " hp-stats " >
2026-03-09 20:34:35 +01:00
< div class = " hp-stat-card " >< div class = " hp-stat-num " >< ? = number_format ( $total_ever ) ?> </div><div class="hp-stat-lbl"><?= $T('total_blocked') ?></div></div>
< div class = " hp-stat-card " >< div class = " hp-stat-num " >< ? = number_format ( $today ) ?> </div><div class="hp-stat-lbl"><?= $T('today') ?></div></div>
< div class = " hp-stat-card " >< div class = " hp-stat-num " >< ? = number_format ( $unique_ips ) ?> </div><div class="hp-stat-lbl"><?= $T('unique_ips') ?></div></div>
< div class = " hp-stat-card " >< div class = " hp-stat-num " >< ? = count ( $form_types ) ?> </div><div class="hp-stat-lbl"><?= $T('form_types_hit') ?></div></div>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ div >
<!-- Filters + clear -->
< form method = " get " >
< input type = " hidden " name = " page " value = " <?= esc_attr(self::MENU_SLUG) ?> " >
< input type = " hidden " name = " tab " value = " logs " >
< div class = " hp-filters " >
2026-03-09 20:34:35 +01:00
< input type = " text " name = " hp_search " placeholder = " <?= esc_attr( $T ('search_ph')) ?> " value = " <?= esc_attr( $search ) ?> " size = " 28 " >
< input type = " text " name = " hp_ip " placeholder = " <?= esc_attr( $T ('filter_ip_ph')) ?> " value = " <?= esc_attr( $filter_ip ) ?> " >
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< select name = " hp_form " >
2026-03-09 20:34:35 +01:00
< option value = " " >< ? = $T ( 'all_forms' ) ?> </option>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php foreach ( $form_types as $ft ) : ?>
< option value = " <?= esc_attr( $ft ) ?> " < ? = selected ( $filter_form , $ft , false ) ?> ><?= esc_html($ft) ?></option>
< ? php endforeach ; ?>
</ select >
2026-03-09 20:34:35 +01:00
< button type = " submit " class = " button " >< ? = $T ( 'filter_btn' ) ?> </button>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php if ( $search || $filter_ip || $filter_form ) : ?>
2026-03-09 20:34:35 +01:00
< a href = " <?= esc_url( $base ) ?> " class = " button " >< ? = $T ( 'reset_btn' ) ?> </a>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php endif ; ?>
< span style = " flex:1 " ></ span >
2026-03-09 20:34:35 +01:00
< form method = " post " style = " display:inline " onsubmit = " return confirm('<?= esc_js( $T ('clear_confirm')) ?>') " >
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php wp_nonce_field ( self :: NONCE_ACTION ); ?>
< input type = " hidden " name = " hp_action " value = " clear_logs " >
2026-03-09 20:34:35 +01:00
< button type = " submit " class = " button hp-red " >< ? = $T ( 'clear_logs' ) ?> </button>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ form >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
</ div >
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ form >
2026-03-09 20:34:35 +01:00
< p >< ? = $T ( 'showing' ) ?> <strong><?= number_format($total) ?></strong> <?= $T('results') ?> (<?= sprintf($T('page_of'), $paged, $total_pages) ?>)</p>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< table class = " hp-log widefat " >
< thead >
2026-03-09 20:34:35 +01:00
< tr >< th > #</th><th><?= $T('col_date') ?></th><th><?= $T('col_ip') ?></th><th><?= $T('col_form') ?></th><th><?= $T('col_reason') ?></th><th><?= $T('col_uri') ?></th><th><?= $T('col_ua') ?></th></tr>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ thead >
< tbody >
< ? php if ( empty ( $rows )) : ?>
2026-03-09 20:34:35 +01:00
< tr >< td colspan = " 7 " style = " text-align:center;padding:24px;color:#646970 " >< ? = $T ( 'no_results' ) ?> </td></tr>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php else : foreach ( $rows as $row ) : ?>
< tr >
< td >< ? = esc_html ( $row -> id ) ?> </td>
< td style = " white-space:nowrap " >< ? = esc_html ( $row -> blocked_at ) ?> </td>
< td >
< code >< ? = esc_html ( $row -> ip_address ) ?> </code><br>
2026-03-09 20:34:35 +01:00
< a href = " <?= esc_url(add_query_arg(['page' => self::MENU_SLUG, 'tab' => 'logs', 'hp_ip' => $row->ip_address ], admin_url('admin.php'))) ?> " style = " font-size:11px " >< ? = $T ( 'filter_link' ) ?> </a>
& nbsp ; < a href = " https://ipinfo.io/<?= esc_attr(urlencode( $row->ip_address )) ?> " target = " _blank " style = " font-size:11px " >< ? = $T ( 'lookup_link' ) ?> </a>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ td >
< td >< span class = " hp-badge " >< ? = esc_html ( $row -> form_type ) ?> </span></td>
< td >< ? = esc_html ( $row -> reason ) ?> </td>
< td style = " font-size:11px;word-break:break-all " >< ? = esc_html ( $row -> request_uri ) ?> </td>
< td class = " hp-ua " >< ? = esc_html ( $row -> user_agent ) ?> </td>
</ tr >
< ? php endforeach ; endif ; ?>
</ tbody >
</ table >
< ? php if ( $total_pages > 1 ) : ?>
< div class = " hp-pager " >
< ? php if ( $paged > 1 ) : ?>
2026-03-09 20:34:35 +01:00
< a href = " <?= esc_url(add_query_arg(array_merge( $_GET , ['paged' => $paged - 1]))) ?> " >< ? = $T ( 'prev' ) ?> </a>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php endif ; ?>
< ? php for ( $p = max ( 1 , $paged - 3 ); $p <= min ( $total_pages , $paged + 3 ); $p ++ ) :
$url = esc_url ( add_query_arg ( array_merge ( $_GET , [ 'paged' => $p ]))); ?>
< ? php if ( $p === $paged ) : ?>
< span class = " current " >< ? = $p ?> </span>
< ? php else : ?>
< a href = " <?= $url ?> " >< ? = $p ?> </a>
< ? php endif ; ?>
< ? php endfor ; ?>
< ? php if ( $paged < $total_pages ) : ?>
2026-03-09 20:34:35 +01:00
< a href = " <?= esc_url(add_query_arg(array_merge( $_GET , ['paged' => $paged + 1]))) ?> " >< ? = $T ( 'next' ) ?> </a>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< ? php endif ; ?>
</ div >
< ? php endif ; ?>
< ? php
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Settings / API tab ───────────────────────────────────────── */
private static function render_settings_tab () {
2026-03-09 20:34:35 +01:00
$T = fn ( string $k ) : string => SmartHoneypotI18n :: t ( $k );
$s = SmartHoneypotAPIClient :: settings ();
$queue_size = SmartHoneypotAPIClient :: queue_size ();
$next_run = wp_next_scheduled ( 'hp_api_flush' );
$token_via_const = defined ( 'HP_API_TOKEN' ) && HP_API_TOKEN !== '' ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
?>
< div style = " max-width:700px;margin-top:20px " >
2026-03-09 20:34:35 +01:00
< h2 >< ? = $T ( 'settings_title' ) ?> </h2>
< p style = " color:#646970;margin-bottom:16px " >< ? = $T ( 'settings_desc' ) ?> </p>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< form method = " post " >
< ? php wp_nonce_field ( self :: NONCE_ACTION ); ?>
< input type = " hidden " name = " hp_action " value = " save_api_settings " >
< table class = " form-table " >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'enable_label' ) ?> </th>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< td >
< label >
< input type = " checkbox " name = " hp_api_enabled " value = " 1 " < ? = checked ( $s [ 'enabled' ]) ?> >
2026-03-09 20:34:35 +01:00
< ? = $T ( 'enable_cb' ) ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ label >
</ td >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
</ tr >
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'url_label' ) ?> </th>
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
< td >
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< input type = " url " name = " hp_api_url " value = " <?= esc_attr( $s['api_url'] ) ?> "
class = " regular-text " placeholder = " https://your-api-host:3000 " >
2026-03-09 20:34:35 +01:00
< p class = " description " >< ? = $T ( 'url_desc' ) ?> </p>
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
</ td >
</ tr >
2026-03-09 19:26:23 +01:00
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'token_label' ) ?> </th>
2026-03-09 19:26:23 +01:00
< td >
2026-03-09 20:34:35 +01:00
< ? php if ( $token_via_const ) : ?>
< input type = " text " class = " regular-text " value = " •••••••••••• " disabled >
< p class = " description " >< ? = $T ( 'token_const_note' ) ?> </p>
< ? php else : ?>
< input type = " password " name = " hp_api_token " value = " <?= esc_attr( $s['api_token'] ) ?> "
class = " regular-text " placeholder = " Bearer token (matches API_TOKEN in docker-compose) " >
< p class = " description " >< ? = $T ( 'token_desc' ) ?> </p>
< ? php endif ; ?>
2026-03-09 19:26:23 +01:00
</ td >
</ tr >
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ table >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
2026-03-09 20:34:35 +01:00
< ? php submit_button ( $T ( 'save_settings' )); ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ form >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< hr >
2026-03-09 20:34:35 +01:00
< h3 >< ? = $T ( 'conn_status' ) ?> </h3>
2026-03-09 19:40:18 +01:00
< ? php
$conn = $s [ 'connection_ok' ];
if ( $conn === true ) {
2026-03-09 20:34:35 +01:00
$dot_class = 'dot-on' ;
$dot_label = $T ( 'conn_ok' );
$dot_style = '' ;
2026-03-09 19:40:18 +01:00
} elseif ( $conn === false ) {
2026-03-09 20:34:35 +01:00
$dot_class = 'dot-fail' ;
$dot_label = $T ( 'conn_fail' );
$dot_style = 'background:#b32d2e;' ;
2026-03-09 19:40:18 +01:00
} else {
2026-03-09 20:34:35 +01:00
$dot_class = 'dot-off' ;
$dot_label = $T ( 'conn_untested' );
$dot_style = '' ;
2026-03-09 19:40:18 +01:00
}
?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< table class = " form-table " >
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'conn_label' ) ?> </th>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
< td >
< span class = " hp-api-status " >
2026-03-09 19:40:18 +01:00
< span class = " dot <?= $dot_class ?> " style = " <?= $dot_style ?> " ></ span >
< ? = esc_html ( $dot_label ) ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ span >
2026-03-09 19:40:18 +01:00
< ? php if ( $conn === false && $s [ 'last_error' ]) : ?>
< p class = " description " style = " color:#b32d2e;margin-top:4px " >< ? = esc_html ( $s [ 'last_error' ]) ?> </p>
< ? php endif ; ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ td >
</ tr >
2026-03-09 19:40:18 +01:00
< ? php if ( $s [ 'last_verified' ]) : ?>
2026-03-09 20:34:35 +01:00
< tr >< th >< ? = $T ( 'last_verified' ) ?> </th><td><?= esc_html(date('Y-m-d H:i:s', $s['last_verified'])) ?></td></tr>
2026-03-09 19:40:18 +01:00
< ? php endif ; ?>
2026-03-09 20:34:35 +01:00
< tr >< th >< ? = $T ( 'enabled_lbl' ) ?> </th><td><?= $s['enabled'] ? $T('yes') : $T('no') ?></td></tr>
< tr >< th >< ? = $T ( 'last_sync' ) ?> </th><td><?= $s['last_sync'] ? esc_html(date('Y-m-d H:i:s', $s['last_sync'])) : $T('never') ?></td></tr>
< tr >< th >< ? = $T ( 'total_sent' ) ?> </th><td><?= number_format((int) $s['sent_total']) ?> <?= $T('blocks_unit') ?></td></tr>
< tr >< th >< ? = $T ( 'queue_size' ) ?> </th><td><?= number_format($queue_size) ?> <?= $T('pending_unit') ?></td></tr>
< tr >< th >< ? = $T ( 'next_flush' ) ?> </th><td><?= $next_run ? esc_html(date('Y-m-d H:i:s', $next_run)) . ' (every 5 min)' : $T('not_scheduled') ?></td></tr>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ table >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
2026-03-09 19:40:18 +01:00
< div style = " display:flex;gap:10px;margin-top:14px;flex-wrap:wrap;align-items:center " >
< ? php if ( $s [ 'api_url' ]) : ?>
< form method = " post " >
< ? php wp_nonce_field ( self :: NONCE_ACTION ); ?>
< input type = " hidden " name = " hp_action " value = " test_connection " >
2026-03-09 20:34:35 +01:00
< button type = " submit " class = " button button-primary " >< ? = $T ( 'test_conn' ) ?> </button>
2026-03-09 19:40:18 +01:00
</ form >
< ? php endif ; ?>
< ? php if ( $queue_size > 0 && $s [ 'enabled' ] && $s [ 'api_url' ]) : ?>
< form method = " post " >
< ? php wp_nonce_field ( self :: NONCE_ACTION ); ?>
< input type = " hidden " name = " hp_action " value = " flush_queue " >
2026-03-09 20:34:35 +01:00
< button type = " submit " class = " button button-secondary " >< ? = $T ( 'flush_queue' ) ?> (<?= $queue_size ?> <?= $T('pending_unit') ?>)</button>
2026-03-09 19:40:18 +01:00
</ form >
< ? php endif ; ?>
</ div >
2026-03-09 19:54:50 +01:00
< ? php if ( $s [ 'api_url' ] && $s [ 'enabled' ]) : ?>
< hr >
2026-03-09 20:34:35 +01:00
< h3 >< ? = $T ( 'history_title' ) ?> </h3>
< p style = " color:#646970;margin-bottom:12px " >< ? = $T ( 'history_desc' ) ?> </p>
2026-03-09 19:54:50 +01:00
< ? php
$local_total = SmartHoneypotDB :: count ();
$history_sent = ( int ) get_option ( 'hp_history_total_sent' , 0 );
$remaining = max ( 0 , $local_total - $history_sent );
$pct = $local_total > 0 ? min ( 100 , round ( $history_sent / $local_total * 100 )) : 0 ;
?>
< table class = " form-table " >
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'local_log' ) ?> </th>
< td >< ? = sprintf ( $T ( 'local_log_val' ), number_format ( $local_total )) ?> </td>
2026-03-09 19:54:50 +01:00
</ tr >
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'sent_api' ) ?> </th>
2026-03-09 19:54:50 +01:00
< td >
2026-03-09 20:34:35 +01:00
< ? = number_format ( $history_sent ) ?> (<?= $pct ?>%)
2026-03-09 19:54:50 +01:00
< ? php if ( $local_total > 0 ) : ?>
< div style = " margin-top:6px;background:#f0f0f1;border-radius:3px;height:8px;max-width:300px " >
< div style = " background:#2271b1;height:100%;border-radius:3px;width:<?= $pct ?>%;transition:width .4s " ></ div >
</ div >
< ? php endif ; ?>
</ td >
</ tr >
< tr >
2026-03-09 20:34:35 +01:00
< th >< ? = $T ( 'remaining_lbl' ) ?> </th>
< td >< ? = sprintf ( $T ( 'remaining_val' ), number_format ( $remaining )) ?> </td>
2026-03-09 19:54:50 +01:00
</ tr >
</ table >
< div style = " display:flex;gap:10px;margin-top:12px;flex-wrap:wrap;align-items:center " >
< ? php if ( $remaining > 0 ) : ?>
< form method = " post " >
< ? php wp_nonce_field ( self :: NONCE_ACTION ); ?>
< input type = " hidden " name = " hp_action " value = " send_history " >
< button type = " submit " class = " button button-secondary " >
2026-03-09 20:34:35 +01:00
< ? = $history_sent === 0 ? $T ( 'send_history' ) : $T ( 'send_next' ) ?>
( < ? = min ( 50 , $remaining ) ?> of <?= number_format($remaining) ?> <?= $T('pending_unit') ?>)
2026-03-09 19:54:50 +01:00
</ button >
</ form >
< ? php else : ?>
2026-03-09 20:34:35 +01:00
< span style = " color:#00a32a;font-weight:600 " >< ? = $T ( 'all_sent' ) ?> </span>
2026-03-09 19:54:50 +01:00
< ? php endif ; ?>
< ? php if ( $history_sent > 0 ) : ?>
< form method = " post " onsubmit = " return confirm('Reset history sync progress? This allows re-sending all records from the beginning.') " >
< ? php wp_nonce_field ( self :: NONCE_ACTION ); ?>
< input type = " hidden " name = " hp_action " value = " reset_history " >
2026-03-09 20:34:35 +01:00
< button type = " submit " class = " button " >< ? = $T ( 'reset_progress' ) ?> </button>
2026-03-09 19:54:50 +01:00
</ form >
< ? php endif ; ?>
</ div >
< ? php endif ; ?>
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
</ div >
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
< ? php
}
}
/* ======================================================================
* MAIN PLUGIN CLASS
* ====================================================================*/
2026-02-16 09:54:17 +01:00
class SmartHoneypotAntiSpam {
private $hp_name ;
private $token_name ;
private $time_name ;
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
private $current_form_type = 'Unknown' ;
2026-02-16 09:54:17 +01:00
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
private const MIN_SUBMIT_TIME = 3 ;
private const MAX_SUBMIT_TIME = 7200 ;
private const RATE_LIMIT = 3 ;
2026-02-16 09:54:17 +01:00
private $secret ;
public function __construct () {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> secret = wp_hash ( 'honeypot_plugin_secret_v2' );
$this -> hp_name = 'website_url_confirm' ;
2026-02-16 09:54:17 +01:00
$this -> token_name = 'form_session_id' ;
$this -> time_name = 'form_render_ts' ;
add_action ( 'init' , [ $this , 'init' ]);
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Init ──────────────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function init () {
if ( is_admin ()) {
add_action ( 'admin_notices' , [ $this , 'activation_notice' ]);
return ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
// Inject honeypot
2026-02-16 09:54:17 +01:00
add_filter ( 'the_content' , [ $this , 'add_to_content_forms' ], 99 );
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
add_action ( 'comment_form_after_fields' , [ $this , 'echo_honeypot' ]);
2026-02-16 09:54:17 +01:00
add_action ( 'comment_form_logged_in_after' , [ $this , 'echo_honeypot' ]);
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
add_action ( 'woocommerce_register_form' , [ $this , 'echo_honeypot' ]);
add_action ( 'woocommerce_login_form' , [ $this , 'echo_honeypot' ]);
add_action ( 'woocommerce_after_order_notes' ,[ $this , 'echo_honeypot' ]);
add_action ( 'register_form' , [ $this , 'echo_honeypot' ]);
add_action ( 'login_form' , [ $this , 'echo_honeypot' ]);
add_action ( 'elementor_pro/forms/render_field' , [ $this , 'add_to_elementor_form' ], 10 , 2 );
add_action ( 'elementor/widget/render_content' , [ $this , 'filter_elementor_widget' ], 10 , 2 );
add_filter ( 'gform_form_tag' , [ $this , 'add_to_gravity_forms' ], 10 , 2 );
add_filter ( 'wpcf7_form_elements' , [ $this , 'add_to_cf7' ]);
add_filter ( 'get_search_form' , [ $this , 'add_to_search_form' ], 99 );
2026-02-16 09:54:17 +01:00
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
// Validate
2026-02-16 09:54:17 +01:00
add_filter ( 'woocommerce_process_registration_errors' , [ $this , 'validate_wc_registration' ], 10 , 4 );
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
add_filter ( 'woocommerce_process_login_errors' , [ $this , 'validate_wc_login' ], 10 , 3 );
add_action ( 'woocommerce_after_checkout_validation' , [ $this , 'validate_wc_checkout' ], 10 , 2 );
add_filter ( 'registration_errors' , [ $this , 'validate_wp_registration' ], 10 , 3 );
add_filter ( 'preprocess_comment' , [ $this , 'validate_comment' ]);
add_action ( 'elementor_pro/forms/validation' , [ $this , 'validate_elementor_form' ], 10 , 2 );
add_action ( 'template_redirect' , [ $this , 'validate_generic_post' ]);
2026-02-16 09:54:17 +01:00
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
// CSS & JS
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
add_action ( 'wp_head' , [ $this , 'print_css' ]);
2026-02-16 09:54:17 +01:00
add_action ( 'wp_footer' , [ $this , 'print_js' ], 99 );
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Honeypot HTML ─────────────────────────────────────────────── */
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
private function get_honeypot_html () : string {
2026-02-16 09:54:17 +01:00
return sprintf (
' < div class = " frm-extra-field " aria - hidden = " true " >
< label for = " %1 $s " > Website URL Confirmation </ label >
< input type = " text " id = " %1 $s " name = " %1 $s " value = " " tabindex = " -1 " autocomplete = " off " />
< input type = " hidden " name = " %2 $s " value = " " />
< input type = " hidden " name = " %3 $s " value = " %4 $s " />
</ div > ' ,
esc_attr ( $this -> hp_name ),
esc_attr ( $this -> token_name ),
esc_attr ( $this -> time_name ),
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
esc_attr ( time ())
2026-02-16 09:54:17 +01:00
);
}
public function echo_honeypot () {
echo $this -> get_honeypot_html ();
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Injection helpers ─────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function add_to_content_forms ( $content ) {
if ( is_admin () || is_feed ()) {
return $content ;
}
return preg_replace_callback (
'/(<form\b[^>]*>)(.*?)(<\/form>)/is' ,
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
fn ( $m ) => $m [ 1 ] . $m [ 2 ] . $this -> get_honeypot_html () . $m [ 3 ],
2026-02-16 09:54:17 +01:00
$content
);
}
public function add_to_search_form ( $form ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
return preg_replace ( '/(<\/form>)/i' , $this -> get_honeypot_html () . '$1' , $form , 1 );
2026-02-16 09:54:17 +01:00
}
public function add_to_elementor_form ( $field , $instance ) {
static $done = false ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
if ( ! $done && $field [ 'type' ] === 'submit' ) { $done = true ; echo $this -> get_honeypot_html (); }
2026-02-16 09:54:17 +01:00
}
public function filter_elementor_widget ( $content , $widget ) {
if ( $widget -> get_name () === 'form' ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$content = preg_replace ( '/(<\/form>)/i' , $this -> get_honeypot_html () . '$1' , $content , 1 );
2026-02-16 09:54:17 +01:00
}
return $content ;
}
public function add_to_gravity_forms ( $tag , $form ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
return preg_replace ( '/(<div class="gform_footer)/i' , $this -> get_honeypot_html () . '$1' , $tag , 1 );
2026-02-16 09:54:17 +01:00
}
public function add_to_cf7 ( $form ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
return preg_replace ( '/(\[submit[^\]]*\])/i' , $this -> get_honeypot_html () . '$1' , $form , 1 );
2026-02-16 09:54:17 +01:00
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Validation ────────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
private function check_submission ( bool $require_fields = true ) : bool {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
if ( $require_fields && ! isset ( $_POST [ $this -> hp_name ])) {
$this -> log_spam ( 'Honeypot field missing (direct POST)' );
return false ;
2026-02-16 09:54:17 +01:00
}
if ( isset ( $_POST [ $this -> hp_name ]) && $_POST [ $this -> hp_name ] !== '' ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> log_spam ( 'Honeypot field was filled in' );
2026-02-16 09:54:17 +01:00
return false ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
if ( $require_fields && empty ( $_POST [ $this -> token_name ])) {
$this -> log_spam ( 'JS token absent (no JavaScript)' );
return false ;
}
if ( ! empty ( $_POST [ $this -> token_name ]) && ! $this -> validate_js_token ( $_POST [ $this -> token_name ])) {
$this -> log_spam ( 'JS token invalid or tampered' );
return false ;
2026-02-16 09:54:17 +01:00
}
if ( $require_fields && ! isset ( $_POST [ $this -> time_name ])) {
$this -> log_spam ( 'Timestamp field missing' );
return false ;
}
if ( isset ( $_POST [ $this -> time_name ])) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$diff = time () - intval ( $_POST [ $this -> time_name ]);
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
if ( $diff < self :: MIN_SUBMIT_TIME ) { $this -> log_spam ( " Submitted too fast ( { $diff } s) " ); return false ; }
if ( $diff > self :: MAX_SUBMIT_TIME ) { $this -> log_spam ( " Timestamp expired ( { $diff } s) " ); return false ; }
2026-02-16 09:54:17 +01:00
}
$this -> clean_post_data ();
return true ;
}
private function validate_js_token ( string $token ) : bool {
$parts = explode ( '|' , $token );
if ( count ( $parts ) !== 2 ) {
return false ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$expected = hash_hmac ( 'sha256' , $parts [ 0 ] . '|honeypot_js_proof' , $this -> secret );
return hash_equals ( substr ( $expected , 0 , 16 ), $parts [ 1 ]);
2026-02-16 09:54:17 +01:00
}
private function clean_post_data () {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
foreach ([ $this -> hp_name , $this -> token_name , $this -> time_name ] as $k ) {
unset ( $_POST [ $k ], $_REQUEST [ $k ]);
2026-02-16 09:54:17 +01:00
}
}
private function log_spam ( string $reason ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$ip = $_SERVER [ 'REMOTE_ADDR' ] ? ? '' ;
$uri = $_SERVER [ 'REQUEST_URI' ] ? ? '' ;
$ua = $_SERVER [ 'HTTP_USER_AGENT' ] ? ? '' ;
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
// Write to local DB
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
SmartHoneypotDB :: insert ([
'ip' => $ip ,
'form' => $this -> current_form_type ,
'reason' => $reason ,
'uri' => $uri ,
'ua' => $ua ,
]);
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
// Queue for central API
SmartHoneypotAPIClient :: enqueue ([
'ip' => $ip ,
'form_type' => $this -> current_form_type ,
'reason' => $reason ,
'user_agent' => $ua ,
'blocked_at' => current_time ( 'mysql' ),
]);
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
error_log ( " [Honeypot] { $reason } | form= { $this -> current_form_type } | ip= { $ip } | uri= { $uri } " );
2026-02-16 09:54:17 +01:00
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Rate limiting ─────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
private function check_rate_limit () : bool {
$ip = $_SERVER [ 'REMOTE_ADDR' ] ? ? '' ;
if ( ! $ip ) {
return false ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$key = 'hp_rate_' . md5 ( $ip );
2026-02-16 09:54:17 +01:00
$count = ( int ) get_transient ( $key );
if ( $count >= self :: RATE_LIMIT ) {
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$this -> log_spam ( " Rate limit exceeded ( { $count } /hr from { $ip } ) " );
2026-02-16 09:54:17 +01:00
return false ;
}
set_transient ( $key , $count + 1 , HOUR_IN_SECONDS );
return true ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── WooCommerce ───────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function validate_wc_registration ( $errors , $username , $password , $email ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> current_form_type = 'WooCommerce Registration' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( true )) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$errors -> add ( 'honeypot_spam' , __ ( '<strong>Error</strong>: Registration blocked. Enable JavaScript and try again.' , 'smart-honeypot' ));
2026-02-16 09:54:17 +01:00
return $errors ;
}
if ( ! $this -> check_rate_limit ()) {
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
$errors -> add ( 'honeypot_rate' , __ ( '<strong>Error</strong>: Too many attempts. Try again later.' , 'smart-honeypot' ));
2026-02-16 09:54:17 +01:00
}
return $errors ;
}
public function validate_wc_login ( $errors , $username , $password ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> current_form_type = 'WooCommerce Login' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( true )) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$errors -> add ( 'honeypot_spam' , __ ( '<strong>Error</strong>: Login blocked. Enable JavaScript and try again.' , 'smart-honeypot' ));
2026-02-16 09:54:17 +01:00
}
return $errors ;
}
public function validate_wc_checkout ( $data , $errors ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> current_form_type = 'WooCommerce Checkout' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( false )) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$errors -> add ( 'honeypot_spam' , __ ( 'Order could not be processed. Please try again.' , 'smart-honeypot' ));
2026-02-16 09:54:17 +01:00
}
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── WordPress core ────────────────────────────────────────────── */
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
public function validate_wp_registration ( $errors , $login , $email ) {
$this -> current_form_type = 'WP Registration' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( true )) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$errors -> add ( 'honeypot_spam' , __ ( '<strong>Error</strong>: Registration blocked. Enable JavaScript and try again.' , 'smart-honeypot' ));
2026-02-16 09:54:17 +01:00
}
if ( ! $this -> check_rate_limit ()) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$errors -> add ( 'honeypot_rate' , __ ( '<strong>Error</strong>: Too many attempts. Try again later.' , 'smart-honeypot' ));
2026-02-16 09:54:17 +01:00
}
return $errors ;
}
public function validate_comment ( $commentdata ) {
if ( is_user_logged_in () && current_user_can ( 'moderate_comments' )) {
$this -> clean_post_data ();
return $commentdata ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> current_form_type = 'Comment Form' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( true )) {
wp_die (
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
__ ( 'Comment blocked as spam. Enable JavaScript and try again.' , 'smart-honeypot' ),
2026-02-16 09:54:17 +01:00
__ ( 'Spam Detected' , 'smart-honeypot' ),
[ 'response' => 403 , 'back_link' => true ]
);
}
return $commentdata ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Elementor ─────────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function validate_elementor_form ( $record , $ajax_handler ) {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> current_form_type = 'Elementor Form' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( true )) {
$ajax_handler -> add_error ( 'honeypot' , __ ( 'Spam detected. Please try again.' , 'smart-honeypot' ));
}
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Generic catch-all ─────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function validate_generic_post () {
if ( $_SERVER [ 'REQUEST_METHOD' ] !== 'POST' ) {
return ;
}
if ( ! isset ( $_POST [ $this -> hp_name ]) && ! isset ( $_POST [ $this -> token_name ])) {
return ;
}
if (
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
isset ( $_POST [ 'woocommerce-register-nonce' ]) ||
isset ( $_POST [ 'woocommerce-login-nonce' ]) ||
isset ( $_POST [ 'woocommerce-process-checkout-nonce' ]) ||
isset ( $_POST [ 'comment_post_ID' ]) ||
2026-02-16 09:54:17 +01:00
( isset ( $_POST [ 'action' ]) && $_POST [ 'action' ] === 'elementor_pro_forms_send_form' )
) {
return ;
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$this -> current_form_type = 'Generic Form' ;
2026-02-16 09:54:17 +01:00
if ( ! $this -> check_submission ( false )) {
if ( wp_doing_ajax ()) {
wp_send_json_error ([ 'message' => __ ( 'Spam detected.' , 'smart-honeypot' )]);
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
wp_safe_redirect ( wp_get_referer () ? : home_url ());
2026-02-16 09:54:17 +01:00
exit ;
}
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── CSS ───────────────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function print_css () {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
echo '<style>.frm-extra-field{position:absolute!important;left:-9999px!important;top:-9999px!important;height:0!important;width:0!important;overflow:hidden!important;opacity:0!important;pointer-events:none!important;z-index:-1!important;clip:rect(0,0,0,0)!important}</style>' ;
2026-02-16 09:54:17 +01:00
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── JS — HMAC token via SubtleCrypto ──────────────────────────── */
2026-02-16 09:54:17 +01:00
public function print_js () {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$secret = esc_js ( $this -> secret );
2026-02-16 09:54:17 +01:00
$token_name = esc_js ( $this -> token_name );
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
$time_name = esc_js ( $this -> time_name );
2026-02-16 09:54:17 +01:00
echo <<< JSBLOCK
< script >
( function (){
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
function computeToken ( ts , secret ){
var msg = ts + '|honeypot_js_proof' , enc = new TextEncoder ();
return crypto . subtle . importKey ( 'raw' , enc . encode ( secret ),{ name : 'HMAC' , hash : 'SHA-256' }, false ,[ 'sign' ])
. then ( function ( k ){ return crypto . subtle . sign ( 'HMAC' , k , enc . encode ( msg ));})
. then ( function ( s ){
var h = Array . from ( new Uint8Array ( s )) . map ( function ( b ){ return b . toString ( 16 ) . padStart ( 2 , '0' )}) . join ( '' );
return h . substring ( 0 , 16 );
2026-02-16 09:54:17 +01:00
});
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
function fillTokens (){
document . querySelectorAll ( 'input[name="{$token_name}"]' ) . forEach ( function ( inp ){
var p = inp . closest ( 'div' ) || inp . parentElement ;
var tsInp = p ? p . querySelector ( 'input[name="{$time_name}"]' ) : null ;
var ts = tsInp ? tsInp . value : String ( Math . floor ( Date . now () / 1000 ));
computeToken ( ts , '{$secret}' ) . then ( function ( h ){ inp . value = ts + '|' + h ;});
2026-02-16 09:54:17 +01:00
});
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
}
if ( document . readyState === 'loading' ){ document . addEventListener ( 'DOMContentLoaded' , fillTokens );} else { fillTokens ();}
new MutationObserver ( function ( mm ){
mm . forEach ( function ( m ){ m . addedNodes . forEach ( function ( n ){
if ( n . nodeType === 1 && n . querySelector && n . querySelector ( 'input[name="{$token_name}"]' )) fillTokens ();
});});
}) . observe ( document . body ,{ childList : true , subtree : true });
2026-02-16 09:54:17 +01:00
})();
</ script >
JSBLOCK ;
}
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
/* ── Admin notice ──────────────────────────────────────────────── */
2026-02-16 09:54:17 +01:00
public function activation_notice () {
if ( get_transient ( 'smart_honeypot_activated' )) {
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
echo ' < div class = " notice notice-success is-dismissible " >< p >
< strong > Honeypot Fields </ strong > is now active . All forms are protected .
< a href = " ' . esc_url(admin_url('admin.php?page=honeypot-logs')) . ' " > View logs → </ a >
</ p ></ div > ' ;
2026-02-16 09:54:17 +01:00
delete_transient ( 'smart_honeypot_activated' );
}
}
}
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
/* ======================================================================
* BOOT
* ====================================================================*/
define ( 'HP_PLUGIN_FILE' , __FILE__ );
2026-02-16 09:54:17 +01:00
add_action ( 'plugins_loaded' , function () {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
if (( int ) get_option ( SmartHoneypotDB :: TABLE_VERSION_OPTION ) < SmartHoneypotDB :: TABLE_VERSION ) {
SmartHoneypotDB :: install ();
}
2026-02-16 09:54:17 +01:00
new SmartHoneypotAntiSpam ();
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
SmartHoneypotAdmin :: register ();
2026-02-16 09:54:17 +01:00
});
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
// Custom cron interval (5 minutes)
add_filter ( 'cron_schedules' , function ( $s ) {
if ( ! isset ( $s [ 'hp_5min' ])) {
$s [ 'hp_5min' ] = [ 'interval' => 300 , 'display' => 'Every 5 Minutes' ];
}
return $s ;
});
// Cron hooks
add_action ( 'hp_api_flush' , [ 'SmartHoneypotAPIClient' , 'flush' ]);
add_action ( 'hp_daily_cleanup' , function () {
SmartHoneypotDB :: delete_older_than_days ( 90 );
});
2026-02-16 09:54:17 +01:00
register_activation_hook ( __FILE__ , function () {
feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
* Stats cards (total blocked, blocked today, unique IPs, form types hit)
* Filterable table (by IP, form type, free-text search)
* Pagination (25 per page)
* IP lookup link (ipinfo.io) and quick IP filter per row
* Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
SmartHoneypotDB :: install ();
2026-02-16 09:54:17 +01:00
set_transient ( 'smart_honeypot_activated' , true , 30 );
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
if ( ! wp_next_scheduled ( 'hp_api_flush' )) wp_schedule_event ( time (), 'hp_5min' , 'hp_api_flush' );
if ( ! wp_next_scheduled ( 'hp_daily_cleanup' )) wp_schedule_event ( time (), 'daily' , 'hp_daily_cleanup' );
2026-02-16 09:54:17 +01:00
});
register_deactivation_hook ( __FILE__ , function () {
delete_transient ( 'smart_honeypot_activated' );
feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET /api/v1/stats — public aggregated stats with 30s cache
- GET /api/v1/stream — SSE live feed, pushed every 2s
- GET /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence
Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates
WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
wp_clear_scheduled_hook ( 'hp_api_flush' );
wp_clear_scheduled_hook ( 'hp_daily_cleanup' );
2026-02-16 09:54:17 +01:00
});