Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
/**
4
 * This file is part of FPDI
5
 *
6
 * @package   setasign\Fpdi
7
 * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com)
8
 * @license   http://opensource.org/licenses/mit-license The MIT License
9
 */
10
 
11
namespace setasign\Fpdi\PdfParser\Filter;
12
 
13
/**
14
 * Class for handling LZW encoded data
15
 */
16
class Lzw implements FilterInterface
17
{
18
    /**
19
     * @var null|string
20
     */
21
    protected $data;
22
 
23
    /**
24
     * @var array
25
     */
26
    protected $sTable = [];
27
 
28
    /**
29
     * @var int
30
     */
31
    protected $dataLength = 0;
32
 
33
    /**
34
     * @var int
35
     */
36
    protected $tIdx;
37
 
38
    /**
39
     * @var int
40
     */
41
    protected $bitsToGet = 9;
42
 
43
    /**
44
     * @var int
45
     */
46
    protected $bytePointer;
47
 
48
    /**
49
     * @var int
50
     */
51
    protected $nextData = 0;
52
 
53
    /**
54
     * @var int
55
     */
56
    protected $nextBits = 0;
57
 
58
    /**
59
     * @var array
60
     */
61
    protected $andTable = [511, 1023, 2047, 4095];
62
 
63
    /**
64
     * Method to decode LZW compressed data.
65
     *
66
     * @param string $data The compressed data
67
     * @return string The uncompressed data
68
     * @throws LzwException
69
     */
70
    public function decode($data)
71
    {
72
        if ($data[0] === "\x00" && $data[1] === "\x01") {
73
            throw new LzwException(
74
                'LZW flavour not supported.',
75
                LzwException::LZW_FLAVOUR_NOT_SUPPORTED
76
            );
77
        }
78
 
79
        $this->initsTable();
80
 
81
        $this->data = $data;
82
        $this->dataLength = \strlen($data);
83
 
84
        // Initialize pointers
85
        $this->bytePointer = 0;
86
 
87
        $this->nextData = 0;
88
        $this->nextBits = 0;
89
 
90
        $prevCode = 0;
91
 
92
        $uncompData = '';
93
 
94
        while (($code = $this->getNextCode()) !== 257) {
95
            if ($code === 256) {
96
                $this->initsTable();
97
            } elseif ($prevCode === 256) {
98
                $uncompData .= $this->sTable[$code];
99
            } elseif ($code < $this->tIdx) {
100
                $string = $this->sTable[$code];
101
                $uncompData .= $string;
102
 
103
                $this->addStringToTable($this->sTable[$prevCode], $string[0]);
104
            } else {
105
                $string = $this->sTable[$prevCode];
106
                $string .= $string[0];
107
                $uncompData .= $string;
108
 
109
                $this->addStringToTable($string);
110
            }
111
            $prevCode = $code;
112
        }
113
 
114
        return $uncompData;
115
    }
116
 
117
    /**
118
     * Initialize the string table.
119
     */
120
    protected function initsTable()
121
    {
122
        $this->sTable = [];
123
 
124
        for ($i = 0; $i < 256; $i++) {
125
            $this->sTable[$i] = \chr($i);
126
        }
127
 
128
        $this->tIdx = 258;
129
        $this->bitsToGet = 9;
130
    }
131
 
132
    /**
133
     * Add a new string to the string table.
134
     *
135
     * @param string $oldString
136
     * @param string $newString
137
     */
138
    protected function addStringToTable($oldString, $newString = '')
139
    {
140
        $string = $oldString . $newString;
141
 
142
        // Add this new String to the table
143
        $this->sTable[$this->tIdx++] = $string;
144
 
145
        if ($this->tIdx === 511) {
146
            $this->bitsToGet = 10;
147
        } elseif ($this->tIdx === 1023) {
148
            $this->bitsToGet = 11;
149
        } elseif ($this->tIdx === 2047) {
150
            $this->bitsToGet = 12;
151
        }
152
    }
153
 
154
    /**
155
     * Returns the next 9, 10, 11 or 12 bits.
156
     *
157
     * @return int
158
     */
159
    protected function getNextCode()
160
    {
161
        if ($this->bytePointer === $this->dataLength) {
162
            return 257;
163
        }
164
 
165
        $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff);
166
        $this->nextBits += 8;
167
 
168
        if ($this->nextBits < $this->bitsToGet) {
169
            $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff);
170
            $this->nextBits += 8;
171
        }
172
 
173
        $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet - 9];
174
        $this->nextBits -= $this->bitsToGet;
175
 
176
        return $code;
177
    }
178
}