|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/***************************************************************************\ |
|
4
|
|
|
* SPIP, Systeme de publication pour l'internet * |
|
5
|
|
|
* * |
|
6
|
|
|
* Copyright (c) 2001-2019 * |
|
7
|
|
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * |
|
8
|
|
|
* * |
|
9
|
|
|
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. * |
|
10
|
|
|
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * |
|
11
|
|
|
\***************************************************************************/ |
|
12
|
|
|
|
|
13
|
|
|
/** |
|
14
|
|
|
* Gestion des headers et redirections |
|
15
|
|
|
* |
|
16
|
|
|
* @package SPIP\Core\Headers |
|
17
|
|
|
**/ |
|
18
|
|
|
|
|
19
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) { |
|
20
|
|
|
return; |
|
21
|
|
|
} |
|
22
|
|
|
|
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
* Envoyer le navigateur sur une nouvelle adresse |
|
26
|
|
|
* |
|
27
|
|
|
* Le tout en évitant les attaques par la redirection (souvent indique par un `$_GET`) |
|
28
|
|
|
* |
|
29
|
|
|
* @example |
|
30
|
|
|
* ``` |
|
31
|
|
|
* $redirect = parametre_url(urldecode(_request('redirect')),'id_article=' . $id_article); |
|
32
|
|
|
* include_spip('inc/headers'); |
|
33
|
|
|
* redirige_par_entete($redirect); |
|
34
|
|
|
* ``` |
|
35
|
|
|
* |
|
36
|
|
|
* @param string $url URL de redirection |
|
37
|
|
|
* @param string $equiv ? |
|
38
|
|
|
* @param int $status Code de redirection (301 ou 302) |
|
39
|
|
|
**/ |
|
40
|
|
|
function redirige_par_entete($url, $equiv = '', $status = 302) { |
|
41
|
|
|
if (!in_array($status, array(301, 302))) { |
|
42
|
|
|
$status = 302; |
|
43
|
|
|
} |
|
44
|
|
|
|
|
45
|
|
|
$url = trim(strtr($url, "\n\r", " ")); |
|
46
|
|
|
# si l'url de redirection est relative, on la passe en absolue |
|
47
|
|
|
if (!preg_match(",^(\w+:)?//,", $url)) { |
|
48
|
|
|
include_spip("inc/filtres_mini"); |
|
49
|
|
|
$url = url_absolue($url); |
|
50
|
|
|
} |
|
51
|
|
|
|
|
52
|
|
|
if (defined('_AJAX') and _AJAX) { |
|
53
|
|
|
$url = parametre_url($url, 'var_ajax_redir', 1, '&'); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
// ne pas laisser passer n'importe quoi dans l'url |
|
57
|
|
|
$url = str_replace(array('<', '"'), array('<', '"'), $url); |
|
58
|
|
|
$url = str_replace(array("\r", "\n", ' '), array('%0D', '%0A', '%20'), $url); |
|
59
|
|
|
while (strpos($url, '%0A') !== false) { |
|
60
|
|
|
$url = str_replace('%0A', '', $url); |
|
61
|
|
|
} |
|
62
|
|
|
// interdire les url inline avec des pseudo-protocoles : |
|
63
|
|
|
if ( |
|
64
|
|
|
(preg_match(",data:,i", $url) and preg_match("/base64\s*,/i", $url)) |
|
65
|
|
|
or preg_match(",(javascript|mailto):,i", $url) |
|
66
|
|
|
) { |
|
67
|
|
|
$url = "./"; |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
// Il n'y a que sous Apache que setcookie puis redirection fonctionne |
|
71
|
|
|
include_spip('inc/cookie'); |
|
72
|
|
|
if ((!$equiv and !spip_cookie_envoye()) or ( |
|
73
|
|
|
(strncmp("Apache", $_SERVER['SERVER_SOFTWARE'], 6) == 0) |
|
74
|
|
|
or (stripos($_SERVER['SERVER_SIGNATURE'], 'Apache') !== false) |
|
75
|
|
|
or function_exists('apache_getenv') |
|
76
|
|
|
or defined('_SERVER_APACHE') |
|
77
|
|
|
) |
|
78
|
|
|
) { |
|
79
|
|
|
@header("Location: " . $url); |
|
|
|
|
|
|
80
|
|
|
$equiv = ""; |
|
81
|
|
|
} else { |
|
82
|
|
|
@header("Refresh: 0; url=" . $url); |
|
|
|
|
|
|
83
|
|
|
if (isset($GLOBALS['meta']['charset'])) { |
|
84
|
|
|
@header("Content-Type: text/html; charset=" . $GLOBALS['meta']['charset']); |
|
|
|
|
|
|
85
|
|
|
} |
|
86
|
|
|
$equiv = "<meta http-equiv='Refresh' content='0; url=$url'>"; |
|
87
|
|
|
} |
|
88
|
|
|
include_spip('inc/lang'); |
|
89
|
|
|
if ($status != 302) { |
|
90
|
|
|
http_status($status); |
|
91
|
|
|
} |
|
92
|
|
|
echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">', "\n", |
|
93
|
|
|
html_lang_attributes(), ' |
|
94
|
|
|
<head>', |
|
95
|
|
|
$equiv, ' |
|
96
|
|
|
<title>HTTP ' . $status . '</title> |
|
97
|
|
|
' . ((isset($GLOBALS['meta']['charset'])) ? '<meta http-equiv="Content-Type" content="text/html;charset=' . $GLOBALS['meta']['charset'] . '">' : '') . ' |
|
98
|
|
|
</head> |
|
99
|
|
|
<body> |
|
100
|
|
|
<h1>HTTP ' . $status . '</h1> |
|
101
|
|
|
<a href="', |
|
102
|
|
|
quote_amp($url), |
|
103
|
|
|
'">', |
|
104
|
|
|
_T('navigateur_pas_redirige'), |
|
105
|
|
|
'</a></body></html>'; |
|
106
|
|
|
|
|
107
|
|
|
spip_log("redirige $status: $url"); |
|
108
|
|
|
|
|
109
|
|
|
exit; |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
// http://code.spip.net/@redirige_formulaire |
|
113
|
|
|
function redirige_formulaire($url, $equiv = '', $format = 'message') { |
|
114
|
|
|
if (!_AJAX |
|
115
|
|
|
and !headers_sent() |
|
116
|
|
|
and !_request('var_ajax') |
|
117
|
|
|
) { |
|
118
|
|
|
redirige_par_entete(str_replace('&', '&', $url), $equiv); |
|
119
|
|
|
} // si c'est une ancre, fixer simplement le window.location.hash |
|
120
|
|
|
elseif ($format == 'ajaxform' and preg_match(',^#[0-9a-z\-_]+$,i', $url)) { |
|
121
|
|
|
return array( |
|
122
|
|
|
// on renvoie un lien masque qui sera traite par ajaxCallback.js |
|
123
|
|
|
"<a href='$url' name='ajax_ancre' style='display:none;'>anchor</a>", |
|
124
|
|
|
// et rien dans le message ok |
|
125
|
|
|
'' |
|
126
|
|
|
); |
|
127
|
|
|
} else { |
|
128
|
|
|
// ne pas laisser passer n'importe quoi dans l'url |
|
129
|
|
|
$url = str_replace(array('<', '"'), array('<', '"'), $url); |
|
130
|
|
|
|
|
131
|
|
|
$url = strtr($url, "\n\r", " "); |
|
132
|
|
|
# en theorie on devrait faire ca tout le temps, mais quand la chaine |
|
133
|
|
|
# commence par ? c'est imperatif, sinon l'url finale n'est pas la bonne |
|
134
|
|
|
if ($url[0] == '?') { |
|
135
|
|
|
$url = url_de_base() . $url; |
|
136
|
|
|
} |
|
137
|
|
|
$url = str_replace('&', '&', $url); |
|
138
|
|
|
spip_log("redirige formulaire ajax: $url"); |
|
139
|
|
|
include_spip('inc/filtres'); |
|
140
|
|
|
if ($format == 'ajaxform') { |
|
141
|
|
|
return array( |
|
142
|
|
|
// on renvoie un lien masque qui sera traite par ajaxCallback.js |
|
143
|
|
|
'<a href="' . quote_amp($url) . '" name="ajax_redirect" style="display:none;">' . _T('navigateur_pas_redirige') . '</a>', |
|
144
|
|
|
// et un message au cas ou |
|
145
|
|
|
'<br /><a href="' . quote_amp($url) . '">' . _T('navigateur_pas_redirige') . '</a>' |
|
146
|
|
|
); |
|
147
|
|
|
} else // format message texte, tout en js inline |
|
148
|
|
|
{ |
|
149
|
|
|
return |
|
150
|
|
|
// ie poste les formulaires dans une iframe, il faut donc rediriger son parent |
|
151
|
|
|
"<script type='text/javascript'>if (parent.window){parent.window.document.location.replace(\"$url\");} else {document.location.replace(\"$url\");}</script>" |
|
152
|
|
|
. http_img_pack('searching.gif', '') |
|
153
|
|
|
. '<br />' |
|
154
|
|
|
. '<a href="' . quote_amp($url) . '">' . _T('navigateur_pas_redirige') . '</a>'; |
|
155
|
|
|
} |
|
156
|
|
|
} |
|
157
|
|
|
} |
|
158
|
|
|
|
|
159
|
|
|
/** |
|
160
|
|
|
* Effectue une redirection par header PHP vers un script de l’interface privée |
|
161
|
|
|
* |
|
162
|
|
|
* @uses redirige_par_entete() Qui tue le script PHP. |
|
163
|
|
|
* @example |
|
164
|
|
|
* ``` |
|
165
|
|
|
* include_spip('inc/headers'); |
|
166
|
|
|
* redirige_url_ecrire('rubriques','id_rubrique=' . $id_rubrique); |
|
167
|
|
|
* ``` |
|
168
|
|
|
* |
|
169
|
|
|
* @param string $script |
|
170
|
|
|
* Nom de la page privée (exec) |
|
171
|
|
|
* @param string $args |
|
172
|
|
|
* Arguments à transmettre. Exemple `etape=1&autre=oui` |
|
173
|
|
|
* @param string $equiv |
|
174
|
|
|
* @return void |
|
175
|
|
|
**/ |
|
176
|
|
|
function redirige_url_ecrire($script = '', $args = '', $equiv = '') { |
|
177
|
|
|
return redirige_par_entete(generer_url_ecrire($script, $args, true), $equiv); |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
|
|
/** |
|
181
|
|
|
* Renvoie au client le header HTTP avec le message correspondant au code indiqué. |
|
182
|
|
|
* |
|
183
|
|
|
* Ainsi `http_status(301)` enverra le message `301 Moved Permanently`. |
|
184
|
|
|
* |
|
185
|
|
|
* @link http://php.net/manual/fr/function.header.php Fonction header() de PHP utilisée ici |
|
186
|
|
|
* |
|
187
|
|
|
* @param int $status |
|
188
|
|
|
* Code d'erreur |
|
189
|
|
|
**/ |
|
190
|
|
|
function http_status($status) { |
|
191
|
|
|
|
|
192
|
|
|
static $status_string = array( |
|
193
|
|
|
200 => '200 OK', |
|
194
|
|
|
204 => '204 No Content', |
|
195
|
|
|
301 => '301 Moved Permanently', |
|
196
|
|
|
302 => '302 Found', |
|
197
|
|
|
304 => '304 Not Modified', |
|
198
|
|
|
401 => '401 Unauthorized', |
|
199
|
|
|
403 => '403 Forbidden', |
|
200
|
|
|
404 => '404 Not Found', |
|
201
|
|
|
503 => '503 Service Unavailable' |
|
202
|
|
|
); |
|
203
|
|
|
|
|
204
|
|
|
if (!empty($GLOBALS['REDIRECT_STATUS']) && $GLOBALS['REDIRECT_STATUS'] == $status) { |
|
205
|
|
|
return; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
$php_cgi = ($GLOBALS['flag_sapi_name'] and preg_match(",cgi,i", @php_sapi_name())); |
|
209
|
|
|
if ($php_cgi) { |
|
210
|
|
|
header("Status: " . $status_string[$status]); |
|
211
|
|
|
} else { |
|
212
|
|
|
header("HTTP/1.0 " . $status_string[$status]); |
|
213
|
|
|
} |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
// Retourne ce qui va bien pour que le navigateur ne mette pas la page en cache |
|
217
|
|
|
// http://code.spip.net/@http_no_cache |
|
218
|
|
|
function http_no_cache() { |
|
219
|
|
|
if (headers_sent()) { |
|
220
|
|
|
spip_log("http_no_cache arrive trop tard"); |
|
221
|
|
|
|
|
222
|
|
|
return; |
|
223
|
|
|
} |
|
224
|
|
|
$charset = empty($GLOBALS['meta']['charset']) ? 'utf-8' : $GLOBALS['meta']['charset']; |
|
225
|
|
|
|
|
226
|
|
|
// selon http://developer.apple.com/internet/safari/faq.html#anchor5 |
|
227
|
|
|
// il faudrait aussi pour Safari |
|
228
|
|
|
// header("Cache-Control: post-check=0, pre-check=0", false) |
|
229
|
|
|
// mais ca ne respecte pas |
|
230
|
|
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 |
|
231
|
|
|
|
|
232
|
|
|
header("Content-Type: text/html; charset=$charset"); |
|
233
|
|
|
header("Expires: 0"); |
|
234
|
|
|
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); |
|
235
|
|
|
header("Cache-Control: no-cache, must-revalidate"); |
|
236
|
|
|
header("Pragma: no-cache"); |
|
237
|
|
|
} |
|
238
|
|
|
|
If you suppress an error, we recommend checking for the error condition explicitly: