Subversion Repositories Applications.papyrus

Rev

Rev 767 | Go to most recent revision | Details | 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
//
35
// $Id: URL.php,v 1.1 2005-03-30 08:50:33 jpm Exp $
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
 
139
            $this->protocol    = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http');
140
 
141
            /**
142
            * Figure out host/port
143
            */
144
            if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {
145
                $host = $matches[1];
146
                if (!empty($matches[3])) {
147
                    $port = $matches[3];
148
                } else {
149
                    $port = $this->getStandardPort($this->protocol);
150
                }
151
            }
152
 
153
            $this->user        = '';
154
            $this->pass        = '';
155
            $this->host        = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
156
            $this->port        = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
157
            $this->path        = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
158
            $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
159
            $this->anchor      = '';
160
        }
161
 
162
        // Parse the url and store the various parts
163
        if (!empty($url)) {
164
            $urlinfo = parse_url($url);
165
 
166
            // Default querystring
167
            $this->querystring = array();
168
 
169
            foreach ($urlinfo as $key => $value) {
170
                switch ($key) {
171
                    case 'scheme':
172
                        $this->protocol = $value;
173
                        $this->port     = $this->getStandardPort($value);
174
                        break;
175
 
176
                    case 'user':
177
                    case 'pass':
178
                    case 'host':
179
                    case 'port':
180
                        $this->$key = $value;
181
                        break;
182
 
183
                    case 'path':
184
                        if ($value{0} == '/') {
185
                            $this->path = $value;
186
                        } else {
187
                            $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
188
                            $this->path = sprintf('%s/%s', $path, $value);
189
                        }
190
                        break;
191
 
192
                    case 'query':
193
                        $this->querystring = $this->_parseRawQueryString($value);
194
                        break;
195
 
196
                    case 'fragment':
197
                        $this->anchor = $value;
198
                        break;
199
                }
200
            }
201
        }
202
    }
203
 
204
    /**
205
    * Returns full url
206
    *
207
    * @return string Full url
208
    * @access public
209
    */
210
    function getURL()
211
    {
212
        $querystring = $this->getQueryString();
213
 
214
        $this->url = $this->protocol . '://'
215
                   . $this->user . (!empty($this->pass) ? ':' : '')
216
                   . $this->pass . (!empty($this->user) ? '@' : '')
217
                   . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
218
                   . $this->path
219
                   . (!empty($querystring) ? '?' . $querystring : '')
220
                   . (!empty($this->anchor) ? '#' . $this->anchor : '');
221
 
222
        return $this->url;
223
    }
224
 
225
    /**
226
    * Adds a querystring item
227
    *
228
    * @param  string $name       Name of item
229
    * @param  string $value      Value of item
230
    * @param  bool   $preencoded Whether value is urlencoded or not, default = not
231
    * @access public
232
    */
233
    function addQueryString($name, $value, $preencoded = false)
234
    {
235
        if ($preencoded) {
236
            $this->querystring[$name] = $value;
237
        } else {
238
            $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
239
        }
240
    }
241
 
242
    /**
243
    * Removes a querystring item
244
    *
245
    * @param  string $name Name of item
246
    * @access public
247
    */
248
    function removeQueryString($name)
249
    {
250
        if (isset($this->querystring[$name])) {
251
            unset($this->querystring[$name]);
252
        }
253
    }
254
 
255
    /**
256
    * Sets the querystring to literally what you supply
257
    *
258
    * @param  string $querystring The querystring data. Should be of the format foo=bar&x=y etc
259
    * @access public
260
    */
261
    function addRawQueryString($querystring)
262
    {
263
        $this->querystring = $this->_parseRawQueryString($querystring);
264
    }
265
 
266
    /**
267
    * Returns flat querystring
268
    *
269
    * @return string Querystring
270
    * @access public
271
    */
272
    function getQueryString()
273
    {
274
        if (!empty($this->querystring)) {
275
            foreach ($this->querystring as $name => $value) {
276
                if (is_array($value)) {
277
                    foreach ($value as $k => $v) {
278
                        $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
279
                    }
280
                } elseif (!is_null($value)) {
281
                    $querystring[] = $name . '=' . $value;
282
                } else {
283
                    $querystring[] = $name;
284
                }
285
            }
286
            $querystring = implode(ini_get('arg_separator.output'), $querystring);
287
        } else {
288
            $querystring = '';
289
        }
290
 
291
        return $querystring;
292
    }
293
 
294
    /**
295
    * Parses raw querystring and returns an array of it
296
    *
297
    * @param  string  $querystring The querystring to parse
298
    * @return array                An array of the querystring data
299
    * @access private
300
    */
301
    function _parseRawQuerystring($querystring)
302
    {
303
        $parts  = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
304
        $return = array();
305
 
306
        foreach ($parts as $part) {
307
            if (strpos($part, '=') !== false) {
308
                $value = substr($part, strpos($part, '=') + 1);
309
                $key   = substr($part, 0, strpos($part, '='));
310
            } else {
311
                $value = null;
312
                $key   = $part;
313
            }
314
            if (substr($key, -2) == '[]') {
315
                $key = substr($key, 0, -2);
316
                if (@!is_array($return[$key])) {
317
                    $return[$key]   = array();
318
                    $return[$key][] = $value;
319
                } else {
320
                    $return[$key][] = $value;
321
                }
322
            } elseif (!$this->useBrackets AND !empty($return[$key])) {
323
                $return[$key]   = (array)$return[$key];
324
                $return[$key][] = $value;
325
            } else {
326
                $return[$key] = $value;
327
            }
328
        }
329
 
330
        return $return;
331
    }
332
 
333
    /**
334
    * Resolves //, ../ and ./ from a path and returns
335
    * the result. Eg:
336
    *
337
    * /foo/bar/../boo.php    => /foo/boo.php
338
    * /foo/bar/../../boo.php => /boo.php
339
    * /foo/bar/.././/boo.php => /foo/boo.php
340
    *
341
    * This method can also be called statically.
342
    *
343
    * @param  string $url URL path to resolve
344
    * @return string      The result
345
    */
346
    function resolvePath($path)
347
    {
348
        $path = explode('/', str_replace('//', '/', $path));
349
 
350
        for ($i=0; $i<count($path); $i++) {
351
            if ($path[$i] == '.') {
352
                unset($path[$i]);
353
                $path = array_values($path);
354
                $i--;
355
 
356
            } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
357
                unset($path[$i]);
358
                unset($path[$i-1]);
359
                $path = array_values($path);
360
                $i -= 2;
361
 
362
            } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
363
                unset($path[$i]);
364
                $path = array_values($path);
365
                $i--;
366
 
367
            } else {
368
                continue;
369
            }
370
        }
371
 
372
        return implode('/', $path);
373
    }
374
 
375
    /**
376
    * Returns the standard port number for a protocol
377
    *
378
    * @param  string  $scheme The protocol to lookup
379
    * @return integer         Port number or NULL if no scheme matches
380
    *
381
    * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
382
    */
383
    function getStandardPort($scheme)
384
    {
385
        switch (strtolower($scheme)) {
386
            case 'http':    return 80;
387
            case 'https':   return 443;
388
            case 'ftp':     return 21;
389
            case 'imap':    return 143;
390
            case 'imaps':   return 993;
391
            case 'pop3':    return 110;
392
            case 'pop3s':   return 995;
393
            default:        return null;
394
       }
395
    }
396
 
397
    /**
398
    * Forces the URL to a particular protocol
399
    *
400
    * @param string  $protocol Protocol to force the URL to
401
    * @param integer $port     Optional port (standard port is used by default)
402
    */
403
    function setProtocol($protocol, $port = null)
404
    {
405
        $this->protocol = $protocol;
406
        $this->port = is_null($port) ? $this->getStandardPort() : $port;
407
    }
408
 
409
}
410
?>