Browse Source

Path collapsing for special schemes

Also reject default authority for special schemes other than file
master
J. King 4 years ago
parent
commit
7ab046446d
  1. 36
      lib/Url.php

36
lib/Url.php

@ -360,10 +360,7 @@ PCRE;
protected function setPath(string $value): void {
if ($this->specialScheme) {
$value = str_replace("\\", "/", $value);
}
if ($this->scheme === "file" && preg_match(self::WINDOWS_PATH_PATTERN, $value, $match)) {
$value = "/".$match[1].":".$match[2];
$value = $this->collapsePath(str_replace("\\", "/", $value));
}
$this->path = $this->percentEncode($value, $this->isUrn() ? "C0" : "path");
}
@ -384,6 +381,35 @@ PCRE;
}
}
protected function collapsePath(string $path): string {
if (preg_match("<^/?$>", $path)) {
return $path;
}
if ($this->scheme === "file" && preg_match(self::WINDOWS_PATH_PATTERN, $path, $match)) {
$path = "/".$match[1].":".$match[2];
}
$abs = $path[0] === "/";
$dir = $path[-1] === "/";
$term = $dir || preg_match("</(?:\.|%2E){1,2}$>i", $path);
$path = explode("/", substr($path, (int) $abs, strlen($path) - ($abs + $dir)));
$out = [];
foreach ($path as $s) {
if (preg_match('/^(?:\.|%2E)$/i', $s)) {
// current-directory segment; these should simply be omitted
continue;
} elseif (preg_match('/^(?:\.|%2E){2}$/i', $s)) {
// parent-directory segment; pop a directory off the output
array_pop($out);
} else {
$out[] = $s;
}
}
if (!$out) {
return $abs ? "/" : "";
}
return ($abs ? "/" : "").implode("/", $out).($term ? "/" : "");
}
protected function percentEncode(string $data, string $type): string {
assert(array_key_exists($type, self::PERCENT_ENCODE_SETS), "Invalid percent-encoding set");
$out = "";
@ -455,6 +481,8 @@ PCRE;
if ($host === false) {
throw new \InvalidArgumentException("Invalid host in URL");
}
} elseif ($this->specialScheme && $this->scheme !== "file") {
throw new \InvalidArgumentException("Invalid host in URL");
}
return $host;
}

Loading…
Cancel
Save