menzilmekan-backend/plugins/offline/cors/classes/OriginMatcher.php

100 lines
3.3 KiB
PHP

<?php
namespace OFFLINE\CORS\Classes;
class OriginMatcher
{
public static function matches($pattern, $origin)
{
if ($pattern === $origin) {
return true;
}
$scheme = parse_url($origin, PHP_URL_SCHEME);
$host = parse_url($origin, PHP_URL_HOST);
$port = parse_url($origin, PHP_URL_PORT);
$schemePattern = static::parseOriginPattern($pattern, PHP_URL_SCHEME);
$hostPattern = static::parseOriginPattern($pattern, PHP_URL_HOST);
$portPattern = static::parseOriginPattern($pattern, PHP_URL_PORT);
$schemeMatches = static::schemeMatches($schemePattern, $scheme);
$hostMatches = static::hostMatches($hostPattern, $host);
$portMatches = static::portMatches($portPattern, $port);
return $schemeMatches && $hostMatches && $portMatches;
}
public static function schemeMatches($pattern, $scheme)
{
return is_null($pattern) || $pattern === $scheme;
}
public static function hostMatches($pattern, $host)
{
$patternComponents = array_reverse(explode('.', $pattern));
$hostComponents = array_reverse(explode('.', $host));
foreach ($patternComponents as $index => $patternComponent) {
if ($patternComponent === '*') {
return true;
}
if ( ! isset($hostComponents[$index])) {
return false;
}
if ($hostComponents[$index] !== $patternComponent) {
return false;
}
}
return count($patternComponents) === count($hostComponents);
}
public static function portMatches($pattern, $port)
{
if ($pattern === "*") {
return true;
}
if ((string)$pattern === "") {
return (string)$port === "";
}
if (preg_match('/\A\d+\z/', $pattern)) {
return (string)$pattern === (string)$port;
}
if (preg_match('/\A(?P<from>\d+)-(?P<to>\d+)\z/', $pattern, $captured)) {
return $captured['from'] <= $port && $port <= $captured['to'];
}
throw new \InvalidArgumentException("Invalid port pattern: ${pattern}");
}
public static function parseOriginPattern($originPattern, $component = -1)
{
$matched = preg_match(
'!\A
(?: (?P<scheme> ([a-z][a-z0-9+\-.]*) ):// )?
(?P<host> (?:\*|[\w-]+)(?:\.[\w-]+)* )
(?: :(?P<port> (?: \*|\d+(?:-\d+)? ) ) )?
\z!x',
$originPattern,
$captured
);
if ( ! $matched) {
throw new \InvalidArgumentException("Invalid origin pattern ${originPattern}");
}
$components = [
'scheme' => $captured['scheme'] ?: null,
'host' => $captured['host'],
'port' => array_key_exists('port', $captured) ? $captured['port'] : null,
];
switch ($component) {
case -1:
return $components;
case PHP_URL_SCHEME:
return $components['scheme'];
case PHP_URL_HOST:
return $components['host'];
case PHP_URL_PORT:
return $components['port'];
}
throw new \InvalidArgumentException("Invalid component: ${component}");
}
}