97 self::OPTION_STRICT =>
true,
98 self::OPTION_USE_BRACKETS =>
true,
99 self::OPTION_DROP_SEQUENCE =>
true,
100 self::OPTION_ENCODE_KEYS =>
true,
101 self::OPTION_SEPARATOR_INPUT =>
'&',
102 self::OPTION_SEPARATOR_OUTPUT =>
'&',
150 foreach ($options as $optionName => $value) {
151 if (array_key_exists($optionName, $this->_options)) {
152 $this->_options[$optionName] = $value;
172 $method =
'set' . $var;
173 if (method_exists($this, $method)) {
174 $this->$method($arg);
192 $method =
'get' . $var;
193 if (method_exists($this, $method)) {
194 return $this->$method();
224 $this->_scheme = $scheme;
236 return $this->_userinfo !==
false
237 ? preg_replace(
'(:.*$)',
'', $this->_userinfo)
251 return $this->_userinfo !==
false
252 ? substr(strstr($this->_userinfo,
':'), 1)
278 if ($password !==
false) {
279 $userinfo .=
':' . $password;
282 if ($userinfo !==
false) {
286 $this->_userinfo = $userinfo;
311 $this->_host = $host;
336 $this->_port = $port;
348 if (
false === $this->_host) {
354 if (strlen($this->_userinfo)) {
355 $authority .= $this->_userinfo .
'@';
360 if ($this->_port !==
false) {
379 $this->_userinfo =
false;
380 $this->_host =
false;
381 $this->_port =
false;
383 if (
'' === $authority) {
384 $this->_host = $authority;
388 if (!preg_match(
'(^(([^\@]*)\@)?(.+?)(:(\d*))?$)', $authority, $matches)) {
393 $this->_userinfo = $this->
_encodeData($matches[2]);
396 $this->_host = $matches[3];
398 if (isset($matches[5]) && strlen($matches[5])) {
399 $this->_port = $matches[5];
423 $this->_path = $path;
450 $this->_query = $query;
474 $this->_fragment = $fragment;
487 $separator = $this->
getOption(self::OPTION_SEPARATOR_INPUT);
488 $encodeKeys = $this->
getOption(self::OPTION_ENCODE_KEYS);
489 $useBrackets = $this->
getOption(self::OPTION_USE_BRACKETS);
493 for ($part = strtok($this->_query, $separator);
495 $part = strtok($separator)
497 list($key, $value) = explode(
'=', $part, 2) + array(1 =>
'');
500 $key = rawurldecode($key);
502 $value = rawurldecode($value);
507 if (isset($return[$key])) {
508 $return[$key] = (array) $return[$key];
509 $return[$key][] = $value;
511 $return[$key] = $value;
535 if ($offset ===
false) {
538 $name = substr($key, 0, $offset);
541 if (!strlen($name)) {
547 $array[$name] = $value;
550 $brackets = substr($key, $offset);
551 if (!isset($array[$name])) {
552 $array[$name] = null;
555 $brackets, $value, $array[$name]
576 for ($iteration = 0; strlen($buffer); $iteration++) {
588 'Net_URL2 Internal Error: '. __METHOD__ .
'(): ' .
589 'Opening bracket [ must exist at offset 0'
594 $close = strpos($buffer,
']', 1);
601 'Net_URL2 Internal Error: '. __METHOD__ .
'(): ' .
602 'Closing bracket ] must exist, not found'
607 $index = substr($buffer, 1, $close - 1);
608 if (strlen($index)) {
609 $entry = &$entry[$index];
611 if (!is_array($entry)) {
618 $buffer = substr($buffer, $close + 1);
635 if (
false !== $open = strpos($key,
'[')
636 and
false === strpos($key,
']', $open + 1)
654 $this->_query =
false;
658 $this->
getOption(self::OPTION_SEPARATOR_OUTPUT)
675 $array[$name] = $value;
690 unset($array[$name]);
704 if ($this->_scheme !==
false) {
705 $url .= $this->_scheme .
':';
709 if ($authority ===
false && strtolower($this->_scheme) ===
'file') {
715 if ($this->_query !==
false) {
719 if ($this->_fragment !==
false) {
737 if ($authority ===
false) {
741 $terminator = ($path !==
'' && $path[0] !==
'/') ?
'/' :
'';
743 return '//' . $authority . $terminator . $path;
767 return $url->getUrl();
784 if ($this->_scheme) {
785 $this->_scheme = strtolower($this->_scheme);
790 $this->_host = strtolower($this->_host);
794 if (
'' === $this->_port
797 && $this->_port == getservbyname($this->_scheme,
'tcp')
799 $this->_port =
false;
804 $fields = array(&$this->_userinfo, &$this->_host, &$this->_path,
805 &$this->_query, &$this->_fragment);
806 foreach ($fields as &$field) {
807 if ($field !==
false) {
814 $this->_path = self::removeDotSegments($this->_path);
817 if (
false !== $this->_host &&
'' === $this->_path) {
823 && strlen($this->_path)
824 && $this->_path[0] !==
'/'
842 return preg_replace_callback(
843 '((?:%[0-9a-fA-Z]{2})+)', array($this,
'_normalizeCallback'),
860 return self::urlencode(urldecode($matches[0]));
884 if (!$reference instanceof
Net_URL2) {
885 $reference =
new self($reference);
887 if (!$reference->_isFragmentOnly() && !$this->
isAbsolute()) {
889 'Base-URL must be absolute if reference is not fragment-only'
895 if (!$this->
getOption(self::OPTION_STRICT)
896 && $reference->_scheme == $this->_scheme
898 $reference->_scheme =
false;
901 $target =
new self(
'');
902 if ($reference->_scheme !==
false) {
903 $target->_scheme = $reference->_scheme;
904 $target->setAuthority($reference->getAuthority());
905 $target->_path = self::removeDotSegments($reference->_path);
906 $target->_query = $reference->_query;
908 $authority = $reference->getAuthority();
909 if ($authority !==
false) {
910 $target->setAuthority($authority);
911 $target->_path = self::removeDotSegments($reference->_path);
912 $target->_query = $reference->_query;
914 if ($reference->_path ==
'') {
916 if ($reference->_query !==
false) {
917 $target->_query = $reference->_query;
922 if (substr($reference->_path, 0, 1) ==
'/') {
923 $target->_path = self::removeDotSegments($reference->_path);
926 if ($this->_host !==
false && $this->_path ==
'') {
927 $target->_path =
'/' . $reference->_path;
929 $i = strrpos($this->_path,
'/');
931 $target->_path = substr($this->_path, 0, $i + 1);
933 $target->_path .= $reference->_path;
935 $target->_path = self::removeDotSegments($target->_path);
937 $target->_query = $reference->_query;
944 $target->_fragment = $reference->_fragment;
958 $this->_fragment !==
false
959 && $this->_query ===
false
960 && $this->_path ===
''
961 && $this->_port ===
false
962 && $this->_host ===
false
963 && $this->_userinfo ===
false
964 && $this->_scheme ===
false
978 $path = (string) $path;
985 while (
'' !== $path && $j++ < $loopLimit) {
986 if (substr($path, 0, 2) ===
'./') {
988 $path = substr($path, 2);
989 }
elseif (substr($path, 0, 3) ===
'../') {
991 $path = substr($path, 3);
992 }
elseif (substr($path, 0, 3) ===
'/./' || $path ===
'/.') {
994 $path =
'/' . substr($path, 3);
995 }
elseif (substr($path, 0, 4) ===
'/../' || $path ===
'/..') {
997 $path =
'/' . substr($path, 4);
998 $i = strrpos($output,
'/');
999 $output = $i ===
false ?
'' : substr($output, 0, $i);
1000 }
elseif ($path ===
'.' || $path ===
'..') {
1005 $i = strpos($path,
'/', $path[0] ===
'/');
1011 $output .= substr($path, 0, $i);
1012 $path = substr($path, $i);
1018 'Unable to remove dot segments; hit loop limit %d (left: %s)',
1019 $j, var_export($path,
true)
1021 trigger_error($message, E_USER_WARNING);
1054 if (!isset($_SERVER[
'REQUEST_METHOD'])) {
1056 throw new Exception(
'Script was not called through a webserver');
1060 $url =
new self($_SERVER[
'PHP_SELF']);
1061 $url->_scheme = isset($_SERVER[
'HTTPS']) ?
'https' :
'http';
1062 $url->_host = $_SERVER[
'SERVER_NAME'];
1063 $port = $_SERVER[
'SERVER_PORT'];
1064 if (
$url->_scheme ==
'http' && $port != 80
1065 ||
$url->_scheme ==
'https' && $port != 443
1067 $url->_port = $port;
1079 return self::getRequested()->getUrl();
1091 if (!isset($_SERVER[
'REQUEST_METHOD'])) {
1093 throw new Exception(
'Script was not called through a webserver');
1097 $url =
new self($_SERVER[
'REQUEST_URI']);
1098 $url->_scheme = isset($_SERVER[
'HTTPS']) ?
'https' :
'http';
1100 $url->setAuthority($_SERVER[
'HTTP_HOST']);
1113 return isset($this->_options[$optionName])
1114 ? $this->_options[$optionName] :
false;
1128 protected function buildQuery(array $data, $separator, $key = null)
1132 $this->_options[self::OPTION_DROP_SEQUENCE] ===
true
1133 && array_keys($data) === array_keys(array_values($data))
1135 foreach ($data as $name => $value) {
1136 if ($this->
getOption(self::OPTION_ENCODE_KEYS) ===
true) {
1137 $name = rawurlencode($name);
1139 if ($key !== null) {
1140 if ($this->
getOption(self::OPTION_USE_BRACKETS) ===
true) {
1141 $drop_names && $name =
'';
1142 $name = $key .
'[' . $name .
']';
1147 if (is_array($value)) {
1148 $query[] = $this->
buildQuery($value, $separator, $name);
1150 $query[] = $name .
'=' . rawurlencode($value);
1153 return implode($separator, $query);
1171 '(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)',
1177 $this->_scheme = !empty($matches[1]) ? $matches[2] :
false;
1178 $this->
setAuthority(!empty($matches[3]) ? $matches[4] :
false);
1180 $this->_query = !empty($matches[6])
1184 $this->_fragment = !empty($matches[8]) ? $matches[9] :
false;
1200 return preg_replace_callback(
1201 '([\x-\x20\x22\x3C\x3E\x7F-\xFF]+)',
1202 array($this,
'_encodeCallback'),
$url
1217 return rawurlencode($matches[0]);