PageRenderTime 145ms CodeModel.GetById 69ms app.highlight 16ms RepoModel.GetById 55ms app.codeStats 0ms

/lib/PEAR/Net/URL.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 485 lines | 233 code | 56 blank | 196 comment | 44 complexity | e7042d4176244ed99fe4b9c8e8cc6fb5 MD5 | raw file
  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
 40class 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?>