From f3b00829ed5d6f0c5ef182f81ea79f52ff59f78b Mon Sep 17 00:00:00 2001 From: Sebijk Date: Fri, 13 Oct 2023 21:40:43 +0200 Subject: [PATCH] fix static call in fax plugin and update fpdi to 2.5 --- src/plugins/fax.plugin.php | 3 +- src/serverlib/3rdparty/fpdf/fpdi/LICENSE.txt | 2 +- .../3rdparty/fpdf/fpdi/composer.json | 2 +- .../3rdparty/fpdf/fpdi/src/FpdfTpl.php | 2 +- .../3rdparty/fpdf/fpdi/src/FpdfTplTrait.php | 13 +- .../3rdparty/fpdf/fpdi/src/FpdfTrait.php | 205 ++++++++++++++++++ src/serverlib/3rdparty/fpdf/fpdi/src/Fpdi.php | 125 +---------- .../3rdparty/fpdf/fpdi/src/FpdiException.php | 2 +- .../3rdparty/fpdf/fpdi/src/FpdiTrait.php | 119 ++++++++-- .../3rdparty/fpdf/fpdi/src/GraphicsState.php | 97 +++++++++ .../3rdparty/fpdf/fpdi/src/Math/Matrix.php | 116 ++++++++++ .../3rdparty/fpdf/fpdi/src/Math/Vector.php | 66 ++++++ .../CrossReference/AbstractReader.php | 2 +- .../CrossReference/CrossReference.php | 2 +- .../CrossReferenceException.php | 2 +- .../PdfParser/CrossReference/FixedReader.php | 2 +- .../PdfParser/CrossReference/LineReader.php | 2 +- .../CrossReference/ReaderInterface.php | 2 +- .../fpdi/src/PdfParser/Filter/Ascii85.php | 2 +- .../src/PdfParser/Filter/Ascii85Exception.php | 2 +- .../fpdi/src/PdfParser/Filter/AsciiHex.php | 2 +- .../src/PdfParser/Filter/FilterException.php | 2 +- .../src/PdfParser/Filter/FilterInterface.php | 2 +- .../fpdf/fpdi/src/PdfParser/Filter/Flate.php | 6 +- .../src/PdfParser/Filter/FlateException.php | 2 +- .../fpdf/fpdi/src/PdfParser/Filter/Lzw.php | 2 +- .../src/PdfParser/Filter/LzwException.php | 2 +- .../fpdf/fpdi/src/PdfParser/PdfParser.php | 86 ++++++-- .../fpdi/src/PdfParser/PdfParserException.php | 2 +- .../fpdf/fpdi/src/PdfParser/StreamReader.php | 8 +- .../fpdf/fpdi/src/PdfParser/Tokenizer.php | 2 +- .../fpdf/fpdi/src/PdfParser/Type/PdfArray.php | 4 +- .../fpdi/src/PdfParser/Type/PdfBoolean.php | 2 +- .../fpdi/src/PdfParser/Type/PdfDictionary.php | 2 +- .../fpdi/src/PdfParser/Type/PdfHexString.php | 4 +- .../src/PdfParser/Type/PdfIndirectObject.php | 16 +- .../Type/PdfIndirectObjectReference.php | 2 +- .../fpdf/fpdi/src/PdfParser/Type/PdfName.php | 2 +- .../fpdf/fpdi/src/PdfParser/Type/PdfNull.php | 2 +- .../fpdi/src/PdfParser/Type/PdfNumeric.php | 2 +- .../fpdi/src/PdfParser/Type/PdfStream.php | 49 ++++- .../fpdi/src/PdfParser/Type/PdfString.php | 32 ++- .../fpdf/fpdi/src/PdfParser/Type/PdfToken.php | 2 +- .../fpdf/fpdi/src/PdfParser/Type/PdfType.php | 2 +- .../src/PdfParser/Type/PdfTypeException.php | 2 +- .../src/PdfReader/DataStructure/Rectangle.php | 8 +- .../3rdparty/fpdf/fpdi/src/PdfReader/Page.php | 126 ++++++++++- .../fpdi/src/PdfReader/PageBoundaries.php | 2 +- .../fpdf/fpdi/src/PdfReader/PdfReader.php | 2 +- .../fpdi/src/PdfReader/PdfReaderException.php | 2 +- .../3rdparty/fpdf/fpdi/src/Tcpdf/Fpdi.php | 141 +++++++++++- .../3rdparty/fpdf/fpdi/src/TcpdfFpdi.php | 2 +- .../3rdparty/fpdf/fpdi/src/Tfpdf/FpdfTpl.php | 2 +- .../3rdparty/fpdf/fpdi/src/Tfpdf/Fpdi.php | 130 +---------- .../3rdparty/fpdf/fpdi/src/autoload.php | 2 +- 55 files changed, 1071 insertions(+), 353 deletions(-) create mode 100644 src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTrait.php create mode 100644 src/serverlib/3rdparty/fpdf/fpdi/src/GraphicsState.php create mode 100644 src/serverlib/3rdparty/fpdf/fpdi/src/Math/Matrix.php create mode 100644 src/serverlib/3rdparty/fpdf/fpdi/src/Math/Vector.php diff --git a/src/plugins/fax.plugin.php b/src/plugins/fax.plugin.php index 5fba0b0..0e85f84 100644 --- a/src/plugins/fax.plugin.php +++ b/src/plugins/fax.plugin.php @@ -3544,9 +3544,10 @@ function _FaxPluginCreateFPDISubclass() $this->SetFillColor(255, 255, 255); // draw + if(function_exists('CharsetDecode')) $this->signatureArray['text'] = CharsetDecode($this->signatureArray['text'], false, 'ISO-8859-15'); $this->MultiCell(0, ($this->signatureArray['fontsize']/$this->k)*1.5, - FaxPlugin::_pdfStr($this->signatureArray['text']), + $this->signatureArray['text'], $border, $this->signatureArray['align'], true); diff --git a/src/serverlib/3rdparty/fpdf/fpdi/LICENSE.txt b/src/serverlib/3rdparty/fpdf/fpdi/LICENSE.txt index 45672fa..f1778c7 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/LICENSE.txt +++ b/src/serverlib/3rdparty/fpdf/fpdi/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Setasign GmbH & Co. KG, https://www.setasign.com +Copyright (c) 2023 Setasign GmbH & Co. KG, https://www.setasign.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/serverlib/3rdparty/fpdf/fpdi/composer.json b/src/serverlib/3rdparty/fpdf/fpdi/composer.json index da67012..b947748 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/composer.json +++ b/src/serverlib/3rdparty/fpdf/fpdi/composer.json @@ -40,7 +40,7 @@ "phpunit/phpunit": "~5.7", "setasign/fpdf": "~1.8", "tecnickcom/tcpdf": "~6.2", - "setasign/tfpdf": "1.31", + "setasign/tfpdf": "~1.31", "squizlabs/php_codesniffer": "^3.5" }, "autoload-dev": { diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTpl.php b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTpl.php index 4b93f53..0f3a6fc 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTpl.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTpl.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTplTrait.php b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTplTrait.php index d2da97c..2da9d55 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTplTrait.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTplTrait.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -13,7 +13,7 @@ namespace setasign\Fpdi; /** * Trait FpdfTplTrait * - * This class adds a templating feature to tFPDF. + * This trait adds a templating feature to FPDF and tFPDF. */ trait FpdfTplTrait { @@ -234,7 +234,9 @@ trait FpdfTplTrait 'lMargin' => $this->lMargin, 'rMargin' => $this->rMargin, 'h' => $this->h, + 'hPt' => $this->hPt, 'w' => $this->w, + 'wPt' => $this->wPt, 'FontFamily' => $this->FontFamily, 'FontStyle' => $this->FontStyle, 'FontSizePt' => $this->FontSizePt, @@ -251,7 +253,9 @@ trait FpdfTplTrait $this->currentTemplateId = $templateId; $this->h = $height; + $this->hPt = $height / $this->k; $this->w = $width; + $this->wPt = $width / $this->k; $this->SetXY($this->lMargin, $this->tMargin); $this->SetRightMargin($this->w - $width + $this->rMargin); @@ -279,7 +283,9 @@ trait FpdfTplTrait $this->lMargin = $state['lMargin']; $this->rMargin = $state['rMargin']; $this->h = $state['h']; + $this->hPt = $state['hPt']; $this->w = $state['w']; + $this->wPt = $state['wPt']; $this->SetAutoPageBreak($state['AutoPageBreak'], $state['bMargin']); $this->FontFamily = $state['FontFamily']; @@ -406,9 +412,6 @@ trait FpdfTplTrait } } - /** - * @inheritdoc - */ protected function _putimages() { parent::_putimages(); diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTrait.php b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTrait.php new file mode 100644 index 0000000..0b56288 --- /dev/null +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdfTrait.php @@ -0,0 +1,205 @@ +cleanUp(); + } + + /** + * Draws an imported page or a template onto the page or another template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see Fpdi::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (isset($this->importedPages[$tpl])) { + $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); + if ($this->currentTemplateId !== null) { + $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl; + } + return $size; + } + + return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize); + } + + /** + * Get the size of an imported page or template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + $size = parent::getTemplateSize($tpl, $width, $height); + if ($size === false) { + return $this->getImportedPageSize($tpl, $width, $height); + } + + return $size; + } + + /** + * @throws CrossReferenceException + * @throws PdfParserException + */ + protected function _putimages() + { + $this->currentReaderId = null; + parent::_putimages(); + + foreach ($this->importedPages as $key => $pageData) { + $this->_newobj(); + $this->importedPages[$key]['objectNumber'] = $this->n; + $this->currentReaderId = $pageData['readerId']; + $this->writePdfType($pageData['stream']); + $this->_put('endobj'); + } + + foreach (\array_keys($this->readers) as $readerId) { + $parser = $this->getPdfReader($readerId)->getParser(); + $this->currentReaderId = $readerId; + + while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { + try { + $object = $parser->getIndirectObject($objectNumber); + } catch (CrossReferenceException $e) { + if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { + $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); + } else { + throw $e; + } + } + + $this->writePdfType($object); + } + } + + $this->currentReaderId = null; + } + + /** + * @inheritdoc + */ + protected function _putxobjectdict() + { + foreach ($this->importedPages as $pageData) { + $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); + } + + parent::_putxobjectdict(); + } + + /** + * @param int $n + * @return void + * @throws PdfParser\Type\PdfTypeException + */ + protected function _putlinks($n) + { + foreach ($this->PageLinks[$n] as $pl) { + $this->_newobj(); + $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]); + $this->_put('<_put('/A <_textstring($pl[4]) . '>>'); + if (isset($pl['importedLink'])) { + $values = $pl['importedLink']['pdfObject']->value; + unset( + $values['P'], + $values['NM'], + $values['AP'], + $values['AS'], + $values['Type'], + $values['Subtype'], + $values['Rect'], + $values['A'], + $values['QuadPoints'], + $values['Rotate'], + $values['M'], + $values['StructParent'] + ); + + foreach ($values as $name => $entry) { + $this->_put('/' . $name . ' ', false); + $this->writePdfType($entry); + } + + if (isset($pl['quadPoints'])) { + $s = '/QuadPoints['; + foreach ($pl['quadPoints'] as $value) { + $s .= sprintf('%.2F ', $value); + } + $s .= ']'; + $this->_put($s); + } + } else { + $this->_put('/Border [0 0 0]', false); + } + $this->_put('>>'); + } else { + $this->_put('/Border [0 0 0] ', false); + $l = $this->links[$pl[4]]; + if (isset($this->PageInfo[$l[0]]['size'])) { + $h = $this->PageInfo[$l[0]]['size'][1]; + } else { + $h = ($this->DefOrientation === 'P') + ? $this->DefPageSize[1] * $this->k + : $this->DefPageSize[0] * $this->k; + } + $this->_put(sprintf( + '/Dest [%d 0 R /XYZ 0 %.2F null]>>', + $this->PageInfo[$l[0]]['n'], + $h - $l[1] * $this->k + )); + } + $this->_put('endobj'); + } + } + + protected function _put($s, $newLine = true) + { + if ($newLine) { + $this->buffer .= $s . "\n"; + } else { + $this->buffer .= $s; + } + } +} diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/Fpdi.php b/src/serverlib/3rdparty/fpdf/fpdi/src/Fpdi.php index dc46bb1..7c1f493 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/Fpdi.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/Fpdi.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -23,131 +23,12 @@ use setasign\Fpdi\PdfParser\Type\PdfNull; class Fpdi extends FpdfTpl { use FpdiTrait; + use FpdfTrait; /** * FPDI version * * @string */ - const VERSION = '2.3.7'; - - protected function _enddoc() - { - parent::_enddoc(); - $this->cleanUp(); - } - - /** - * Draws an imported page or a template onto the page or another template. - * - * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the - * aspect ratio. - * - * @param mixed $tpl The template id - * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array - * with the keys "x", "y", "width", "height", "adjustPageSize". - * @param float|int $y The ordinate of upper-left corner. - * @param float|int|null $width The width. - * @param float|int|null $height The height. - * @param bool $adjustPageSize - * @return array The size - * @see Fpdi::getTemplateSize() - */ - public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) - { - if (isset($this->importedPages[$tpl])) { - $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); - if ($this->currentTemplateId !== null) { - $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl; - } - return $size; - } - - return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize); - } - - /** - * Get the size of an imported page or template. - * - * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the - * aspect ratio. - * - * @param mixed $tpl The template id - * @param float|int|null $width The width. - * @param float|int|null $height The height. - * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) - */ - public function getTemplateSize($tpl, $width = null, $height = null) - { - $size = parent::getTemplateSize($tpl, $width, $height); - if ($size === false) { - return $this->getImportedPageSize($tpl, $width, $height); - } - - return $size; - } - - /** - * @inheritdoc - * @throws CrossReferenceException - * @throws PdfParserException - */ - protected function _putimages() - { - $this->currentReaderId = null; - parent::_putimages(); - - foreach ($this->importedPages as $key => $pageData) { - $this->_newobj(); - $this->importedPages[$key]['objectNumber'] = $this->n; - $this->currentReaderId = $pageData['readerId']; - $this->writePdfType($pageData['stream']); - $this->_put('endobj'); - } - - foreach (\array_keys($this->readers) as $readerId) { - $parser = $this->getPdfReader($readerId)->getParser(); - $this->currentReaderId = $readerId; - - while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { - try { - $object = $parser->getIndirectObject($objectNumber); - } catch (CrossReferenceException $e) { - if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { - $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); - } else { - throw $e; - } - } - - $this->writePdfType($object); - } - } - - $this->currentReaderId = null; - } - - /** - * @inheritdoc - */ - protected function _putxobjectdict() - { - foreach ($this->importedPages as $key => $pageData) { - $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); - } - - parent::_putxobjectdict(); - } - - /** - * @inheritdoc - */ - protected function _put($s, $newLine = true) - { - if ($newLine) { - $this->buffer .= $s . "\n"; - } else { - $this->buffer .= $s; - } - } + const VERSION = '2.5.0'; } diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiException.php index 2286667..0414d8b 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiTrait.php b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiTrait.php index 3b29857..8387528 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiTrait.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/FpdiTrait.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -29,6 +29,7 @@ use setasign\Fpdi\PdfParser\Type\PdfString; use setasign\Fpdi\PdfParser\Type\PdfToken; use setasign\Fpdi\PdfParser\Type\PdfType; use setasign\Fpdi\PdfParser\Type\PdfTypeException; +use setasign\Fpdi\PdfReader\DataStructure\Rectangle; use setasign\Fpdi\PdfReader\PageBoundaries; use setasign\Fpdi\PdfReader\PdfReader; use setasign\Fpdi\PdfReader\PdfReaderException; @@ -123,9 +124,10 @@ trait FpdiTrait * Get a new pdf parser instance. * * @param StreamReader $streamReader + * @param array $parserParams Individual parameters passed to the parser instance. * @return PdfParser|FpdiPdfParser */ - protected function getPdfParserInstance(StreamReader $streamReader) + protected function getPdfParserInstance(StreamReader $streamReader, array $parserParams = []) { // note: if you get an exception here - turn off errors/warnings on not found for your autoloader. // psr-4 (https://www.php-fig.org/psr/psr-4/) says: Autoloader implementations MUST NOT throw @@ -133,7 +135,7 @@ trait FpdiTrait /** @noinspection PhpUndefinedClassInspection */ if (\class_exists(FpdiPdfParser::class)) { /** @noinspection PhpUndefinedClassInspection */ - return new FpdiPdfParser($streamReader); + return new FpdiPdfParser($streamReader, $parserParams); } return new PdfParser($streamReader); @@ -144,9 +146,10 @@ trait FpdiTrait * * @param string|resource|PdfReader|StreamReader $file An open file descriptor, a path to a file, a PdfReader * instance or a StreamReader instance. + * @param array $parserParams Individual parameters passed to the parser instance. * @return string */ - protected function getPdfReaderId($file) + protected function getPdfReaderId($file, array $parserParams = []) { if (\is_resource($file)) { $id = (string) $file; @@ -177,7 +180,7 @@ trait FpdiTrait $streamReader = $file; } - $reader = new PdfReader($this->getPdfParserInstance($streamReader)); + $reader = new PdfReader($this->getPdfParserInstance($streamReader, $parserParams)); /** @noinspection OffsetOperationsInspection */ $this->readers[$id] = $reader; @@ -210,7 +213,24 @@ trait FpdiTrait */ public function setSourceFile($file) { - $this->currentReaderId = $this->getPdfReaderId($file); + return $this->setSourceFileWithParserParams($file); + } + + /** + * Set the source PDF file with parameters which are passed to the parser instance. + * + * This method allows us to pass e.g. authentication information to the parser instance. + * + * @param string|resource|StreamReader $file Path to the file or a stream resource or a StreamReader instance. + * @param array $parserParams Individual parameters passed to the parser instance. + * @return int The page count of the PDF document. + * @throws CrossReferenceException + * @throws PdfParserException + * @throws PdfTypeException + */ + public function setSourceFileWithParserParams($file, array $parserParams = []) + { + $this->currentReaderId = $this->getPdfReaderId($file, $parserParams); $this->objectsToCopy[$this->currentReaderId] = []; $reader = $this->getPdfReader($this->currentReaderId); @@ -225,6 +245,7 @@ trait FpdiTrait * @param int $pageNumber The page number. * @param string $box The page boundary to import. Default set to PageBoundaries::CROP_BOX. * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used). + * @param bool $importExternalLinks Define whether external links are imported or not. * @return string A unique string identifying the imported page. * @throws CrossReferenceException * @throws FilterException @@ -233,16 +254,20 @@ trait FpdiTrait * @throws PdfReaderException * @see PageBoundaries */ - public function importPage($pageNumber, $box = PageBoundaries::CROP_BOX, $groupXObject = true) - { - if (null === $this->currentReaderId) { + public function importPage( + $pageNumber, + $box = PageBoundaries::CROP_BOX, + $groupXObject = true, + $importExternalLinks = false + ) { + if ($this->currentReaderId === null) { throw new \BadMethodCallException('No reader initiated. Call setSourceFile() first.'); } $pageId = $this->currentReaderId; $pageNumber = (int)$pageNumber; - $pageId .= '|' . $pageNumber . '|' . ($groupXObject ? '1' : '0'); + $pageId .= '|' . $pageNumber . '|' . ($groupXObject ? '1' : '0') . '|' . ($importExternalLinks ? '1' : '0'); // for backwards compatibility with FPDI 1 $box = \ltrim($box, '/'); @@ -378,13 +403,19 @@ trait FpdiTrait $stream = PdfStream::create($dict, ''); } + $externalLinks = []; + if ($importExternalLinks) { + $externalLinks = $page->getExternalLinks($box); + } + $this->importedPages[$pageId] = [ 'objectNumber' => null, 'readerId' => $this->currentReaderId, 'id' => 'TPL' . $this->getNextTemplateId(), 'width' => $width / $this->k, 'height' => $height / $this->k, - 'stream' => $stream + 'stream' => $stream, + 'externalLinks' => $externalLinks ]; return $pageId; @@ -430,21 +461,79 @@ trait FpdiTrait $this->setPageFormat($newSize, $newSize['orientation']); } + $scaleX = ($newSize['width'] / $originalSize['width']); + $scaleY = ($newSize['height'] / $originalSize['height']); + $xPt = $x * $this->k; + $yPt = $y * $this->k; + $newHeightPt = $newSize['height'] * $this->k; + $this->_out( // reset standard values, translate and scale \sprintf( 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q', - ($newSize['width'] / $originalSize['width']), - ($newSize['height'] / $originalSize['height']), - $x * $this->k, - ($this->h - $y - $newSize['height']) * $this->k, + $scaleX, + $scaleY, + $xPt, + $this->hPt - $yPt - $newHeightPt, $importedPage['id'] ) ); + if (count($importedPage['externalLinks']) > 0) { + foreach ($importedPage['externalLinks'] as $externalLink) { + // mPDF uses also 'externalLinks' but doesn't come with a rect-value + if (!isset($externalLink['rect'])) { + continue; + } + + /** @var Rectangle $rect */ + $rect = $externalLink['rect']; + $this->Link( + $x + $rect->getLlx() / $this->k * $scaleX, + $y + $newSize['height'] - ($rect->getLly() + $rect->getHeight()) / $this->k * $scaleY, + $rect->getWidth() / $this->k * $scaleX, + $rect->getHeight() / $this->k * $scaleY, + $externalLink['uri'] + ); + + $this->adjustLastLink($externalLink, $xPt, $scaleX, $yPt, $newHeightPt, $scaleY, $importedPage); + } + } + return $newSize; } + /** + * This method will add additional data to the last created link/annotation. + * + * It is separated because TCPDF uses its own logic to handle link annotations. + * This method is overwritten in the TCPDF implementation. + * + * @param array $externalLink + * @param float|int $xPt + * @param float|int $scaleX + * @param float|int $yPt + * @param float|int $newHeightPt + * @param float|int $scaleY + * @param array $importedPage + * @return void + */ + protected function adjustLastLink($externalLink, $xPt, $scaleX, $yPt, $newHeightPt, $scaleY, $importedPage) + { + // let's create a relation of the newly created link to the data of the external link + $lastLink = count($this->PageLinks[$this->page]); + $this->PageLinks[$this->page][$lastLink - 1]['importedLink'] = $externalLink; + if (count($externalLink['quadPoints']) > 0) { + $quadPoints = []; + for ($i = 0, $n = count($externalLink['quadPoints']); $i < $n; $i += 2) { + $quadPoints[] = $xPt + $externalLink['quadPoints'][$i] * $scaleX; + $quadPoints[] = $this->hPt - $yPt - $newHeightPt + $externalLink['quadPoints'][$i + 1] * $scaleY; + } + + $this->PageLinks[$this->page][$lastLink - 1]['quadPoints'] = $quadPoints; + } + } + /** * Get the size of an imported page. * diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/GraphicsState.php b/src/serverlib/3rdparty/fpdf/fpdi/src/GraphicsState.php new file mode 100644 index 0000000..27feafb --- /dev/null +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/GraphicsState.php @@ -0,0 +1,97 @@ +ctm = $ctm; + } + + /** + * @param Matrix $matrix + * @return $this + */ + public function add(Matrix $matrix) + { + $this->ctm = $matrix->multiply($this->ctm); + return $this; + } + + /** + * @param int|float $x + * @param int|float $y + * @param int|float $angle + * @return $this + */ + public function rotate($x, $y, $angle) + { + if (abs($angle) < 1e-5) { + return $this; + } + + $angle = deg2rad($angle); + $c = cos($angle); + $s = sin($angle); + + $this->add(new Matrix($c, $s, -$s, $c, $x, $y)); + + return $this->translate(-$x, -$y); + } + + /** + * @param int|float $shiftX + * @param int|float $shiftY + * @return $this + */ + public function translate($shiftX, $shiftY) + { + return $this->add(new Matrix(1, 0, 0, 1, $shiftX, $shiftY)); + } + + /** + * @param int|float $scaleX + * @param int|float $scaleY + * @return $this + */ + public function scale($scaleX, $scaleY) + { + return $this->add(new Matrix($scaleX, 0, 0, $scaleY, 0, 0)); + } + + /** + * @param Vector $vector + * @return Vector + */ + public function toUserSpace(Vector $vector) + { + return $vector->multiplyWithMatrix($this->ctm); + } +} diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/Math/Matrix.php b/src/serverlib/3rdparty/fpdf/fpdi/src/Math/Matrix.php new file mode 100644 index 0000000..662a5a2 --- /dev/null +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/Math/Matrix.php @@ -0,0 +1,116 @@ +a = (float)$a; + $this->b = (float)$b; + $this->c = (float)$c; + $this->d = (float)$d; + $this->e = (float)$e; + $this->f = (float)$f; + } + + /** + * @return float[] + */ + public function getValues() + { + return [$this->a, $this->b, $this->c, $this->d, $this->e, $this->f]; + } + + /** + * @param Matrix $by + * @return Matrix + */ + public function multiply(self $by) + { + $a = + $this->a * $by->a + + $this->b * $by->c + //+ 0 * $by->e + ; + + $b = + $this->a * $by->b + + $this->b * $by->d + //+ 0 * $by->f + ; + + $c = + $this->c * $by->a + + $this->d * $by->c + //+ 0 * $by->e + ; + + $d = + $this->c * $by->b + + $this->d * $by->d + //+ 0 * $by->f + ; + + $e = + $this->e * $by->a + + $this->f * $by->c + + /*1 * */$by->e; + + $f = + $this->e * $by->b + + $this->f * $by->d + + /*1 * */$by->f; + + return new self($a, $b, $c, $d, $e, $f); + } +} diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/Math/Vector.php b/src/serverlib/3rdparty/fpdf/fpdi/src/Math/Vector.php new file mode 100644 index 0000000..df782d4 --- /dev/null +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/Math/Vector.php @@ -0,0 +1,66 @@ +x = (float)$x; + $this->y = (float)$y; + } + + /** + * @return float + */ + public function getX() + { + return $this->x; + } + + /** + * @return float + */ + public function getY() + { + return $this->y; + } + + /** + * @param Matrix $matrix + * @return Vector + */ + public function multiplyWithMatrix(Matrix $matrix) + { + list($a, $b, $c, $d, $e, $f) = $matrix->getValues(); + $x = $a * $this->x + $c * $this->y + $e; + $y = $b * $this->x + $d * $this->y + $f; + + return new self($x, $y); + } +} diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/AbstractReader.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/AbstractReader.php index b54237b..bcf21d6 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/AbstractReader.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/AbstractReader.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReference.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReference.php index c47e8c4..c9d19b9 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReference.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReference.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php index 7d88d5d..8a1a589 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/FixedReader.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/FixedReader.php index ed417df..8abf7fb 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/FixedReader.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/FixedReader.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/LineReader.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/LineReader.php index 5b67744..bcbd8e4 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/LineReader.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/LineReader.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/ReaderInterface.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/ReaderInterface.php index d2dfdd0..0bdc0ab 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/ReaderInterface.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/CrossReference/ReaderInterface.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85.php index 1dc936d..1a1882d 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85Exception.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85Exception.php index f4b6758..83a780c 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85Exception.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Ascii85Exception.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/AsciiHex.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/AsciiHex.php index d0c3436..c3ba800 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/AsciiHex.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/AsciiHex.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterException.php index c55a7a8..c71ff38 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterInterface.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterInterface.php index 3700190..3aa4872 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterInterface.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FilterInterface.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Flate.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Flate.php index b8f79d1..1cefa15 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Flate.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Flate.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -44,7 +44,9 @@ class Flate implements FilterInterface // let's try if the checksum is CRC32 $fh = fopen('php://temp', 'w+b'); fwrite($fh, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $oData); - stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 30]); + // "window" == 31 -> 16 + (8 to 15): Uses the low 4 bits of the value as the window size logarithm. + // The input must include a gzip header and trailer (via 16). + stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 31]); fseek($fh, 0); $data = @stream_get_contents($fh); fclose($fh); diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FlateException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FlateException.php index d897ac8..7791ca7 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FlateException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/FlateException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Lzw.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Lzw.php index 0d6cf38..f0b16c8 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Lzw.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/Lzw.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/LzwException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/LzwException.php index 6ebad4f..9f42038 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/LzwException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Filter/LzwException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParser.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParser.php index f724314..22a72e6 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParser.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParser.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -25,6 +25,7 @@ use setasign\Fpdi\PdfParser\Type\PdfStream; use setasign\Fpdi\PdfParser\Type\PdfString; use setasign\Fpdi\PdfParser\Type\PdfToken; use setasign\Fpdi\PdfParser\Type\PdfType; +use setasign\Fpdi\PdfParser\Type\PdfTypeException; /** * A PDF parser class @@ -145,7 +146,7 @@ class PdfParser } /** - * Get the cross reference instance. + * Get the cross-reference instance. * * @return CrossReference * @throws CrossReferenceException @@ -258,25 +259,25 @@ class PdfParser switch ($token) { case '(': $this->ensureExpectedType($token, $expectedType); - return PdfString::parse($this->streamReader); + return $this->parsePdfString(); case '<': if ($this->streamReader->getByte() === '<') { $this->ensureExpectedType('<<', $expectedType); $this->streamReader->addOffset(1); - return PdfDictionary::parse($this->tokenizer, $this->streamReader, $this); + return $this->parsePdfDictionary(); } $this->ensureExpectedType($token, $expectedType); - return PdfHexString::parse($this->streamReader); + return $this->parsePdfHexString(); case '/': $this->ensureExpectedType($token, $expectedType); - return PdfName::parse($this->tokenizer, $this->streamReader); + return $this->parsePdfName(); case '[': $this->ensureExpectedType($token, $expectedType); - return PdfArray::parse($this->tokenizer, $this); + return $this->parsePdfArray(); default: if (\is_numeric($token)) { @@ -291,13 +292,7 @@ class PdfParser ); } - return PdfIndirectObject::parse( - (int) $token, - (int) $token2, - $this, - $this->tokenizer, - $this->streamReader - ); + return $this->parsePdfIndirectObject((int)$token, (int)$token2); case 'R': if ( $expectedType !== null && @@ -309,7 +304,7 @@ class PdfParser ); } - return PdfIndirectObjectReference::create((int) $token, (int) $token2); + return PdfIndirectObjectReference::create((int)$token, (int)$token2); } $this->tokenizer->pushStack($token3); @@ -351,6 +346,65 @@ class PdfParser } } + /** + * @return PdfString + */ + protected function parsePdfString() + { + return PdfString::parse($this->streamReader); + } + + /** + * @return false|PdfHexString + */ + protected function parsePdfHexString() + { + return PdfHexString::parse($this->streamReader); + } + + /** + * @return bool|PdfDictionary + * @throws PdfTypeException + */ + protected function parsePdfDictionary() + { + return PdfDictionary::parse($this->tokenizer, $this->streamReader, $this); + } + + /** + * @return PdfName + */ + protected function parsePdfName() + { + return PdfName::parse($this->tokenizer, $this->streamReader); + } + + /** + * @return false|PdfArray + * @throws PdfTypeException + */ + protected function parsePdfArray() + { + return PdfArray::parse($this->tokenizer, $this); + } + + /** + * @param int $objectNumber + * @param int $generationNumber + * @return false|PdfIndirectObject + * @throws Type\PdfTypeException + */ + protected function parsePdfIndirectObject($objectNumber, $generationNumber) + { + return PdfIndirectObject::parse( + $objectNumber, + $generationNumber, + $this, + $this->tokenizer, + $this->streamReader + ); + } + /** * Ensures that the token will evaluate to an expected object type (or not). * @@ -359,7 +413,7 @@ class PdfParser * @return bool * @throws Type\PdfTypeException */ - private function ensureExpectedType($token, $expectedType) + protected function ensureExpectedType($token, $expectedType) { static $mapping = [ '(' => PdfString::class, diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParserException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParserException.php index 6d034d8..0629d9d 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParserException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/PdfParserException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/StreamReader.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/StreamReader.php index ee40ebb..a493a85 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/StreamReader.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/StreamReader.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -113,6 +113,12 @@ class StreamReader ); } + if (fseek($stream, 0) === -1) { + throw new \InvalidArgumentException( + 'Given stream is not seekable!' + ); + } + $this->stream = $stream; $this->closeStream = $closeStream; $this->reset(); diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Tokenizer.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Tokenizer.php index a3bcd01..5c1ccd8 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Tokenizer.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Tokenizer.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfArray.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfArray.php index 5d0bbbd..c7981b6 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfArray.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfArray.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -25,7 +25,7 @@ class PdfArray extends PdfType * * @param Tokenizer $tokenizer * @param PdfParser $parser - * @return bool|self + * @return false|self * @throws PdfTypeException */ public static function parse(Tokenizer $tokenizer, PdfParser $parser) diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfBoolean.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfBoolean.php index ba4233a..ad7c5d6 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfBoolean.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfBoolean.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfDictionary.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfDictionary.php index 2818842..8991322 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfDictionary.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfDictionary.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfHexString.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfHexString.php index 0084ada..cd9d2b6 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfHexString.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfHexString.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -21,7 +21,7 @@ class PdfHexString extends PdfType * Parses a hexadecimal string object from the stream reader. * * @param StreamReader $streamReader - * @return bool|self + * @return false|self */ public static function parse(StreamReader $streamReader) { diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObject.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObject.php index 15786d0..72a80e1 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObject.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObject.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -22,17 +22,17 @@ class PdfIndirectObject extends PdfType /** * Parses an indirect object from a tokenizer, parser and stream-reader. * - * @param int $objectNumberToken - * @param int $objectGenerationNumberToken + * @param int $objectNumber + * @param int $objectGenerationNumber * @param PdfParser $parser * @param Tokenizer $tokenizer * @param StreamReader $reader - * @return bool|self + * @return self|false * @throws PdfTypeException */ public static function parse( - $objectNumberToken, - $objectGenerationNumberToken, + $objectNumber, + $objectGenerationNumber, PdfParser $parser, Tokenizer $tokenizer, StreamReader $reader @@ -50,8 +50,8 @@ class PdfIndirectObject extends PdfType } $v = new self(); - $v->objectNumber = (int) $objectNumberToken; - $v->generationNumber = (int) $objectGenerationNumberToken; + $v->objectNumber = (int) $objectNumber; + $v->generationNumber = (int) $objectGenerationNumber; $v->value = $value; return $v; diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php index 2725d0c..975e9e8 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfName.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfName.php index 194a13f..0fbfe52 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfName.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfName.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNull.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNull.php index 0c4c108..4830564 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNull.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNull.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNumeric.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNumeric.php index 9de912b..454b368 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNumeric.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfNumeric.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfStream.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfStream.php index 7adf218..cfa2cdb 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfStream.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfStream.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -212,6 +212,28 @@ class PdfStream extends PdfType return $buffer; } + /** + * Get all filters defined for this stream. + * + * @return PdfType[] + * @throws PdfTypeException + */ + public function getFilters() + { + $filters = PdfDictionary::get($this->value, 'Filter'); + if ($filters instanceof PdfNull) { + return []; + } + + if ($filters instanceof PdfArray) { + $filters = $filters->value; + } else { + $filters = [$filters]; + } + + return $filters; + } + /** * Get the unfiltered stream data. * @@ -222,17 +244,11 @@ class PdfStream extends PdfType public function getUnfilteredStream() { $stream = $this->getStream(); - $filters = PdfDictionary::get($this->value, 'Filter'); - if ($filters instanceof PdfNull) { + $filters = $this->getFilters(); + if ($filters === []) { return $stream; } - if ($filters instanceof PdfArray) { - $filters = $filters->value; - } else { - $filters = [$filters]; - } - $decodeParams = PdfDictionary::get($this->value, 'DecodeParms'); if ($decodeParams instanceof PdfArray) { $decodeParams = $decodeParams->value; @@ -308,6 +324,21 @@ class PdfStream extends PdfType $stream = $filterObject->decode($stream); break; + case 'Crypt': + if (!$decodeParam instanceof PdfDictionary) { + break; + } + // Filter is "Identity" + $name = PdfDictionary::get($decodeParam, 'Name'); + if (!$name instanceof PdfName || $name->value !== 'Identity') { + break; + } + + throw new FilterException( + 'Support for Crypt filters other than "Identity" is not implemented.', + FilterException::UNSUPPORTED_FILTER + ); + default: throw new FilterException( \sprintf('Unsupported filter "%s".', $filter->value), diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfString.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfString.php index 1636e68..dc4ce33 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfString.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfString.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ @@ -78,6 +78,36 @@ class PdfString extends PdfType return PdfType::ensureType(self::class, $string, 'String value expected.'); } + /** + * Escapes sequences in a string according to the PDF specification. + * + * @param string $s + * @return string + */ + public static function escape($s) + { + // Still a bit faster, than direct replacing + if ( + \strpos($s, '\\') !== false || + \strpos($s, ')') !== false || + \strpos($s, '(') !== false || + \strpos($s, "\x0D") !== false || + \strpos($s, "\x0A") !== false || + \strpos($s, "\x09") !== false || + \strpos($s, "\x08") !== false || + \strpos($s, "\x0C") !== false + ) { + // is faster than strtr(...) + return \str_replace( + ['\\', ')', '(', "\x0D", "\x0A", "\x09", "\x08", "\x0C"], + ['\\\\', '\\)', '\\(', '\r', '\n', '\t', '\b', '\f'], + $s + ); + } + + return $s; + } + /** * Unescapes escaped sequences in a PDF string according to the PDF specification. * diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfToken.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfToken.php index 012b9fd..8293c28 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfToken.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfToken.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfType.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfType.php index 7672dcd..065ad38 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfType.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfType.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfTypeException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfTypeException.php index 593d147..88d2c20 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfTypeException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfParser/Type/PdfTypeException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/DataStructure/Rectangle.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/DataStructure/Rectangle.php index 9b19ff8..afbe569 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/DataStructure/Rectangle.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/DataStructure/Rectangle.php @@ -4,12 +4,13 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ namespace setasign\Fpdi\PdfReader\DataStructure; +use setasign\Fpdi\Math\Vector; use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException; use setasign\Fpdi\PdfParser\PdfParser; use setasign\Fpdi\PdfParser\PdfParserException; @@ -64,6 +65,11 @@ class Rectangle return new self($ax, $ay, $bx, $by); } + public static function byVectors(Vector $ll, Vector $ur) + { + return new self($ll->getX(), $ll->getY(), $ur->getX(), $ur->getY()); + } + /** * Rectangle constructor. * diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/Page.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/Page.php index b207c79..8d08c95 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/Page.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/Page.php @@ -4,21 +4,26 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ namespace setasign\Fpdi\PdfReader; +use setasign\Fpdi\GraphicsState; +use setasign\Fpdi\Math\Vector; use setasign\Fpdi\PdfParser\Filter\FilterException; use setasign\Fpdi\PdfParser\PdfParser; use setasign\Fpdi\PdfParser\PdfParserException; use setasign\Fpdi\PdfParser\Type\PdfArray; use setasign\Fpdi\PdfParser\Type\PdfDictionary; +use setasign\Fpdi\PdfParser\Type\PdfHexString; use setasign\Fpdi\PdfParser\Type\PdfIndirectObject; +use setasign\Fpdi\PdfParser\Type\PdfName; use setasign\Fpdi\PdfParser\Type\PdfNull; use setasign\Fpdi\PdfParser\Type\PdfNumeric; use setasign\Fpdi\PdfParser\Type\PdfStream; +use setasign\Fpdi\PdfParser\Type\PdfString; use setasign\Fpdi\PdfParser\Type\PdfType; use setasign\Fpdi\PdfParser\Type\PdfTypeException; use setasign\Fpdi\PdfReader\DataStructure\Rectangle; @@ -83,7 +88,7 @@ class Page */ public function getPageDictionary() { - if (null === $this->pageDictionary) { + if ($this->pageDictionary === null) { $this->pageDictionary = PdfDictionary::ensure(PdfType::resolve($this->getPageObject(), $this->parser)); } @@ -155,7 +160,7 @@ class Page public function getRotation() { $rotation = $this->getAttribute('Rotate'); - if (null === $rotation) { + if ($rotation === null) { return 0; } @@ -268,4 +273,119 @@ class Page PdfReaderException::UNEXPECTED_DATA_TYPE ); } + + /** + * Get information of all external links on this page. + * + * All coordinates are normalized in view to rotation and translation of the boundary-box, so that their + * origin is lower-left. + * + * @return array + * @throws CrossReferenceException + * @throws PdfParserException + * @throws PdfTypeException + */ + public function getExternalLinks($box = PageBoundaries::CROP_BOX) + { + $dict = $this->getPageDictionary(); + $annotations = PdfType::resolve(PdfDictionary::get($dict, 'Annots'), $this->parser); + + if (!$annotations instanceof PdfArray) { + return []; + } + + $links = []; + + foreach ($annotations->value as $entry) { + $annotation = PdfType::resolve($entry, $this->parser); + + $value = PdfType::resolve(PdfDictionary::get($annotation, 'Subtype'), $this->parser); + if (!$value instanceof PdfName || $value->value !== 'Link') { + continue; + } + + $dest = PdfType::resolve(PdfDictionary::get($annotation, 'Dest'), $this->parser); + if (!$dest instanceof PdfNull) { + continue; + } + + $action = PdfType::resolve(PdfDictionary::get($annotation, 'A'), $this->parser); + if (!$action instanceof PdfDictionary) { + continue; + } + + $actionType = PdfType::resolve(PdfDictionary::get($action, 'S'), $this->parser); + if (!$actionType instanceof PdfName || $actionType->value !== 'URI') { + continue; + } + + $uri = PdfType::resolve(PdfDictionary::get($action, 'URI'), $this->parser); + if ($uri instanceof PdfString) { + $uriValue = PdfString::unescape($uri->value); + } elseif ($uri instanceof PdfHexString) { + $uriValue = \hex2bin($uri->value); + } else { + continue; + } + + $rect = PdfType::resolve(PdfDictionary::get($annotation, 'Rect'), $this->parser); + if (!$rect instanceof PdfArray || count($rect->value) !== 4) { + continue; + } + + $rect = Rectangle::byPdfArray($rect, $this->parser); + if ($rect->getWidth() === 0 || $rect->getHeight() === 0) { + continue; + } + + $bbox = $this->getBoundary($box); + $rotation = $this->getRotation(); + + $gs = new GraphicsState(); + $gs->translate(-$bbox->getLlx(), -$bbox->getLly()); + $gs->rotate($bbox->getLlx(), $bbox->getLly(), -$rotation); + + switch ($rotation) { + case 90: + $gs->translate(-$bbox->getWidth(), 0); + break; + case 180: + $gs->translate(-$bbox->getWidth(), -$bbox->getHeight()); + break; + case 270: + $gs->translate(0, -$bbox->getHeight()); + break; + } + + $normalizedRect = Rectangle::byVectors( + $gs->toUserSpace(new Vector($rect->getLlx(), $rect->getLly())), + $gs->toUserSpace(new Vector($rect->getUrx(), $rect->getUry())) + ); + + $quadPoints = PdfType::resolve(PdfDictionary::get($annotation, 'QuadPoints'), $this->parser); + $normalizedQuadPoints = []; + if ($quadPoints instanceof PdfArray) { + $quadPointsCount = count($quadPoints->value); + if ($quadPointsCount % 8 === 0) { + for ($i = 0; ($i + 1) < $quadPointsCount; $i += 2) { + $x = PdfNumeric::ensure(PdfType::resolve($quadPoints->value[$i], $this->parser)); + $y = PdfNumeric::ensure(PdfType::resolve($quadPoints->value[$i + 1], $this->parser)); + + $v = $gs->toUserSpace(new Vector($x->value, $y->value)); + $normalizedQuadPoints[] = $v->getX(); + $normalizedQuadPoints[] = $v->getY(); + } + } + } + + $links[] = [ + 'rect' => $normalizedRect, + 'quadPoints' => $normalizedQuadPoints, + 'uri' => $uriValue, + 'pdfObject' => $annotation + ]; + } + + return $links; + } } diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PageBoundaries.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PageBoundaries.php index 9a6a1f3..ec24cde 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PageBoundaries.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PageBoundaries.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReader.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReader.php index e31b110..6e4dae8 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReader.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReader.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReaderException.php b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReaderException.php index 99f7d12..2b3487e 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReaderException.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/PdfReader/PdfReaderException.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/Tcpdf/Fpdi.php b/src/serverlib/3rdparty/fpdf/fpdi/src/Tcpdf/Fpdi.php index 90c11b8..f82c690 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/Tcpdf/Fpdi.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/Tcpdf/Fpdi.php @@ -4,18 +4,22 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ namespace setasign\Fpdi\Tcpdf; +use setasign\Fpdi\FpdiException; use setasign\Fpdi\FpdiTrait; use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException; use setasign\Fpdi\PdfParser\Filter\AsciiHex; use setasign\Fpdi\PdfParser\PdfParserException; +use setasign\Fpdi\PdfParser\Type\PdfArray; +use setasign\Fpdi\PdfParser\Type\PdfDictionary; use setasign\Fpdi\PdfParser\Type\PdfHexString; use setasign\Fpdi\PdfParser\Type\PdfIndirectObject; +use setasign\Fpdi\PdfParser\Type\PdfName; use setasign\Fpdi\PdfParser\Type\PdfNull; use setasign\Fpdi\PdfParser\Type\PdfNumeric; use setasign\Fpdi\PdfParser\Type\PdfStream; @@ -42,7 +46,7 @@ class Fpdi extends \TCPDF * * @string */ - const VERSION = '2.3.7'; + const VERSION = '2.5.0'; /** * A counter for template ids. @@ -146,7 +150,7 @@ class Fpdi extends \TCPDF { $out = parent::_getxobjectdict(); - foreach ($this->importedPages as $key => $pageData) { + foreach ($this->importedPages as $pageData) { $out .= '/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R '; } @@ -247,7 +251,7 @@ class Fpdi extends \TCPDF if ($value instanceof PdfString) { $string = PdfString::unescape($value->value); $string = $this->_encrypt_data($this->currentObjectNumber, $string); - $value->value = \TCPDF_STATIC::_escape($string); + $value->value = PdfString::escape($string); } elseif ($value instanceof PdfHexString) { $filter = new AsciiHex(); $string = $filter->decode($value->value); @@ -268,4 +272,133 @@ class Fpdi extends \TCPDF $this->fpdiWritePdfType($value); } + + /** + * This method will add additional data to the last created link/annotation. + * + * It will copy styling properties (supported by TCPDF) of the imported link. + * + * @param array $externalLink + * @param float|int $xPt + * @param float|int $scaleX + * @param float|int $yPt + * @param float|int $newHeightPt + * @param float|int $scaleY + * @param array $importedPage + * @return void + */ + protected function adjustLastLink($externalLink, $xPt, $scaleX, $yPt, $newHeightPt, $scaleY, $importedPage) + { + $parser = $this->getPdfReader($importedPage['readerId'])->getParser(); + + if ($this->inxobj) { + // store parameters for later use on template + $lastAnnotationKey = count($this->xobjects[$this->xobjid]['annotations']) - 1; + $lastAnnotationOpt = &$this->xobjects[$this->xobjid]['annotations'][$lastAnnotationKey]['opt']; + } else { + $lastAnnotationKey = count($this->PageAnnots[$this->page]) - 1; + $lastAnnotationOpt = &$this->PageAnnots[$this->page][$lastAnnotationKey]['opt']; + } + + // ensure we have a default value - otherwise TCPDF will set it to 4 throughout + $lastAnnotationOpt['f'] = 0; + + $values = $externalLink['pdfObject']->value; + unset( + $values['P'], + $values['NM'], + $values['AP'], + $values['AS'], + $values['Type'], + $values['Subtype'], + $values['Rect'], + $values['A'], + $values['QuadPoints'], + $values['Rotate'], + $values['M'], + $values['StructParent'] + ); + + foreach ($values as $key => $value) { + try { + switch ($key) { + case 'BS': + $value = PdfDictionary::ensure($value); + $bs = []; + if (isset($value->value['W'])) { + $bs['w'] = PdfNumeric::ensure(PdfType::resolve($value->value['W'], $parser))->value; + } + + if (isset($value->value['S'])) { + $bs['s'] = PdfName::ensure(PdfType::resolve($value->value['S'], $parser))->value; + } + + if (isset($value->value['D'])) { + $d = []; + foreach (PdfArray::ensure(PdfType::resolve($value->value['D'], $parser))->value as $item) { + $d[] = PdfNumeric::ensure(PdfType::resolve($item, $parser))->value; + } + $bs['d'] = $d; + } + + $lastAnnotationOpt['bs'] = $bs; + break; + + case 'Border': + $borderArray = PdfArray::ensure(PdfType::resolve($value, $parser))->value; + if (count($borderArray) < 3) { + continue 2; + } + + $border = [ + PdfNumeric::ensure(PdfType::resolve($borderArray[0], $parser))->value, + PdfNumeric::ensure(PdfType::resolve($borderArray[1], $parser))->value, + PdfNumeric::ensure(PdfType::resolve($borderArray[2], $parser))->value, + ]; + if (isset($borderArray[3])) { + $dashArray = []; + foreach (PdfArray::ensure(PdfType::resolve($borderArray[3], $parser))->value as $item) { + $dashArray[] = PdfNumeric::ensure(PdfType::resolve($item, $parser))->value; + } + $border[] = $dashArray; + } + + $lastAnnotationOpt['border'] = $border; + break; + + case 'C': + $c = []; + $colors = PdfArray::ensure(PdfType::resolve($value, $parser))->value; + $m = count($colors) === 4 ? 100 : 255; + foreach ($colors as $item) { + $c[] = PdfNumeric::ensure(PdfType::resolve($item, $parser))->value * $m; + } + $lastAnnotationOpt['c'] = $c; + break; + + case 'F': + $lastAnnotationOpt['f'] = $value->value; + break; + + case 'BE': + // is broken in current TCPDF version: "bc" key is checked but "bs" is used. + break; + } + // let's silence invalid/not supported values + } catch (FpdiException $e) { + continue; + } + } + + // QuadPoints are not supported by TCPDF +// if (count($externalLink['quadPoints']) > 0) { +// $quadPoints = []; +// for ($i = 0, $n = count($externalLink['quadPoints']); $i < $n; $i += 2) { +// $quadPoints[] = $xPt + $externalLink['quadPoints'][$i] * $scaleX; +// $quadPoints[] = $this->hPt - $yPt - $newHeightPt + $externalLink['quadPoints'][$i + 1] * $scaleY; +// } +// +// ????? = $quadPoints; +// } + } } diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/TcpdfFpdi.php b/src/serverlib/3rdparty/fpdf/fpdi/src/TcpdfFpdi.php index 9e6825b..8f3c095 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/TcpdfFpdi.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/TcpdfFpdi.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/FpdfTpl.php b/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/FpdfTpl.php index c00d53d..7b02bc8 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/FpdfTpl.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/FpdfTpl.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/Fpdi.php b/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/Fpdi.php index 9af3f88..473a7ae 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/Fpdi.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/Tfpdf/Fpdi.php @@ -4,17 +4,14 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */ namespace setasign\Fpdi\Tfpdf; +use setasign\Fpdi\FpdfTrait; use setasign\Fpdi\FpdiTrait; -use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException; -use setasign\Fpdi\PdfParser\PdfParserException; -use setasign\Fpdi\PdfParser\Type\PdfIndirectObject; -use setasign\Fpdi\PdfParser\Type\PdfNull; /** * Class Fpdi @@ -24,131 +21,12 @@ use setasign\Fpdi\PdfParser\Type\PdfNull; class Fpdi extends FpdfTpl { use FpdiTrait; + use FpdfTrait; /** * FPDI version * * @string */ - const VERSION = '2.3.7'; - - public function _enddoc() - { - parent::_enddoc(); - $this->cleanUp(); - } - - /** - * Draws an imported page or a template onto the page or another template. - * - * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the - * aspect ratio. - * - * @param mixed $tpl The template id - * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array - * with the keys "x", "y", "width", "height", "adjustPageSize". - * @param float|int $y The ordinate of upper-left corner. - * @param float|int|null $width The width. - * @param float|int|null $height The height. - * @param bool $adjustPageSize - * @return array The size - * @see Fpdi::getTemplateSize() - */ - public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) - { - if (isset($this->importedPages[$tpl])) { - $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); - if ($this->currentTemplateId !== null) { - $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl; - } - return $size; - } - - return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize); - } - - /** - * Get the size of an imported page or template. - * - * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the - * aspect ratio. - * - * @param mixed $tpl The template id - * @param float|int|null $width The width. - * @param float|int|null $height The height. - * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) - */ - public function getTemplateSize($tpl, $width = null, $height = null) - { - $size = parent::getTemplateSize($tpl, $width, $height); - if ($size === false) { - return $this->getImportedPageSize($tpl, $width, $height); - } - - return $size; - } - - /** - * @inheritdoc - * @throws CrossReferenceException - * @throws PdfParserException - */ - public function _putimages() - { - $this->currentReaderId = null; - parent::_putimages(); - - foreach ($this->importedPages as $key => $pageData) { - $this->_newobj(); - $this->importedPages[$key]['objectNumber'] = $this->n; - $this->currentReaderId = $pageData['readerId']; - $this->writePdfType($pageData['stream']); - $this->_put('endobj'); - } - - foreach (\array_keys($this->readers) as $readerId) { - $parser = $this->getPdfReader($readerId)->getParser(); - $this->currentReaderId = $readerId; - - while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { - try { - $object = $parser->getIndirectObject($objectNumber); - } catch (CrossReferenceException $e) { - if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { - $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); - } else { - throw $e; - } - } - - $this->writePdfType($object); - } - } - - $this->currentReaderId = null; - } - - /** - * @inheritdoc - */ - protected function _putxobjectdict() - { - foreach ($this->importedPages as $key => $pageData) { - $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); - } - - parent::_putxobjectdict(); - } - - /** - * @inheritdoc - */ - protected function _put($s, $newLine = true) - { - if ($newLine) { - $this->buffer .= $s . "\n"; - } else { - $this->buffer .= $s; - } - } + const VERSION = '2.5.0'; } diff --git a/src/serverlib/3rdparty/fpdf/fpdi/src/autoload.php b/src/serverlib/3rdparty/fpdf/fpdi/src/autoload.php index 4c3df9d..7ea6b05 100755 --- a/src/serverlib/3rdparty/fpdf/fpdi/src/autoload.php +++ b/src/serverlib/3rdparty/fpdf/fpdi/src/autoload.php @@ -4,7 +4,7 @@ * This file is part of FPDI * * @package setasign\Fpdi - * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @copyright Copyright (c) 2023 Setasign GmbH & Co. KG (https://www.setasign.com) * @license http://opensource.org/licenses/mit-license The MIT License */