|
|
|
<?php
|
|
|
|
namespace Base\Tool;
|
|
|
|
|
|
|
|
class Base62
|
|
|
|
{
|
|
|
|
const ENCODES = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/';
|
|
|
|
|
|
|
|
private static function getCharArray($string)
|
|
|
|
{
|
|
|
|
$list = [];
|
|
|
|
$length = strlen($string);
|
|
|
|
for ($i = 0; $i < $length; $i++) {
|
|
|
|
$list[] = $string[$i];
|
|
|
|
}
|
|
|
|
return $list;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static function getIndexChars($string) {
|
|
|
|
$length = strlen($string);
|
|
|
|
$chars = [];
|
|
|
|
for($i = 0; $i < 256; $i++) {
|
|
|
|
$chars[] = 0;
|
|
|
|
}
|
|
|
|
for($i = 0; $i < $length; $i++) {
|
|
|
|
$chars[$string[$i]] = $i ;
|
|
|
|
}
|
|
|
|
return $chars;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getSpecialChar($char, $default = null)
|
|
|
|
{
|
|
|
|
if ($default == null) {
|
|
|
|
$default = $char;
|
|
|
|
}
|
|
|
|
return $char == 'i' ? "ia" : ($char == '+' ? "ib" : ($char == '/' ? "ic" : $default));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function encode($string)
|
|
|
|
{
|
|
|
|
$encodes = self::getCharArray(self::ENCODES);
|
|
|
|
$bytes = self::stringToBytes($string);
|
|
|
|
$pos = 0;
|
|
|
|
$val = 0;
|
|
|
|
$result = [];
|
|
|
|
for ($i = 0; $i < count($bytes); $i++) {
|
|
|
|
$val = ($val << 8) | ($bytes[$i] & 0xFF);
|
|
|
|
$pos += 8;
|
|
|
|
while ($pos > 5) {
|
|
|
|
$char = $encodes[$val >> ($pos -= 6)];
|
|
|
|
$encodeChar = self::getSpecialChar($char);
|
|
|
|
$result[] = $encodeChar;
|
|
|
|
$val &= ((1 << $pos) - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($pos > 0) {
|
|
|
|
$char = $encodes[$val << (6 - $pos)];
|
|
|
|
$result[] = self::getSpecialChar($char);
|
|
|
|
}
|
|
|
|
return implode('', $result);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function decode($string)
|
|
|
|
{
|
|
|
|
$decodes = self::getIndexChars(self::ENCODES);
|
|
|
|
$chars = self::getCharArray($string);
|
|
|
|
$pos = 0;
|
|
|
|
$val = 0;
|
|
|
|
$bytes = [];
|
|
|
|
for ($i = 0; $i < count($chars); $i++) {
|
|
|
|
$char = $chars[$i];
|
|
|
|
if ($char == 'i') {
|
|
|
|
$char = $chars[++$i];
|
|
|
|
$char =
|
|
|
|
$char == 'a' ? 'i' :
|
|
|
|
($char == 'b' ? '+' :
|
|
|
|
($char == 'c' ? '/' : $chars[--$i]));
|
|
|
|
}
|
|
|
|
$val = ($val << 6) | $decodes[$char];
|
|
|
|
$pos += 6;
|
|
|
|
while ($pos > 7) {
|
|
|
|
$bytes[] = $val >> ($pos -= 8);
|
|
|
|
$val &= ((1 << $pos) - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return self::bytesToString($bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static function bytesToString($bytes) {
|
|
|
|
$string = '';
|
|
|
|
foreach($bytes as $byte) {
|
|
|
|
$string .= chr($byte);
|
|
|
|
}
|
|
|
|
return $string;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static function stringToBytes($string) {
|
|
|
|
$length = strlen($string);
|
|
|
|
$bytes = array();
|
|
|
|
for($i = 0; $i < $length; $i++) {
|
|
|
|
if(ord($string[$i]) >= 128){
|
|
|
|
$byte = ord($string[$i]) - 256;
|
|
|
|
}else{
|
|
|
|
$byte = ord($string[$i]);
|
|
|
|
}
|
|
|
|
$bytes[] = $byte ;
|
|
|
|
}
|
|
|
|
return $bytes;
|
|
|
|
}
|
|
|
|
}
|