Browse Source

More host-parsing fixes

master
J. King 4 years ago
parent
commit
598808a37c
  1. 30
      lib/Url.php

30
lib/Url.php

@ -44,7 +44,7 @@ class Url implements UriInterface {
(\#.*)? # fragment part (\#.*)? # fragment part
$>six $>six
PCRE; PCRE;
protected const HOST_PATTERN = '/^(\[[a-f0-9:\.]*\]|[^:]*)(?::([^\/]*))?$/si'; protected const HOST_PATTERN = '/^(\[[a-f0-9:\.]*\]|[^:]*)(:[^\/]*)?$/si';
protected const USER_PATTERN = '/^([^:]*)(?::(.*))?$/s'; protected const USER_PATTERN = '/^([^:]*)(?::(.*))?$/s';
protected const SCHEME_PATTERN = '/^(?:[a-z][a-z0-9\.\-\+]*|)$/i'; protected const SCHEME_PATTERN = '/^(?:[a-z][a-z0-9\.\-\+]*|)$/i';
protected const IPV4_PATTERN = '/^[\.xX0-9a-fA-F\x{ff10}-\x{ff19}\x{ff21}-\x{ff26}\x{ff41}-\x{ff46}\x{ff38}\x{ff58}\x{ff0e}]*$/u'; // matches ASCII and fullwidth equivalents protected const IPV4_PATTERN = '/^[\.xX0-9a-fA-F\x{ff10}-\x{ff19}\x{ff21}-\x{ff26}\x{ff41}-\x{ff46}\x{ff38}\x{ff58}\x{ff0e}]*$/u'; // matches ASCII and fullwidth equivalents
@ -154,11 +154,21 @@ PCRE;
} }
if (preg_match(self::HOST_PATTERN, substr($auth, $cleft + 1), $match)) { if (preg_match(self::HOST_PATTERN, substr($auth, $cleft + 1), $match)) {
$this->setHost($match[1]); $this->setHost($match[1]);
$this->setPort($match[2] ?? ""); if ($match[2] ?? "") {
$this->setPort(substr($match[2], 1));
}
}
if (!$this->specialScheme && !strlen($match[1])) {
throw new \InvalidArgumentException("Credentials with default host in URL");
} }
} elseif (preg_match(self::HOST_PATTERN, $auth, $match)) { } elseif (preg_match(self::HOST_PATTERN, $auth, $match)) {
$this->setHost($match[1]); $this->setHost($match[1]);
$this->setPort($match[2] ?? ""); if ($match[2] ?? "") {
if (!$this->specialScheme && !strlen($match[1])) {
throw new \InvalidArgumentException("Port with default host in URL");
}
$this->setPort(substr($match[2], 1));
}
} }
} }
// resolve with the base, if necessary // resolve with the base, if necessary
@ -404,7 +414,9 @@ PCRE;
protected function collapsePath(string $path, string $base = ""): string { protected function collapsePath(string $path, string $base = ""): string {
$winDrive = ""; $winDrive = "";
if ($this->scheme === "file") { if ($path === "") {
return $base;
} elseif ($this->scheme === "file") {
if (preg_match(self::WINDOWS_PATH_PATTERN, $path, $match)) { if (preg_match(self::WINDOWS_PATH_PATTERN, $path, $match)) {
// If a Windows drive letter is present, the host is implicitly localhost // If a Windows drive letter is present, the host is implicitly localhost
$this->setHost(""); $this->setHost("");
@ -414,16 +426,13 @@ PCRE;
$this->setHost(""); $this->setHost("");
$winDrive = $match[1].":"; $winDrive = $match[1].":";
} }
} } elseif ($path === "/") {
if ($path === "/") {
return $path; return $path;
} elseif ($path === "") {
return $base;
} }
$abs = $path[0] === "/"; $abs = $path[0] === "/";
$dir = $path[-1] === "/"; $dir = $path[-1] === "/";
$term = $dir || preg_match("</(?:\.|%2E){1,2}$>i", $path); $term = $dir || preg_match("</(?:\.|%2E){1,2}$>i", $path);
$path = explode("/", substr($path, (int) $abs, strlen($path) - ($abs + $dir))); $path = explode("/", (string) substr($path, (int) $abs, strlen($path) - ($abs + $dir)));
if (!$abs && strlen($base)) { if (!$abs && strlen($base)) {
// also consider the base path, if appropriate // also consider the base path, if appropriate
$abs = $base[0] === "/"; $abs = $base[0] === "/";
@ -451,8 +460,7 @@ PCRE;
$term = true; $term = true;
} }
array_unshift($out, $winDrive); array_unshift($out, $winDrive);
} } elseif (!$out) {
if (!$out) {
return $abs ? "/" : ""; return $abs ? "/" : "";
} }
return ($abs ? "/" : "").implode("/", $out).($term ? "/" : ""); return ($abs ? "/" : "").implode("/", $out).($term ? "/" : "");

Loading…
Cancel
Save