<?php /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * \***************************************************************************/ /** * Gestion des headers et redirections * * @package SPIP\Core\Headers **/ if (!defined('_ECRIRE_INC_VERSION')) { return; } /** * Envoyer le navigateur sur une nouvelle adresse * * Le tout en évitant les attaques par la redirection (souvent indique par un `$_GET`) * * @example * ``` * $redirect = parametre_url(urldecode(_request('redirect')),'id_article=' . $id_article); * include_spip('inc/headers'); * redirige_par_entete($redirect); * ``` * * @param string $url URL de redirection * @param string $equiv ? * @param int $status Code de redirection (301 ou 302) **/ function redirige_par_entete($url, $equiv = '', $status = 302) { if (!in_array($status, array(301, 302))) { $status = 302; } $url = trim(strtr($url, "\n\r", " ")); # si l'url de redirection est relative, on la passe en absolue if (!preg_match(",^(\w+:)?//,", $url)) { include_spip("inc/filtres_mini"); $url = url_absolue($url); } if ($x = _request('transformer_xml')) { $url = parametre_url($url, 'transformer_xml', $x, '&'); } if (defined('_AJAX') and _AJAX) { $url = parametre_url($url, 'var_ajax_redir', 1, '&'); } // ne pas laisser passer n'importe quoi dans l'url $url = str_replace(array('<', '"'), array('<', '"'), $url); $url = str_replace(array("\r", "\n", ' '), array('%0D', '%0A', '%20'), $url); while (strpos($url, '%0A') !== false) { $url = str_replace('%0A', '', $url); } // interdire les url inline avec des pseudo-protocoles : if ( (preg_match(",data:,i", $url) and preg_match("/base64\s*,/i", $url)) or preg_match(",(javascript|mailto):,i", $url) ) { $url = "./"; } // Il n'y a que sous Apache que setcookie puis redirection fonctionne include_spip('inc/cookie'); if ((!$equiv and !spip_cookie_envoye()) or ( (strncmp("Apache", $_SERVER['SERVER_SOFTWARE'], 6) == 0) or (stripos($_SERVER['SERVER_SIGNATURE'], 'Apache') !== false) or function_exists('apache_getenv') or defined('_SERVER_APACHE') ) ) { @header("Location: " . $url); $equiv = ""; } else { @header("Refresh: 0; url=" . $url); if (isset($GLOBALS['meta']['charset'])) { @header("Content-Type: text/html; charset=" . $GLOBALS['meta']['charset']); } $equiv = "<meta http-equiv='Refresh' content='0; url=$url'>"; } include_spip('inc/lang'); if ($status != 302) { http_status($status); } echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">', "\n", html_lang_attributes(), ' <head>', $equiv, ' <title>HTTP ' . $status . '</title> ' . ((isset($GLOBALS['meta']['charset'])) ? '<meta http-equiv="Content-Type" content="text/html;charset=' . $GLOBALS['meta']['charset'] . '">' : '') . ' </head> <body> <h1>HTTP ' . $status . '</h1> <a href="', quote_amp($url), '">', _T('navigateur_pas_redirige'), '</a></body></html>'; spip_log("redirige $status: $url"); exit; } // http://code.spip.net/@redirige_formulaire function redirige_formulaire($url, $equiv = '', $format = 'message') { if (!_AJAX and !headers_sent() and !_request('var_ajax') ) { redirige_par_entete(str_replace('&', '&', $url), $equiv); } // si c'est une ancre, fixer simplement le window.location.hash elseif ($format == 'ajaxform' and preg_match(',^#[0-9a-z\-_]+$,i', $url)) { return array( // on renvoie un lien masque qui sera traite par ajaxCallback.js "<a href='$url' name='ajax_ancre' style='display:none;'>anchor</a>", // et rien dans le message ok '' ); } else { // ne pas laisser passer n'importe quoi dans l'url $url = str_replace(array('<', '"'), array('<', '"'), $url); $url = strtr($url, "\n\r", " "); # en theorie on devrait faire ca tout le temps, mais quand la chaine # commence par ? c'est imperatif, sinon l'url finale n'est pas la bonne if ($url[0] == '?') { $url = url_de_base() . $url; } $url = str_replace('&', '&', $url); spip_log("redirige formulaire ajax: $url"); include_spip('inc/filtres'); if ($format == 'ajaxform') { return array( // on renvoie un lien masque qui sera traite par ajaxCallback.js '<a href="' . quote_amp($url) . '" name="ajax_redirect" style="display:none;">' . _T('navigateur_pas_redirige') . '</a>', // et un message au cas ou '<br /><a href="' . quote_amp($url) . '">' . _T('navigateur_pas_redirige') . '</a>' ); } else // format message texte, tout en js inline { return // ie poste les formulaires dans une iframe, il faut donc rediriger son parent "<script type='text/javascript'>if (parent.window){parent.window.document.location.replace(\"$url\");} else {document.location.replace(\"$url\");}</script>" . http_img_pack('searching.gif', '') . '<br />' . '<a href="' . quote_amp($url) . '">' . _T('navigateur_pas_redirige') . '</a>'; } } } /** * Effectue une redirection par header PHP vers un script de l’interface privée * * @uses redirige_par_entete() Qui tue le script PHP. * @example * ``` * include_spip('inc/headers'); * redirige_url_ecrire('rubriques','id_rubrique=' . $id_rubrique); * ``` * * @param string $script * Nom de la page privée (exec) * @param string $args * Arguments à transmettre. Exemple `etape=1&autre=oui` * @param string $equiv * @return void **/ function redirige_url_ecrire($script = '', $args = '', $equiv = '') { return redirige_par_entete(generer_url_ecrire($script, $args, true), $equiv); } /** * Renvoie au client le header HTTP avec le message correspondant au code indiqué. * * Ainsi `http_status(301)` enverra le message `301 Moved Permanently`. * * @link https://www.php.net/manual/fr/function.http-response-code.php * @uses http_response_code() * * @param int $status * Code d'erreur **/ function http_status($status) { http_response_code($status); } // Retourne ce qui va bien pour que le navigateur ne mette pas la page en cache // http://code.spip.net/@http_no_cache function http_no_cache() { if (headers_sent()) { spip_log("http_no_cache arrive trop tard"); return; } $charset = empty($GLOBALS['meta']['charset']) ? 'utf-8' : $GLOBALS['meta']['charset']; // selon http://developer.apple.com/internet/safari/faq.html#anchor5 // il faudrait aussi pour Safari // header("Cache-Control: post-check=0, pre-check=0", false) // mais ca ne respecte pas // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 header("Content-Type: text/html; charset=$charset"); header("Expires: 0"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); }