| @@ -1,82 +1,120 @@ | ||
| 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 | -} | |
| 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 URLs | |
| 7 | + * (except for = char which can be excluded using the pad option for URLs). | |
| 8 | + * | |
| 9 | + * @package default | |
| 10 | + * @author Bryan Ruiz | |
| 11 | + **/ | |
| 12 | +class Base32 { | |
| 13 | + | |
| 14 | + private static $map = array( | |
| 15 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7 | |
| 16 | + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15 | |
| 17 | + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23 | |
| 18 | + 'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31 | |
| 19 | + '=' // padding char | |
| 20 | + ); | |
| 21 | + | |
| 22 | + private static $flippedMap = array( | |
| 23 | + 'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, 'H' => 7, | |
| 24 | + 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13, 'O' => 14, 'P' => 15, | |
| 25 | + 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23, | |
| 26 | + 'Y' => 24, 'Z' => 25, '2' => 26, '3' => 27, '4' => 28, '5' => 29, '6' => 30, '7' => 31 | |
| 27 | + ); | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * Use padding false when encoding for URLs. | |
| 31 | + * | |
| 32 | + * @return string | |
| 33 | + */ | |
| 34 | + public static function encode($input, $padding = true) { | |
| 35 | + if ($input === '' || $input === null) { | |
| 36 | + return ''; | |
| 37 | + } | |
| 38 | + | |
| 39 | + $input = (string) $input; | |
| 40 | + $inputLength = strlen($input); | |
| 41 | + $binaryString = ''; | |
| 42 | + | |
| 43 | + for ($i = 0; $i < $inputLength; $i++) { | |
| 44 | + $binaryString .= str_pad(base_convert((string) ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT); | |
| 45 | + } | |
| 46 | + | |
| 47 | + $fiveBitBinaryArray = str_split($binaryString, 5); | |
| 48 | + $base32 = ''; | |
| 49 | + $chunkCount = count($fiveBitBinaryArray); | |
| 50 | + | |
| 51 | + for ($i = 0; $i < $chunkCount; $i++) { | |
| 52 | + $base32 .= self::$map[(int) base_convert(str_pad($fiveBitBinaryArray[$i], 5, '0'), 2, 10)]; | |
| 53 | + } | |
| 54 | + | |
| 55 | + if ($padding) { | |
| 56 | + $x = strlen($binaryString) % 40; | |
| 57 | + if ($x !== 0) { | |
| 58 | + if ($x === 8) { | |
| 59 | + $base32 .= str_repeat(self::$map[32], 6); | |
| 60 | + } elseif ($x === 16) { | |
| 61 | + $base32 .= str_repeat(self::$map[32], 4); | |
| 62 | + } elseif ($x === 24) { | |
| 63 | + $base32 .= str_repeat(self::$map[32], 3); | |
| 64 | + } elseif ($x === 32) { | |
| 65 | + $base32 .= self::$map[32]; | |
| 66 | + } | |
| 67 | + } | |
| 68 | + } | |
| 69 | + | |
| 70 | + return $base32; | |
| 71 | + } | |
| 72 | + | |
| 73 | + public static function decode($input) { | |
| 74 | + if ($input === '' || $input === null) { | |
| 75 | + return ''; | |
| 76 | + } | |
| 77 | + | |
| 78 | + $input = strtoupper((string) $input); | |
| 79 | + $paddingCharCount = substr_count($input, self::$map[32]); | |
| 80 | + $allowedValues = array(6, 4, 3, 1, 0); | |
| 81 | + | |
| 82 | + if (!in_array($paddingCharCount, $allowedValues, true)) { | |
| 83 | + return false; | |
| 84 | + } | |
| 85 | + | |
| 86 | + for ($i = 0; $i < 4; $i++) { | |
| 87 | + if ( | |
| 88 | + $paddingCharCount === $allowedValues[$i] && | |
| 89 | + substr($input, -$allowedValues[$i]) !== str_repeat(self::$map[32], $allowedValues[$i]) | |
| 90 | + ) { | |
| 91 | + return false; | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + $input = str_replace('=', '', $input); | |
| 96 | + $input = str_split($input); | |
| 97 | + $binaryString = ''; | |
| 98 | + $inputCount = count($input); | |
| 99 | + | |
| 100 | + for ($i = 0; $i < $inputCount; $i++) { | |
| 101 | + if (!isset(self::$flippedMap[$input[$i]])) { | |
| 102 | + return false; | |
| 103 | + } | |
| 104 | + $binaryString .= str_pad(base_convert((string) self::$flippedMap[$input[$i]], 10, 2), 5, '0', STR_PAD_LEFT); | |
| 105 | + } | |
| 106 | + | |
| 107 | + $eightBits = str_split($binaryString, 8); | |
| 108 | + $output = ''; | |
| 109 | + $eightBitCount = count($eightBits); | |
| 110 | + | |
| 111 | + for ($z = 0; $z < $eightBitCount; $z++) { | |
| 112 | + if (strlen($eightBits[$z]) !== 8) { | |
| 113 | + continue; | |
| 114 | + } | |
| 115 | + $output .= chr((int) base_convert($eightBits[$z], 2, 10)); | |
| 116 | + } | |
| 117 | + | |
| 118 | + return $output; | |
| 119 | + } | |
| 120 | +} | |