feat(i18n): LocaleController switcher with open-redirect protection (closes #73)

- App\Controllers\LocaleController: GET /locale?set=xx&return=/path
  - Sets 1-year cookie (HttpOnly=false for SSR, SameSite=Lax, Secure on HTTPS)
  - 302 redirect to explicit return URL > Referer > /
  - Pure buildResponse() helper for unit tests (no headers/exit)
  - current() helper: resolves locale from $_GET/$_COOKIE/Accept-Language
- safeRedirect: rejects absolute URLs, protocol-relative (//evil.com),
  backslash tricks (\\evil.com), javascript:/data: schemes
- 28 PHPUnit tests (LocaleControllerTest), all green
- Total project tests now: 92
This commit is contained in:
Hermes
2026-06-04 08:57:33 +00:00
parent 63c8c759d2
commit ce21242308
3 changed files with 307 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ $router = new Router();
$router->addRoute('/', \App\Controllers\HomeController::class, 'index');
$router->addRoute('/impressum', \App\Controllers\ImpressumController::class, 'index');
$router->addRoute('/datenschutz', \App\Controllers\DatenschutzController::class, 'index');
$router->addRoute('/locale', \App\Controllers\LocaleController::class, 'switch');
// Dispatch
$uri = $_SERVER['REQUEST_URI'] ?? '/';