@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m"; public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; /** * @return array{0: string, 1: int|null}|null */ public static function parseHostHeader(string $authority) : ?array { if ($authority === '') { return null; } $host = $authority; $port = null; if ($authority[0] === '[') { $closingBracket = \strpos($authority, ']'); if ($closingBracket === \false) { return null; } $host = \substr($authority, 0, $closingBracket + 1); $remainder = \substr($authority, $closingBracket + 1); if ($remainder !== '') { if ($remainder[0] !== ':') { return null; } $port = self::parseAuthorityPort(\substr($remainder, 1)); if ($port === null) { return null; } } } elseif (\false !== ($colon = \strpos($authority, ':'))) { $host = \substr($authority, 0, $colon); $port = self::parseAuthorityPort(\substr($authority, $colon + 1)); if ($port === null) { return null; } } if ($host === '' || !self::isValidHostHeaderHost($host)) { return null; } return [$host, $port]; } private static function isValidHostHeaderHost(string $host) : bool { if (\preg_match('/[\\x00-\\x20\\x7F\\/\\?#@\\\\]/', $host)) { return \false; } if (\strpos($host, '[') !== \false || \strpos($host, ']') !== \false) { if ($host[0] !== '[' || \substr($host, -1) !== ']') { return \false; } $address = \substr($host, 1, -1); return \filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6) !== \false || \preg_match('/^v[0-9a-f]+\\.[' . \YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc3986::CHAR_UNRESERVED . \YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc3986::CHAR_SUB_DELIMS . ':]+$/iD', $address) === 1; } return \strpos($host, ':') === \false; } private static function parseAuthorityPort(string $port) : ?int { if ($port === '' || !\ctype_digit($port)) { return null; } $normalized = \ltrim($port, '0'); if ($normalized === '') { return 0; } if (\strlen($normalized) > 5 || (int) $normalized > 0xffff) { return null; } return (int) $normalized; } }