|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 //============================================================+ 00003 // File name : tcpdf_filters.php 00004 // Version : 1.0.000 00005 // Begin : 2011-05-23 00006 // Last Update : 2011-06-26 00007 // Author : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com 00008 // License : http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT GNU-LGPLv3 + YOU CAN'T REMOVE ANY TCPDF COPYRIGHT NOTICE OR LINK FROM THE GENERATED PDF DOCUMENTS. 00009 // ------------------------------------------------------------------- 00010 // Copyright (C) 2011-2011 Nicola Asuni - Tecnick.com S.r.l. 00011 // 00012 // This file is part of TCPDF software library. 00013 // 00014 // TCPDF is free software: you can redistribute it and/or modify it 00015 // under the terms of the GNU Lesser General Public License as 00016 // published by the Free Software Foundation, either version 3 of the 00017 // License, or (at your option) any later version. Additionally, 00018 // YOU CAN'T REMOVE ANY TCPDF COPYRIGHT NOTICE OR LINK FROM THE 00019 // GENERATED PDF DOCUMENTS. 00020 // 00021 // TCPDF is distributed in the hope that it will be useful, but 00022 // WITHOUT ANY WARRANTY; without even the implied warranty of 00023 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00024 // See the GNU Lesser General Public License for more details. 00025 // 00026 // You should have received a copy of the License 00027 // along with TCPDF. If not, see 00028 // <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. 00029 // 00030 // See LICENSE.TXT file for more information. 00031 // ------------------------------------------------------------------- 00032 // 00033 // Description : This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters). 00034 // 00035 //============================================================+ 00036 00053 class TCPDF_FILTERS { 00054 00059 private $available_filters = array('ASCIIHexDecode', 'ASCII85Decode', 'LZWDecode', 'FlateDecode', 'RunLengthDecode'); 00060 00061 // ----------------------------------------------------------------------------- 00062 00069 public function getAvailableFilters() { 00070 return $this->available_filters; 00071 } 00072 00081 public function decodeFilter($filter, $data) { 00082 switch ($filter) { 00083 case 'ASCIIHexDecode': { 00084 return $this->decodeFilterASCIIHexDecode($data); 00085 break; 00086 } 00087 case 'ASCII85Decode': { 00088 return $this->decodeFilterASCII85Decode($data); 00089 break; 00090 } 00091 case 'LZWDecode': { 00092 return $this->decodeFilterLZWDecode($data); 00093 break; 00094 } 00095 case 'FlateDecode': { 00096 return $this->decodeFilterFlateDecode($data); 00097 break; 00098 } 00099 case 'RunLengthDecode': { 00100 return $this->decodeFilterRunLengthDecode($data); 00101 break; 00102 } 00103 case 'CCITTFaxDecode': { 00104 return $this->decodeFilterCCITTFaxDecode($data); 00105 break; 00106 } 00107 case 'JBIG2Decode': { 00108 return $this->decodeFilterJBIG2Decode($data); 00109 break; 00110 } 00111 case 'DCTDecode': { 00112 return $this->decodeFilterDCTDecode($data); 00113 break; 00114 } 00115 case 'JPXDecode': { 00116 return $this->decodeFilterJPXDecode($data); 00117 break; 00118 } 00119 case 'Crypt': { 00120 return $this->decodeFilterCrypt($data); 00121 break; 00122 } 00123 default: { 00124 return decodeFilterStandard($data); 00125 break; 00126 } 00127 } 00128 } 00129 00130 // --- FILTERS (PDF 32000-2008 - 7.4 Filters) ------------------------------ 00131 00140 public function decodeFilterStandard($data) { 00141 return $data; 00142 } 00143 00152 public function decodeFilterASCIIHexDecode($data) { 00153 // intialize string to return 00154 $decoded = ''; 00155 // all white-space characters shall be ignored 00156 $data = preg_replace('/[\s]/', '', $data); 00157 // check for EOD character: GREATER-THAN SIGN (3Eh) 00158 $eod = strpos($data, '>'); 00159 if ($eod !== false) { 00160 // remove EOD and extra data (if any) 00161 $data = substr($data, 0, $eod); 00162 $eod = true; 00163 } 00164 // get data length 00165 $data_length = strlen($data); 00166 if (($data_length % 2) != 0) { 00167 // odd number of hexadecimal digits 00168 if ($eod) { 00169 // EOD shall behave as if a 0 (zero) followed the last digit 00170 $data = substr($data, 0, -1).'0'.substr($data, -1); 00171 } else { 00172 $this->Error('decodeASCIIHex: invalid code'); 00173 } 00174 } 00175 // check for invalid characters 00176 if (preg_match('/[^a-fA-F\d]/', $data) > 0) { 00177 $this->Error('decodeASCIIHex: invalid code'); 00178 } 00179 // get one byte of binary data for each pair of ASCII hexadecimal digits 00180 $decoded = pack('H*', $data); 00181 return $decoded; 00182 } 00183 00192 public function decodeFilterASCII85Decode($data) { 00193 // intialize string to return 00194 $decoded = ''; 00195 // all white-space characters shall be ignored 00196 $data = preg_replace('/[\s]/', '', $data); 00197 // remove start sequence 2-character sequence <~ (3Ch)(7Eh) 00198 if (strpos($data, '<~') !== false) { 00199 // remove EOD and extra data (if any) 00200 $data = substr($data, 2); 00201 } 00202 // check for EOD: 2-character sequence ~> (7Eh)(3Eh) 00203 $eod = strpos($data, '~>'); 00204 if ($eod !== false) { 00205 // remove EOD and extra data (if any) 00206 $data = substr($data, 0, $eod); 00207 } 00208 // data length 00209 $data_length = strlen($data); 00210 // check for invalid characters 00211 if (preg_match('/[^\x21-\x75,\x74]/', $data) > 0) { 00212 $this->Error('decodeASCII85: invalid code'); 00213 } 00214 // z sequence 00215 $zseq = chr(0).chr(0).chr(0).chr(0); 00216 // position inside a group of 4 bytes (0-3) 00217 $group_pos = 0; 00218 $tuple = 0; 00219 $pow85 = array((85*85*85*85), (85*85*85), (85*85), 85, 1); 00220 $last_pos = ($data_length - 1); 00221 // for each byte 00222 for ($i = 0; $i < $data_length; ++$i) { 00223 // get char value 00224 $char = ord($data[$i]); 00225 if ($char == 122) { // 'z' 00226 if ($group_pos == 0) { 00227 $decoded .= $zseq; 00228 } else { 00229 $this->Error('decodeASCII85: invalid code'); 00230 } 00231 } else { 00232 // the value represented by a group of 5 characters should never be greater than 2^32 - 1 00233 $tuple += (($char - 33) * $pow85[$group_pos]); 00234 if ($group_pos == 4) { 00235 $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8).chr($tuple); 00236 $tuple = 0; 00237 $group_pos = 0; 00238 } else { 00239 ++$group_pos; 00240 } 00241 } 00242 } 00243 if ($group_pos > 1) { 00244 $tuple += $pow85[($group_pos - 1)]; 00245 } 00246 // last tuple (if any) 00247 switch ($group_pos) { 00248 case 4: { 00249 $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8); 00250 break; 00251 } 00252 case 3: { 00253 $decoded .= chr($tuple >> 24).chr($tuple >> 16); 00254 break; 00255 } 00256 case 2: { 00257 $decoded .= chr($tuple >> 24); 00258 break; 00259 } 00260 case 1: { 00261 $this->Error('decodeASCII85: invalid code'); 00262 break; 00263 } 00264 } 00265 return $decoded; 00266 } 00267 00276 public function decodeFilterLZWDecode($data) { 00277 // intialize string to return 00278 $decoded = ''; 00279 // data length 00280 $data_length = strlen($data); 00281 // convert string to binary string 00282 $bitstring = ''; 00283 for ($i = 0; $i < $data_length; ++$i) { 00284 $bitstring .= sprintf('%08b', ord($data{$i})); 00285 } 00286 // get the number of bits 00287 $data_length = strlen($bitstring); 00288 // initialize code length in bits 00289 $bitlen = 9; 00290 // initialize dictionary index 00291 $dix = 258; 00292 // initialize the dictionary (with the first 256 entries). 00293 $dictionary = array(); 00294 for ($i = 0; $i < 256; ++$i) { 00295 $dictionary[$i] = chr($i); 00296 } 00297 // previous val 00298 $prev_index = 0; 00299 // while we encounter EOD marker (257), read code_length bits 00300 while (($data_length > 0) AND (($index = bindec(substr($bitstring, 0, $bitlen))) != 257)) { 00301 // remove read bits from string 00302 $bitstring = substr($bitstring, $bitlen); 00303 // update number of bits 00304 $data_length -= $bitlen; 00305 if ($index == 256) { // clear-table marker 00306 // reset code length in bits 00307 $bitlen = 9; 00308 // reset dictionary index 00309 $dix = 258; 00310 $prev_index = 256; 00311 // reset the dictionary (with the first 256 entries). 00312 $dictionary = array(); 00313 for ($i = 0; $i < 256; ++$i) { 00314 $dictionary[$i] = chr($i); 00315 } 00316 } elseif ($prev_index == 256) { 00317 // first entry 00318 $decoded .= $dictionary[$index]; 00319 $prev_index = $index; 00320 } else { 00321 // check if index exist in the dictionary 00322 if ($index < $dix) { 00323 // index exist on dictionary 00324 $decoded .= $dictionary[$index]; 00325 $dic_val = $dictionary[$prev_index].$dictionary[$index]{0}; 00326 // store current index 00327 $prev_index = $index; 00328 } else { 00329 // index do not exist on dictionary 00330 $dic_val = $dictionary[$prev_index].$dictionary[$prev_index]{0}; 00331 $decoded .= $dic_val; 00332 } 00333 // update dictionary 00334 $dictionary[$dix] = $dic_val; 00335 ++$dix; 00336 // change bit length by case 00337 if ($dix == 2047) { 00338 $bitlen = 12; 00339 } elseif ($dix == 1023) { 00340 $bitlen = 11; 00341 } elseif ($dix == 511) { 00342 $bitlen = 10; 00343 } 00344 } 00345 } 00346 return $decoded; 00347 } 00348 00357 public function decodeFilterFlateDecode($data) { 00358 // intialize string to return 00359 $decoded = gzuncompress($data); 00360 if ($decoded === false) { 00361 $this->Error('decodeFlate: invalid code'); 00362 } 00363 return $decoded; 00364 } 00365 00373 public function decodeFilterRunLengthDecode($data) { 00374 // intialize string to return 00375 $decoded = ''; 00376 // data length 00377 $data_length = strlen($data); 00378 $i = 0; 00379 while($i < $data_length) { 00380 // get current byte value 00381 $byte = ord($data{$i}); 00382 if ($byte == 128) { 00383 // a length value of 128 denote EOD 00384 break; 00385 } elseif ($byte < 128) { 00386 // if the length byte is in the range 0 to 127 00387 // the following length + 1 (1 to 128) bytes shall be copied literally during decompression 00388 $decoded .= substr($data, ($i + 1), ($byte + 1)); 00389 // move to next block 00390 $i += ($byte + 2); 00391 } else { 00392 // if length is in the range 129 to 255, 00393 // the following single byte shall be copied 257 - length (2 to 128) times during decompression 00394 $decoded .= str_repeat($data{($i + 1)}, (257 - $byte)); 00395 // move to next block 00396 $i += 2; 00397 } 00398 } 00399 return $decoded; 00400 } 00401 00410 public function decodeFilterCCITTFaxDecode($data) { 00411 return $data; 00412 } 00413 00422 public function decodeFilterJBIG2Decode($data) { 00423 return $data; 00424 } 00425 00434 public function decodeFilterDCTDecode($data) { 00435 return $data; 00436 } 00437 00446 public function decodeFilterJPXDecode($data) { 00447 return $data; 00448 } 00449 00458 public function decodeFilterCrypt($data) { 00459 return $data; 00460 } 00461 00462 // --- END FILTERS SECTION ------------------------------------------------- 00463 00470 public function Error($msg) { 00471 // exit program and print error 00472 die('<strong>TCPDF_FILTERS ERROR: </strong>'.$msg); 00473 } 00474 00475 } // END OF TCPDF_FILTERS CLASS 00476 00477 //============================================================+ 00478 // END OF FILE 00479 //============================================================+