fix: deploy src/ before phpMan.php to avoid transient 500 errors On 2026-07-13, deploying v4.9.26 to production caused 2 transient HTTP 500 errors (Applebot requests at 20:19:46 and 20:19:48 PDT): PHP Fatal error: Uncaught Error: Call to undefined function validatePathInfo() in /home/chedong/chedong.com/phpMan.php:106 Root cause: the Makefile deploy order uploaded phpMan.php (which calls validatePathInfo) BEFORE src/util.php (which defines it). During the ~30 second window between the two rsync/scp operations, any request to a Perl module URL hit the new phpMan.php with the old src/, returning 500 instead of 200/403. Fix: swap the order in both _deploy-code (staging) and _release-code (production) so src/ is uploaded first, then phpMan.php. Same rsync/scp commands, just reordered. The first v4.9.x release with a src/ function addition since the multi-file split revealed this latent ordering bug. Before this, src/ files were unchanged on most deploys so the window never had a mismatched function definition. After fix: post-deploy window 7-13 20:19-20:42 (25 min) shows - 676 successful phpMan.php responses (200/301/302) - 2 expected 403s (sftp://, sftp:onedrive:gdocs: — correctly rejected) - 0 new 500s after 20:19:50 Co-Authored-By: AtomCode (minimax-m3) <noreply@atomgit.com>
Merge SourceForge upstream (AdSense) + Perl module fix
fix: prevent PHP default_socket_timeout from preempting CURLOPT_TIMEOUT
Add ini_set('default_socket_timeout', max(timeout+30, 900)) before
each LLM API call so the 600s primary / 300s fallback cURL timeouts
actually take effect. Previously default_socket_timeout=60s was
silently cutting off long-running requests.
Co-Authored-By: Claude <noreply@taotoken.net>
fix: allow valid Perl modules with multiple :: in 403 guard The PATH_INFO 403 guard was rejecting any path segment with > 2 colons, which wrongly blocked valid Perl module URLs like /man/Dpkg::Control::HashCore (4 colons, two :: pairs) and /perldoc/A::B::C::D::E (8 colons). Replace the count-based check with a single-colon detector: only colons that are NOT part of a '::' pair are treated as URI-scheme indicators. This preserves the original protection against scanner probes (sftp:onedrive:gdocs:) while allowing any depth of Perl package name. - Extract the guard into testable validatePathInfo() in src/util.php - Returns the failing condition name (tooLong/tooDeep/hasProto/ hasProtocolColon) instead of just true/false - Add test/unit/test_path_guard.php with 26 assertions covering: - Valid Perl modules at 1/2/3/4/5 :: pairs - C++ namespaces (std::string) - Rejection of sftp://, http://, sftp:onedrive:, Foo::Bar:Baz - Boundary cases for tooLong (100 chars) and tooDeep (5/6 segments) - All 349 unit+integration tests pass
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>
Increase LLM timeout: primary 120→600s, fallback default 60→300s
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>
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 LLM gateway failure analysis report - Timeout distribution: Jul 8 worst (2,448 errors), Jul 7 (745), Jul 1 (458) - Error type breakdown: 68.5% HTTP 0, 21.2% 403 (fallback-2), 4.4% 400 (fallback-3) - Root cause: primary 120s timeout + fallback-1 60s timeout + fallback-2/3 broken - Recommendations: fix fallback-2 allowlist, fix fallback-3 model name, reduce LLM_MAX_TOKENS Co-Authored-By: Claude <noreply@taotoken.net>