Subversion Repositories Applications.framework

Rev

Rev 85 | Rev 120 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 85 Rev 105
Line 1... Line 1...
1
<?php
1
<?php
2
// +-----------------------------------------------------------------------+
-
 
3
// | Copyright (c) 2007-2008, Christian Schmidt, Peytz & Co. A/S           |
-
 
4
// | All rights reserved.                                                  |
-
 
5
// |                                                                       |
-
 
6
// | Redistribution and use in source and binary forms, with or without    |
-
 
7
// | modification, are permitted provided that the following conditions    |
-
 
8
// | are met:                                                              |
-
 
9
// |                                                                       |
-
 
10
// | o Redistributions of source code must retain the above copyright      |
-
 
11
// |   notice, this list of conditions and the following disclaimer.       |
-
 
12
// | o Redistributions in binary form must reproduce the above copyright   |
-
 
13
// |   notice, this list of conditions and the following disclaimer in the |
-
 
14
// |   documentation and/or other materials provided with the distribution.|
-
 
15
// | o The names of the authors may not be used to endorse or promote      |
-
 
16
// |   products derived from this software without specific prior written  |
-
 
17
// |   permission.                                                         |
-
 
18
// |                                                                       |
-
 
19
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
-
 
20
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
-
 
21
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-
 
22
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
-
 
23
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-
 
24
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
-
 
25
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-
 
26
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-
 
27
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
-
 
28
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-
 
29
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
-
 
30
// |                                                                       |
-
 
31
// +-----------------------------------------------------------------------+
-
 
32
// | Author: Christian Schmidt <schmidt at php dot net>                    |
-
 
33
// +-----------------------------------------------------------------------+
-
 
34
//
-
 
35
// $Id: Url.php 85 2009-08-27 08:19:18Z jpm $
-
 
36
//
-
 
37
// Net_URL2 Class (PHP5 Only)
2
// declare(encoding='UTF-8');
38
 
-
 
39
// This code is released under the BSD License - http://www.opensource.org/licenses/bsd-license.php
-
 
40
/**
3
/**
-
 
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
-
 
6
* 
-
 
7
* PHP Version 5 
-
 
8
* 
-
 
9
* @category  Class
41
 * @license BSD License
10
* @package   Framework
-
 
11
// auteur principal
-
 
12
* @author    Christian Schmidt <schmidt@php.net>
-
 
13
// autre auteurs
-
 
14
* @author    aurelien <aurelien@tela-botanica.org>
-
 
15
* @copyright 2009 Tela-Botanica
-
 
16
* @license   http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL  
-
 
17
* @license   http://www.gnu.org/licenses/gpl.html Licence GNU-GPL  
-
 
18
* @version   SVN: $Id: Url.php 105 2009-08-31 15:25:05Z aurelien $ 
-
 
19
* @link      /doc/framework/ 
-
 
20
* 
42
 */
21
*/
43
class Url
22
class Url
44
{
23
{
45
    /**
24
    /**
46
     * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default
25
     * Parsing strict dans resoudre() (voir RFC 3986, section 5.2.2). Par défaut
47
     * is true.
26
     * à true.
48
     */
27
     */
49
    const OPTION_STRICT           = 'strict';
28
    const OPTION_STRICTE           = 'strict';
Line 50... Line 29...
50
 
29
 
51
    /**
30
    /**
52
     * Represent arrays in query using PHP's [] notation. Default is true.
31
     * Répresenter les tableaux dans les requêtes en utilisant la notation php []. Par défaut à true.
53
     */
32
     */
Line 54... Line 33...
54
    const OPTION_USE_BRACKETS     = 'use_brackets';
33
    const OPTION_UTILISER_CROCHETS     = 'use_brackets';
55
 
34
 
56
    /**
35
    /**
57
     * URL-encode query variable keys. Default is true.
36
     * URL-encoder les clés des variables dans les requêtes. Par défaut à true.
Line 58... Line 37...
58
     */
37
     */
59
    const OPTION_ENCODE_KEYS      = 'encode_keys';
38
    const OPTION_ENCODER_CLES      = 'encode_keys';
60
 
39
 
61
    /**
40
    /**
62
     * Query variable separators when parsing the query string. Every character
41
     * Séparateurs de variables lors du parsing de la requête. Chaque caractère
63
     * is considered a separator. Default is specified by the
42
     * est considéré comme un séparateur. Par défaut, spécifié par le paramêtre
Line 64... Line 43...
64
     * arg_separator.input php.ini setting (this defaults to "&").
43
     * arg_separator.input dans php.ini (par défaut "&").
65
     */
44
     */
66
    const OPTION_SEPARATOR_INPUT  = 'input_separator';
45
    const OPTION_SEPARATEUR_ENTREE  = 'input_separator';
67
 
-
 
68
    /**
46
 
69
     * Query variable separator used when generating the query string. Default
47
    /**
Line 70... Line 48...
70
     * is specified by the arg_separator.output php.ini setting (this defaults
48
     * Séparateur de variables lors de la génération de la requête. Par défaut, spécifié
71
     * to "&").
49
     * par le paramètre arg_separator.output dans php.ini (par défaut "&").
-
 
50
     */
72
     */
51
    const OPTION_SEPARATEUR_SORTIE = 'output_separator';
73
    const OPTION_SEPARATOR_OUTPUT = 'output_separator';
52
 
74
 
53
    /**
75
    /**
54
     * Options par défaut correspondant au comportement de php
76
     * Default options corresponds to how PHP handles $_GET.
55
     * vis à vis de $_GET
77
     */
56
     */
78
    private $options = array(
57
    private $options = array(
79
        self::OPTION_STRICT           => true,
58
        self::OPTION_STRICTE           => true,
Line 80... Line 59...
80
        self::OPTION_USE_BRACKETS     => true,
59
        self::OPTION_UTILISER_CROCHETS     => true,
81
        self::OPTION_ENCODE_KEYS      => true,
60
        self::OPTION_ENCODER_CLES      => true,
82
        self::OPTION_SEPARATOR_INPUT  => 'x&',
61
        self::OPTION_SEPARATEUR_ENTREE  => 'x&',
83
        self::OPTION_SEPARATOR_OUTPUT => 'x&',
62
        self::OPTION_SEPARATEUR_SORTIE => 'x&',
Line 84... Line 63...
84
        );
63
        );
85
 
64
 
86
    /**
65
    /**
87
     * @var  string|bool
66
     * @var  string|bool
Line 88... Line 67...
88
     */
67
     */
89
    private $scheme = false;
68
    private $schema = false;
90
 
69
 
91
    /**
70
    /**
Line 92... Line 71...
92
     * @var  string|bool
71
     * @var  string|bool
93
     */
72
     */
94
    private $userinfo = false;
73
    private $infoUtilisateur = false;
95
 
74
 
Line 96... Line 75...
96
    /**
75
    /**
97
     * @var  string|bool
76
     * @var  string|bool
98
     */
77
     */
99
    private $host = false;
78
    private $hote = false;
Line 100... Line 79...
100
 
79
 
101
    /**
80
    /**
102
     * @var  int|bool
81
     * @var  int|bool
103
     */
82
     */
Line 104... Line 83...
104
    private $port = false;
83
    private $port = false;
105
 
84
 
106
    /**
85
    /**
107
     * @var  string
86
     * @var  string
Line 108... Line 87...
108
     */
87
     */
109
    private $path = '';
88
    private $chemin = '';
110
 
89
 
111
    /**
90
    /**
112
     * @var  string|bool
91
     * @var  string|bool
113
     */
92
     */
114
    private $query = false;
93
    private $requete = false;
115
 
94
 
116
    /**
95
    /**
117
     * @var  string|bool
96
     * @var  string|bool
118
     */
97
     */
119
    private $fragment = false;
98
    private $fragment = false;
120
 
99
 
121
    /**
100
    /**
122
     * @param string $url     an absolute or relative URL
101
     * @param string $url     une URL relative ou absolue
Line 123... Line 102...
123
     * @param array  $options
102
     * @param array  $options
124
     */
103
     */
125
    public function __construct($url, $options = null)
104
    public function __construct($url, $options = null)
126
    {
105
    {
Line 127... Line 106...
127
        $this->setOption(self::OPTION_SEPARATOR_INPUT,
106
        $this->setOption(self::OPTION_SEPARATEUR_ENTREE,
128
                         ini_get('arg_separator.input'));
107
                         ini_get('arg_separator.input'));
129
        $this->setOption(self::OPTION_SEPARATOR_OUTPUT,
108
        $this->setOption(self::OPTION_SEPARATEUR_SORTIE,
130
                         ini_get('arg_separator.output'));
109
                         ini_get('arg_separator.output'));
Line 131... Line 110...
131
        if (is_array($options)) {
110
        if (is_array($options)) {
132
            foreach ($options as $optionName => $value) {
111
            foreach ($options as $nomOption => $valeur) {
133
                $this->setOption($optionName);
112
                $this->setOption($nomOption);
Line 134... Line 113...
134
            }
113
            }
135
        }
114
        }
136
 
115
 
137
        if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
116
        if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
Line 138... Line 117...
138
            $this->scheme = $reg[1];
117
            $this->schema = $reg[1];
139
            $url = substr($url, strlen($reg[0]));
118
            $url = substr($url, strlen($reg[0]));
140
        }
119
        }
141
 
120
 
Line 142... Line 121...
142
        if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
121
        if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
143
            $this->setAuthority($reg[1]);
122
            $this->setAutorite($reg[1]);
144
            $url = substr($url, strlen($reg[0]));
123
            $url = substr($url, strlen($reg[0]));
145
        }
124
        }
146
 
125
 
147
        $i = strcspn($url, '?#');
126
        $i = strcspn($url, '?#');
148
        $this->path = substr($url, 0, $i);
127
        $this->chemin = substr($url, 0, $i);
149
        $url = substr($url, $i);
128
        $url = substr($url, $i);
150
 
129
 
151
        if (preg_match('@^\?([^#]*)@', $url, $reg)) {
130
        if (preg_match('@^\?([^#]*)@', $url, $reg)) {
Line 152... Line 131...
152
            $this->query = $reg[1];
131
            $this->requete = $reg[1];
153
            $url = substr($url, strlen($reg[0]));
132
            $url = substr($url, strlen($reg[0]));
154
        }
133
        }
155
 
134
 
156
        if ($url) {
135
        if ($url) {
157
            $this->fragment = substr($url, 1);
136
            $this->fragment = substr($url, 1);
158
        }
137
        }
159
    }
138
    }
160
 
139
 
161
    /**
140
    /**
Line 162... Line 141...
162
     * Returns the scheme, e.g. "http" or "urn", or false if there is no
141
     * Retourne le schéma, c.a.d. "http" ou "urn", ou false si aucun schéma n'est
163
     * scheme specified, i.e. if this is a relative URL.
142
     * spécifié, i.e. l'url est une url relative
164
     *
143
     *
165
     * @return  string|bool
144
     * @return  string|bool
166
     */
145
     */
167
    public function getScheme()
146
    public function getSchema()
168
    {
147
    {
169
        return $this->scheme;
148
        return $this->schema;
170
    }
149
    }
171
 
150
 
Line 172... Line 151...
172
    /**
151
    /**
173
     * @param string|bool $scheme
152
     * @param string|bool $schema
174
     *
153
     *
175
     * @return void
154
     * @return void
176
     * @see    getScheme()
-
 
177
     */
155
     * @see    getSchema()
178
    public function setScheme($scheme)
156
     */
179
    {
157
    public function setSchema($schema)
180
        $this->scheme = $scheme;
158
    {
181
    }
159
        $this->schema = $schema;
182
 
160
    }
183
    /**
161
 
Line 184... Line 162...
184
     * Returns the user part of the userinfo part (the part preceding the first
162
    /**
185
     *  ":"), or false if there is no userinfo part.
163
     * renvoie la partie user de la partie infoUtilisateur (partie précédant le premier
186
     *
164
     *  ":"), ou false si aucune partie infoUtilisateur n'est définie.
187
     * @return  string|bool
165
     *
188
     */
166
     * @return  string|bool
189
    public function getUser()
167
     */
190
    {
168
    public function getUtilisateur()
191
        return $this->userinfo !== false ? preg_replace('@:.*$@', '', $this->userinfo) : false;
169
    {
192
    }
170
        return $this->infoUtilisateur !== false ? preg_replace('@:.*$@', '', $this->infoUtilisateur) : false;
193
 
171
    }
Line 194... Line 172...
194
    /**
172
 
195
     * Returns the password part of the userinfo part (the part after the first
173
    /**
196
     *  ":"), or false if there is no userinfo part (i.e. the URL does not
174
     * renvoie la partie mot de passe de la partie infoUtilisateur (partie après le premier
197
     * contain "@" in front of the hostname) or the userinfo part does not
175
     *  ":"), , ou false si aucune partie infoUtilisateur n'est définie (i.e. l'URL ne contient 
198
     * contain ":".
176
     * pas de "@" en face du nom d'hôte) ou si la partie infoUtilisateur ne contient pas de ":".
199
     *
177
     *
200
     * @return  string|bool
178
     * @return  string|bool
201
     */
179
     */
202
    public function getPassword()
180
    public function getMotDePasse()
203
    {
181
    {
204
        return $this->userinfo !== false ? substr(strstr($this->userinfo, ':'), 1) : false;
182
        return $this->infoUtilisateur !== false ? substr(strstr($this->infoUtilisateur, ':'), 1) : false;
205
    }
183
    }
206
 
184
 
207
    /**
185
    /**
208
     * Returns the userinfo part, or false if there is none, i.e. if the
186
     * Renvoie la partie userinfio, ou false si celle-ci n'existe pas, i.e. si la partie 
209
     * authority part does not contain "@".
187
     * autorité ne contient pas de "@"
Line 210... Line 188...
210
     *
188
     *
211
     * @return  string|bool
189
     * @return  string|bool
212
     */
190
     */
213
    public function getUserinfo()
191
    public function getInfoUtilisateur()
214
    {
192
    {
215
        return $this->userinfo;
193
        return $this->infoUtilisateur;
216
    }
194
    }
217
 
195
 
218
    /**
196
    /**
219
     * Sets the userinfo part. If two arguments are passed, they are combined
197
     * Setteur pour la partie infoUtilisateur. Si deux argument sont passé, ils sont combinés
Line 220... Line 198...
220
     * in the userinfo part as username ":" password.
198
     * dans la partie infoUtilisateur de cette manière username ":" password.
221
     *
199
     *
222
     * @param string|bool $userinfo userinfo or username
200
     * @param string|bool $infoUtilisateur infoUtilisateur ou username
223
     * @param string|bool $password
201
     * @param string|bool $motDePasse
224
     *
202
     *
225
     * @return void
203
     * @return void
226
     */
204
     */
227
    public function setUserinfo($userinfo, $password = false)
205
    public function setInfoUtilisateur($infoUtilisateur, $motDePasse = false)
228
    {
206
    {
Line 229... Line 207...
229
        $this->userinfo = $userinfo;
207
        $this->infoUtilisateur = $infoUtilisateur;
230
        if ($password !== false) {
208
        if ($motDePasse !== false) {
231
            $this->userinfo .= ':' . $password;
209
            $this->infoUtilisateur .= ':' . $motDePasse;
232
        }
210
        }
233
    }
211
    }
234
 
212
 
235
    /**
213
    /**
236
     * Returns the host part, or false if there is no authority part, e.g.
214
     * Renvoie la partie hôte, ou false s'il n'y a pas de partie autorité, c.a.d.
Line 273... Line 251...
273
    {
251
    {
274
        $this->port = intval($port);
252
        $this->port = intval($port);
275
    }
253
    }
Line 276... Line 254...
276
 
254
 
277
    /**
255
    /**
278
     * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or
256
     * Renvoie la partie autorité, i.e. [ infoUtilisateur "@" ] hote [ ":" port ], ou
279
     * false if there is no authority none.
257
     * false si celle-ci est absente.
280
     *
258
     *
281
     * @return string|bool
259
     * @return string|bool
282
     */
260
     */
283
    public function getAuthority()
261
    public function getAutorite()
284
    {
262
    {
285
        if (!$this->host) {
263
        if (!$this->hote) {
286
            return false;
264
            return false;
Line 287... Line 265...
287
        }
265
        }
Line 288... Line 266...
288
 
266
 
289
        $authority = '';
267
        $autorite = '';
290
 
268
 
Line 291... Line 269...
291
        if ($this->userinfo !== false) {
269
        if ($this->infoUtilisateur !== false) {
Line 292... Line 270...
292
            $authority .= $this->userinfo . '@';
270
            $autorite .= $this->infoUtilisateur . '@';
293
        }
271
        }
294
 
272
 
Line 295... Line 273...
295
        $authority .= $this->host;
273
        $autorite .= $this->hote;
296
 
274
 
Line 297... Line 275...
297
        if ($this->port !== false) {
275
        if ($this->port !== false) {
298
            $authority .= ':' . $this->port;
276
            $autorite .= ':' . $this->port;
299
        }
277
        }
300
 
278
 
301
        return $authority;
279
        return $autorite;
302
    }
280
    }
303
 
281
 
304
    /**
282
    /**
305
     * @param string|false $authority
283
     * @param string|false $autorite
306
     *
284
     *
307
     * @return void
285
     * @return void
308
     */
286
     */
309
    public function setAuthority($authority)
287
    public function setAutorite($autorite)
310
    {
288
    {
311
        $this->user = false;
289
        $this->user = false;
Line 312... Line 290...
312
        $this->pass = false;
290
        $this->pass = false;
313
        $this->host = false;
291
        $this->hote = false;
314
        $this->port = false;
292
        $this->port = false;
315
        if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) {
293
        if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $autorite, $reg)) {
316
            if ($reg[1]) {
294
            if ($reg[1]) {
317
                $this->userinfo = $reg[2];
295
                $this->infoUtilisateur = $reg[2];
Line 318... Line 296...
318
            }
296
            }
319
 
297
 
320
            $this->host = $reg[3];
298
            $this->hote = $reg[3];
321
            if (isset($reg[5])) {
299
            if (isset($reg[5])) {
322
                $this->port = intval($reg[5]);
300
                $this->port = intval($reg[5]);
323
            }
301
            }
324
        }
302
        }
325
    }
303
    }
326
 
304
 
Line 327... Line 305...
327
    /**
305
    /**
328
     * Returns the path part (possibly an empty string).
306
     * Renvoie la partie chemin (chemin) (éventuellement vide).
329
     *
307
     *
330
     * @return string
308
     * @return string
331
     */
309
     */
332
    public function getPath()
310
    public function getChemin()
333
    {
311
    {
334
        return $this->path;
312
        return $this->chemin;
335
    }
313
    }
Line 336... Line 314...
336
 
314
 
337
    /**
315
    /**
338
     * @param string $path
316
     * @param string $chemin
339
     *
317
     *
340
     * @return void
318
     * @return void
341
     */
319
     */
342
    public function setPath($path)
320
    public function setChemin($chemin)
343
    {
321
    {
344
        $this->path = $path;
322
        $this->chemin = $chemin;
345
    }
323
    }
346
 
324
 
Line 347... Line 325...
347
    /**
325
    /**
348
     * Returns the query string (excluding the leading "?"), or false if "?"
326
     * renvoie la chaine de requête (requete string) (sans le premier "?"), ou false si "?"
349
     * isn't present in the URL.
327
     * n'est pas présent dans l'url.
350
     *
328
     *
351
     * @return  string|bool
329
     * @return  string|bool
352
     * @see     self::getQueryVariables()
330
     * @see     self::getVariablesRequete()
353
     */
331
     */
354
    public function getQuery()
332
    public function getRequete()
355
    {
333
    {
356
        return $this->query;
334
        return $this->requete;
Line 357... Line 335...
357
    }
335
    }
358
 
336
 
359
    /**
337
    /**
360
     * @param string|bool $query
338
     * @param string|bool $requete
361
     *
339
     *
362
     * @return void
340
     * @return void
363
     * @see   self::setQueryVariables()
341
     * @see   self::setVariablesRequete()
Line 386... Line 364...
386
    {
364
    {
387
        $this->fragment = $fragment;
365
        $this->fragment = $fragment;
388
    }
366
    }
Line 389... Line 367...
389
 
367
 
390
    /**
368
    /**
391
     * Returns the query string like an array as the variables would appear in
369
     * Renvoie la requete string sous forme d'un tableau de variables telles qu'elles apparaitraient
392
     * $_GET in a PHP script.
370
     * dans le $_GET d'un script PHP
393
     *
371
     *
394
     * @return  array
372
     * @return  array
395
     */
373
     */
396
    public function getQueryVariables()
374
    public function getVariablesRequete()
397
    {
375
    {
398
        $pattern = '/[' .
376
        $pattern = '/[' .
399
                   preg_quote($this->getOption(self::OPTION_SEPARATOR_INPUT), '/') .
377
                   preg_quote($this->getOption(self::OPTION_SEPARATEUR_ENTREE), '/') .
400
                   ']/';
378
                   ']/';
401
        $parts   = preg_split($pattern, $this->query, -1, PREG_SPLIT_NO_EMPTY);
379
        $parties   = preg_split($pattern, $this->requete, -1, PREG_SPLIT_NO_EMPTY);
Line 402... Line 380...
402
        $return  = array();
380
        $retour  = array();
403
 
381
 
404
        foreach ($parts as $part) {
382
        foreach ($parties as $partie) {
405
            if (strpos($part, '=') !== false) {
383
            if (strpos($partie, '=') !== false) {
406
                list($key, $value) = explode('=', $part, 2);
384
                list($cle, $valeur) = explode('=', $partie, 2);
407
            } else {
385
            } else {
408
                $key   = $part;
386
                $cle   = $partie;
Line 409... Line 387...
409
                $value = null;
387
                $valeur = null;
410
            }
388
            }
411
 
389
 
412
            if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
390
            if ($this->getOption(self::OPTION_ENCODER_CLES)) {
Line 413... Line 391...
413
                $key = rawurldecode($key);
391
                $cle = rawurldecode($cle);
414
            }
392
            }
Line 415... Line 393...
415
            $value = rawurldecode($value);
393
            $valeur = rawurldecode($valeur);
416
 
394
 
Line 417... Line 395...
417
            if ($this->getOption(self::OPTION_USE_BRACKETS) &&
395
            if ($this->getOption(self::OPTION_UTILISER_CROCHETS) &&
418
                preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
396
                preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $cle, $matches)) {
419
 
397
 
420
                $key = $matches[1];
398
                $cle = $matches[1];
Line 421... Line 399...
421
                $idx = $matches[2];
399
                $idx = $matches[2];
422
 
400
 
423
                // Ensure is an array
401
                // On s'assure que c'est bien un tableau
424
                if (empty($return[$key]) || !is_array($return[$key])) {
402
                if (empty($retour[$cle]) || !is_array($retour[$cle])) {
425
                    $return[$key] = array();
403
                    $retour[$cle] = array();
426
                }
404
                }
427
 
405
 
428
                // Add data
406
                // Ajout des données
429
                if ($idx === '') {
407
                if ($idx === '') {
430
                    $return[$key][] = $value;
408
                    $retour[$cle][] = $valeur;
431
                } else {
409
                } else {
432
                    $return[$key][$idx] = $value;
410
                    $retour[$cle][$idx] = $valeur;
433
                }
411
                }
434
            } elseif (!$this->getOption(self::OPTION_USE_BRACKETS)
412
            } elseif (!$this->getOption(self::OPTION_UTILISER_CROCHETS)
435
                      && !empty($return[$key])
413
                      && !empty($retour[$cle])
Line 436... Line 414...
436
            ) {
414
            ) {
437
                $return[$key]   = (array) $return[$key];
415
                $retour[$cle]   = (array) $retour[$cle];
Line 438... Line 416...
438
                $return[$key][] = $value;
416
                $retour[$cle][] = $valeur;
439
            } else {
417
            } else {
440
                $return[$key] = $value;
418
                $retour[$cle] = $valeur;
441
            }
419
            }
442
        }
420
        }
443
 
421
 
444
        return $return;
422
        return $retour;
445
    }
423
    }
446
 
424
 
447
    /**
425
    /**
448
     * @param array $array (name => value) array
426
     * @param array $tableau (nom => valeur) tableau
449
     *
427
     *
450
     * @return void
428
     * @return void
451
     */
429
     */
Line 452... Line 430...
452
    public function setQueryVariables(array $array)
430
    public function setVariablesRequete(array $tableau)
453
    {
431
    {
454
        if (!$array) {
432
        if (!$tableau) {
455
            $this->query = false;
433
            $this->requete = false;
456
        } else {
434
        } else {
457
            foreach ($array as $name => $value) {
435
            foreach ($tableau as $nom => $valeur) {
458
                if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
436
                if ($this->getOption(self::OPTION_ENCODER_CLES)) {
459
                    $name = rawurlencode($name);
437
                    $nom = rawurlencode($nom);
460
                }
438
                }
461
 
439
 
462
                if (is_array($value)) {
440
                if (is_array($valeur)) {
463
                    foreach ($value as $k => $v) {
441
                    foreach ($valeur as $k => $v) {
464
                        $parts[] = $this->getOption(self::OPTION_USE_BRACKETS)
442
                        $parties[] = $this->getOption(self::OPTION_UTILISER_CROCHETS)
465
                            ? sprintf('%s[%s]=%s', $name, $k, $v)
443
                            ? sprintf('%s[%s]=%s', $nom, $k, $v)
466
                            : ($name . '=' . $v);
444
                            : ($nom . '=' . $v);
467
                    }
445
                    }
Line 468... Line 446...
468
                } elseif (!is_null($value)) {
446
                } elseif (!is_null($valeur)) {
469
                    $parts[] = $name . '=' . $value;
447
                    $parties[] = $nom . '=' . $valeur;
470
                } else {
448
                } else {
471
                    $parts[] = $name;
449
                    $parties[] = $nom;
472
                }
450
                }
473
            }
451
            }
474
            $this->query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT),
452
            $this->requete = implode($this->getOption(self::OPTION_SEPARATEUR_SORTIE),
475
                                   $parts);
453
                                   $parties);
476
        }
454
        }
477
    }
455
    }
478
 
456
 
479
    /**
457
    /**
Line 480... Line 458...
480
     * @param string $name
458
     * @param string $nom
481
     * @param mixed  $value
459
     * @param mixed  $valeur
482
     *
460
     *
483
     * @return  array
461
     * @return  array
484
     */
462
     */
485
    public function setQueryVariable($name, $value)
463
    public function setVariableRequete($nom, $valeur)
486
    {
464
    {
487
        $array = $this->getQueryVariables();
465
        $tableau = $this->getVariablesRequete();
488
        $array[$name] = $value;
466
        $tableau[$nom] = $valeur;
489
        $this->setQueryVariables($array);
467
        $this->setVariablesRequete($tableau);
490
    }
468
    }
Line 491... Line 469...
491
 
469
 
492
    /**
470
    /**
493
     * @param string $name
471
     * @param string $nom
494
     *
472
     *
495
     * @return void
473
     * @return void
496
     */
474
     */
497
    public function unsetQueryVariable($name)
475
    public function unsetVariableRequete($nom)
498
    {
476
    {
499
        $array = $this->getQueryVariables();
477
        $tableau = $this->getVariablesRequete();
Line 500... Line 478...
500
        unset($array[$name]);
478
        unset($tableau[$nom]);
501
        $this->setQueryVariables($array);
479
        $this->setVariablesRequete($tableau);
502
    }
480
    }
Line 503... Line 481...
503
 
481
 
504
    /**
482
    /**
505
     * Returns a string representation of this URL.
483
     * Renvoie un représentation sous forme de chaine de l'URL
506
     *
484
     *
507
     * @return  string
485
     * @return  string
Line 508... Line 486...
508
     */
486
     */
509
    public function getURL()
487
    public function getURL()
510
    {
488
    {
Line 511... Line 489...
511
        // See RFC 3986, section 5.3
489
        // Voir RFC 3986, section 5.3
512
        $url = "";
490
        $url = "";
513
 
491
 
Line 514... Line 492...
514
        if ($this->scheme !== false) {
492
        if ($this->schema !== false) {
515
            $url .= $this->scheme . ':';
493
            $url .= $this->schema . ':';
Line 516... Line 494...
516
        }
494
        }
517
 
495
 
518
        $authority = $this->getAuthority();
496
        $autorite = $this->getAutorite();
519
        if ($authority !== false) {
497
        if ($autorite !== false) {
520
            $url .= '//' . $authority;
498
            $url .= '//' . $autorite;
521
        }
499
        }
522
        $url .= $this->path;
500
        $url .= $this->chemin;
523
 
501
 
524
        if ($this->query !== false) {
502
        if ($this->requete !== false) {
525
            $url .= '?' . $this->query;
503
            $url .= '?' . $this->requete;
526
        }
504
        }
527
 
505
 
Line 528... Line 506...
528
        if ($this->fragment !== false) {
506
        if ($this->fragment !== false) {
529
            $url .= '#' . $this->fragment;
507
            $url .= '#' . $this->fragment;
530
        }
508
        }
531
    
509
    
532
        return $url;
510
        return $url;
533
    }
511
    }
534
 
512
 
535
    /** 
513
    /** 
Line 536... Line 514...
536
     * Returns a normalized string representation of this URL. This is useful
514
     * Renvoie une représentation de cette URL sous forme de chaine normalisée. Utile pour la 
537
     * for comparison of URLs.
515
     * comparaison d'URLs
538
     *
516
     *
539
     * @return  string
517
     * @return  string
Line 540... Line 518...
540
     */
518
     */
541
    public function getNormalizedURL()
519
    public function getURLNormalisee()
542
    {
520
    {
543
        $url = clone $this;
521
        $url = clone $this;
Line 544... Line 522...
544
        $url->normalize();
522
        $url->normaliser();
545
        return $url->getUrl();
523
        return $url->getUrl();
546
    }
524
    }
547
 
525
 
Line 548... Line 526...
548
    /** 
526
    /** 
549
     * Returns a normalized Net_URL2 instance.
527
     * Renvoie une instance normalisée de Url
Line 550... Line 528...
550
     *
528
     *
551
     * @return  Net_URL2
529
     * @return  Url
552
     */
530
     */
553
    public function normalize()
531
    public function normaliser()
554
    {
532
    {
555
        // See RFC 3886, section 6
533
        // See RFC 3886, section 6
Line 556... Line 534...
556
 
534
 
557
        // Schemes are case-insensitive
535
        // les cchémas sont insesibles à la casse
Line 558... Line 536...
558
        if ($this->scheme) {
536
        if ($this->schema) {
559
            $this->scheme = strtolower($this->scheme);
537
            $this->schema = strtolower($this->schema);
560
        }
538
        }
561
 
539
 
562
        // Hostnames are case-insensitive
540
        // les noms d'hotes sont insensibles à la casse
Line 563... Line 541...
563
        if ($this->host) {
541
        if ($this->hote) {
564
            $this->host = strtolower($this->host);
542
            $this->hote = strtolower($this->hote);
565
        }
543
        }
566
 
544
 
567
        // Remove default port number for known schemes (RFC 3986, section 6.2.3)
545
        // Supprimer le numéro de port par défaut pour les schemas connus (RFC 3986, section 6.2.3)
568
        if ($this->port &&
546
        if ($this->port &&
569
            $this->scheme &&
547
            $this->schema &&
570
            $this->port == getservbyname($this->scheme, 'tcp')) {
548
            $this->port == getservbyname($this->schema, 'tcp')) {
571
 
549
 
Line 572... Line 550...
572
            $this->port = false;
550
            $this->port = false;
573
        }
551
        }
574
 
552
 
575
        // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1)
553
        // normalisation dans le cas d'un encodage avec %XX pourcentage (RFC 3986, section 6.2.2.1)
576
        foreach (array('userinfo', 'host', 'path') as $part) {
554
        foreach (array('infoUtilisateur', 'hote', 'chemin') as $partie) {
577
            if ($this->$part) {
555
            if ($this->$partie) {
578
                $this->$part  = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$part);
556
                $this->$partie  = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$partie);
579
            }
557
            }
580
        }
558
        }
581
 
559
 
582
        // Path segment normalization (RFC 3986, section 6.2.2.3)
560
        // normalisation des segments du chemin (RFC 3986, section 6.2.2.3)
583
        $this->path = self::removeDotSegments($this->path);
561
        $this->chemin = self::supprimerSegmentsAPoints($this->chemin);
584
 
562
 
585
        // Scheme based normalization (RFC 3986, section 6.2.3)
563
        // normalisation basée sur le schéma (RFC 3986, section 6.2.3)
586
        if ($this->host && !$this->path) {
564
        if ($this->hote && !$this->chemin) {
587
            $this->path = '/';
565
            $this->chemin = '/';
Line 588... Line 566...
588
        }
566
        }
589
    }
567
    }
590
 
568
 
591
    /**
569
    /**
592
     * Returns whether this instance represents an absolute URL.
570
     * Renvoie vrai ou faux suivant que l'instance en cours représente une URL relative ou absolue.
593
     *
571
     *
594
     * @return  bool
572
     * @return  bool
595
     */
573
     */
596
    public function isAbsolute()
574
    public function etreAbsolue()
597
    {
575
    {
598
        return (bool) $this->scheme;
576
        return (bool) $this->schema;
599
    }
577
    }
600
 
578
 
601
    /**
579
    /**
602
     * Returns an Net_URL2 instance representing an absolute URL relative to
580
     * Renvoie une instance de Url représentant une URL absolue relative à
603
     * this URL.
581
     * cette URL.
604
     *
582
     *
605
     * @param Net_URL2|string $reference relative URL
583
     * @param Url|string $reference URL relative
606
     *
584
     *
607
     * @return Net_URL2
585
     * @return Url
608
     */
586
     */
609
    public function resolve($reference)
587
    public function resoudre($reference)
610
    {
588
    {
611
        if (is_string($reference)) {
589
        if (is_string($reference)) {
612
            $reference = new self($reference);
590
            $reference = new self($reference);
613
        }
591
        }
614
        if (!$this->isAbsolute()) {
592
        if (!$this->etreAbsolue()) {
615
            throw new Exception('Base-URL must be absolute');
593
            throw new Exception('L\'URL de base doit être absolue !');
616
        }
594
        }
617
 
595
 
618
        // A non-strict parser may ignore a scheme in the reference if it is
596
        // Un parseur non strict peut choisir d'ignorer un schema dans la référence
619
        // identical to the base URI's scheme.
597
        // si celui ci est identique au schéma de base de l'URI.
620
        if (!$this->getOption(self::OPTION_STRICT) && $reference->scheme == $this->scheme) {
598
        if (!$this->getOption(self::OPTION_STRICTE) && $reference->schema == $this->schema) {
621
            $reference->scheme = false;
599
            $reference->schema = false;
622
        }
600
        }
623
 
601
 
624
        $target = new self('');
602
        $cible = new self('');
625
        if ($reference->scheme !== false) {
603
        if ($reference->schema !== false) {
626
            $target->scheme = $reference->scheme;
604
            $cible->schema = $reference->schema;
627
            $target->setAuthority($reference->getAuthority());
605
            $cible->setAutorite($reference->getAutorite());
628
            $target->path  = self::removeDotSegments($reference->path);
606
            $cible->chemin  = self::supprimerSegmentsAPoints($reference->chemin);
629
            $target->query = $reference->query;
607
            $cible->requete = $reference->requete;
630
        } else {
608
        } else {
631
            $authority = $reference->getAuthority();
609
            $autorite = $reference->getAutorite();
632
            if ($authority !== false) {
610
            if ($autorite !== false) {
633
                $target->setAuthority($authority);
611
                $cible->setAutorite($autorite);
634
                $target->path  = self::removeDotSegments($reference->path);
612
                $cible->chemin  = self::supprimerSegmentsAPoints($reference->chemin);
635
                $target->query = $reference->query;
613
                $cible->requete = $reference->requete;
Line 636... Line 614...
636
            } else {
614
            } else {
Line 637... Line 615...
637
                if ($reference->path == '') {
615
                if ($reference->chemin == '') {
638
                    $target->path = $this->path;
616
                    $cible->chemin = $this->chemin;
Line 639... Line 617...
639
                    if ($reference->query !== false) {
617
                    if ($reference->requete !== false) {
640
                        $target->query = $reference->query;
618
                        $cible->requete = $reference->requete;
641
                    } else {
619
                    } else {
642
                        $target->query = $this->query;
620
                        $cible->requete = $this->requete;
643
                    }
621
                    }
644
                } else {
622
                } else {
645
                    if (substr($reference->path, 0, 1) == '/') {
623
                    if (substr($reference->chemin, 0, 1) == '/') {
646
                        $target->path = self::removeDotSegments($reference->path);
624
                        $cible->chemin = self::supprimerSegmentsAPoints($reference->chemin);
647
                    } else {
625
                    } else {
648
                        // Merge paths (RFC 3986, section 5.2.3)
626
                        // Concaténation chemins (RFC 3986, section 5.2.3)
649
                        if ($this->host !== false && $this->path == '') {
627
                        if ($this->hote !== false && $this->chemin == '') {
Line 650... Line 628...
650
                            $target->path = '/' . $this->path;
628
                            $cible->chemin = '/' . $this->chemin;
651
                        } else {
629
                        } else {
652
                            $i = strrpos($this->path, '/');
630
                            $i = strrpos($this->chemin, '/');
653
                            if ($i !== false) {
631
                            if ($i !== false) {
654
                                $target->path = substr($this->path, 0, $i + 1);
632
                                $cible->chemin = substr($this->chemin, 0, $i + 1);
655
                            }
633
                            }
656
                            $target->path .= $reference->path;
634
                            $cible->chemin .= $reference->chemin;
657
                        }
635
                        }
658
                        $target->path = self::removeDotSegments($target->path);
636
                        $cible->chemin = self::supprimerSegmentsAPoints($cible->chemin);
659
                    }
637
                    }
660
                    $target->query = $reference->query;
638
                    $cible->requete = $reference->requete;
661
                }
639
                }
662
                $target->setAuthority($this->getAuthority());
640
                $cible->setAutorite($this->getAutorite());
663
            }
641
            }
664
            $target->scheme = $this->scheme;
642
            $cible->schema = $this->schema;
665
        }
643
        }
666
 
644
 
667
        $target->fragment = $reference->fragment;
645
        $cible->fragment = $reference->fragment;
668
 
646
 
669
        return $target;
647
        return $cible;
670
    }
648
    }
671
 
649
 
672
    /**
650
    /**
Line 673... Line 651...
673
     * Removes dots as described in RFC 3986, section 5.2.4, e.g.
651
     * La suppression des segments à points est décrite dans la RFC 3986, section 5.2.4, e.g.
674
     * "/foo/../bar/baz" => "/bar/baz"
652
     * "/foo/../bar/baz" => "/bar/baz"
675
     *
653
     *
676
     * @param string $path a path
654
     * @param string $chemin un chemin
677
     *
655
     *
678
     * @return string a path
656
     * @return string un chemin
679
     */
657
     */
680
    private static function removeDotSegments($path)
658
    private static function supprimerSegmentsAPoints($chemin)
681
    {
659
    {
682
        $output = '';
660
        $sortie = '';
683
 
661
 
684
        // Make sure not to be trapped in an infinite loop due to a bug in this
662
        // Assurons de ne pas nous retrouver piégés dans une boucle infinie due à un bug de 
685
        // method
663
        // cette méthode
Line 686... Line 664...
686
        $j = 0; 
664
        $j = 0; 
687
        while ($path && $j++ < 100) {
665
        while ($chemin && $j++ < 100) {
Line 688... Line 666...
688
            // Step A
666
            // Étape A
689
            if (substr($path, 0, 2) == './') {
667
            if (substr($chemin, 0, 2) == './') {
690
                $path = substr($path, 2);
668
                $chemin = substr($chemin, 2);
691
            } elseif (substr($path, 0, 3) == '../') {
669
            } elseif (substr($chemin, 0, 3) == '../') {
692
                $path = substr($path, 3);
670
                $chemin = substr($chemin, 3);
693
 
671
 
694
            // Step B
672
            // Étape B
695
            } elseif (substr($path, 0, 3) == '/./' || $path == '/.') {
673
            } elseif (substr($chemin, 0, 3) == '/./' || $chemin == '/.') {
696
                $path = '/' . substr($path, 3);
674
                $chemin = '/' . substr($chemin, 3);
697
 
675
 
698
            // Step C
676
            // Étape C
699
            } elseif (substr($path, 0, 4) == '/../' || $path == '/..') {
677
            } elseif (substr($chemin, 0, 4) == '/../' || $chemin == '/..') {
Line 700... Line 678...
700
                $path = '/' . substr($path, 4);
678
                $chemin = '/' . substr($chemin, 4);
701
                $i = strrpos($output, '/');
679
                $i = strrpos($sortie, '/');
702
                $output = $i === false ? '' : substr($output, 0, $i);
680
                $sortie = $i === false ? '' : substr($sortie, 0, $i);
703
 
681
 
704
            // Step D
682
            // Étape D
705
            } elseif ($path == '.' || $path == '..') {
683
            } elseif ($chemin == '.' || $chemin == '..') {
706
                $path = '';
684
                $chemin = '';
Line 707... Line 685...
707
 
685
 
708
            // Step E
686
            // Étape E
709
            } else {
687
            } else {
710
                $i = strpos($path, '/');
688
                $i = strpos($chemin, '/');
Line 711... Line 689...
711
                if ($i === 0) {
689
                if ($i === 0) {
712
                    $i = strpos($path, '/', 1);
690
                    $i = strpos($chemin, '/', 1);
713
                }
691
                }
714
                if ($i === false) {
692
                if ($i === false) {
715
                    $i = strlen($path);
693
                    $i = strlen($chemin);
716
                }
694
                }
717
                $output .= substr($path, 0, $i);
695
                $sortie .= substr($chemin, 0, $i);
718
                $path = substr($path, $i);
696
                $chemin = substr($chemin, $i);
719
            }
697
            }
Line 720... Line 698...
720
        }
698
        }
721
 
699
 
722
        return $output;
700
        return $sortie;
723
    }
701
    }
724
 
702
 
725
    /**
703
    /**
726
     * Returns a Net_URL2 instance representing the canonical URL of the
704
     * Renvoie une instance de Url representant l'URL canonique du script PHP
727
     * currently executing PHP script.
705
     * en cours d'éxécution
728
     * 
706
     * 
729
     * @return  string
707
     * @return  string
730
     */
708
     */
731
    public static function getCanonical()
709
    public static function getCanonique()
Line 732... Line 710...
732
    {
710
    {
733
        if (!isset($_SERVER['REQUEST_METHOD'])) {
711
        if (!isset($_SERVER['REQUEST_METHOD'])) {
734
            // ALERT - no current URL
712
            // ALERT - pas d'URL en cours
735
            throw new Exception('Script was not called through a webserver');
713
            throw new Exception('Le script n\'a pas été appellé à travers un serveur web');
736
        }
714
        }
737
 
715
 
738
        // Begin with a relative URL
716
        // on part d'une URL relative
Line 739... Line 717...
739
        $url = new self($_SERVER['PHP_SELF']);
717
        $url = new self($_SERVER['PHP_SELF']);
740
        $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
718
        $url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
741
        $url->host = $_SERVER['SERVER_NAME'];
719
        $url->hote = $_SERVER['SERVER_NAME'];
742
        $port = intval($_SERVER['SERVER_PORT']);
720
        $port = intval($_SERVER['SERVER_PORT']);
743
        if ($url->scheme == 'http' && $port != 80 ||
721
        if ($url->schema == 'http' && $port != 80 ||
744
            $url->scheme == 'https' && $port != 443) {
722
            $url->schema == 'https' && $port != 443) {
745
 
723
 
746
            $url->port = $port;
724
            $url->port = $port;
747
        }
725
        }
748
        return $url;
726
        return $url;
749
    }
727
    }
750
 
728
 
751
    /**
729
    /**
752
     * Returns the URL used to retrieve the current request.
730
     * Renvoie l'URL utilisée pour récupérer la requête en cours
753
     *
731
     *
754
     * @return  string
732
     * @return  string
755
     */
733
     */
756
    public static function getRequestedURL()
734
    public static function getURLDemande()
Line 757... Line 735...
757
    {
735
    {
758
        return self::getRequested()->getUrl();
736
        return self::getDemande()->getUrl();
759
    }
737
    }
760
 
738
 
761
    /**
739
    /**
762
     * Returns a Net_URL2 instance representing the URL used to retrieve the
740
     * Renvoie une instance de Url representant l'URL utilisée pour 
763
     * current request.
741
     * récupérer la requête en cours
764
     *
742
     *
765
     * @return  Net_URL2
743
     * @return  Url
766
     */
744
     */
767
    public static function getRequested()
745
    public static function getDemande()
768
    {
746
    {
Line 769... Line 747...
769
        if (!isset($_SERVER['REQUEST_METHOD'])) {
747
        if (!isset($_SERVER['REQUEST_METHOD'])) {
770
            // ALERT - no current URL
748
            // ALERTE - pas d'URL en cours
771
            throw new Exception('Script was not called through a webserver');
749
            throw new Exception('Le script n\'a pas été appellé à travers un serveur web');