diff --git a/Base32.php b/Base32.php index ece5236..bc0e82a 100644 --- a/Base32.php +++ b/Base32.php @@ -10,32 +10,23 @@ final class Base32 { private readonly string $alphabet; + private readonly string $padding; - private function __construct( - string $alphabet, - private readonly string $padding, - ) { - if (1 !== strlen($this->padding)) { - throw new ValueError('The padding character must be one byte long.'); - } - - if (in_array($this->padding, ["\r", "\n"], true)) { - throw new ValueError('The padding character is invalid.'); - } - - if (32 !== count(array_unique(str_split($alphabet)))) { - throw new ValueError('The alphabet must be 32 bytes long string containing unique characters.'); - } - - if ( - str_contains($alphabet, "\r") || - str_contains($alphabet, "\n") || - str_contains($alphabet, $this->padding) - ) { - throw new ValueError('The alphabet contains an invalid character.'); - } - - $this->alphabet = strtoupper($alphabet); + private function __construct(string $alphabet, string $padding) + { + $alphabet = strtoupper($alphabet); + + [$this->alphabet, $this->padding] = match (true) { + 1 !== strlen($padding) => throw new ValueError('The padding character must a single character.'), + "\r" === $padding => throw new ValueError('The padding character can not be the carriage return character.'), + "\n" === $padding => throw new ValueError('The padding character can not be the newline escape sequence.'), + 32 !== strlen($alphabet) => throw new ValueError('The alphabet must be a 32 bytes long string.'), + 32 !== count(array_unique(str_split($alphabet))) => throw new ValueError('The alphabet must contain unique characters.'), + str_contains($alphabet, "\r") => throw new ValueError('The alphabet can not contain the carriage return character.'), + str_contains($alphabet, "\n") => throw new ValueError('The alphabet can not contain the newline escape sequence.'), + str_contains($alphabet, strtoupper($padding)) => throw new ValueError('The alphabet can not contain the padding character.'), + default => [$alphabet, $padding], + }; } public static function new(string $alphabet, string $padding): self @@ -49,11 +40,12 @@ public function decode(string $encoded, bool $strict = false): string return ''; } + $encoded = str_replace(["\r", "\n"], [''], $encoded); if (!$strict) { - $encoded = strtoupper($encoded); + $encoded = str_replace(strtoupper($this->padding), $this->padding, strtoupper($encoded)); } - if (strtoupper($encoded) !== $encoded) { + if (str_replace(strtoupper($this->padding), $this->padding, strtoupper($encoded)) !== $encoded) { throw new RuntimeException('The encoded data contains non uppercased characters.'); } diff --git a/Base32Test.php b/Base32Test.php index da8da99..02bf1cc 100644 --- a/Base32Test.php +++ b/Base32Test.php @@ -57,6 +57,17 @@ public function it_will_base32_encode_and_decode(string $string): void self::assertSame($string, base32_decode(base32_encode($string, PHP_BASE32_HEX), PHP_BASE32_HEX)); } + #[Test] + public function it_will_base32_decode_multiline_data(): void + { + $base32 = << [ 'sequence' => 'A', - 'message' => 'The alphabet must be 32 bytes long string containing unique characters.', + 'message' => 'The alphabet must be a 32 bytes long string.', 'alphabet' => '1234567890asdfghjklzxcvbnm', 'padding' => '=', ]; yield 'the padding character is contained within the alphabet' => [ 'sequence' => 'A', - 'message' => 'The alphabet contains an invalid character.', + 'message' => 'The alphabet can not contain the padding character.', 'alphabet' => str_replace('A', '*', PHP_BASE32_ASCII), 'padding' => '*', ]; + yield 'the padding character is contained within the alphabet is case insensitive' => [ + 'sequence' => 'A', + 'message' => 'The alphabet can not contain the padding character.', + 'alphabet' => str_replace('A', '*', PHP_BASE32_ASCII), + 'padding' => 'a', + ]; + yield 'the padding character is different than one byte' => [ 'sequence' => 'A', - 'message' => 'The padding character must be one byte long.', + 'message' => 'The padding character must a single character.', 'alphabet' => PHP_BASE32_ASCII, 'padding' => 'yo', ]; yield 'the padding character can not contain "\r"' => [ 'sequence' => 'A', - 'message' => 'The padding character is invalid.', + 'message' => 'The padding character can not be the carriage return character.', 'alphabet' => PHP_BASE32_ASCII, 'padding' => "\r", ]; yield 'the padding character can not contain "\n"' => [ 'sequence' => 'A', - 'message' => 'The padding character is invalid.', + 'message' => 'The padding character can not be the newline escape sequence.', 'alphabet' => PHP_BASE32_ASCII, 'padding' => "\n", ];