Журнал изменений
Resolves PHP warnings caused by uninitialized variables and unsafe array access across core attachment handler, forum, account, and template modules.
Core changes:
- Attachment encoder (core/system.php):
- Initialize $timg, $width, $height before conditional branches
- Prevents "undefined variable" notices when attachment is not an image
- Add isset() guards for $date[4][$i] and $date[5][$i]
- Avoids "undefined index" when optional dimensions are missing
- Cast $timg to (string) for str_replace() safety
- Account profile view (modules/account/index.php):
- Initialize $rgroup as empty array and $uranks as empty string
- Prevents notices when user has no rank groups or point system is off
- Forum module (modules/forum/index.php):
- Initialize $massiv, $cmassiv, $where, $umassiv as empty arrays
- Prevents "undefined variable" if early return paths are taken
- Add is_array() + !empty() guard for $userinfo before accessing keys
- Handles guest/anonymous users who return non-array from getusrinfo()
- Add is_array() + !empty() guard for $umassiv before foreach loop
- Fix missing newline at end of file
- Template avatar display (templates/lite/index.php):
- Add is_array() + !empty() guard on $userinfo before avatar access
- Prevents file_exists() warning when getusrinfo() returns non-array
- Extract avatar value into $uavatar with safe fallback
Benefits:
- Eliminates PHP notice/warning log noise in production
- Prevents potential errors for guest or edge-case user states
- Consistent defensive initialization pattern across modules
Technical notes:
- No behavioral changes for normal authenticated users
- All fallback values match existing implicit PHP defaults
- Backward compatible with current template and module contracts
SEO-related settings (rewrite, sep, tsep, title, ctitle, ltitle, keys, akeys, dkeys, etc.) are migrated from config_seo.php into the global $conf array, making them editable via the admin panel.
Core changes:
- Admin config UI (admin/modules/config.php):
- Add input fields for title separator (tsep) and SEO title toggles
- Change default URL separator from '|' to '-'
- Save new fields (tsep, title, ctitle) to database
- SEO config cleanup (config/config_seo.php):
- Comment out all settings now managed via $conf
- Retain file structure for reference
- Global config (config/global.php):
- Add 'title' and 'ctitle' keys to $conf array
- URL generation (core/system.php):
- getSeoUrl() reads from $conf instead of $confse
- Language file (admin/language/ru.php):
- Add translations for _TSEP, _SEOTITLE, _SEOCTITLE
Benefits:
- SEO settings are now configurable through the admin interface
- No more manual file editing required for SEO configuration
- Consistent with existing admin-managed configuration pattern
Technical notes:
- config_seo.php entries commented out, not deleted, for reference
- Backward compatible via ?? default operators in getSeoUrl()
Condense the inline comment for the PATH_INFO rejection block to a concise single-line description.
Core changes:
- Comment update (security.php):
- Replace verbose multi-clause comment with shorter form
- Keeps same technical meaning in fewer words
Add detailed test suite descriptions covering all Unit and Validation tests, including the new safety net tests for Phase 1 refactoring.
Core changes:
- Test documentation (docs/TESTS.md):
- Add Test Suites section with two subsections: Unit and Validation
- List every test file with test count and purpose
- Include PasswordHashTest, InputFilterTest, TemplateIfTest
- Add commands for running individual suites and files
Benefits:
- New contributors can quickly understand test coverage
- Clear mapping between test files and CMS components
Add 41 new unit tests covering password hashing, input filtering, and template conditionals to establish a regression baseline before the upcoming security hardening changes.
Core changes:
- Password hash tests (PasswordHashTest.php):
- Verify md5_salt() algorithm: md5(md5(salt) . md5(pass))
- Consistency, hex format, salt dependency, known values
- Unicode and special character handling
- Validate future bcrypt format for migration readiness
- Input filter tests (InputFilterTest.php):
- num_filter: digit extraction, non-numeric handling, edge cases
- var_filter: allowed chars, Unicode support, XSS prevention
- isVar: alphanumeric validation, array handling
- text_filter: HTML escaping, BBCode stripping, type modes
- url_filter: protocol prefixing, empty handling
- save_text: quote/dollar/backslash escaping
- Template conditional tests (TemplateIfTest.php):
- setTemplateIf: true/false branches, else blocks
- Nested conditions, string true/false coercion
- Undefined flags, multiple independent ifs
- Whitespace tolerance in tags
Benefits:
- Regression safety net before password_hash migration
- Baseline for eval() removal in template system
- Validates filter behavior before SQL parameterization
Technical notes:
- Uses algorithm replicas to avoid system.php dependency chain
- All 113 project tests pass (54 new + 59 existing)
- No changes to production code
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.