| 1 |
<?php |
| 2 |
|
| 3 |
declare (strict_types=1); |
| 4 |
namespace WCPOS\Vendor\GuzzleHttp\Psr7; |
| 5 |
|
| 6 |
/** |
| 7 |
* @internal |
| 8 |
*/ |
| 9 |
final class Rfc9112 |
| 10 |
{ |
| 11 |
/** |
| 12 |
* An HTTP protocol version for use in a regular expression. |
| 13 |
*/ |
| 14 |
public const PROTOCOL_VERSION_PATTERN = '\\d+(?:\\.\\d+)?'; |
| 15 |
/** |
| 16 |
* The request-target bytes accepted by the HTTP/1 start-line grammar for |
| 17 |
* use in a regular expression. |
| 18 |
*/ |
| 19 |
public const REQUEST_TARGET_PATTERN = '[^\\x00-\\x20\\x7F]+'; |
| 20 |
private function __construct() |
| 21 |
{ |
| 22 |
} |
| 23 |
/** |
| 24 |
* Header related regular expressions (based on amphp/http package) |
| 25 |
* |
| 26 |
* Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons. |
| 27 |
* |
| 28 |
* @see https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15 |
| 29 |
* |
| 30 |
* @license https://github.com/amphp/http/blob/v1.0.1/LICENSE |
| 31 |
*/ |
| 32 |
public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m"; |
| 33 |
public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; |
| 34 |
public static function isValidProtocolVersion(string $version) : bool |
| 35 |
{ |
| 36 |
return \preg_match('/^' . self::PROTOCOL_VERSION_PATTERN . '$/D', $version) === 1; |
| 37 |
} |
| 38 |
public static function isValidRequestTarget(string $target) : bool |
| 39 |
{ |
| 40 |
return \preg_match('/^' . self::REQUEST_TARGET_PATTERN . '$/D', $target) === 1; |
| 41 |
} |
| 42 |
public static function isValidReasonPhrase(string $reasonPhrase) : bool |
| 43 |
{ |
| 44 |
return Rfc9110::isFieldValue($reasonPhrase); |
| 45 |
} |
| 46 |
/** |
| 47 |
* @return array{0: string, 1: int|null}|null |
| 48 |
*/ |
| 49 |
public static function parseHostHeader(string $authority) : ?array |
| 50 |
{ |
| 51 |
if ($authority === '') { |
| 52 |
return null; |
| 53 |
} |
| 54 |
$host = $authority; |
| 55 |
$port = null; |
| 56 |
if (\str_starts_with($authority, '[')) { |
| 57 |
$closingBracket = \strpos($authority, ']'); |
| 58 |
if ($closingBracket === \false) { |
| 59 |
return null; |
| 60 |
} |
| 61 |
$host = \substr($authority, 0, $closingBracket + 1); |
| 62 |
$remainder = \substr($authority, $closingBracket + 1); |
| 63 |
if ($remainder !== '') { |
| 64 |
if (!\str_starts_with($remainder, ':')) { |
| 65 |
return null; |
| 66 |
} |
| 67 |
$port = self::parsePort(\substr($remainder, 1)); |
| 68 |
if ($port === null) { |
| 69 |
return null; |
| 70 |
} |
| 71 |
} |
| 72 |
} elseif (\false !== ($colon = \strpos($authority, ':'))) { |
| 73 |
$host = \substr($authority, 0, $colon); |
| 74 |
$port = self::parsePort(\substr($authority, $colon + 1)); |
| 75 |
if ($port === null) { |
| 76 |
return null; |
| 77 |
} |
| 78 |
} |
| 79 |
if ($host === '' || !Rfc3986::isValidHost($host)) { |
| 80 |
return null; |
| 81 |
} |
| 82 |
return [$host, $port]; |
| 83 |
} |
| 84 |
public static function isAbsoluteFormRequestTarget(string $target) : bool |
| 85 |
{ |
| 86 |
return \preg_match('/^[A-Za-z][A-Za-z0-9+.-]*:\\/\\//D', $target) === 1; |
| 87 |
} |
| 88 |
public static function isAsteriskFormRequestTarget(string $method, string $target) : bool |
| 89 |
{ |
| 90 |
return $method === 'OPTIONS' && $target === '*'; |
| 91 |
} |
| 92 |
public static function isConnectAuthorityFormRequestTarget(string $method, string $target) : bool |
| 93 |
{ |
| 94 |
return $method === 'CONNECT' && \strpbrk($target, '/?#') === \false; |
| 95 |
} |
| 96 |
public static function parsePort(string $port) : ?int |
| 97 |
{ |
| 98 |
if (!Rfc3986::isValidPort($port)) { |
| 99 |
return null; |
| 100 |
} |
| 101 |
// A zero port is valid per RFC 3986 but meaningless for an HTTP |
| 102 |
// authority, so reject it on top of the generic syntax check. |
| 103 |
$parsed = (int) \ltrim($port, '0'); |
| 104 |
return $parsed === 0 ? null : $parsed; |
| 105 |
} |
| 106 |
} |
| 107 |
|