Completed
Push — master ( 55c88a...92be1d )
by cam
04:36
created

headers.php ➔ redirige_par_entete()   F

Complexity

Conditions 19
Paths 192

Size

Total Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
nc 192
nop 3
dl 0
loc 71
rs 3.75
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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('&lt;', '&quot;'), $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 (isset($_SERVER['SERVER_SIGNATURE']) and stripos($_SERVER['SERVER_SIGNATURE'], 'Apache') !== false)
75
			or function_exists('apache_getenv')
76
			or defined('_SERVER_APACHE')
77
		)
78
	) {
79
		@header("Location: " . $url);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
80
		$equiv = "";
81
	} else {
82
		@header("Refresh: 0; url=" . $url);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
83
		if (isset($GLOBALS['meta']['charset'])) {
84
			@header("Content-Type: text/html; charset=" . $GLOBALS['meta']['charset']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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('&amp;', '&', $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('&lt;', '&quot;'), $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('&amp;', '&', $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