From e357f5919a14e2666005f26da7ee78fd8993247a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 5 Mar 2021 16:41:01 +0100 Subject: [PATCH] Make HtmlOutputNodeImg::getHostMatcher() reusable as Url::getHostnameMatcher() --- .../output/node/HtmlOutputNodeImg.class.php | 55 ++----------------- wcfsetup/install/files/lib/util/Url.class.php | 52 ++++++++++++++++++ 2 files changed, 57 insertions(+), 50 deletions(-) diff --git a/wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeImg.class.php b/wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeImg.class.php index 0f16d95070..f6439a609a 100644 --- a/wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeImg.class.php +++ b/wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeImg.class.php @@ -195,56 +195,11 @@ class HtmlOutputNodeImg extends AbstractHtmlOutputNode } /** - * Returns a function that matches hosts against the given whitelist. - * The whitelist supports wildcards using using `*.` prefix. - * - * @param string[] $whitelist - * @return callable + * @deprecated 5.4 Use Url::getHostnameMatcher(). */ - protected function getHostMatcher(array $whitelist) + protected function getHostMatcher(array $hostnames) { - $hosts = []; - foreach ($whitelist as $host) { - $isWildcard = false; - if (\mb_strpos($host, '*') !== false) { - $host = \preg_replace('~^(\*\.)+~', '', $host); - if (\mb_strpos($host, '*') !== false || $host === '') { - // bad host - continue; - } - - $isWildcard = true; - } - - $host = \mb_strtolower($host); - if (!isset($hosts[$host])) { - $hosts[$host] = $isWildcard; - } - } - - return static function ($hostname) use ($hosts) { - static $validHosts = []; - - $hostname = \mb_strtolower($hostname); - if (isset($hosts[$hostname]) || isset($validHosts[$hostname])) { - return true; - } else { - // check wildcard hosts - foreach ($hosts as $host => $isWildcard) { - if ($isWildcard && \mb_strpos($hostname, $host) !== false) { - // the prepended dot will ensure that `example.com` matches only - // on domains like `foo.example.com` but not on `bar-example.com` - if (StringUtil::endsWith($hostname, '.' . $host)) { - $validHosts[$hostname] = $hostname; - - return true; - } - } - } - } - - return false; - }; + return Url::getHostnameMatcher($hostnames); } /** @@ -266,7 +221,7 @@ class HtmlOutputNodeImg extends AbstractHtmlOutputNode $whitelist[] = $host; } - $matcher = $this->getHostMatcher($whitelist); + $matcher = Url::getHostnameMatcher($whitelist); } return $matcher($hostname); @@ -303,7 +258,7 @@ class HtmlOutputNodeImg extends AbstractHtmlOutputNode $whitelist[] = $host; } - $matcher = $this->getHostMatcher($whitelist); + $matcher = Url::getHostnameMatcher($whitelist); } $host = Url::parse($src)['host']; diff --git a/wcfsetup/install/files/lib/util/Url.class.php b/wcfsetup/install/files/lib/util/Url.class.php index 8b0ac217e0..4a0b0aec8d 100644 --- a/wcfsetup/install/files/lib/util/Url.class.php +++ b/wcfsetup/install/files/lib/util/Url.class.php @@ -168,4 +168,56 @@ final class Url implements \ArrayAccess throw new \RuntimeException("Unknown url component offset '" . $property . "'."); } + + /** + * Returns a matcher that decides whether the URL matches the given list of hostnames. Hostnames may contain an + * optional wildcard prefix (`*.`). + * + * @since 5.4 + */ + public static function getHostnameMatcher(array $hostnames): callable + { + $hosts = []; + foreach ($hostnames as $host) { + $isWildcard = false; + if (\mb_strpos($host, '*') !== false) { + $host = \preg_replace('~^(\*\.)+~', '', $host); + if (\mb_strpos($host, '*') !== false || $host === '') { + // bad host + continue; + } + + $isWildcard = true; + } + + $host = \mb_strtolower($host); + if (!isset($hosts[$host])) { + $hosts[$host] = $isWildcard; + } + } + + return static function ($hostname) use ($hosts) { + static $validHosts = []; + + $hostname = \mb_strtolower($hostname); + if (isset($hosts[$hostname]) || isset($validHosts[$hostname])) { + return true; + } else { + // check wildcard hosts + foreach ($hosts as $host => $isWildcard) { + if ($isWildcard && \mb_strpos($hostname, $host) !== false) { + // the prepended dot will ensure that `example.com` matches only + // on domains like `foo.example.com` but not on `bar-example.com` + if (StringUtil::endsWith($hostname, '.' . $host)) { + $validHosts[$hostname] = $hostname; + + return true; + } + } + } + } + + return false; + }; + } } -- 2.20.1