web/lib/Zend/Uri/Http.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category  Zend
       
    16  * @package   Zend_Uri
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license   http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version   $Id: Http.php 23409 2010-11-19 19:55:25Z bittarman $
       
    20  */
       
    21 
       
    22 /**
       
    23  * @see Zend_Uri
       
    24  */
       
    25 require_once 'Zend/Uri.php';
       
    26 
       
    27 /**
       
    28  * @see Zend_Validate_Hostname
       
    29  */
       
    30 require_once 'Zend/Validate/Hostname.php';
       
    31 
       
    32 /**
       
    33  * HTTP(S) URI handler
       
    34  *
       
    35  * @category  Zend
       
    36  * @package   Zend_Uri
       
    37  * @uses      Zend_Uri
       
    38  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    39  * @license   http://framework.zend.com/license/new-bsd     New BSD License
       
    40  */
       
    41 class Zend_Uri_Http extends Zend_Uri
       
    42 {
       
    43     /**
       
    44      * Character classes for validation regular expressions
       
    45      */
       
    46     const CHAR_ALNUM    = 'A-Za-z0-9';
       
    47     const CHAR_MARK     = '-_.!~*\'()\[\]';
       
    48     const CHAR_RESERVED = ';\/?:@&=+$,';
       
    49     const CHAR_SEGMENT  = ':@&=+$,;';
       
    50     const CHAR_UNWISE   = '{}|\\\\^`';
       
    51 
       
    52     /**
       
    53      * HTTP username
       
    54      *
       
    55      * @var string
       
    56      */
       
    57     protected $_username = '';
       
    58 
       
    59     /**
       
    60      * HTTP password
       
    61      *
       
    62      * @var string
       
    63      */
       
    64     protected $_password = '';
       
    65 
       
    66     /**
       
    67      * HTTP host
       
    68      *
       
    69      * @var string
       
    70      */
       
    71     protected $_host = '';
       
    72 
       
    73     /**
       
    74      * HTTP post
       
    75      *
       
    76      * @var string
       
    77      */
       
    78     protected $_port = '';
       
    79 
       
    80     /**
       
    81      * HTTP part
       
    82      *
       
    83      * @var string
       
    84      */
       
    85     protected $_path = '';
       
    86 
       
    87     /**
       
    88      * HTTP query
       
    89      *
       
    90      * @var string
       
    91      */
       
    92     protected $_query = '';
       
    93 
       
    94     /**
       
    95      * HTTP fragment
       
    96      *
       
    97      * @var string
       
    98      */
       
    99     protected $_fragment = '';
       
   100 
       
   101     /**
       
   102      * Regular expression grammar rules for validation; values added by constructor
       
   103      *
       
   104      * @var array
       
   105      */
       
   106     protected $_regex = array();
       
   107 
       
   108     /**
       
   109      * Constructor accepts a string $scheme (e.g., http, https) and a scheme-specific part of the URI
       
   110      * (e.g., example.com/path/to/resource?query=param#fragment)
       
   111      *
       
   112      * @param  string $scheme         The scheme of the URI
       
   113      * @param  string $schemeSpecific The scheme-specific part of the URI
       
   114      * @throws Zend_Uri_Exception When the URI is not valid
       
   115      */
       
   116     protected function __construct($scheme, $schemeSpecific = '')
       
   117     {
       
   118         // Set the scheme
       
   119         $this->_scheme = $scheme;
       
   120 
       
   121         // Set up grammar rules for validation via regular expressions. These
       
   122         // are to be used with slash-delimited regular expression strings.
       
   123 
       
   124         // Escaped special characters (eg. '%25' for '%')
       
   125         $this->_regex['escaped']    = '%[[:xdigit:]]{2}';
       
   126 
       
   127         // Unreserved characters
       
   128         $this->_regex['unreserved'] = '[' . self::CHAR_ALNUM . self::CHAR_MARK . ']';
       
   129 
       
   130         // Segment can use escaped, unreserved or a set of additional chars
       
   131         $this->_regex['segment']    = '(?:' . $this->_regex['escaped'] . '|[' .
       
   132             self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_SEGMENT . '])*';
       
   133 
       
   134         // Path can be a series of segmets char strings seperated by '/'
       
   135         $this->_regex['path']       = '(?:\/(?:' . $this->_regex['segment'] . ')?)+';
       
   136 
       
   137         // URI characters can be escaped, alphanumeric, mark or reserved chars
       
   138         $this->_regex['uric']       = '(?:' . $this->_regex['escaped'] . '|[' .
       
   139             self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_RESERVED .
       
   140 
       
   141         // If unwise chars are allowed, add them to the URI chars class
       
   142             (self::$_config['allow_unwise'] ? self::CHAR_UNWISE : '') . '])';
       
   143 
       
   144         // If no scheme-specific part was supplied, the user intends to create
       
   145         // a new URI with this object.  No further parsing is required.
       
   146         if (strlen($schemeSpecific) === 0) {
       
   147             return;
       
   148         }
       
   149 
       
   150         // Parse the scheme-specific URI parts into the instance variables.
       
   151         $this->_parseUri($schemeSpecific);
       
   152 
       
   153         // Validate the URI
       
   154         if ($this->valid() === false) {
       
   155             require_once 'Zend/Uri/Exception.php';
       
   156             throw new Zend_Uri_Exception('Invalid URI supplied');
       
   157         }
       
   158     }
       
   159 
       
   160     /**
       
   161      * Creates a Zend_Uri_Http from the given string
       
   162      *
       
   163      * @param  string $uri String to create URI from, must start with
       
   164      *                     'http://' or 'https://'
       
   165      * @throws InvalidArgumentException  When the given $uri is not a string or
       
   166      *                                   does not start with http:// or https://
       
   167      * @throws Zend_Uri_Exception        When the given $uri is invalid
       
   168      * @return Zend_Uri_Http
       
   169      */
       
   170     public static function fromString($uri)
       
   171     {
       
   172         if (is_string($uri) === false) {
       
   173             require_once 'Zend/Uri/Exception.php';
       
   174             throw new Zend_Uri_Exception('$uri is not a string');
       
   175         }
       
   176 
       
   177         $uri            = explode(':', $uri, 2);
       
   178         $scheme         = strtolower($uri[0]);
       
   179         $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
       
   180 
       
   181         if (in_array($scheme, array('http', 'https')) === false) {
       
   182             require_once 'Zend/Uri/Exception.php';
       
   183             throw new Zend_Uri_Exception("Invalid scheme: '$scheme'");
       
   184         }
       
   185 
       
   186         $schemeHandler = new Zend_Uri_Http($scheme, $schemeSpecific);
       
   187         return $schemeHandler;
       
   188     }
       
   189 
       
   190     /**
       
   191      * Parse the scheme-specific portion of the URI and place its parts into instance variables.
       
   192      *
       
   193      * @param  string $schemeSpecific The scheme-specific portion to parse
       
   194      * @throws Zend_Uri_Exception When scheme-specific decoposition fails
       
   195      * @throws Zend_Uri_Exception When authority decomposition fails
       
   196      * @return void
       
   197      */
       
   198     protected function _parseUri($schemeSpecific)
       
   199     {
       
   200         // High-level decomposition parser
       
   201         $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
       
   202         $status  = @preg_match($pattern, $schemeSpecific, $matches);
       
   203         if ($status === false) {
       
   204             require_once 'Zend/Uri/Exception.php';
       
   205             throw new Zend_Uri_Exception('Internal error: scheme-specific decomposition failed');
       
   206         }
       
   207 
       
   208         // Failed decomposition; no further processing needed
       
   209         if ($status === false) {
       
   210             return;
       
   211         }
       
   212 
       
   213         // Save URI components that need no further decomposition
       
   214         $this->_path     = isset($matches[4]) === true ? $matches[4] : '';
       
   215         $this->_query    = isset($matches[6]) === true ? $matches[6] : '';
       
   216         $this->_fragment = isset($matches[8]) === true ? $matches[8] : '';
       
   217 
       
   218         // Additional decomposition to get username, password, host, and port
       
   219         $combo   = isset($matches[3]) === true ? $matches[3] : '';
       
   220         $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
       
   221         $status  = @preg_match($pattern, $combo, $matches);
       
   222         if ($status === false) {
       
   223             require_once 'Zend/Uri/Exception.php';
       
   224             throw new Zend_Uri_Exception('Internal error: authority decomposition failed');
       
   225         }
       
   226 
       
   227         // Failed decomposition; no further processing needed
       
   228         if ($status === false) {
       
   229             return;
       
   230         }
       
   231 
       
   232         // Save remaining URI components
       
   233         $this->_username = isset($matches[2]) === true ? $matches[2] : '';
       
   234         $this->_password = isset($matches[4]) === true ? $matches[4] : '';
       
   235         $this->_host     = isset($matches[5]) === true ? $matches[5] : '';
       
   236         $this->_port     = isset($matches[7]) === true ? $matches[7] : '';
       
   237 
       
   238     }
       
   239 
       
   240     /**
       
   241      * Returns a URI based on current values of the instance variables. If any
       
   242      * part of the URI does not pass validation, then an exception is thrown.
       
   243      *
       
   244      * @throws Zend_Uri_Exception When one or more parts of the URI are invalid
       
   245      * @return string
       
   246      */
       
   247     public function getUri()
       
   248     {
       
   249         if ($this->valid() === false) {
       
   250             require_once 'Zend/Uri/Exception.php';
       
   251             throw new Zend_Uri_Exception('One or more parts of the URI are invalid');
       
   252         }
       
   253 
       
   254         $password = strlen($this->_password) > 0 ? ":$this->_password" : '';
       
   255         $auth     = strlen($this->_username) > 0 ? "$this->_username$password@" : '';
       
   256         $port     = strlen($this->_port) > 0 ? ":$this->_port" : '';
       
   257         $query    = strlen($this->_query) > 0 ? "?$this->_query" : '';
       
   258         $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : '';
       
   259 
       
   260         return $this->_scheme
       
   261              . '://'
       
   262              . $auth
       
   263              . $this->_host
       
   264              . $port
       
   265              . $this->_path
       
   266              . $query
       
   267              . $fragment;
       
   268     }
       
   269 
       
   270     /**
       
   271      * Validate the current URI from the instance variables. Returns true if and only if all
       
   272      * parts pass validation.
       
   273      *
       
   274      * @return boolean
       
   275      */
       
   276     public function valid()
       
   277     {
       
   278         // Return true if and only if all parts of the URI have passed validation
       
   279         return $this->validateUsername()
       
   280            and $this->validatePassword()
       
   281            and $this->validateHost()
       
   282            and $this->validatePort()
       
   283            and $this->validatePath()
       
   284            and $this->validateQuery()
       
   285            and $this->validateFragment();
       
   286     }
       
   287 
       
   288     /**
       
   289      * Returns the username portion of the URL, or FALSE if none.
       
   290      *
       
   291      * @return string
       
   292      */
       
   293     public function getUsername()
       
   294     {
       
   295         return strlen($this->_username) > 0 ? $this->_username : false;
       
   296     }
       
   297 
       
   298     /**
       
   299      * Returns true if and only if the username passes validation. If no username is passed,
       
   300      * then the username contained in the instance variable is used.
       
   301      *
       
   302      * @param  string $username The HTTP username
       
   303      * @throws Zend_Uri_Exception When username validation fails
       
   304      * @return boolean
       
   305      * @link   http://www.faqs.org/rfcs/rfc2396.html
       
   306      */
       
   307     public function validateUsername($username = null)
       
   308     {
       
   309         if ($username === null) {
       
   310             $username = $this->_username;
       
   311         }
       
   312 
       
   313         // If the username is empty, then it is considered valid
       
   314         if (strlen($username) === 0) {
       
   315             return true;
       
   316         }
       
   317 
       
   318         // Check the username against the allowed values
       
   319         $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
       
   320             self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username);
       
   321 
       
   322         if ($status === false) {
       
   323             require_once 'Zend/Uri/Exception.php';
       
   324             throw new Zend_Uri_Exception('Internal error: username validation failed');
       
   325         }
       
   326 
       
   327         return $status === 1;
       
   328     }
       
   329 
       
   330     /**
       
   331      * Sets the username for the current URI, and returns the old username
       
   332      *
       
   333      * @param  string $username The HTTP username
       
   334      * @throws Zend_Uri_Exception When $username is not a valid HTTP username
       
   335      * @return string
       
   336      */
       
   337     public function setUsername($username)
       
   338     {
       
   339         if ($this->validateUsername($username) === false) {
       
   340             require_once 'Zend/Uri/Exception.php';
       
   341             throw new Zend_Uri_Exception("Username \"$username\" is not a valid HTTP username");
       
   342         }
       
   343 
       
   344         $oldUsername     = $this->_username;
       
   345         $this->_username = $username;
       
   346 
       
   347         return $oldUsername;
       
   348     }
       
   349 
       
   350     /**
       
   351      * Returns the password portion of the URL, or FALSE if none.
       
   352      *
       
   353      * @return string
       
   354      */
       
   355     public function getPassword()
       
   356     {
       
   357         return strlen($this->_password) > 0 ? $this->_password : false;
       
   358     }
       
   359 
       
   360     /**
       
   361      * Returns true if and only if the password passes validation. If no password is passed,
       
   362      * then the password contained in the instance variable is used.
       
   363      *
       
   364      * @param  string $password The HTTP password
       
   365      * @throws Zend_Uri_Exception When password validation fails
       
   366      * @return boolean
       
   367      * @link   http://www.faqs.org/rfcs/rfc2396.html
       
   368      */
       
   369     public function validatePassword($password = null)
       
   370     {
       
   371         if ($password === null) {
       
   372             $password = $this->_password;
       
   373         }
       
   374 
       
   375         // If the password is empty, then it is considered valid
       
   376         if (strlen($password) === 0) {
       
   377             return true;
       
   378         }
       
   379 
       
   380         // If the password is nonempty, but there is no username, then it is considered invalid
       
   381         if (strlen($password) > 0 and strlen($this->_username) === 0) {
       
   382             return false;
       
   383         }
       
   384 
       
   385         // Check the password against the allowed values
       
   386         $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
       
   387             self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password);
       
   388 
       
   389         if ($status === false) {
       
   390             require_once 'Zend/Uri/Exception.php';
       
   391             throw new Zend_Uri_Exception('Internal error: password validation failed.');
       
   392         }
       
   393 
       
   394         return $status == 1;
       
   395     }
       
   396 
       
   397     /**
       
   398      * Sets the password for the current URI, and returns the old password
       
   399      *
       
   400      * @param  string $password The HTTP password
       
   401      * @throws Zend_Uri_Exception When $password is not a valid HTTP password
       
   402      * @return string
       
   403      */
       
   404     public function setPassword($password)
       
   405     {
       
   406         if ($this->validatePassword($password) === false) {
       
   407             require_once 'Zend/Uri/Exception.php';
       
   408             throw new Zend_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
       
   409         }
       
   410 
       
   411         $oldPassword     = $this->_password;
       
   412         $this->_password = $password;
       
   413 
       
   414         return $oldPassword;
       
   415     }
       
   416 
       
   417     /**
       
   418      * Returns the domain or host IP portion of the URL, or FALSE if none.
       
   419      *
       
   420      * @return string
       
   421      */
       
   422     public function getHost()
       
   423     {
       
   424         return strlen($this->_host) > 0 ? $this->_host : false;
       
   425     }
       
   426 
       
   427     /**
       
   428      * Returns true if and only if the host string passes validation. If no host is passed,
       
   429      * then the host contained in the instance variable is used.
       
   430      *
       
   431      * @param  string $host The HTTP host
       
   432      * @return boolean
       
   433      * @uses   Zend_Filter
       
   434      */
       
   435     public function validateHost($host = null)
       
   436     {
       
   437         if ($host === null) {
       
   438             $host = $this->_host;
       
   439         }
       
   440 
       
   441         // If the host is empty, then it is considered invalid
       
   442         if (strlen($host) === 0) {
       
   443             return false;
       
   444         }
       
   445 
       
   446         // Check the host against the allowed values; delegated to Zend_Filter.
       
   447         $validate = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL);
       
   448 
       
   449         return $validate->isValid($host);
       
   450     }
       
   451 
       
   452     /**
       
   453      * Sets the host for the current URI, and returns the old host
       
   454      *
       
   455      * @param  string $host The HTTP host
       
   456      * @throws Zend_Uri_Exception When $host is nota valid HTTP host
       
   457      * @return string
       
   458      */
       
   459     public function setHost($host)
       
   460     {
       
   461         if ($this->validateHost($host) === false) {
       
   462             require_once 'Zend/Uri/Exception.php';
       
   463             throw new Zend_Uri_Exception("Host \"$host\" is not a valid HTTP host");
       
   464         }
       
   465 
       
   466         $oldHost     = $this->_host;
       
   467         $this->_host = $host;
       
   468 
       
   469         return $oldHost;
       
   470     }
       
   471 
       
   472     /**
       
   473      * Returns the TCP port, or FALSE if none.
       
   474      *
       
   475      * @return string
       
   476      */
       
   477     public function getPort()
       
   478     {
       
   479         return strlen($this->_port) > 0 ? $this->_port : false;
       
   480     }
       
   481 
       
   482     /**
       
   483      * Returns true if and only if the TCP port string passes validation. If no port is passed,
       
   484      * then the port contained in the instance variable is used.
       
   485      *
       
   486      * @param  string $port The HTTP port
       
   487      * @return boolean
       
   488      */
       
   489     public function validatePort($port = null)
       
   490     {
       
   491         if ($port === null) {
       
   492             $port = $this->_port;
       
   493         }
       
   494 
       
   495         // If the port is empty, then it is considered valid
       
   496         if (strlen($port) === 0) {
       
   497             return true;
       
   498         }
       
   499 
       
   500         // Check the port against the allowed values
       
   501         return ctype_digit((string) $port) and 1 <= $port and $port <= 65535;
       
   502     }
       
   503 
       
   504     /**
       
   505      * Sets the port for the current URI, and returns the old port
       
   506      *
       
   507      * @param  string $port The HTTP port
       
   508      * @throws Zend_Uri_Exception When $port is not a valid HTTP port
       
   509      * @return string
       
   510      */
       
   511     public function setPort($port)
       
   512     {
       
   513         if ($this->validatePort($port) === false) {
       
   514             require_once 'Zend/Uri/Exception.php';
       
   515             throw new Zend_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
       
   516         }
       
   517 
       
   518         $oldPort     = $this->_port;
       
   519         $this->_port = $port;
       
   520 
       
   521         return $oldPort;
       
   522     }
       
   523 
       
   524     /**
       
   525      * Returns the path and filename portion of the URL.
       
   526      *
       
   527      * @return string
       
   528      */
       
   529     public function getPath()
       
   530     {
       
   531         return strlen($this->_path) > 0 ? $this->_path : '/';
       
   532     }
       
   533 
       
   534     /**
       
   535      * Returns true if and only if the path string passes validation. If no path is passed,
       
   536      * then the path contained in the instance variable is used.
       
   537      *
       
   538      * @param  string $path The HTTP path
       
   539      * @throws Zend_Uri_Exception When path validation fails
       
   540      * @return boolean
       
   541      */
       
   542     public function validatePath($path = null)
       
   543     {
       
   544         if ($path === null) {
       
   545             $path = $this->_path;
       
   546         }
       
   547 
       
   548         // If the path is empty, then it is considered valid
       
   549         if (strlen($path) === 0) {
       
   550             return true;
       
   551         }
       
   552 
       
   553         // Determine whether the path is well-formed
       
   554         $pattern = '/^' . $this->_regex['path'] . '$/';
       
   555         $status  = @preg_match($pattern, $path);
       
   556         if ($status === false) {
       
   557             require_once 'Zend/Uri/Exception.php';
       
   558             throw new Zend_Uri_Exception('Internal error: path validation failed');
       
   559         }
       
   560 
       
   561         return (boolean) $status;
       
   562     }
       
   563 
       
   564     /**
       
   565      * Sets the path for the current URI, and returns the old path
       
   566      *
       
   567      * @param  string $path The HTTP path
       
   568      * @throws Zend_Uri_Exception When $path is not a valid HTTP path
       
   569      * @return string
       
   570      */
       
   571     public function setPath($path)
       
   572     {
       
   573         if ($this->validatePath($path) === false) {
       
   574             require_once 'Zend/Uri/Exception.php';
       
   575             throw new Zend_Uri_Exception("Path \"$path\" is not a valid HTTP path");
       
   576         }
       
   577 
       
   578         $oldPath     = $this->_path;
       
   579         $this->_path = $path;
       
   580 
       
   581         return $oldPath;
       
   582     }
       
   583 
       
   584     /**
       
   585      * Returns the query portion of the URL (after ?), or FALSE if none.
       
   586      *
       
   587      * @return string
       
   588      */
       
   589     public function getQuery()
       
   590     {
       
   591         return strlen($this->_query) > 0 ? $this->_query : false;
       
   592     }
       
   593 
       
   594     /**
       
   595      * Returns the query portion of the URL (after ?) as a
       
   596      * key-value-array. If the query is empty an empty array
       
   597      * is returned
       
   598      *
       
   599      * @return array
       
   600      */
       
   601     public function getQueryAsArray()
       
   602     {
       
   603         $query = $this->getQuery();
       
   604         $querryArray = array();
       
   605         if ($query !== false) {
       
   606             parse_str($query, $querryArray);
       
   607         }
       
   608         return $querryArray;
       
   609     }
       
   610 
       
   611     /**
       
   612      * Returns true if and only if the query string passes validation. If no query is passed,
       
   613      * then the query string contained in the instance variable is used.
       
   614      *
       
   615      * @param  string $query The query to validate
       
   616      * @throws Zend_Uri_Exception When query validation fails
       
   617      * @return boolean
       
   618      * @link   http://www.faqs.org/rfcs/rfc2396.html
       
   619      */
       
   620     public function validateQuery($query = null)
       
   621     {
       
   622         if ($query === null) {
       
   623             $query = $this->_query;
       
   624         }
       
   625 
       
   626         // If query is empty, it is considered to be valid
       
   627         if (strlen($query) === 0) {
       
   628             return true;
       
   629         }
       
   630 
       
   631         // Determine whether the query is well-formed
       
   632         $pattern = '/^' . $this->_regex['uric'] . '*$/';
       
   633         $status  = @preg_match($pattern, $query);
       
   634         if ($status === false) {
       
   635             require_once 'Zend/Uri/Exception.php';
       
   636             throw new Zend_Uri_Exception('Internal error: query validation failed');
       
   637         }
       
   638 
       
   639         return $status == 1;
       
   640     }
       
   641 
       
   642     /**
       
   643      * Add or replace params in the query string for the current URI, and
       
   644      * return the old query.
       
   645      *
       
   646      * @param  array $queryParams
       
   647      * @return string Old query string
       
   648      */
       
   649     public function addReplaceQueryParameters(array $queryParams)
       
   650     {
       
   651         $queryParams = array_merge($this->getQueryAsArray(), $queryParams);
       
   652         return $this->setQuery($queryParams);
       
   653     }
       
   654 
       
   655     /**
       
   656      * Remove params in the query string for the current URI, and
       
   657      * return the old query.
       
   658      *
       
   659      * @param  array $queryParamKeys
       
   660      * @return string Old query string
       
   661      */
       
   662     public function removeQueryParameters(array $queryParamKeys)
       
   663     {
       
   664         $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0));
       
   665         return $this->setQuery($queryParams);
       
   666     }
       
   667 
       
   668     /**
       
   669      * Set the query string for the current URI, and return the old query
       
   670      * string This method accepts both strings and arrays.
       
   671      *
       
   672      * @param  string|array $query The query string or array
       
   673      * @throws Zend_Uri_Exception When $query is not a valid query string
       
   674      * @return string              Old query string
       
   675      */
       
   676     public function setQuery($query)
       
   677     {
       
   678         $oldQuery = $this->_query;
       
   679 
       
   680         // If query is empty, set an empty string
       
   681         if (empty($query) === true) {
       
   682             $this->_query = '';
       
   683             return $oldQuery;
       
   684         }
       
   685 
       
   686         // If query is an array, make a string out of it
       
   687         if (is_array($query) === true) {
       
   688             $query = http_build_query($query, '', '&');
       
   689         } else {
       
   690             // If it is a string, make sure it is valid. If not parse and encode it
       
   691             $query = (string) $query;
       
   692             if ($this->validateQuery($query) === false) {
       
   693                 parse_str($query, $queryArray);
       
   694                 $query = http_build_query($queryArray, '', '&');
       
   695             }
       
   696         }
       
   697 
       
   698         // Make sure the query is valid, and set it
       
   699         if ($this->validateQuery($query) === false) {
       
   700             require_once 'Zend/Uri/Exception.php';
       
   701             throw new Zend_Uri_Exception("'$query' is not a valid query string");
       
   702         }
       
   703 
       
   704         $this->_query = $query;
       
   705 
       
   706         return $oldQuery;
       
   707     }
       
   708 
       
   709     /**
       
   710      * Returns the fragment portion of the URL (after #), or FALSE if none.
       
   711      *
       
   712      * @return string|false
       
   713      */
       
   714     public function getFragment()
       
   715     {
       
   716         return strlen($this->_fragment) > 0 ? $this->_fragment : false;
       
   717     }
       
   718 
       
   719     /**
       
   720      * Returns true if and only if the fragment passes validation. If no fragment is passed,
       
   721      * then the fragment contained in the instance variable is used.
       
   722      *
       
   723      * @param  string $fragment Fragment of an URI
       
   724      * @throws Zend_Uri_Exception When fragment validation fails
       
   725      * @return boolean
       
   726      * @link   http://www.faqs.org/rfcs/rfc2396.html
       
   727      */
       
   728     public function validateFragment($fragment = null)
       
   729     {
       
   730         if ($fragment === null) {
       
   731             $fragment = $this->_fragment;
       
   732         }
       
   733 
       
   734         // If fragment is empty, it is considered to be valid
       
   735         if (strlen($fragment) === 0) {
       
   736             return true;
       
   737         }
       
   738 
       
   739         // Determine whether the fragment is well-formed
       
   740         $pattern = '/^' . $this->_regex['uric'] . '*$/';
       
   741         $status  = @preg_match($pattern, $fragment);
       
   742         if ($status === false) {
       
   743             require_once 'Zend/Uri/Exception.php';
       
   744             throw new Zend_Uri_Exception('Internal error: fragment validation failed');
       
   745         }
       
   746 
       
   747         return (boolean) $status;
       
   748     }
       
   749 
       
   750     /**
       
   751      * Sets the fragment for the current URI, and returns the old fragment
       
   752      *
       
   753      * @param  string $fragment Fragment of the current URI
       
   754      * @throws Zend_Uri_Exception When $fragment is not a valid HTTP fragment
       
   755      * @return string
       
   756      */
       
   757     public function setFragment($fragment)
       
   758     {
       
   759         if ($this->validateFragment($fragment) === false) {
       
   760             require_once 'Zend/Uri/Exception.php';
       
   761             throw new Zend_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
       
   762         }
       
   763 
       
   764         $oldFragment     = $this->_fragment;
       
   765         $this->_fragment = $fragment;
       
   766 
       
   767         return $oldFragment;
       
   768     }
       
   769 }