Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/packages/zendframework/uri.php

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