Журнал изменений
Harden authentication, SQL queries, and input handling across admin and modules; migrate Bootstrap 5 and HTMX to plugins/ with proper structure.
Core changes:
- Authentication fixes (core/security.php, core/system.php, admin/index.php):
- isAdmin(): remove substr() truncation on bcrypt hash (was 72 chars, now full)
- is_user(): replace loose == with hash_equals() for timing-safe comparison
- check_admin(), add_admin(): header('Location:') replaced with setRedirect()
- logout(): raw SQL concatenation replaced with prepared statement + setRedirect()
- changeeditor(): raw SQL replaced with prepared statement; $_POST → getVar()
- login(): raw $_POST['aname'], $_POST['aemail'] → getVar()
- SQL hardening — LIKE prepared statements (8 modules):
- modules/news, media, files, links, faq, pages, shop: $let interpolation replaced with :let placeholder + ['let' => $let.'%'] params
- modules/help: $let and $uid both replaced with named placeholders
- news: removed redundant addslashes() on $let
- Security headers (core/system.php):
- Added X-Content-Type-Options: nosniff
- Added X-Frame-Options: SAMEORIGIN
- Added Referrer-Policy: strict-origin-when-cross-origin
- Frontend plugin structure (plugins/, config/global.php):
- Bootstrap 5 (CSS + JS bundle + Icons) moved to plugins/bootstrap/
- HTMX moved from templates/admin/js/ to plugins/htmx/
- bootstrap-icons.css, fonts/ removed from templates/admin/
- script_f and css_f updated to reflect new paths
- Scheduler module (admin/modules/scheduler.php, config/scheduler.php):
- Full scheduler module implementation with cron-based job execution
- Newsletter module (admin/modules/newsletter.php, config/newsletter.php):
- Newsletter configuration and admin module updates
Benefits:
- Timing-safe password comparison prevents brute-force timing attacks
- Prepared statements on LIKE queries eliminate SQL injection vectors
- Security headers protect against MIME sniffing, clickjacking, referrer leakage
- Centralised plugin paths simplify future library updates
Technical notes:
- bcrypt hashes are 60 chars; old 40-char substr caused login failure after migration
- setRedirect() calls exit internally; explicit exit after header() no longer needed
- params array passed as 10th arg to setArticleNumbers() — already supported
Small maintenance changes to newsletter module and sitemap configuration to align with scheduler-based job dispatch and updated admin panel.
Core changes:
- Newsletter (admin/modules/newsletter.php, admin/info/newsletter/*.html):
- Minor adjustments following scheduler integration refactor
- Sitemap (config/sitemap.php, modules/sitemap/admin/index.php, sitemap.xml):
- Sitemap config and admin panel aligned with current module structure
- sitemap.xml regenerated
Benefits:
- Consistent state after scheduler refactor
- Info pages reflect current system behavior
Expands the security statistics panel to cover all files in storage/logs/, replacing the .log-only filter with a label-based allowlist approach. Removes hardcoded .log extension throughout; .json files (dump_map, monitor) are now handled via an $ext exception map.
Core changes:
- Security module (admin/modules/security.php):
- $labels array extended: database, dump, dump_log, dump_map, error_file, error_php, error_site, error_sql, hack, log, log_admin, log_user, monitor, warn
- $ext map: ['dump_map' => 'json', 'monitor' => 'json']
- security(): replaced preg_match('.log') with skip-list + isset($labels)
- fileview(), down(), del(): use $ext[$file] ?? 'log' for path and filename
- confsave(): persists sess_d, sess_b, log_b, log_d; dump_skip field added
- Info pages (admin/info/security/*.html — all 6):
- Reference to hardcoded interval setting replaced with Scheduler module link
- Config (config/security.php):
- dump_skip default removed (now managed via Scheduler/confsave)
- log_d default adjusted
Benefits:
- .json log files (dump_map, monitor) now visible and downloadable in UI
- No unknown files shown: only keys present in $labels are rendered
- .htaccess and index.html automatically skipped
Technical notes:
- filterVar strips dots, so file extensions cannot be passed via URL
- Extension is derived server-side from $ext map with 'log' fallback
Introduces a configurable task scheduler with cron-format schedules, per-job state tracking, lock/timeout protection, and a HTMX-powered live status panel. Replaces hardcoded filereport/backup/sitemap/newsletter triggers in index.php with a unified scheduler dispatch.
Core changes:
- Scheduler module (admin/modules/scheduler.php):
- Live status table with HTMX auto-refresh per job
- Add/edit/delete custom jobs, unlock stuck jobs, manual run trigger
- Cron-format schedule field with format hint
- Scheduler engine (core/system.php):
- getSchedulerConfig(), getSchedulerDir(), getSchedulerFile()
- addSchedulerRun(): dispatches filereport, backup, sitemap, newsletter
- checkSchedulerAccess(): validates cron/manual token access
- dump.json renamed to dump_map.json to avoid key conflict with dump.log
- Dispatcher (index.php):
- New case 'scheduler' in go==3 branch: validates access, runs job, returns JSON
- Config (config/scheduler.php, config/modules.php):
- Default scheduler config with system jobs (filescan, backup, sitemap, newsletter)
- scheduler module entry added to modules.php
- Lang (admin/lang/*.php — all 6 languages):
- SCHEDULER* constants: status, last_run, last_ok, next_run, trigger, duration, fails, schedule, handler, priority, lock, unlock, run, jobkey, url, saved, deleted, unlocked, running, idle, addjob, editjob, url_info, system_info, saveerr, manual, batch, schedule_info
- _SEC_STAT_DB, _SEC_STAT_DMAP, _SEC_STAT_MON: security log labels for database.log, dump_map.json, monitor.json
Benefits:
- Decoupled scheduling from HTTP request cycle
- Per-job state files with lock/timeout prevent concurrent execution
- Extensible: custom jobs configurable without code changes
Technical notes:
- Job state stored in storage/logs/scheduler/<job>.json
- Cron schedule validated server-side; manual runs bypass schedule check
- dump_map.json replaces dump.json (breaking: rename existing file)
Integrate the preserved local work back into master after fast-forwarding the branch to the latest origin/master state. This keeps the remote updates and the local language, configuration, setup, and test changes together without any history rewrite.
Core changes:
- Remote synchronization (master):
- Fast-forward local master to origin/master
- Keep upstream changes from the latest GitHub state
- Local work integration (config, language, setup, tests):
- Merge the backup branch with the preserved local changes
- Resolve the config/global.php conflict in favor of the saved local sitekey
Benefits:
- Leaves master up to date with GitHub and your local work intact
- Provides a recoverable backup branch and commit history
- Avoids destructive Git operations and force-based workflows
Technical notes:
- Merge commit created after fast-forward sync
- No rebase and no history rewrite
- Working tree should be clean after commit
Preserve the current in-progress local work on language files, configuration, and setup flow before updating master from origin/master. This creates a safe restore point for merge-based synchronization without rewriting history.
Core changes:
- Language and config updates (admin/lang/.php, lang/.php, config/*.php):
- Save current local edits across translations and configuration files
- Preserve in-progress constant and module/security adjustments
- Setup and test updates (setup/index.php, tests/LanguageConstantsUsageTest.php):
- Save local setup workflow changes
- Preserve related test adjustments for later integration
Benefits:
- Provides a recoverable checkpoint before remote synchronization
- Reduces risk of losing uncommitted work during merge operations
- Keeps the update flow aligned with repository safety rules
Technical notes:
- No history rewrite
- Local backup commit only
- Backward compatibility to be validated after merge
- database: simplify navi() signature, remove unused $opt and $legacy params
- database: align op/case/handler to project standard (del/del/del())
- database: replace filter_input() with getVar() for consistency
- database: fix $conf['db']['name'] → $dbname for safe query building
- database: translate German comments to English, fix parse-branch indent
- database: use LOGS_DIR constant in addDblog()
- monitor: rename monitor_metrics.json → monitor.json
Three bug fixes identified via error log analysis (2517 entries, period 2026-03-13 to 2026-03-15). Closes the dominant error (2504 occurrences) and hardens input validation against encoded path traversal probes.
Core changes:
- Search module (modules/search/index.php):
- Guard $conf['search'] with is_array() before accessing ['mods']
- $conf['search'] is a string when config is scalar, causing TypeError
- Affected every bot crawling ?name=search (Bing, Google, Baidu, etc.)
- Monitor (admin/modules/monitor.php):
- Check open_basedir before calling is_dir() on extension_dir
- Used array_reduce over PATH_SEPARATOR-split paths
- Avoids E_WARNING when ext dir is outside allowed open_basedir paths
- Security (core/security.php):
- Extend $quote pattern in checkGet: '../' → '..[/%]'
- Now catches ../ (direct), ..\ (Windows), ..% (URL-encoded: ..%2F etc.)
- Blocks double-encoded path traversal (e.g. %252F) after PHP auto-decode
Benefits:
- Eliminates 2504 TypeError entries from error_php.log
- Removes 9 recurring open_basedir warnings in monitor
- Path traversal attempts now logged to hack.log via addHackReport()
Technical notes:
- No config or schema changes
- Backward compatible
Extended monitor.php with exec() fallbacks for /proc/meminfo, /proc/cpuinfo, /proc/net/dev when open_basedir blocks direct file reads; lscpu/nproc/free used as secondary sources. Improved getMetricStorePath() to resolve writable directory dynamically. Added unloaded PHP extensions detection.
Core changes:
- monitor.php: exec-fallbacks for Linux /proc reads, dynamic metrics path, lscpu/nproc support, unloaded extensions list
- core/system.php: no-image.png fallback for missing upload files; onerror handler on BB/Markdown img tags; better alt text from filename
- security.php + config/security.php: new dump_skip config field with textarea UI and sanitized save logic
- modules/forum/index.php: rename $massiv→$rows, $params→$pars; cleaner named placeholders
- modules/account/admin/index.php: fix SQL WHERE clauses with table alias u.
- admin/info/admins/ru.html → ru.md migration; add admin/info/monitor/ help pages
- templates: add no-image.png to all three themes; add find/view admin icons
Benefits:
- Monitor works on hosts with restricted open_basedir
- Broken images show placeholder instead of broken icon
- dump_skip allows excluding paths from file change scanner
- Forum and account SQL queries more robust against ambiguous column names