| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* Encode in Base32 based on RFC 4648. |
| 5 |
* Requires 20% more space than base64 |
| 6 |
* Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls) |
| 7 |
* |
| 8 |
* @package default |
| 9 |
* @author Bryan Ruiz |
| 10 |
**/ |
| 11 |
class Base32 { |
| 12 |
|
| 13 |
private static $map = array( |
| 14 |
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7 |
| 15 |
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15 |
| 16 |
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23 |
| 17 |
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31 |
| 18 |
'=' // padding char |
| 19 |
); |
| 20 |
|
| 21 |
private static $flippedMap = array( |
| 22 |
'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7', |
| 23 |
'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15', |
| 24 |
'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23', |
| 25 |
'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31' |
| 26 |
); |
| 27 |
|
| 28 |
/** |
| 29 |
* Use padding false when encoding for urls |
| 30 |
* |
| 31 |
* @return base32 encoded string |
| 32 |
* @author Bryan Ruiz |
| 33 |
**/ |
| 34 |
public static function encode($input, $padding = true) { |
| 35 |
if(empty($input)) return ""; |
| 36 |
$input = str_split($input); |
| 37 |
$binaryString = ""; |
| 38 |
for($i = 0; $i < count($input); $i++) { |
| 39 |
$binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT); |
| 40 |
} |
| 41 |
$fiveBitBinaryArray = str_split($binaryString, 5); |
| 42 |
$base32 = ""; |
| 43 |
$i=0; |
| 44 |
while($i < count($fiveBitBinaryArray)) { |
| 45 |
$base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)]; |
| 46 |
$i++; |
| 47 |
} |
| 48 |
if($padding && ($x = strlen($binaryString) % 40) != 0) { |
| 49 |
if($x == 8) $base32 .= str_repeat(self::$map[32], 6); |
| 50 |
else if($x == 16) $base32 .= str_repeat(self::$map[32], 4); |
| 51 |
else if($x == 24) $base32 .= str_repeat(self::$map[32], 3); |
| 52 |
else if($x == 32) $base32 .= self::$map[32]; |
| 53 |
} |
| 54 |
return $base32; |
| 55 |
} |
| 56 |
|
| 57 |
public static function decode($input) { |
| 58 |
if(empty($input)) return; |
| 59 |
$paddingCharCount = substr_count($input, self::$map[32]); |
| 60 |
$allowedValues = array(6,4,3,1,0); |
| 61 |
if(!in_array($paddingCharCount, $allowedValues)) return false; |
| 62 |
for($i=0; $i<4; $i++){ |
| 63 |
if($paddingCharCount == $allowedValues[$i] && |
| 64 |
substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false; |
| 65 |
} |
| 66 |
$input = str_replace('=','', $input); |
| 67 |
$input = str_split($input); |
| 68 |
$binaryString = ""; |
| 69 |
for($i=0; $i < count($input); $i = $i+8) { |
| 70 |
$x = ""; |
| 71 |
if(!in_array($input[$i], self::$map)) return false; |
| 72 |
for($j=0; $j < 8; $j++) { |
| 73 |
$x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT); |
| 74 |
} |
| 75 |
$eightBits = str_split($x, 8); |
| 76 |
for($z = 0; $z < count($eightBits); $z++) { |
| 77 |
$binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:""; |
| 78 |
} |
| 79 |
} |
| 80 |
return $binaryString; |
| 81 |
} |
| 82 |
} |