225 lines
6.3 KiB
PHP
225 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace App\Helpers;
|
|
|
|
class LZStringHelper
|
|
{
|
|
/**
|
|
* Decompresses a string compressed with LZ-String's compressToEncodedURIComponent method.
|
|
* This is a PHP port of the JavaScript LZ-String library.
|
|
*
|
|
* @param string $compressed
|
|
* @return string|null
|
|
*/
|
|
public static function decompressFromEncodedURIComponent($compressed)
|
|
{
|
|
if ($compressed === null || $compressed === '') {
|
|
return '';
|
|
}
|
|
|
|
// Replace URL-safe characters back
|
|
$compressed = str_replace(' ', '+', $compressed);
|
|
|
|
return self::decompress(strlen($compressed), 32, function ($index) use ($compressed) {
|
|
return self::getBaseValue(self::$keyStrUriSafe, $compressed[$index]);
|
|
});
|
|
}
|
|
|
|
private static $keyStrUriSafe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$';
|
|
|
|
private static function getBaseValue($alphabet, $character)
|
|
{
|
|
$pos = strpos($alphabet, $character);
|
|
|
|
return $pos !== false ? $pos : -1;
|
|
}
|
|
|
|
private static function decompress($length, $resetValue, $getNextValue)
|
|
{
|
|
$dictionary = [];
|
|
$enlargeIn = 4;
|
|
$dictSize = 4;
|
|
$numBits = 3;
|
|
$entry = '';
|
|
$result = [];
|
|
$data = ['val' => $getNextValue(0), 'position' => $resetValue, 'index' => 1];
|
|
|
|
for ($i = 0; $i < 3; $i++) {
|
|
$dictionary[$i] = chr($i);
|
|
}
|
|
|
|
$bits = 0;
|
|
$maxpower = pow(2, 2);
|
|
$power = 1;
|
|
|
|
while ($power != $maxpower) {
|
|
$resb = $data['val'] & $data['position'];
|
|
$data['position'] >>= 1;
|
|
|
|
if ($data['position'] == 0) {
|
|
$data['position'] = $resetValue;
|
|
$data['val'] = $getNextValue($data['index']++);
|
|
}
|
|
|
|
$bits |= ($resb > 0 ? 1 : 0) * $power;
|
|
$power <<= 1;
|
|
}
|
|
|
|
$next = $bits;
|
|
|
|
switch ($next) {
|
|
case 0:
|
|
$bits = 0;
|
|
$maxpower = pow(2, 8);
|
|
$power = 1;
|
|
|
|
while ($power != $maxpower) {
|
|
$resb = $data['val'] & $data['position'];
|
|
$data['position'] >>= 1;
|
|
|
|
if ($data['position'] == 0) {
|
|
$data['position'] = $resetValue;
|
|
$data['val'] = $getNextValue($data['index']++);
|
|
}
|
|
|
|
$bits |= ($resb > 0 ? 1 : 0) * $power;
|
|
$power <<= 1;
|
|
}
|
|
|
|
$c = chr($bits);
|
|
break;
|
|
|
|
case 1:
|
|
$bits = 0;
|
|
$maxpower = pow(2, 16);
|
|
$power = 1;
|
|
|
|
while ($power != $maxpower) {
|
|
$resb = $data['val'] & $data['position'];
|
|
$data['position'] >>= 1;
|
|
|
|
if ($data['position'] == 0) {
|
|
$data['position'] = $resetValue;
|
|
$data['val'] = $getNextValue($data['index']++);
|
|
}
|
|
|
|
$bits |= ($resb > 0 ? 1 : 0) * $power;
|
|
$power <<= 1;
|
|
}
|
|
|
|
$c = chr($bits);
|
|
break;
|
|
|
|
case 2:
|
|
return '';
|
|
}
|
|
|
|
$dictionary[$dictSize++] = $c;
|
|
$w = $c;
|
|
$result[] = $c;
|
|
|
|
while (true) {
|
|
if ($data['index'] > $length) {
|
|
return '';
|
|
}
|
|
|
|
$bits = 0;
|
|
$maxpower = pow(2, $numBits);
|
|
$power = 1;
|
|
|
|
while ($power != $maxpower) {
|
|
$resb = $data['val'] & $data['position'];
|
|
$data['position'] >>= 1;
|
|
|
|
if ($data['position'] == 0) {
|
|
$data['position'] = $resetValue;
|
|
$data['val'] = $getNextValue($data['index']++);
|
|
}
|
|
|
|
$bits |= ($resb > 0 ? 1 : 0) * $power;
|
|
$power <<= 1;
|
|
}
|
|
|
|
$c = $bits;
|
|
|
|
switch ($c) {
|
|
case 0:
|
|
$bits = 0;
|
|
$maxpower = pow(2, 8);
|
|
$power = 1;
|
|
|
|
while ($power != $maxpower) {
|
|
$resb = $data['val'] & $data['position'];
|
|
$data['position'] >>= 1;
|
|
|
|
if ($data['position'] == 0) {
|
|
$data['position'] = $resetValue;
|
|
$data['val'] = $getNextValue($data['index']++);
|
|
}
|
|
|
|
$bits |= ($resb > 0 ? 1 : 0) * $power;
|
|
$power <<= 1;
|
|
}
|
|
|
|
$dictionary[$dictSize++] = chr($bits);
|
|
$c = $dictSize - 1;
|
|
$enlargeIn--;
|
|
break;
|
|
|
|
case 1:
|
|
$bits = 0;
|
|
$maxpower = pow(2, 16);
|
|
$power = 1;
|
|
|
|
while ($power != $maxpower) {
|
|
$resb = $data['val'] & $data['position'];
|
|
$data['position'] >>= 1;
|
|
|
|
if ($data['position'] == 0) {
|
|
$data['position'] = $resetValue;
|
|
$data['val'] = $getNextValue($data['index']++);
|
|
}
|
|
|
|
$bits |= ($resb > 0 ? 1 : 0) * $power;
|
|
$power <<= 1;
|
|
}
|
|
|
|
$dictionary[$dictSize++] = chr($bits);
|
|
$c = $dictSize - 1;
|
|
$enlargeIn--;
|
|
break;
|
|
|
|
case 2:
|
|
return implode('', $result);
|
|
}
|
|
|
|
if ($enlargeIn == 0) {
|
|
$enlargeIn = pow(2, $numBits);
|
|
$numBits++;
|
|
}
|
|
|
|
if (isset($dictionary[$c])) {
|
|
$entry = $dictionary[$c];
|
|
} else {
|
|
if ($c === $dictSize) {
|
|
$entry = $w.$w[0];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
$result[] = $entry;
|
|
|
|
$dictionary[$dictSize++] = $w.$entry[0];
|
|
$enlargeIn--;
|
|
|
|
$w = $entry;
|
|
|
|
if ($enlargeIn == 0) {
|
|
$enlargeIn = pow(2, $numBits);
|
|
$numBits++;
|
|
}
|
|
}
|
|
}
|
|
}
|