source: trunk/client/inc/hpdf5/tecnickcom/tcpdf/include/tcpdf_filters.php@ 347

Last change on this file since 347 was 347, checked in by roby, 3 years ago

Aggiornamento per compatibilità con php7.4

File size: 14.3 KB
Line 
1<?php
2//============================================================+
3// File name : tcpdf_filters.php
4// Version : 1.0.001
5// Begin : 2011-05-23
6// Last Update : 2014-04-25
7// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
8// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
9// -------------------------------------------------------------------
10// Copyright (C) 2011-2013 Nicola Asuni - Tecnick.com LTD
11//
12// This file is part of TCPDF software library.
13//
14// TCPDF is free software: you can redistribute it and/or modify it
15// under the terms of the GNU Lesser General Public License as
16// published by the Free Software Foundation, either version 3 of the
17// License, or (at your option) any later version.
18//
19// TCPDF is distributed in the hope that it will be useful, but
20// WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22// See the GNU Lesser General Public License for more details.
23//
24// You should have received a copy of the License
25// along with TCPDF. If not, see
26// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
27//
28// See LICENSE.TXT file for more information.
29// -------------------------------------------------------------------
30//
31// Description : This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).
32//
33//============================================================+
34
35/**
36 * @file
37 * This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).<br>
38 * @package com.tecnick.tcpdf
39 * @author Nicola Asuni
40 * @version 1.0.001
41 */
42
43/**
44 * @class TCPDF_FILTERS
45 * This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).<br>
46 * @package com.tecnick.tcpdf
47 * @brief This is a PHP class for decoding common PDF filters.
48 * @version 1.0.001
49 * @author Nicola Asuni - info@tecnick.com
50 */
51class TCPDF_FILTERS {
52
53 /**
54 * Define a list of available filter decoders.
55 * @private static
56 */
57 private static $available_filters = array('ASCIIHexDecode', 'ASCII85Decode', 'LZWDecode', 'FlateDecode', 'RunLengthDecode');
58
59// -----------------------------------------------------------------------------
60
61 /**
62 * Get a list of available decoding filters.
63 * @return (array) Array of available filter decoders.
64 * @since 1.0.000 (2011-05-23)
65 * @public static
66 */
67 public static function getAvailableFilters() {
68 return self::$available_filters;
69 }
70
71 /**
72 * Decode data using the specified filter type.
73 * @param $filter (string) Filter name.
74 * @param $data (string) Data to decode.
75 * @return Decoded data string.
76 * @since 1.0.000 (2011-05-23)
77 * @public static
78 */
79 public static function decodeFilter($filter, $data) {
80 switch ($filter) {
81 case 'ASCIIHexDecode': {
82 return self::decodeFilterASCIIHexDecode($data);
83 break;
84 }
85 case 'ASCII85Decode': {
86 return self::decodeFilterASCII85Decode($data);
87 break;
88 }
89 case 'LZWDecode': {
90 return self::decodeFilterLZWDecode($data);
91 break;
92 }
93 case 'FlateDecode': {
94 return self::decodeFilterFlateDecode($data);
95 break;
96 }
97 case 'RunLengthDecode': {
98 return self::decodeFilterRunLengthDecode($data);
99 break;
100 }
101 case 'CCITTFaxDecode': {
102 return self::decodeFilterCCITTFaxDecode($data);
103 break;
104 }
105 case 'JBIG2Decode': {
106 return self::decodeFilterJBIG2Decode($data);
107 break;
108 }
109 case 'DCTDecode': {
110 return self::decodeFilterDCTDecode($data);
111 break;
112 }
113 case 'JPXDecode': {
114 return self::decodeFilterJPXDecode($data);
115 break;
116 }
117 case 'Crypt': {
118 return self::decodeFilterCrypt($data);
119 break;
120 }
121 default: {
122 return self::decodeFilterStandard($data);
123 break;
124 }
125 }
126 }
127
128 // --- FILTERS (PDF 32000-2008 - 7.4 Filters) ------------------------------
129
130 /**
131 * Standard
132 * Default decoding filter (leaves data unchanged).
133 * @param $data (string) Data to decode.
134 * @return Decoded data string.
135 * @since 1.0.000 (2011-05-23)
136 * @public static
137 */
138 public static function decodeFilterStandard($data) {
139 return $data;
140 }
141
142 /**
143 * ASCIIHexDecode
144 * Decodes data encoded in an ASCII hexadecimal representation, reproducing the original binary data.
145 * @param $data (string) Data to decode.
146 * @return Decoded data string.
147 * @since 1.0.000 (2011-05-23)
148 * @public static
149 */
150 public static function decodeFilterASCIIHexDecode($data) {
151 // initialize string to return
152 $decoded = '';
153 // all white-space characters shall be ignored
154 $data = preg_replace('/[\s]/', '', $data);
155 // check for EOD character: GREATER-THAN SIGN (3Eh)
156 $eod = strpos($data, '>');
157 if ($eod !== false) {
158 // remove EOD and extra data (if any)
159 $data = substr($data, 0, $eod);
160 $eod = true;
161 }
162 // get data length
163 $data_length = strlen($data);
164 if (($data_length % 2) != 0) {
165 // odd number of hexadecimal digits
166 if ($eod) {
167 // EOD shall behave as if a 0 (zero) followed the last digit
168 $data = substr($data, 0, -1).'0'.substr($data, -1);
169 } else {
170 self::Error('decodeFilterASCIIHexDecode: invalid code');
171 }
172 }
173 // check for invalid characters
174 if (preg_match('/[^a-fA-F\d]/', $data) > 0) {
175 self::Error('decodeFilterASCIIHexDecode: invalid code');
176 }
177 // get one byte of binary data for each pair of ASCII hexadecimal digits
178 $decoded = pack('H*', $data);
179 return $decoded;
180 }
181
182 /**
183 * ASCII85Decode
184 * Decodes data encoded in an ASCII base-85 representation, reproducing the original binary data.
185 * @param $data (string) Data to decode.
186 * @return Decoded data string.
187 * @since 1.0.000 (2011-05-23)
188 * @public static
189 */
190 public static function decodeFilterASCII85Decode($data) {
191 // initialize string to return
192 $decoded = '';
193 // all white-space characters shall be ignored
194 $data = preg_replace('/[\s]/', '', $data);
195 // remove start sequence 2-character sequence <~ (3Ch)(7Eh)
196 if (strpos($data, '<~') !== false) {
197 // remove EOD and extra data (if any)
198 $data = substr($data, 2);
199 }
200 // check for EOD: 2-character sequence ~> (7Eh)(3Eh)
201 $eod = strpos($data, '~>');
202 if ($eod !== false) {
203 // remove EOD and extra data (if any)
204 $data = substr($data, 0, $eod);
205 }
206 // data length
207 $data_length = strlen($data);
208 // check for invalid characters
209 if (preg_match('/[^\x21-\x75,\x74]/', $data) > 0) {
210 self::Error('decodeFilterASCII85Decode: invalid code');
211 }
212 // z sequence
213 $zseq = chr(0).chr(0).chr(0).chr(0);
214 // position inside a group of 4 bytes (0-3)
215 $group_pos = 0;
216 $tuple = 0;
217 $pow85 = array((85*85*85*85), (85*85*85), (85*85), 85, 1);
218 $last_pos = ($data_length - 1);
219 // for each byte
220 for ($i = 0; $i < $data_length; ++$i) {
221 // get char value
222 $char = ord($data[$i]);
223 if ($char == 122) { // 'z'
224 if ($group_pos == 0) {
225 $decoded .= $zseq;
226 } else {
227 self::Error('decodeFilterASCII85Decode: invalid code');
228 }
229 } else {
230 // the value represented by a group of 5 characters should never be greater than 2^32 - 1
231 $tuple += (($char - 33) * $pow85[$group_pos]);
232 if ($group_pos == 4) {
233 $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8).chr($tuple);
234 $tuple = 0;
235 $group_pos = 0;
236 } else {
237 ++$group_pos;
238 }
239 }
240 }
241 if ($group_pos > 1) {
242 $tuple += $pow85[($group_pos - 1)];
243 }
244 // last tuple (if any)
245 switch ($group_pos) {
246 case 4: {
247 $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8);
248 break;
249 }
250 case 3: {
251 $decoded .= chr($tuple >> 24).chr($tuple >> 16);
252 break;
253 }
254 case 2: {
255 $decoded .= chr($tuple >> 24);
256 break;
257 }
258 case 1: {
259 self::Error('decodeFilterASCII85Decode: invalid code');
260 break;
261 }
262 }
263 return $decoded;
264 }
265
266 /**
267 * LZWDecode
268 * Decompresses data encoded using the LZW (Lempel-Ziv-Welch) adaptive compression method, reproducing the original text or binary data.
269 * @param $data (string) Data to decode.
270 * @return Decoded data string.
271 * @since 1.0.000 (2011-05-23)
272 * @public static
273 */
274 public static function decodeFilterLZWDecode($data) {
275 // initialize string to return
276 $decoded = '';
277 // data length
278 $data_length = strlen($data);
279 // convert string to binary string
280 $bitstring = '';
281 for ($i = 0; $i < $data_length; ++$i) {
282 $bitstring .= sprintf('%08b', ord($data[$i]));
283 }
284 // get the number of bits
285 $data_length = strlen($bitstring);
286 // initialize code length in bits
287 $bitlen = 9;
288 // initialize dictionary index
289 $dix = 258;
290 // initialize the dictionary (with the first 256 entries).
291 $dictionary = array();
292 for ($i = 0; $i < 256; ++$i) {
293 $dictionary[$i] = chr($i);
294 }
295 // previous val
296 $prev_index = 0;
297 // while we encounter EOD marker (257), read code_length bits
298 while (($data_length > 0) AND (($index = bindec(substr($bitstring, 0, $bitlen))) != 257)) {
299 // remove read bits from string
300 $bitstring = substr($bitstring, $bitlen);
301 // update number of bits
302 $data_length -= $bitlen;
303 if ($index == 256) { // clear-table marker
304 // reset code length in bits
305 $bitlen = 9;
306 // reset dictionary index
307 $dix = 258;
308 $prev_index = 256;
309 // reset the dictionary (with the first 256 entries).
310 $dictionary = array();
311 for ($i = 0; $i < 256; ++$i) {
312 $dictionary[$i] = chr($i);
313 }
314 } elseif ($prev_index == 256) {
315 // first entry
316 $decoded .= $dictionary[$index];
317 $prev_index = $index;
318 } else {
319 // check if index exist in the dictionary
320 if ($index < $dix) {
321 // index exist on dictionary
322 $decoded .= $dictionary[$index];
323 $dic_val = $dictionary[$prev_index].$dictionary[$index][0];
324 // store current index
325 $prev_index = $index;
326 } else {
327 // index do not exist on dictionary
328 $dic_val = $dictionary[$prev_index].$dictionary[$prev_index][0];
329 $decoded .= $dic_val;
330 }
331 // update dictionary
332 $dictionary[$dix] = $dic_val;
333 ++$dix;
334 // change bit length by case
335 if ($dix == 2047) {
336 $bitlen = 12;
337 } elseif ($dix == 1023) {
338 $bitlen = 11;
339 } elseif ($dix == 511) {
340 $bitlen = 10;
341 }
342 }
343 }
344 return $decoded;
345 }
346
347 /**
348 * FlateDecode
349 * Decompresses data encoded using the zlib/deflate compression method, reproducing the original text or binary data.
350 * @param $data (string) Data to decode.
351 * @return Decoded data string.
352 * @since 1.0.000 (2011-05-23)
353 * @public static
354 */
355 public static function decodeFilterFlateDecode($data) {
356 // initialize string to return
357 $decoded = @gzuncompress($data);
358 if ($decoded === false) {
359 self::Error('decodeFilterFlateDecode: invalid code');
360 }
361 return $decoded;
362 }
363
364 /**
365 * RunLengthDecode
366 * Decompresses data encoded using a byte-oriented run-length encoding algorithm.
367 * @param $data (string) Data to decode.
368 * @since 1.0.000 (2011-05-23)
369 * @public static
370 */
371 public static function decodeFilterRunLengthDecode($data) {
372 // initialize string to return
373 $decoded = '';
374 // data length
375 $data_length = strlen($data);
376 $i = 0;
377 while($i < $data_length) {
378 // get current byte value
379 $byte = ord($data[$i]);
380 if ($byte == 128) {
381 // a length value of 128 denote EOD
382 break;
383 } elseif ($byte < 128) {
384 // if the length byte is in the range 0 to 127
385 // the following length + 1 (1 to 128) bytes shall be copied literally during decompression
386 $decoded .= substr($data, ($i + 1), ($byte + 1));
387 // move to next block
388 $i += ($byte + 2);
389 } else {
390 // if length is in the range 129 to 255,
391 // the following single byte shall be copied 257 - length (2 to 128) times during decompression
392 $decoded .= str_repeat($data[($i + 1)], (257 - $byte));
393 // move to next block
394 $i += 2;
395 }
396 }
397 return $decoded;
398 }
399
400 /**
401 * CCITTFaxDecode (NOT IMPLEMETED - RETURN AN EXCEPTION)
402 * Decompresses data encoded using the CCITT facsimile standard, reproducing the original data (typically monochrome image data at 1 bit per pixel).
403 * @param $data (string) Data to decode.
404 * @return Decoded data string.
405 * @since 1.0.000 (2011-05-23)
406 * @public static
407 */
408 public static function decodeFilterCCITTFaxDecode($data) {
409 self::Error('~decodeFilterCCITTFaxDecode: this method has not been yet implemented');
410 //return $data;
411 }
412
413 /**
414 * JBIG2Decode (NOT IMPLEMETED - RETURN AN EXCEPTION)
415 * Decompresses data encoded using the JBIG2 standard, reproducing the original monochrome (1 bit per pixel) image data (or an approximation of that data).
416 * @param $data (string) Data to decode.
417 * @return Decoded data string.
418 * @since 1.0.000 (2011-05-23)
419 * @public static
420 */
421 public static function decodeFilterJBIG2Decode($data) {
422 self::Error('~decodeFilterJBIG2Decode: this method has not been yet implemented');
423 //return $data;
424 }
425
426 /**
427 * DCTDecode (NOT IMPLEMETED - RETURN AN EXCEPTION)
428 * Decompresses data encoded using a DCT (discrete cosine transform) technique based on the JPEG standard, reproducing image sample data that approximates the original data.
429 * @param $data (string) Data to decode.
430 * @return Decoded data string.
431 * @since 1.0.000 (2011-05-23)
432 * @public static
433 */
434 public static function decodeFilterDCTDecode($data) {
435 self::Error('~decodeFilterDCTDecode: this method has not been yet implemented');
436 //return $data;
437 }
438
439 /**
440 * JPXDecode (NOT IMPLEMETED - RETURN AN EXCEPTION)
441 * Decompresses data encoded using the wavelet-based JPEG2000 standard, reproducing the original image data.
442 * @param $data (string) Data to decode.
443 * @return Decoded data string.
444 * @since 1.0.000 (2011-05-23)
445 * @public static
446 */
447 public static function decodeFilterJPXDecode($data) {
448 self::Error('~decodeFilterJPXDecode: this method has not been yet implemented');
449 //return $data;
450 }
451
452 /**
453 * Crypt (NOT IMPLEMETED - RETURN AN EXCEPTION)
454 * Decrypts data encrypted by a security handler, reproducing the data as it was before encryption.
455 * @param $data (string) Data to decode.
456 * @return Decoded data string.
457 * @since 1.0.000 (2011-05-23)
458 * @public static
459 */
460 public static function decodeFilterCrypt($data) {
461 self::Error('~decodeFilterCrypt: this method has not been yet implemented');
462 //return $data;
463 }
464
465 // --- END FILTERS SECTION -------------------------------------------------
466
467 /**
468 * Throw an exception.
469 * @param $msg (string) The error message
470 * @since 1.0.000 (2011-05-23)
471 * @public static
472 */
473 public static function Error($msg) {
474 throw new Exception('TCPDF_PARSER ERROR: '.$msg);
475 }
476
477} // END OF TCPDF_FILTERS CLASS
478
479//============================================================+
480// END OF FILE
481//============================================================+
Note: See TracBrowser for help on using the repository browser.