Subversion Repositories Applications.papyrus

Rev

Rev 320 | Rev 1706 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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