/framework/vendor/zend/Zend/Pdf/Element/Object/Stream.php
PHP | 422 lines | 242 code | 56 blank | 124 comment | 42 complexity | e8c099ebc2a49a552c9d5bdd9f6102f5 MD5 | raw file
1<?php 2/** 3 * Zend Framework 4 * 5 * LICENSE 6 * 7 * This source file is subject to the new BSD license that is bundled 8 * with this package in the file LICENSE.txt. 9 * It is also available through the world-wide-web at this URL: 10 * http://framework.zend.com/license/new-bsd 11 * If you did not receive a copy of the license and are unable to 12 * obtain it through the world-wide-web, please send an email 13 * to license@zend.com so we can send you a copy immediately. 14 * 15 * @category Zend 16 * @package Zend_Pdf 17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 18 * @license http://framework.zend.com/license/new-bsd New BSD License 19 * @version $Id: Stream.php 20096 2010-01-06 02:05:09Z bkarwin $ 20 */ 21 22 23/** Internally used classes */ 24require_once 'Zend/Pdf/Element/Stream.php'; 25require_once 'Zend/Pdf/Element/Dictionary.php'; 26require_once 'Zend/Pdf/Element/Numeric.php'; 27 28 29/** Zend_Pdf_Element_Object */ 30require_once 'Zend/Pdf/Element/Object.php'; 31 32/** 33 * PDF file 'stream object' element implementation 34 * 35 * @category Zend 36 * @package Zend_Pdf 37 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 38 * @license http://framework.zend.com/license/new-bsd New BSD License 39 */ 40class Zend_Pdf_Element_Object_Stream extends Zend_Pdf_Element_Object 41{ 42 /** 43 * StreamObject dictionary 44 * Required enries: 45 * Length 46 * 47 * @var Zend_Pdf_Element_Dictionary 48 */ 49 private $_dictionary; 50 51 /** 52 * Flag which signals, that stream is decoded 53 * 54 * @var boolean 55 */ 56 private $_streamDecoded; 57 58 /** 59 * Stored original stream object dictionary. 60 * Used to decode stream during an access time. 61 * 62 * The only properties, which affect decoding, are sored here. 63 * 64 * @var array|null 65 */ 66 private $_originalDictionary = null; 67 68 /** 69 * Object constructor 70 * 71 * @param mixed $val 72 * @param integer $objNum 73 * @param integer $genNum 74 * @param Zend_Pdf_ElementFactory $factory 75 * @param Zend_Pdf_Element_Dictionary|null $dictionary 76 * @throws Zend_Pdf_Exception 77 */ 78 public function __construct($val, $objNum, $genNum, Zend_Pdf_ElementFactory $factory, $dictionary = null) 79 { 80 parent::__construct(new Zend_Pdf_Element_Stream($val), $objNum, $genNum, $factory); 81 82 if ($dictionary === null) { 83 $this->_dictionary = new Zend_Pdf_Element_Dictionary(); 84 $this->_dictionary->Length = new Zend_Pdf_Element_Numeric(strlen( $val )); 85 $this->_streamDecoded = true; 86 } else { 87 $this->_dictionary = $dictionary; 88 $this->_streamDecoded = false; 89 } 90 } 91 92 93 /** 94 * Store original dictionary information in $_originalDictionary class member. 95 * Used to store information and to normalize filters information before defiltering. 96 * 97 */ 98 private function _storeOriginalDictionary() 99 { 100 $this->_originalDictionary = array(); 101 102 $this->_originalDictionary['Filter'] = array(); 103 $this->_originalDictionary['DecodeParms'] = array(); 104 if ($this->_dictionary->Filter === null) { 105 // Do nothing. 106 } else if ($this->_dictionary->Filter->getType() == Zend_Pdf_Element::TYPE_ARRAY) { 107 foreach ($this->_dictionary->Filter->items as $id => $filter) { 108 $this->_originalDictionary['Filter'][$id] = $filter->value; 109 $this->_originalDictionary['DecodeParms'][$id] = array(); 110 111 if ($this->_dictionary->DecodeParms !== null ) { 112 if ($this->_dictionary->DecodeParms->items[$id] !== null && 113 $this->_dictionary->DecodeParms->items[$id]->value !== null ) { 114 foreach ($this->_dictionary->DecodeParms->items[$id]->getKeys() as $paramKey) { 115 $this->_originalDictionary['DecodeParms'][$id][$paramKey] = 116 $this->_dictionary->DecodeParms->items[$id]->$paramKey->value; 117 } 118 } 119 } 120 } 121 } else if ($this->_dictionary->Filter->getType() != Zend_Pdf_Element::TYPE_NULL) { 122 $this->_originalDictionary['Filter'][0] = $this->_dictionary->Filter->value; 123 $this->_originalDictionary['DecodeParms'][0] = array(); 124 if ($this->_dictionary->DecodeParms !== null ) { 125 foreach ($this->_dictionary->DecodeParms->getKeys() as $paramKey) { 126 $this->_originalDictionary['DecodeParms'][0][$paramKey] = 127 $this->_dictionary->DecodeParms->$paramKey->value; 128 } 129 } 130 } 131 132 if ($this->_dictionary->F !== null) { 133 $this->_originalDictionary['F'] = $this->_dictionary->F->value; 134 } 135 136 $this->_originalDictionary['FFilter'] = array(); 137 $this->_originalDictionary['FDecodeParms'] = array(); 138 if ($this->_dictionary->FFilter === null) { 139 // Do nothing. 140 } else if ($this->_dictionary->FFilter->getType() == Zend_Pdf_Element::TYPE_ARRAY) { 141 foreach ($this->_dictionary->FFilter->items as $id => $filter) { 142 $this->_originalDictionary['FFilter'][$id] = $filter->value; 143 $this->_originalDictionary['FDecodeParms'][$id] = array(); 144 145 if ($this->_dictionary->FDecodeParms !== null ) { 146 if ($this->_dictionary->FDecodeParms->items[$id] !== null && 147 $this->_dictionary->FDecodeParms->items[$id]->value !== null) { 148 foreach ($this->_dictionary->FDecodeParms->items[$id]->getKeys() as $paramKey) { 149 $this->_originalDictionary['FDecodeParms'][$id][$paramKey] = 150 $this->_dictionary->FDecodeParms->items[$id]->items[$paramKey]->value; 151 } 152 } 153 } 154 } 155 } else { 156 $this->_originalDictionary['FFilter'][0] = $this->_dictionary->FFilter->value; 157 $this->_originalDictionary['FDecodeParms'][0] = array(); 158 if ($this->_dictionary->FDecodeParms !== null ) { 159 foreach ($this->_dictionary->FDecodeParms->getKeys() as $paramKey) { 160 $this->_originalDictionary['FDecodeParms'][0][$paramKey] = 161 $this->_dictionary->FDecodeParms->items[$paramKey]->value; 162 } 163 } 164 } 165 } 166 167 /** 168 * Decode stream 169 * 170 * @throws Zend_Pdf_Exception 171 */ 172 private function _decodeStream() 173 { 174 if ($this->_originalDictionary === null) { 175 $this->_storeOriginalDictionary(); 176 } 177 178 /** 179 * All applied stream filters must be processed to decode stream. 180 * If we don't recognize any of applied filetrs an exception should be thrown here 181 */ 182 if (isset($this->_originalDictionary['F'])) { 183 /** @todo Check, how external files can be processed. */ 184 require_once 'Zend/Pdf/Exception.php'; 185 throw new Zend_Pdf_Exception('External filters are not supported now.'); 186 } 187 188 foreach ($this->_originalDictionary['Filter'] as $id => $filterName ) { 189 $valueRef = &$this->_value->value->getRef(); 190 $this->_value->value->touch(); 191 switch ($filterName) { 192 case 'ASCIIHexDecode': 193 require_once 'Zend/Pdf/Filter/AsciiHex.php'; 194 $valueRef = Zend_Pdf_Filter_AsciiHex::decode($valueRef); 195 break; 196 197 case 'ASCII85Decode': 198 require_once 'Zend/Pdf/Filter/Ascii85.php'; 199 $valueRef = Zend_Pdf_Filter_Ascii85::decode($valueRef); 200 break; 201 202 case 'FlateDecode': 203 require_once 'Zend/Pdf/Filter/Compression/Flate.php'; 204 $valueRef = Zend_Pdf_Filter_Compression_Flate::decode($valueRef, 205 $this->_originalDictionary['DecodeParms'][$id]); 206 break; 207 208 case 'LZWDecode': 209 require_once 'Zend/Pdf/Filter/Compression/Lzw.php'; 210 $valueRef = Zend_Pdf_Filter_Compression_Lzw::decode($valueRef, 211 $this->_originalDictionary['DecodeParms'][$id]); 212 break; 213 214 case 'RunLengthDecode': 215 require_once 'Zend/Pdf/Filter/RunLength.php'; 216 $valueRef = Zend_Pdf_Filter_RunLength::decode($valueRef); 217 break; 218 219 default: 220 require_once 'Zend/Pdf/Exception.php'; 221 throw new Zend_Pdf_Exception('Unknown stream filter: \'' . $filterName . '\'.'); 222 } 223 } 224 225 $this->_streamDecoded = true; 226 } 227 228 /** 229 * Encode stream 230 * 231 * @throws Zend_Pdf_Exception 232 */ 233 private function _encodeStream() 234 { 235 /** 236 * All applied stream filters must be processed to encode stream. 237 * If we don't recognize any of applied filetrs an exception should be thrown here 238 */ 239 if (isset($this->_originalDictionary['F'])) { 240 /** @todo Check, how external files can be processed. */ 241 require_once 'Zend/Pdf/Exception.php'; 242 throw new Zend_Pdf_Exception('External filters are not supported now.'); 243 } 244 245 $filters = array_reverse($this->_originalDictionary['Filter'], true); 246 247 foreach ($filters as $id => $filterName ) { 248 $valueRef = &$this->_value->value->getRef(); 249 $this->_value->value->touch(); 250 switch ($filterName) { 251 case 'ASCIIHexDecode': 252 require_once 'Zend/Pdf/Filter/AsciiHex.php'; 253 $valueRef = Zend_Pdf_Filter_AsciiHex::encode($valueRef); 254 break; 255 256 case 'ASCII85Decode': 257 require_once 'Zend/Pdf/Filter/Ascii85.php'; 258 $valueRef = Zend_Pdf_Filter_Ascii85::encode($valueRef); 259 break; 260 261 case 'FlateDecode': 262 require_once 'Zend/Pdf/Filter/Compression/Flate.php'; 263 $valueRef = Zend_Pdf_Filter_Compression_Flate::encode($valueRef, 264 $this->_originalDictionary['DecodeParms'][$id]); 265 break; 266 267 case 'LZWDecode': 268 require_once 'Zend/Pdf/Filter/Compression/Lzw.php'; 269 $valueRef = Zend_Pdf_Filter_Compression_Lzw::encode($valueRef, 270 $this->_originalDictionary['DecodeParms'][$id]); 271 break; 272 273 case 'RunLengthDecode': 274 require_once 'Zend/Pdf/Filter/RunLength.php'; 275 $valueRef = Zend_Pdf_Filter_RunLength::encode($valueRef); 276 break; 277 278 default: 279 require_once 'Zend/Pdf/Exception.php'; 280 throw new Zend_Pdf_Exception('Unknown stream filter: \'' . $filterName . '\'.'); 281 } 282 } 283 284 $this->_streamDecoded = false; 285 } 286 287 /** 288 * Get handler 289 * 290 * @param string $property 291 * @return mixed 292 * @throws Zend_Pdf_Exception 293 */ 294 public function __get($property) 295 { 296 if ($property == 'dictionary') { 297 /** 298 * If stream is note decoded yet, then store original decoding options (do it only once). 299 */ 300 if (( !$this->_streamDecoded ) && ($this->_originalDictionary === null)) { 301 $this->_storeOriginalDictionary(); 302 } 303 304 return $this->_dictionary; 305 } 306 307 if ($property == 'value') { 308 if (!$this->_streamDecoded) { 309 $this->_decodeStream(); 310 } 311 312 return $this->_value->value->getRef(); 313 } 314 315 require_once 'Zend/Pdf/Exception.php'; 316 throw new Zend_Pdf_Exception('Unknown stream object property requested.'); 317 } 318 319 320 /** 321 * Set handler 322 * 323 * @param string $property 324 * @param mixed $value 325 */ 326 public function __set($property, $value) 327 { 328 if ($property == 'value') { 329 $valueRef = &$this->_value->value->getRef(); 330 $valueRef = $value; 331 $this->_value->value->touch(); 332 333 $this->_streamDecoded = true; 334 335 return; 336 } 337 338 require_once 'Zend/Pdf/Exception.php'; 339 throw new Zend_Pdf_Exception('Unknown stream object property: \'' . $property . '\'.'); 340 } 341 342 343 /** 344 * Treat stream data as already encoded 345 */ 346 public function skipFilters() 347 { 348 $this->_streamDecoded = false; 349 } 350 351 352 /** 353 * Call handler 354 * 355 * @param string $method 356 * @param array $args 357 * @return mixed 358 */ 359 public function __call($method, $args) 360 { 361 if (!$this->_streamDecoded) { 362 $this->_decodeStream(); 363 } 364 365 switch (count($args)) { 366 case 0: 367 return $this->_value->$method(); 368 case 1: 369 return $this->_value->$method($args[0]); 370 default: 371 require_once 'Zend/Pdf/Exception.php'; 372 throw new Zend_Pdf_Exception('Unsupported number of arguments'); 373 } 374 } 375 376 /** 377 * Dump object to a string to save within PDF file 378 * 379 * $factory parameter defines operation context. 380 * 381 * @param Zend_Pdf_ElementFactory $factory 382 * @return string 383 */ 384 public function dump(Zend_Pdf_ElementFactory $factory) 385 { 386 $shift = $factory->getEnumerationShift($this->_factory); 387 388 if ($this->_streamDecoded) { 389 $this->_storeOriginalDictionary(); 390 $this->_encodeStream(); 391 } else if ($this->_originalDictionary != null) { 392 $startDictionary = $this->_originalDictionary; 393 $this->_storeOriginalDictionary(); 394 $newDictionary = $this->_originalDictionary; 395 396 if ($startDictionary !== $newDictionary) { 397 $this->_originalDictionary = $startDictionary; 398 $this->_decodeStream(); 399 400 $this->_originalDictionary = $newDictionary; 401 $this->_encodeStream(); 402 } 403 } 404 405 // Update stream length 406 $this->dictionary->Length->value = $this->_value->length(); 407 408 return $this->_objNum + $shift . " " . $this->_genNum . " obj \n" 409 . $this->dictionary->toString($factory) . "\n" 410 . $this->_value->toString($factory) . "\n" 411 . "endobj\n"; 412 } 413 414 /** 415 * Clean up resources, used by object 416 */ 417 public function cleanUp() 418 { 419 $this->_dictionary = null; 420 $this->_value = null; 421 } 422}