/** * Dereference. * Take inderect object, take $value member of this object (must be Zend_Pdf_Element), * take reference to the $value member of this object and assign it to * $value member of current PDF Reference object * $obj can be null * * @throws Zend_Pdf_Exception */ private function _dereference() { $obj = $this->_context->getParser()->getObject($this->_context->getRefTable()->getOffset($this->_objNum . ' ' . $this->_genNum . ' R'), $this->_context); if ($obj === null) { $this->_ref = new Zend_Pdf_Element_Null(); return; } if ($obj->toString() != $this->_objNum . ' ' . $this->_genNum . ' R') { throw new Zend_Pdf_Exception('Incorrect reference to the object'); } $this->_ref = $obj; $this->setParentObject($obj); $this->_factory->registerObject($this); }
/** * Dereference. * Take inderect object, take $value member of this object (must be Zend_Pdf_Element), * take reference to the $value member of this object and assign it to * $value member of current PDF Reference object * $obj can be null * * @throws Zend_Pdf_Exception */ private function _dereference() { if (($obj = $this->_factory->fetchObject($this->_objNum . ' ' . $this->_genNum)) === null) { $obj = $this->_context->getParser()->getObject($this->_context->getRefTable()->getOffset($this->_objNum . ' ' . $this->_genNum . ' R'), $this->_context); } if ($obj === null) { $this->_ref = new Zend_Pdf_Element_Null(); return; } if ($obj->toString() != $this->_objNum . ' ' . $this->_genNum . ' R') { require_once 'Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception('Incorrect reference to the object'); } $this->_ref = $obj; }
/** * Get header of free objects list * Returns object number of last free object * * @throws Zend_Pdf_Exception * @return integer */ public function getLastFreeObject() { try { $this->_context->getRefTable()->getNextFree('0 65535 R'); } catch (Zend_Pdf_Exception $e) { if ($e->getMessage() == 'Object not found.') { /** * Here is work around for some wrong generated PDFs. * We have not found reference to the header of free object list, * thus we treat it as there are no free objects. */ return 0; } throw new Zend_Pdf_Exception($e->getMessage(), $e->getCode(), $e); } }
/** * Load XReference table and referenced objects * * @param integer $offset * @throws Zend_Pdf_Exception * @return Zend_Pdf_Trailer_Keeper */ private function _loadXRefTable($offset) { $this->_pushContext(); $this->_current = $offset; $refTable = new Zend_Pdf_Element_Reference_Table(); $context = new Zend_Pdf_Element_Reference_Context($this, $refTable); $this->_currentContext = $context; $nextLexeme = $this->_readLexeme(); if ($nextLexeme == 'xref') { /** * Common cross-reference table */ $this->_skipWhiteSpace(); while (($nextLexeme = $this->_readLexeme()) != 'trailer') { if (!ctype_digit($nextLexeme)) { throw new Zend_Pdf_Exception(sprintf('PDF file syntax error. Offset - 0x%X. Cross-reference table subheader values must contain only digits.', $this->_current - strlen($nextLexeme))); } $objNum = (int) $nextLexeme; $refCount = $this->_readLexeme(); if (!ctype_digit($refCount)) { throw new Zend_Pdf_Exception(sprintf('PDF file syntax error. Offset - 0x%X. Cross-reference table subheader values must contain only digits.', $this->_current - strlen($refCount))); } $this->_skipWhiteSpace(); while ($refCount > 0) { $objectOffset = substr($this->_pdfString, $this->_current, 10); if (!ctype_digit($objectOffset)) { throw new Zend_Pdf_Exception(sprintf('PDF file cross-reference table syntax error. Offset - 0x%X. Offset must contain only digits.', $this->_current)); } // Force $objectOffset to be treated as decimal instead of octal number for ($numStart = 0; $numStart < strlen($objectOffset) - 1; $numStart++) { if ($objectOffset[$numStart] != '0') { break; } } $objectOffset = substr($objectOffset, $numStart); $this->_current += 10; if (!self::isWhiteSpace(ord($this->_pdfString[$this->_current]))) { throw new Zend_Pdf_Exception(sprintf('PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_current)); } $this->_current++; $genNumber = substr($this->_pdfString, $this->_current, 5); if (!ctype_digit($objectOffset)) { throw new Zend_Pdf_Exception(sprintf('PDF file cross-reference table syntax error. Offset - 0x%X. Offset must contain only digits.', $this->_current)); } // Force $objectOffset to be treated as decimal instead of octal number for ($numStart = 0; $numStart < strlen($genNumber) - 1; $numStart++) { if ($genNumber[$numStart] != '0') { break; } } $genNumber = substr($genNumber, $numStart); $this->_current += 5; if (!self::isWhiteSpace(ord($this->_pdfString[$this->_current]))) { throw new Zend_Pdf_Exception(sprintf('PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_current)); } $this->_current++; $inUseKey = $this->_pdfString[$this->_current]; $this->_current++; switch ($inUseKey) { case 'f': // free entry unset($this->_refTable[$objNum . ' ' . $genNumber . ' R']); $refTable->addReference($objNum . ' ' . $genNumber . ' R', $objectOffset, false); break; case 'n': // in-use entry $refTable->addReference($objNum . ' ' . $genNumber . ' R', $objectOffset, true); } if (!self::isWhiteSpace(ord($this->_pdfString[$this->_current]))) { throw new Zend_Pdf_Exception(sprintf('PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_current)); } $this->_current++; if (!self::isWhiteSpace(ord($this->_pdfString[$this->_current]))) { throw new Zend_Pdf_Exception(sprintf('PDF file cross-reference table syntax error. Offset - 0x%X. Value separator must be white space.', $this->_current)); } $this->_current++; $refCount--; $objNum++; } } $trailerDictOffset = $this->_current; $trailerDict = $this->_readElementalObject(); if (!$trailerDict instanceof Zend_Pdf_Element_Dictionary) { throw new Zend_Pdf_Exception(sprintf('PDF file syntax error. Offset - 0x%X. Dictionary expected after \'trailer\' keyword.', $trailerDictOffset)); } $trailerObj = new Zend_Pdf_Trailer_Keeper($trailerDict, $context); if ($trailerDict->Prev instanceof Zend_Pdf_Element_Numeric || $trailerDict->Prev instanceof Zend_Pdf_Element_Reference) { $trailerObj->setPrev($this->_loadXRefTable($trailerDict->Prev->value)); $context->getRefTable()->setParent($trailerObj->getPrev()->getRefTable()); } /** * We set '/Prev' dictionary property to the current cross-reference section offset. * It doesn't correspond to the actual data, but is true when trailer will be used * as trailer for next generated PDF section. */ $trailerObj->Prev = new Zend_Pdf_Element_Numeric($offset); } else { throw new Zend_Exception(sprintf('Pdf file syntax error. Offset - 0x%X. \'xref\' lexeme expected.', $this->_current - strlen($nextLexeme))); /** * @todo Cross-Reference stream object must be loaded here. */ } $this->_popContext(); return $trailerObj; }
/** * Get header of free objects list * Returns object number of last free object * * @return integer */ public function getLastFreeObject() { $this->_context->getRefTable()->getNextFree('0 65535 R'); }