Subversion Repositories Applications.papyrus

Rev

Rev 1706 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
<?php
2
// +-----------------------------------------------------------------------+
3
// | Copyright (c) 2002-2004, Richard Heyes                                |
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: Richard Heyes <richard at php net>                            |
33
// +-----------------------------------------------------------------------+
34
//
35
// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $
36
//
37
// Net_URL Class
38
 
39
 
40
class Net_URL
41
{
42
    var $options = array('encode_query_keys' => false);
43
    /**
44
    * Full url
45
    * @var string
46
    */
47
    var $url;
48
 
49
    /**
50
    * Protocol
51
    * @var string
52
    */
53
    var $protocol;
54
 
55
    /**
56
    * Username
57
    * @var string
58
    */
59
    var $username;
60
 
61
    /**
62
    * Password
63
    * @var string
64
    */
65
    var $password;
66
 
67
    /**
68
    * Host
69
    * @var string
70
    */
71
    var $host;
72
 
73
    /**
74
    * Port
75
    * @var integer
76
    */
77
    var $port;
78
 
79
    /**
80
    * Path
81
    * @var string
82
    */
83
    var $path;
84
 
85
    /**
86
    * Query string
87
    * @var array
88
    */
89
    var $querystring;
90
 
91
    /**
92
    * Anchor
93
    * @var string
94
    */
95
    var $anchor;
96
 
97
    /**
98
    * Whether to use []
99
    * @var bool
100
    */
101
    var $useBrackets;
102
 
103
    /**
104
    * PHP4 Constructor
105
    *
106
    * @see __construct()
107
    */
108
    function Net_URL($url = null, $useBrackets = true)
109
    {
110
        $this->__construct($url, $useBrackets);
111
    }
112
 
113
    /**
114
    * PHP5 Constructor
115
    *
116
    * Parses the given url and stores the various parts
117
    * Defaults are used in certain cases
118
    *
119
    * @param string $url         Optional URL
120
    * @param bool   $useBrackets Whether to use square brackets when
121
    *                            multiple querystrings with the same name
122
    *                            exist
123
    */
124
    function __construct($url = null, $useBrackets = true)
125
    {
126
        $this->url = $url;
127
        $this->useBrackets = $useBrackets;
128
 
129
        $this->initialize();
130
    }
131
 
132
    function initialize()
133
    {
134
        $HTTP_SERVER_VARS  = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
135
 
136
        $this->user        = '';
137
        $this->pass        = '';
138
        $this->host        = '';
139
        $this->port        = 80;
140
        $this->path        = '';
141
        $this->querystring = array();
142
        $this->anchor      = '';
143
 
144
        // Only use defaults if not an absolute URL given
145
        if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
146
            $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
147
 
148
            /**
149
            * Figure out host/port
150
            */
151
            if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) &&
152
                preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches))
153
            {
154
                $host = $matches[1];
155
                if (!empty($matches[3])) {
156
                    $port = $matches[3];
157
                } else {
158
                    $port = $this->getStandardPort($this->protocol);
159
                }
160
            }
161
 
162
            $this->user        = '';
163
            $this->pass        = '';
164
            $this->host        = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
165
            $this->port        = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
166
            $this->path        = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
167
            $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
168
            $this->anchor      = '';
169
        }
170
 
171
        // Parse the url and store the various parts
172
        if (!empty($this->url)) {
173
            $urlinfo = parse_url($this->url);
174
 
175
            // Default querystring
176
            $this->querystring = array();
177
 
178
            foreach ($urlinfo as $key => $value) {
179
                switch ($key) {
180
                    case 'scheme':
181
                        $this->protocol = $value;
182
                        $this->port     = $this->getStandardPort($value);
183
                        break;
184
 
185
                    case 'user':
186
                    case 'pass':
187
                    case 'host':
188
                    case 'port':
189
                        $this->$key = $value;
190
                        break;
191
 
192
                    case 'path':
193
                        if ($value{0} == '/') {
194
                            $this->path = $value;
195
                        } else {
196
                            $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
197
                            $this->path = sprintf('%s/%s', $path, $value);
198
                        }
199
                        break;
200
 
201
                    case 'query':
202
                        $this->querystring = $this->_parseRawQueryString($value);
203
                        break;
204
 
205
                    case 'fragment':
206
                        $this->anchor = $value;
207
                        break;
208
                }
209
            }
210
        }
211
    }
212
    /**
213
    * Returns full url
214
    *
215
    * @return string Full url
216
    * @access public
217
    */
218
    function getURL()
219
    {
220
        $querystring = $this->getQueryString();
221
 
222
        $this->url = $this->protocol . '://'
223
                   . $this->user . (!empty($this->pass) ? ':' : '')
224
                   . $this->pass . (!empty($this->user) ? '@' : '')
225
                   . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
226
                   . $this->path
227
                   . (!empty($querystring) ? '?' . $querystring : '')
228
                   . (!empty($this->anchor) ? '#' . $this->anchor : '');
229
 
230
        return $this->url;
231
    }
232
 
233
    /**
234
    * Adds or updates a querystring item (URL parameter).
235
    * Automatically encodes parameters with rawurlencode() if $preencoded
236
    *  is false.
237
    * You can pass an array to $value, it gets mapped via [] in the URL if
238
    * $this->useBrackets is activated.
239
    *
240
    * @param  string $name       Name of item
241
    * @param  string $value      Value of item
242
    * @param  bool   $preencoded Whether value is urlencoded or not, default = not
243
    * @access public
244
    */
245
    function addQueryString($name, $value, $preencoded = false)
246
    {
247
        if ($this->getOption('encode_query_keys')) {
248
            $name = rawurlencode($name);
249
        }
250
 
251
        if ($preencoded) {
252
            $this->querystring[$name] = $value;
253
        } else {
254
            $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
255
        }
256
    }
257
 
258
    /**
259
    * Removes a querystring item
260
    *
261
    * @param  string $name Name of item
262
    * @access public
263
    */
264
    function removeQueryString($name)
265
    {
266
        if ($this->getOption('encode_query_keys')) {
267
            $name = rawurlencode($name);
268
        }
269
 
270
        if (isset($this->querystring[$name])) {
271
            unset($this->querystring[$name]);
272
        }
273
    }
274
 
275
    /**
276
    * Sets the querystring to literally what you supply
277
    *
278
    * @param  string $querystring The querystring data. Should be of the format foo=bar&x=y etc
279
    * @access public
280
    */
281
    function addRawQueryString($querystring)
282
    {
283
        $this->querystring = $this->_parseRawQueryString($querystring);
284
    }
285
 
286
    /**
287
    * Returns flat querystring
288
    *
289
    * @return string Querystring
290
    * @access public
291
    */
292
    function getQueryString()
293
    {
294
        if (!empty($this->querystring)) {
295
            foreach ($this->querystring as $name => $value) {
296
                // Encode var name
297
                $name = rawurlencode($name);
298
 
299
                if (is_array($value)) {
300
                    foreach ($value as $k => $v) {
301
                        $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
302
                    }
303
                } elseif (!is_null($value)) {
304
                    $querystring[] = $name . '=' . $value;
305
                } else {
306
                    $querystring[] = $name;
307
                }
308
            }
309
            $querystring = implode(ini_get('arg_separator.output'), $querystring);
310
        } else {
311
            $querystring = '';
312
        }
313
 
314
        return $querystring;
315
    }
316
 
317
    /**
318
    * Parses raw querystring and returns an array of it
319
    *
320
    * @param  string  $querystring The querystring to parse
321
    * @return array                An array of the querystring data
322
    * @access private
323
    */
324
    function _parseRawQuerystring($querystring)
325
    {
326
        $parts  = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
327
        $return = array();
328
 
329
        foreach ($parts as $part) {
330
            if (strpos($part, '=') !== false) {
331
                $value = substr($part, strpos($part, '=') + 1);
332
                $key   = substr($part, 0, strpos($part, '='));
333
            } else {
334
                $value = null;
335
                $key   = $part;
336
            }
337
 
338
            if (!$this->getOption('encode_query_keys')) {
339
                $key = rawurldecode($key);
340
            }
341
 
342
            if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
343
                $key = $matches[1];
344
                $idx = $matches[2];
345
 
346
                // Ensure is an array
347
                if (empty($return[$key]) || !is_array($return[$key])) {
348
                    $return[$key] = array();
349
                }
350
 
351
                // Add data
352
                if ($idx === '') {
353
                    $return[$key][] = $value;
354
                } else {
355
                    $return[$key][$idx] = $value;
356
                }
357
            } elseif (!$this->useBrackets AND !empty($return[$key])) {
358
                $return[$key]   = (array)$return[$key];
359
                $return[$key][] = $value;
360
            } else {
361
                $return[$key] = $value;
362
            }
363
        }
364
 
365
        return $return;
366
    }
367
 
368
    /**
369
    * Resolves //, ../ and ./ from a path and returns
370
    * the result. Eg:
371
    *
372
    * /foo/bar/../boo.php    => /foo/boo.php
373
    * /foo/bar/../../boo.php => /boo.php
374
    * /foo/bar/.././/boo.php => /foo/boo.php
375
    *
376
    * This method can also be called statically.
377
    *
378
    * @param  string $path URL path to resolve
379
    * @return string      The result
380
    */
381
    function resolvePath($path)
382
    {
383
        $path = explode('/', str_replace('//', '/', $path));
384
 
385
        for ($i=0; $i<count($path); $i++) {
386
            if ($path[$i] == '.') {
387
                unset($path[$i]);
388
                $path = array_values($path);
389
                $i--;
390
 
391
            } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
392
                unset($path[$i]);
393
                unset($path[$i-1]);
394
                $path = array_values($path);
395
                $i -= 2;
396
 
397
            } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
398
                unset($path[$i]);
399
                $path = array_values($path);
400
                $i--;
401
 
402
            } else {
403
                continue;
404
            }
405
        }
406
 
407
        return implode('/', $path);
408
    }
409
 
410
    /**
411
    * Returns the standard port number for a protocol
412
    *
413
    * @param  string  $scheme The protocol to lookup
414
    * @return integer         Port number or NULL if no scheme matches
415
    *
416
    * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
417
    */
418
    function getStandardPort($scheme)
419
    {
420
        switch (strtolower($scheme)) {
421
            case 'http':    return 80;
422
            case 'https':   return 443;
423
            case 'ftp':     return 21;
424
            case 'imap':    return 143;
425
            case 'imaps':   return 993;
426
            case 'pop3':    return 110;
427
            case 'pop3s':   return 995;
428
            default:        return null;
429
       }
430
    }
431
 
432
    /**
433
    * Forces the URL to a particular protocol
434
    *
435
    * @param string  $protocol Protocol to force the URL to
436
    * @param integer $port     Optional port (standard port is used by default)
437
    */
438
    function setProtocol($protocol, $port = null)
439
    {
440
        $this->protocol = $protocol;
441
        $this->port     = is_null($port) ? $this->getStandardPort($protocol) : $port;
442
    }
443
 
444
    /**
445
     * Set an option
446
     *
447
     * This function set an option
448
     * to be used thorough the script.
449
     *
450
     * @access public
451
     * @param  string $optionName  The optionname to set
452
     * @param  string $value       The value of this option.
453
     */
454
    function setOption($optionName, $value)
455
    {
456
        if (!array_key_exists($optionName, $this->options)) {
457
            return false;
458
        }
459
 
460
        $this->options[$optionName] = $value;
461
        $this->initialize();
462
    }
463
 
464
    /**
465
     * Get an option
466
     *
467
     * This function gets an option
468
     * from the $this->options array
469
     * and return it's value.
470
     *
471
     * @access public
472
     * @param  string $opionName  The name of the option to retrieve
473
     * @see    $this->options
474
     */
475
    function getOption($optionName)
476
    {
477
        if (!isset($this->options[$optionName])) {
478
            return false;
479
        }
480
 
481
        return $this->options[$optionName];
482
    }
483
 
484
}
485
?>