Subversion Repositories Applications.framework

Rev

Rev 286 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 286 Rev 405
1
<?php
1
<?php
2
// declare(encoding='UTF-8');
2
// declare(encoding='UTF-8');
3
/**
3
/**
4
 * Classe Url, gérant le découpage des paramètres, leurs modification etc...
4
 * Classe Url, gérant le découpage des paramètres, leurs modification etc...
5
 * Traduction et conversion d'une classe (NET_Url2) issue de Pear
5
 * Traduction et conversion d'une classe (NET_Url2) issue de Pear
6
 *
6
 *
7
 * @category	Php 5.2
7
 * @category	Php 5.2
8
 * @package	Framework
8
 * @package	Framework
9
 * @author		Christian SCHMIDT <schmidt@php.net> (Auteur classe originale)
9
 * @author		Christian SCHMIDT <schmidt@php.net> (Auteur classe originale)
10
 * @author		Aurélien PERONNET <aurelien@tela-botanica.org>
10
 * @author		Aurélien PERONNET <aurelien@tela-botanica.org>
11
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
11
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
12
 * @copyright	Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
12
 * @copyright	Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
13
 * @license	http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
13
 * @license	http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
14
 * @license	http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
14
 * @license	http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
15
 * @version	SVN: $Id: Url.php 286 2011-01-05 11:37:57Z jpm $
15
 * @version	SVN: $Id: Url.php 405 2012-02-22 15:45:39Z gduche $
16
 * @link		/doc/framework/
16
 * @link		/doc/framework/
17
*/
17
*/
18
class Url {
18
class Url {
19
 
19
 
20
	/**
20
	/**
21
	 * Répresenter les tableaux dans les requêtes en utilisant la notation php []. Par défaut à true.
21
	 * Répresenter les tableaux dans les requêtes en utilisant la notation php []. Par défaut à true.
22
	 */
22
	 */
23
	const OPTION_UTILISER_CROCHETS = 'utiliser_crochets';
23
	const OPTION_UTILISER_CROCHETS = 'utiliser_crochets';
24
 
24
 
25
	/**
25
	/**
26
	 * URL-encoder les clés des variables dans les requêtes. Par défaut à true.
26
	 * URL-encoder les clés des variables dans les requêtes. Par défaut à true.
27
	 */
27
	 */
28
	const OPTION_ENCODER_CLES = 'encoder_cles';
28
	const OPTION_ENCODER_CLES = 'encoder_cles';
29
 
29
 
30
	/**
30
	/**
-
 
31
	* URL-encoder les valeurs des variables dans les requêtes. Par défaut à false.
-
 
32
	*/
-
 
33
	const OPTION_ENCODER_VALEURS = 'encoder_valeurs';
-
 
34
	
-
 
35
	/**
31
	 * Séparateurs de variables lors du parsing de la requête. Chaque caractère
36
	 * Séparateurs de variables lors du parsing de la requête. Chaque caractère
32
	 * est considéré comme un séparateur. Par défaut, spécifié par le paramêtre
37
	 * est considéré comme un séparateur. Par défaut, spécifié par le paramêtre
33
	 * arg_separator.input dans php.ini (par défaut "&").
38
	 * arg_separator.input dans php.ini (par défaut "&").
34
	 */
39
	 */
35
	const OPTION_SEPARATEUR_ENTREE = 'separateur_entree';
40
	const OPTION_SEPARATEUR_ENTREE = 'separateur_entree';
36
 
41
 
37
	/**
42
	/**
38
	 * Séparateur de variables lors de la génération de la requête. Par défaut, spécifié
43
	 * Séparateur de variables lors de la génération de la requête. Par défaut, spécifié
39
	 * par le paramètre arg_separator.output dans php.ini (par défaut "&").
44
	 * par le paramètre arg_separator.output dans php.ini (par défaut "&").
40
	 */
45
	 */
41
	const OPTION_SEPARATEUR_SORTIE = 'separateur_sortie';
46
	const OPTION_SEPARATEUR_SORTIE = 'separateur_sortie';
42
 
47
 
43
	/**
48
	/**
44
	 * Options par défaut correspondant au comportement de php
49
	 * Options par défaut correspondant au comportement de php
45
	 * vis à vis de $_GET
50
	 * vis à vis de $_GET
46
	 */
51
	 */
47
	private $options = array(
52
	private $options = array(
48
		self::OPTION_UTILISER_CROCHETS => true,
53
		self::OPTION_UTILISER_CROCHETS => true,
49
		self::OPTION_ENCODER_CLES => true,
54
		self::OPTION_ENCODER_CLES => true,
-
 
55
		self::OPTION_ENCODER_VALEURS => false,
50
		self::OPTION_SEPARATEUR_ENTREE => '&',
56
		self::OPTION_SEPARATEUR_ENTREE => '&',
51
		self::OPTION_SEPARATEUR_SORTIE => '&');
57
		self::OPTION_SEPARATEUR_SORTIE => '&');
52
 
58
 
53
	/**
59
	/**
54
	 * @var  string|bool
60
	 * @var  string|bool
55
	 */
61
	 */
56
	private $schema = false;
62
	private $schema = false;
57
 
63
 
58
	/**
64
	/**
59
	 * @var  string|bool
65
	 * @var  string|bool
60
	 */
66
	 */
61
	private $infoUtilisateur = false;
67
	private $infoUtilisateur = false;
62
 
68
 
63
	/**
69
	/**
64
	 * @var  string|bool
70
	 * @var  string|bool
65
	 */
71
	 */
66
	private $hote = false;
72
	private $hote = false;
67
 
73
 
68
	/**
74
	/**
69
	 * @var  int|bool
75
	 * @var  int|bool
70
	 */
76
	 */
71
	private $port = false;
77
	private $port = false;
72
 
78
 
73
	/**
79
	/**
74
	 * @var  string
80
	 * @var  string
75
	 */
81
	 */
76
	private $chemin = '';
82
	private $chemin = '';
77
 
83
 
78
	/**
84
	/**
79
	 * @var  string|bool
85
	 * @var  string|bool
80
	 */
86
	 */
81
	private $requete = false;
87
	private $requete = false;
82
 
88
 
83
	/**
89
	/**
84
	 * @var  string|bool
90
	 * @var  string|bool
85
	 */
91
	 */
86
	private $fragment = false;
92
	private $fragment = false;
87
 
93
 
88
	/** Tableau des noms des paramètres à définir dans le fichier de config car obligatoirement nécessaire à cette classe.*/
94
	/** Tableau des noms des paramètres à définir dans le fichier de config car obligatoirement nécessaire à cette classe.*/
89
	private $parametres_obligatoires = array('url_arg_separateur_entree', 'url_arg_separateur_sortie');
95
	private $parametres_obligatoires = array('url_arg_separateur_entree', 'url_arg_separateur_sortie');
90
	
96
	
91
	/**
97
	/**
92
	 * @param string $url	 une URL relative ou absolue
98
	 * @param string $url	 une URL relative ou absolue
93
	 * @param array  $options
99
	 * @param array  $options
94
	 */
100
	 */
95
	public function __construct($url, $options = null) {
101
	public function __construct($url, $options = null) {
96
		Config::verifierPresenceParametres($this->parametres_obligatoires);
102
		Config::verifierPresenceParametres($this->parametres_obligatoires);
97
		
103
		
98
		$this->setOption(self::OPTION_SEPARATEUR_ENTREE, Config::get('url_arg_separateur_entree'));
104
		$this->setOption(self::OPTION_SEPARATEUR_ENTREE, Config::get('url_arg_separateur_entree'));
99
		$this->setOption(self::OPTION_SEPARATEUR_SORTIE, Config::get('url_arg_separateur_sortie'));
105
		$this->setOption(self::OPTION_SEPARATEUR_SORTIE, Config::get('url_arg_separateur_sortie'));
100
		if (is_array($options)) {
106
		if (is_array($options)) {
101
			foreach ($options as $nomOption => $valeur) {
107
			foreach ($options as $nomOption => $valeur) {
102
				$this->setOption($nomOption);
108
				$this->setOption($nomOption);
103
			}
109
			}
104
		}
110
		}
105
 
111
 
106
		if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
112
		if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
107
			$this->schema = $reg[1];
113
			$this->schema = $reg[1];
108
			$url = substr($url, strlen($reg[0]));
114
			$url = substr($url, strlen($reg[0]));
109
		}
115
		}
110
 
116
 
111
		if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
117
		if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
112
			$this->setAutorite($reg[1]);
118
			$this->setAutorite($reg[1]);
113
			$url = substr($url, strlen($reg[0]));
119
			$url = substr($url, strlen($reg[0]));
114
		}
120
		}
115
 
121
 
116
		$i = strcspn($url, '?#');
122
		$i = strcspn($url, '?#');
117
		$this->chemin = substr($url, 0, $i);
123
		$this->chemin = substr($url, 0, $i);
118
		$url = substr($url, $i);
124
		$url = substr($url, $i);
119
 
125
 
120
		if (preg_match('@^\?([^#]*)@', $url, $reg)) {
126
		if (preg_match('@^\?([^#]*)@', $url, $reg)) {
121
			$this->requete = $reg[1];
127
			$this->requete = $reg[1];
122
			$url = substr($url, strlen($reg[0]));
128
			$url = substr($url, strlen($reg[0]));
123
		}
129
		}
124
 
130
 
125
		if ($url) {
131
		if ($url) {
126
			$this->fragment = substr($url, 1);
132
			$this->fragment = substr($url, 1);
127
		}
133
		}
128
	}
134
	}
129
	
135
	
130
	/**
136
	/**
131
	 * Renvoie la valeur de l'option specifiée.
137
	 * Renvoie la valeur de l'option specifiée.
132
	 *
138
	 *
133
	 * @param string $nomOption Nom de l'option demandée
139
	 * @param string $nomOption Nom de l'option demandée
134
	 *
140
	 *
135
	 * @return  mixed
141
	 * @return  mixed
136
	 */
142
	 */
137
	public function getOption($nomOption) {
143
	public function getOption($nomOption) {
138
		return isset($this->options[$nomOption]) ? $this->options[$nomOption] : false;
144
		return isset($this->options[$nomOption]) ? $this->options[$nomOption] : false;
139
	}
145
	}
140
 
146
 
141
	/**
147
	/**
142
	 * Met à jour la valeur de l'option spécifiée.
148
	 * Met à jour la valeur de l'option spécifiée.
143
	 *
149
	 *
144
	 * @param string $nomOption une des constantes commençant par self::OPTION_
150
	 * @param string $nomOption une des constantes commençant par self::OPTION_
145
	 * @param mixed  $valeur	  valeur de l'option
151
	 * @param mixed  $valeur	  valeur de l'option
146
	 *
152
	 *
147
	 * @return void
153
	 * @return void
148
	 * @see  self::OPTION_STRICTE
154
	 * @see  self::OPTION_STRICTE
149
	 * @see  self::OPTION_UTILISER_CROCHETS
155
	 * @see  self::OPTION_UTILISER_CROCHETS
150
	 * @see  self::OPTION_ENCODER_CLES
156
	 * @see  self::OPTION_ENCODER_CLES
151
	 */
157
	 */
152
	public function setOption($nomOption, $valeur) {
158
	public function setOption($nomOption, $valeur) {
153
		if (!array_key_exists($nomOption, $this->options)) {
159
		if (!array_key_exists($nomOption, $this->options)) {
154
			return false;
160
			return false;
155
		}
161
		}
156
		$this->options[$nomOption] = $valeur;
162
		$this->options[$nomOption] = $valeur;
157
	}
163
	}
158
 
164
 
159
	/**
165
	/**
160
	 * Renvoie la partie autorité, i.e. [ infoUtilisateur "@" ] hote [ ":" port ], ou
166
	 * Renvoie la partie autorité, i.e. [ infoUtilisateur "@" ] hote [ ":" port ], ou
161
	 * false si celle-ci est absente.
167
	 * false si celle-ci est absente.
162
	 *
168
	 *
163
	 * @return string|bool
169
	 * @return string|bool
164
	 */
170
	 */
165
	private function getAutorite() {
171
	private function getAutorite() {
166
		if (!$this->hote) {
172
		if (!$this->hote) {
167
			return false;
173
			return false;
168
		}
174
		}
169
 
175
 
170
		$autorite = '';
176
		$autorite = '';
171
 
177
 
172
		if ($this->infoUtilisateur !== false) {
178
		if ($this->infoUtilisateur !== false) {
173
			$autorite .= $this->infoUtilisateur . '@';
179
			$autorite .= $this->infoUtilisateur . '@';
174
		}
180
		}
175
 
181
 
176
		$autorite .= $this->hote;
182
		$autorite .= $this->hote;
177
 
183
 
178
		if ($this->port !== false) {
184
		if ($this->port !== false) {
179
			$autorite .= ':' . $this->port;
185
			$autorite .= ':' . $this->port;
180
		}
186
		}
181
 
187
 
182
		return $autorite;
188
		return $autorite;
183
	}
189
	}
184
 
190
 
185
	/**
191
	/**
186
	 * @param string|false $autorite
192
	 * @param string|false $autorite
187
	 *
193
	 *
188
	 * @return void
194
	 * @return void
189
	 */
195
	 */
190
	private function setAutorite($autorite) {
196
	private function setAutorite($autorite) {
191
		$this->user = false;
197
		$this->user = false;
192
		$this->pass = false;
198
		$this->pass = false;
193
		$this->hote = false;
199
		$this->hote = false;
194
		$this->port = false;
200
		$this->port = false;
195
		if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $autorite, $reg)) {
201
		if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $autorite, $reg)) {
196
			if ($reg[1]) {
202
			if ($reg[1]) {
197
				$this->infoUtilisateur = $reg[2];
203
				$this->infoUtilisateur = $reg[2];
198
			}
204
			}
199
 
205
 
200
			$this->hote = $reg[3];
206
			$this->hote = $reg[3];
201
			if (isset($reg[5])) {
207
			if (isset($reg[5])) {
202
				$this->port = intval($reg[5]);
208
				$this->port = intval($reg[5]);
203
			}
209
			}
204
		}
210
		}
205
	}
211
	}
206
 
212
 
207
	/**
213
	/**
208
	 * Renvoie vrai ou faux suivant que l'instance en cours représente une URL relative ou absolue.
214
	 * Renvoie vrai ou faux suivant que l'instance en cours représente une URL relative ou absolue.
209
	 *
215
	 *
210
	 * @return  bool
216
	 * @return  bool
211
	 */
217
	 */
212
	private function etreAbsolue() {
218
	private function etreAbsolue() {
213
		return (bool) $this->schema;
219
		return (bool) $this->schema;
214
	}
220
	}
215
	
221
	
216
	/**
222
	/**
217
	 * La suppression des segments à points est décrite dans la RFC 3986, section 5.2.4, e.g.
223
	 * La suppression des segments à points est décrite dans la RFC 3986, section 5.2.4, e.g.
218
	 * "/foo/../bar/baz" => "/bar/baz"
224
	 * "/foo/../bar/baz" => "/bar/baz"
219
	 *
225
	 *
220
	 * @param string $chemin un chemin
226
	 * @param string $chemin un chemin
221
	 *
227
	 *
222
	 * @return string un chemin
228
	 * @return string un chemin
223
	 */
229
	 */
224
	private static function supprimerSegmentsAPoints($chemin) {
230
	private static function supprimerSegmentsAPoints($chemin) {
225
		$sortie = '';
231
		$sortie = '';
226
 
232
 
227
		// Assurons nous de ne pas nous retrouver piégés dans une boucle infinie due à un bug de cette méthode
233
		// Assurons nous de ne pas nous retrouver piégés dans une boucle infinie due à un bug de cette méthode
228
		$j = 0;
234
		$j = 0;
229
		while ($chemin && $j++ < 100) {
235
		while ($chemin && $j++ < 100) {
230
			if (substr($chemin, 0, 2) == './') {// Étape A
236
			if (substr($chemin, 0, 2) == './') {// Étape A
231
				$chemin = substr($chemin, 2);
237
				$chemin = substr($chemin, 2);
232
			} else if (substr($chemin, 0, 3) == '../') {
238
			} else if (substr($chemin, 0, 3) == '../') {
233
				$chemin = substr($chemin, 3);
239
				$chemin = substr($chemin, 3);
234
			} else if (substr($chemin, 0, 3) == '/./' || $chemin == '/.') {// Étape B
240
			} else if (substr($chemin, 0, 3) == '/./' || $chemin == '/.') {// Étape B
235
				$chemin = '/' . substr($chemin, 3);
241
				$chemin = '/' . substr($chemin, 3);
236
			} else if (substr($chemin, 0, 4) == '/../' || $chemin == '/..') {// Étape C
242
			} else if (substr($chemin, 0, 4) == '/../' || $chemin == '/..') {// Étape C
237
				$chemin = '/' . substr($chemin, 4);
243
				$chemin = '/' . substr($chemin, 4);
238
				$i = strrpos($sortie, '/');
244
				$i = strrpos($sortie, '/');
239
				$sortie = $i === false ? '' : substr($sortie, 0, $i);
245
				$sortie = $i === false ? '' : substr($sortie, 0, $i);
240
			} else if ($chemin == '.' || $chemin == '..') {// Étape D
246
			} else if ($chemin == '.' || $chemin == '..') {// Étape D
241
				$chemin = '';
247
				$chemin = '';
242
			} else {// Étape E
248
			} else {// Étape E
243
				$i = strpos($chemin, '/');
249
				$i = strpos($chemin, '/');
244
				if ($i === 0) {
250
				if ($i === 0) {
245
					$i = strpos($chemin, '/', 1);
251
					$i = strpos($chemin, '/', 1);
246
				}
252
				}
247
				if ($i === false) {
253
				if ($i === false) {
248
					$i = strlen($chemin);
254
					$i = strlen($chemin);
249
				}
255
				}
250
				$sortie .= substr($chemin, 0, $i);
256
				$sortie .= substr($chemin, 0, $i);
251
				$chemin = substr($chemin, $i);
257
				$chemin = substr($chemin, $i);
252
			}
258
			}
253
		}
259
		}
254
 
260
 
255
		return $sortie;
261
		return $sortie;
256
	}
262
	}
257
	
263
	
258
	/**
264
	/**
259
	 * (Re-)Création de la partie requête de l'URL à partir des données du tableau (passé en paramètre).
265
	 * (Re-)Création de la partie requête de l'URL à partir des données du tableau (passé en paramètre).
260
	 * 
266
	 * 
261
	 * @param array (nom => valeur) tableau de clés & valeurs pour la partie requête de l'url.
267
	 * @param array (nom => valeur) tableau de clés & valeurs pour la partie requête de l'url.
262
	 * @return void (Re-)Création de la partie requête.
268
	 * @return void (Re-)Création de la partie requête.
263
	 */
269
	 */
264
	public function setRequete(Array $parametres) {
270
	public function setRequete(Array $parametres) {
265
		if (!$parametres) {
271
		if (!$parametres) {
266
			$this->requete = false;
272
			$this->requete = false;
267
		} else {
273
		} else {
268
			foreach ($parametres as $nom => $valeur) {
274
			foreach ($parametres as $nom => $valeur) {
269
				if ($this->getOption(self::OPTION_ENCODER_CLES)) {
275
				if ($this->getOption(self::OPTION_ENCODER_CLES)) {
270
					$nom = rawurlencode($nom);
276
					$nom = rawurlencode($nom);
271
				}
277
				}
-
 
278
 
-
 
279
				if ($this->getOption(self::OPTION_ENCODER_VALEURS)) {
-
 
280
					$valeur = rawurlencode($valeur);
-
 
281
				}
272
 
282
				
273
				if (is_array($valeur)) {
283
				if (is_array($valeur)) {
274
					foreach ($valeur as $k => $v) {
284
					foreach ($valeur as $k => $v) {
275
						if ($this->getOption(self::OPTION_UTILISER_CROCHETS)) {
285
						if ($this->getOption(self::OPTION_UTILISER_CROCHETS)) {
276
							$parties[] = sprintf('%s[%s]=%s', $nom, $k, $v);
286
							$parties[] = sprintf('%s[%s]=%s', $nom, $k, $v);
277
						} else {
287
						} else {
278
							$parties[] = $nom.'='.$v;
288
							$parties[] = $nom.'='.$v;
279
						}
289
						}
280
					}
290
					}
281
				} else if (!is_null($valeur)) {
291
				} else if (!is_null($valeur)) {
282
					$parties[] = $nom . '=' . $valeur;
292
					$parties[] = $nom . '=' . $valeur;
283
				} else {
293
				} else {
284
					$parties[] = $nom;
294
					$parties[] = $nom;
285
				}
295
				}
286
			}
296
			}
287
			$this->requete = implode($this->getOption(self::OPTION_SEPARATEUR_SORTIE), $parties);
297
			$this->requete = implode($this->getOption(self::OPTION_SEPARATEUR_SORTIE), $parties);
288
		}
298
		}
289
	}
299
	}
290
	
300
	
291
	/**
301
	/**
292
	 * (Re-)Création de la partie requête de l'URL à partir de la fusion du tableau (passé en paramètre) et 
302
	 * (Re-)Création de la partie requête de l'URL à partir de la fusion du tableau (passé en paramètre) et 
293
	 * les valeurs présentes dans $_GET.
303
	 * les valeurs présentes dans $_GET.
294
	 * 
304
	 * 
295
	 * @param array (nom => valeur) tableau de clés & valeurs pour la partie requête de l'url.
305
	 * @param array (nom => valeur) tableau de clés & valeurs pour la partie requête de l'url.
296
	 * @return void (Re-)Création de la partie requête.
306
	 * @return void (Re-)Création de la partie requête.
297
	 */
307
	 */
298
	public function fusionnerRequete(Array $parametres) {
308
	public function fusionnerRequete(Array $parametres) {
299
		if ($parametres) {
309
		if ($parametres) {
300
			$requete = $parametres + $_GET;
310
			$requete = $parametres + $_GET;
301
			$this->setRequete($requete);
311
			$this->setRequete($requete);
302
		}
312
		}
303
	}
313
	}
304
 
314
 
305
	/**
315
	/**
306
	 * Normalise les données de l'instance d'Url faisant appel à cette méthode.
316
	 * Normalise les données de l'instance d'Url faisant appel à cette méthode.
307
	 *
317
	 *
308
	 * @return  void l'instance d'Url courrante est normalisée.
318
	 * @return  void l'instance d'Url courrante est normalisée.
309
	 */
319
	 */
310
	public function normaliser() {
320
	public function normaliser() {
311
		// Voir RFC 3886, section 6
321
		// Voir RFC 3886, section 6
312
 
322
 
313
		// les cchémas sont insesibles à la casse
323
		// les cchémas sont insesibles à la casse
314
		if ($this->schema) {
324
		if ($this->schema) {
315
			$this->schema = strtolower($this->schema);
325
			$this->schema = strtolower($this->schema);
316
		}
326
		}
317
 
327
 
318
		// les noms d'hotes sont insensibles à la casse
328
		// les noms d'hotes sont insensibles à la casse
319
		if ($this->hote) {
329
		if ($this->hote) {
320
			$this->hote = strtolower($this->hote);
330
			$this->hote = strtolower($this->hote);
321
		}
331
		}
322
 
332
 
323
		// Supprimer le numéro de port par défaut pour les schemas connus (RFC 3986, section 6.2.3)
333
		// Supprimer le numéro de port par défaut pour les schemas connus (RFC 3986, section 6.2.3)
324
		if ($this->port && $this->schema && $this->port == getservbyname($this->schema, 'tcp')) {
334
		if ($this->port && $this->schema && $this->port == getservbyname($this->schema, 'tcp')) {
325
			$this->port = false;
335
			$this->port = false;
326
		}
336
		}
327
 
337
 
328
		// normalisation dans le cas d'un encodage avec %XX pourcentage (RFC 3986, section 6.2.2.1)
338
		// normalisation dans le cas d'un encodage avec %XX pourcentage (RFC 3986, section 6.2.2.1)
329
		foreach (array('infoUtilisateur', 'hote', 'chemin') as $partie) {
339
		foreach (array('infoUtilisateur', 'hote', 'chemin') as $partie) {
330
			if ($this->$partie) {
340
			if ($this->$partie) {
331
				$this->$partie  = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$partie);
341
				$this->$partie  = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$partie);
332
			}
342
			}
333
		}
343
		}
334
 
344
 
335
		// normalisation des segments du chemin (RFC 3986, section 6.2.2.3)
345
		// normalisation des segments du chemin (RFC 3986, section 6.2.2.3)
336
		$this->chemin = self::supprimerSegmentsAPoints($this->chemin);
346
		$this->chemin = self::supprimerSegmentsAPoints($this->chemin);
337
 
347
 
338
		// normalisation basée sur le schéma (RFC 3986, section 6.2.3)
348
		// normalisation basée sur le schéma (RFC 3986, section 6.2.3)
339
		if ($this->hote && !$this->chemin) {
349
		if ($this->hote && !$this->chemin) {
340
			$this->chemin = '/';
350
			$this->chemin = '/';
341
		}
351
		}
342
	}
352
	}
343
 
353
 
344
	/**
354
	/**
345
	 * Renvoie une instance d'objet Url representant l'URL canonique du script PHP en cours d'éxécution.
355
	 * Renvoie une instance d'objet Url representant l'URL canonique du script PHP en cours d'éxécution.
346
	 *
356
	 *
347
	 * @return Url retourne un objet Url ou null en cas d'erreur.
357
	 * @return Url retourne un objet Url ou null en cas d'erreur.
348
	 */
358
	 */
349
	public static function getCanonique() {
359
	public static function getCanonique() {
350
		$url = null;
360
		$url = null;
351
		if (!isset($_SERVER['REQUEST_METHOD'])) {
361
		if (!isset($_SERVER['REQUEST_METHOD'])) {
352
			trigger_error("Le script n'a pas été appellé à travers un serveur web", E_USER_WARNING);
362
			trigger_error("Le script n'a pas été appellé à travers un serveur web", E_USER_WARNING);
353
		} else {
363
		} else {
354
			// À partir d'une URL relative
364
			// À partir d'une URL relative
355
			$url = new self($_SERVER['PHP_SELF']);
365
			$url = new self($_SERVER['PHP_SELF']);
356
			$url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
366
			$url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
357
			$url->hote = $_SERVER['SERVER_NAME'];
367
			$url->hote = $_SERVER['SERVER_NAME'];
358
			$port = intval($_SERVER['SERVER_PORT']);
368
			$port = intval($_SERVER['SERVER_PORT']);
359
			if ($url->schema == 'http' && $port != 80 || $url->schema == 'https' && $port != 443) {
369
			if ($url->schema == 'http' && $port != 80 || $url->schema == 'https' && $port != 443) {
360
				$url->port = $port;
370
				$url->port = $port;
361
			}
371
			}
362
		}
372
		}
363
		return $url;
373
		return $url;
364
	}
374
	}
365
 
375
 
366
	/**
376
	/**
367
	 * Renvoie une instance d'objet Url representant l'URL utilisée pour récupérer la requête en cours.
377
	 * Renvoie une instance d'objet Url representant l'URL utilisée pour récupérer la requête en cours.
368
	 *
378
	 *
369
	 * @return Url retourne un objet Url ou null en cas d'erreur.
379
	 * @return Url retourne un objet Url ou null en cas d'erreur.
370
	 */
380
	 */
371
	public static function getDemande() {
381
	public static function getDemande() {
372
		$url = null;
382
		$url = null;
373
		if (!isset($_SERVER['REQUEST_METHOD'])) {
383
		if (!isset($_SERVER['REQUEST_METHOD'])) {
374
			trigger_error("Le script n'a pas été appellé à travers un serveur web", E_USER_WARNING);
384
			trigger_error("Le script n'a pas été appellé à travers un serveur web", E_USER_WARNING);
375
		} else {
385
		} else {
376
			// On part d'une URL relative
386
			// On part d'une URL relative
377
			$url = new self($_SERVER['REQUEST_URI']);
387
			$url = new self($_SERVER['REQUEST_URI']);
378
			$url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
388
			$url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
379
			// On met à jour les valeurs de l'hôte et si possible du port
389
			// On met à jour les valeurs de l'hôte et si possible du port
380
			$url->setAutorite($_SERVER['HTTP_hote']);
390
			$url->setAutorite($_SERVER['HTTP_hote']);
381
		}
391
		}
382
		return $url;
392
		return $url;
383
	}
393
	}
384
 
394
 
385
	
395
	
386
	/**
396
	/**
387
	 * Renvoie un représentation sous forme de chaine de l'URL.
397
	 * Renvoie un représentation sous forme de chaine de l'URL.
388
	 *
398
	 *
389
	 * @return  string l'url
399
	 * @return  string l'url
390
	 */
400
	 */
391
	public function getURL() {
401
	public function getURL() {
392
		// Voir RFC 3986, section 5.3
402
		// Voir RFC 3986, section 5.3
393
		$url = '';
403
		$url = '';
394
		
404
		
395
		if ($this->schema !== false) {
405
		if ($this->schema !== false) {
396
			$url .= $this->schema . ':';
406
			$url .= $this->schema . ':';
397
		}
407
		}
398
 
408
 
399
		$autorite = $this->getAutorite();
409
		$autorite = $this->getAutorite();
400
		if ($autorite !== false) {
410
		if ($autorite !== false) {
401
			$url .= '//' . $autorite;
411
			$url .= '//' . $autorite;
402
		}
412
		}
403
		$url .= $this->chemin;
413
		$url .= $this->chemin;
404
 
414
 
405
		if ($this->requete !== false) {
415
		if ($this->requete !== false) {
406
			$url .= '?' . $this->requete;
416
			$url .= '?' . $this->requete;
407
		}
417
		}
408
 
418
 
409
		if ($this->fragment !== false) {
419
		if ($this->fragment !== false) {
410
			$url .= '#' . $this->fragment;
420
			$url .= '#' . $this->fragment;
411
		}
421
		}
412
 
422
 
413
		return $url;
423
		return $url;
414
	}
424
	}
415
}
425
}
416
?>
426
?>