From 869a1e1350d23841703a6b1f8dab643a31a32e57 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sun, 23 Apr 2023 01:05:46 -0600 Subject: [PATCH] Create base2n.php Add an MIT binary to text PHP class --- resources/classes/base2n.php | 304 +++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 resources/classes/base2n.php diff --git a/resources/classes/base2n.php b/resources/classes/base2n.php new file mode 100644 index 0000000000..e3f5eb6bb5 --- /dev/null +++ b/resources/classes/base2n.php @@ -0,0 +1,304 @@ += ($radix <<= 1) && $bitsPerCharacter < 8) { + $bitsPerCharacter++; + } + + $radix >>= 1; + throw new InvalidArgumentException( + '$bitsPerCharacter can not be more than ' . $bitsPerCharacter + . ' given $chars length of ' . $charLength + . ' (max radix ' . $radix . ')'); + + } elseif ($bitsPerCharacter > 8) { + // $bitsPerCharacter must not be greater than 8 + throw new InvalidArgumentException('$bitsPerCharacter can not be greater than 8'); + + } else { + $radix = 1 << $bitsPerCharacter; + } + + $this->_chars = $chars; + $this->_bitsPerCharacter = $bitsPerCharacter; + $this->_radix = $radix; + $this->_rightPadFinalBits = $rightPadFinalBits; + $this->_padFinalGroup = $padFinalGroup; + $this->_padCharacter = $padCharacter[0]; + $this->_caseSensitive = $caseSensitive; + } + + /** + * Encode a string + * + * @param string $rawString Binary data to encode + * @return string + */ + public function encode($rawString) + { + // Unpack string into an array of bytes + $bytes = unpack('C*', $rawString); + $byteCount = count($bytes); + + $encodedString = ''; + $byte = array_shift($bytes); + $bitsRead = 0; + $oldBits = 0; + + $chars = $this->_chars; + $bitsPerCharacter = $this->_bitsPerCharacter; + $rightPadFinalBits = $this->_rightPadFinalBits; + $padFinalGroup = $this->_padFinalGroup; + $padCharacter = $this->_padCharacter; + + $charsPerByte = 8 / $bitsPerCharacter; + $encodedLength = $byteCount * $charsPerByte; + + // Generate encoded output; each loop produces one encoded character + for ($c = 0; $c < $encodedLength; $c++) { + + // Get the bits needed for this encoded character + if ($bitsRead + $bitsPerCharacter > 8) { + // Not enough bits remain in this byte for the current character + // Save the remaining bits before getting the next byte + $oldBitCount = 8 - $bitsRead; + $oldBits = $byte ^ ($byte >> $oldBitCount << $oldBitCount); + $newBitCount = $bitsPerCharacter - $oldBitCount; + + if (!$bytes) { + // Last bits; match final character and exit loop + if ($rightPadFinalBits) $oldBits <<= $newBitCount; + $encodedString .= $chars[$oldBits]; + + if ($padFinalGroup) { + // Array of the lowest common multiples of $bitsPerCharacter and 8, divided by 8 + $lcmMap = array(1 => 1, 2 => 1, 3 => 3, 4 => 1, 5 => 5, 6 => 3, 7 => 7, 8 => 1); + $bytesPerGroup = $lcmMap[$bitsPerCharacter]; + $pads = $bytesPerGroup * $charsPerByte - ceil((strlen($rawString) % $bytesPerGroup) * $charsPerByte); + $encodedString .= str_repeat($padCharacter, $pads); + } + + break; + } + + // Get next byte + $byte = array_shift($bytes); + $bitsRead = 0; + + } else { + $oldBitCount = 0; + $newBitCount = $bitsPerCharacter; + } + + // Read only the needed bits from this byte + $bits = $byte >> 8 - ($bitsRead + ($newBitCount)); + $bits ^= $bits >> $newBitCount << $newBitCount; + $bitsRead += $newBitCount; + + if ($oldBitCount) { + // Bits come from seperate bytes, add $oldBits to $bits + $bits = ($oldBits << $newBitCount) | $bits; + } + + $encodedString .= $chars[$bits]; + } + + return $encodedString; + } + + /** + * Decode a string + * + * @param string $encodedString Data to decode + * @param boolean $strict Returns NULL if $encodedString contains an undecodable character + * @return string + */ + public function decode($encodedString, $strict = FALSE) + { + if (!$encodedString || !is_string($encodedString)) { + // Empty string, nothing to decode + return ''; + } + + $chars = $this->_chars; + $bitsPerCharacter = $this->_bitsPerCharacter; + $radix = $this->_radix; + $rightPadFinalBits = $this->_rightPadFinalBits; + $padFinalGroup = $this->_padFinalGroup; + $padCharacter = $this->_padCharacter; + $caseSensitive = $this->_caseSensitive; + + // Get index of encoded characters + if ($this->_charmap) { + $charmap = $this->_charmap; + + } else { + $charmap = array(); + + for ($i = 0; $i < $radix; $i++) { + $charmap[$chars[$i]] = $i; + } + + $this->_charmap = $charmap; + } + + // The last encoded character is $encodedString[$lastNotatedIndex] + $lastNotatedIndex = strlen($encodedString) - 1; + + // Remove trailing padding characters + if ($padFinalGroup) { + while ($encodedString[$lastNotatedIndex] === $padCharacter) { + $encodedString = substr($encodedString, 0, $lastNotatedIndex); + $lastNotatedIndex--; + } + } + + $rawString = ''; + $byte = 0; + $bitsWritten = 0; + + // Convert each encoded character to a series of unencoded bits + for ($c = 0; $c <= $lastNotatedIndex; $c++) { + + if (!$caseSensitive && !isset($charmap[$encodedString[$c]])) { + // Encoded character was not found; try other case + if (isset($charmap[$cUpper = strtoupper($encodedString[$c])])) { + $charmap[$encodedString[$c]] = $charmap[$cUpper]; + + } elseif (isset($charmap[$cLower = strtolower($encodedString[$c])])) { + $charmap[$encodedString[$c]] = $charmap[$cLower]; + } + } + + if (isset($charmap[$encodedString[$c]])) { + $bitsNeeded = 8 - $bitsWritten; + $unusedBitCount = $bitsPerCharacter - $bitsNeeded; + + // Get the new bits ready + if ($bitsNeeded > $bitsPerCharacter) { + // New bits aren't enough to complete a byte; shift them left into position + $newBits = $charmap[$encodedString[$c]] << $bitsNeeded - $bitsPerCharacter; + $bitsWritten += $bitsPerCharacter; + + } elseif ($c !== $lastNotatedIndex || $rightPadFinalBits) { + // Zero or more too many bits to complete a byte; shift right + $newBits = $charmap[$encodedString[$c]] >> $unusedBitCount; + $bitsWritten = 8; //$bitsWritten += $bitsNeeded; + + } else { + // Final bits don't need to be shifted + $newBits = $charmap[$encodedString[$c]]; + $bitsWritten = 8; + } + + $byte |= $newBits; + + if ($bitsWritten === 8 || $c === $lastNotatedIndex) { + // Byte is ready to be written + $rawString .= pack('C', $byte); + + if ($c !== $lastNotatedIndex) { + // Start the next byte + $bitsWritten = $unusedBitCount; + $byte = ($charmap[$encodedString[$c]] ^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten; + } + } + + } elseif ($strict) { + // Unable to decode character; abort + return NULL; + } + } + + return $rawString; + } +} + +?>