[opencourrier-Commits] r1119 - in branches/5.1.0/app: . fpdi-1.6.2 fpdi-1.6.2/filters

13 views
Skip to first unread message

fray...@hephaestos.ovh.adullact.org

unread,
Jun 12, 2020, 4:18:32 PM6/12/20
to openmairie-...@googlegroups.com
Author: fraynaud
Date: 2020-06-12 22:18:30 +0200 (Fri, 12 Jun 2020)
New Revision: 1119

Added:
branches/5.1.0/app/fpdi-1.6.2/
branches/5.1.0/app/fpdi-1.6.2/LICENSE
branches/5.1.0/app/fpdi-1.6.2/composer.json
branches/5.1.0/app/fpdi-1.6.2/filters/
branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCII85.php
branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCIIHexDecode.php
branches/5.1.0/app/fpdi-1.6.2/filters/FilterLZW.php
branches/5.1.0/app/fpdi-1.6.2/fpdf_tpl.php
branches/5.1.0/app/fpdi-1.6.2/fpdi.php
branches/5.1.0/app/fpdi-1.6.2/fpdi_bridge.php
branches/5.1.0/app/fpdi-1.6.2/fpdi_pdf_parser.php
branches/5.1.0/app/fpdi-1.6.2/pdf_context.php
branches/5.1.0/app/fpdi-1.6.2/pdf_parser.php
Removed:
branches/5.1.0/app/fpdf/
branches/5.1.0/app/pdf/
Log:

mise en place de la 1.6.2 fpdi pour cachet courrier



Added: branches/5.1.0/app/fpdi-1.6.2/LICENSE
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/LICENSE (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/LICENSE 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Setasign - Jan Slabon, 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
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/composer.json
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/composer.json (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/composer.json 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,30 @@
+{
+ "name": "setasign/fpdi",
+ "version": "1.6.2",
+ "homepage": "https://www.setasign.com/fpdi",
+ "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.",
+ "type": "library",
+ "keywords": ["pdf", "fpdi", "fpdf"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Jan Slabon",
+ "email": "jan.s...@setasign.com",
+ "homepage": "https://www.setasign.com"
+ }
+ ],
+ "autoload": {
+ "classmap": [
+ "filters/",
+ "fpdi.php",
+ "fpdf_tpl.php",
+ "fpdi_pdf_parser.php",
+ "pdf_context.php"
+ ]
+ },
+ "suggest": {
+ "setasign/fpdf": "FPDI will extend this class but as it is also possible to use \"tecnickcom/tcpdf\" as an alternative there's no fixed dependency configured.",
+ "setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.",
+ "setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF."
+ }
+}

Added: branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCII85.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCII85.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCII85.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,106 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+/**
+ * Class FilterASCII85
+ */
+class FilterASCII85
+{
+ /**
+ * Decode ASCII85 encoded string
+ *
+ * @param string $in
+ * @return string
+ * @throws Exception
+ */
+ public function decode($in)
+ {
+ $ord = array(
+ '~' => ord('~'),
+ 'z' => ord('z'),
+ 'u' => ord('u'),
+ '!' => ord('!')
+ );
+
+ $out = '';
+ $state = 0;
+ $chn = null;
+
+ $l = strlen($in);
+
+ for ($k = 0; $k < $l; ++$k) {
+ $ch = ord($in[$k]) & 0xff;
+
+ if ($ch == $ord['~']) {
+ break;
+ }
+ if (preg_match('/^\s$/',chr($ch))) {
+ continue;
+ }
+ if ($ch == $ord['z'] && $state == 0) {
+ $out .= chr(0) . chr(0) . chr(0) . chr(0);
+ continue;
+ }
+ if ($ch < $ord['!'] || $ch > $ord['u']) {
+ throw new Exception('Illegal character in ASCII85Decode.');
+ }
+
+ $chn[$state++] = $ch - $ord['!'];
+
+ if ($state == 5) {
+ $state = 0;
+ $r = 0;
+ for ($j = 0; $j < 5; ++$j) {
+ $r = (int)($r * 85 + $chn[$j]);
+ }
+
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ $out .= chr($r >> 8);
+ $out .= chr($r);
+ }
+ }
+ $r = 0;
+
+ if ($state == 1) {
+ throw new Exception('Illegal length in ASCII85Decode.');
+ }
+
+ if ($state == 2) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85;
+ $out .= chr($r >> 24);
+
+ } else if ($state == 3) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85;
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+
+ } else if ($state == 4) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ;
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ $out .= chr($r >> 8);
+ }
+
+ return $out;
+ }
+
+ /**
+ * NOT IMPLEMENTED
+ *
+ * @param string $in
+ * @return string
+ * @throws LogicException
+ */
+ public function encode($in)
+ {
+ throw new LogicException("ASCII85 encoding not implemented.");
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCIIHexDecode.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCIIHexDecode.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/filters/FilterASCIIHexDecode.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,43 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+/**
+ * Class FilterASCIIHexDecode
+ */
+class FilterASCIIHexDecode
+{
+ /**
+ * Converts an ASCII hexadecimal encoded string into it's binary representation.
+ *
+ * @param string $data The input string
+ * @return string
+ */
+ public function decode($data)
+ {
+ $data = preg_replace('/[^0-9A-Fa-f]/', '', rtrim($data, '>'));
+ if ((strlen($data) % 2) == 1) {
+ $data .= '0';
+ }
+
+ return pack('H*', $data);
+ }
+
+ /**
+ * Converts a string into ASCII hexadecimal representation.
+ *
+ * @param string $data The input string
+ * @param boolean $leaveEOD
+ * @return string
+ */
+ public function encode($data, $leaveEOD = false)
+ {
+ return current(unpack('H*', $data)) . ($leaveEOD ? '' : '>');
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/filters/FilterLZW.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/filters/FilterLZW.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/filters/FilterLZW.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,164 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+/**
+ * Class FilterLZW
+ */
+class FilterLZW
+{
+ protected $_sTable = array();
+ protected $_data = null;
+ protected $_dataLength = 0;
+ protected $_tIdx;
+ protected $_bitsToGet = 9;
+ protected $_bytePointer;
+ protected $_bitPointer;
+ protected $_nextData = 0;
+ protected $_nextBits = 0;
+ protected $_andTable = array(511, 1023, 2047, 4095);
+
+ /**
+ * Decodes LZW compressed data.
+ *
+ * @param string $data The compressed data.
+ * @throws Exception
+ * @return string
+ */
+ public function decode($data)
+ {
+ if ($data[0] == 0x00 && $data[1] == 0x01) {
+ throw new Exception('LZW flavour not supported.');
+ }
+
+ $this->_initsTable();
+
+ $this->_data = $data;
+ $this->_dataLength = strlen($data);
+
+ // Initialize pointers
+ $this->_bytePointer = 0;
+ $this->_bitPointer = 0;
+
+ $this->_nextData = 0;
+ $this->_nextBits = 0;
+
+ $oldCode = 0;
+
+ $unCompData = '';
+
+ while (($code = $this->_getNextCode()) != 257) {
+ if ($code == 256) {
+ $this->_initsTable();
+ $code = $this->_getNextCode();
+
+ if ($code == 257) {
+ break;
+ }
+
+ if (!isset($this->_sTable[$code])) {
+ throw new Exception('Error while decompression LZW compressed data.');
+ }
+
+ $unCompData .= $this->_sTable[$code];
+ $oldCode = $code;
+
+ } else {
+
+ if ($code < $this->_tIdx) {
+ $string = $this->_sTable[$code];
+ $unCompData .= $string;
+
+ $this->_addStringToTable($this->_sTable[$oldCode], $string[0]);
+ $oldCode = $code;
+ } else {
+ $string = $this->_sTable[$oldCode];
+ $string = $string . $string[0];
+ $unCompData .= $string;
+
+ $this->_addStringToTable($string);
+ $oldCode = $code;
+ }
+ }
+ }
+
+ return $unCompData;
+ }
+
+
+ /**
+ * Initialize the string table.
+ */
+ protected function _initsTable()
+ {
+ $this->_sTable = array();
+
+ for ($i = 0; $i < 256; $i++)
+ $this->_sTable[$i] = chr($i);
+
+ $this->_tIdx = 258;
+ $this->_bitsToGet = 9;
+ }
+
+ /**
+ * Add a new string to the string table.
+ */
+ protected function _addStringToTable($oldString, $newString = '')
+ {
+ $string = $oldString . $newString;
+
+ // Add this new String to the table
+ $this->_sTable[$this->_tIdx++] = $string;
+
+ if ($this->_tIdx == 511) {
+ $this->_bitsToGet = 10;
+ } else if ($this->_tIdx == 1023) {
+ $this->_bitsToGet = 11;
+ } else if ($this->_tIdx == 2047) {
+ $this->_bitsToGet = 12;
+ }
+ }
+
+ /**
+ * Returns the next 9, 10, 11 or 12 bits
+ *
+ * @return int
+ */
+ protected function _getNextCode()
+ {
+ if ($this->_bytePointer == $this->_dataLength) {
+ return 257;
+ }
+
+ $this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff);
+ $this->_nextBits += 8;
+
+ if ($this->_nextBits < $this->_bitsToGet) {
+ $this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff);
+ $this->_nextBits += 8;
+ }
+
+ $code = ($this->_nextData >> ($this->_nextBits - $this->_bitsToGet)) & $this->_andTable[$this->_bitsToGet-9];
+ $this->_nextBits -= $this->_bitsToGet;
+
+ return $code;
+ }
+
+ /**
+ * NOT IMPLEMENTED
+ *
+ * @param string $in
+ * @return string
+ * @throws LogicException
+ */
+ public function encode($in)
+ {
+ throw new LogicException("LZW encoding not implemented.");
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/fpdf_tpl.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/fpdf_tpl.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/fpdf_tpl.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,548 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+if (!class_exists('fpdi_bridge')) {
+ require_once('fpdi_bridge.php');
+}
+
+/**
+ * Class FPDF_TPL
+ */
+class FPDF_TPL extends fpdi_bridge
+{
+ /**
+ * Array of template data
+ *
+ * @var array
+ */
+ protected $_tpls = array();
+
+ /**
+ * Current Template-Id
+ *
+ * @var int
+ */
+ public $tpl = 0;
+
+ /**
+ * "In Template"-Flag
+ *
+ * @var boolean
+ */
+ protected $_inTpl = false;
+
+ /**
+ * Name prefix of templates used in Resources dictionary
+ *
+ * @var string A String defining the Prefix used as Template-Object-Names. Have to begin with an /
+ */
+ public $tplPrefix = "/TPL";
+
+ /**
+ * Resources used by templates and pages
+ *
+ * @var array
+ */
+ protected $_res = array();
+
+ /**
+ * Last used template data
+ *
+ * @var array
+ */
+ public $lastUsedTemplateData = array();
+
+ /**
+ * Start a template.
+ *
+ * This method starts a template. You can give own coordinates to build an own sized
+ * template. Pay attention, that the margins are adapted to the new template size.
+ * If you want to write outside the template, for example to build a clipped template,
+ * you have to set the margins and "cursor"-position manual after beginTemplate()-call.
+ *
+ * If no parameter is given, the template uses the current page-size.
+ * The method returns an id of the current template. This id is used later for using this template.
+ * Warning: A created template is saved in the resulting PDF at all events. Also if you don't use it after creation!
+ *
+ * @param int $x The x-coordinate given in user-unit
+ * @param int $y The y-coordinate given in user-unit
+ * @param int $w The width given in user-unit
+ * @param int $h The height given in user-unit
+ * @return int The id of new created template
+ * @throws LogicException
+ */
+ public function beginTemplate($x = null, $y = null, $w = null, $h = null)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ throw new LogicException('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.');
+ }
+
+ if ($this->page <= 0) {
+ throw new LogicException("You have to add at least a page first!");
+ }
+
+ if ($x == null)
+ $x = 0;
+ if ($y == null)
+ $y = 0;
+ if ($w == null)
+ $w = $this->w;
+ if ($h == null)
+ $h = $this->h;
+
+ // Save settings
+ $this->tpl++;
+ $tpl =& $this->_tpls[$this->tpl];
+ $tpl = array(
+ 'o_x' => $this->x,
+ 'o_y' => $this->y,
+ 'o_AutoPageBreak' => $this->AutoPageBreak,
+ 'o_bMargin' => $this->bMargin,
+ 'o_tMargin' => $this->tMargin,
+ 'o_lMargin' => $this->lMargin,
+ 'o_rMargin' => $this->rMargin,
+ 'o_h' => $this->h,
+ 'o_w' => $this->w,
+ 'o_FontFamily' => $this->FontFamily,
+ 'o_FontStyle' => $this->FontStyle,
+ 'o_FontSizePt' => $this->FontSizePt,
+ 'o_FontSize' => $this->FontSize,
+ 'buffer' => '',
+ 'x' => $x,
+ 'y' => $y,
+ 'w' => $w,
+ 'h' => $h
+ );
+
+ $this->SetAutoPageBreak(false);
+
+ // Define own high and width to calculate correct positions
+ $this->h = $h;
+ $this->w = $w;
+
+ $this->_inTpl = true;
+ $this->SetXY($x + $this->lMargin, $y + $this->tMargin);
+ $this->SetRightMargin($this->w - $w + $this->rMargin);
+
+ if ($this->CurrentFont) {
+ $fontKey = $this->FontFamily . $this->FontStyle;
+ if ($fontKey) {
+ $this->_res['tpl'][$this->tpl]['fonts'][$fontKey] =& $this->fonts[$fontKey];
+ $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
+ }
+ }
+
+ return $this->tpl;
+ }
+
+ /**
+ * End template.
+ *
+ * This method ends a template and reset initiated variables collected in {@link beginTemplate()}.
+ *
+ * @return int|boolean If a template is opened, the id is returned. If not a false is returned.
+ */
+ public function endTemplate()
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args);
+ }
+
+ if ($this->_inTpl) {
+ $this->_inTpl = false;
+ $tpl = $this->_tpls[$this->tpl];
+ $this->SetXY($tpl['o_x'], $tpl['o_y']);
+ $this->tMargin = $tpl['o_tMargin'];
+ $this->lMargin = $tpl['o_lMargin'];
+ $this->rMargin = $tpl['o_rMargin'];
+ $this->h = $tpl['o_h'];
+ $this->w = $tpl['o_w'];
+ $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
+
+ $this->FontFamily = $tpl['o_FontFamily'];
+ $this->FontStyle = $tpl['o_FontStyle'];
+ $this->FontSizePt = $tpl['o_FontSizePt'];
+ $this->FontSize = $tpl['o_FontSize'];
+
+ $fontKey = $this->FontFamily . $this->FontStyle;
+ if ($fontKey)
+ $this->CurrentFont =& $this->fonts[$fontKey];
+
+ return $this->tpl;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Use a template in current page or other template.
+ *
+ * You can use a template in a page or in another template.
+ * You can give the used template a new size.
+ * All parameters are optional. The width or height is calculated automatically
+ * if one is given. If no parameter is given the origin size as defined in
+ * {@link beginTemplate()} method is used.
+ *
+ * The calculated or used width and height are returned as an array.
+ *
+ * @param int $tplIdx A valid template-id
+ * @param int $x The x-position
+ * @param int $y The y-position
+ * @param int $w The new width of the template
+ * @param int $h The new height of the template
+ * @return array The height and width of the template (array('w' => ..., 'h' => ...))
+ * @throws LogicException|InvalidArgumentException
+ */
+ public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0)
+ {
+ if ($this->page <= 0) {
+ throw new LogicException('You have to add at least a page first!');
+ }
+
+ if (!isset($this->_tpls[$tplIdx])) {
+ throw new InvalidArgumentException('Template does not exist!');
+ }
+
+ if ($this->_inTpl) {
+ $this->_res['tpl'][$this->tpl]['tpls'][$tplIdx] =& $this->_tpls[$tplIdx];
+ }
+
+ $tpl = $this->_tpls[$tplIdx];
+ $_w = $tpl['w'];
+ $_h = $tpl['h'];
+
+ if ($x == null) {
+ $x = 0;
+ }
+
+ if ($y == null) {
+ $y = 0;
+ }
+
+ $x += $tpl['x'];
+ $y += $tpl['y'];
+
+ $wh = $this->getTemplateSize($tplIdx, $w, $h);
+ $w = $wh['w'];
+ $h = $wh['h'];
+
+ $tplData = array(
+ 'x' => $this->x,
+ 'y' => $this->y,
+ 'w' => $w,
+ 'h' => $h,
+ 'scaleX' => ($w / $_w),
+ 'scaleY' => ($h / $_h),
+ 'tx' => $x,
+ 'ty' => ($this->h - $y - $h),
+ 'lty' => ($this->h - $y - $h) - ($this->h - $_h) * ($h / $_h)
+ );
+
+ $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm',
+ $tplData['scaleX'], $tplData['scaleY'], $tplData['tx'] * $this->k, $tplData['ty'] * $this->k)
+ ); // Translate
+ $this->_out(sprintf('%s%d Do Q', $this->tplPrefix, $tplIdx));
+
+ $this->lastUsedTemplateData = $tplData;
+
+ return array('w' => $w, 'h' => $h);
+ }
+
+ /**
+ * Get the calculated size of a template.
+ *
+ * If one size is given, this method calculates the other one.
+ *
+ * @param int $tplIdx A valid template-id
+ * @param int $w The width of the template
+ * @param int $h The height of the template
+ * @return array The height and width of the template (array('w' => ..., 'h' => ...))
+ */
+ public function getTemplateSize($tplIdx, $w = 0, $h = 0)
+ {
+ if (!isset($this->_tpls[$tplIdx]))
+ return false;
+
+ $tpl = $this->_tpls[$tplIdx];
+ $_w = $tpl['w'];
+ $_h = $tpl['h'];
+
+ if ($w == 0 && $h == 0) {
+ $w = $_w;
+ $h = $_h;
+ }
+
+ if ($w == 0)
+ $w = $h * $_w / $_h;
+ if($h == 0)
+ $h = $w * $_h / $_w;
+
+ return array("w" => $w, "h" => $h);
+ }
+
+ /**
+ * Sets the font used to print character strings.
+ *
+ * See FPDF/TCPDF documentation.
+ *
+ * @see http://fpdf.org/en/doc/setfont.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045
+ */
+ public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::SetFont'), $args);
+ }
+
+ parent::SetFont($family, $style, $size);
+
+ $fontkey = $this->FontFamily . $this->FontStyle;
+
+ if ($this->_inTpl) {
+ $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];
+ } else {
+ $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];
+ }
+ }
+
+ /**
+ * Puts an image.
+ *
+ * See FPDF/TCPDF documentation.
+ *
+ * @see http://fpdf.org/en/doc/image.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a714c2bee7d6b39d4d6d304540c761352
+ */
+ public function Image(
+ $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false,
+ $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false,
+ $hidden = false, $fitonpage = false, $alt = false, $altimgs = array()
+ )
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::Image'), $args);
+ }
+
+ $ret = parent::Image($file, $x, $y, $w, $h, $type, $link);
+ if ($this->_inTpl) {
+ $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];
+ } else {
+ $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Adds a new page to the document.
+ *
+ * See FPDF/TCPDF documentation.
+ *
+ * This method cannot be used if you'd started a template.
+ *
+ * @see http://fpdf.org/en/doc/addpage.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced
+ */
+ public function AddPage($orientation = '', $format = '', $rotationOrKeepmargins = false, $tocpage = false)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::AddPage'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Adding pages in templates is not possible!');
+ }
+
+ parent::AddPage($orientation, $format, $rotationOrKeepmargins);
+ }
+
+ /**
+ * Puts a link on a rectangular area of the page.
+ *
+ * Overwritten because adding links in a template will not work.
+ *
+ * @see http://fpdf.org/en/doc/link.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ab87bf1826384fbfe30eb499d42f1d994
+ */
+ public function Link($x, $y, $w, $h, $link, $spaces = 0)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::Link'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Using links in templates is not posible!');
+ }
+
+ parent::Link($x, $y, $w, $h, $link);
+ }
+
+ /**
+ * Creates a new internal link and returns its identifier.
+ *
+ * Overwritten because adding links in a template will not work.
+ *
+ * @see http://fpdf.org/en/doc/addlink.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a749522038ed7786c3e1701435dcb891e
+ */
+ public function AddLink()
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::AddLink'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Adding links in templates is not possible!');
+ }
+
+ return parent::AddLink();
+ }
+
+ /**
+ * Defines the page and position a link points to.
+ *
+ * Overwritten because adding links in a template will not work.
+ *
+ * @see http://fpdf.org/en/doc/setlink.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ace5be60e7857953ea5e2b89cb90df0ae
+ */
+ public function SetLink($link, $y = 0, $page = -1)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::SetLink'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Setting links in templates is not possible!');
+ }
+
+ parent::SetLink($link, $y, $page);
+ }
+
+ /**
+ * Writes the form XObjects to the PDF document.
+ */
+ protected function _putformxobjects()
+ {
+ $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
+ reset($this->_tpls);
+
+ foreach($this->_tpls AS $tplIdx => $tpl) {
+ $this->_newobj();
+ $this->_tpls[$tplIdx]['n'] = $this->n;
+ $this->_out('<<'.$filter.'/Type /XObject');
+ $this->_out('/Subtype /Form');
+ $this->_out('/FormType 1');
+ $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
+ // llx
+ $tpl['x'] * $this->k,
+ // lly
+ -$tpl['y'] * $this->k,
+ // urx
+ ($tpl['w'] + $tpl['x']) * $this->k,
+ // ury
+ ($tpl['h'] - $tpl['y']) * $this->k
+ ));
+
+ if ($tpl['x'] != 0 || $tpl['y'] != 0) {
+ $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',
+ -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2
+ ));
+ }
+
+ $this->_out('/Resources ');
+ $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
+
+ if (isset($this->_res['tpl'][$tplIdx])) {
+ $res = $this->_res['tpl'][$tplIdx];
+ if (isset($res['fonts']) && count($res['fonts'])) {
+ $this->_out('/Font <<');
+
+ foreach($res['fonts'] as $font) {
+ $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
+ }
+
+ $this->_out('>>');
+ }
+
+ if(isset($res['images']) || isset($res['tpls'])) {
+ $this->_out('/XObject <<');
+
+ if (isset($res['images'])) {
+ foreach($res['images'] as $image)
+ $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
+ }
+
+ if (isset($res['tpls'])) {
+ foreach($res['tpls'] as $i => $_tpl)
+ $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
+ }
+
+ $this->_out('>>');
+ }
+ }
+
+ $this->_out('>>');
+
+ $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
+ $this->_out('/Length ' . strlen($buffer) . ' >>');
+ $this->_putstream($buffer);
+ $this->_out('endobj');
+ }
+ }
+
+ /**
+ * Output images.
+ *
+ * Overwritten to add {@link _putformxobjects()} after _putimages().
+ */
+ public function _putimages()
+ {
+ parent::_putimages();
+ $this->_putformxobjects();
+ }
+
+ /**
+ * Writes the references of XObject resources to the document.
+ *
+ * Overwritten to add the the templates to the XObject resource dictionary.
+ */
+ public function _putxobjectdict()
+ {
+ parent::_putxobjectdict();
+
+ foreach($this->_tpls as $tplIdx => $tpl) {
+ $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']));
+ }
+ }
+
+ /**
+ * Writes bytes to the resulting document.
+ *
+ * Overwritten to delegate the data to the template buffer.
+ *
+ * @param string $s
+ */
+ public function _out($s)
+ {
+ if ($this->state == 2 && $this->_inTpl) {
+ $this->_tpls[$this->tpl]['buffer'] .= $s . "\n";
+ } else {
+ parent::_out($s);
+ }
+ }
+}

Added: branches/5.1.0/app/fpdi-1.6.2/fpdi.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/fpdi.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/fpdi.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,705 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+if (!class_exists('FPDF_TPL')) {
+ require_once('fpdf_tpl.php');
+}
+
+/**
+ * Class FPDI
+ */
+class FPDI extends FPDF_TPL
+{
+ /**
+ * FPDI version
+ *
+ * @string
+ */
+ const VERSION = '1.6.2';
+
+ /**
+ * Actual filename
+ *
+ * @var string
+ */
+ public $currentFilename;
+
+ /**
+ * Parser-Objects
+ *
+ * @var fpdi_pdf_parser[]
+ */
+ public $parsers = array();
+
+ /**
+ * Current parser
+ *
+ * @var fpdi_pdf_parser
+ */
+ public $currentParser;
+
+ /**
+ * The name of the last imported page box
+ *
+ * @var string
+ */
+ public $lastUsedPageBox;
+
+ /**
+ * Object stack
+ *
+ * @var array
+ */
+ protected $_objStack;
+
+ /**
+ * Done object stack
+ *
+ * @var array
+ */
+ protected $_doneObjStack;
+
+ /**
+ * Current Object Id.
+ *
+ * @var integer
+ */
+ protected $_currentObjId;
+
+ /**
+ * Cache for imported pages/template ids
+ *
+ * @var array
+ */
+ protected $_importedPages = array();
+
+ /**
+ * Set a source-file.
+ *
+ * Depending on the PDF version of the used document the PDF version of the resulting document will
+ * be adjusted to the higher version.
+ *
+ * @param string $filename A valid path to the PDF document from which pages should be imported from
+ * @return int The number of pages in the document
+ * @throws Exception
+ */
+ public function setSourceFile($filename)
+ {
+ $_filename = realpath($filename);
+ if (false !== $_filename)
+ $filename = $_filename;
+
+ $currentFilename = $this->currentFilename;
+ $currentParser = $this->currentParser;
+
+ try {
+ $this->currentFilename = $filename;
+
+ if (!isset($this->parsers[$filename])) {
+ $this->parsers[$filename] = $this->_getPdfParser($filename);
+ $this->setPdfVersion(
+ max($this->getPdfVersion(), $this->parsers[$filename]->getPdfVersion())
+ );
+ }
+
+ $this->currentParser = $this->parsers[$filename];
+
+ } catch (Exception $e) {
+ unset($this->parsers[$filename]);
+ $this->currentFilename = $currentFilename;
+ $this->currentParser = $currentParser;
+ throw $e;
+ }
+
+ return $this->parsers[$filename]->getPageCount();
+ }
+
+ /**
+ * Returns a PDF parser object
+ *
+ * @param string $filename
+ * @return fpdi_pdf_parser
+ */
+ protected function _getPdfParser($filename)
+ {
+ if (!class_exists('fpdi_pdf_parser')) {
+ require_once('fpdi_pdf_parser.php');
+ }
+ return new fpdi_pdf_parser($filename);
+ }
+
+ /**
+ * Get the current PDF version.
+ *
+ * @return string
+ */
+ public function getPdfVersion()
+ {
+ return $this->PDFVersion;
+ }
+
+ /**
+ * Set the PDF version.
+ *
+ * @param string $version
+ */
+ public function setPdfVersion($version = '1.3')
+ {
+ $this->PDFVersion = sprintf('%.1F', $version);
+ }
+
+ /**
+ * Import a page.
+ *
+ * The second parameter defines the bounding box that should be used to transform the page into a
+ * form XObject.
+ *
+ * Following values are available: MediaBox, CropBox, BleedBox, TrimBox, ArtBox.
+ * If a box is not especially defined its default box will be used:
+ *
+ * <ul>
+ * <li>CropBox: Default -> MediaBox</li>
+ * <li>BleedBox: Default -> CropBox</li>
+ * <li>TrimBox: Default -> CropBox</li>
+ * <li>ArtBox: Default -> CropBox</li>
+ * </ul>
+ *
+ * It is possible to get the used page box by the {@link getLastUsedPageBox()} method.
+ *
+ * @param int $pageNo The page number
+ * @param string $boxName The boundary box to use when transforming the page into a form XObject
+ * @param boolean $groupXObject Define the form XObject as a group XObject to support transparency (if used)
+ * @return int An id of the imported page/template to use with e.g. fpdf_tpl::useTemplate()
+ * @throws LogicException|InvalidArgumentException
+ * @see getLastUsedPageBox()
+ */
+ public function importPage($pageNo, $boxName = 'CropBox', $groupXObject = true)
+ {
+ if ($this->_inTpl) {
+ throw new LogicException('Please import the desired pages before creating a new template.');
+ }
+
+ $fn = $this->currentFilename;
+ $boxName = '/' . ltrim($boxName, '/');
+
+ // check if page already imported
+ $pageKey = $fn . '-' . ((int)$pageNo) . $boxName;
+ if (isset($this->_importedPages[$pageKey])) {
+ return $this->_importedPages[$pageKey];
+ }
+
+ $parser = $this->parsers[$fn];
+ $parser->setPageNo($pageNo);
+
+ if (!in_array($boxName, $parser->availableBoxes)) {
+ throw new InvalidArgumentException(sprintf('Unknown box: %s', $boxName));
+ }
+
+ $pageBoxes = $parser->getPageBoxes($pageNo, $this->k);
+
+ /**
+ * MediaBox
+ * CropBox: Default -> MediaBox
+ * BleedBox: Default -> CropBox
+ * TrimBox: Default -> CropBox
+ * ArtBox: Default -> CropBox
+ */
+ if (!isset($pageBoxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox'))
+ $boxName = '/CropBox';
+ if (!isset($pageBoxes[$boxName]) && $boxName == '/CropBox')
+ $boxName = '/MediaBox';
+
+ if (!isset($pageBoxes[$boxName]))
+ return false;
+
+ $this->lastUsedPageBox = $boxName;
+
+ $box = $pageBoxes[$boxName];
+
+ $this->tpl++;
+ $this->_tpls[$this->tpl] = array();
+ $tpl =& $this->_tpls[$this->tpl];
+ $tpl['parser'] = $parser;
+ $tpl['resources'] = $parser->getPageResources();
+ $tpl['buffer'] = $parser->getContent();
+ $tpl['box'] = $box;
+ $tpl['groupXObject'] = $groupXObject;
+ if ($groupXObject) {
+ $this->setPdfVersion(max($this->getPdfVersion(), 1.4));
+ }
+
+ // To build an array that can be used by PDF_TPL::useTemplate()
+ $this->_tpls[$this->tpl] = array_merge($this->_tpls[$this->tpl], $box);
+
+ // An imported page will start at 0,0 all the time. Translation will be set in _putformxobjects()
+ $tpl['x'] = 0;
+ $tpl['y'] = 0;
+
+ // handle rotated pages
+ $rotation = $parser->getPageRotation($pageNo);
+ $tpl['_rotationAngle'] = 0;
+ if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) {
+ $steps = $angle / 90;
+
+ $_w = $tpl['w'];
+ $_h = $tpl['h'];
+ $tpl['w'] = $steps % 2 == 0 ? $_w : $_h;
+ $tpl['h'] = $steps % 2 == 0 ? $_h : $_w;
+
+ if ($angle < 0)
+ $angle += 360;
+
+ $tpl['_rotationAngle'] = $angle * -1;
+ }
+
+ $this->_importedPages[$pageKey] = $this->tpl;
+
+ return $this->tpl;
+ }
+
+ /**
+ * Returns the last used page boundary box.
+ *
+ * @return string The used boundary box: MediaBox, CropBox, BleedBox, TrimBox or ArtBox
+ */
+ public function getLastUsedPageBox()
+ {
+ return $this->lastUsedPageBox;
+ }
+
+ /**
+ * Use a template or imported page in current page or other template.
+ *
+ * You can use a template in a page or in another template.
+ * You can give the used template a new size. All parameters are optional.
+ * The width or height is calculated automatically if one is given. If no
+ * parameter is given the origin size as defined in beginTemplate() or of
+ * the imported page is used.
+ *
+ * The calculated or used width and height are returned as an array.
+ *
+ * @param int $tplIdx A valid template-id
+ * @param int $x The x-position
+ * @param int $y The y-position
+ * @param int $w The new width of the template
+ * @param int $h The new height of the template
+ * @param boolean $adjustPageSize If set to true the current page will be resized to fit the dimensions
+ * of the template
+ *
+ * @return array The height and width of the template (array('w' => ..., 'h' => ...))
+ * @throws LogicException|InvalidArgumentException
+ */
+ public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0, $adjustPageSize = false)
+ {
+ if ($adjustPageSize == true && is_null($x) && is_null($y)) {
+ $size = $this->getTemplateSize($tplIdx, $w, $h);
+ $orientation = $size['w'] > $size['h'] ? 'L' : 'P';
+ $size = array($size['w'], $size['h']);
+
+ if (is_subclass_of($this, 'TCPDF')) {
+ $this->setPageFormat($size, $orientation);
+ } else {
+ $size = $this->_getpagesize($size);
+
+ if($orientation != $this->CurOrientation ||
+ $size[0] != $this->CurPageSize[0] ||
+ $size[1] != $this->CurPageSize[1]
+ ) {
+ // New size or orientation
+ if ($orientation=='P') {
+ $this->w = $size[0];
+ $this->h = $size[1];
+ } else {
+ $this->w = $size[1];
+ $this->h = $size[0];
+ }
+ $this->wPt = $this->w * $this->k;
+ $this->hPt = $this->h * $this->k;
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
+ $this->CurOrientation = $orientation;
+ $this->CurPageSize = $size;
+ if (FPDF_VERSION >= 1.8) {
+ $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt);
+ } else {
+ $this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
+ }
+ }
+ }
+ }
+
+ $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values
+ $size = parent::useTemplate($tplIdx, $x, $y, $w, $h);
+ $this->_out('Q');
+
+ return $size;
+ }
+
+ /**
+ * Copy all imported objects to the resulting document.
+ */
+ protected function _putimportedobjects()
+ {
+ foreach($this->parsers AS $filename => $p) {
+ $this->currentParser = $p;
+ if (!isset($this->_objStack[$filename]) || !is_array($this->_objStack[$filename])) {
+ continue;
+ }
+ while(($n = key($this->_objStack[$filename])) !== null) {
+ try {
+ $nObj = $this->currentParser->resolveObject($this->_objStack[$filename][$n][1]);
+ } catch (Exception $e) {
+ $nObj = array(pdf_parser::TYPE_OBJECT, pdf_parser::TYPE_NULL);
+ }
+
+ $this->_newobj($this->_objStack[$filename][$n][0]);
+
+ if ($nObj[0] == pdf_parser::TYPE_STREAM) {
+ $this->_writeValue($nObj);
+ } else {
+ $this->_writeValue($nObj[1]);
+ }
+
+ $this->_out("\nendobj");
+ $this->_objStack[$filename][$n] = null; // free memory
+ unset($this->_objStack[$filename][$n]);
+ reset($this->_objStack[$filename]);
+ }
+ }
+ }
+
+ /**
+ * Writes the form XObjects to the PDF document.
+ */
+ protected function _putformxobjects()
+ {
+ $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
+ reset($this->_tpls);
+ foreach($this->_tpls AS $tplIdx => $tpl) {
+ $this->_newobj();
+ $currentN = $this->n; // TCPDF/Protection: rem current "n"
+
+ $this->_tpls[$tplIdx]['n'] = $this->n;
+ $this->_out('<<' . $filter . '/Type /XObject');
+ $this->_out('/Subtype /Form');
+ $this->_out('/FormType 1');
+
+ $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
+ (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x']) * $this->k,
+ (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y']) * $this->k,
+ (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x']) * $this->k,
+ (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h'] - $tpl['y']) * $this->k
+ ));
+
+ $c = 1;
+ $s = 0;
+ $tx = 0;
+ $ty = 0;
+
+ if (isset($tpl['box'])) {
+ $tx = -$tpl['box']['llx'];
+ $ty = -$tpl['box']['lly'];
+
+ if ($tpl['_rotationAngle'] <> 0) {
+ $angle = $tpl['_rotationAngle'] * M_PI/180;
+ $c = cos($angle);
+ $s = sin($angle);
+
+ switch($tpl['_rotationAngle']) {
+ case -90:
+ $tx = -$tpl['box']['lly'];
+ $ty = $tpl['box']['urx'];
+ break;
+ case -180:
+ $tx = $tpl['box']['urx'];
+ $ty = $tpl['box']['ury'];
+ break;
+ case -270:
+ $tx = $tpl['box']['ury'];
+ $ty = -$tpl['box']['llx'];
+ break;
+ }
+ }
+ } else if ($tpl['x'] != 0 || $tpl['y'] != 0) {
+ $tx = -$tpl['x'] * 2;
+ $ty = $tpl['y'] * 2;
+ }
+
+ $tx *= $this->k;
+ $ty *= $this->k;
+
+ if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) {
+ $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]',
+ $c, $s, -$s, $c, $tx, $ty
+ ));
+ }
+
+ $this->_out('/Resources ');
+
+ if (isset($tpl['resources'])) {
+ $this->currentParser = $tpl['parser'];
+ $this->_writeValue($tpl['resources']); // "n" will be changed
+ } else {
+
+ $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
+ if (isset($this->_res['tpl'][$tplIdx])) {
+ $res = $this->_res['tpl'][$tplIdx];
+
+ if (isset($res['fonts']) && count($res['fonts'])) {
+ $this->_out('/Font <<');
+ foreach ($res['fonts'] as $font)
+ $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
+ $this->_out('>>');
+ }
+ if (isset($res['images']) && count($res['images']) ||
+ isset($res['tpls']) && count($res['tpls']))
+ {
+ $this->_out('/XObject <<');
+ if (isset($res['images'])) {
+ foreach ($res['images'] as $image)
+ $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
+ }
+ if (isset($res['tpls'])) {
+ foreach ($res['tpls'] as $i => $_tpl)
+ $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
+ }
+ $this->_out('>>');
+ }
+ $this->_out('>>');
+ }
+ }
+
+ if (isset($tpl['groupXObject']) && $tpl['groupXObject']) {
+ $this->_out('/Group <</Type/Group/S/Transparency>>');
+ }
+
+ $newN = $this->n; // TCPDF: rem new "n"
+ $this->n = $currentN; // TCPDF: reset to current "n"
+
+ $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
+
+ if (is_subclass_of($this, 'TCPDF')) {
+ $buffer = $this->_getrawstream($buffer);
+ $this->_out('/Length ' . strlen($buffer) . ' >>');
+ $this->_out("stream\n" . $buffer . "\nendstream");
+ } else {
+ $this->_out('/Length ' . strlen($buffer) . ' >>');
+ $this->_putstream($buffer);
+ }
+ $this->_out('endobj');
+ $this->n = $newN; // TCPDF: reset to new "n"
+ }
+
+ $this->_putimportedobjects();
+ }
+
+ /**
+ * Creates and optionally write the object definition to the document.
+ *
+ * Rewritten to handle existing own defined objects
+ *
+ * @param bool $objId
+ * @param bool $onlyNewObj
+ * @return bool|int
+ */
+ public function _newobj($objId = false, $onlyNewObj = false)
+ {
+ if (!$objId) {
+ $objId = ++$this->n;
+ }
+
+ // Begin a new object
+ if (!$onlyNewObj) {
+ $this->offsets[$objId] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer);
+ $this->_out($objId . ' 0 obj');
+ $this->_currentObjId = $objId; // for later use with encryption
+ }
+
+ return $objId;
+ }
+
+ /**
+ * Writes a PDF value to the resulting document.
+ *
+ * Needed to rebuild the source document
+ *
+ * @param mixed $value A PDF-Value. Structure of values see cases in this method
+ */
+ protected function _writeValue(&$value)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ parent::_prepareValue($value);
+ }
+
+ switch ($value[0]) {
+
+ case pdf_parser::TYPE_TOKEN:
+ $this->_straightOut($value[1] . ' ');
+ break;
+ case pdf_parser::TYPE_NUMERIC:
+ case pdf_parser::TYPE_REAL:
+ if (is_float($value[1]) && $value[1] != 0) {
+ $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ');
+ } else {
+ $this->_straightOut($value[1] . ' ');
+ }
+ break;
+
+ case pdf_parser::TYPE_ARRAY:
+
+ // An array. Output the proper
+ // structure and move on.
+
+ $this->_straightOut('[');
+ for ($i = 0; $i < count($value[1]); $i++) {
+ $this->_writeValue($value[1][$i]);
+ }
+
+ $this->_out(']');
+ break;
+
+ case pdf_parser::TYPE_DICTIONARY:
+
+ // A dictionary.
+ $this->_straightOut('<<');
+
+ reset ($value[1]);
+
+ while (list($k, $v) = each($value[1])) {
+ $this->_straightOut($k . ' ');
+ $this->_writeValue($v);
+ }
+
+ $this->_straightOut('>>');
+ break;
+
+ case pdf_parser::TYPE_OBJREF:
+
+ // An indirect object reference
+ // Fill the object stack if needed
+ $cpfn =& $this->currentParser->filename;
+ if (!isset($this->_doneObjStack[$cpfn][$value[1]])) {
+ $this->_newobj(false, true);
+ $this->_objStack[$cpfn][$value[1]] = array($this->n, $value);
+ $this->_doneObjStack[$cpfn][$value[1]] = array($this->n, $value);
+ }
+ $objId = $this->_doneObjStack[$cpfn][$value[1]][0];
+
+ $this->_out($objId . ' 0 R');
+ break;
+
+ case pdf_parser::TYPE_STRING:
+
+ // A string.
+ $this->_straightOut('(' . $value[1] . ')');
+
+ break;
+
+ case pdf_parser::TYPE_STREAM:
+
+ // A stream. First, output the
+ // stream dictionary, then the
+ // stream data itself.
+ $this->_writeValue($value[1]);
+ $this->_out('stream');
+ $this->_out($value[2][1]);
+ $this->_straightOut("endstream");
+ break;
+
+ case pdf_parser::TYPE_HEX:
+ $this->_straightOut('<' . $value[1] . '>');
+ break;
+
+ case pdf_parser::TYPE_BOOLEAN:
+ $this->_straightOut($value[1] ? 'true ' : 'false ');
+ break;
+
+ case pdf_parser::TYPE_NULL:
+ // The null object.
+ $this->_straightOut('null ');
+ break;
+ }
+ }
+
+
+ /**
+ * Modified _out() method so not each call will add a newline to the output.
+ */
+ protected function _straightOut($s)
+ {
+ if (!is_subclass_of($this, 'TCPDF')) {
+ if ($this->state == 2) {
+ $this->pages[$this->page] .= $s;
+ } else {
+ $this->buffer .= $s;
+ }
+
+ } else {
+ if ($this->state == 2) {
+ if ($this->inxobj) {
+ // we are inside an XObject template
+ $this->xobjects[$this->xobjid]['outdata'] .= $s;
+ } else if ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
+ // puts data before page footer
+ $pagebuff = $this->getPageBuffer($this->page);
+ $page = substr($pagebuff, 0, -$this->footerlen[$this->page]);
+ $footer = substr($pagebuff, -$this->footerlen[$this->page]);
+ $this->setPageBuffer($this->page, $page . $s . $footer);
+ // update footer position
+ $this->footerpos[$this->page] += strlen($s);
+ } else {
+ // set page data
+ $this->setPageBuffer($this->page, $s, true);
+ }
+ } else if ($this->state > 0) {
+ // set general data
+ $this->setBuffer($s);
+ }
+ }
+ }
+
+ /**
+ * Ends the document
+ *
+ * Overwritten to close opened parsers
+ */
+ public function _enddoc()
+ {
+ parent::_enddoc();
+ $this->_closeParsers();
+ }
+
+ /**
+ * Close all files opened by parsers.
+ *
+ * @return boolean
+ */
+ protected function _closeParsers()
+ {
+ if ($this->state > 2) {
+ $this->cleanUp();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes cycled references and closes the file handles of the parser objects.
+ */
+ public function cleanUp()
+ {
+ while (($parser = array_pop($this->parsers)) !== null) {
+ /**
+ * @var fpdi_pdf_parser $parser
+ */
+ $parser->closeFile();
+ }
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/fpdi_bridge.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/fpdi_bridge.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/fpdi_bridge.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,206 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+/**
+ * This file is used as a bridge between TCPDF or FPDF
+ * It will dynamically create the class extending the available
+ * class FPDF or TCPDF.
+ *
+ * This way it is possible to use FPDI for both FPDF and TCPDF with one FPDI version.
+ */
+
+if (!class_exists('TCPDF', false)) {
+ /**
+ * Class fpdi_bridge
+ */
+ class fpdi_bridge extends FPDF
+ {
+ // empty body
+ }
+
+} else {
+
+ /**
+ * Class fpdi_bridge
+ */
+ class fpdi_bridge extends TCPDF
+ {
+ /**
+ * Array of Tpl-Data
+ *
+ * @var array
+ */
+ protected $_tpls = array();
+
+ /**
+ * Name-prefix of Templates used in Resources-Dictionary
+ *
+ * @var string A String defining the Prefix used as Template-Object-Names. Have to begin with an /
+ */
+ public $tplPrefix = "/TPL";
+
+ /**
+ * Current Object Id.
+ *
+ * @var integer
+ */
+ protected $_currentObjId;
+
+ /**
+ * Return XObjects Dictionary.
+ *
+ * Overwritten to add additional XObjects to the resources dictionary of TCPDF
+ *
+ * @return string
+ */
+ protected function _getxobjectdict()
+ {
+ $out = parent::_getxobjectdict();
+ foreach ($this->_tpls as $tplIdx => $tpl) {
+ $out .= sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']);
+ }
+
+ return $out;
+ }
+
+ /**
+ * Writes a PDF value to the resulting document.
+ *
+ * Prepares the value for encryption of imported data by FPDI
+ *
+ * @param array $value
+ */
+ protected function _prepareValue(&$value)
+ {
+ switch ($value[0]) {
+ case pdf_parser::TYPE_STRING:
+ if ($this->encrypted) {
+ $value[1] = $this->_unescape($value[1]);
+ $value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]);
+ $value[1] = TCPDF_STATIC::_escape($value[1]);
+ }
+ break;
+
+ case pdf_parser::TYPE_STREAM:
+ if ($this->encrypted) {
+ $value[2][1] = $this->_encrypt_data($this->_currentObjId, $value[2][1]);
+ $value[1][1]['/Length'] = array(
+ pdf_parser::TYPE_NUMERIC,
+ strlen($value[2][1])
+ );
+ }
+ break;
+
+ case pdf_parser::TYPE_HEX:
+ if ($this->encrypted) {
+ $value[1] = $this->hex2str($value[1]);
+ $value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]);
+
+ // remake hexstring of encrypted string
+ $value[1] = $this->str2hex($value[1]);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Un-escapes a PDF string
+ *
+ * @param string $s
+ * @return string
+ */
+ protected function _unescape($s)
+ {
+ $out = '';
+ for ($count = 0, $n = strlen($s); $count < $n; $count++) {
+ if ($s[$count] != '\\' || $count == $n-1) {
+ $out .= $s[$count];
+ } else {
+ switch ($s[++$count]) {
+ case ')':
+ case '(':
+ case '\\':
+ $out .= $s[$count];
+ break;
+ case 'f':
+ $out .= chr(0x0C);
+ break;
+ case 'b':
+ $out .= chr(0x08);
+ break;
+ case 't':
+ $out .= chr(0x09);
+ break;
+ case 'r':
+ $out .= chr(0x0D);
+ break;
+ case 'n':
+ $out .= chr(0x0A);
+ break;
+ case "\r":
+ if ($count != $n-1 && $s[$count+1] == "\n")
+ $count++;
+ break;
+ case "\n":
+ break;
+ default:
+ // Octal-Values
+ if (ord($s[$count]) >= ord('0') &&
+ ord($s[$count]) <= ord('9')) {
+ $oct = ''. $s[$count];
+
+ if (ord($s[$count+1]) >= ord('0') &&
+ ord($s[$count+1]) <= ord('9')) {
+ $oct .= $s[++$count];
+
+ if (ord($s[$count+1]) >= ord('0') &&
+ ord($s[$count+1]) <= ord('9')) {
+ $oct .= $s[++$count];
+ }
+ }
+
+ $out .= chr(octdec($oct));
+ } else {
+ $out .= $s[$count];
+ }
+ }
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Hexadecimal to string
+ *
+ * @param string $data
+ * @return string
+ */
+ public function hex2str($data)
+ {
+ $data = preg_replace('/[^0-9A-Fa-f]/', '', rtrim($data, '>'));
+ if ((strlen($data) % 2) == 1) {
+ $data .= '0';
+ }
+
+ return pack('H*', $data);
+ }
+
+ /**
+ * String to hexadecimal
+ *
+ * @param string $str
+ * @return string
+ */
+ public function str2hex($str)
+ {
+ return current(unpack('H*', $str));
+ }
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/fpdi_pdf_parser.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/fpdi_pdf_parser.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/fpdi_pdf_parser.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,355 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (http://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+if (!class_exists('pdf_parser')) {
+ require_once('pdf_parser.php');
+}
+
+/**
+ * Class fpdi_pdf_parser
+ */
+class fpdi_pdf_parser extends pdf_parser
+{
+ /**
+ * Pages
+ *
+ * Index begins at 0
+ *
+ * @var array
+ */
+ protected $_pages;
+
+ /**
+ * Page count
+ *
+ * @var integer
+ */
+ protected $_pageCount;
+
+ /**
+ * Current page number
+ *
+ * @var integer
+ */
+ public $pageNo;
+
+ /**
+ * PDF version of imported document
+ *
+ * @var string
+ */
+ public $_pdfVersion;
+
+ /**
+ * Available BoxTypes
+ *
+ * @var array
+ */
+ public $availableBoxes = array('/MediaBox', '/CropBox', '/BleedBox', '/TrimBox', '/ArtBox');
+
+ /**
+ * The constructor.
+ *
+ * @param string $filename The source filename
+ */
+ public function __construct($filename)
+ {
+ parent::__construct($filename);
+
+ // resolve Pages-Dictonary
+ $pages = $this->resolveObject($this->_root[1][1]['/Pages']);
+
+ // Read pages
+ $this->_readPages($pages, $this->_pages);
+
+ // count pages;
+ $this->_pageCount = count($this->_pages);
+ }
+
+ /**
+ * Get page count from source file.
+ *
+ * @return int
+ */
+ public function getPageCount()
+ {
+ return $this->_pageCount;
+ }
+
+ /**
+ * Set the page number.
+ *
+ * @param int $pageNo Page number to use
+ * @throws InvalidArgumentException
+ */
+ public function setPageNo($pageNo)
+ {
+ $pageNo = ((int) $pageNo) - 1;
+
+ if ($pageNo < 0 || $pageNo >= $this->getPageCount()) {
+ throw new InvalidArgumentException('Invalid page number!');
+ }
+
+ $this->pageNo = $pageNo;
+ }
+
+ /**
+ * Get page-resources from current page
+ *
+ * @return array|boolean
+ */
+ public function getPageResources()
+ {
+ return $this->_getPageResources($this->_pages[$this->pageNo]);
+ }
+
+ /**
+ * Get page-resources from a /Page dictionary.
+ *
+ * @param array $obj Array of pdf-data
+ * @return array|boolean
+ */
+ protected function _getPageResources($obj)
+ {
+ $obj = $this->resolveObject($obj);
+
+ // If the current object has a resources
+ // dictionary associated with it, we use
+ // it. Otherwise, we move back to its
+ // parent object.
+ if (isset($obj[1][1]['/Resources'])) {
+ $res = $this->resolveObject($obj[1][1]['/Resources']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+ return $res;
+ }
+
+ if (!isset($obj[1][1]['/Parent'])) {
+ return false;
+ }
+
+ $res = $this->_getPageResources($obj[1][1]['/Parent']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+ return $res;
+ }
+
+ /**
+ * Get content of current page.
+ *
+ * If /Contents is an array, the streams are concatenated
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ $buffer = '';
+
+ if (isset($this->_pages[$this->pageNo][1][1]['/Contents'])) {
+ $contents = $this->_getPageContent($this->_pages[$this->pageNo][1][1]['/Contents']);
+ foreach ($contents AS $tmpContent) {
+ if ($tmpContent[0] !== pdf_parser::TYPE_STREAM) {
+ continue;
+ }
+
+ $buffer .= $this->_unFilterStream($tmpContent) . ' ';
+ }
+ }
+
+ return $buffer;
+ }
+
+ /**
+ * Resolve all content objects.
+ *
+ * @param array $contentRef
+ * @return array
+ */
+ protected function _getPageContent($contentRef)
+ {
+ $contents = array();
+
+ if ($contentRef[0] == pdf_parser::TYPE_OBJREF) {
+ $content = $this->resolveObject($contentRef);
+ if ($content[1][0] == pdf_parser::TYPE_ARRAY) {
+ $contents = $this->_getPageContent($content[1]);
+ } else {
+ $contents[] = $content;
+ }
+ } else if ($contentRef[0] == pdf_parser::TYPE_ARRAY) {
+ foreach ($contentRef[1] AS $tmp_content_ref) {
+ $contents = array_merge($contents, $this->_getPageContent($tmp_content_ref));
+ }
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Get a boundary box from a page
+ *
+ * Array format is same as used by FPDF_TPL.
+ *
+ * @param array $page a /Page dictionary
+ * @param string $boxIndex Type of box {see {@link $availableBoxes})
+ * @param float Scale factor from user space units to points
+ *
+ * @return array|boolean
+ */
+ protected function _getPageBox($page, $boxIndex, $k)
+ {
+ $page = $this->resolveObject($page);
+ $box = null;
+ if (isset($page[1][1][$boxIndex])) {
+ $box = $page[1][1][$boxIndex];
+ }
+
+ if (!is_null($box) && $box[0] == pdf_parser::TYPE_OBJREF) {
+ $tmp_box = $this->resolveObject($box);
+ $box = $tmp_box[1];
+ }
+
+ if (!is_null($box) && $box[0] == pdf_parser::TYPE_ARRAY) {
+ $b = $box[1];
+ return array(
+ 'x' => $b[0][1] / $k,
+ 'y' => $b[1][1] / $k,
+ 'w' => abs($b[0][1] - $b[2][1]) / $k,
+ 'h' => abs($b[1][1] - $b[3][1]) / $k,
+ 'llx' => min($b[0][1], $b[2][1]) / $k,
+ 'lly' => min($b[1][1], $b[3][1]) / $k,
+ 'urx' => max($b[0][1], $b[2][1]) / $k,
+ 'ury' => max($b[1][1], $b[3][1]) / $k,
+ );
+ } else if (!isset($page[1][1]['/Parent'])) {
+ return false;
+ } else {
+ return $this->_getPageBox($this->resolveObject($page[1][1]['/Parent']), $boxIndex, $k);
+ }
+ }
+
+ /**
+ * Get all page boundary boxes by page number
+ *
+ * @param int $pageNo The page number
+ * @param float $k Scale factor from user space units to points
+ * @return array
+ * @throws InvalidArgumentException
+ */
+ public function getPageBoxes($pageNo, $k)
+ {
+ if (!isset($this->_pages[$pageNo - 1])) {
+ throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.');
+ }
+
+ return $this->_getPageBoxes($this->_pages[$pageNo - 1], $k);
+ }
+
+ /**
+ * Get all boxes from /Page dictionary
+ *
+ * @param array $page A /Page dictionary
+ * @param float $k Scale factor from user space units to points
+ * @return array
+ */
+ protected function _getPageBoxes($page, $k)
+ {
+ $boxes = array();
+
+ foreach($this->availableBoxes AS $box) {
+ if ($_box = $this->_getPageBox($page, $box, $k)) {
+ $boxes[$box] = $_box;
+ }
+ }
+
+ return $boxes;
+ }
+
+ /**
+ * Get the page rotation by page number
+ *
+ * @param integer $pageNo
+ * @throws InvalidArgumentException
+ * @return array
+ */
+ public function getPageRotation($pageNo)
+ {
+ if (!isset($this->_pages[$pageNo - 1])) {
+ throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.');
+ }
+
+ return $this->_getPageRotation($this->_pages[$pageNo - 1]);
+ }
+
+ /**
+ * Get the rotation value of a page
+ *
+ * @param array $obj A /Page dictionary
+ * @return array|bool
+ */
+ protected function _getPageRotation($obj)
+ {
+ $obj = $this->resolveObject($obj);
+ if (isset($obj[1][1]['/Rotate'])) {
+ $res = $this->resolveObject($obj[1][1]['/Rotate']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+ return $res;
+ }
+
+ if (!isset($obj[1][1]['/Parent'])) {
+ return false;
+ }
+
+ $res = $this->_getPageRotation($obj[1][1]['/Parent']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+
+ return $res;
+ }
+
+ /**
+ * Read all pages
+ *
+ * @param array $pages /Pages dictionary
+ * @param array $result The result array
+ * @throws Exception
+ */
+ protected function _readPages(&$pages, &$result)
+ {
+ // Get the kids dictionary
+ $_kids = $this->resolveObject($pages[1][1]['/Kids']);
+
+ if (!is_array($_kids)) {
+ throw new Exception('Cannot find /Kids in current /Page-Dictionary');
+ }
+
+ if ($_kids[0] === self::TYPE_OBJECT) {
+ $_kids = $_kids[1];
+ }
+
+ $kids = $_kids[1];
+
+ foreach ($kids as $v) {
+ $pg = $this->resolveObject($v);
+ if ($pg[0] !== pdf_parser::TYPE_OBJECT) {
+ throw new Exception('Invalid data type in page tree.');
+ }
+
+ if ($pg[1][1]['/Type'][1] === '/Pages') {
+ // If one of the kids is an embedded
+ // /Pages array, resolve it as well.
+ $this->_readPages($pg, $result);
+ } else {
+ $result[] = $pg;
+ }
+ }
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/pdf_context.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/pdf_context.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/pdf_context.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,151 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+/**
+ * Class pdf_context
+ */
+class pdf_context
+{
+ /**
+ * Mode
+ *
+ * @var integer 0 = file | 1 = string
+ */
+ protected $_mode = 0;
+
+ /**
+ * @var resource|string
+ */
+ public $file;
+
+ /**
+ * @var string
+ */
+ public $buffer;
+
+ /**
+ * @var integer
+ */
+ public $offset;
+
+ /**
+ * @var integer
+ */
+ public $length;
+
+ /**
+ * @var array
+ */
+ public $stack;
+
+ /**
+ * The constructor
+ *
+ * @param resource $f
+ */
+ public function __construct(&$f)
+ {
+ $this->file =& $f;
+ if (is_string($this->file))
+ $this->_mode = 1;
+
+ $this->reset();
+ }
+
+ /**
+ * Get the position in the file stream
+ *
+ * @return int
+ */
+ public function getPos()
+ {
+ if ($this->_mode == 0) {
+ if (feof($this->file)) {
+ $stat = fstat($this->file);
+ fseek($this->file, $stat['size']);
+ }
+
+ $pos = ftell($this->file);
+
+ return $pos;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Reset the position in the file stream.
+ *
+ * Optionally move the file pointer to a new location and reset the buffered data.
+ *
+ * @param null $pos
+ * @param int $l
+ */
+ public function reset($pos = null, $l = 100)
+ {
+ if ($this->_mode == 0) {
+ if (!is_null($pos)) {
+ fseek($this->file, $pos);
+ }
+
+ $this->buffer = $l > 0 ? fread($this->file, $l) : '';
+ $this->length = strlen($this->buffer);
+ if ($this->length < $l)
+ $this->increaseLength($l - $this->length);
+ } else {
+ $this->buffer = $this->file;
+ $this->length = strlen($this->buffer);
+ }
+ $this->offset = 0;
+ $this->stack = array();
+ }
+
+ /**
+ * Make sure that there is at least one character beyond the current offset in the buffer.
+ *
+ * To prevent the tokenizer from attempting to access data that does not exist.
+ *
+ * @return bool
+ */
+ public function ensureContent()
+ {
+ if ($this->offset >= $this->length - 1) {
+ return $this->increaseLength();
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Forcefully read more data into the buffer
+ *
+ * @param int $l
+ * @return bool
+ */
+ public function increaseLength($l = 100)
+ {
+ if ($this->_mode == 0 && feof($this->file)) {
+ return false;
+ } else if ($this->_mode == 0) {
+ $totalLength = $this->length + $l;
+ do {
+ $toRead = $totalLength - $this->length;
+ if ($toRead < 1)
+ break;
+
+ $this->buffer .= fread($this->file, $toRead);
+ } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file));
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file

Added: branches/5.1.0/app/fpdi-1.6.2/pdf_parser.php
===================================================================
--- branches/5.1.0/app/fpdi-1.6.2/pdf_parser.php (rev 0)
+++ branches/5.1.0/app/fpdi-1.6.2/pdf_parser.php 2020-06-12 20:18:30 UTC (rev 1119)
@@ -0,0 +1,925 @@
+<?php
+/**
+ * This file is part of FPDI
+ *
+ * @package FPDI
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ * @version 1.6.2
+ */
+
+/**
+ * Class pdf_parser
+ */
+class pdf_parser
+{
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_NULL = 0;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_NUMERIC = 1;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_TOKEN = 2;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_HEX = 3;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_STRING = 4;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_DICTIONARY = 5;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_ARRAY = 6;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_OBJDEC = 7;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_OBJREF = 8;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_OBJECT = 9;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_STREAM = 10;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_BOOLEAN = 11;
+
+ /**
+ * Type constant
+ *
+ * @var integer
+ */
+ const TYPE_REAL = 12;
+
+ /**
+ * Define the amount of byte in which the initial keyword of a PDF document should be searched.
+ *
+ * @var int
+ */
+ static public $searchForStartxrefLength = 5500;
+
+ /**
+ * Filename
+ *
+ * @var string
+ */
+ public $filename;
+
+ /**
+ * File resource
+ *
+ * @var resource
+ */
+ protected $_f;
+
+ /**
+ * PDF Context
+ *
+ * @var pdf_context
+ */
+ protected $_c;
+
+ /**
+ * xref-Data
+ *
+ * @var array
+ */
+ protected $_xref;
+
+ /**
+ * Data of the Root object
+ *
+ * @var array
+ */
+ protected $_root;
+
+ /**
+ * PDF version of the loaded document
+ *
+ * @var string
+ */
+ protected $_pdfVersion;
+
+ /**
+ * For reading encrypted documents and xref/object streams are in use
+ *
+ * @var boolean
+ */
+ protected $_readPlain = true;
+
+ /**
+ * The current read object
+ *
+ * @var array
+ */
+ protected $_currentObj;
+
+ /**
+ * Constructor
+ *
+ * @param string $filename Source filename
+ * @throws InvalidArgumentException
+ */
+ public function __construct($filename)
+ {
+ $this->filename = $filename;
+
+ $this->_f = @fopen($this->filename, 'rb');
+
+ if (!$this->_f) {
+ throw new InvalidArgumentException(sprintf('Cannot open %s !', $filename));
+ }
+
+ $this->getPdfVersion();
+
+ if (!class_exists('pdf_context')) {
+ require_once('pdf_context.php');
+ }
+ $this->_c = new pdf_context($this->_f);
+
+ // Read xref-Data
+ $this->_xref = array();
+ $this->_readXref($this->_xref, $this->_findXref());
+
+ // Check for Encryption
+ $this->getEncryption();
+
+ // Read root
+ $this->_readRoot();
+ }
+
+ /**
+ * Destructor
+ */
+ public function __destruct()
+ {
+ $this->closeFile();
+ }
+
+ /**
+ * Close the opened file
+ */
+ public function closeFile()
+ {
+ if (isset($this->_f) && is_resource($this->_f)) {
+ fclose($this->_f);
+ unset($this->_f);
+ }
+ }
+
+ /**
+ * Check Trailer for Encryption
+ *
+ * @throws Exception
+ */
+ public function getEncryption()
+ {
+ if (isset($this->_xref['trailer'][1]['/Encrypt'])) {
+ throw new Exception('File is encrypted!');
+ }
+ }
+
+ /**
+ * Get PDF-Version
+ *
+ * @return string
+ */
+ public function getPdfVersion()
+ {
+ if ($this->_pdfVersion === null) {
+ fseek($this->_f, 0);
+ preg_match('/\d\.\d/', fread($this->_f, 16), $m);
+ if (isset($m[0]))
+ $this->_pdfVersion = $m[0];
+ }
+
+ return $this->_pdfVersion;
+ }
+
+ /**
+ * Read the /Root dictionary
+ */
+ protected function _readRoot()
+ {
+ if ($this->_xref['trailer'][1]['/Root'][0] != self::TYPE_OBJREF) {
+ throw new Exception('Wrong Type of Root-Element! Must be an indirect reference');
+ }
+
+ $this->_root = $this->resolveObject($this->_xref['trailer'][1]['/Root']);
+ }
+
+ /**
+ * Find the xref table
+ *
+ * @return integer
+ * @throws Exception
+ */
+ protected function _findXref()
+ {
+ $toRead = self::$searchForStartxrefLength;
+
+ $stat = fseek($this->_f, -$toRead, SEEK_END);
+ if ($stat === -1) {
+ fseek($this->_f, 0);
+ }
+
+ $data = fread($this->_f, $toRead);
+
+ $keywordPos = strpos(strrev($data), strrev('startxref'));
+ if (false === $keywordPos) {
+ $keywordPos = strpos(strrev($data), strrev('startref'));
+ }
+
+ if (false === $keywordPos) {
+ throw new Exception('Unable to find "startxref" keyword.');
+ }
+
+ $pos = strlen($data) - $keywordPos;
+ $data = substr($data, $pos);
+
+ if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) {
+ throw new Exception('Unable to find pointer to xref table.');
+ }
+
+ return (int) $matches[1];
+ }
+
+ /**
+ * Read the xref table
+ *
+ * @param array $result Array of xref table entries
+ * @param integer $offset of xref table
+ * @return boolean
+ * @throws Exception
+ */
+ protected function _readXref(&$result, $offset)
+ {
+ $tempPos = $offset - min(20, $offset);
+ fseek($this->_f, $tempPos); // set some bytes backwards to fetch corrupted docs
+
+ $data = fread($this->_f, 100);
+
+ $xrefPos = strrpos($data, 'xref');
+
+ if ($xrefPos === false) {
+ $this->_c->reset($offset);
+ $xrefStreamObjDec = $this->_readValue($this->_c);
+
+ if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == self::TYPE_OBJDEC) {
+ throw new Exception(
+ sprintf(
+ 'This document (%s) probably uses a compression technique which is not supported by the ' .
+ 'free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)',
+ $this->filename
+ )
+ );
+ } else {
+ throw new Exception('Unable to find xref table.');
+ }
+ }
+
+ if (!isset($result['xrefLocation'])) {
+ $result['xrefLocation'] = $tempPos + $xrefPos;
+ $result['maxObject'] = 0;
+ }
+
+ $cycles = -1;
+ $bytesPerCycle = 100;
+
+ fseek($this->_f, $tempPos = $tempPos + $xrefPos + 4); // set the handle directly after the "xref"-keyword
+ $data = fread($this->_f, $bytesPerCycle);
+
+ while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle * $cycles++, 0))) === false && !feof($this->_f)) {
+ $data .= fread($this->_f, $bytesPerCycle);
+ }
+
+ if ($trailerPos === false) {
+ throw new Exception('Trailer keyword not found after xref table');
+ }
+
+ $data = ltrim(substr($data, 0, $trailerPos));
+
+ // get Line-Ending
+ $found = preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for line breaks
+ if ($found === 0) {
+ throw new Exception('Xref table seems to be corrupted.');
+ }
+ $differentLineEndings = count(array_unique($m[0]));
+ if ($differentLineEndings > 1) {
+ $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY);
+ } else {
+ $lines = explode($m[0][0], $data);
+ }
+
+ $data = $differentLineEndings = $m = null;
+ unset($data, $differentLineEndings, $m);
+
+ $linesCount = count($lines);
+
+ $start = 1;
+
+ for ($i = 0; $i < $linesCount; $i++) {
+ $line = trim($lines[$i]);
+ if ($line) {
+ $pieces = explode(' ', $line);
+ $c = count($pieces);
+ switch($c) {
+ case 2:
+ $start = (int)$pieces[0];
+ $end = $start + (int)$pieces[1];
+ if ($end > $result['maxObject'])
+ $result['maxObject'] = $end;
+ break;
+ case 3:
+ if (!isset($result['xref'][$start]))
+ $result['xref'][$start] = array();
+
+ if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) {
+ $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null;
+ }
+ $start++;
+ break;
+ default:
+ throw new Exception('Unexpected data in xref table');
+ }
+ }
+ }
+
+ $lines = $pieces = $line = $start = $end = $gen = null;
+ unset($lines, $pieces, $line, $start, $end, $gen);
+
+ $this->_c->reset($tempPos + $trailerPos + 7);
+ $trailer = $this->_readValue($this->_c);
+
+ if (!isset($result['trailer'])) {
+ $result['trailer'] = $trailer;
+ }
+
+ if (isset($trailer[1]['/Prev'])) {
+ $this->_readXref($result, $trailer[1]['/Prev'][1]);
+ }
+
+ $trailer = null;
+ unset($trailer);
+
+ return true;
+ }
+
+ /**
+ * Reads a PDF value
+ *
+ * @param pdf_context $c
+ * @param string $token A token
+ * @return mixed
+ * @throws Exception
+ */
+ protected function _readValue(&$c, $token = null)
+ {
+ if (is_null($token)) {
+ $token = $this->_readToken($c);
+ }
+
+ if ($token === false) {
+ return false;
+ }
+
+ switch ($token) {
+ case '<':
+ // This is a hex string.
+ // Read the value, then the terminator
+
+ $pos = $c->offset;
+
+ while(1) {
+
+ $match = strpos($c->buffer, '>', $pos);
+
+ // If you can't find it, try
+ // reading more data from the stream
+
+ if ($match === false) {
+ if (!$c->increaseLength()) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+
+ $result = substr($c->buffer, $c->offset, $match - $c->offset);
+ $c->offset = $match + 1;
+
+ return array (self::TYPE_HEX, $result);
+ }
+ break;
+
+ case '<<':
+ // This is a dictionary.
+
+ $result = array();
+
+ // Recurse into this function until we reach
+ // the end of the dictionary.
+ while (($key = $this->_readToken($c)) !== '>>') {
+ if ($key === false) {
+ return false;
+ }
+
+ if (($value = $this->_readValue($c)) === false) {
+ return false;
+ }
+
+ // Catch missing value
+ if ($value[0] == self::TYPE_TOKEN && $value[1] == '>>') {
+ $result[$key] = array(self::TYPE_NULL);
+ break;
+ }
+
+ $result[$key] = $value;
+ }
+
+ return array (self::TYPE_DICTIONARY, $result);
+
+ case '[':
+ // This is an array.
+
+ $result = array();
+
+ // Recurse into this function until we reach
+ // the end of the array.
+ while (($token = $this->_readToken($c)) !== ']') {
+ if ($token === false) {
+ return false;
+ }
+
+ if (($value = $this->_readValue($c, $token)) === false) {
+ return false;
+ }
+
+ $result[] = $value;
+ }
+
+ return array (self::TYPE_ARRAY, $result);
+
+ case '(':
+ // This is a string
+ $pos = $c->offset;
+
+ $openBrackets = 1;
+ do {
+ for (; $openBrackets != 0 && $pos < $c->length; $pos++) {
+ switch (ord($c->buffer[$pos])) {
+ case 0x28: // '('
+ $openBrackets++;
+ break;
+ case 0x29: // ')'
+ $openBrackets--;
+ break;
+ case 0x5C: // backslash
+ $pos++;
+ }
+ }
+ } while($openBrackets != 0 && $c->increaseLength());
+
+ $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1);
+ $c->offset = $pos;
+
+ return array (self::TYPE_STRING, $result);
+
+ case 'stream':
+ $tempPos = $c->getPos() - strlen($c->buffer);
+ $tempOffset = $c->offset;
+
+ $c->reset($startPos = $tempPos + $tempOffset);
+
+ // Find the first "newline"
+ while ($c->buffer[0] !== chr(10) && $c->buffer[0] !== chr(13)) {
+ $c->reset(++$startPos);
+ if ($c->ensureContent() === false) {
+ throw new Exception(
+ 'Unable to parse stream data. No newline followed the stream keyword.'
+ );
+ }
+ }
+
+ $e = 0; // ensure line breaks in front of the stream
+ if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13))
+ $e++;
+ if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10))
+ $e++;
+
+ if ($this->_currentObj[1][1]['/Length'][0] == self::TYPE_OBJREF) {
+ $tmpLength = $this->resolveObject($this->_currentObj[1][1]['/Length']);
+ $length = $tmpLength[1][1];
+ } else {
+ $length = $this->_currentObj[1][1]['/Length'][1];
+ }
+
+ if ($length > 0) {
+ $c->reset($startPos + $e, $length);
+ $v = $c->buffer;
+ } else {
+ $v = '';
+ }
+
+ $c->reset($startPos + $e + $length);
+ $endstream = $this->_readToken($c);
+
+ if ($endstream != 'endstream') {
+ $c->reset($startPos + $e + $length + 9); // 9 = strlen("endstream")
+ // We don't throw an error here because the next
+ // round trip will start at a new offset
+ }
+
+ return array(self::TYPE_STREAM, $v);
+
+ default:
+ if (is_numeric($token)) {
+ // A numeric token. Make sure that
+ // it is not part of something else.
+ if (($tok2 = $this->_readToken($c)) !== false) {
+ if (is_numeric($tok2)) {
+
+ // Two numeric tokens in a row.
+ // In this case, we're probably in
+ // front of either an object reference
+ // or an object specification.
+ // Determine the case and return the data
+ if (($tok3 = $this->_readToken($c)) !== false) {
+ switch ($tok3) {
+ case 'obj':
+ return array(self::TYPE_OBJDEC, (int)$token, (int)$tok2);
+ case 'R':
+ return array(self::TYPE_OBJREF, (int)$token, (int)$tok2);
+ }
+ // If we get to this point, that numeric value up
+ // there was just a numeric value. Push the extra
+ // tokens back into the stack and return the value.
+ array_push($c->stack, $tok3);
+ }
+ }
+
+ array_push($c->stack, $tok2);
+ }
+
+ if ($token === (string)((int)$token))
+ return array(self::TYPE_NUMERIC, (int)$token);
+ else
+ return array(self::TYPE_REAL, (float)$token);
+ } else if ($token == 'true' || $token == 'false') {
+ return array(self::TYPE_BOOLEAN, $token == 'true');
+ } else if ($token == 'null') {
+ return array(self::TYPE_NULL);
+ } else {
+ // Just a token. Return it.
+ return array(self::TYPE_TOKEN, $token);
+ }
+ }
+ }
+
+ /**
+ * Resolve an object
+ *
+ * @param array $objSpec The object-data
+ * @return array|boolean
+ * @throws Exception
+ */
+ public function resolveObject($objSpec)
+ {
+ $c = $this->_c;
+
+ // Exit if we get invalid data
+ if (!is_array($objSpec)) {
+ return false;
+ }
+
+ if ($objSpec[0] == self::TYPE_OBJREF) {
+
+ // This is a reference, resolve it
+ if (isset($this->_xref['xref'][$objSpec[1]][$objSpec[2]])) {
+
+ // Save current file position
+ // This is needed if you want to resolve
+ // references while you're reading another object
+ // (e.g.: if you need to determine the length
+ // of a stream)
+
+ $oldPos = $c->getPos();
+
+ // Reposition the file pointer and
+ // load the object header.
+
+ $c->reset($this->_xref['xref'][$objSpec[1]][$objSpec[2]]);
+
+ $header = $this->_readValue($c);
+
+ if ($header[0] != self::TYPE_OBJDEC || $header[1] != $objSpec[1] || $header[2] != $objSpec[2]) {
+ $toSearchFor = $objSpec[1] . ' ' . $objSpec[2] . ' obj';
+ if (preg_match('/' . $toSearchFor . '/', $c->buffer)) {
+ $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor);
+ // reset stack
+ $c->stack = array();
+ } else {
+ throw new Exception(
+ sprintf("Unable to find object (%s, %s) at expected location.", $objSpec[1], $objSpec[2])
+ );
+ }
+ }
+
+ // If we're being asked to store all the information
+ // about the object, we add the object ID and generation
+ // number for later use
+ $result = array (
+ self::TYPE_OBJECT,
+ 'obj' => $objSpec[1],
+ 'gen' => $objSpec[2]
+ );
+
+ $this->_currentObj =& $result;
+
+ // Now simply read the object data until
+ // we encounter an end-of-object marker
+ while (true) {
+ $value = $this->_readValue($c);
+ if ($value === false || count($result) > 4) {
+ // in this case the parser couldn't find an "endobj" so we break here
+ break;
+ }
+
+ if ($value[0] == self::TYPE_TOKEN && $value[1] === 'endobj') {
+ break;
+ }
+
+ $result[] = $value;
+ }
+
+ $c->reset($oldPos);
+
+ if (isset($result[2][0]) && $result[2][0] == self::TYPE_STREAM) {
+ $result[0] = self::TYPE_STREAM;
+ }
+
+ } else {
+ throw new Exception(
+ sprintf("Unable to find object (%s, %s) at expected location.", $objSpec[1], $objSpec[2])
+ );
+ }
+
+ return $result;
+ } else {
+ return $objSpec;
+ }
+ }
+
+ /**
+ * Reads a token from the context
+ *
+ * @param pdf_context $c
+ * @return mixed
+ */
+ protected function _readToken($c)
+ {
+ // If there is a token available
+ // on the stack, pop it out and
+ // return it.
+
+ if (count($c->stack)) {
+ return array_pop($c->stack);
+ }
+
+ // Strip away any whitespace
+
+ do {
+ if (!$c->ensureContent()) {
+ return false;
+ }
+ $c->offset += strspn($c->buffer, "\x20\x0A\x0C\x0D\x09\x00", $c->offset);
+ } while ($c->offset >= $c->length - 1);
+
+ // Get the first character in the stream
+
+ $char = $c->buffer[$c->offset++];
+
+ switch ($char) {
+
+ case '[':
+ case ']':
+ case '(':
+ case ')':
+
+ // This is either an array or literal string
+ // delimiter, Return it
+
+ return $char;
+
+ case '<':
+ case '>':
+
+ // This could either be a hex string or
+ // dictionary delimiter. Determine the
+ // appropriate case and return the token
+
+ if ($c->buffer[$c->offset] == $char) {
+ if (!$c->ensureContent()) {
+ return false;
+ }
+ $c->offset++;
+ return $char . $char;
+ } else {
+ return $char;
+ }
+
+ case '%':
+
+ // This is a comment - jump over it!
+
+ $pos = $c->offset;
+ while(1) {
+ $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos);
+ if ($match === 0) {
+ if (!$c->increaseLength()) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+
+ $c->offset = $m[0][1] + strlen($m[0][0]);
+
+ return $this->_readToken($c);
+ }
+
+ default:
+
+ // This is "another" type of token (probably
+ // a dictionary entry or a numeric value)
+ // Find the end and return it.
+
+ if (!$c->ensureContent()) {
+ return false;
+ }
+
+ while(1) {
+
+ // Determine the length of the token
+
+ $pos = strcspn($c->buffer, "\x20%[]<>()/\x0A\x0C\x0D\x09\x00", $c->offset);
+
+ if ($c->offset + $pos <= $c->length - 1) {
+ break;
+ } else {
+ // If the script reaches this point,
+ // the token may span beyond the end
+ // of the current buffer. Therefore,
+ // we increase the size of the buffer
+ // and try again--just to be safe.
+
+ $c->increaseLength();
+ }
+ }
+
+ $result = substr($c->buffer, $c->offset - 1, $pos + 1);
+
+ $c->offset += $pos;
+
+ return $result;
+ }
+ }
+
+ /**
+ * Un-filter a stream object
+ *
+ * @param array $obj
+ * @return string
+ * @throws Exception
+ */
+ protected function _unFilterStream($obj)
+ {
+ $filters = array();
+
+ if (isset($obj[1][1]['/Filter'])) {
+ $filter = $obj[1][1]['/Filter'];
+
+ if ($filter[0] == pdf_parser::TYPE_OBJREF) {
+ $tmpFilter = $this->resolveObject($filter);
+ $filter = $tmpFilter[1];
+ }
+
+ if ($filter[0] == pdf_parser::TYPE_TOKEN) {
+ $filters[] = $filter;
+ } else if ($filter[0] == pdf_parser::TYPE_ARRAY) {
+ $filters = $filter[1];
+ }
+ }
+
+ $stream = $obj[2][1];
+
+ foreach ($filters AS $filter) {
+ switch ($filter[1]) {
+ case '/FlateDecode':
+ case '/Fl':
+ if (function_exists('gzuncompress')) {
+ $oStream = $stream;
+ $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : '';
+ } else {
+ throw new Exception(
+ sprintf('To handle %s filter, please compile php with zlib support.', $filter[1])
+ );
+ }
+
+ if ($stream === false) {
+ $tries = 0;
+ while ($tries < 8 && ($stream === false || strlen($stream) < strlen($oStream))) {
+ $oStream = substr($oStream, 1);
+ $stream = @gzinflate($oStream);
+ $tries++;
+ }
+
+ if ($stream === false) {
+ throw new Exception('Error while decompressing stream.');
+ }
+ }
+ break;
+ case '/LZWDecode':
+ if (!class_exists('FilterLZW')) {
+ require_once('filters/FilterLZW.php');
+ }
+ $decoder = new FilterLZW();
+ $stream = $decoder->decode($stream);
+ break;
+ case '/ASCII85Decode':
+ if (!class_exists('FilterASCII85')) {
+ require_once('filters/FilterASCII85.php');
+ }
+ $decoder = new FilterASCII85();
+ $stream = $decoder->decode($stream);
+ break;
+ case '/ASCIIHexDecode':
+ if (!class_exists('FilterASCIIHexDecode')) {
+ require_once('filters/FilterASCIIHexDecode.php');
+ }
+ $decoder = new FilterASCIIHexDecode();
+ $stream = $decoder->decode($stream);
+ break;
+ case null:
+ break;
+ default:
+ throw new Exception(sprintf('Unsupported Filter: %s', $filter[1]));
+ }
+ }
+
+ return $stream;
+ }
+}
\ No newline at end of file

Reply all
Reply to author
Forward
0 new messages