Add runtime process status to --status output Per-mode table shows: - Running/stopped status with uptime (✅ ⚠️ ⏸️) - PID and process age - Error count since process start - Last enhanced timestamp + stall detection (>5min idle = ⚠️) Reads PID files at known locations per mode, checks posix_kill for liveness, queries error log for per-mode error counts. Co-Authored-By: Claude <noreply@taotoken.net>
Restore PATH_INFO guard (ec489ee, lost in code split) + colons enhancement Original guard (2024-06-24) rejected >100 chars, >5 segments, :/ pattern. Lost during 4,500→753 line src/ split. Restored with 403 Forbidden. Added: segment with >2 colons check. Verified: 7/5 log had 1,148 protocol-prefix requests, 52 returned 200. Co-Authored-By: Claude <noreply@taotoken.net>
Add log-analyze.sh — web access log analysis tool Supports date range, spider breakdown, page type stats, status codes, hourly distribution. Auto-discovers rotated logs by date. Usage: bash cli/log-analyze.sh [YYYY-MM-DD] [YYYY-MM-DD] Co-Authored-By: Claude <noreply@taotoken.net>
Add URL attack guard: reject malformed paths with protocol-prefix traps Blocks requests like /man/DUPLICITY/sftp:/onedrive:/gdocs:/scp:/... that generate infinite crawl variants. Two checks at PATH_INFO entry: 1. Path length > 300 chars → 400 (no valid phpMan URL exceeds this) 2. Segment with > 2 colons → 400 (Perl modules use ::, attack paths use sftp:, gdocs:, onedrive:, etc. — protocol prefixes) Prevents 20K+ wasted ClaudeBot requests hitting man command execution. Co-Authored-By: Claude <noreply@taotoken.net>
Add --restart option to batch-enhance.php --restart stops any existing batch for the given --mode, cleans the PID file, then starts a new process. Works per-mode via --mode + --pid-file. Usage: php cli/batch-enhance.php --mode=man --restart --rate-limit=30 php cli/batch-enhance.php --mode=man --restart --resume-from=735 php cli/batch-enhance.php --mode=perldoc --restart --pid-file=/tmp/bp.pid Co-Authored-By: Claude <noreply@taotoken.net>
v4.9.26: fix GIT_DESCRIBE guard in showFooter + add AdSense support - Fix bare GIT_DESCRIBE in showFooter (last unguarded reference in codebase) → triple-fallback: GIT_DESCRIBE → PHPMAN_VERSION → 'unknown' → matches tldr.php:85 pattern - Add PHPMAN_ADSENSE_ID config constant (default '' = disabled) - CSP: extend script-src/connect-src for AdSense domains → pagead2.googlesyndication.com (script-src) → *.adtrafficquality.google, pagead2.googlesyndication.com (connect-src) → frame-src 'self' *.googlesyndication.com (ad iframes) - CSP restructured: connect-src built from aggregate $connectSrc → supports GA-only, AdSense-only, both, or neither - showFooter: inject adsbygoogle.js when PHPMAN_ADSENSE_ID is set Co-Authored-By: Claude code 2.1.193 with deepseek-v4-pro <noreply@taotoken.net>
Raise maxConsecutiveFailures 3→10 to reduce man batch abort rate Man pages (20-120KB HTML input) frequently hit 3 consecutive LLM failures from primary timeouts + fallback-2 token limits. Raising to 10 allows the batch to skip past problematic entries and keep running, rather than aborting every 10-40 entries. Fallback-2 changed to longCat-flash-chat on server side. Co-Authored-By: Claude <noreply@taotoken.net>
Add unit tests: callLLM/callLLMEndpoint semantics + cleanEmojiHtml XSS + tldr guard test_enhance.php (23 tests): - callLLM() empty config guard, callLLMEndpoint signature validation - cleanEmojiHtml(): XSS defense (script/style/meta/title stripping, event handler removal, javascript:/data: URI neutralization, DOCTYPE/html/head/body wrapper stripping, <h1>→<h2> downgrade) test_tldr_guard.php (4 tests): - GIT_DESCRIBE defined() guard fallback chain - Triple-fallback to 'unknown' pattern from tldr.php:109 Fix stale comment in format_html.php:71 (<span class="u"> → <u>) Co-Authored-By: Claude <noreply@taotoken.net>
v4.9.25: fix FTS5 duplicate entries — DELETE FROM search_fts instead of DROP+CREATE/RENAME FTS5 shadow tables survive DROP TABLE on this SQLite version, causing every index rebuild to append another full copy of all entries. Total row count grew from 13,851 to 83,006 over 6 rebuilds. DELETE FROM search_fts properly clears all content while keeping the virtual table structure intact. Also: rebuildSearchIndex() now only deletes mode='search' cache entries, preserving all page HTML caches. Co-Authored-By: AtomCode (deepseek-v4-flash) <noreply@atomgit.com>
v4.9.24: fix rebuildSearchIndex cache cleanup — DELETE WHERE mode='search', not format='search'
Search results are stored with mode='search' (format='html'), not
format='search'. The v4.9.23 fix targeted format IN ('search','json')
which never matched any rows, leaving stale search caches intact.
Co-Authored-By: AtomCode (deepseek-v4-flash) <noreply@atomgit.com>