Four admin modules used is_admin_god() as their access guard, allowing only super-admins in. Replaced with is_admin_modul() so module access can be delegated to non-god administrators via the modules config.
Core changes:
- Access guard replacement (four files):
- modules/account/admin/index.php: is_admin_god() -> is_admin_modul('account')
- modules/changelog/admin/index.php: is_admin_god() -> is_admin_modul('changelog')
- modules/rss/admin/index.php: is_admin_god() -> is_admin_modul('rss')
- modules/sitemap/admin/index.php: is_admin_god() -> is_admin_modul('sitemap')
- Additional fixes in the same files:
- account: rename users() to account() to match op dispatch convention
- changelog: remove @ suppressor from file_get_contents()
- sitemap: remove @ suppressor from fopen(); remove BOM from file header
Benefits:
- Delegated admin access works correctly for these modules
- Error suppression removed; failures are now visible in error logs
Technical notes:
- is_admin_modul() reads from $conf['modules'] so no DB query needed
- Behavior for god-level admins is unchanged (they pass all module checks)
Renames internal helpers to camelCase, extracts platform detection, and renames template placeholders to snake_case for consistency.
Core changes:
- Monitor module (admin/modules/monitor.php):
- Rename navi() to getMonitorTabs() to avoid collision with module navs
- Extract isWindows() and getServerSoftware() helpers
- Rename get_server_load_data() to getServerLoadData()
Rename template placeholders: ramP/offR/dashD/offD/diskP/pathUp/pathDown to ram_p/off_r/dash_d/off_d/disk_p/path_up/path_down
- Monitor template (templates/admin/basic-monitor.html):
- Update all SVG and chart placeholder tokens to match new snake_case names
Benefits:
- Consistent naming convention across admin module helpers
- Snake_case template tokens match the broader SLAED template convention
Technical notes:
- Placeholder rename is a coordinated change across PHP and HTML
- No logic changes; all monitoring metrics and rendering preserved
Rewrites whois admin module to match current SLAED coding standards: typed functions, single-quoted strings, and modern navigation API.
Core changes:
- Navigation (modules/whois/admin/index.php):
- Replace whois_navi() / func_get_args() with typed navi()
- Switch to getAdminTabs() and name=whois&op= URL scheme
- All handler functions:
- Add void return type declarations
- Replace double-quoted strings with single-quoted throughout
- Replace list() with [] destructuring in fetchrow loops
- Replace $admin_file with $afile
Benefits:
- Consistent style with other modernized admin modules
- Cleaner navigation registration via getAdminTabs()
Technical notes:
- Copyright year updated to 2026
- No functional logic changes; all CRUD operations preserved
Rewrites voting admin module to align with the current SLAED admin architecture: typed functions, modern API calls, and clean URL routing.
Core changes:
- Navigation (modules/voting/admin/index.php):
- Replace voting_navi() / func_get_args() pattern with typed navi()
- Use getAdminTabs() and name=voting&op= URL scheme
- All handler functions:
- Add void return type declarations
- Replace $admin_file with $afile, tpl_eval() with setTemplateBasic()
- Replace double-quoted heredoc style with single-quoted strings
- Replace list() with [] destructuring in fetchrow loops
- Admin links:
- Update op=voting_add/delete to name=voting&op=add/delete throughout
Benefits:
- Consistent with other modernized admin modules
- Typed API reduces silent failures from wrong argument types
- URL routing aligned with new op-based dispatch scheme
Technical notes:
- Copyright year updated to 2026
- No functional logic changes; all CRUD operations preserved
UNIQUE KEY mid_modul_uid (mid, modul, uid) blocked all guest votes after the first one, because all guests share uid=0. The application already enforces one-vote-per-IP in PHP; the DB key now mirrors that.
Core changes:
- Schema for fresh installs (setup/sql/table.sql):
- Drop UNIQUE KEY mid_modul_uid (mid, modul, uid)
- Add UNIQUE KEY mid_modul_host (mid, modul, host)
- Migration for 6.2 > 6.3 upgrade (setup/sql/table_update6_3.sql):
- Same key replacement applied to the ALTER TABLE block
- Setup wizard (setup/index.php):
- Append deduplication DELETE and key migration queries to update6_3 branch
- DELETE removes duplicate (mid, modul, host) rows keeping earliest id
- ALTER TABLE DROP INDEX IF EXISTS mid_modul_uid (safe if already absent)
- ALTER TABLE ADD UNIQUE KEY mid_modul_host
- Fix unused $key => $val in language() foreach loop
- getInfo() output added to report migration result in the UI
Benefits:
- Multiple guests from different IPs can now vote in the same poll
- DB-level uniqueness still enforces one vote per IP per item per module
- Race-condition protection preserved via $inserted guard (see prev commit)
Technical notes:
- host column is VARCHAR(45), covers both IPv4 and IPv6
- PHP duplicate check logic (by host for guests, by uid for users) unchanged
- Migration is idempotent: IF EXISTS prevents error on already-applied runs
The voting list page exposed raw $stitle in HTML attribute and JS onclick context, and fetched an unused column from the database.
Core changes:
- voting() (modules/voting/index.php):
- Apply htmlspecialchars($stitle, ENT_QUOTES) in title="" attribute
Apply htmlspecialchars($stitle, ENT_QUOTES) in JS DelCheck() argument to prevent apostrophes from breaking the inline event handler string
- Remove unused 'questions' column from SELECT and list() destructuring
- Remove unused $confv from global declaration in view()
- Replace foreach ($langlist as $key => $val) with $val only
Benefits:
- Eliminates attribute-injection risk for admin-authored titles with quotes
- Prevents JS syntax error in moderator delete confirmation for special chars
- Reduces SELECT payload by one unused column
Technical notes:
- $stitle is already HTML-entity encoded at save time via save_text()
- htmlspecialchars() adds a second encoding layer safe for attribute context
- Behavior preserved; no template or route changes
Previously, if the INSERT into _rating failed (e.g. due to a DB constraint violation), code continued and updated vote counters anyway, causing silent count inflation across all rating-enabled modules.
Core changes:
- Rating function (core/system.php):
- Capture sql_query() result into $inserted
- Wrap all module UPDATE statements and update_points() calls in if ($inserted)
- SELECT + echo ajax_rating() still runs to return current state to client
- avoting_save() (core/system.php):
- Same guard applied to the voting-specific INSERT path
- Vote answer array update and update_points(42) skipped on INSERT fail
- getVoting() result still returned so UI shows current results
Benefits:
- Vote counters stay consistent with actual _rating table rows
- Eliminates data corruption on duplicate-key or race-condition failures
- getVoting() / ajax_rating() always return a response, preserving UX
Technical notes:
- sql_query() returns false on PDOException (caught internally) and logs
- Fix covers both rating() and avoting_save() code paths
- No schema changes in this commit
The admin basic item template used positional array references (\$arg[1] through \$arg[10]) which were fragile and hard to read. Replaces them with descriptive named tokens matching the keys passed by setTemplateBasic().
Core changes:
- Placeholder rename (templates/admin/basic.html):
- \$arg[2] → {%id%}
- \$arg[3] → {%title%}
- \$arg[4] → {%text%}
- \$arg[5] → {%post%}
- \$arg[6] → {%date%}
- \$arg[7] → {%reads%}
- \$arg[8] → {%comm%}
- \$arg[9] → {%rating%}
- \$arg[10] → {%admin%}
- \$arg[1] → {%ctitle%}
Benefits:
- Template is self-documenting; field purpose visible without cross-referencing PHP
- Named tokens decouple template from positional argument order
- Consistent with the named-token convention used in other templates
Technical notes:
- Requires setTemplateBasic() callers to pass named-key arrays
- No HTML structure changed; layout identical
Converts the sitemap public module to current SLAED PHP conventions: 4-space indentation, single-quoted strings, void return type, SITEMAP_DIR constant for file resolution, and updated template helpers.
Core changes:
- Code style (modules/sitemap/index.php):
- Tabs → 4-space indentation throughout
- Double-quoted strings → single-quoted
- sitemap() → sitemap(): void
- File path (modules/sitemap/index.php):
Hardcoded 'config/sitemap/sitemap.txt' → SITEMAP_DIR.'/sitemap.txt'
- Resolves via constant, independent of working directory
- Template helpers (modules/sitemap/index.php):
- tpl_eval('title', ...) → setTemplateBasic('title', ['title' => ...])
- tpl_eval('open/close') → setTemplateBasic('open/close')
- tpl_warn() → setTemplateWarning()
- Switch style (modules/sitemap/index.php):
- Multiline switch/case → compact single-line form
- Removed closing ?>
Benefits:
- Consistent style with other modernized public modules
- File path resolved via constant rather than implicit cwd
Technical notes:
- Behavior unchanged; pure refactor
- Copyright year updated to 2026
Cleans up the sitemap admin module: replaces $aroute with $afile, uses the SITEMAP_DIR constant for file paths, adds a null-check for fopen(), passes the $legacy parameter to getAdminTabs(), and guards file_get_contents() with is_readable().
Core changes:
- Global variable (modules/sitemap/admin/index.php):
- $aroute → $afile in all functions (sitemap, xsl, xslsave, conf, confsave)
- File path hardening (modules/sitemap/admin/index.php):
- Hardcoded 'sitemap.xsl' → SITEMAP_DIR.'/sitemap.xsl'
- file_get_contents() → is_readable() guard before read
fopen() now checked for false before entering while loop
- fclose() moved inside the if-block to prevent warning on null handle
- Navigation fix (modules/sitemap/admin/index.php):
- $legacy parameter now forwarded correctly to getAdminTabs()
Benefits:
- Eliminates $aroute global; consistent with other modernized modules
- Prevents PHP warnings from fopen() failure on missing XML files
- File paths resolved via constant rather than implicit cwd
Technical notes:
- Behavior unchanged; pure refactor and hardening
- fopen() suppression (@) retained from original for non-critical read