2023-08-26 16:28:29 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace BookStack\Util;
|
|
|
|
|
|
|
|
use BookStack\Exceptions\HttpFetchException;
|
|
|
|
|
|
|
|
class SsrUrlValidator
|
|
|
|
{
|
|
|
|
protected string $config;
|
|
|
|
|
|
|
|
public function __construct(string $config = null)
|
|
|
|
{
|
|
|
|
$this->config = $config ?? config('app.ssr_hosts') ?? '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @throws HttpFetchException
|
|
|
|
*/
|
|
|
|
public function ensureAllowed(string $url): void
|
|
|
|
{
|
|
|
|
if (!$this->allowed($url)) {
|
|
|
|
throw new HttpFetchException(trans('errors.http_ssr_url_no_match'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the given URL is allowed by the configured SSR host values.
|
|
|
|
*/
|
|
|
|
public function allowed(string $url): bool
|
|
|
|
{
|
|
|
|
$allowed = $this->getHostPatterns();
|
|
|
|
|
|
|
|
foreach ($allowed as $pattern) {
|
|
|
|
if ($this->urlMatchesPattern($url, $pattern)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function urlMatchesPattern($url, $pattern): bool
|
|
|
|
{
|
2023-08-26 21:13:37 +02:00
|
|
|
$pattern = rtrim(trim($pattern), '/');
|
2023-08-26 16:28:29 +02:00
|
|
|
$url = trim($url);
|
|
|
|
|
|
|
|
if (empty($pattern) || empty($url)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$quoted = preg_quote($pattern, '/');
|
|
|
|
$regexPattern = str_replace('\*', '.*', $quoted);
|
|
|
|
|
2023-08-26 21:13:37 +02:00
|
|
|
return preg_match('/^' . $regexPattern . '($|\/.*$|#.*$)/i', $url);
|
2023-08-26 16:28:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
protected function getHostPatterns(): array
|
|
|
|
{
|
|
|
|
return explode(' ', strtolower($this->config));
|
|
|
|
}
|
|
|
|
}
|