source: extensions/Google2Piwigo/include/Zend/Uri/Http.php @ 17475

Last change on this file since 17475 was 17475, checked in by mistic100, 12 years ago

new extension: Google2Piwigo

File size: 23.5 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-2012 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 24594 2012-01-05 21:27:01Z matthew $
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-2012 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        // Save remaining URI components
228        $this->_username = isset($matches[2]) === true ? $matches[2] : '';
229        $this->_password = isset($matches[4]) === true ? $matches[4] : '';
230        $this->_host     = isset($matches[5]) === true 
231                         ? preg_replace('~^\[([^]]+)\]$~', '\1', $matches[5])  // Strip wrapper [] from IPv6 literal
232                         : '';
233        $this->_port     = isset($matches[7]) === true ? $matches[7] : '';
234    }
235
236    /**
237     * Returns a URI based on current values of the instance variables. If any
238     * part of the URI does not pass validation, then an exception is thrown.
239     *
240     * @throws Zend_Uri_Exception When one or more parts of the URI are invalid
241     * @return string
242     */
243    public function getUri()
244    {
245        if ($this->valid() === false) {
246            require_once 'Zend/Uri/Exception.php';
247            throw new Zend_Uri_Exception('One or more parts of the URI are invalid');
248        }
249
250        $password = strlen($this->_password) > 0 ? ":$this->_password" : '';
251        $auth     = strlen($this->_username) > 0 ? "$this->_username$password@" : '';
252        $port     = strlen($this->_port) > 0 ? ":$this->_port" : '';
253        $query    = strlen($this->_query) > 0 ? "?$this->_query" : '';
254        $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : '';
255
256        return $this->_scheme
257             . '://'
258             . $auth
259             . $this->_host
260             . $port
261             . $this->_path
262             . $query
263             . $fragment;
264    }
265
266    /**
267     * Validate the current URI from the instance variables. Returns true if and only if all
268     * parts pass validation.
269     *
270     * @return boolean
271     */
272    public function valid()
273    {
274        // Return true if and only if all parts of the URI have passed validation
275        return $this->validateUsername()
276           and $this->validatePassword()
277           and $this->validateHost()
278           and $this->validatePort()
279           and $this->validatePath()
280           and $this->validateQuery()
281           and $this->validateFragment();
282    }
283
284    /**
285     * Returns the username portion of the URL, or FALSE if none.
286     *
287     * @return string
288     */
289    public function getUsername()
290    {
291        return strlen($this->_username) > 0 ? $this->_username : false;
292    }
293
294    /**
295     * Returns true if and only if the username passes validation. If no username is passed,
296     * then the username contained in the instance variable is used.
297     *
298     * @param  string $username The HTTP username
299     * @throws Zend_Uri_Exception When username validation fails
300     * @return boolean
301     * @link   http://www.faqs.org/rfcs/rfc2396.html
302     */
303    public function validateUsername($username = null)
304    {
305        if ($username === null) {
306            $username = $this->_username;
307        }
308
309        // If the username is empty, then it is considered valid
310        if (strlen($username) === 0) {
311            return true;
312        }
313
314        // Check the username against the allowed values
315        $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
316            self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username);
317
318        if ($status === false) {
319            require_once 'Zend/Uri/Exception.php';
320            throw new Zend_Uri_Exception('Internal error: username validation failed');
321        }
322
323        return $status === 1;
324    }
325
326    /**
327     * Sets the username for the current URI, and returns the old username
328     *
329     * @param  string $username The HTTP username
330     * @throws Zend_Uri_Exception When $username is not a valid HTTP username
331     * @return string
332     */
333    public function setUsername($username)
334    {
335        if ($this->validateUsername($username) === false) {
336            require_once 'Zend/Uri/Exception.php';
337            throw new Zend_Uri_Exception("Username \"$username\" is not a valid HTTP username");
338        }
339
340        $oldUsername     = $this->_username;
341        $this->_username = $username;
342
343        return $oldUsername;
344    }
345
346    /**
347     * Returns the password portion of the URL, or FALSE if none.
348     *
349     * @return string
350     */
351    public function getPassword()
352    {
353        return strlen($this->_password) > 0 ? $this->_password : false;
354    }
355
356    /**
357     * Returns true if and only if the password passes validation. If no password is passed,
358     * then the password contained in the instance variable is used.
359     *
360     * @param  string $password The HTTP password
361     * @throws Zend_Uri_Exception When password validation fails
362     * @return boolean
363     * @link   http://www.faqs.org/rfcs/rfc2396.html
364     */
365    public function validatePassword($password = null)
366    {
367        if ($password === null) {
368            $password = $this->_password;
369        }
370
371        // If the password is empty, then it is considered valid
372        if (strlen($password) === 0) {
373            return true;
374        }
375
376        // If the password is nonempty, but there is no username, then it is considered invalid
377        if (strlen($password) > 0 and strlen($this->_username) === 0) {
378            return false;
379        }
380
381        // Check the password against the allowed values
382        $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
383            self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password);
384
385        if ($status === false) {
386            require_once 'Zend/Uri/Exception.php';
387            throw new Zend_Uri_Exception('Internal error: password validation failed.');
388        }
389
390        return $status == 1;
391    }
392
393    /**
394     * Sets the password for the current URI, and returns the old password
395     *
396     * @param  string $password The HTTP password
397     * @throws Zend_Uri_Exception When $password is not a valid HTTP password
398     * @return string
399     */
400    public function setPassword($password)
401    {
402        if ($this->validatePassword($password) === false) {
403            require_once 'Zend/Uri/Exception.php';
404            throw new Zend_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
405        }
406
407        $oldPassword     = $this->_password;
408        $this->_password = $password;
409
410        return $oldPassword;
411    }
412
413    /**
414     * Returns the domain or host IP portion of the URL, or FALSE if none.
415     *
416     * @return string
417     */
418    public function getHost()
419    {
420        return strlen($this->_host) > 0 ? $this->_host : false;
421    }
422
423    /**
424     * Returns true if and only if the host string passes validation. If no host is passed,
425     * then the host contained in the instance variable is used.
426     *
427     * @param  string $host The HTTP host
428     * @return boolean
429     * @uses   Zend_Filter
430     */
431    public function validateHost($host = null)
432    {
433        if ($host === null) {
434            $host = $this->_host;
435        }
436
437        // If the host is empty, then it is considered invalid
438        if (strlen($host) === 0) {
439            return false;
440        }
441
442        // Check the host against the allowed values; delegated to Zend_Filter.
443        $validate = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL);
444
445        return $validate->isValid($host);
446    }
447
448    /**
449     * Sets the host for the current URI, and returns the old host
450     *
451     * @param  string $host The HTTP host
452     * @throws Zend_Uri_Exception When $host is nota valid HTTP host
453     * @return string
454     */
455    public function setHost($host)
456    {
457        if ($this->validateHost($host) === false) {
458            require_once 'Zend/Uri/Exception.php';
459            throw new Zend_Uri_Exception("Host \"$host\" is not a valid HTTP host");
460        }
461
462        $oldHost     = $this->_host;
463        $this->_host = $host;
464
465        return $oldHost;
466    }
467
468    /**
469     * Returns the TCP port, or FALSE if none.
470     *
471     * @return string
472     */
473    public function getPort()
474    {
475        return strlen($this->_port) > 0 ? $this->_port : false;
476    }
477
478    /**
479     * Returns true if and only if the TCP port string passes validation. If no port is passed,
480     * then the port contained in the instance variable is used.
481     *
482     * @param  string $port The HTTP port
483     * @return boolean
484     */
485    public function validatePort($port = null)
486    {
487        if ($port === null) {
488            $port = $this->_port;
489        }
490
491        // If the port is empty, then it is considered valid
492        if (strlen($port) === 0) {
493            return true;
494        }
495
496        // Check the port against the allowed values
497        return ctype_digit((string) $port) and 1 <= $port and $port <= 65535;
498    }
499
500    /**
501     * Sets the port for the current URI, and returns the old port
502     *
503     * @param  string $port The HTTP port
504     * @throws Zend_Uri_Exception When $port is not a valid HTTP port
505     * @return string
506     */
507    public function setPort($port)
508    {
509        if ($this->validatePort($port) === false) {
510            require_once 'Zend/Uri/Exception.php';
511            throw new Zend_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
512        }
513
514        $oldPort     = $this->_port;
515        $this->_port = $port;
516
517        return $oldPort;
518    }
519
520    /**
521     * Returns the path and filename portion of the URL.
522     *
523     * @return string
524     */
525    public function getPath()
526    {
527        return strlen($this->_path) > 0 ? $this->_path : '/';
528    }
529
530    /**
531     * Returns true if and only if the path string passes validation. If no path is passed,
532     * then the path contained in the instance variable is used.
533     *
534     * @param  string $path The HTTP path
535     * @throws Zend_Uri_Exception When path validation fails
536     * @return boolean
537     */
538    public function validatePath($path = null)
539    {
540        if ($path === null) {
541            $path = $this->_path;
542        }
543
544        // If the path is empty, then it is considered valid
545        if (strlen($path) === 0) {
546            return true;
547        }
548
549        // Determine whether the path is well-formed
550        $pattern = '/^' . $this->_regex['path'] . '$/';
551        $status  = @preg_match($pattern, $path);
552        if ($status === false) {
553            require_once 'Zend/Uri/Exception.php';
554            throw new Zend_Uri_Exception('Internal error: path validation failed');
555        }
556
557        return (boolean) $status;
558    }
559
560    /**
561     * Sets the path for the current URI, and returns the old path
562     *
563     * @param  string $path The HTTP path
564     * @throws Zend_Uri_Exception When $path is not a valid HTTP path
565     * @return string
566     */
567    public function setPath($path)
568    {
569        if ($this->validatePath($path) === false) {
570            require_once 'Zend/Uri/Exception.php';
571            throw new Zend_Uri_Exception("Path \"$path\" is not a valid HTTP path");
572        }
573
574        $oldPath     = $this->_path;
575        $this->_path = $path;
576
577        return $oldPath;
578    }
579
580    /**
581     * Returns the query portion of the URL (after ?), or FALSE if none.
582     *
583     * @return string
584     */
585    public function getQuery()
586    {
587        return strlen($this->_query) > 0 ? $this->_query : false;
588    }
589
590    /**
591     * Returns the query portion of the URL (after ?) as a
592     * key-value-array. If the query is empty an empty array
593     * is returned
594     *
595     * @return array
596     */
597    public function getQueryAsArray()
598    {
599        $query = $this->getQuery();
600        $querryArray = array();
601        if ($query !== false) {
602            parse_str($query, $querryArray);
603        }
604        return $querryArray;
605    }
606
607    /**
608     * Returns true if and only if the query string passes validation. If no query is passed,
609     * then the query string contained in the instance variable is used.
610     *
611     * @param  string $query The query to validate
612     * @throws Zend_Uri_Exception When query validation fails
613     * @return boolean
614     * @link   http://www.faqs.org/rfcs/rfc2396.html
615     */
616    public function validateQuery($query = null)
617    {
618        if ($query === null) {
619            $query = $this->_query;
620        }
621
622        // If query is empty, it is considered to be valid
623        if (strlen($query) === 0) {
624            return true;
625        }
626
627        // Determine whether the query is well-formed
628        $pattern = '/^' . $this->_regex['uric'] . '*$/';
629        $status  = @preg_match($pattern, $query);
630        if ($status === false) {
631            require_once 'Zend/Uri/Exception.php';
632            throw new Zend_Uri_Exception('Internal error: query validation failed');
633        }
634
635        return $status == 1;
636    }
637
638    /**
639     * Add or replace params in the query string for the current URI, and
640     * return the old query.
641     *
642     * @param  array $queryParams
643     * @return string Old query string
644     */
645    public function addReplaceQueryParameters(array $queryParams)
646    {
647        $queryParams = array_merge($this->getQueryAsArray(), $queryParams);
648        return $this->setQuery($queryParams);
649    }
650
651    /**
652     * Remove params in the query string for the current URI, and
653     * return the old query.
654     *
655     * @param  array $queryParamKeys
656     * @return string Old query string
657     */
658    public function removeQueryParameters(array $queryParamKeys)
659    {
660        $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0));
661        return $this->setQuery($queryParams);
662    }
663
664    /**
665     * Set the query string for the current URI, and return the old query
666     * string This method accepts both strings and arrays.
667     *
668     * @param  string|array $query The query string or array
669     * @throws Zend_Uri_Exception When $query is not a valid query string
670     * @return string              Old query string
671     */
672    public function setQuery($query)
673    {
674        $oldQuery = $this->_query;
675
676        // If query is empty, set an empty string
677        if (empty($query) === true) {
678            $this->_query = '';
679            return $oldQuery;
680        }
681
682        // If query is an array, make a string out of it
683        if (is_array($query) === true) {
684            $query = http_build_query($query, '', '&');
685        } else {
686            // If it is a string, make sure it is valid. If not parse and encode it
687            $query = (string) $query;
688            if ($this->validateQuery($query) === false) {
689                parse_str($query, $queryArray);
690                $query = http_build_query($queryArray, '', '&');
691            }
692        }
693
694        // Make sure the query is valid, and set it
695        if ($this->validateQuery($query) === false) {
696            require_once 'Zend/Uri/Exception.php';
697            throw new Zend_Uri_Exception("'$query' is not a valid query string");
698        }
699
700        $this->_query = $query;
701
702        return $oldQuery;
703    }
704
705    /**
706     * Returns the fragment portion of the URL (after #), or FALSE if none.
707     *
708     * @return string|false
709     */
710    public function getFragment()
711    {
712        return strlen($this->_fragment) > 0 ? $this->_fragment : false;
713    }
714
715    /**
716     * Returns true if and only if the fragment passes validation. If no fragment is passed,
717     * then the fragment contained in the instance variable is used.
718     *
719     * @param  string $fragment Fragment of an URI
720     * @throws Zend_Uri_Exception When fragment validation fails
721     * @return boolean
722     * @link   http://www.faqs.org/rfcs/rfc2396.html
723     */
724    public function validateFragment($fragment = null)
725    {
726        if ($fragment === null) {
727            $fragment = $this->_fragment;
728        }
729
730        // If fragment is empty, it is considered to be valid
731        if (strlen($fragment) === 0) {
732            return true;
733        }
734
735        // Determine whether the fragment is well-formed
736        $pattern = '/^' . $this->_regex['uric'] . '*$/';
737        $status  = @preg_match($pattern, $fragment);
738        if ($status === false) {
739            require_once 'Zend/Uri/Exception.php';
740            throw new Zend_Uri_Exception('Internal error: fragment validation failed');
741        }
742
743        return (boolean) $status;
744    }
745
746    /**
747     * Sets the fragment for the current URI, and returns the old fragment
748     *
749     * @param  string $fragment Fragment of the current URI
750     * @throws Zend_Uri_Exception When $fragment is not a valid HTTP fragment
751     * @return string
752     */
753    public function setFragment($fragment)
754    {
755        if ($this->validateFragment($fragment) === false) {
756            require_once 'Zend/Uri/Exception.php';
757            throw new Zend_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
758        }
759
760        $oldFragment     = $this->_fragment;
761        $this->_fragment = $fragment;
762
763        return $oldFragment;
764    }
765}
Note: See TracBrowser for help on using the repository browser.