From 598808a37cf6182a998baf9e9fa7e63f68833e17 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 15 May 2020 17:41:10 -0400 Subject: [PATCH] More host-parsing fixes --- lib/Url.php | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/Url.php b/lib/Url.php index dc05f15..687641e 100644 --- a/lib/Url.php +++ b/lib/Url.php @@ -44,7 +44,7 @@ class Url implements UriInterface { (\#.*)? # fragment part $>six PCRE; - protected const HOST_PATTERN = '/^(\[[a-f0-9:\.]*\]|[^:]*)(?::([^\/]*))?$/si'; + protected const HOST_PATTERN = '/^(\[[a-f0-9:\.]*\]|[^:]*)(:[^\/]*)?$/si'; protected const USER_PATTERN = '/^([^:]*)(?::(.*))?$/s'; 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 @@ -154,11 +154,21 @@ PCRE; } if (preg_match(self::HOST_PATTERN, substr($auth, $cleft + 1), $match)) { $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)) { $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 @@ -404,7 +414,9 @@ PCRE; protected function collapsePath(string $path, string $base = ""): string { $winDrive = ""; - if ($this->scheme === "file") { + if ($path === "") { + return $base; + } elseif ($this->scheme === "file") { if (preg_match(self::WINDOWS_PATH_PATTERN, $path, $match)) { // If a Windows drive letter is present, the host is implicitly localhost $this->setHost(""); @@ -414,16 +426,13 @@ PCRE; $this->setHost(""); $winDrive = $match[1].":"; } - } - if ($path === "/") { + } elseif ($path === "/") { return $path; - } elseif ($path === "") { - return $base; } $abs = $path[0] === "/"; $dir = $path[-1] === "/"; $term = $dir || preg_match("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)) { // also consider the base path, if appropriate $abs = $base[0] === "/"; @@ -451,8 +460,7 @@ PCRE; $term = true; } array_unshift($out, $winDrive); - } - if (!$out) { + } elseif (!$out) { return $abs ? "/" : ""; } return ($abs ? "/" : "").implode("/", $out).($term ? "/" : "");