always wins. * - The actual bytes stream through /admin/media.php (the server validated * inlined below), preserving the existing security checks (path whitelist, * realpath() jail, MIME allow-list, Interdit bypass gated by admin session). * * Security: * - Auth-gated by AdminAuth::requireLogin(). * - Path is validated against thesis-file prefixes before it is passed on. * - The embedded iframe is same-origin (/admin/media.php); admin CSP permits * frame-src 'self'. noindex/nofollow and no-referrer keep it private. * * Usage: /admin/media-viewer.php?path=tfe/2025/2025-001/rapport.pdf */ require_once __DIR__ . '/../../bootstrap.php'; require_once __DIR__ . '/../../src/AdminAuth.php'; AdminAuth::requireLogin(); require_once APP_ROOT . '/src/Database.php'; require_once APP_ROOT . '/src/ErrorHandler.php'; $path = trim((string)($_GET['path'] ?? '')); // Only thesis-file paths are ever served; reject anything else early. if (!preg_match('#^(theses|documents|tfe|these|frart)/[^?&]{1,255}$#', $path)) { http_response_code(400); echo 'Chemin invalide.'; exit; } $displayName = 'Document'; try { $mediaDb = Database::getInstance(); $displayName = $mediaDb->getFileDisplayName($path) ?? basename($path); } catch (\Throwable $e) { ErrorHandler::log('media_viewer_display', $e, ['path' => $path]); } if ($displayName === '') { $displayName = 'Document'; } $src = '/admin/media.php?path=' . urlencode($path); $title = htmlspecialchars($displayName); $srcAttr = htmlspecialchars($src); ?> <?= $title ?> – XAMXAM