0, 'path' => '/', 'secure' => $secure, 'httponly' => true, 'samesite' => 'Strict', ]); session_start(); } function mvlog_auth_config(): array { if (!is_file(MVLOG_AUTH_CONFIG)) return ['users' => []]; $config = require MVLOG_AUTH_CONFIG; return is_array($config) ? $config : ['users' => []]; } function mvlog_login(string $user, string $password): bool { mvlog_session_start(); $users = mvlog_auth_config()['users'] ?? []; $hash = is_array($users) ? ($users[$user] ?? null) : null; if (!is_string($hash) || !password_verify($password, $hash)) return false; session_regenerate_id(true); $_SESSION['mvlog_user'] = $user; $_SESSION['mvlog_login_at'] = time(); return true; } function mvlog_current_user(): ?string { mvlog_session_start(); return isset($_SESSION['mvlog_user']) && is_string($_SESSION['mvlog_user']) ? $_SESSION['mvlog_user'] : null; } function mvlog_normalize_next(string $next): string { if ($next === '' || str_contains($next, " ") || str_contains($next, " ")) return '/admin.php'; $parts = parse_url($next); if ($parts === false || isset($parts['scheme']) || isset($parts['host'])) return '/admin.php'; $path = (string)($parts['path'] ?? ''); if ($path === '' || $path === '/mvlog') { $path = '/admin.php'; } elseif (str_starts_with($path, '/mvlog/')) { $path = substr($path, 6); } $query = isset($parts['query']) ? ('?' . $parts['query']) : ''; return $path . $query; } function mvlog_require_login(): void { if (mvlog_current_user() !== null) return; $next = mvlog_normalize_next((string)($_SERVER['REQUEST_URI'] ?? '/admin.php')); header('Location: login.php?next=' . rawurlencode($next)); exit; } function mvlog_logout(): void { mvlog_session_start(); $_SESSION = []; if (ini_get('session.use_cookies')) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'] ?? '', $params['secure'], $params['httponly']); } session_destroy(); } function mvlog_safe_next(string $next): string { return mvlog_normalize_next($next); }