Skip to content

Commit

Permalink
Improve implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Mar 27, 2024
1 parent 0c37300 commit 04fe762
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 19 deletions.
60 changes: 42 additions & 18 deletions src/Base32/Base32.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
use RuntimeException;
use ValueError;

use function array_key_exists;
use function chr;
use function rtrim;
use function str_replace;
use function str_split;
use function strcspn;
use function strlen;
use function strpos;
use function strtoupper;
use function substr;
use function unpack;

final class Base32
{
private const ALPHABET_SIZE = 32;
Expand All @@ -32,7 +44,7 @@ private function __construct(string $alphabet, string $padding)

$upperAlphabet = strtoupper($alphabet);
$upperPadding = strtoupper($padding);
if (32 !== strcspn($upperAlphabet, self::RESERVED_CHARACTERS.$upperPadding)) {
if (self::ALPHABET_SIZE !== strcspn($upperAlphabet, self::RESERVED_CHARACTERS.$upperPadding)) {
throw new ValueError('The alphabet can not contain a reserved character.');
}

Expand Down Expand Up @@ -102,20 +114,13 @@ public function decode(string $encoded, bool $strict = false): string
$encoded = strtoupper($encoded);
}

$remainder = strlen($encoded) % 8;
if (0 !== $remainder) {
if ($strict) {
throw new RuntimeException('The encoded data length is invalid.');
}

$encoded .= str_repeat($padding, $remainder);
}

$inside = rtrim($encoded, $padding);
$end = substr($encoded, strlen($inside));
$endLength = strlen($end);
if ($strict && 0 !== $endLength && 1 !== $endLength && 3 !== $endLength && 4 !== $endLength && 6 !== $endLength) {
throw new RuntimeException('The encoded data ends with an invalid padding sequence length.');
if ($strict) {
$endLength = strlen($end);
if (0 !== $endLength && 1 !== $endLength && 3 !== $endLength && 4 !== $endLength && 6 !== $endLength) {
throw new RuntimeException('The encoded data ends with an invalid padding sequence length.');
}
}

if (false !== strpos($inside, $padding)) {
Expand All @@ -126,21 +131,40 @@ public function decode(string $encoded, bool $strict = false): string
$encoded = str_replace($padding, '', $inside).$end;
}

$remainder = strlen($encoded) % 8;
if (0 !== $remainder) {
if ($strict) {
throw new RuntimeException('The encoded data length is invalid.');
}

$remainderStr = '';
for ($index = 0; $index < $remainder; $index++) {
$remainderStr .= $padding;
}

$encoded .= $remainderStr;
}

$chars = [];
foreach (str_split($alphabet) as $offset => $char) {
$chars[$char] = $offset;
for ($index = 0; $index < self::ALPHABET_SIZE; $index++) {
$chars[$alphabet[$index]] = $index;
}
$chars[$padding] = 0;

$offset = 0;
$bitLen = 5;
$length = strlen($encoded);
$decoded = '';

do {
$val ??= $chars[$encoded[$offset]] ?? -1;
if (!isset($val)) {
$index = $encoded[$offset];
$val = array_key_exists($index, $chars) ? $chars[$index] : -1;
}

if (-1 === $val) {
if ($strict) {
throw new RuntimeException('The encoded data contains characters unknown to the base32 alphabet.');
throw new RuntimeException('The encoded data contains characters unknown to the alphabet.');
}
$offset++;
if ($offset < $length) {
Expand All @@ -159,7 +183,7 @@ public function decode(string $encoded, bool $strict = false): string
}

if ($strict && !array_key_exists($pentet, $chars)) {
throw new RuntimeException('The encoded data contains characters unknown to the base32 alphabet.');
throw new RuntimeException('The encoded data contains characters unknown to the alphabet.');
}

$val = ($val << 5) + ($chars[$pentet] ?? 0);
Expand Down
2 changes: 1 addition & 1 deletion src/Base32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ If the strict parameter is set to `true` then the base32_decode() function will
- if encoded sequence length is invalid
- if the input contains character from outside the base64 alphabet.
- if padding is invalid
- if encoded characters are not all uppercased
- if encoded characters do not follow the alphabet lettercase.

otherwise listed constraints are silently ignored or discarded.

Expand Down

0 comments on commit 04fe762

Please sign in to comment.