home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Net / URL2.php < prev   
Encoding:
PHP Script  |  2008-07-02  |  22.8 KB  |  814 lines

  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: URL2.php,v 1.10 2008/04/26 21:57:08 schmidt Exp $
  36. //
  37. // Net_URL2 Class (PHP5 Only)
  38.  
  39. // This code is released under the BSD License - http://www.opensource.org/licenses/bsd-license.php
  40. /**
  41.  * @license BSD License
  42.  */
  43. class Net_URL2
  44. {
  45.     /**
  46.      * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default
  47.      * is true.
  48.      */
  49.     const OPTION_STRICT           = 'strict';
  50.  
  51.     /**
  52.      * Represent arrays in query using PHP's [] notation. Default is true.
  53.      */
  54.     const OPTION_USE_BRACKETS     = 'use_brackets';
  55.  
  56.     /**
  57.      * URL-encode query variable keys. Default is true.
  58.      */
  59.     const OPTION_ENCODE_KEYS      = 'encode_keys';
  60.  
  61.     /**
  62.      * Query variable separators when parsing the query string. Every character
  63.      * is considered a separator. Default is specified by the
  64.      * arg_separator.input php.ini setting (this defaults to "&").
  65.      */
  66.     const OPTION_SEPARATOR_INPUT  = 'input_separator';
  67.  
  68.     /**
  69.      * Query variable separator used when generating the query string. Default
  70.      * is specified by the arg_separator.output php.ini setting (this defaults
  71.      * to "&").
  72.      */
  73.     const OPTION_SEPARATOR_OUTPUT = 'output_separator';
  74.  
  75.     /**
  76.      * Default options corresponds to how PHP handles $_GET.
  77.      */
  78.     private $options = array(
  79.         self::OPTION_STRICT           => true,
  80.         self::OPTION_USE_BRACKETS     => true,
  81.         self::OPTION_ENCODE_KEYS      => true,
  82.         self::OPTION_SEPARATOR_INPUT  => 'x&',
  83.         self::OPTION_SEPARATOR_OUTPUT => 'x&',
  84.         );
  85.  
  86.     /**
  87.      * @var  string|bool
  88.      */
  89.     private $scheme = false;
  90.  
  91.     /**
  92.      * @var  string|bool
  93.      */
  94.     private $userinfo = false;
  95.  
  96.     /**
  97.      * @var  string|bool
  98.      */
  99.     private $host = false;
  100.  
  101.     /**
  102.      * @var  int|bool
  103.      */
  104.     private $port = false;
  105.  
  106.     /**
  107.      * @var  string
  108.      */
  109.     private $path = '';
  110.  
  111.     /**
  112.      * @var  string|bool
  113.      */
  114.     private $query = false;
  115.  
  116.     /**
  117.      * @var  string|bool
  118.      */
  119.     private $fragment = false;
  120.  
  121.     /**
  122.      * @param string $url     an absolute or relative URL
  123.      * @param array  $options
  124.      */
  125.     public function __construct($url, $options = null)
  126.     {
  127.         $this->setOption(self::OPTION_SEPARATOR_INPUT,
  128.                          ini_get('arg_separator.input'));
  129.         $this->setOption(self::OPTION_SEPARATOR_OUTPUT,
  130.                          ini_get('arg_separator.output'));
  131.         if (is_array($options)) {
  132.             foreach ($options as $optionName => $value) {
  133.                 $this->setOption($optionName);
  134.             }
  135.         }
  136.  
  137.         if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
  138.             $this->scheme = $reg[1];
  139.             $url = substr($url, strlen($reg[0]));
  140.         }
  141.  
  142.         if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
  143.             $this->setAuthority($reg[1]);
  144.             $url = substr($url, strlen($reg[0]));
  145.         }
  146.  
  147.         $i = strcspn($url, '?#');
  148.         $this->path = substr($url, 0, $i);
  149.         $url = substr($url, $i);
  150.  
  151.         if (preg_match('@^\?([^#]*)@', $url, $reg)) {
  152.             $this->query = $reg[1];
  153.             $url = substr($url, strlen($reg[0]));
  154.         }
  155.  
  156.         if ($url) {
  157.             $this->fragment = substr($url, 1);
  158.         }
  159.     }
  160.  
  161.     /**
  162.      * Returns the scheme, e.g. "http" or "urn", or false if there is no
  163.      * scheme specified, i.e. if this is a relative URL.
  164.      *
  165.      * @return  string|bool
  166.      */
  167.     public function getScheme()
  168.     {
  169.         return $this->scheme;
  170.     }
  171.  
  172.     /**
  173.      * @param string|bool $scheme
  174.      *
  175.      * @return void
  176.      * @see    getScheme()
  177.      */
  178.     public function setScheme($scheme)
  179.     {
  180.         $this->scheme = $scheme;
  181.     }
  182.  
  183.     /**
  184.      * Returns the user part of the userinfo part (the part preceding the first
  185.      *  ":"), or false if there is no userinfo part.
  186.      *
  187.      * @return  string|bool
  188.      */
  189.     public function getUser()
  190.     {
  191.         return $this->userinfo !== false ? preg_replace('@:.*$@', '', $this->userinfo) : false;
  192.     }
  193.  
  194.     /**
  195.      * Returns the password part of the userinfo part (the part after the first
  196.      *  ":"), or false if there is no userinfo part (i.e. the URL does not
  197.      * contain "@" in front of the hostname) or the userinfo part does not
  198.      * contain ":".
  199.      *
  200.      * @return  string|bool
  201.      */
  202.     public function getPassword()
  203.     {
  204.         return $this->userinfo !== false ? substr(strstr($this->userinfo, ':'), 1) : false;
  205.     }
  206.  
  207.     /**
  208.      * Returns the userinfo part, or false if there is none, i.e. if the
  209.      * authority part does not contain "@".
  210.      *
  211.      * @return  string|bool
  212.      */
  213.     public function getUserinfo()
  214.     {
  215.         return $this->userinfo;
  216.     }
  217.  
  218.     /**
  219.      * Sets the userinfo part. If two arguments are passed, they are combined
  220.      * in the userinfo part as username ":" password.
  221.      *
  222.      * @param string|bool $userinfo userinfo or username
  223.      * @param string|bool $password
  224.      *
  225.      * @return void
  226.      */
  227.     public function setUserinfo($userinfo, $password = false)
  228.     {
  229.         $this->userinfo = $userinfo;
  230.         if ($password !== false) {
  231.             $this->userinfo .= ':' . $password;
  232.         }
  233.     }
  234.  
  235.     /**
  236.      * Returns the host part, or false if there is no authority part, e.g.
  237.      * relative URLs.
  238.      *
  239.      * @return  string|bool
  240.      */
  241.     public function getHost()
  242.     {
  243.         return $this->host;
  244.     }
  245.  
  246.     /**
  247.      * @param string|bool $host
  248.      *
  249.      * @return void
  250.      */
  251.     public function setHost($host)
  252.     {
  253.         $this->host = $host;
  254.     }
  255.  
  256.     /**
  257.      * Returns the port number, or false if there is no port number specified,
  258.      * i.e. if the default port is to be used.
  259.      *
  260.      * @return  int|bool
  261.      */
  262.     public function getPort()
  263.     {
  264.         return $this->port;
  265.     }
  266.  
  267.     /**
  268.      * @param int|bool $port
  269.      *
  270.      * @return void
  271.      */
  272.     public function setPort($port)
  273.     {
  274.         $this->port = intval($port);
  275.     }
  276.  
  277.     /**
  278.      * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or
  279.      * false if there is no authority none.
  280.      *
  281.      * @return string|bool
  282.      */
  283.     public function getAuthority()
  284.     {
  285.         if (!$this->host) {
  286.             return false;
  287.         }
  288.  
  289.         $authority = '';
  290.  
  291.         if ($this->userinfo !== false) {
  292.             $authority .= $this->userinfo . '@';
  293.         }
  294.  
  295.         $authority .= $this->host;
  296.  
  297.         if ($this->port !== false) {
  298.             $authority .= ':' . $this->port;
  299.         }
  300.  
  301.         return $authority;
  302.     }
  303.  
  304.     /**
  305.      * @param string|false $authority
  306.      *
  307.      * @return void
  308.      */
  309.     public function setAuthority($authority)
  310.     {
  311.         $this->user = false;
  312.         $this->pass = false;
  313.         $this->host = false;
  314.         $this->port = false;
  315.         if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) {
  316.             if ($reg[1]) {
  317.                 $this->userinfo = $reg[2];
  318.             }
  319.  
  320.             $this->host = $reg[3];
  321.             if (isset($reg[5])) {
  322.                 $this->port = intval($reg[5]);
  323.             }
  324.         }
  325.     }
  326.  
  327.     /**
  328.      * Returns the path part (possibly an empty string).
  329.      *
  330.      * @return string
  331.      */
  332.     public function getPath()
  333.     {
  334.         return $this->path;
  335.     }
  336.  
  337.     /**
  338.      * @param string $path
  339.      *
  340.      * @return void
  341.      */
  342.     public function setPath($path)
  343.     {
  344.         $this->path = $path;
  345.     }
  346.  
  347.     /**
  348.      * Returns the query string (excluding the leading "?"), or false if "?"
  349.      * isn't present in the URL.
  350.      *
  351.      * @return  string|bool
  352.      * @see     self::getQueryVariables()
  353.      */
  354.     public function getQuery()
  355.     {
  356.         return $this->query;
  357.     }
  358.  
  359.     /**
  360.      * @param string|bool $query
  361.      *
  362.      * @return void
  363.      * @see   self::setQueryVariables()
  364.      */
  365.     public function setQuery($query)
  366.     {
  367.         $this->query = $query;
  368.     }
  369.  
  370.     /**
  371.      * Returns the fragment name, or false if "#" isn't present in the URL.
  372.      *
  373.      * @return  string|bool
  374.      */
  375.     public function getFragment()
  376.     {
  377.         return $this->fragment;
  378.     }
  379.  
  380.     /**
  381.      * @param string|bool $fragment
  382.      *
  383.      * @return void
  384.      */
  385.     public function setFragment($fragment)
  386.     {
  387.         $this->fragment = $fragment;
  388.     }
  389.  
  390.     /**
  391.      * Returns the query string like an array as the variables would appear in
  392.      * $_GET in a PHP script.
  393.      *
  394.      * @return  array
  395.      */
  396.     public function getQueryVariables()
  397.     {
  398.         $pattern = '/[' .
  399.                    preg_quote($this->getOption(self::OPTION_SEPARATOR_INPUT), '/') .
  400.                    ']/';
  401.         $parts   = preg_split($pattern, $this->query, -1, PREG_SPLIT_NO_EMPTY);
  402.         $return  = array();
  403.  
  404.         foreach ($parts as $part) {
  405.             if (strpos($part, '=') !== false) {
  406.                 list($key, $value) = explode('=', $part, 2);
  407.             } else {
  408.                 $key   = $part;
  409.                 $value = null;
  410.             }
  411.  
  412.             if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
  413.                 $key = rawurldecode($key);
  414.             }
  415.             $value = rawurldecode($value);
  416.  
  417.             if ($this->getOption(self::OPTION_USE_BRACKETS) &&
  418.                 preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
  419.  
  420.                 $key = $matches[1];
  421.                 $idx = $matches[2];
  422.  
  423.                 // Ensure is an array
  424.                 if (empty($return[$key]) || !is_array($return[$key])) {
  425.                     $return[$key] = array();
  426.                 }
  427.  
  428.                 // Add data
  429.                 if ($idx === '') {
  430.                     $return[$key][] = $value;
  431.                 } else {
  432.                     $return[$key][$idx] = $value;
  433.                 }
  434.             } elseif (!$this->getOption(self::OPTION_USE_BRACKETS)
  435.                       && !empty($return[$key])
  436.             ) {
  437.                 $return[$key]   = (array) $return[$key];
  438.                 $return[$key][] = $value;
  439.             } else {
  440.                 $return[$key] = $value;
  441.             }
  442.         }
  443.  
  444.         return $return;
  445.     }
  446.  
  447.     /**
  448.      * @param array $array (name => value) array
  449.      *
  450.      * @return void
  451.      */
  452.     public function setQueryVariables(array $array)
  453.     {
  454.         if (!$array) {
  455.             $this->query = false;
  456.         } else {
  457.             foreach ($array as $name => $value) {
  458.                 if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
  459.                     $name = rawurlencode($name);
  460.                 }
  461.  
  462.                 if (is_array($value)) {
  463.                     foreach ($value as $k => $v) {
  464.                         $parts[] = $this->getOption(self::OPTION_USE_BRACKETS)
  465.                             ? sprintf('%s[%s]=%s', $name, $k, $v)
  466.                             : ($name . '=' . $v);
  467.                     }
  468.                 } elseif (!is_null($value)) {
  469.                     $parts[] = $name . '=' . $value;
  470.                 } else {
  471.                     $parts[] = $name;
  472.                 }
  473.             }
  474.             $this->query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT),
  475.                                    $parts);
  476.         }
  477.     }
  478.  
  479.     /**
  480.      * @param string $name
  481.      * @param mixed  $value
  482.      *
  483.      * @return  array
  484.      */
  485.     public function setQueryVariable($name, $value)
  486.     {
  487.         $array = $this->getQueryVariables();
  488.         $array[$name] = $value;
  489.         $this->setQueryVariables($array);
  490.     }
  491.  
  492.     /**
  493.      * @param string $name
  494.      *
  495.      * @return void
  496.      */
  497.     public function unsetQueryVariable($name)
  498.     {
  499.         $array = $this->getQueryVariables();
  500.         unset($array[$name]);
  501.         $this->setQueryVariables($array);
  502.     }
  503.  
  504.     /**
  505.      * Returns a string representation of this URL.
  506.      *
  507.      * @return  string
  508.      */
  509.     public function getURL()
  510.     {
  511.         // See RFC 3986, section 5.3
  512.         $url = "";
  513.  
  514.         if ($this->scheme !== false) {
  515.             $url .= $this->scheme . ':';
  516.         }
  517.  
  518.         $authority = $this->getAuthority();
  519.         if ($authority !== false) {
  520.             $url .= '//' . $authority;
  521.         }
  522.         $url .= $this->path;
  523.  
  524.         if ($this->query !== false) {
  525.             $url .= '?' . $this->query;
  526.         }
  527.  
  528.         if ($this->fragment !== false) {
  529.             $url .= '#' . $this->fragment;
  530.         }
  531.     
  532.         return $url;
  533.     }
  534.  
  535.     /** 
  536.      * Returns a normalized string representation of this URL. This is useful
  537.      * for comparison of URLs.
  538.      *
  539.      * @return  string
  540.      */
  541.     public function getNormalizedURL()
  542.     {
  543.         $url = clone $this;
  544.         $url->normalize();
  545.         return $url->getUrl();
  546.     }
  547.  
  548.     /** 
  549.      * Returns a normalized Net_URL2 instance.
  550.      *
  551.      * @return  Net_URL2
  552.      */
  553.     public function normalize()
  554.     {
  555.         // See RFC 3886, section 6
  556.  
  557.         // Schemes are case-insensitive
  558.         if ($this->scheme) {
  559.             $this->scheme = strtolower($this->scheme);
  560.         }
  561.  
  562.         // Hostnames are case-insensitive
  563.         if ($this->host) {
  564.             $this->host = strtolower($this->host);
  565.         }
  566.  
  567.         // Remove default port number for known schemes (RFC 3986, section 6.2.3)
  568.         if ($this->port &&
  569.             $this->scheme &&
  570.             $this->port == getservbyname($this->scheme, 'tcp')) {
  571.  
  572.             $this->port = false;
  573.         }
  574.  
  575.         // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1)
  576.         foreach (array('userinfo', 'host', 'path') as $part) {
  577.             if ($this->$part) {
  578.                 $this->$part  = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$part);
  579.             }
  580.         }
  581.  
  582.         // Path segment normalization (RFC 3986, section 6.2.2.3)
  583.         $this->path = self::removeDotSegments($this->path);
  584.  
  585.         // Scheme based normalization (RFC 3986, section 6.2.3)
  586.         if ($this->host && !$this->path) {
  587.             $this->path = '/';
  588.         }
  589.     }
  590.  
  591.     /**
  592.      * Returns whether this instance represents an absolute URL.
  593.      *
  594.      * @return  bool
  595.      */
  596.     public function isAbsolute()
  597.     {
  598.         return (bool) $this->scheme;
  599.     }
  600.  
  601.     /**
  602.      * Returns an Net_URL2 instance representing an absolute URL relative to
  603.      * this URL.
  604.      *
  605.      * @param Net_URL2|string $reference relative URL
  606.      *
  607.      * @return Net_URL2
  608.      */
  609.     public function resolve($reference)
  610.     {
  611.         if (is_string($reference)) {
  612.             $reference = new self($reference);
  613.         }
  614.         if (!$this->isAbsolute()) {
  615.             throw new Exception('Base-URL must be absolute');
  616.         }
  617.  
  618.         // A non-strict parser may ignore a scheme in the reference if it is
  619.         // identical to the base URI's scheme.
  620.         if (!$this->getOption(self::OPTION_STRICT) && $reference->scheme == $this->scheme) {
  621.             $reference->scheme = false;
  622.         }
  623.  
  624.         $target = new self('');
  625.         if ($reference->scheme !== false) {
  626.             $target->scheme = $reference->scheme;
  627.             $target->setAuthority($reference->getAuthority());
  628.             $target->path  = self::removeDotSegments($reference->path);
  629.             $target->query = $reference->query;
  630.         } else {
  631.             $authority = $reference->getAuthority();
  632.             if ($authority !== false) {
  633.                 $target->setAuthority($authority);
  634.                 $target->path  = self::removeDotSegments($reference->path);
  635.                 $target->query = $reference->query;
  636.             } else {
  637.                 if ($reference->path == '') {
  638.                     $target->path = $this->path;
  639.                     if ($reference->query !== false) {
  640.                         $target->query = $reference->query;
  641.                     } else {
  642.                         $target->query = $this->query;
  643.                     }
  644.                 } else {
  645.                     if (substr($reference->path, 0, 1) == '/') {
  646.                         $target->path = self::removeDotSegments($reference->path);
  647.                     } else {
  648.                         // Merge paths (RFC 3986, section 5.2.3)
  649.                         if ($this->host !== false && $this->path == '') {
  650.                             $target->path = '/' . $this->path;
  651.                         } else {
  652.                             $i = strrpos($this->path, '/');
  653.                             if ($i !== false) {
  654.                                 $target->path = substr($this->path, 0, $i + 1);
  655.                             }
  656.                             $target->path .= $reference->path;
  657.                         }
  658.                         $target->path = self::removeDotSegments($target->path);
  659.                     }
  660.                     $target->query = $reference->query;
  661.                 }
  662.                 $target->setAuthority($this->getAuthority());
  663.             }
  664.             $target->scheme = $this->scheme;
  665.         }
  666.  
  667.         $target->fragment = $reference->fragment;
  668.  
  669.         return $target;
  670.     }
  671.  
  672.     /**
  673.      * Removes dots as described in RFC 3986, section 5.2.4, e.g.
  674.      * "/foo/../bar/baz" => "/bar/baz"
  675.      *
  676.      * @param string $path a path
  677.      *
  678.      * @return string a path
  679.      */
  680.     private static function removeDotSegments($path)
  681.     {
  682.         $output = '';
  683.  
  684.         // Make sure not to be trapped in an infinite loop due to a bug in this
  685.         // method
  686.         $j = 0; 
  687.         while ($path && $j++ < 100) {
  688.             // Step A
  689.             if (substr($path, 0, 2) == './') {
  690.                 $path = substr($path, 2);
  691.             } elseif (substr($path, 0, 3) == '../') {
  692.                 $path = substr($path, 3);
  693.  
  694.             // Step B
  695.             } elseif (substr($path, 0, 3) == '/./' || $path == '/.') {
  696.                 $path = '/' . substr($path, 3);
  697.  
  698.             // Step C
  699.             } elseif (substr($path, 0, 4) == '/../' || $path == '/..') {
  700.                 $path = '/' . substr($path, 4);
  701.                 $i = strrpos($output, '/');
  702.                 $output = $i === false ? '' : substr($output, 0, $i);
  703.  
  704.             // Step D
  705.             } elseif ($path == '.' || $path == '..') {
  706.                 $path = '';
  707.  
  708.             // Step E
  709.             } else {
  710.                 $i = strpos($path, '/');
  711.                 if ($i === 0) {
  712.                     $i = strpos($path, '/', 1);
  713.                 }
  714.                 if ($i === false) {
  715.                     $i = strlen($path);
  716.                 }
  717.                 $output .= substr($path, 0, $i);
  718.                 $path = substr($path, $i);
  719.             }
  720.         }
  721.  
  722.         return $output;
  723.     }
  724.  
  725.     /**
  726.      * Returns a Net_URL2 instance representing the canonical URL of the
  727.      * currently executing PHP script.
  728.      * 
  729.      * @return  string
  730.      */
  731.     public static function getCanonical()
  732.     {
  733.         if (!isset($_SERVER['REQUEST_METHOD'])) {
  734.             // ALERT - no current URL
  735.             throw new Exception('Script was not called through a webserver');
  736.         }
  737.  
  738.         // Begin with a relative URL
  739.         $url = new self($_SERVER['PHP_SELF']);
  740.         $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
  741.         $url->host = $_SERVER['SERVER_NAME'];
  742.         $port = intval($_SERVER['SERVER_PORT']);
  743.         if ($url->scheme == 'http' && $port != 80 ||
  744.             $url->scheme == 'https' && $port != 443) {
  745.  
  746.             $url->port = $port;
  747.         }
  748.         return $url;
  749.     }
  750.  
  751.     /**
  752.      * Returns the URL used to retrieve the current request.
  753.      *
  754.      * @return  string
  755.      */
  756.     public static function getRequestedURL()
  757.     {
  758.         return self::getRequested()->getUrl();
  759.     }
  760.  
  761.     /**
  762.      * Returns a Net_URL2 instance representing the URL used to retrieve the
  763.      * current request.
  764.      *
  765.      * @return  Net_URL2
  766.      */
  767.     public static function getRequested()
  768.     {
  769.         if (!isset($_SERVER['REQUEST_METHOD'])) {
  770.             // ALERT - no current URL
  771.             throw new Exception('Script was not called through a webserver');
  772.         }
  773.  
  774.         // Begin with a relative URL
  775.         $url = new self($_SERVER['REQUEST_URI']);
  776.         $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
  777.         // Set host and possibly port
  778.         $url->setAuthority($_SERVER['HTTP_HOST']);
  779.         return $url;
  780.     }
  781.  
  782.     /**
  783.      * Sets the specified option.
  784.      *
  785.      * @param string $optionName a self::OPTION_ constant
  786.      * @param mixed  $value      option value  
  787.      *
  788.      * @return void
  789.      * @see  self::OPTION_STRICT
  790.      * @see  self::OPTION_USE_BRACKETS
  791.      * @see  self::OPTION_ENCODE_KEYS
  792.      */
  793.     function setOption($optionName, $value)
  794.     {
  795.         if (!array_key_exists($optionName, $this->options)) {
  796.             return false;
  797.         }
  798.         $this->options[$optionName] = $value;
  799.     }
  800.  
  801.     /**
  802.      * Returns the value of the specified option.
  803.      *
  804.      * @param string $optionName The name of the option to retrieve
  805.      *
  806.      * @return  mixed
  807.      */
  808.     function getOption($optionName)
  809.     {
  810.         return isset($this->options[$optionName])
  811.             ? $this->options[$optionName] : false;
  812.     }
  813. }
  814.