<?php namespace nur\v; use nur\base; use nur\session; /** * Class http: des outils pour parler le protocole HTTP dans le cadre de la * génération d'une page */ class http { static final function get_url(): string { $proto = $_SERVER["HTTP_X_FORWARDED_PROTO"]; $host = $_SERVER["HTTP_X_FORWARDED_HOST"]; $uri = $_SERVER["SCRIPT_NAME"]; return "$proto://$host$uri"; } static final function get_baseurl(): string { $proto = $_SERVER["HTTP_X_FORWARDED_PROTO"]; $host = $_SERVER["HTTP_X_FORWARDED_HOST"]; $baseuri = dirname($_SERVER["SCRIPT_NAME"]); return "$proto://$host$baseuri"; } /** * ne pas mettre en cache la réponse. * * appeler cette méthode est nécessaire si une page est dynamique * et que les sessions ne sont pas utilisées. * * si un session est déjà démarrée, cette méthode est un NOP, sauf si * $force==true */ static function no_cache(bool $force=false): void { if (session::started() && !$force) return; header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); header("Cache-Control: no-cache, max-age=0, must-revalidate"); header("Pragma: public"); } /** spécifier le type de contenu de la réponse */ static function content_type(string $content_type=null, string $charset=null): void { if ($content_type === null) $content_type = "application/octet-stream"; if (substr($content_type, 0, 5) == "text/") { if ($charset === null) $charset = "utf-8"; if ($charset) $content_type .= "; charset=$charset"; } header("Content-Type: $content_type"); } static final function content_type_text(): void { self::content_type("text/plain"); } /** indiquer que la réponse doit être téléchargée */ static function download_as($filename, string $disposition=null): void { if (base::nz($filename)) { $filename = basename($filename); if ($disposition === null) $disposition = "attachment"; header("Content-Disposition: $disposition; filename=\"$filename\""); } } /** rediriger vers l'url spécifiée et arrêter le script immédiatement */ static function redirect(string $url, bool $exit_now=true): void { header("Location: $url"); if ($exit_now) exit; } /** rafraichir vers l'url spécifiée et arrêter le script immédiatement */ static function refresh(string $url, int $delay=1, bool $exit_now=true): void { header("Refresh: $delay; url=$url"); if ($exit_now) exit; } /** envoyer le status "pas de contenu" et arrêter le script immédiatement */ static function send_no_content(bool $exit_now=true): void { header("HTTP/1.1 204 No Content"); if ($exit_now) exit; } /** * Envoyer le fichier spécifié pour téléchargement et arrêter le script * immédiatement. On assume que les méthodes statiques {@link content_type()} * et {@link download_as()} ont déjà été appelées. * * - si $delete==true, supprimer le fichier après téléchargement. * - si $add_content_length==true, ajouter une en-tête qui précise la taille * du fichier à télécharger. attention: la taille du fichier ne devrait pas * changer * - si $close_session==true, la session est fermée avant de lancer le * téléchargement du fichier pour éviter de garder inutilement le verrou. * NB: si le fichier à retourner est d'une certaine taille, il est avisé * de fermer la session pour ne pas bloquer la navigation. * * si une erreur s'est produite, retourner false, même si $exit_now==true */ static function send_file(string $file, bool $delete=false, bool $close_session=true, bool $add_content_length=true, bool $exit_now=true): bool { $fd = fopen($file, "r"); if ($fd === false) return false; if ($close_session) session::close(); if ($add_content_length) { $size = filesize($file); if ($size !== false) header("Content-Length: $size"); } if ($delete) unlink($file); $written = fpassthru($fd); # XXX si $written !== $size, il faudrait agir en conséquence... fclose($fd); if ($written === false) return false; if ($exit_now) exit; return true; } static final function error(string $status, bool $exit=true): void { header("HTTP/1.1 $status"); if ($exit) exit(); } static final function error400(?string $message=null, ?string $body=null, bool $exit=true): void { if ($message === null) $message = "Bad Request"; elseif ($body === null) $body = $message; self::error("400 $message", false); if ($body !== null) echo $body; if ($exit) exit(); } static final function error404(?string $message=null, ?string $body=null, bool $exit=true): void { if ($message === null) $message = "Not Found"; elseif ($body === null) $body = $message; self::error("404 $message", false); if ($body !== null) echo $body; if ($exit) exit(); } static final function error500(?string $message=null, ?string $body=null, bool $exit=true): void { if ($message === null) $message = "Internal Server Error"; elseif ($body === null) $body = $message; self::error("500 $message", false); if ($body !== null) echo $body; if ($exit) exit(); } }