source: trunk/www.guidonia.net/wp/wp-content/plugins/webtv/Drivers/Zend/Uri/Http.php@ 44

Last change on this file since 44 was 44, checked in by luciano, 14 years ago
File size: 22.3 KB
Line 
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-2008 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 14650 2009-04-05 03:15:38Z robinsk $
20 */
21
22/**
23 * @see Zend_Uri
24 */
25require_once 'Zend/Uri.php';
26
27/**
28 * @see Zend_Validate_Hostname
29 */
30require_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-2008 Zend Technologies USA Inc. (http://www.zend.com)
39 * @license http://framework.zend.com/license/new-bsd New BSD License
40 */
41class 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, or FALSE if none.
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 true if and only if the query string passes validation. If no query is passed,
596 * then the query string contained in the instance variable is used.
597 *
598 * @param string $query The query to validate
599 * @throws Zend_Uri_Exception When query validation fails
600 * @return boolean
601 * @link http://www.faqs.org/rfcs/rfc2396.html
602 */
603 public function validateQuery($query = null)
604 {
605 if ($query === null) {
606 $query = $this->_query;
607 }
608
609 // If query is empty, it is considered to be valid
610 if (strlen($query) === 0) {
611 return true;
612 }
613
614 // Determine whether the query is well-formed
615 $pattern = '/^' . $this->_regex['uric'] . '*$/';
616 $status = @preg_match($pattern, $query);
617 if ($status === false) {
618 require_once 'Zend/Uri/Exception.php';
619 throw new Zend_Uri_Exception('Internal error: query validation failed');
620 }
621
622 return $status == 1;
623 }
624
625 /**
626 * Set the query string for the current URI, and return the old query
627 * string This method accepts both strings and arrays.
628 *
629 * @param string|array $query The query string or array
630 * @throws Zend_Uri_Exception When $query is not a valid query string
631 * @return string Old query string
632 */
633 public function setQuery($query)
634 {
635 $oldQuery = $this->_query;
636
637 // If query is empty, set an empty string
638 if (empty($query) === true) {
639 $this->_query = '';
640 return $oldQuery;
641 }
642
643 // If query is an array, make a string out of it
644 if (is_array($query) === true) {
645 $query = http_build_query($query, '', '&');
646 } else {
647 // If it is a string, make sure it is valid. If not parse and encode it
648 $query = (string) $query;
649 if ($this->validateQuery($query) === false) {
650 parse_str($query, $queryArray);
651 $query = http_build_query($queryArray, '', '&');
652 }
653 }
654
655 // Make sure the query is valid, and set it
656 if ($this->validateQuery($query) === false) {
657 require_once 'Zend/Uri/Exception.php';
658 throw new Zend_Uri_Exception("'$query' is not a valid query string");
659 }
660
661 $this->_query = $query;
662
663 return $oldQuery;
664 }
665
666 /**
667 * Returns the fragment portion of the URL (after #), or FALSE if none.
668 *
669 * @return string|false
670 */
671 public function getFragment()
672 {
673 return strlen($this->_fragment) > 0 ? $this->_fragment : false;
674 }
675
676 /**
677 * Returns true if and only if the fragment passes validation. If no fragment is passed,
678 * then the fragment contained in the instance variable is used.
679 *
680 * @param string $fragment Fragment of an URI
681 * @throws Zend_Uri_Exception When fragment validation fails
682 * @return boolean
683 * @link http://www.faqs.org/rfcs/rfc2396.html
684 */
685 public function validateFragment($fragment = null)
686 {
687 if ($fragment === null) {
688 $fragment = $this->_fragment;
689 }
690
691 // If fragment is empty, it is considered to be valid
692 if (strlen($fragment) === 0) {
693 return true;
694 }
695
696 // Determine whether the fragment is well-formed
697 $pattern = '/^' . $this->_regex['uric'] . '*$/';
698 $status = @preg_match($pattern, $fragment);
699 if ($status === false) {
700 require_once 'Zend/Uri/Exception.php';
701 throw new Zend_Uri_Exception('Internal error: fragment validation failed');
702 }
703
704 return (boolean) $status;
705 }
706
707 /**
708 * Sets the fragment for the current URI, and returns the old fragment
709 *
710 * @param string $fragment Fragment of the current URI
711 * @throws Zend_Uri_Exception When $fragment is not a valid HTTP fragment
712 * @return string
713 */
714 public function setFragment($fragment)
715 {
716 if ($this->validateFragment($fragment) === false) {
717 require_once 'Zend/Uri/Exception.php';
718 throw new Zend_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
719 }
720
721 $oldFragment = $this->_fragment;
722 $this->_fragment = $fragment;
723
724 return $oldFragment;
725 }
726}
Note: See TracBrowser for help on using the repository browser.