89 lines
2.8 KiB
PHP
89 lines
2.8 KiB
PHP
<?php namespace App\Support;
|
|
|
|
class Base32
|
|
{
|
|
public static $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
|
|
|
/**
|
|
* Test if an encoded string is compatible with this encoder/decoder
|
|
*
|
|
* @param string $data The encoded string.
|
|
* @return boolean Returns true if the encoded string is compatible, otherwise false.
|
|
*/
|
|
public static function isValid($data)
|
|
{
|
|
return ((strlen($data) % 8) === 0 && preg_match("/^[".Base32::$charset."]+=*$/i", $data) === 1);
|
|
}
|
|
|
|
/**
|
|
* Encode a string of raw data
|
|
*
|
|
* @param string $data String of raw data to encode.
|
|
* @return string Returns the encoded string.
|
|
*/
|
|
public static function encode($data)
|
|
{
|
|
$encoded = null;
|
|
|
|
if ($data) {
|
|
$binString = '';
|
|
// 'AB' => 01000001 01000010
|
|
foreach (str_split($data) as $char) {
|
|
$binString .= str_pad(decbin(ord($char)), 8, 0, STR_PAD_LEFT);
|
|
}
|
|
|
|
// 01000001 01000010 => 01000 00101 00001 00000 => 'IFBA'
|
|
for ($offset = 0; $offset < strlen($binString); $offset += 5) {
|
|
$chunk = str_pad(substr($binString, $offset, 5), 5, 0, STR_PAD_RIGHT);
|
|
$encoded .= Base32::$charset[bindec($chunk)];
|
|
}
|
|
|
|
// 'IFBA' => 'IFBA===='
|
|
if (strlen($encoded) % 8) {
|
|
$encoded .= str_repeat('=', 8 - (strlen($encoded) % 8));
|
|
}
|
|
}
|
|
|
|
return $encoded;
|
|
}
|
|
|
|
/**
|
|
* Decode an encoded string
|
|
*
|
|
* @param string $data String of encoded data to decode.
|
|
* @return string Returns the decoded string.
|
|
* @throws given string is not valid for this encoder/decoder.
|
|
*/
|
|
public static function decode($data)
|
|
{
|
|
$decoded = null;
|
|
|
|
if ($data) {
|
|
if (!Base32::isValid($data)) {
|
|
throw new \Exception('Invalid base32 string');
|
|
}
|
|
|
|
// 'ifba====' => 'IFBA'
|
|
$data = rtrim(strtoupper($data), '=');
|
|
|
|
$binString = '';
|
|
// 'IFBA' => 01000 00101 00001 00000
|
|
foreach (str_split($data) as $char) {
|
|
$binString .= str_pad(decbin(strpos(Base32::$charset, $char)), 5, 0, STR_PAD_LEFT);
|
|
}
|
|
|
|
// 01000 00101 00001 00000 => 01000001 01000010
|
|
// Assuming it's safe to drop the trailing bits, as if this is a
|
|
// valid Base32 string, they'll be padding zeros anyway.
|
|
$binString = substr($binString, 0, (floor(strlen($binString) / 8) * 8));
|
|
|
|
// 01000001 01000010 => 'AB'
|
|
for ($offset = 0; $offset < strlen($binString); $offset += 8) {
|
|
$chunk = str_pad(substr($binString, $offset, 8), 8, 0, STR_PAD_RIGHT);
|
|
$decoded .= chr(bindec($chunk));
|
|
}
|
|
}
|
|
return $decoded;
|
|
}
|
|
}
|