Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
<?php

/**
 * This file is part of FPDI
 *
 * @package   setasign\Fpdi
 * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
 * @license   http://opensource.org/licenses/mit-license The MIT License
 */

namespace setasign\Fpdi\PdfParser\Filter;

/**
 * Class for handling LZW encoded data
 */
class Lzw implements FilterInterface
{
    /**
     * @var null|string
     */
    protected $data;

    /**
     * @var array
     */
    protected $sTable = [];

    /**
     * @var int
     */
    protected $dataLength = 0;

    /**
     * @var int
     */
    protected $tIdx;

    /**
     * @var int
     */
    protected $bitsToGet = 9;

    /**
     * @var int
     */
    protected $bytePointer;

    /**
     * @var int
     */
    protected $nextData = 0;

    /**
     * @var int
     */
    protected $nextBits = 0;

    /**
     * @var array
     */
    protected $andTable = [511, 1023, 2047, 4095];

    /**
     * Method to decode LZW compressed data.
     *
     * @param string $data The compressed data
     * @return string The uncompressed data
     * @throws LzwException
     */
    public function decode($data)
    {
        if ($data[0] === "\x00" && $data[1] === "\x01") {
            throw new LzwException(
                'LZW flavour not supported.',
                LzwException::LZW_FLAVOUR_NOT_SUPPORTED
            );
        }

        $this->initsTable();

        $this->data = $data;
        $this->dataLength = \strlen($data);

        // Initialize pointers
        $this->bytePointer = 0;

        $this->nextData = 0;
        $this->nextBits = 0;

< $oldCode = 0;
> $prevCode = 0;
$uncompData = ''; while (($code = $this->getNextCode()) !== 257) { if ($code === 256) { $this->initsTable();
< $code = $this->getNextCode(); < < if ($code === 257) { < break; < } <
> } elseif ($prevCode === 256) {
$uncompData .= $this->sTable[$code];
< $oldCode = $code; < } else { < if ($code < $this->tIdx) {
> } elseif ($code < $this->tIdx) {
$string = $this->sTable[$code]; $uncompData .= $string;
< $this->addStringToTable($this->sTable[$oldCode], $string[0]); < $oldCode = $code;
> $this->addStringToTable($this->sTable[$prevCode], $string[0]);
} else {
< $string = $this->sTable[$oldCode];
> $string = $this->sTable[$prevCode];
$string .= $string[0]; $uncompData .= $string; $this->addStringToTable($string);
< $oldCode = $code; < }
}
> $prevCode = $code;
} return $uncompData; } /** * Initialize the string table. */ protected function initsTable() { $this->sTable = []; for ($i = 0; $i < 256; $i++) { $this->sTable[$i] = \chr($i); } $this->tIdx = 258; $this->bitsToGet = 9; } /** * Add a new string to the string table. * * @param string $oldString * @param string $newString */ protected function addStringToTable($oldString, $newString = '') { $string = $oldString . $newString; // Add this new String to the table $this->sTable[$this->tIdx++] = $string; if ($this->tIdx === 511) { $this->bitsToGet = 10; } elseif ($this->tIdx === 1023) { $this->bitsToGet = 11; } elseif ($this->tIdx === 2047) { $this->bitsToGet = 12; } } /** * Returns the next 9, 10, 11 or 12 bits. *
< * @return integer
> * @return int
*/ protected function getNextCode() { if ($this->bytePointer === $this->dataLength) { return 257; } $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff); $this->nextBits += 8; if ($this->nextBits < $this->bitsToGet) { $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff); $this->nextBits += 8; } $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet - 9]; $this->nextBits -= $this->bitsToGet; return $code; } }