summaryrefslogtreecommitdiffstats
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/autoload.php2
-rw-r--r--vendor/composer/autoload_classmap.php1
-rw-r--r--vendor/composer/autoload_real.php10
-rw-r--r--vendor/composer/installed.json63
-rw-r--r--vendor/pear/net_url2/.gitignore7
-rw-r--r--vendor/pear/net_url2/.scrutinizer.yml38
-rw-r--r--vendor/pear/net_url2/.travis.yml17
-rwxr-xr-xvendor/pear/net_url2/Net/URL2.php1219
-rw-r--r--vendor/pear/net_url2/README.md43
-rw-r--r--vendor/pear/net_url2/composer.json47
-rwxr-xr-xvendor/pear/net_url2/docs/6470.php56
-rw-r--r--vendor/pear/net_url2/docs/BSD-3-CLAUSE-Heyes27
-rwxr-xr-xvendor/pear/net_url2/docs/example.php62
-rw-r--r--vendor/pear/net_url2/package.xml469
-rw-r--r--vendor/pear/net_url2/phpunit.xml.dist17
-rw-r--r--vendor/pear/net_url2/tests/AllTests.php59
-rw-r--r--vendor/pear/net_url2/tests/Net/URL2Test.php1088
17 files changed, 3219 insertions, 6 deletions
diff --git a/vendor/autoload.php b/vendor/autoload.php
index 00dd6cbac..31951a1d7 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer' . '/autoload_real.php';
-return ComposerAutoloaderInit24b6ebb4f09ef9d427b235c134732c27::getLoader();
+return ComposerAutoloaderInit1dd142fbce5beefcee5a01512aad0200::getLoader();
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 7a91153b0..077c06a60 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
+ 'Net_URL2' => $vendorDir . '/pear/net_url2/Net/URL2.php',
);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index d3d749f31..96775e0f1 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit24b6ebb4f09ef9d427b235c134732c27
+class ComposerAutoloaderInit1dd142fbce5beefcee5a01512aad0200
{
private static $loader;
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit24b6ebb4f09ef9d427b235c134732c27
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInit24b6ebb4f09ef9d427b235c134732c27', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit1dd142fbce5beefcee5a01512aad0200', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInit24b6ebb4f09ef9d427b235c134732c27', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit1dd142fbce5beefcee5a01512aad0200', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
@@ -42,14 +42,14 @@ class ComposerAutoloaderInit24b6ebb4f09ef9d427b235c134732c27
$includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) {
- composerRequire24b6ebb4f09ef9d427b235c134732c27($file);
+ composerRequire1dd142fbce5beefcee5a01512aad0200($file);
}
return $loader;
}
}
-function composerRequire24b6ebb4f09ef9d427b235c134732c27($file)
+function composerRequire1dd142fbce5beefcee5a01512aad0200($file)
{
require $file;
}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 1c7127b82..c302c015a 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -121,5 +121,68 @@
],
"description": "Modern library to handle RSS/Atom feeds",
"homepage": "https://github.com/fguillot/picoFeed"
+ },
+ {
+ "name": "pear/net_url2",
+ "version": "v2.2.0",
+ "version_normalized": "2.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pear/Net_URL2.git",
+ "reference": "fa9b1ecb3c3e640d4a54d58d681a4cb7524f209e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pear/Net_URL2/zipball/fa9b1ecb3c3e640d4a54d58d681a4cb7524f209e",
+ "reference": "fa9b1ecb3c3e640d4a54d58d681a4cb7524f209e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.1.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">=3.3.0"
+ },
+ "time": "2015-04-18 17:36:57",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "Net/URL2.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "David Coallier",
+ "email": "davidc@php.net"
+ },
+ {
+ "name": "Tom Klingenberg",
+ "email": "tkli@php.net"
+ },
+ {
+ "name": "Christian Schmidt",
+ "email": "chmidt@php.net"
+ }
+ ],
+ "description": "Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of relative URLs.",
+ "homepage": "https://github.com/pear/Net_URL2",
+ "keywords": [
+ "PEAR",
+ "net",
+ "networking",
+ "rfc3986",
+ "uri",
+ "url"
+ ]
}
]
diff --git a/vendor/pear/net_url2/.gitignore b/vendor/pear/net_url2/.gitignore
new file mode 100644
index 000000000..0e7f38ac3
--- /dev/null
+++ b/vendor/pear/net_url2/.gitignore
@@ -0,0 +1,7 @@
+# pear related
+/Net_URL2-*.tgz
+
+# composer related
+vendor/
+/composer.lock
+/composer.phar
diff --git a/vendor/pear/net_url2/.scrutinizer.yml b/vendor/pear/net_url2/.scrutinizer.yml
new file mode 100644
index 000000000..bfdb37388
--- /dev/null
+++ b/vendor/pear/net_url2/.scrutinizer.yml
@@ -0,0 +1,38 @@
+filter:
+ excluded_paths:
+ - 'docs/*'
+tools:
+ php_code_coverage:
+ enabled: true
+ test_command: phpunit
+ php_cpd:
+ excluded_dirs:
+ - tests
+ filter:
+ excluded_paths: []
+ php_pdepend:
+ excluded_dirs:
+ - tests
+ php_hhvm:
+ filter:
+ excluded_paths: []
+ php_mess_detector:
+ filter:
+ excluded_paths: []
+ php_analyzer:
+ enabled: true
+ filter:
+ excluded_paths: ['docs/*']
+ php_code_sniffer:
+ enabled: true
+ filter:
+ excluded_paths: ['docs/*']
+ config:
+ tab_width: 4
+ encoding: utf8
+ ruleset: ~
+ standard: PEAR
+ php_loc:
+ excluded_dirs:
+ - tests
+ - docs
diff --git a/vendor/pear/net_url2/.travis.yml b/vendor/pear/net_url2/.travis.yml
new file mode 100644
index 000000000..a3e7bdc49
--- /dev/null
+++ b/vendor/pear/net_url2/.travis.yml
@@ -0,0 +1,17 @@
+language: php
+
+php:
+ - 5.2
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - hhvm
+ - hhvm-nightly
+
+matrix:
+ allow_failures:
+ - php: hhvm-nightly
+
+script: phpunit --coverage-text tests/Net
diff --git a/vendor/pear/net_url2/Net/URL2.php b/vendor/pear/net_url2/Net/URL2.php
new file mode 100755
index 000000000..dba48ce04
--- /dev/null
+++ b/vendor/pear/net_url2/Net/URL2.php
@@ -0,0 +1,1219 @@
+<?php
+/**
+ * Net_URL2, a class representing a URL as per RFC 3986.
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2007-2009, Peytz & Co. A/S
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Net_URL2 nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Christian Schmidt <schmidt@php.net>
+ * @copyright 2007-2009 Peytz & Co. A/S
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @version CVS: $Id$
+ * @link https://tools.ietf.org/html/rfc3986
+ */
+
+/**
+ * Represents a URL as per RFC 3986.
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Christian Schmidt <schmidt@php.net>
+ * @copyright 2007-2009 Peytz & Co. A/S
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @version Release: @package_version@
+ * @link https://pear.php.net/package/Net_URL2
+ */
+class Net_URL2
+{
+ /**
+ * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default
+ * is true.
+ */
+ const OPTION_STRICT = 'strict';
+
+ /**
+ * Represent arrays in query using PHP's [] notation. Default is true.
+ */
+ const OPTION_USE_BRACKETS = 'use_brackets';
+
+ /**
+ * Drop zero-based integer sequences in query using PHP's [] notation. Default
+ * is true.
+ */
+ const OPTION_DROP_SEQUENCE = 'drop_sequence';
+
+ /**
+ * URL-encode query variable keys. Default is true.
+ */
+ const OPTION_ENCODE_KEYS = 'encode_keys';
+
+ /**
+ * Query variable separators when parsing the query string. Every character
+ * is considered a separator. Default is "&".
+ */
+ const OPTION_SEPARATOR_INPUT = 'input_separator';
+
+ /**
+ * Query variable separator used when generating the query string. Default
+ * is "&".
+ */
+ const OPTION_SEPARATOR_OUTPUT = 'output_separator';
+
+ /**
+ * Default options corresponds to how PHP handles $_GET.
+ */
+ private $_options = array(
+ self::OPTION_STRICT => true,
+ self::OPTION_USE_BRACKETS => true,
+ self::OPTION_DROP_SEQUENCE => true,
+ self::OPTION_ENCODE_KEYS => true,
+ self::OPTION_SEPARATOR_INPUT => '&',
+ self::OPTION_SEPARATOR_OUTPUT => '&',
+ );
+
+ /**
+ * @var string|bool
+ */
+ private $_scheme = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_userinfo = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_host = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_port = false;
+
+ /**
+ * @var string
+ */
+ private $_path = '';
+
+ /**
+ * @var string|bool
+ */
+ private $_query = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_fragment = false;
+
+ /**
+ * Constructor.
+ *
+ * @param string $url an absolute or relative URL
+ * @param array $options an array of OPTION_xxx constants
+ *
+ * @uses self::parseUrl()
+ */
+ public function __construct($url, array $options = array())
+ {
+ foreach ($options as $optionName => $value) {
+ if (array_key_exists($optionName, $this->_options)) {
+ $this->_options[$optionName] = $value;
+ }
+ }
+
+ $this->parseUrl($url);
+ }
+
+ /**
+ * Magic Setter.
+ *
+ * This method will magically set the value of a private variable ($var)
+ * with the value passed as the args
+ *
+ * @param string $var The private variable to set.
+ * @param mixed $arg An argument of any type.
+ *
+ * @return void
+ */
+ public function __set($var, $arg)
+ {
+ $method = 'set' . $var;
+ if (method_exists($this, $method)) {
+ $this->$method($arg);
+ }
+ }
+
+ /**
+ * Magic Getter.
+ *
+ * This is the magic get method to retrieve the private variable
+ * that was set by either __set() or it's setter...
+ *
+ * @param string $var The property name to retrieve.
+ *
+ * @return mixed $this->$var Either a boolean false if the
+ * property is not set or the value
+ * of the private property.
+ */
+ public function __get($var)
+ {
+ $method = 'get' . $var;
+ if (method_exists($this, $method)) {
+ return $this->$method();
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the scheme, e.g. "http" or "urn", or false if there is no
+ * scheme specified, i.e. if this is a relative URL.
+ *
+ * @return string|bool
+ */
+ public function getScheme()
+ {
+ return $this->_scheme;
+ }
+
+ /**
+ * Sets the scheme, e.g. "http" or "urn". Specify false if there is no
+ * scheme specified, i.e. if this is a relative URL.
+ *
+ * @param string|bool $scheme e.g. "http" or "urn", or false if there is no
+ * scheme specified, i.e. if this is a relative
+ * URL
+ *
+ * @return $this
+ * @see getScheme
+ */
+ public function setScheme($scheme)
+ {
+ $this->_scheme = $scheme;
+ return $this;
+ }
+
+ /**
+ * Returns the user part of the userinfo part (the part preceding the first
+ * ":"), or false if there is no userinfo part.
+ *
+ * @return string|bool
+ */
+ public function getUser()
+ {
+ return $this->_userinfo !== false
+ ? preg_replace('(:.*$)', '', $this->_userinfo)
+ : false;
+ }
+
+ /**
+ * Returns the password part of the userinfo part (the part after the first
+ * ":"), or false if there is no userinfo part (i.e. the URL does not
+ * contain "@" in front of the hostname) or the userinfo part does not
+ * contain ":".
+ *
+ * @return string|bool
+ */
+ public function getPassword()
+ {
+ return $this->_userinfo !== false
+ ? substr(strstr($this->_userinfo, ':'), 1)
+ : false;
+ }
+
+ /**
+ * Returns the userinfo part, or false if there is none, i.e. if the
+ * authority part does not contain "@".
+ *
+ * @return string|bool
+ */
+ public function getUserinfo()
+ {
+ return $this->_userinfo;
+ }
+
+ /**
+ * Sets the userinfo part. If two arguments are passed, they are combined
+ * in the userinfo part as username ":" password.
+ *
+ * @param string|bool $userinfo userinfo or username
+ * @param string|bool $password optional password, or false
+ *
+ * @return $this
+ */
+ public function setUserinfo($userinfo, $password = false)
+ {
+ if ($password !== false) {
+ $userinfo .= ':' . $password;
+ }
+
+ if ($userinfo !== false) {
+ $userinfo = $this->_encodeData($userinfo);
+ }
+
+ $this->_userinfo = $userinfo;
+ return $this;
+ }
+
+ /**
+ * Returns the host part, or false if there is no authority part, e.g.
+ * relative URLs.
+ *
+ * @return string|bool a hostname, an IP address, or false
+ */
+ public function getHost()
+ {
+ return $this->_host;
+ }
+
+ /**
+ * Sets the host part. Specify false if there is no authority part, e.g.
+ * relative URLs.
+ *
+ * @param string|bool $host a hostname, an IP address, or false
+ *
+ * @return $this
+ */
+ public function setHost($host)
+ {
+ $this->_host = $host;
+ return $this;
+ }
+
+ /**
+ * Returns the port number, or false if there is no port number specified,
+ * i.e. if the default port is to be used.
+ *
+ * @return string|bool
+ */
+ public function getPort()
+ {
+ return $this->_port;
+ }
+
+ /**
+ * Sets the port number. Specify false if there is no port number specified,
+ * i.e. if the default port is to be used.
+ *
+ * @param string|bool $port a port number, or false
+ *
+ * @return $this
+ */
+ public function setPort($port)
+ {
+ $this->_port = $port;
+ return $this;
+ }
+
+ /**
+ * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or
+ * false if there is no authority.
+ *
+ * @return string|bool
+ */
+ public function getAuthority()
+ {
+ if (false === $this->_host) {
+ return false;
+ }
+
+ $authority = '';
+
+ if (strlen($this->_userinfo)) {
+ $authority .= $this->_userinfo . '@';
+ }
+
+ $authority .= $this->_host;
+
+ if ($this->_port !== false) {
+ $authority .= ':' . $this->_port;
+ }
+
+ return $authority;
+ }
+
+ /**
+ * Sets the authority part, i.e. [ userinfo "@" ] host [ ":" port ]. Specify
+ * false if there is no authority.
+ *
+ * @param string|bool $authority a hostname or an IP address, possibly
+ * with userinfo prefixed and port number
+ * appended, e.g. "foo:bar@example.org:81".
+ *
+ * @return $this
+ */
+ public function setAuthority($authority)
+ {
+ $this->_userinfo = false;
+ $this->_host = false;
+ $this->_port = false;
+
+ if ('' === $authority) {
+ $this->_host = $authority;
+ return $this;
+ }
+
+ if (!preg_match('(^(([^\@]*)\@)?(.+?)(:(\d*))?$)', $authority, $matches)) {
+ return $this;
+ }
+
+ if ($matches[1]) {
+ $this->_userinfo = $this->_encodeData($matches[2]);
+ }
+
+ $this->_host = $matches[3];
+
+ if (isset($matches[5]) && strlen($matches[5])) {
+ $this->_port = $matches[5];
+ }
+ return $this;
+ }
+
+ /**
+ * Returns the path part (possibly an empty string).
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->_path;
+ }
+
+ /**
+ * Sets the path part (possibly an empty string).
+ *
+ * @param string $path a path
+ *
+ * @return $this
+ */
+ public function setPath($path)
+ {
+ $this->_path = $path;
+ return $this;
+ }
+
+ /**
+ * Returns the query string (excluding the leading "?"), or false if "?"
+ * is not present in the URL.
+ *
+ * @return string|bool
+ * @see getQueryVariables
+ */
+ public function getQuery()
+ {
+ return $this->_query;
+ }
+
+ /**
+ * Sets the query string (excluding the leading "?"). Specify false if "?"
+ * is not present in the URL.
+ *
+ * @param string|bool $query a query string, e.g. "foo=1&bar=2"
+ *
+ * @return $this
+ * @see setQueryVariables
+ */
+ public function setQuery($query)
+ {
+ $this->_query = $query;
+ return $this;
+ }
+
+ /**
+ * Returns the fragment name, or false if "#" is not present in the URL.
+ *
+ * @return string|bool
+ */
+ public function getFragment()
+ {
+ return $this->_fragment;
+ }
+
+ /**
+ * Sets the fragment name. Specify false if "#" is not present in the URL.
+ *
+ * @param string|bool $fragment a fragment excluding the leading "#", or
+ * false
+ *
+ * @return $this
+ */
+ public function setFragment($fragment)
+ {
+ $this->_fragment = $fragment;
+ return $this;
+ }
+
+ /**
+ * Returns the query string like an array as the variables would appear in
+ * $_GET in a PHP script. If the URL does not contain a "?", an empty array
+ * is returned.
+ *
+ * @return array
+ */
+ public function getQueryVariables()
+ {
+ $separator = $this->getOption(self::OPTION_SEPARATOR_INPUT);
+ $encodeKeys = $this->getOption(self::OPTION_ENCODE_KEYS);
+ $useBrackets = $this->getOption(self::OPTION_USE_BRACKETS);
+
+ $return = array();
+
+ for ($part = strtok($this->_query, $separator);
+ strlen($part);
+ $part = strtok($separator)
+ ) {
+ list($key, $value) = explode('=', $part, 2) + array(1 => '');
+
+ if ($encodeKeys) {
+ $key = rawurldecode($key);
+ }
+ $value = rawurldecode($value);
+
+ if ($useBrackets) {
+ $return = $this->_queryArrayByKey($key, $value, $return);
+ } else {
+ if (isset($return[$key])) {
+ $return[$key] = (array) $return[$key];
+ $return[$key][] = $value;
+ } else {
+ $return[$key] = $value;
+ }
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Parse a single query key=value pair into an existing php array
+ *
+ * @param string $key query-key
+ * @param string $value query-value
+ * @param array $array of existing query variables (if any)
+ *
+ * @return mixed
+ */
+ private function _queryArrayByKey($key, $value, array $array = array())
+ {
+ if (!strlen($key)) {
+ return $array;
+ }
+
+ $offset = $this->_queryKeyBracketOffset($key);
+ if ($offset === false) {
+ $name = $key;
+ } else {
+ $name = substr($key, 0, $offset);
+ }
+
+ if (!strlen($name)) {
+ return $array;
+ }
+
+ if (!$offset) {
+ // named value
+ $array[$name] = $value;
+ } else {
+ // array
+ $brackets = substr($key, $offset);
+ if (!isset($array[$name])) {
+ $array[$name] = null;
+ }
+ $array[$name] = $this->_queryArrayByBrackets(
+ $brackets, $value, $array[$name]
+ );
+ }
+
+ return $array;
+ }
+
+ /**
+ * Parse a key-buffer to place value in array
+ *
+ * @param string $buffer to consume all keys from
+ * @param string $value to be set/add
+ * @param array $array to traverse and set/add value in
+ *
+ * @throws Exception
+ * @return array
+ */
+ private function _queryArrayByBrackets($buffer, $value, array $array = null)
+ {
+ $entry = &$array;
+
+ for ($iteration = 0; strlen($buffer); $iteration++) {
+ $open = $this->_queryKeyBracketOffset($buffer);
+ if ($open !== 0) {
+ // Opening bracket [ must exist at offset 0, if not, there is
+ // no bracket to parse and the value dropped.
+ // if this happens in the first iteration, this is flawed, see
+ // as well the second exception below.
+ if ($iteration) {
+ break;
+ }
+ // @codeCoverageIgnoreStart
+ throw new Exception(
+ 'Net_URL2 Internal Error: '. __METHOD__ .'(): ' .
+ 'Opening bracket [ must exist at offset 0'
+ );
+ // @codeCoverageIgnoreEnd
+ }
+
+ $close = strpos($buffer, ']', 1);
+ if (!$close) {
+ // this error condition should never be reached as this is a
+ // private method and bracket pairs are checked beforehand.
+ // See as well the first exception for the opening bracket.
+ // @codeCoverageIgnoreStart
+ throw new Exception(
+ 'Net_URL2 Internal Error: '. __METHOD__ .'(): ' .
+ 'Closing bracket ] must exist, not found'
+ );
+ // @codeCoverageIgnoreEnd
+ }
+
+ $index = substr($buffer, 1, $close - 1);
+ if (strlen($index)) {
+ $entry = &$entry[$index];
+ } else {
+ if (!is_array($entry)) {
+ $entry = array();
+ }
+ $entry[] = &$new;
+ $entry = &$new;
+ unset($new);
+ }
+ $buffer = substr($buffer, $close + 1);
+ }
+
+ $entry = $value;
+
+ return $array;
+ }
+
+ /**
+ * Query-key has brackets ("...[]")
+ *
+ * @param string $key query-key
+ *
+ * @return bool|int offset of opening bracket, false if no brackets
+ */
+ private function _queryKeyBracketOffset($key)
+ {
+ if (false !== $open = strpos($key, '[')
+ and false === strpos($key, ']', $open + 1)
+ ) {
+ $open = false;
+ }
+
+ return $open;
+ }
+
+ /**
+ * Sets the query string to the specified variable in the query string.
+ *
+ * @param array $array (name => value) array
+ *
+ * @return $this
+ */
+ public function setQueryVariables(array $array)
+ {
+ if (!$array) {
+ $this->_query = false;
+ } else {
+ $this->_query = $this->buildQuery(
+ $array,
+ $this->getOption(self::OPTION_SEPARATOR_OUTPUT)
+ );
+ }
+ return $this;
+ }
+
+ /**
+ * Sets the specified variable in the query string.
+ *
+ * @param string $name variable name
+ * @param mixed $value variable value
+ *
+ * @return $this
+ */
+ public function setQueryVariable($name, $value)
+ {
+ $array = $this->getQueryVariables();
+ $array[$name] = $value;
+ $this->setQueryVariables($array);
+ return $this;
+ }
+
+ /**
+ * Removes the specified variable from the query string.
+ *
+ * @param string $name a query string variable, e.g. "foo" in "?foo=1"
+ *
+ * @return void
+ */
+ public function unsetQueryVariable($name)
+ {
+ $array = $this->getQueryVariables();
+ unset($array[$name]);
+ $this->setQueryVariables($array);
+ }
+
+ /**
+ * Returns a string representation of this URL.
+ *
+ * @return string
+ */
+ public function getURL()
+ {
+ // See RFC 3986, section 5.3
+ $url = '';
+
+ if ($this->_scheme !== false) {
+ $url .= $this->_scheme . ':';
+ }
+
+ $authority = $this->getAuthority();
+ if ($authority === false && strtolower($this->_scheme) === 'file') {
+ $authority = '';
+ }
+
+ $url .= $this->_buildAuthorityAndPath($authority, $this->_path);
+
+ if ($this->_query !== false) {
+ $url .= '?' . $this->_query;
+ }
+
+ if ($this->_fragment !== false) {
+ $url .= '#' . $this->_fragment;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Put authority and path together, wrapping authority
+ * into proper separators/terminators.
+ *
+ * @param string|bool $authority authority
+ * @param string $path path
+ *
+ * @return string
+ */
+ private function _buildAuthorityAndPath($authority, $path)
+ {
+ if ($authority === false) {
+ return $path;
+ }
+
+ $terminator = ($path !== '' && $path[0] !== '/') ? '/' : '';
+
+ return '//' . $authority . $terminator . $path;
+ }
+
+ /**
+ * Returns a string representation of this URL.
+ *
+ * @return string
+ * @link https://php.net/language.oop5.magic#object.tostring
+ */
+ public function __toString()
+ {
+ return $this->getURL();
+ }
+
+ /**
+ * Returns a normalized string representation of this URL. This is useful
+ * for comparison of URLs.
+ *
+ * @return string
+ */
+ public function getNormalizedURL()
+ {
+ $url = clone $this;
+ $url->normalize();
+ return $url->getUrl();
+ }
+
+ /**
+ * Normalizes the URL
+ *
+ * See RFC 3986, Section 6. Normalization and Comparison
+ *
+ * @link https://tools.ietf.org/html/rfc3986#section-6
+ *
+ * @return void
+ */
+ public function normalize()
+ {
+ // See RFC 3986, section 6
+
+ // Scheme is case-insensitive
+ if ($this->_scheme) {
+ $this->_scheme = strtolower($this->_scheme);
+ }
+
+ // Hostname is case-insensitive
+ if ($this->_host) {
+ $this->_host = strtolower($this->_host);
+ }
+
+ // Remove default port number for known schemes (RFC 3986, section 6.2.3)
+ if ('' === $this->_port
+ || $this->_port
+ && $this->_scheme
+ && $this->_port == getservbyname($this->_scheme, 'tcp')
+ ) {
+ $this->_port = false;
+ }
+
+ // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1)
+ // Normalize percentage-encoded unreserved characters (section 6.2.2.2)
+ $fields = array(&$this->_userinfo, &$this->_host, &$this->_path,
+ &$this->_query, &$this->_fragment);
+ foreach ($fields as &$field) {
+ if ($field !== false) {
+ $field = $this->_normalize("$field");
+ }
+ }
+ unset($field);
+
+ // Path segment normalization (RFC 3986, section 6.2.2.3)
+ $this->_path = self::removeDotSegments($this->_path);
+
+ // Scheme based normalization (RFC 3986, section 6.2.3)
+ if (false !== $this->_host && '' === $this->_path) {
+ $this->_path = '/';
+ }
+
+ // path should start with '/' if there is authority (section 3.3.)
+ if (strlen($this->getAuthority())
+ && strlen($this->_path)
+ && $this->_path[0] !== '/'
+ ) {
+ $this->_path = '/' . $this->_path;
+ }
+ }
+
+ /**
+ * Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1)
+ * Normalize percentage-encoded unreserved characters (section 6.2.2.2)
+ *
+ * @param string|array $mixed string or array of strings to normalize
+ *
+ * @return string|array
+ * @see normalize
+ * @see _normalizeCallback()
+ */
+ private function _normalize($mixed)
+ {
+ return preg_replace_callback(
+ '((?:%[0-9a-fA-Z]{2})+)', array($this, '_normalizeCallback'),
+ $mixed
+ );
+ }
+
+ /**
+ * Callback for _normalize() of %XX percentage-encodings
+ *
+ * @param array $matches as by preg_replace_callback
+ *
+ * @return string
+ * @see normalize
+ * @see _normalize
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ */
+ private function _normalizeCallback($matches)
+ {
+ return self::urlencode(urldecode($matches[0]));
+ }
+
+ /**
+ * Returns whether this instance represents an absolute URL.
+ *
+ * @return bool
+ */
+ public function isAbsolute()
+ {
+ return (bool) $this->_scheme;
+ }
+
+ /**
+ * Returns an Net_URL2 instance representing an absolute URL relative to
+ * this URL.
+ *
+ * @param Net_URL2|string $reference relative URL
+ *
+ * @throws Exception
+ * @return $this
+ */
+ public function resolve($reference)
+ {
+ if (!$reference instanceof Net_URL2) {
+ $reference = new self($reference);
+ }
+ if (!$reference->_isFragmentOnly() && !$this->isAbsolute()) {
+ throw new Exception(
+ 'Base-URL must be absolute if reference is not fragment-only'
+ );
+ }
+
+ // A non-strict parser may ignore a scheme in the reference if it is
+ // identical to the base URI's scheme.
+ if (!$this->getOption(self::OPTION_STRICT)
+ && $reference->_scheme == $this->_scheme
+ ) {
+ $reference->_scheme = false;
+ }
+
+ $target = new self('');
+ if ($reference->_scheme !== false) {
+ $target->_scheme = $reference->_scheme;
+ $target->setAuthority($reference->getAuthority());
+ $target->_path = self::removeDotSegments($reference->_path);
+ $target->_query = $reference->_query;
+ } else {
+ $authority = $reference->getAuthority();
+ if ($authority !== false) {
+ $target->setAuthority($authority);
+ $target->_path = self::removeDotSegments($reference->_path);
+ $target->_query = $reference->_query;
+ } else {
+ if ($reference->_path == '') {
+ $target->_path = $this->_path;
+ if ($reference->_query !== false) {
+ $target->_query = $reference->_query;
+ } else {
+ $target->_query = $this->_query;
+ }
+ } else {
+ if (substr($reference->_path, 0, 1) == '/') {
+ $target->_path = self::removeDotSegments($reference->_path);
+ } else {
+ // Merge paths (RFC 3986, section 5.2.3)
+ if ($this->_host !== false && $this->_path == '') {
+ $target->_path = '/' . $reference->_path;
+ } else {
+ $i = strrpos($this->_path, '/');
+ if ($i !== false) {
+ $target->_path = substr($this->_path, 0, $i + 1);
+ }
+ $target->_path .= $reference->_path;
+ }
+ $target->_path = self::removeDotSegments($target->_path);
+ }
+ $target->_query = $reference->_query;
+ }
+ $target->setAuthority($this->getAuthority());
+ }
+ $target->_scheme = $this->_scheme;
+ }
+
+ $target->_fragment = $reference->_fragment;
+
+ return $target;
+ }
+
+ /**
+ * URL is fragment-only
+ *
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ * @return bool
+ */
+ private function _isFragmentOnly()
+ {
+ return (
+ $this->_fragment !== false
+ && $this->_query === false
+ && $this->_path === ''
+ && $this->_port === false
+ && $this->_host === false
+ && $this->_userinfo === false
+ && $this->_scheme === false
+ );
+ }
+
+ /**
+ * Removes dots as described in RFC 3986, section 5.2.4, e.g.
+ * "/foo/../bar/baz" => "/bar/baz"
+ *
+ * @param string $path a path
+ *
+ * @return string a path
+ */
+ public static function removeDotSegments($path)
+ {
+ $path = (string) $path;
+ $output = '';
+
+ // Make sure not to be trapped in an infinite loop due to a bug in this
+ // method
+ $loopLimit = 256;
+ $j = 0;
+ while ('' !== $path && $j++ < $loopLimit) {
+ if (substr($path, 0, 2) === './') {
+ // Step 2.A
+ $path = substr($path, 2);
+ } elseif (substr($path, 0, 3) === '../') {
+ // Step 2.A
+ $path = substr($path, 3);
+ } elseif (substr($path, 0, 3) === '/./' || $path === '/.') {
+ // Step 2.B
+ $path = '/' . substr($path, 3);
+ } elseif (substr($path, 0, 4) === '/../' || $path === '/..') {
+ // Step 2.C
+ $path = '/' . substr($path, 4);
+ $i = strrpos($output, '/');
+ $output = $i === false ? '' : substr($output, 0, $i);
+ } elseif ($path === '.' || $path === '..') {
+ // Step 2.D
+ $path = '';
+ } else {
+ // Step 2.E
+ $i = strpos($path, '/', $path[0] === '/');
+ if ($i === false) {
+ $output .= $path;
+ $path = '';
+ break;
+ }
+ $output .= substr($path, 0, $i);
+ $path = substr($path, $i);
+ }
+ }
+
+ if ($path !== '') {
+ $message = sprintf(
+ 'Unable to remove dot segments; hit loop limit %d (left: %s)',
+ $j, var_export($path, true)
+ );
+ trigger_error($message, E_USER_WARNING);
+ }
+
+ return $output;
+ }
+
+ /**
+ * Percent-encodes all non-alphanumeric characters except these: _ . - ~
+ * Similar to PHP's rawurlencode(), except that it also encodes ~ in PHP
+ * 5.2.x and earlier.
+ *
+ * @param string $string string to encode
+ *
+ * @return string
+ */
+ public static function urlencode($string)
+ {
+ $encoded = rawurlencode($string);
+
+ // This is only necessary in PHP < 5.3.
+ $encoded = str_replace('%7E', '~', $encoded);
+ return $encoded;
+ }
+
+ /**
+ * Returns a Net_URL2 instance representing the canonical URL of the
+ * currently executing PHP script.
+ *
+ * @throws Exception
+ * @return string
+ */
+ public static function getCanonical()
+ {
+ if (!isset($_SERVER['REQUEST_METHOD'])) {
+ // ALERT - no current URL
+ throw new Exception('Script was not called through a webserver');
+ }
+
+ // Begin with a relative URL
+ $url = new self($_SERVER['PHP_SELF']);
+ $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
+ $url->_host = $_SERVER['SERVER_NAME'];
+ $port = $_SERVER['SERVER_PORT'];
+ if ($url->_scheme == 'http' && $port != 80
+ || $url->_scheme == 'https' && $port != 443
+ ) {
+ $url->_port = $port;
+ }
+ return $url;
+ }
+
+ /**
+ * Returns the URL used to retrieve the current request.
+ *
+ * @return string
+ */
+ public static function getRequestedURL()
+ {
+ return self::getRequested()->getUrl();
+ }
+
+ /**
+ * Returns a Net_URL2 instance representing the URL used to retrieve the
+ * current request.
+ *
+ * @throws Exception
+ * @return $this
+ */
+ public static function getRequested()
+ {
+ if (!isset($_SERVER['REQUEST_METHOD'])) {
+ // ALERT - no current URL
+ throw new Exception('Script was not called through a webserver');
+ }
+
+ // Begin with a relative URL
+ $url = new self($_SERVER['REQUEST_URI']);
+ $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
+ // Set host and possibly port
+ $url->setAuthority($_SERVER['HTTP_HOST']);
+ return $url;
+ }
+
+ /**
+ * Returns the value of the specified option.
+ *
+ * @param string $optionName The name of the option to retrieve
+ *
+ * @return mixed
+ */
+ public function getOption($optionName)
+ {
+ return isset($this->_options[$optionName])
+ ? $this->_options[$optionName] : false;
+ }
+
+ /**
+ * A simple version of http_build_query in userland. The encoded string is
+ * percentage encoded according to RFC 3986.
+ *
+ * @param array $data An array, which has to be converted into
+ * QUERY_STRING. Anything is possible.
+ * @param string $separator Separator {@link self::OPTION_SEPARATOR_OUTPUT}
+ * @param string $key For stacked values (arrays in an array).
+ *
+ * @return string
+ */
+ protected function buildQuery(array $data, $separator, $key = null)
+ {
+ $query = array();
+ $drop_names = (
+ $this->_options[self::OPTION_DROP_SEQUENCE] === true
+ && array_keys($data) === array_keys(array_values($data))
+ );
+ foreach ($data as $name => $value) {
+ if ($this->getOption(self::OPTION_ENCODE_KEYS) === true) {
+ $name = rawurlencode($name);
+ }
+ if ($key !== null) {
+ if ($this->getOption(self::OPTION_USE_BRACKETS) === true) {
+ $drop_names && $name = '';
+ $name = $key . '[' . $name . ']';
+ } else {
+ $name = $key;
+ }
+ }
+ if (is_array($value)) {
+ $query[] = $this->buildQuery($value, $separator, $name);
+ } else {
+ $query[] = $name . '=' . rawurlencode($value);
+ }
+ }
+ return implode($separator, $query);
+ }
+
+ /**
+ * This method uses a regex to parse the url into the designated parts.
+ *
+ * @param string $url URL
+ *
+ * @return void
+ * @uses self::$_scheme, self::setAuthority(), self::$_path, self::$_query,
+ * self::$_fragment
+ * @see __construct
+ */
+ protected function parseUrl($url)
+ {
+ // The regular expression is copied verbatim from RFC 3986, appendix B.
+ // The expression does not validate the URL but matches any string.
+ preg_match(
+ '(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)',
+ $url, $matches
+ );
+
+ // "path" is always present (possibly as an empty string); the rest
+ // are optional.
+ $this->_scheme = !empty($matches[1]) ? $matches[2] : false;
+ $this->setAuthority(!empty($matches[3]) ? $matches[4] : false);
+ $this->_path = $this->_encodeData($matches[5]);
+ $this->_query = !empty($matches[6])
+ ? $this->_encodeData($matches[7])
+ : false
+ ;
+ $this->_fragment = !empty($matches[8]) ? $matches[9] : false;
+ }
+
+ /**
+ * Encode characters that might have been forgotten to encode when passing
+ * in an URL. Applied onto Userinfo, Path and Query.
+ *
+ * @param string $url URL
+ *
+ * @return string
+ * @see parseUrl
+ * @see setAuthority
+ * @link https://pear.php.net/bugs/bug.php?id=20425
+ */
+ private function _encodeData($url)
+ {
+ return preg_replace_callback(
+ '([\x-\x20\x22\x3C\x3E\x7F-\xFF]+)',
+ array($this, '_encodeCallback'), $url
+ );
+ }
+
+ /**
+ * callback for encoding character data
+ *
+ * @param array $matches Matches
+ *
+ * @return string
+ * @see _encodeData
+ * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+ */
+ private function _encodeCallback(array $matches)
+ {
+ return rawurlencode($matches[0]);
+ }
+}
diff --git a/vendor/pear/net_url2/README.md b/vendor/pear/net_url2/README.md
new file mode 100644
index 000000000..bc98d3aec
--- /dev/null
+++ b/vendor/pear/net_url2/README.md
@@ -0,0 +1,43 @@
+[![Net_URL2 on Packagist](https://poser.pugx.org/pear/net_url2/v/stable.png)][pear/net_url2]
+[![Build Status](https://travis-ci.org/pear/Net_URL2.png)][Travis CI]
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/pear/Net_URL2/badges/quality-score.png?s=23b0d3f0ed58ee865317c500ee2cbe94517438ec)](https://scrutinizer-ci.com/g/pear/Net_URL2/)
+[![Code Coverage](https://scrutinizer-ci.com/g/pear/Net_URL2/badges/coverage.png?s=44d3682d7cdef471570d80dd8a7290a1e23fdfee)](https://scrutinizer-ci.com/g/pear/Net_URL2/)
+
+# Net_URL2
+
+Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.),
+URL generation, and resolving of relative URLs.
+
+This package is [Pear Net_URL2] and has been migrated from [Pear SVN]
+
+Please report all new issues via the [PEAR bug tracker].
+
+On Packagist as [pear/net_url2].
+
+[Pear Net_URL2]: https://pear.php.net/package/Net_URL2
+[Pear SVN]: https://svn.php.net/repository/pear/packages/Net_URL2
+[PEAR bug tracker]: https://pear.php.net/bugs/search.php?cmd=display&package_name%5B%5D=Net_URL2
+[pear/net_url2]: https://packagist.org/packages/pear/net_url2
+[Travis CI]: https://travis-ci.org/pear/Net_URL2
+
+## Testing, Packaging and Installing (Pear)
+
+To test, run either
+
+ $ phpunit tests/
+
+ or
+
+ $ pear run-tests -r
+
+To build, simply
+
+ $ pear package
+
+To install from scratch
+
+ $ pear install package.xml
+
+To upgrade
+
+ $ pear upgrade -f package.xml
diff --git a/vendor/pear/net_url2/composer.json b/vendor/pear/net_url2/composer.json
new file mode 100644
index 000000000..b33698e5d
--- /dev/null
+++ b/vendor/pear/net_url2/composer.json
@@ -0,0 +1,47 @@
+{
+ "name": "pear/net_url2",
+ "description": "Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of relative URLs.",
+ "type": "library",
+ "keywords": [
+ "pear",
+ "net",
+ "url",
+ "uri",
+ "networking",
+ "rfc3986"
+ ],
+ "homepage": "https://github.com/pear/Net_URL2",
+ "license": "BSD-3-Clause",
+ "authors": [
+ {
+ "name": "Tom Klingenberg",
+ "email": "tkli@php.net"
+ },
+ {
+ "name": "David Coallier",
+ "email": "davidc@php.net"
+ },
+ {
+ "name": "Christian Schmidt",
+ "email": "chmidt@php.net"
+ }
+ ],
+ "support": {
+ "issues": "https://pear.php.net/bugs/search.php?cmd=display&package_name[]=Net_URL2",
+ "source": "https://github.com/pear/Net_URL2"
+ },
+ "require": {
+ "php": ">=5.1.4"
+ },
+ "autoload": {
+ "classmap": ["Net/URL2.php"]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2.x-dev"
+ }
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">=3.3.0"
+ }
+}
diff --git a/vendor/pear/net_url2/docs/6470.php b/vendor/pear/net_url2/docs/6470.php
new file mode 100755
index 000000000..8ef0ff046
--- /dev/null
+++ b/vendor/pear/net_url2/docs/6470.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Net_URL2, a class representing a URL as per RFC 3986.
+ *
+ * PHP version 5
+ *
+ * This file contains code Copyright (c) 2002-2003, Richard Heyes,
+ * See BSD-3-CLAUSE-Heyes,
+ * Author: Richard Heyes <richard at php net>
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Some Pear Developers <pear@php.net>
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @link https://tools.ietf.org/html/rfc3986
+ */
+
+/**
+* This example will decode the url given and display its
+* constituent parts.
+*/
+ error_reporting(E_ALL | E_STRICT);
+
+ require_once 'Net/URL2.php';
+
+ $url = new Net_URL2('https://www.example.com/foo/bar/index.php?foo=bar');
+
+?>
+<html>
+<body>
+
+<pre>
+Protocol...: <?php echo $url->protocol; ?>
+
+Username...: <?php echo $url->user; ?>
+
+Password...: <?php echo $url->pass; ?>
+
+Server.....: <?php echo $url->host; ?>
+
+Port.......: <?php $url->port; ?>
+
+File/path..: <?php $url->path; ?>
+
+Querystring: <?php print_r($url->querystring); ?>
+
+Anchor.....: <?php echo $url->anchor;?>
+
+Full URL...: <?php echo $url->getUrl(); ?>
+
+Resolve path (/.././/foo/bar/joe/./././../jabba): <b><?php
+ echo $url->resolve('/.././/foo/bar/joe/./././../jabba'); ?></b>
+</pre>
+
+</body>
+</html>
diff --git a/vendor/pear/net_url2/docs/BSD-3-CLAUSE-Heyes b/vendor/pear/net_url2/docs/BSD-3-CLAUSE-Heyes
new file mode 100644
index 000000000..b45ca8e94
--- /dev/null
+++ b/vendor/pear/net_url2/docs/BSD-3-CLAUSE-Heyes
@@ -0,0 +1,27 @@
+Copyright (c) 2002-2003, Richard Heyes
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3) Neither the name of the Richard Heyes nor the names of his
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/pear/net_url2/docs/example.php b/vendor/pear/net_url2/docs/example.php
new file mode 100755
index 000000000..351be68b8
--- /dev/null
+++ b/vendor/pear/net_url2/docs/example.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Net_URL2, a class representing a URL as per RFC 3986.
+ *
+ * PHP version 5
+ *
+ * This file contains code Copyright (c) 2002-2003, Richard Heyes,
+ * See BSD-3-CLAUSE-Heyes,
+ * Author: Richard Heyes <richard at php net>
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Some Pear Developers <pear@php.net>
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @link https://tools.ietf.org/html/rfc3986
+ */
+
+/**
+* This example will decode the url given and display its
+* constituent parts.
+*/
+
+error_reporting(E_ALL | E_STRICT);
+
+require 'Net/URL2.php';
+
+$url = new Net_URL2(
+ 'https://example.com/pls/portal30/PORTAL30.wwpob_page.changetabs?'
+ .'p_back_url=http%3A%2F%2Fexample.com%2Fservlet%2Fpage%3F_pageid%3D360'
+ .'%2C366%2C368%2C382%26_dad%3Dportal30%26_schema%3DPORTAL30&foo=bar'
+);
+
+?>
+<html>
+<body>
+
+<pre>
+Protocol...: <?php echo $url->protocol; ?>
+
+Username...: <?php echo $url->user; ?>
+
+Password...: <?php echo $url->pass; ?>
+
+Server.....: <?php echo $url->host; ?>
+
+Port.......: <?php $url->port; ?>
+
+File/path..: <?php $url->path; ?>
+
+Querystring: <?php print_r($url->querystring); ?>
+
+Anchor.....: <?php echo $url->anchor;?>
+
+Full URL...: <?php echo $url->getUrl(); ?>
+
+
+Resolve path (.././/foo/bar/joe/./././../jabba): <b><?php
+ echo $url->resolve('.././/foo/bar/joe/./././../jabba'); ?></b>
+</pre>
+
+</body>
+</html>
diff --git a/vendor/pear/net_url2/package.xml b/vendor/pear/net_url2/package.xml
new file mode 100644
index 000000000..7f0b42ae4
--- /dev/null
+++ b/vendor/pear/net_url2/package.xml
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.5.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
+ xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Net_URL2</name>
+ <channel>pear.php.net</channel>
+ <extends>Net_URL</extends>
+ <summary>Class for parsing and handling URL.</summary>
+ <description>
+ Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of
+ relative URLs.
+ </description>
+ <lead>
+ <name>Tom Klingenberg</name>
+ <user>tkli</user>
+ <email>tkli@php.net</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>David Coallier</name>
+ <user>davidc</user>
+ <email>davidc@php.net</email>
+ <active>no</active>
+ </lead>
+ <lead>
+ <name>Christian Schmidt</name>
+ <user>schmidt</user>
+ <email>schmidt@php.net</email>
+ <active>no</active>
+ </lead>
+
+ <date>2015-04-18</date>
+ <time>19:00:00</time>
+ <version>
+ <release>2.2.0</release>
+ <api>2.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Changed composer autoloader to classmap, fixes include path pollution
+ </notes>
+
+ <contents>
+ <dir name="/">
+ <dir name="docs">
+ <file baseinstalldir="Net" name="example.php" role="doc" />
+ <file baseinstalldir="Net" name="6470.php" role="doc" />
+ <file baseinstalldir="Net" name="BSD-3-CLAUSE-Heyes" role="doc" />
+ </dir>
+ <!-- //docs -->
+ <dir name="tests">
+ <file name="AllTests.php" role="test" />
+ <dir name="Net">
+ <file name="URL2Test.php" role="test">
+ <tasks:replace type="package-info" to="version" from="@package_version@" />
+ </file>
+ </dir>
+ </dir>
+ <dir name="Net">
+ <file name="URL2.php" role="php">
+ <tasks:replace type="package-info" to="version" from="@package_version@" />
+ </file>
+ </dir>
+ </dir>
+ <!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.1.4</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.0b1</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <phprelease />
+ <changelog>
+ <release>
+ <date>2015-04-18</date>
+ <time>19:00:00</time>
+ <version>
+ <release>2.2.0</release>
+ <api>2.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Changed composer autoloader to classmap, fixes include path pollution
+ </notes>
+ </release>
+ <release>
+ <date>2014-12-27</date>
+ <time>14:00:00</time>
+ <version>
+ <release>2.1.1</release>
+ <api>2.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20473: Normalize query and fragment broken
+ </notes>
+ </release>
+ <release>
+ <date>2014-10-21</date>
+ <time>18:09:00</time>
+ <version>
+ <release>2.1.0</release>
+ <api>2.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * New: OPTION_DROP_SEQUENCE
+ </notes>
+ </release>
+ <release>
+ <date>2014-10-21</date>
+ <time>18:06:00</time>
+ <version>
+ <release>2.0.12</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Removed: OPTION_DROP_SEQUENCE
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-10-18</date>
+ <time>08:39:00</time>
+ <version>
+ <release>2.0.11</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * New: OPTION_DROP_SEQUENCE
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-10-09</date>
+ <time>22:12:00</time>
+ <version>
+ <release>2.0.10</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Imp: composer for pear
+ * Fix: Documentation problem
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-10-08</date>
+ <time>15:52:00</time>
+ <version>
+ <release>2.0.9</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20418: Incorrect normalization of URI with missing authority
+ * Upd: Test for RFC 3986 Section 1.1.2 Examples
+ * Upd: Travis CI - PHP 5.6 added
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-10-07</date>
+ <time>23:25:00</time>
+ <version>
+ <release>2.0.8</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20420: Inconsistent setAuthority and getAuthority
+ * Fixed #20423: URI with IPv6 or IPvFuture not parsed
+ * Imp: Test for RFC 3986 Section 1.1.2 Examples
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-09-07</date>
+ <time>08:34:00</time>
+ <version>
+ <release>2.0.7</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20385: Incorrect normalization of userinfo
+ * Fixed #20399: Setting userinfo to FALSE not transparent
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-07-21</date>
+ <time>00:03:00</time>
+ <version>
+ <release>2.0.6</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20304: file:// URI gets crippled
+ </notes>
+ </release>
+
+ <release>
+ <date>2014-01-01</date>
+ <time>21:59:00</time>
+ <version>
+ <release>2.0.5</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #17036: Brackets broken for query variables
+ * Fixed diverse coding style violations and misc. minor issues
+ * Increased code coverage
+ </notes>
+ </release>
+
+ <release>
+ <date>2013-12-31</date>
+ <time>01:59:00</time>
+ <version>
+ <release>2.0.4</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20161: URLs with "0" as host fail to normalize with empty path
+ * A flaw in NetURL2::removeDotSegments() introduced in 2.0.1 has been fixed
+ * New: NetURL2::removeDotSegments() emits a warning on loop limit reach
+ * Url-segment maximum count raised from 100 to 256 (loop limit)
+ </notes>
+ </release>
+
+ <release>
+ <date>2013-12-30</date>
+ <time>01:32:00</time>
+ <version>
+ <release>2.0.3</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #20156: setAuthority() flaw with "0" as host
+ * Fixed #20157: normalize() flaw with "0" as path
+ * Fixed #20158: Fragment-only references are not resolved to non-absolute base URI
+ * Fixed #20159: Authority not terminated by slash
+ * Fixed diverse coding style violations and misc. minor issues
+ * Increased code coverage
+ * Added support for Scrutinizer CI
+ </notes>
+ </release>
+
+ <release>
+ <date>2013-12-27</date>
+ <time>19:16:00</time>
+ <version>
+ <release>2.0.2</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
+ <notes>
+ * Fixed #19684: Redirects containing spaces do not work
+ * Fixed diverse coding style violations and misc. minor issues
+ * Improved source package distribution
+ * Added support for Travis CI
+ </notes>
+ </release>
+
+ <release>
+ <date>2013-12-24</date>
+ <time>18:12:00</time>
+ <version>
+ <release>2.0.1</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license>BSD-3-Clause</license>
+ <notes>
+ * Fixed Bug #20013: getNormalizedURL() adds leading "@" chars in the Authority
+ * Fixed Bug #20016: Wrong data in 6d4f4dd "Package.xml preparation."
+ * Fixed Bug #19176: resolve() does not merge the path if the base path is empty
+ * Fixed Bug #19315: removeDotSegments("0") not working
+ </notes>
+ </release>
+
+ <release>
+ <date>2011-10-20</date>
+ <time>10:43:00</time>
+ <version>
+ <release>2.0.0</release>
+ <api>2.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license>BSD-3-Clause</license>
+ <notes>
+ * Fixed the version of the release. Follow the convention for Package2.
+ * Fixed Bug #18917: URL2.php moved to ./Net/Net (davidc)
+ </notes>
+ </release>
+
+ <release>
+ <version>
+ <release>1.0.0</release>
+ <api>1.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2011-10-20</date>
+ <license>BSD-3-Clause</license>
+ <notes>
+ * Fixed Bug #17036: Problem with parsed query string
+ * Fixed Bug #17087: setOption() function is gone
+ * Fixed #17166: Fluent Interface
+ * Fixed #17167: Refactor __construct
+ * Fixed Bug #18267: setQueryVariables() fails to encode array values
+ * Fixed Bug #14399: Fixed multiple bugs in Net_URL2 (Missing setOption value, unused properties, etc.)
+ </notes>
+ </release>
+
+ <release>
+ <version>
+ <release>0.3.1</release>
+ <api>0.3.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <date>2011-02-22</date>
+ <license>BSD-3-Clause</license>
+ <notes>
+ * BC break: Removed setOption() to avoid undefined behaviour (bug #16674)
+ * Fixed Bug #16854: Invalid package.xml making it impossible to install with Pyrus
+ * Fixed Bug #16651: Port may be an empty string
+ * Fixed Bug #16653: Don't make OPTION_SEPARATOR_(IN|OUT)PUT default to arg_separator.(in|out)put
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>0.3.0</release>
+ <api>0.3.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <date>2009-09-05</date>
+ <license>BSD-3-Clause</license>
+ <notes>
+ * Fixed #14399 (Errors in URL parsing (items #1 and #3))
+ * Fixed #14735 (Encode query string values)
+ * Fixed #15546 (Add adding __toString())
+ * Fixed #15367 (Use RFC 3986-compliant version of rawurlencode() in PHP &lt; 5.2)
+ * Fixed #14289 (Add __get() and __set())
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>0.2.0</release>
+ <api>0.2.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <date>2008-06-18</date>
+ <license>BSD-3-Clause</license>
+ <notes>
+ * Major rewrite to comply with RFC3986 (bug #11574).
+ * Much better support for resolving relative URLs.
+ * WARNING: Method and property names has changed to reflect the terminology used in the RFC - THIS RELEASE IS
+ NOT BACKWARDS COMPATIBLE WITH VERSION 0.1.0.
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>0.1.0</release>
+ <api>0.1.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <date>2007-05-08</date>
+ <license>BSD-3-Clause</license>
+ <notes>Convert to PHP5 only. PHP4 users should continue with version 1.0.15</notes>
+ </release>
+ </changelog>
+</package>
diff --git a/vendor/pear/net_url2/phpunit.xml.dist b/vendor/pear/net_url2/phpunit.xml.dist
new file mode 100644
index 000000000..2fee31891
--- /dev/null
+++ b/vendor/pear/net_url2/phpunit.xml.dist
@@ -0,0 +1,17 @@
+<phpunit bootstrap="Net/URL2.php"
+ colors="false"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ stopOnFailure="true">
+ <testsuites>
+ <testsuite name="Tests">
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <file>Net/URL2.php</file>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/vendor/pear/net_url2/tests/AllTests.php b/vendor/pear/net_url2/tests/AllTests.php
new file mode 100644
index 000000000..65492fe36
--- /dev/null
+++ b/vendor/pear/net_url2/tests/AllTests.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Net_URL2, a class representing a URL as per RFC 3986.
+ *
+ * PHP version 5
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Some Pear Developers <pear@php.net>
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @link https://tools.ietf.org/html/rfc3986
+ */
+
+require_once 'PHPUnit/Autoload.php';
+
+chdir(dirname(__FILE__) . '/../');
+
+require_once 'Net/URL2Test.php';
+require_once 'Net/URL2.php';
+
+/**
+ * Test class for Net_URL2.
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Some Pear Developers <pear@php.net>
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @version Release: @package_version@
+ * @link https://pear.php.net/package/Net_URL2
+ */
+class Net_URL2_AllTests
+{
+ /**
+ * main()
+ *
+ * @return void
+ */
+ public static function main()
+ {
+
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ /**
+ * suite()
+ *
+ * @return PHPUnit_Framework_TestSuite
+ */
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('Net_URL2 tests');
+ /** Add testsuites, if there is. */
+ $suite->addTestSuite('Net_URL2Test');
+
+ return $suite;
+ }
+}
+
+Net_URL2_AllTests::main();
diff --git a/vendor/pear/net_url2/tests/Net/URL2Test.php b/vendor/pear/net_url2/tests/Net/URL2Test.php
new file mode 100644
index 000000000..a17d0c5f6
--- /dev/null
+++ b/vendor/pear/net_url2/tests/Net/URL2Test.php
@@ -0,0 +1,1088 @@
+<?php
+/**
+ * Net_URL2, a class representing a URL as per RFC 3986.
+ *
+ * PHP version 5
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Some Pear Developers <pear@php.net>
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @link https://tools.ietf.org/html/rfc3986
+ */
+
+/**
+ * Test class for Net_URL2.
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Some Pear Developers <pear@php.net>
+ * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @version Release: @package_version@
+ * @link https://pear.php.net/package/Net_URL2
+ */
+class Net_URL2Test extends PHPUnit_Framework_TestCase
+{
+ /**
+ * Tests setting a zero-length string and false as authority
+ * Also: Regression test for Bug #20420
+ *
+ * @covers Net_URL2::setAuthority
+ * @return void
+ * @link https://pear.php.net/bugs/bug.php?id=20420
+ */
+ public function testSetEmptyAuthority()
+ {
+ $url = new Net_URL2('http://www.example.com/');
+ $url->setAuthority('');
+ $this->assertSame('', $url->getAuthority());
+ $this->assertSame('', $url->getHost());
+ $this->assertSame(false, $url->getPort());
+ $this->assertSame(false, $url->getUserinfo());
+ $this->assertSame(false, $url->getUser());
+
+ $url->setAuthority(false);
+ $this->assertSame(false, $url->getAuthority());
+ }
+
+ /**
+ * Tests setting an empty userinfo part
+ * Also: Regression test for Bug #20013 and Bug #20399
+ *
+ * @covers Net_URL2::setUserinfo
+ * @covers Net_URL2::getUserinfo
+ * @covers Net_URL2::getURL
+ * @return void
+ * @link https://pear.php.net/bugs/bug.php?id=20013
+ * @link https://pear.php.net/bugs/bug.php?id=20399
+ */
+ public function testSetEmptyUserinfo()
+ {
+ $url = new Net_URL2('http://@www.example.com/');
+ $this->assertSame('http://www.example.com/', $url->getURL());
+
+ $url = new Net_URL2('http://www.example.com/');
+ $this->assertSame('http://www.example.com/', $url->getURL());
+ $url->setUserinfo('');
+ $this->assertSame('http://www.example.com/', $url->getURL());
+ $this->assertSame('', $url->getUserinfo());
+ $url->setUserinfo(false);
+ $this->assertSame('http://www.example.com/', $url->getURL());
+ $this->assertFalse($url->getUserinfo());
+ }
+
+ /**
+ * Tests an URL with no userinfo and normalization
+ *
+ * Also: Regression test for Bug #20385
+ *
+ * @covers Net_URL2::getUserinfo
+ * @covers Net_URL2::normalize
+ * @covers Net_URL2::getNormalizedURL
+ * @return void
+ * @link https://pear.php.net/bugs/bug.php?id=20385
+ */
+ public function testNoUserinfoAndNormalize()
+ {
+ $testUrl = 'http://www.example.com/';
+
+ $url = new Net_URL2($testUrl);
+ $this->assertFalse($url->getUserinfo());
+
+ $url->normalize();
+ $this->assertFalse($url->getUserinfo());
+
+ $this->assertEquals($testUrl, $url->getURL());
+ $this->assertEquals($testUrl, $url->getNormalizedURL());
+ }
+
+ /**
+ * Tests setQueryVariable().
+ *
+ * @return void
+ */
+ public function testSetQueryVariable()
+ {
+
+ $url = new Net_URL2('http://www.example.com/');
+ $url->setQueryVariable('pear', 'fun');
+ $this->assertEquals($url->getURL(), 'http://www.example.com/?pear=fun');
+ }
+
+ /**
+ * Tests setQueryVariables().
+ *
+ * @return void
+ */
+ public function testSetQueryVariables()
+ {
+
+ $url = new Net_URL2('http://www.example.com/');
+ $url->setQueryVariables(array('pear' => 'fun'));
+ $this->assertEquals('http://www.example.com/?pear=fun', $url->getURL());
+ $url->setQueryVariables(array('pear' => 'fun for sure'));
+ $this->assertEquals(
+ 'http://www.example.com/?pear=fun%20for%20sure', $url->getURL()
+ );
+ }
+
+ /**
+ * Tests unsetQueryVariable()
+ *
+ * @return void
+ */
+ public function testUnsetQueryVariable()
+ {
+ $url = new Net_URL2(
+ 'http://www.example.com/?name=david&pear=fun&fish=slippery'
+ );
+
+ $removes = array(
+ 'pear' => 'http://www.example.com/?name=david&fish=slippery',
+ 'name' => 'http://www.example.com/?fish=slippery',
+ 'fish' => 'http://www.example.com/',
+ );
+
+ foreach ($removes as $name => $expected) {
+ $url->unsetQueryVariable($name);
+ $this->assertEquals($expected, $url);
+ }
+ }
+
+ /**
+ * Tests setQuery().
+ *
+ * @return void
+ */
+ public function testSetQuery()
+ {
+
+ $url = new Net_URL2('http://www.example.com/');
+ $url->setQuery('flapdoodle&dilly%20all%20day');
+ $this->assertEquals(
+ $url->getURL(), 'http://www.example.com/?flapdoodle&dilly%20all%20day'
+ );
+ }
+
+ /**
+ * Tests getQuery().
+ *
+ * @return void
+ */
+ public function testGetQuery()
+ {
+
+ $url = new Net_URL2('http://www.example.com/?foo');
+ $this->assertEquals($url->getQuery(), 'foo');
+ $url = new Net_URL2('http://www.example.com/?pear=fun&fruit=fruity');
+ $this->assertEquals($url->getQuery(), 'pear=fun&fruit=fruity');
+ }
+
+ /**
+ * Tests setScheme().
+ *
+ * @return void
+ */
+ public function testSetScheme()
+ {
+
+ $url = new Net_URL2('http://www.example.com/');
+ $url->setScheme('ftp');
+ $this->assertEquals($url->getURL(), 'ftp://www.example.com/');
+ $url->setScheme('gopher');
+ $this->assertEquals($url->getURL(), 'gopher://www.example.com/');
+ }
+
+ /**
+ * Tests setting the fragment.
+ *
+ * @return void
+ */
+ public function testSetFragment()
+ {
+
+ $url = new Net_URL2('http://www.example.com/');
+ $url->setFragment('pear');
+ $this->assertEquals('http://www.example.com/#pear', $url->getURL());
+ }
+
+ /**
+ * A dataProvider for paths that are solved to a base URI.
+ *
+ * @see testResolveUrls
+ * @return array
+ */
+ public function provideResolveUrls()
+ {
+ return array(
+ array(
+ // Examples from RFC 3986, section 5.4.
+ // relative base-URI, (URL => absolute URL), [(options)]
+ 'http://a/b/c/d;p?q',
+ array(
+ 'g:h' => 'g:h',
+ 'g' => 'http://a/b/c/g',
+ './g' => 'http://a/b/c/g',
+ 'g/' => 'http://a/b/c/g/',
+ '/g' => 'http://a/g',
+ '//g' => 'http://g',
+ '?y' => 'http://a/b/c/d;p?y',
+ 'g?y' => 'http://a/b/c/g?y',
+ '#s' => 'http://a/b/c/d;p?q#s',
+ 'g#s' => 'http://a/b/c/g#s',
+ 'g?y#s' => 'http://a/b/c/g?y#s',
+ ';x' => 'http://a/b/c/;x',
+ 'g;x' => 'http://a/b/c/g;x',
+ 'g;x?y#s' => 'http://a/b/c/g;x?y#s',
+ '' => 'http://a/b/c/d;p?q',
+ '.' => 'http://a/b/c/',
+ './' => 'http://a/b/c/',
+ '..' => 'http://a/b/',
+ '../' => 'http://a/b/',
+ '../g' => 'http://a/b/g',
+ '../..' => 'http://a/',
+ '../../' => 'http://a/',
+ '../../g' => 'http://a/g',
+ '../../../g' => 'http://a/g',
+ '../../../../g' => 'http://a/g',
+ '/./g' => 'http://a/g',
+ '/../g' => 'http://a/g',
+ 'g.' => 'http://a/b/c/g.',
+ '.g' => 'http://a/b/c/.g',
+ 'g..' => 'http://a/b/c/g..',
+ '..g' => 'http://a/b/c/..g',
+ './../g' => 'http://a/b/g',
+ './g/.' => 'http://a/b/c/g/',
+ 'g/./h' => 'http://a/b/c/g/h',
+ 'g/../h' => 'http://a/b/c/h',
+ 'g;x=1/./y' => 'http://a/b/c/g;x=1/y',
+ 'g;x=1/../y' => 'http://a/b/c/y',
+ 'g?y/./x' => 'http://a/b/c/g?y/./x',
+ 'g?y/../x' => 'http://a/b/c/g?y/../x',
+ 'g#s/./x' => 'http://a/b/c/g#s/./x',
+ 'g#s/../x' => 'http://a/b/c/g#s/../x',
+ 'http:g' => 'http:g',
+ ),
+ ),
+ array(
+ 'http://a/b/c/d;p?q',
+ array('http:g' => 'http://a/b/c/g'),
+ array('::OPTION_STRICT' => false)
+ ),
+ );
+ }
+
+ /**
+ * Test the resolve() function to resolve URLs to each other.
+ *
+ * @param string $baseURL base-URI
+ * @param array $relativeAbsolutePairs url-pairs, relative => resolved
+ * @param array $options Net_URL2 options
+ *
+ * @dataProvider provideResolveUrls
+ * @covers Net_URL2::resolve
+ * @return void
+ */
+ public function testResolveUrls($baseURL, array $relativeAbsolutePairs,
+ array $options = array()
+ ) {
+ $options = $this->_translateOptionData($options);
+ $base = new Net_URL2($baseURL, $options);
+ $count = count($relativeAbsolutePairs);
+ $this->assertGreaterThan(0, $count, 'relative-absolute-pairs data is empty');
+ foreach ($relativeAbsolutePairs as $relativeURL => $absoluteURL) {
+ $this->assertSame($absoluteURL, (string) $base->resolve($relativeURL));
+ }
+ }
+
+ /**
+ * Helper method to turn options with strings as the constant names
+ * (to allow to externalize the fixtures) into a concrete options
+ * array that uses the values from the Net_URL2 class constants.
+ *
+ * @param array $options options
+ *
+ * @return array
+ */
+ private function _translateOptionData(array $options)
+ {
+ // translate string option-names to class constant starting with a colon.
+ foreach ($options as $name => $value) {
+ if ($name[0] === ':') {
+ unset($options[$name]);
+ $options[constant("Net_URL2$name")] = $value;
+ }
+ }
+ return $options;
+ }
+
+ /**
+ * Test the resolve() function throwing an exception with invalid data.
+ *
+ * @covers Net_URL2::resolve
+ * @return void
+ */
+ public function testResolveException()
+ {
+ // resolving a relative to a relative URL throws an exception
+ $base = new Net_URL2('news.html?category=arts');
+ $this->addToAssertionCount(1);
+ try {
+ $base->resolve('../arts.html#section-2.4');
+ } catch (Exception $e) {
+ $expected = 'Base-URL must be absolute if reference is not fragment-onl';
+ $this->assertStringStartsWith($expected, $e->getMessage());
+ return;
+ }
+ $this->fail('Expected exception not thrown.');
+ }
+
+ /**
+ * Assert that there is a last error message and it contains needle.
+ *
+ * @param string $needle needle
+ *
+ * @return void
+ */
+ private function _assertLastErrorContains($needle)
+ {
+ $error = error_get_last();
+ $this->assertArrayHasKey('message', $error, 'there was an error previously');
+ $pos = strpos($error['message'], $needle);
+
+ $this->assertTrue(
+ false !== $pos,
+ sprintf(
+ 'Last error message "%s" contains "%s"', $error['message'], $needle
+ )
+ );
+ }
+
+ /**
+ * Test UrlEncoding
+ *
+ * @return void
+ * @link https://pear.php.net/bugs/bug.php?id=18267
+ */
+ public function testUrlEncoding()
+ {
+ $options = array(Net_URL2::OPTION_DROP_SEQUENCE => false);
+ $url = new Net_URL2('http://localhost/bug.php', $options);
+ $url->setQueryVariables(
+ array(
+ 'indexed' => array(
+ 'first value', 'second value', array('foo', 'bar'),
+ )
+ )
+ );
+ $this->assertEquals(
+ 'http://localhost/bug.php?indexed[0]=first%20value&indexed[1]' .
+ '=second%20value&indexed[2][0]=foo&indexed[2][1]=bar',
+ strval($url)
+ );
+ }
+
+ /**
+ * A test to verify that keys in QUERY_STRING are encoded by default.
+ *
+ * @return void
+ * @see Net_URL2::OPTION_ENCODE_KEYS
+ * @see Net_URL2::buildQuery()
+ */
+ public function testEncodeKeys()
+ {
+ $url = new Net_URL2('http://example.org');
+ $url->setQueryVariables(array('helgi rulez' => 'till too'));
+ $this->assertEquals(
+ 'http://example.org?helgi%20rulez=till%20too',
+ strval($url)
+ );
+ }
+
+ /**
+ * A test to verify that keys in QUERY_STRING are not encoded when we supply
+ * 'false' via {@link Net_URL2::__construct()}.
+ *
+ * @return void
+ * @see Net_URL2::OPTION_ENCODE_KEYS
+ * @see Net_URL2::buildQuery()
+ */
+ public function testDontEncodeKeys()
+ {
+ $url = new Net_URL2(
+ 'http://example.org',
+ array(Net_URL2::OPTION_ENCODE_KEYS => false)
+ );
+ $url->setQueryVariables(array('till rulez' => 'helgi too'));
+ $this->assertEquals(
+ 'http://example.org?till rulez=helgi%20too',
+ strval($url)
+ );
+ }
+
+ /**
+ * Brackets for array query variables
+ *
+ * Also text to not encode zero based integer sequence into brackets
+ *
+ * @return void
+ *
+ * @link https://pear.php.net/bugs/bug.php?id=20427
+ */
+ public function testUseBrackets()
+ {
+ $url = new Net_URL2('http://example.org/');
+ $url->setQueryVariables(array('foo' => array('bar', 'baz')));
+ $expected = 'http://example.org/?foo[]=bar&foo[]=baz';
+ $this->assertEquals($expected, $url->getURL());
+
+ $options = array(Net_URL2::OPTION_DROP_SEQUENCE => false);
+ $url = new Net_URL2('http://example.org/', $options);
+ $url->setQueryVariables(array('foo' => array('bar', 'foobar')));
+ $expected = 'http://example.org/?foo[0]=bar&foo[1]=foobar';
+ $this->assertEquals($expected, $url->getURL());
+ }
+
+ /**
+ * Do not use brackets for query variables passed as array
+ *
+ * @return void
+ */
+ public function testDontUseBrackets()
+ {
+ $url = new Net_URL2(
+ 'http://example.org/',
+ array(Net_URL2::OPTION_USE_BRACKETS => false)
+ );
+ $url->setQueryVariables(array('foo' => array('bar', 'foobar')));
+ $this->assertEquals(
+ 'http://example.org/?foo=bar&foo=foobar',
+ strval($url)
+ );
+ }
+
+ /**
+ * A dataProvider for example URIs from RFC 3986 Section 1.1.2
+ *
+ * @return array
+ * @link http://tools.ietf.org/html/rfc3986#section-1.1.2
+ * @see testExampleUri
+ */
+ public function provideExampleUri()
+ {
+ return array(
+ array('ftp://ftp.is.co.za/rfc/rfc1808.txt'),
+ array('http://www.ietf.org/rfc/rfc2396.txt'),
+ array('ldap://[2001:db8::7]/c=GB?objectClass?one'),
+ array('mailto:John.Doe@example.com'),
+ array('news:comp.infosystems.www.servers.unix'),
+ array('tel:+1-816-555-1212'),
+ array('telnet://192.0.2.16:80/'),
+ array('urn:oasis:names:specification:docbook:dtd:xml:4.1.2'),
+ );
+ }
+
+ /**
+ * test that Net_URL2 works with the example URIs from RFC 3986 Section 1.1.2
+ *
+ * @param string $uri example URI
+ *
+ * @return void
+ * @dataProvider provideExampleUri
+ * @link http://tools.ietf.org/html/rfc3986#section-1.1.2
+ * @see testComponentRecompositionAndNormalization
+ */
+ public function testExampleUri($uri)
+ {
+ $url = new Net_URL2($uri);
+ $this->assertSame($uri, $url->__toString());
+ $url->normalize();
+ $this->assertSame($uri, $url->__toString());
+ }
+
+ /**
+ * A dataProvider for pairs of paths with dot segments and
+ * their form when removed.
+ *
+ * @see testRemoveDotSegments
+ * @return array
+ */
+ public function providePath()
+ {
+ // The numbers behind are in reference to sections
+ // in RFC 3986 5.2.4. Remove Dot Segments
+ return array(
+ array('../', ''), // 2. A.
+ array('./', ''), // 2. A.
+ array('/./', '/'), // 2. B.
+ array('/.', '/'), // 2. B.
+ array('/../', '/'), // 2. C.
+ array('/..', '/'), // 2. C.
+ array('..', ''), // 2. D.
+ array('.', ''), // 2. D.
+ array('a', 'a'), // 2. E.
+ array('/a', '/a'), // 2. E.
+ array('/a/b/c/./../../g', '/a/g'), // 3.
+ array('mid/content=5/../6', 'mid/6'), // 3.
+ array('../foo/bar.php', 'foo/bar.php'),
+ array('/foo/../bar/boo.php', '/bar/boo.php'),
+ array('/boo/..//foo//bar.php', '//foo//bar.php'),
+ array('/./foo/././bar.php', '/foo/bar.php'),
+ array('./.', ''),
+ );
+ }
+
+ /**
+ * Test removal of dot segments
+ *
+ * @param string $path Path
+ * @param string $assertion Assertion
+ *
+ * @dataProvider providePath
+ * @covers Net_URL2::removeDotSegments
+ * @return void
+ */
+ public function testRemoveDotSegments($path, $assertion)
+ {
+ $this->assertEquals($assertion, Net_URL2::removeDotSegments($path));
+ }
+
+ /**
+ * Test removeDotSegments() loop limit warning
+ *
+ * @covers Net_URL2::removeDotSegments
+ * @return void
+ */
+ public function testRemoveDotSegmentsLoopLimit()
+ {
+ $loopLimit = 256;
+ $segments = str_repeat('a/', $loopLimit);
+
+ @Net_URL2::removeDotSegments($segments . 'b/');
+
+ $this->_assertLastErrorContains(sprintf(' loop limit %d ', $loopLimit + 1));
+ $this->_assertLastErrorContains(" (left: '/b/')");
+ }
+
+ /**
+ * A dataProvider for query strings and their array representation
+ *
+ * @see testGetQueryVariables
+ * @return array
+ */
+ public function provideQueryStrings()
+ {
+ // If the second (expected) value is set or not null, parse_str() differs.
+ // Notes on PHP differences with each entry/block
+ return array(
+ // Net_URL2::getQueryVariables() non-bracket mode
+ array('test=1&t%65st=%41&extra=',
+ array('test' => array('1', 'A'), 'extra' => ''),
+ array('::OPTION_USE_BRACKETS' => false)),
+ array(''),
+ array('='),
+ array('key'),
+ array('key='),
+ array('=value'),
+ array('k=v'),
+ // no space as var-name in PHP (array()):
+ array(' ', array(' ' => '' )),
+ array(' =v', array(' ' => 'v')),
+ array('key=value'),
+ // PHP replaces ".", " " and "[" in name replaced by "_":
+ array('key.=value' , array('key.' => 'value')),
+ array('key =value' , array('key ' => 'value')),
+ array('key[=value' , array('key[' => 'value')),
+ array("key\0=value", array("key\0" => 'value')),
+ array('key]=value'),
+ array('key[]=value'),
+ array('[]=value'),
+ array(']=value'),
+ array(']]=value'),
+ // PHP drops variables that are an open bracket only
+ array('[=value', array('[' => 'value')),
+ // PHP drops spaces in brackets:
+ array('key[ ]=value', array('key' => array(' ' => 'value'))),
+ // PHP replaces space " " in name by "_"
+ array('key []=1' , array('key ' => array('1' ))) ,
+ // PHP does not support "\0" in var-names:
+ array("key[\0]=value" , array('key' => array("\0" => 'value' ))),
+ array("key[a\0]=value" , array('key' => array("a\0" => 'value' ))),
+ array("key[a\0b]=value" , array('key' => array("a\0b" => 'value'))),
+ array('var[]=1&var[0][]=2'),
+ array('key[] []=1'),
+ array('key[] [] []=1'),
+ array('key[] [] []'),
+ array('key[] [] []=[] []'),
+ array('[] [] []=[] []'),
+ );
+ }
+
+ /**
+ * Test parsing of query variables
+ *
+ * @param string $query string
+ * @param mixed $expected null to test against parse_str() behavior
+ * @param array $options Net_URL2 options
+ *
+ * @dataProvider provideQueryStrings
+ * @covers Net_URL2::getQueryVariables
+ * @covers Net_URL2::_queryArrayByKey
+ * @covers Net_URL2::_queryArrayByBrackets
+ * @covers Net_URL2::_queryKeyBracketOffset
+ * @return void
+ */
+ public function testGetQueryVariables($query, $expected = null,
+ array $options = array()
+ ) {
+ $options = $this->_translateOptionData($options);
+
+ $url = new Net_URL2('', $options);
+
+ if ($expected === null) {
+ // parse_str() is in PHP before copy on write, therefore
+ // it uses pass-by-reference for $expected to return
+ // the array
+ parse_str($query, $expected);
+ }
+
+ // Xdebug: If breakpoints are ignored, see Xdebug Issue 0000924
+ $url->setQuery($query);
+ $actual = $url->getQueryVariables();
+
+ // Do two assertions, because the first one shows a more nice diff in case
+ // it fails and the second one is actually strict which is what has to be
+ // tested.
+ $this->assertEquals($expected, $actual);
+ $this->assertSame($expected, $actual);
+ }
+
+ /**
+ * data provider of host and port
+ *
+ * @return array
+ * @see testHostAndPort
+ */
+ public function provideHostAndPort()
+ {
+ return array(
+ array('[::1]', '[::1]', false),
+ array('[::1]:', '[::1]', false),
+ array('[::1]:128', '[::1]', '128'),
+ array('127.0.0.1', '127.0.0.1', false),
+ array('127.0.0.1:', '127.0.0.1', false),
+ array('127.0.0.1:128', '127.0.0.1', '128'),
+ array('localhost', 'localhost', false),
+ array('localhost:', 'localhost', false),
+ array('localhost:128', 'localhost', '128'),
+ );
+ }
+
+ /**
+ * test that an authority containing host and port maps to expected host and port
+ *
+ * This is also a regression test to test that using ip-literals works along-
+ * side ipv4 and reg-name hosts incl. port numbers
+ *
+ * It was reported as Bug #20423 on 2014-10-06 18:25 UTC that
+ * http://[::1]// URI drops the host
+ *
+ * @param string $authority string
+ * @param string $expectedHost string
+ * @param string|bool $expectedPort string or FALSE
+ *
+ * @return void
+ * @dataProvider provideHostAndPort
+ * @covers Net_URL2::setAuthority()
+ * @link https://pear.php.net/bugs/bug.php?id=20423
+ * @link http://tools.ietf.org/html/rfc3986#section-3.2.2
+ * @link http://tools.ietf.org/html/rfc3986#section-3.2
+ * @link http://tools.ietf.org/html/rfc3986#section-3.2.3
+ */
+ public function testHostAndPort($authority, $expectedHost, $expectedPort)
+ {
+ $uri = "http://{$authority}";
+ $url = new Net_URL2($uri);
+ $this->assertSame($expectedHost, $url->getHost());
+ $this->assertSame($expectedPort, $url->getPort());
+ }
+
+ /**
+ * This is a regression test to test that Net_URL2::getQueryVariables() does
+ * not have a problem with nested array values in form of stacked brackets and
+ * was reported as Bug #17036 on 2010-01-26 15:48 UTC that there would be
+ * a problem with parsed query string.
+ *
+ * @link https://pear.php.net/bugs/bug.php?id=17036
+ * @covers Net_URL2::getQueryVariables
+ * @return void
+ */
+ public function test17036()
+ {
+ $queryString = 'start=10&test[0][first][1.1][20]=coucou';
+ $url = new Net_URL2('?' . $queryString);
+ $vars = $url->getQueryVariables();
+
+ $expected = array();
+ $expected['start'] = '10';
+ $expected['test'][0]['first']['1.1'][20] = 'coucou';
+
+ $this->assertEquals($expected, $vars); // give nice diff in case of failuer
+ $this->assertSame($expected, $vars); // strictly assert the premise
+ }
+
+ /**
+ * This is a regression test to test that resolve() does
+ * merge the path if the base path is empty as the opposite
+ * was reported as Bug #19176 on 2011-12-31 02:07 UTC
+ *
+ * @return void
+ */
+ public function test19176()
+ {
+ $foo = new Net_URL2('http://www.example.com');
+ $test = $foo->resolve('test.html')->getURL();
+ $this->assertEquals('http://www.example.com/test.html', $test);
+ }
+
+ /**
+ * This is a regression test that removeDotSegments('0') is
+ * working as it was reported as not-working in Bug #19315
+ * on 2012-03-04 04:18 UTC.
+ *
+ * @return void
+ */
+ public function test19315()
+ {
+ $actual = Net_URL2::removeDotSegments('0');
+ $this->assertSame('0', $actual);
+
+ $nonStringObject = (object)array();
+ try {
+ Net_URL2::removeDotSegments($nonStringObject);
+ } catch (PHPUnit_Framework_Error $error) {
+ $this->addToAssertionCount(1);
+ }
+
+ if (!isset($error)) {
+ $this->fail('Failed to verify that error was given.');
+ }
+ unset($error);
+ }
+
+ /**
+ * This is a regression test to test that recovering from
+ * a wrongly encoded URL is possible.
+ *
+ * It was requested as Request #19684 on 2011-12-31 02:07 UTC
+ * that redirects containing spaces should work.
+ *
+ * @return void
+ */
+ public function test19684()
+ {
+ // Location: URL obtained Thu, 25 Apr 2013 20:51:31 GMT
+ $urlWithSpace = 'http://www.sigmaaldrich.com/catalog/search?interface=CAS N'
+ . 'o.&term=108-88-3&lang=en&region=US&mode=match+partialmax&N=0+2200030'
+ . '48+219853269+219853286';
+
+ $urlCorrect = 'http://www.sigmaaldrich.com/catalog/search?interface=CAS%20N'
+ . 'o.&term=108-88-3&lang=en&region=US&mode=match+partialmax&N=0+2200030'
+ . '48+219853269+219853286';
+
+ $url = new Net_URL2($urlWithSpace);
+
+ $this->assertTrue($url->isAbsolute());
+
+ $urlPart = parse_url($urlCorrect, PHP_URL_PATH);
+ $this->assertSame($urlPart, $url->getPath());
+
+ $urlPart = parse_url($urlCorrect, PHP_URL_QUERY);
+ $this->assertSame($urlPart, $url->getQuery());
+
+ $this->assertSame($urlCorrect, (string)$url);
+
+ $input = 'http://example.com/get + + to my nose/';
+ $expected = 'http://example.com/get%20+%20+%20to%20my%20nose/';
+ $actual = new Net_URL2($input);
+ $this->assertEquals($expected, $actual);
+ $actual->normalize();
+ }
+
+ /**
+ * data provider of list of equivalent URLs.
+ *
+ * @see testNormalize
+ * @see testConstructSelf
+ * @return array
+ */
+ public function provideEquivalentUrlLists()
+ {
+ return array(
+ // String equivalence:
+ array('http://example.com/', 'http://example.com/'),
+
+ // Originally first dataset:
+ array('http://www.example.com/%9a', 'http://www.example.com/%9A'),
+
+ // Example from RFC 3986 6.2.2.:
+ array('example://a/b/c/%7Bfoo%7D', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d'),
+
+ // Example from RFC 3986 6.2.2.1.:
+ array('HTTP://www.EXAMPLE.com/', 'http://www.example.com/'),
+
+ // Example from RFC 3986 6.2.3.:
+ array(
+ 'http://example.com', 'http://example.com/',
+ 'http://example.com:/', 'http://example.com:80/'
+ ),
+
+ // Bug #20161: URLs with "0" as host fail to normalize with empty path
+ array('http://0/', 'http://0'),
+
+ // Bug #20473: Normalize query and fragment broken
+ array('foo:///?%66%6f%6f#%62%61%72', 'foo:///?foo#bar'),
+ );
+ }
+
+ /**
+ * This is a coverage test to invoke the normalize()
+ * method.
+ *
+ * @return void
+ *
+ * @dataProvider provideEquivalentUrlLists
+ */
+ public function testNormalize()
+ {
+ $urls = func_get_args();
+
+ $this->assertGreaterThanOrEqual(2, count($urls));
+
+ $last = null;
+
+ foreach ($urls as $index => $url) {
+ $url = new Net_Url2($url);
+ $url->normalize();
+ if ($index) {
+ $this->assertSame((string)$last, (string)$url);
+ }
+ $last = $url;
+ }
+ }
+
+ /**
+ * This is a coverage test to invoke __get and __set
+ *
+ * @covers Net_URL2::__get
+ * @covers Net_URL2::__set
+ * @return void
+ */
+ public function testMagicSetGet()
+ {
+ $url = new Net_URL2('');
+
+ $property = 'authority';
+ $url->$property = $value = 'value';
+ $this->assertEquals($value, $url->$property);
+
+ $property = 'unsetProperty';
+ $url->$property = $value;
+ $this->assertEquals(false, $url->$property);
+ }
+
+ /**
+ * data provider of uri and normal URIs
+ *
+ * @return array
+ * @see testComponentRecompositionAndNormalization
+ */
+ public function provideComposedAndNormalized()
+ {
+ return array(
+ array(''),
+ array('http:g'),
+ array('user@host'),
+ array('mailto:user@host'),
+ );
+ }
+
+ /**
+ * Tests Net_URL2 RFC 3986 5.3. Component Recomposition in the light
+ * of normalization
+ *
+ * This is also a regression test to test that a missing authority works well
+ * with normalization
+ *
+ * It was reported as Bug #20418 on 2014-10-02 22:10 UTC that there is an
+ * Incorrect normalization of URI with missing authority
+ *
+ * @param string $uri URI
+ *
+ * @return void
+ * @covers Net_URL2::getUrl()
+ * @covers Net_URL2::normalize()
+ * @dataProvider provideComposedAndNormalized
+ * @link https://pear.php.net/bugs/bug.php?id=20418
+ * @see testExampleUri
+ */
+ public function testComponentRecompositionAndNormalization($uri)
+ {
+ $url = new Net_URL2($uri);
+ $this->assertSame($uri, $url->getURL());
+ $url->normalize();
+ $this->assertSame($uri, $url->getURL());
+ }
+
+ /**
+ * Tests Net_URL2 ctors URL parameter works with objects implementing
+ * __toString().
+ *
+ * @dataProvider provideEquivalentUrlLists
+ * @coversNothing
+ * @return void
+ */
+ public function testConstructSelf()
+ {
+ $urls = func_get_args();
+ foreach ($urls as $url) {
+ $urlA = new Net_URL2($url);
+ $urlB = new Net_URL2($urlA);
+ $this->assertSame((string)$urlA, (string)$urlB);
+ }
+ }
+
+ /**
+ * This is a feature test to see that the userinfo's data is getting
+ * encoded as outlined in #19684.
+ *
+ * @covers Net_URL2::setAuthority
+ * @covers Net_URL2::setUserinfo
+ * @return void
+ */
+ public function testEncodeDataUserinfoAuthority()
+ {
+ $url = new Net_URL2('http://john doe:secret@example.com/');
+ $this->assertSame('http://john%20doe:secret@example.com/', (string)$url);
+
+ $url->setUserinfo('john doe');
+ $this->assertSame('http://john%20doe@example.com/', (string)$url);
+
+ $url->setUserinfo('john doe', 'pa wd');
+ $this->assertSame('http://john%20doe:pa%20wd@example.com/', (string)$url);
+ }
+
+ /**
+ * This is a regression test to test that using the
+ * host-name "0" does work with getAuthority()
+ *
+ * It was reported as Bug #20156 on 2013-12-27 22:56 UTC
+ * that setAuthority() with "0" as host would not work
+ *
+ * @covers Net_URL2::setAuthority
+ * @covers Net_URL2::getAuthority
+ * @covers Net_URL2::setHost
+ * @return void
+ */
+ public function test20156()
+ {
+ $url = new Net_URL2('http://user:pass@example.com:127/');
+ $host = '0';
+ $url->setHost($host);
+ $this->assertSame('user:pass@0:127', $url->getAuthority());
+
+ $url->setHost(false);
+ $this->assertSame(false, $url->getAuthority());
+
+ $url->setAuthority($host);
+ $this->assertSame($host, $url->getAuthority());
+ }
+
+ /**
+ * This is a regression test to test that setting "0" as path
+ * does not break normalize().
+ *
+ * It was reported as Bug #20157 on 2013-12-27 23:42 UTC that
+ * normalize() with "0" as path would not work.
+ *
+ * @covers Net_URL2::normalize
+ * @return void
+ */
+ public function test20157()
+ {
+ $subject = 'http://example.com';
+ $url = new Net_URL2($subject);
+ $url->setPath('0');
+ $url->normalize();
+ $this->assertSame("$subject/0", (string)$url);
+ }
+
+ /**
+ * This is a regression test to ensure that fragment-only references can be
+ * resolved to a non-absolute Base-URI.
+ *
+ * It was reported as Bug #20158 2013-12-28 14:49 UTC that fragment-only
+ * references would not be resolved to non-absolute base URI
+ *
+ * @covers Net_URL2::resolve
+ * @covers Net_URL2::_isFragmentOnly
+ * @return void
+ */
+ public function test20158()
+ {
+ $base = new Net_URL2('myfile.html');
+ $resolved = $base->resolve('#world');
+ $this->assertSame('myfile.html#world', (string)$resolved);
+ }
+
+ /**
+ * This is a regression test to ensure that authority and path are properly
+ * combined when the path does not start with a slash which is the separator
+ * character between authority and path.
+ *
+ * It was reported as Bug #20159 2013-12-28 17:18 UTC that authority
+ * would not be terminated by slash
+ *
+ * @covers Net_URL2::getUrl
+ * @return void
+ */
+ public function test20159()
+ {
+ $url = new Net_URL2('index.html');
+ $url->setHost('example.com');
+ $this->assertSame('//example.com/index.html', (string)$url);
+ }
+
+ /**
+ * This is a regression test to test that using the file:// URI scheme with
+ * an empty (default) hostname has the empty authority preserved when the
+ * full URL is build.
+ *
+ * It was reported as Bug #20304 on 2014-06-21 00:06 UTC
+ * that file:// URI are crippled.
+ *
+ * Tests with a default authority for the "file" URI scheme
+ *
+ * @covers Net_URL2::getURL
+ * @return void
+ * @link https://pear.php.net/bugs/bug.php?id=20304
+ */
+ public function test20304()
+ {
+ $file = 'file:///path/to/file';
+ $url = new Net_URL2($file);
+ $this->assertSame($file, (string) $url);
+
+ $file = 'file://localhost/path/to/file';
+ $url = new Net_URL2($file);
+ $this->assertSame($file, (string) $url);
+
+ $file = 'file://user@/path/to/file';
+ $url = new Net_URL2($file);
+ $this->assertSame($file, (string) $url);
+
+ $file = 'FILE:///path/to/file';
+ $url = new Net_URL2($file);
+ $this->assertSame($file, (string) $url);
+ }
+}