23 #require_once 'Zend/Pdf/Element.php'; 24 #require_once 'Zend/Pdf/Element/Numeric.php'; 28 #require_once 'Zend/Pdf/StringParser.php'; 45 private $_stringParser;
69 return strlen($this->_stringParser->data);
79 return $this->_stringParser->data;
89 return $this->_pdfVersion;
99 private function _loadXRefTable($offset)
101 $this->_stringParser->offset = $offset;
103 #require_once 'Zend/Pdf/Element/Reference/Table.php'; 105 #require_once 'Zend/Pdf/Element/Reference/Context.php'; 107 $this->_stringParser->setContext($context);
109 $nextLexeme = $this->_stringParser->readLexeme();
110 if ($nextLexeme ==
'xref') {
114 $this->_stringParser->skipWhiteSpace();
115 while ( ($nextLexeme = $this->_stringParser->readLexeme()) !=
'trailer' ) {
116 if (!ctype_digit($nextLexeme)) {
117 #require_once 'Zend/Pdf/Exception.php'; 118 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Cross-reference table subheader values must contain only digits.', $this->_stringParser->offset-strlen($nextLexeme)));
120 $objNum = (int)$nextLexeme;
122 $refCount = $this->_stringParser->readLexeme();
123 if (!ctype_digit($refCount)) {
124 #require_once 'Zend/Pdf/Exception.php'; 125 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Cross-reference table subheader values must contain only digits.', $this->_stringParser->offset-strlen($refCount)));
128 $this->_stringParser->skipWhiteSpace();
129 while ($refCount > 0) {
130 $objectOffset = substr($this->_stringParser->data, $this->_stringParser->offset, 10);
131 if (!ctype_digit($objectOffset)) {
132 #require_once 'Zend/Pdf/Exception.php'; 133 throw new Zend_Pdf_Exception(sprintf(
'PDF file cross-reference table syntax error. Offset - 0x%X. Offset must contain only digits.', $this->_stringParser->offset));
136 for ($numStart = 0; $numStart < strlen($objectOffset)-1; $numStart++) {
137 if ($objectOffset[$numStart] !=
'0') {
141 $objectOffset = substr($objectOffset, $numStart);
142 $this->_stringParser->offset += 10;
144 if (strpos(
"\x00\t\n\f\r ", $this->_stringParser->data[$this->_stringParser->offset]) ===
false) {
145 #require_once 'Zend/Pdf/Exception.php'; 146 throw new Zend_Pdf_Exception(sprintf(
'PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_stringParser->offset));
148 $this->_stringParser->offset++;
150 $genNumber = substr($this->_stringParser->data, $this->_stringParser->offset, 5);
151 if (!ctype_digit($objectOffset)) {
152 #require_once 'Zend/Pdf/Exception.php'; 153 throw new Zend_Pdf_Exception(sprintf(
'PDF file cross-reference table syntax error. Offset - 0x%X. Offset must contain only digits.', $this->_stringParser->offset));
156 for ($numStart = 0; $numStart < strlen($genNumber)-1; $numStart++) {
157 if ($genNumber[$numStart] !=
'0') {
161 $genNumber = substr($genNumber, $numStart);
162 $this->_stringParser->offset += 5;
164 if (strpos(
"\x00\t\n\f\r ", $this->_stringParser->data[$this->_stringParser->offset]) ===
false) {
165 #require_once 'Zend/Pdf/Exception.php'; 166 throw new Zend_Pdf_Exception(sprintf(
'PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_stringParser->offset));
168 $this->_stringParser->offset++;
170 $inUseKey = $this->_stringParser->data[$this->_stringParser->offset];
171 $this->_stringParser->offset++;
176 unset( $this->_refTable[$objNum .
' ' . $genNumber .
' R'] );
177 $refTable->addReference($objNum .
' ' . $genNumber .
' R',
185 $refTable->addReference($objNum .
' ' . $genNumber .
' R',
191 #require_once 'Zend/Pdf/Exception.php'; 192 throw new Zend_Pdf_Exception(sprintf(
'PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_stringParser->offset));
194 $this->_stringParser->offset++;
196 #require_once 'Zend/Pdf/Exception.php'; 197 throw new Zend_Pdf_Exception(sprintf(
'PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_stringParser->offset));
199 $this->_stringParser->offset++;
206 $trailerDictOffset = $this->_stringParser->offset;
207 $trailerDict = $this->_stringParser->readElement();
209 #require_once 'Zend/Pdf/Exception.php'; 210 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Dictionary expected after \'trailer\' keyword.', $trailerDictOffset));
213 $xrefStream = $this->_stringParser->getObject($offset, $context);
216 #require_once 'Zend/Pdf/Exception.php'; 217 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Cross-reference stream expected.', $offset));
220 $trailerDict = $xrefStream->dictionary;
221 if ($trailerDict->Type->value !=
'XRef') {
222 #require_once 'Zend/Pdf/Exception.php'; 223 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Cross-reference stream object must have /Type property assigned to /XRef.', $offset));
226 #require_once 'Zend/Pdf/Exception.php'; 227 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Cross reference stream dictionary doesn\'t have W entry or it\'s not an array.', $offset));
230 $entryField1Size = $trailerDict->W->items[0]->value;
231 $entryField2Size = $trailerDict->W->items[1]->value;
232 $entryField3Size = $trailerDict->W->items[2]->value;
234 if ($entryField2Size == 0 || $entryField3Size == 0) {
235 #require_once 'Zend/Pdf/Exception.php'; 236 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Wrong W dictionary entry. Only type field of stream entries has default value and could be zero length.', $offset));
239 $xrefStreamData = $xrefStream->value;
241 if ($trailerDict->Index !==
null) {
243 #require_once 'Zend/Pdf/Exception.php'; 244 throw new Zend_Pdf_Exception(sprintf(
'PDF file syntax error. Offset - 0x%X. Cross reference stream dictionary Index entry must be an array.', $offset));
246 $sections = count($trailerDict->Index->items)/2;
253 $size = $entryField1Size + $entryField2Size + $entryField3Size;
254 $entries = strlen($xrefStreamData)/$size;
257 if ($trailerDict->Index !==
null) {
258 $objNum = $trailerDict->Index->items[
$count*2 ]->value;
259 $entries = $trailerDict->Index->items[
$count*2 + 1]->value;
262 $entries = $trailerDict->Size->value;
265 for ($count2 = 0; $count2 < $entries; $count2++) {
266 if ($entryField1Size == 0) {
268 }
else if ($entryField1Size == 1) {
269 $type = ord($xrefStreamData[$streamOffset++]);
272 $streamOffset += $entryField1Size;
275 if ($entryField2Size == 1) {
276 $field2 = ord($xrefStreamData[$streamOffset++]);
279 $streamOffset += $entryField2Size;
282 if ($entryField3Size == 1) {
283 $field3 = ord($xrefStreamData[$streamOffset++]);
286 $streamOffset += $entryField3Size;
292 $refTable->addReference($objNum .
' ' . $field3 .
' R', $field2,
false);
299 $refTable->addReference($objNum .
' ' . $field3 .
' R', $field2,
true);
317 #require_once 'Zend/Pdf/Exception.php'; 322 #require_once 'Zend/Pdf/Trailer/Keeper.php'; 326 $trailerObj->setPrev($this->_loadXRefTable($trailerDict->Prev->value));
327 $context->getRefTable()->setParent($trailerObj->getPrev()->getRefTable());
348 return $this->_trailer;
366 #require_once 'Zend/Pdf/Exception.php'; 372 while ($byteCount > 0 && !
feof($pdfFile)) {
373 $nextBlock = fread($pdfFile, $byteCount);
374 if ($nextBlock ===
false) {
375 #require_once 'Zend/Pdf/Exception.php'; 380 $byteCount -= strlen($nextBlock);
382 if ($byteCount != 0) {
383 #require_once 'Zend/Pdf/Exception.php'; 393 $pdfVersionComment = $this->_stringParser->readComment();
394 if (substr($pdfVersionComment, 0, 5) !=
'%PDF-') {
395 #require_once 'Zend/Pdf/Exception.php'; 399 $pdfVersion = substr($pdfVersionComment, 5);
400 if (version_compare($pdfVersion,
'0.9',
'<') ||
401 version_compare($pdfVersion,
'1.61',
'>=')
409 #require_once 'Zend/Pdf/Exception.php'; 410 throw new Zend_Pdf_Exception(sprintf(
'Unsupported PDF version. Zend_Pdf supports PDF 1.0-1.4. Current version - \'%f\'', $pdfVersion));
412 $this->_pdfVersion = $pdfVersion;
414 $this->_stringParser->offset = strrpos($this->_stringParser->data,
'%%EOF');
415 if ($this->_stringParser->offset ===
false ||
416 strlen($this->_stringParser->data) - $this->_stringParser->offset > 7) {
417 #require_once 'Zend/Pdf/Exception.php'; 418 throw new Zend_Pdf_Exception(
'Pdf file syntax error. End-of-fle marker expected at the end of file.');
421 $this->_stringParser->offset--;
426 ($this->_stringParser->offset > 0)) {
427 $this->_stringParser->offset--;
433 ($this->_stringParser->offset > 0)) {
434 $this->_stringParser->offset--;
440 ($this->_stringParser->offset > 0)) {
441 $this->_stringParser->offset--;
446 $this->_stringParser->offset -= 9;
448 $nextLexeme = $this->_stringParser->readLexeme();
449 if ($nextLexeme !=
'startxref') {
450 #require_once 'Zend/Pdf/Exception.php'; 451 throw new Zend_Pdf_Exception(sprintf(
'Pdf file syntax error. \'startxref\' keyword expected. Offset - 0x%X.', $this->_stringParser->offset-strlen($nextLexeme)));
454 $startXref = $this->_stringParser->readLexeme();
455 if (!ctype_digit($startXref)) {
456 #require_once 'Zend/Pdf/Exception.php'; 457 throw new Zend_Pdf_Exception(sprintf(
'Pdf file syntax error. Cross-reference table offset must contain only digits. Offset - 0x%X.', $this->_stringParser->offset-strlen($nextLexeme)));
460 $this->_trailer = $this->_loadXRefTable($startXref);
461 $factory->setObjectCount($this->_trailer->Size->value);
470 $this->_stringParser->cleanUp();
static parseIntFromStream($stream, $offset, $size)
__construct($source, Zend_Pdf_ElementFactory_Interface $factory, $load)
static isWhiteSpace($chCode)