1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18: class Url {
19:
20: 21: 22:
23: const OPTION_UTILISER_CROCHETS = 'utiliser_crochets';
24:
25: 26: 27:
28: const OPTION_ENCODER_CLES = 'encoder_cles';
29:
30: 31: 32:
33: const OPTION_ENCODER_VALEURS = 'encoder_valeurs';
34:
35: 36: 37: 38: 39:
40: const OPTION_SEPARATEUR_ENTREE = 'separateur_entree';
41:
42: 43: 44: 45:
46: const OPTION_SEPARATEUR_SORTIE = 'separateur_sortie';
47:
48: 49: 50: 51:
52: private $options = array(
53: self::OPTION_UTILISER_CROCHETS => true,
54: self::OPTION_ENCODER_CLES => true,
55: self::OPTION_ENCODER_VALEURS => false,
56: self::OPTION_SEPARATEUR_ENTREE => '&',
57: self::OPTION_SEPARATEUR_SORTIE => '&');
58:
59: 60: 61:
62: private $schema = false;
63:
64: 65: 66:
67: private $infoUtilisateur = false;
68:
69: 70: 71:
72: private $hote = false;
73:
74: 75: 76:
77: private $port = false;
78:
79: 80: 81:
82: private $chemin = '';
83:
84: 85: 86:
87: private $requete = false;
88:
89: 90: 91:
92: private $fragment = false;
93:
94:
95: private $parametres_obligatoires = array('url_arg_separateur_entree', 'url_arg_separateur_sortie');
96:
97: 98: 99: 100:
101: public function __construct($url, $options = null) {
102: Config::verifierPresenceParametres($this->parametres_obligatoires);
103:
104: $this->setOption(self::OPTION_SEPARATEUR_ENTREE, Config::get('url_arg_separateur_entree'));
105: $this->setOption(self::OPTION_SEPARATEUR_SORTIE, Config::get('url_arg_separateur_sortie'));
106: if (is_array($options)) {
107: foreach ($options as $nomOption => $valeur) {
108: $this->setOption($nomOption);
109: }
110: }
111:
112: if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
113: $this->schema = $reg[1];
114: $url = substr($url, strlen($reg[0]));
115: }
116:
117: if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
118: $this->setAutorite($reg[1]);
119: $url = substr($url, strlen($reg[0]));
120: }
121:
122: $i = strcspn($url, '?#');
123: $this->chemin = substr($url, 0, $i);
124: $url = substr($url, $i);
125:
126: if (preg_match('@^\?([^#]*)@', $url, $reg)) {
127: $this->requete = $reg[1];
128: $url = substr($url, strlen($reg[0]));
129: }
130:
131: if ($url) {
132: $this->fragment = substr($url, 1);
133: }
134: }
135:
136: 137: 138: 139: 140: 141: 142:
143: public function getOption($nomOption) {
144: return isset($this->options[$nomOption]) ? $this->options[$nomOption] : false;
145: }
146:
147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157:
158: public function setOption($nomOption, $valeur) {
159: if (!array_key_exists($nomOption, $this->options)) {
160: return false;
161: }
162: $this->options[$nomOption] = $valeur;
163: }
164:
165: 166: 167: 168: 169: 170:
171: private function getAutorite() {
172: if (!$this->hote) {
173: return false;
174: }
175:
176: $autorite = '';
177:
178: if ($this->infoUtilisateur !== false) {
179: $autorite .= $this->infoUtilisateur . '@';
180: }
181:
182: $autorite .= $this->hote;
183:
184: if ($this->port !== false) {
185: $autorite .= ':' . $this->port;
186: }
187:
188: return $autorite;
189: }
190:
191: 192: 193: 194: 195:
196: private function setAutorite($autorite) {
197: $this->user = false;
198: $this->pass = false;
199: $this->hote = false;
200: $this->port = false;
201: if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $autorite, $reg)) {
202: if ($reg[1]) {
203: $this->infoUtilisateur = $reg[2];
204: }
205:
206: $this->hote = $reg[3];
207: if (isset($reg[5])) {
208: $this->port = intval($reg[5]);
209: }
210: }
211: }
212:
213: 214: 215: 216: 217:
218: private function etreAbsolue() {
219: return (bool) $this->schema;
220: }
221:
222: 223: 224: 225: 226: 227: 228: 229:
230: private static function supprimerSegmentsAPoints($chemin) {
231: $sortie = '';
232:
233:
234: $j = 0;
235: while ($chemin && $j++ < 100) {
236: if (substr($chemin, 0, 2) == './') {
237: $chemin = substr($chemin, 2);
238: } else if (substr($chemin, 0, 3) == '../') {
239: $chemin = substr($chemin, 3);
240: } else if (substr($chemin, 0, 3) == '/./' || $chemin == '/.') {
241: $chemin = '/' . substr($chemin, 3);
242: } else if (substr($chemin, 0, 4) == '/../' || $chemin == '/..') {
243: $chemin = '/' . substr($chemin, 4);
244: $i = strrpos($sortie, '/');
245: $sortie = $i === false ? '' : substr($sortie, 0, $i);
246: } else if ($chemin == '.' || $chemin == '..') {
247: $chemin = '';
248: } else {
249: $i = strpos($chemin, '/');
250: if ($i === 0) {
251: $i = strpos($chemin, '/', 1);
252: }
253: if ($i === false) {
254: $i = strlen($chemin);
255: }
256: $sortie .= substr($chemin, 0, $i);
257: $chemin = substr($chemin, $i);
258: }
259: }
260:
261: return $sortie;
262: }
263:
264: 265: 266: 267: 268: 269:
270: public function setRequete(Array $parametres) {
271: if (!$parametres) {
272: $this->requete = false;
273: } else {
274: foreach ($parametres as $nom => $valeur) {
275: if ($this->getOption(self::OPTION_ENCODER_CLES)) {
276: $nom = rawurlencode($nom);
277: }
278:
279: if ($this->getOption(self::OPTION_ENCODER_VALEURS)) {
280: $valeur = rawurlencode($valeur);
281: }
282:
283: if (is_array($valeur)) {
284: foreach ($valeur as $k => $v) {
285: if ($this->getOption(self::OPTION_UTILISER_CROCHETS)) {
286: $parties[] = sprintf('%s[%s]=%s', $nom, $k, $v);
287: } else {
288: $parties[] = $nom.'='.$v;
289: }
290: }
291: } else if (!is_null($valeur)) {
292: $parties[] = $nom . '=' . $valeur;
293: } else {
294: $parties[] = $nom;
295: }
296: }
297: $this->requete = implode($this->getOption(self::OPTION_SEPARATEUR_SORTIE), $parties);
298: }
299: }
300:
301: 302: 303: 304: 305: 306: 307:
308: public function fusionnerRequete(Array $parametres) {
309: if ($parametres) {
310: $requete = $parametres + $_GET;
311: $this->setRequete($requete);
312: }
313: }
314:
315: 316: 317: 318: 319:
320: public function normaliser() {
321:
322:
323:
324: if ($this->schema) {
325: $this->schema = strtolower($this->schema);
326: }
327:
328:
329: if ($this->hote) {
330: $this->hote = strtolower($this->hote);
331: }
332:
333:
334: if ($this->port && $this->schema && $this->port == getservbyname($this->schema, 'tcp')) {
335: $this->port = false;
336: }
337:
338:
339: foreach (array('infoUtilisateur', 'hote', 'chemin') as $partie) {
340: if ($this->$partie) {
341: $this->$partie = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$partie);
342: }
343: }
344:
345:
346: $this->chemin = self::supprimerSegmentsAPoints($this->chemin);
347:
348:
349: if ($this->hote && !$this->chemin) {
350: $this->chemin = '/';
351: }
352: }
353:
354: 355: 356: 357: 358:
359: public static function getCanonique() {
360: $url = null;
361: if (!isset($_SERVER['REQUEST_METHOD'])) {
362: trigger_error("Le script n'a pas été appellé à travers un serveur web", E_USER_WARNING);
363: } else {
364:
365: $url = new self($_SERVER['PHP_SELF']);
366: $url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
367: $url->hote = $_SERVER['SERVER_NAME'];
368: $port = intval($_SERVER['SERVER_PORT']);
369: if ($url->schema == 'http' && $port != 80 || $url->schema == 'https' && $port != 443) {
370: $url->port = $port;
371: }
372: }
373: return $url;
374: }
375:
376: 377: 378: 379: 380:
381: public static function getDemande() {
382: $url = null;
383: if (!isset($_SERVER['REQUEST_METHOD'])) {
384: trigger_error("Le script n'a pas été appellé à travers un serveur web", E_USER_WARNING);
385: } else {
386:
387: $url = new self($_SERVER['REQUEST_URI']);
388: $url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
389:
390: $url->setAutorite($_SERVER['HTTP_hote']);
391: }
392: return $url;
393: }
394:
395:
396: 397: 398: 399: 400:
401: public function getURL() {
402:
403: $url = '';
404:
405: if ($this->schema !== false) {
406: $url .= $this->schema . ':';
407: }
408:
409: $autorite = $this->getAutorite();
410: if ($autorite !== false) {
411: $url .= '//' . $autorite;
412: }
413: $url .= $this->chemin;
414:
415: if ($this->requete !== false) {
416: $url .= '?' . $this->requete;
417: }
418:
419: if ($this->fragment !== false) {
420: $url .= '#' . $this->fragment;
421: }
422:
423: return $url;
424: }
425: }
426: ?>