Esempio n. 1
0
 /**
  * Explicit destination object constructor
  *
  * @param \Zend\Pdf\InternalType\AbstractTypeObject $destinationArray
  * @throws \Zend\Pdf\Exception
  */
 public function __construct(InternalType\AbstractTypeObject $destinationArray)
 {
     if ($destinationArray->getType() != InternalType\AbstractTypeObject::TYPE_ARRAY) {
         throw new Exception\CorruptedPdfException('Explicit destination resource Array must be a direct or an indirect array object.');
     }
     $this->_destinationArray = $destinationArray;
     switch (count($this->_destinationArray->items)) {
         case 0:
             throw new Exception\CorruptedPdfException('Destination array must contain a page reference.');
             break;
         case 1:
             throw new Exception\CorruptedPdfException('Destination array must contain a destination type name.');
             break;
         default:
             // Do nothing
             break;
     }
     switch ($this->_destinationArray->items[0]->getType()) {
         case InternalType\AbstractTypeObject::TYPE_NUMERIC:
             $this->_isRemote = true;
             break;
         case InternalType\AbstractTypeObject::TYPE_DICTIONARY:
             $this->_isRemote = false;
             break;
         default:
             throw new Exception\CorruptedPdfException('Destination target must be a page number or page dictionary object.');
             break;
     }
 }
Esempio n. 2
0
 /**
  * Object constructor
  *
  * @param $rootDictionary root of name dictionary
  * @throws \Zend\Pdf\Exception
  */
 public function __construct(InternalType\AbstractTypeObject $rootDictionary)
 {
     if ($rootDictionary->getType() != InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
         throw new Exception\CorruptedPdfException('Name tree root must be a dictionary.');
     }
     $intermediateNodes = array();
     $leafNodes = array();
     if ($rootDictionary->Kids !== null) {
         $intermediateNodes[] = $rootDictionary;
     } else {
         $leafNodes[] = $rootDictionary;
     }
     while (count($intermediateNodes) != 0) {
         $newIntermediateNodes = array();
         foreach ($intermediateNodes as $node) {
             foreach ($node->Kids->items as $childNode) {
                 if ($childNode->Kids !== null) {
                     $newIntermediateNodes[] = $childNode;
                 } else {
                     $leafNodes[] = $childNode;
                 }
             }
         }
         $intermediateNodes = $newIntermediateNodes;
     }
     foreach ($leafNodes as $leafNode) {
         $destinationsCount = count($leafNode->Names->items) / 2;
         for ($count = 0; $count < $destinationsCount; $count++) {
             $this->_items[$leafNode->Names->items[$count * 2]->value] = $leafNode->Names->items[$count * 2 + 1];
         }
     }
 }
Esempio n. 3
0
 /**
  * Named destination object constructor
  *
  * @param $resource
  * @throws \Zend\Pdf\Exception
  */
 public function __construct(InternalType\AbstractTypeObject $resource)
 {
     if ($resource->getType() != InternalType\AbstractTypeObject::TYPE_NAME && $resource->getType() != InternalType\AbstractTypeObject::TYPE_STRING) {
         throw new Exception\CorruptedPdfException('Named destination resource must be a PDF name or a PDF string.');
     }
     $this->_nameElement = $resource;
 }
Esempio n. 4
0
 /**
  * Annotation object constructor
  *
  * @throws \Zend\Pdf\Exception\ExceptionInterface
  */
 public function __construct(InternalType\AbstractTypeObject $annotationDictionary)
 {
     if ($annotationDictionary->getType() != InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
         throw new Exception\CorruptedPdfException('Annotation dictionary resource has to be a dictionary.');
     }
     if ($annotationDictionary->Subtype === null || $annotationDictionary->Subtype->getType() != InternalType\AbstractTypeObject::TYPE_NAME || $annotationDictionary->Subtype->value != 'Link') {
         throw new Exception\CorruptedPdfException('Subtype => Link entry is requires');
     }
     parent::__construct($annotationDictionary);
 }
Esempio n. 5
0
 /**
  * Annotation object constructor
  *
  * @throws \Zend\Pdf\Exception
  */
 public function __construct(InternalType\AbstractTypeObject $annotationDictionary)
 {
     if ($annotationDictionary->getType() != InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
         throw new Exception\CorruptedPdfException('Annotation dictionary resource has to be a dictionary.');
     }
     if ($annotationDictionary->Subtype === null || $annotationDictionary->Subtype->getType() != InternalType\AbstractTypeObject::TYPE_NAME || !in_array($annotationDictionary->Subtype->value, array(self::SUBTYPE_HIGHLIGHT, self::SUBTYPE_UNDERLINE, self::SUBTYPE_SQUIGGLY, self::SUBTYPE_STRIKEOUT))) {
         throw new Exception\CorruptedPdfException('Subtype => Markup entry is omitted or has wrong value.');
     }
     parent::__construct($annotationDictionary);
 }
Esempio n. 6
0
    /**
     * Load Destination object from a specified resource
     *
     * @internal
     * @param $destinationArray
     * @return \Zend\Pdf\Destination\AbstractDestination
     */
    public static function load(InternalType\AbstractTypeObject $resource)
    {
        if ($resource->getType() == InternalType\AbstractTypeObject::TYPE_NAME  ||  $resource->getType() == InternalType\AbstractTypeObject::TYPE_STRING) {
            return new Named($resource);
        }

        if ($resource->getType() != InternalType\AbstractTypeObject::TYPE_ARRAY) {
            throw new Exception\CorruptedPdfException('An explicit destination must be a direct or an indirect array object.');
        }
        if (count($resource->items) < 2) {
            throw new Exception\CorruptedPdfException('An explicit destination array must contain at least two elements.');
        }

        switch ($resource->items[1]->value) {
            case 'XYZ':
                return new Zoom($resource);
                break;

            case 'Fit':
                return new Fit($resource);
                break;

            case 'FitH':
                return new FitHorizontally($resource);
                break;

            case 'FitV':
                return new FitVertically($resource);
                break;

            case 'FitR':
                return new FitRectangle($resource);
                break;

            case 'FitB':
                return new FitBoundingBox($resource);
                break;

            case 'FitBH':
                return new FitBoundingBoxHorizontally($resource);
                break;

            case 'FitBV':
                return new FitBoundingBoxVertically($resource);
                break;

            default:
                return new Unknown($resource);
                break;
        }
    }
Esempio n. 7
0
 /**
  * Parse resource and return it as an Action or Explicit Destination
  *
  * $param \Zend\Pdf\InternalType $resource
  * @return \Zend\Pdf\Destination\AbstractDestination|\Zend\Pdf\Action\AbstractAction
  * @throws \Zend\Pdf\Exception\ExceptionInterface
  */
 public static function load(InternalType\AbstractTypeObject $resource)
 {
     if ($resource->getType() == InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
         if (($resource->Type === null || $resource->Type->value == 'Action') && $resource->S !== null) {
             // It's a well-formed action, load it
             return Action\AbstractAction::load($resource);
         } elseif ($resource->D !== null) {
             // It's a destination
             $resource = $resource->D;
         } else {
             throw new Exception\CorruptedPdfException('Wrong resource type.');
         }
     }
     if ($resource->getType() == InternalType\AbstractTypeObject::TYPE_ARRAY || $resource->getType() == InternalType\AbstractTypeObject::TYPE_NAME || $resource->getType() == InternalType\AbstractTypeObject::TYPE_STRING) {
         // Resource is an array, just treat it as an explicit destination array
         return Destination\AbstractDestination::load($resource);
     } else {
         throw new Exception\CorruptedPdfException('Wrong resource type.');
     }
 }
Esempio n. 8
0
 /**
  * Set top level parent indirect object.
  *
  * @param \Zend\Pdf\InternalType\IndirectObject $parent
  */
 public function setParentObject(IndirectObject $parent)
 {
     parent::setParentObject($parent);
     foreach ($this->_items as $item) {
         $item->setParentObject($parent);
     }
 }
Esempio n. 9
0
 /**
  * Load PDF action object using specified dictionary
  *
  * @internal
  * @param \Zend\PDF\InternalType\AbstractTypeObject $dictionary (It's actually Dictionary or Dictionary Object or Reference to a Dictionary Object)
  * @param SplObjectStorage $processedActions  list of already processed action dictionaries, used to avoid cyclic references
  * @return \Zend\PDF\Action\AbstractAction
  * @throws \Zend\PDF\Exception
  */
 public static function load(InternalType\AbstractTypeObject $dictionary, \SplObjectStorage $processedActions = null)
 {
     if ($processedActions === null) {
         $processedActions = new \SplObjectStorage();
     }
     if ($dictionary->getType() != InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
         throw new PDF\Exception('$dictionary mast be a direct or an indirect dictionary object.');
     }
     if (isset($dictionary->Type) && $dictionary->Type->value != 'Action') {
         throw new PDF\Exception('Action dictionary Type entry must be set to \'Action\'.');
     }
     if ($dictionary->S === null) {
         throw new PDF\Exception('Action dictionary must contain S entry');
     }
     switch ($dictionary->S->value) {
         case 'GoTo':
             return new GoToAction($dictionary, $processedActions);
             brake;
         case 'GoToR':
             return new GoToR($dictionary, $processedActions);
             brake;
         case 'GoToE':
             return new GoToE($dictionary, $processedActions);
             brake;
         case 'Launch':
             return new Launch($dictionary, $processedActions);
             brake;
         case 'Thread':
             return new Thread($dictionary, $processedActions);
             brake;
         case 'URI':
             return new URI($dictionary, $processedActions);
             brake;
         case 'Sound':
             return new Sound($dictionary, $processedActions);
             brake;
         case 'Movie':
             return new Movie($dictionary, $processedActions);
             brake;
         case 'Hide':
             return new Hide($dictionary, $processedActions);
             brake;
         case 'Named':
             return new Named($dictionary, $processedActions);
             brake;
         case 'SubmitForm':
             return new SubmitForm($dictionary, $processedActions);
             brake;
         case 'ResetForm':
             return new ResetForm($dictionary, $processedActions);
             brake;
         case 'ImportData':
             return new ImportData($dictionary, $processedActions);
             brake;
         case 'JavaScript':
             return new JavaScript($dictionary, $processedActions);
             brake;
         case 'SetOCGState':
             return new SetOCGState($dictionary, $processedActions);
             brake;
         case 'Rendition':
             return new Rendition($dictionary, $processedActions);
             brake;
         case 'Trans':
             return new Trans($dictionary, $processedActions);
             brake;
         case 'GoTo3DView':
             return new GoTo3DView($dictionary, $processedActions);
             brake;
         default:
             return new Unknown($dictionary, $processedActions);
             brake;
     }
 }
Esempio n. 10
0
 /**
  * Convert PDF element to PHP type.
  *
  * @return mixed
  */
 public function toPhp()
 {
     return $this->_value->toPhp();
 }
Esempio n. 11
0
 /**
  * Render the completed PDF to a string.
  * If $newSegmentOnly is true, then only appended part of PDF is returned.
  *
  * @param boolean $newSegmentOnly
  * @param resource $outputStream
  * @return string
  * @throws \Zend\Pdf\Exception
  */
 public function render($newSegmentOnly = false, $outputStream = null)
 {
     // Save document properties if necessary
     if ($this->properties != $this->_originalProperties) {
         $docInfo = $this->_objFactory->newObject(new InternalType\DictionaryObject());
         foreach ($this->properties as $key => $value) {
             switch ($key) {
                 case 'Trapped':
                     switch ($value) {
                         case true:
                             $docInfo->{$key} = new InternalType\NameObject('True');
                             break;
                         case false:
                             $docInfo->{$key} = new InternalType\NameObject('False');
                             break;
                         case null:
                             $docInfo->{$key} = new InternalType\NameObject('Unknown');
                             break;
                         default:
                             throw new Exception\LogicException('Wrong Trapped document property vale: \'' . $value . '\'. Only true, false and null values are allowed.');
                             break;
                     }
                 case 'CreationDate':
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 case 'ModDate':
                     $docInfo->{$key} = new InternalType\StringObject((string) $value);
                     break;
                 case 'Title':
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 case 'Author':
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 case 'Subject':
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 case 'Keywords':
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 case 'Creator':
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                     // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 // break intentionally omitted
                 case 'Producer':
                     if (extension_loaded('mbstring') === true) {
                         $detected = mb_detect_encoding($value);
                         if ($detected !== 'ASCII') {
                             $value = chr(254) . chr(255) . mb_convert_encoding($value, 'UTF-16', $detected);
                         }
                     }
                     $docInfo->{$key} = new InternalType\StringObject((string) $value);
                     break;
                 default:
                     // Set property using PDF type based on PHP type
                     $docInfo->{$key} = InternalType\AbstractTypeObject::phpToPDF($value);
                     break;
             }
         }
         $this->_trailer->Info = $docInfo;
     }
     $this->_dumpPages();
     $this->_dumpNamedDestinations();
     $this->_dumpOutlines();
     // Check, that PDF file was modified
     // File is always modified by _dumpPages() now, but future implementations may eliminate this.
     if (!$this->_objFactory->isModified()) {
         if ($newSegmentOnly) {
             // Do nothing, return
             return '';
         }
         if ($outputStream === null) {
             return $this->_trailer->getPDFString();
         } else {
             $pdfData = $this->_trailer->getPDFString();
             while (strlen($pdfData) > 0 && ($byteCount = fwrite($outputStream, $pdfData)) != false) {
                 $pdfData = substr($pdfData, $byteCount);
             }
             return '';
         }
     }
     // offset (from a start of PDF file) of new PDF file segment
     $offset = $this->_trailer->getPDFLength();
     // Last Object number in a list of free objects
     $lastFreeObject = $this->_trailer->getLastFreeObject();
     // Array of cross-reference table subsections
     $xrefTable = array();
     // Object numbers of first objects in each subsection
     $xrefSectionStartNums = array();
     // Last cross-reference table subsection
     $xrefSection = array();
     // Dummy initialization of the first element (specail case - header of linked list of free objects).
     $xrefSection[] = 0;
     $xrefSectionStartNums[] = 0;
     // Object number of last processed PDF object.
     // Used to manage cross-reference subsections.
     // Initialized by zero (specail case - header of linked list of free objects).
     $lastObjNum = 0;
     if ($outputStream !== null) {
         if (!$newSegmentOnly) {
             $pdfData = $this->_trailer->getPDFString();
             while (strlen($pdfData) > 0 && ($byteCount = fwrite($outputStream, $pdfData)) != false) {
                 $pdfData = substr($pdfData, $byteCount);
             }
         }
     } else {
         $pdfSegmentBlocks = $newSegmentOnly ? array() : array($this->_trailer->getPDFString());
     }
     // Iterate objects to create new reference table
     foreach ($this->_objFactory->listModifiedObjects() as $updateInfo) {
         $objNum = $updateInfo->getObjNum();
         if ($objNum - $lastObjNum != 1) {
             // Save cross-reference table subsection and start new one
             $xrefTable[] = $xrefSection;
             $xrefSection = array();
             $xrefSectionStartNums[] = $objNum;
         }
         if ($updateInfo->isFree()) {
             // Free object cross-reference table entry
             $xrefSection[] = sprintf("%010d %05d f \n", $lastFreeObject, $updateInfo->getGenNum());
             $lastFreeObject = $objNum;
         } else {
             // In-use object cross-reference table entry
             $xrefSection[] = sprintf("%010d %05d n \n", $offset, $updateInfo->getGenNum());
             $pdfBlock = $updateInfo->getObjectDump();
             $offset += strlen($pdfBlock);
             if ($outputStream === null) {
                 $pdfSegmentBlocks[] = $pdfBlock;
             } else {
                 while (strlen($pdfBlock) > 0 && ($byteCount = fwrite($outputStream, $pdfBlock)) != false) {
                     $pdfBlock = substr($pdfBlock, $byteCount);
                 }
             }
         }
         $lastObjNum = $objNum;
     }
     // Save last cross-reference table subsection
     $xrefTable[] = $xrefSection;
     // Modify first entry (specail case - header of linked list of free objects).
     $xrefTable[0][0] = sprintf("%010d 65535 f \n", $lastFreeObject);
     $xrefTableStr = "xref\n";
     foreach ($xrefTable as $sectId => $xrefSection) {
         $xrefTableStr .= sprintf("%d %d \n", $xrefSectionStartNums[$sectId], count($xrefSection));
         foreach ($xrefSection as $xrefTableEntry) {
             $xrefTableStr .= $xrefTableEntry;
         }
     }
     $this->_trailer->Size->value = $this->_objFactory->getObjectCount();
     $pdfBlock = $xrefTableStr . $this->_trailer->toString() . "startxref\n" . $offset . "\n" . "%%EOF\n";
     $this->_objFactory->cleanEnumerationShiftCache();
     if ($outputStream === null) {
         $pdfSegmentBlocks[] = $pdfBlock;
         return implode('', $pdfSegmentBlocks);
     } else {
         while (strlen($pdfBlock) > 0 && ($byteCount = fwrite($outputStream, $pdfBlock)) != false) {
             $pdfBlock = substr($pdfBlock, $byteCount);
         }
         return '';
     }
 }
Esempio n. 12
0
    /**
     * Annotation object constructor
     *
     * @throws \Zend\Pdf\Exception\ExceptionInterface
     */
    public function __construct(InternalType\AbstractTypeObject $annotationDictionary)
    {
        if ($annotationDictionary->getType() != InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
            throw new Exception\CorruptedPdfException('Annotation dictionary resource has to be a dictionary.');
        }

        $this->_annotationDictionary = $annotationDictionary;

        if ($this->_annotationDictionary->Type !== null  &&
            $this->_annotationDictionary->Type->value != 'Annot') {
            throw new Exception\CorruptedPdfException('Wrong resource type. \'Annot\' expected.');
        }

        if ($this->_annotationDictionary->Rect === null) {
            throw new Exception\CorruptedPdfException('\'Rect\' dictionary entry is required.');
        }

        if (count($this->_annotationDictionary->Rect->items) != 4 ||
            $this->_annotationDictionary->Rect->items[0]->getType() != InternalType\AbstractTypeObject::TYPE_NUMERIC ||
            $this->_annotationDictionary->Rect->items[1]->getType() != InternalType\AbstractTypeObject::TYPE_NUMERIC ||
            $this->_annotationDictionary->Rect->items[2]->getType() != InternalType\AbstractTypeObject::TYPE_NUMERIC ||
            $this->_annotationDictionary->Rect->items[3]->getType() != InternalType\AbstractTypeObject::TYPE_NUMERIC ) {
            throw new Exception\CorruptedPdfException('\'Rect\' dictionary entry must be an array of four numeric elements.');
        }
    }
Esempio n. 13
0
 /**
  * Create PDF outline object using specified dictionary
  *
  * @internal
  * @param \Zend\Pdf\InternalType\AbstractTypeObject $dictionary (It's actually Dictionary or Dictionary Object or Reference to a Dictionary Object)
  * @param \Zend\Pdf\Action\AbstractAction  $parentAction
  * @param SplObjectStorage $processedOutlines  List of already processed Outline dictionaries,
  *                                             used to avoid cyclic references
  * @return \Zend\Pdf\Action\AbstractAction
  * @throws \Zend\Pdf\Exception
  */
 public function __construct(InternalType\AbstractTypeObject $dictionary, \SplObjectStorage $processedDictionaries = null)
 {
     if ($dictionary->getType() != InternalType\AbstractTypeObject::TYPE_DICTIONARY) {
         throw new Exception\CorruptedPdfException('$dictionary mast be an indirect dictionary object.');
     }
     if ($processedDictionaries === null) {
         $processedDictionaries = new \SplObjectStorage();
     }
     $processedDictionaries->attach($dictionary);
     $this->_outlineDictionary = $dictionary;
     if ($dictionary->Count !== null) {
         if ($dictionary->Count->getType() != InternalType\AbstractTypeObject::TYPE_NUMERIC) {
             throw new Exception\CorruptedPdfException('Outline dictionary Count entry must be a numeric element.');
         }
         $childOutlinesCount = $dictionary->Count->value;
         if ($childOutlinesCount > 0) {
             $this->_open = true;
         }
         $childOutlinesCount = abs($childOutlinesCount);
         $childDictionary = $dictionary->First;
         for ($count = 0; $count < $childOutlinesCount; $count++) {
             if ($childDictionary === null) {
                 throw new Exception\CorruptedPdfException('Outline childs load error.');
             }
             if (!$processedDictionaries->contains($childDictionary)) {
                 $this->childOutlines[] = new Loaded($childDictionary, $processedDictionaries);
             }
             $childDictionary = $childDictionary->Next;
         }
         if ($childDictionary !== null) {
             throw new Exception\CorruptedPdfException('Outline childs load error.');
         }
         $this->_originalChildOutlines = $this->childOutlines;
     }
 }