Add early rejection of index.php/... style URL requests that could bypass CMS routing and expose internal query parameters.
Core changes:
- Request validation (security.php):
Detect PATH_INFO tricks via $_SERVER['PATH_INFO'] and URL pattern
- Returns 404 for /index.php/name=files&op=view style requests
- Prevents URL-based parameter injection bypass
Benefits:
- Blocks a class of URL manipulation attacks
- No impact on normal CMS operation
Technical notes:
- Runs before any routing or module loading
- Sets $_GET['error'] = 404 for CMS error page handling
- Compatible with all PHP versions >= 8.1
Admin editor flag $admin[3] was accessed without null check in admin.php and had inconsistent default value (1) in system.php textarea functions.
Core changes:
- Admin editor flag guard (core/admin.php):
Add isset($admin[3]) check with default 0
- Prevents potential warning if admin session data is incomplete
- Normalize editor defaults (core/system.php):
Change default from 1 to 0 in textarea() and textareae()
- Aligns with security.php pattern: ($admin[3] ?? '') -> (int)'' = 0
- Default 0 = no visual editor when flag unavailable
Benefits:
- Consistent default behavior across all $admin[3] access points
- Defensive coding against incomplete session data
Technical notes:
- $admin[3] stores editor flags, first char = visual editor toggle
No runtime errors observed yet (admin always authenticated), but guards added for robustness and PHP 8.1+ strict compliance
Guest/bot visitors triggered 4300+ "Undefined array key 3" warnings daily because $user is an empty array for non-authenticated visitors, but $user[3] (story number preference) was accessed without null check.
Core changes:
- Module pagination calls (11 modules):
Add null coalescing default: $user[3] ?? 0
- forum, files, links, pages, faq, shop, media, jokes, help,
auto_links, account
- Consistent numeric default 0 for user_news() parameter
- getUserNews function (core/system.php):
Extract $user[3] ?? 0 into local variable $unum
- Prevents potential warning in direct array access
- Maintains existing !empty() fallback logic
Benefits:
- Eliminates most frequent error in production logs (4321 occurrences)
- Clean PHP 8.1+ compatibility for guest/bot traffic
- No behavioral change for authenticated users
Technical notes:
$user array is [] for guests (security.php:71), cannot be padded with defaults because if ($user) login checks rely on empty array
- user_news() already handles empty $unum via !empty() check
RSS feeds returned SQL syntax errors for all module types (news, files, pages, shop, faq) due to missing $confrs variable in function scope, causing truncated LIMIT clause. SQL error logging was also corrupted by text_filter() stripping <= operators from logged queries.
Core changes:
- RSS feed SQL fix (core/user.php):
Add $confrs to global declaration in rss_channel()
- require_once was skipped because rss.php already loaded in system.php
- $confrs undefined caused $num=null, producing "LIMIT " without value
Replace deprecated $_GET access with null coalescing operator
- $_GET['name'], $_GET['cat'], $_GET['num'], $_GET['id']
- SQL error logging fix (core/security.php):
Replace text_filter() with htmlspecialchars() in error_sql_log()
- text_filter() used strip_tags() which treated <= as HTML tag
- All SQL after <= NOW() was silently stripped from error logs
Benefits:
- RSS feeds now work correctly for all module types
- SQL error logs show complete, untruncated queries
- Eliminates PHP 8.1+ undefined array key warnings in RSS
Technical notes:
Root cause: system.php:35 loads rss.php globally, require_once in rss_channel() was a no-op, $confrs stayed undefined in function scope
- Affected ~30+ SQL errors per day from bot/crawler RSS requests
Exclude Composer binary from version control as it should be installed separately on each machine, not shipped with the project.
Restore the SEO configuration file that was previously merged into core/system.php, keeping config separate from core logic.
Core changes:
- SEO configuration (config/config_seo.php):
Restore $confse array with all SEO settings
- URL rewrite toggle and separators
- Keyword generation settings (count, length, shuffle)
- Auto-description and long title options
- Open Graph meta tags template
- Schema.org structured data template
Benefits:
- Keeps configuration separate from core system code
- Easier to edit SEO settings without touching system.php
- Consistent with other config files (modules, comments, etc.)
Add PHPUnit test to prevent require/include statements from being placed inside functions, which causes silent failures with require_once.
Core changes:
- testNoIncludesInsideFunctions (SecurityValidationTest.php):
Uses PHP tokenizer (token_get_all) for accurate detection
- Tracks brace depth to determine function scope
- Detects T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE
- Reports file path, line number, and function name on failure
- Scans all project PHP files (excludes vendor, tests, setup)
Benefits:
- Prevents recurring require_once-inside-function bugs
- Catches issues at test time before they reach production
- Accurate scope detection via PHP tokenizer vs regex
Technical notes:
- Tokenizer approach handles edge cases (comments, strings)
- Test integrates with existing SecurityValidationTest file scanner
- No false positives for top-level includes or class method bodies
Fix undefined array key warning when search results don't fill the last page, and improve search word input handling.
Core changes:
- Pagination bounds check (index.php:232):
Add isset($conts[$i]) before accessing array element
- Prevents "Undefined array key" when results < page size
- Loop calculates range from $conf['snum'] but array may be shorter
- Search input handling (index.php):
Replace direct $_POST/$_GET access with getVar('req', 'word', 'word')
- Consistent with project input handling conventions
- Proper URL decoding and filtering via var_filter()
Initialize $conts = [] before population loop
- Prevents potential undefined variable warning
Benefits:
- Eliminates warnings on search queries with partial result pages
- Safer input handling through centralized getVar() function
- Clean array initialization prevents edge-case errors
Fix multiple deprecated/warning errors caused by passing null values to string functions when users are not authenticated (bots, guests).
Core changes:
- Null-safe $admin[3] access (security.php, system.php):
Fix checkPost() substr() null deprecation
- Add is_array() check with null coalescing for $admin[3]
Fix save_text() substr() null deprecation
- Same pattern applied consistently
Fix replace_break() substr() null deprecation
- Prevent crash when $admin is not initialized
- Config includes refactoring (system.php):
Move fields.php, statistic.php, rss.php to global scope
- Prevents require_once failure on repeated function calls
Fix fields_out() to use global $conffi instead of require
- require_once inside function only loads file on first call
- Update head() global declarations for $confrs, $confst
- Restore config_seo.php external config file
- Null-safe $user[3] access (account/index.php):
Fix last() function undefined array key warning
- Add null coalescing for $user[3] in user_news() call
Benefits:
- Eliminates PHP 8.1+ deprecation warnings for guest/bot visitors
- Prevents silent failures from require_once inside functions
- Consistent null-safety pattern across all $admin[3] usages
Technical notes:
- Pattern used: $flag = is_array($x) ? ($x[n] ?? '') : ''
- No behavioral changes for authenticated users
- Backward compatible with PHP 7.4+
Added Bootstrap Icons library to provide scalable vector icons for the admin panel interface elements.
Core changes:
- Icon stylesheet (templates/admin/bootstrap-icons.css):
- Bootstrap Icons CSS with font-face declarations
- Icon class definitions for all available Bootstrap Icons
- Font files (templates/admin/fonts/):
- bootstrap-icons.woff and bootstrap-icons.woff2 font files
- index.html placeholder for directory listing protection
Benefits:
- Scalable vector icons for admin interface elements
- Consistent icon styling across the admin panel
- Lightweight WOFF2 format for optimal loading performance
Technical notes:
- Font files referenced via relative path from CSS
- Used by modules admin for type and database status indicators