From 72841c395e30f88954349039853a027f0a1495e3 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 11 Dec 2023 14:13:41 +0100 Subject: [PATCH] New `InputValidator::is_valid_rfc2616_token()` method This new method validates that an arbitrary input parameter can be considered valid for use as a "token" as per the RFC 2616 specification. Includes tests. Ref: https://datatracker.ietf.org/doc/html/rfc2616#section-2.2 --- src/Utility/InputValidator.php | 23 +++ .../IsValidRfc2616TokenTest.php | 146 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 tests/Utility/InputValidator/IsValidRfc2616TokenTest.php diff --git a/src/Utility/InputValidator.php b/src/Utility/InputValidator.php index 25d849b23..0ec86f00c 100644 --- a/src/Utility/InputValidator.php +++ b/src/Utility/InputValidator.php @@ -109,4 +109,27 @@ public static function is_curl_handle($input) { return false; } + + /** + * Verify that a received input parameter is a valid "token name" according to the + * specification in RFC 2616 (HTTP/1.1). + * + * The short version is: 1 or more ascii characters, CTRL chars and separators not allowed. + * For the long version, see the specs in the RFC. + * + * @link https://datatracker.ietf.org/doc/html/rfc2616#section-2.2 + * + * @since 2.1.0 + * + * @param mixed $input Input parameter to verify. + * + * @return bool + */ + public static function is_valid_rfc2616_token($input) { + if (!is_int($input) && !is_string($input)) { + return false; + } + + return (preg_match('@^[0-9A-Za-z!#$%&\'*+.^_`|~-]+$@', $input) === 1); + } } diff --git a/tests/Utility/InputValidator/IsValidRfc2616TokenTest.php b/tests/Utility/InputValidator/IsValidRfc2616TokenTest.php new file mode 100644 index 000000000..81ca87534 --- /dev/null +++ b/tests/Utility/InputValidator/IsValidRfc2616TokenTest.php @@ -0,0 +1,146 @@ +assertTrue(InputValidator::is_valid_rfc2616_token($input)); + } + + /** + * Data Provider. + * + * @return array + */ + public static function dataValidIntegers() { + return TypeProviderHelper::getSelection(TypeProviderHelper::GROUP_INT); + } + + /** + * Data Provider. + * + * @return array + */ + public static function dataValidStrings() { + $all_valid_ascii = '!#$%&\'*+-.'; // Valid chars in ASCII 33-47 range. + // No valid chars in ASCII 58-64 range. + $all_valid_ascii .= '^_`'; // Valid chars in ASCII 91-96 range. + $all_valid_ascii .= '|~'; // Valid chars in ASCII 123-126 range. + + for ($char = 48; $char <= 57; $char++) { + // Chars 0-9. + $all_valid_ascii .= chr($char); + } + + for ($char = 65; $char <= 90; $char++) { + // Chars A-Z. + $all_valid_ascii .= chr($char); + } + + for ($char = 97; $char <= 122; $char++) { + // Chars a-z. + $all_valid_ascii .= chr($char); + } + + return [ + 'string containing only valid ascii characters / all valid ascii characters' => [ + 'input' => $all_valid_ascii, + ], + 'string with a typical cookie name' => [ + 'input' => 'requests-testcookie', + ], + ]; + } + + /** + * Test whether a received input parameter is correctly identified as NOT a valid RFC 2616 token. + * + * @dataProvider dataInvalidTypes + * @dataProvider dataInvalidValues + * + * @param mixed $input Input parameter to verify. + * + * @return void + */ + public function testInvalid($input) { + $this->assertFalse(InputValidator::is_valid_rfc2616_token($input)); + } + + /** + * Data Provider for invalid data types. + * + * @return array + */ + public static function dataInvalidTypes() { + return TypeProviderHelper::getAllExcept(TypeProviderHelper::GROUP_INT, TypeProviderHelper::GROUP_STRING); + } + + /** + * Data Provider for valid data types containing invalid values. + * + * @return array + */ + public static function dataInvalidValues() { + $all_control = chr(127); // DEL. + for ($char = 0; $char <= 31; $char++) { + $all_control .= chr($char); + } + + return [ + 'empty string' => [ + 'input' => '', + ], + 'string containing only control characters / all control characters' => [ + 'input' => $all_control, + ], + 'string containing control character at start' => [ + 'input' => chr(6) . 'some text', + ], + 'string containing control characters in text' => [ + 'input' => "some\ntext\rwith\tcontrol\echaracters\fin\vit", + ], + 'string containing control character at end' => [ + 'input' => 'some text' . chr(127), + ], + 'string containing only separator characters / all separator characters' => [ + 'input' => '()<>@,;:\\"/[]?={} ', + ], + 'string containing separator character at start' => [ + 'input' => '=value', + ], + 'string containing separator characters in text' => [ + 'input' => 'words "with" spaces and quotes', + ], + 'string containing separator character at end' => [ + 'input' => 'punctuated;', + ], + 'string containing separator characters - leading and trailing whitespace' => [ + 'input' => ' words ', + ], + 'string containing non-ascii characters - Iñtërnâtiônàlizætiøn' => [ + 'input' => 'Iñtërnâtiônàlizætiøn', + ], + 'string containing non-ascii characters - ௫' => [ + 'input' => '௫', // Tamil digit five. + ], + ]; + } +}