+ // 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]);