diff --git a/debian/control b/debian/control index ae4c21d..3afd805 100644 --- a/debian/control +++ b/debian/control @@ -96,13 +96,8 @@ Package: pnp4nagios-web Architecture: all Depends: ${misc:Depends}, - libapache2-mod-php5 | php5-cgi | php5, - php5-gd, - libkohana2-php, - libfpdi-php, - libjs-jquery (>= 1.6.2), - libjs-jquery-ui (>= 1.8.ooops.14), - libjs-jquery-mobile, + libapache2-mod-php5 | libapache2-mod-php7.0 | php5-cgi | php7.0-cgi | php7.0 | php5, + php7.0-gd | php5-gd , rrdtool, adduser Recommends: pnp4nagios-bin, pnp4nagios-web-config-icinga | pnp4nagios-web-config-nagios4 diff --git a/debian/rules b/debian/rules index 0e7dabd..3628d49 100755 --- a/debian/rules +++ b/debian/rules @@ -15,9 +15,9 @@ override_dh_auto_configure: dh_auto_configure -- \ --with-layout=debian \ --mandir=/usr/share/man \ - --infodir=/usr/share/info \ - --without-kohana \ - --with-kohana_system=/usr/share/php/kohana2/system + --infodir=/usr/share/info +# --without-kohana \ +# --with-kohana_system=/usr/share/php/kohana2/system override_dh_auto_build: dh_auto_build -- all @@ -67,7 +67,7 @@ override_dh_auto_install: cp debian/icinga-module.cfg debian/tmp/usr/share/doc/pnp4nagios/examples/ # Remove external PHP classes/libraries: FPDF, FPDF-TPL, FPDI - rm -r debian/tmp/usr/share/pnp4nagios/html/application/vendor/fpdf + #rm -r debian/tmp/usr/share/pnp4nagios/html/application/vendor/fpdf # remove source files #rm -f debian/tmp/usr/share/pnp4nagios/html/media/js/jquery.imgareaselect.Debian.txt diff --git a/share/pnp/application/vendor/fpdf/filters/FilterASCII85.php b/share/pnp/application/vendor/fpdf/filters/FilterASCII85.php index fc42d57..dc100c4 100644 --- a/share/pnp/application/vendor/fpdf/filters/FilterASCII85.php +++ b/share/pnp/application/vendor/fpdf/filters/FilterASCII85.php @@ -1,68 +1,66 @@ ord('~'), + 'z' => ord('z'), + 'u' => ord('u'), + '!' => ord('!') + ); -class FilterASCII85 { - - function error($msg) { - die($msg); - } - - function decode($in) { $out = ''; $state = 0; $chn = null; - + $l = strlen($in); - + for ($k = 0; $k < $l; ++$k) { $ch = ord($in[$k]) & 0xff; - - if ($ch == ORD_tilde) { + + 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); + if ($ch == $ord['z'] && $state == 0) { + $out .= chr(0) . chr(0) . chr(0) . chr(0); continue; } - if ($ch < ORD_exclmark || $ch > ORD_u) { - $this->error('Illegal character in ASCII85Decode.'); + if ($ch < $ord['!'] || $ch > $ord['u']) { + throw new Exception('Illegal character in ASCII85Decode.'); } - - $chn[$state++] = $ch - ORD_exclmark; - + + $chn[$state++] = $ch - $ord['!']; + if ($state == 5) { $state = 0; $r = 0; - for ($j = 0; $j < 5; ++$j) - $r = $r * 85 + $chn[$j]; + for ($j = 0; $j < 5; ++$j) { + $r = (int)($r * 85 + $chn[$j]); + } + $out .= chr($r >> 24); $out .= chr($r >> 16); $out .= chr($r >> 8); @@ -70,19 +68,21 @@ class FilterASCII85 { } } $r = 0; - - if ($state == 1) - $this->error('Illegal length in ASCII85Decode.'); + + 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) { + + } 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) { + + } 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); @@ -91,8 +91,16 @@ class FilterASCII85 { return $out; } - - function encode($in) { - $this->error("ASCII85 encoding not implemented."); + + /** + * 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 diff --git a/share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php b/share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php deleted file mode 100644 index 596de48..0000000 --- a/share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php +++ /dev/null @@ -1,33 +0,0 @@ -fpdi =& $fpdi; - } - - function error($msg) { - $this->fpdi->error($msg); - } -} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/filters/FilterASCIIHexDecode.php b/share/pnp/application/vendor/fpdf/filters/FilterASCIIHexDecode.php new file mode 100644 index 0000000..3c29a95 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/filters/FilterASCIIHexDecode.php @@ -0,0 +1,43 @@ +')); + 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 diff --git a/share/pnp/application/vendor/fpdf/filters/FilterLZW.php b/share/pnp/application/vendor/fpdf/filters/FilterLZW.php index 5867603..c3d26ad 100644 --- a/share/pnp/application/vendor/fpdf/filters/FilterLZW.php +++ b/share/pnp/application/vendor/fpdf/filters/FilterLZW.php @@ -1,154 +1,164 @@ error('LZW flavour not supported.'); + public function decode($data) + { + if ($data[0] == 0x00 && $data[1] == 0x01) { + throw new Exception('LZW flavour not supported.'); } - $this->initsTable(); + $this->_initsTable(); - $this->data = $data; - $this->dataLength = strlen($data); + $this->_data = $data; + $this->_dataLength = strlen($data); // Initialize pointers - $this->bytePointer = 0; - $this->bitPointer = 0; + $this->_bytePointer = 0; + $this->_bitPointer = 0; - $this->nextData = 0; - $this->nextBits = 0; + $this->_nextData = 0; + $this->_nextBits = 0; $oldCode = 0; - $string = ''; - $uncompData = ''; + $unCompData = ''; - while (($code = $this->getNextCode()) != 257) { + while (($code = $this->_getNextCode()) != 257) { if ($code == 256) { - $this->initsTable(); - $code = $this->getNextCode(); + $this->_initsTable(); + $code = $this->_getNextCode(); if ($code == 257) { break; } - $uncompData .= $this->sTable[$code]; + 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; + if ($code < $this->_tIdx) { + $string = $this->_sTable[$code]; + $unCompData .= $string; - $this->addStringToTable($this->sTable[$oldCode], $string[0]); + $this->_addStringToTable($this->_sTable[$oldCode], $string[0]); $oldCode = $code; } else { - $string = $this->sTable[$oldCode]; - $string = $string.$string[0]; - $uncompData .= $string; + $string = $this->_sTable[$oldCode]; + $string = $string . $string[0]; + $unCompData .= $string; - $this->addStringToTable($string); + $this->_addStringToTable($string); $oldCode = $code; } } } - - return $uncompData; + + return $unCompData; } /** * Initialize the string table. */ - function initsTable() { - $this->sTable = array(); + protected function _initsTable() + { + $this->_sTable = array(); for ($i = 0; $i < 256; $i++) - $this->sTable[$i] = chr($i); + $this->_sTable[$i] = chr($i); - $this->tIdx = 258; - $this->bitsToGet = 9; + $this->_tIdx = 258; + $this->_bitsToGet = 9; } /** * Add a new string to the string table. */ - function addStringToTable ($oldString, $newString='') { - $string = $oldString.$newString; + protected function _addStringToTable($oldString, $newString = '') + { + $string = $oldString . $newString; // Add this new String to the table - $this->sTable[$this->tIdx++] = $string; + $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; + 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 - function getNextCode() { - if ($this->bytePointer == $this->dataLength) { + /** + * 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; + $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; + 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; + $code = ($this->_nextData >> ($this->_nextBits - $this->_bitsToGet)) & $this->_andTable[$this->_bitsToGet-9]; + $this->_nextBits -= $this->_bitsToGet; return $code; } - - function encode($in) { - $this->error("LZW encoding not implemented."); + + /** + * 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 diff --git a/share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php b/share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php deleted file mode 100644 index 540c22c..0000000 --- a/share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php +++ /dev/null @@ -1,33 +0,0 @@ -fpdi =& $fpdi; - } - - function error($msg) { - $this->fpdi->error($msg); - } -} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/font/courier.php b/share/pnp/application/vendor/fpdf/font/courier.php old mode 100755 new mode 100644 index 213bf35..67dbeda --- a/share/pnp/application/vendor/fpdf/font/courier.php +++ b/share/pnp/application/vendor/fpdf/font/courier.php @@ -5,4 +5,6 @@ $up = -100; $ut = 50; for($i=0;$i<=255;$i++) $cw[chr($i)] = 600; +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/courierb.php b/share/pnp/application/vendor/fpdf/font/courierb.php old mode 100755 new mode 100644 index 3fc69a5..62550a4 --- a/share/pnp/application/vendor/fpdf/font/courierb.php +++ b/share/pnp/application/vendor/fpdf/font/courierb.php @@ -5,4 +5,6 @@ $up = -100; $ut = 50; for($i=0;$i<=255;$i++) $cw[chr($i)] = 600; +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/courierbi.php b/share/pnp/application/vendor/fpdf/font/courierbi.php old mode 100755 new mode 100644 index a49f2ae..6a3ecc6 --- a/share/pnp/application/vendor/fpdf/font/courierbi.php +++ b/share/pnp/application/vendor/fpdf/font/courierbi.php @@ -5,4 +5,6 @@ $up = -100; $ut = 50; for($i=0;$i<=255;$i++) $cw[chr($i)] = 600; +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/courieri.php b/share/pnp/application/vendor/fpdf/font/courieri.php old mode 100755 new mode 100644 index 9c1c2cf..b88e098 --- a/share/pnp/application/vendor/fpdf/font/courieri.php +++ b/share/pnp/application/vendor/fpdf/font/courieri.php @@ -5,4 +5,6 @@ $up = -100; $ut = 50; for($i=0;$i<=255;$i++) $cw[chr($i)] = 600; +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/helvetica.php b/share/pnp/application/vendor/fpdf/font/helvetica.php old mode 100755 new mode 100644 index 7e20c3a..2be3eca --- a/share/pnp/application/vendor/fpdf/font/helvetica.php +++ b/share/pnp/application/vendor/fpdf/font/helvetica.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556, chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/helveticab.php b/share/pnp/application/vendor/fpdf/font/helveticab.php old mode 100755 new mode 100644 index 452e0ac..c88394c --- a/share/pnp/application/vendor/fpdf/font/helveticab.php +++ b/share/pnp/application/vendor/fpdf/font/helveticab.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611, chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/helveticabi.php b/share/pnp/application/vendor/fpdf/font/helveticabi.php old mode 100755 new mode 100644 index ea5c56f..bcea807 --- a/share/pnp/application/vendor/fpdf/font/helveticabi.php +++ b/share/pnp/application/vendor/fpdf/font/helveticabi.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611, chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/helveticai.php b/share/pnp/application/vendor/fpdf/font/helveticai.php old mode 100755 new mode 100644 index e3c638a..a328b04 --- a/share/pnp/application/vendor/fpdf/font/helveticai.php +++ b/share/pnp/application/vendor/fpdf/font/helveticai.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556, chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/symbol.php b/share/pnp/application/vendor/fpdf/font/symbol.php old mode 100755 new mode 100644 index b980b07..5b9147b --- a/share/pnp/application/vendor/fpdf/font/symbol.php +++ b/share/pnp/application/vendor/fpdf/font/symbol.php @@ -16,4 +16,5 @@ $cw = array( chr(198)=>823,chr(199)=>768,chr(200)=>768,chr(201)=>713,chr(202)=>713,chr(203)=>713,chr(204)=>713,chr(205)=>713,chr(206)=>713,chr(207)=>713,chr(208)=>768,chr(209)=>713,chr(210)=>790,chr(211)=>790,chr(212)=>890,chr(213)=>823,chr(214)=>549,chr(215)=>250,chr(216)=>713,chr(217)=>603,chr(218)=>603,chr(219)=>1042, chr(220)=>987,chr(221)=>603,chr(222)=>987,chr(223)=>603,chr(224)=>494,chr(225)=>329,chr(226)=>790,chr(227)=>790,chr(228)=>786,chr(229)=>713,chr(230)=>384,chr(231)=>384,chr(232)=>384,chr(233)=>384,chr(234)=>384,chr(235)=>384,chr(236)=>494,chr(237)=>494,chr(238)=>494,chr(239)=>494,chr(240)=>0,chr(241)=>329, chr(242)=>274,chr(243)=>686,chr(244)=>686,chr(245)=>686,chr(246)=>384,chr(247)=>384,chr(248)=>384,chr(249)=>384,chr(250)=>384,chr(251)=>384,chr(252)=>494,chr(253)=>494,chr(254)=>494,chr(255)=>0); +$uv = array(32=>160,33=>33,34=>8704,35=>35,36=>8707,37=>array(37,2),39=>8715,40=>array(40,2),42=>8727,43=>array(43,2),45=>8722,46=>array(46,18),64=>8773,65=>array(913,2),67=>935,68=>array(916,2),70=>934,71=>915,72=>919,73=>921,74=>977,75=>array(922,4),79=>array(927,2),81=>920,82=>929,83=>array(931,3),86=>962,87=>937,88=>926,89=>936,90=>918,91=>91,92=>8756,93=>93,94=>8869,95=>95,96=>63717,97=>array(945,2),99=>967,100=>array(948,2),102=>966,103=>947,104=>951,105=>953,106=>981,107=>array(954,4),111=>array(959,2),113=>952,114=>961,115=>array(963,3),118=>982,119=>969,120=>958,121=>968,122=>950,123=>array(123,3),126=>8764,160=>8364,161=>978,162=>8242,163=>8804,164=>8725,165=>8734,166=>402,167=>9827,168=>9830,169=>9829,170=>9824,171=>8596,172=>array(8592,4),176=>array(176,2),178=>8243,179=>8805,180=>215,181=>8733,182=>8706,183=>8226,184=>247,185=>array(8800,2),187=>8776,188=>8230,189=>array(63718,2),191=>8629,192=>8501,193=>8465,194=>8476,195=>8472,196=>8855,197=>8853,198=>8709,199=>array(8745,2),201=>8835,202=>8839,203=>8836,204=>8834,205=>8838,206=>array(8712,2),208=>8736,209=>8711,210=>63194,211=>63193,212=>63195,213=>8719,214=>8730,215=>8901,216=>172,217=>array(8743,2),219=>8660,220=>array(8656,4),224=>9674,225=>9001,226=>array(63720,3),229=>8721,230=>array(63723,10),241=>9002,242=>8747,243=>8992,244=>63733,245=>8993,246=>array(63734,9)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/times.php b/share/pnp/application/vendor/fpdf/font/times.php old mode 100755 new mode 100644 index d3ea808..f78850f --- a/share/pnp/application/vendor/fpdf/font/times.php +++ b/share/pnp/application/vendor/fpdf/font/times.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>564,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>722,chr(222)=>556,chr(223)=>500,chr(224)=>444,chr(225)=>444,chr(226)=>444,chr(227)=>444,chr(228)=>444,chr(229)=>444,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500, chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>564,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>500,chr(254)=>500,chr(255)=>500); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/timesb.php b/share/pnp/application/vendor/fpdf/font/timesb.php old mode 100755 new mode 100644 index 1c198f0..0516750 --- a/share/pnp/application/vendor/fpdf/font/timesb.php +++ b/share/pnp/application/vendor/fpdf/font/timesb.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>570,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>722,chr(222)=>611,chr(223)=>556,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556, chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/timesbi.php b/share/pnp/application/vendor/fpdf/font/timesbi.php old mode 100755 new mode 100644 index a6034b2..32fe25e --- a/share/pnp/application/vendor/fpdf/font/timesbi.php +++ b/share/pnp/application/vendor/fpdf/font/timesbi.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>944,chr(199)=>667,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>570,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>611,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556, chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>444,chr(254)=>500,chr(255)=>444); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/timesi.php b/share/pnp/application/vendor/fpdf/font/timesi.php old mode 100755 new mode 100644 index bd9e0d9..b0e5a62 --- a/share/pnp/application/vendor/fpdf/font/timesi.php +++ b/share/pnp/application/vendor/fpdf/font/timesi.php @@ -16,4 +16,6 @@ $cw = array( chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>667,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>675,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, chr(220)=>722,chr(221)=>556,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500, chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>675,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>444,chr(254)=>500,chr(255)=>444); +$enc = 'cp1252'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96)); ?> diff --git a/share/pnp/application/vendor/fpdf/font/zapfdingbats.php b/share/pnp/application/vendor/fpdf/font/zapfdingbats.php old mode 100755 new mode 100644 index afef4d3..b9d0309 --- a/share/pnp/application/vendor/fpdf/font/zapfdingbats.php +++ b/share/pnp/application/vendor/fpdf/font/zapfdingbats.php @@ -16,4 +16,5 @@ $cw = array( chr(198)=>788,chr(199)=>788,chr(200)=>788,chr(201)=>788,chr(202)=>788,chr(203)=>788,chr(204)=>788,chr(205)=>788,chr(206)=>788,chr(207)=>788,chr(208)=>788,chr(209)=>788,chr(210)=>788,chr(211)=>788,chr(212)=>894,chr(213)=>838,chr(214)=>1016,chr(215)=>458,chr(216)=>748,chr(217)=>924,chr(218)=>748,chr(219)=>918, chr(220)=>927,chr(221)=>928,chr(222)=>928,chr(223)=>834,chr(224)=>873,chr(225)=>828,chr(226)=>924,chr(227)=>924,chr(228)=>917,chr(229)=>930,chr(230)=>931,chr(231)=>463,chr(232)=>883,chr(233)=>836,chr(234)=>836,chr(235)=>867,chr(236)=>867,chr(237)=>696,chr(238)=>696,chr(239)=>874,chr(240)=>0,chr(241)=>874, chr(242)=>760,chr(243)=>946,chr(244)=>771,chr(245)=>865,chr(246)=>771,chr(247)=>888,chr(248)=>967,chr(249)=>888,chr(250)=>831,chr(251)=>873,chr(252)=>927,chr(253)=>970,chr(254)=>918,chr(255)=>0); +$uv = array(32=>32,33=>array(9985,4),37=>9742,38=>array(9990,4),42=>9755,43=>9758,44=>array(9996,28),72=>9733,73=>array(10025,35),108=>9679,109=>10061,110=>9632,111=>array(10063,4),115=>9650,116=>9660,117=>9670,118=>10070,119=>9687,120=>array(10072,7),128=>array(10088,14),161=>array(10081,7),168=>9827,169=>9830,170=>9829,171=>9824,172=>array(9312,10),182=>array(10102,31),213=>8594,214=>array(8596,2),216=>array(10136,24),241=>array(10161,14)); ?> diff --git a/share/pnp/application/vendor/fpdf/fpdf.php b/share/pnp/application/vendor/fpdf/fpdf.php old mode 100755 new mode 100644 index 0dd1cb6..cfc0959 --- a/share/pnp/application/vendor/fpdf/fpdf.php +++ b/share/pnp/application/vendor/fpdf/fpdf.php @@ -2,91 +2,90 @@ /******************************************************************************* * FPDF * * * -* Version: 1.7 * -* Date: 2011-06-18 * +* Version: 1.81 * +* Date: 2015-12-20 * * Author: Olivier PLATHEY * *******************************************************************************/ -define('FPDF_VERSION','1.7'); +define('FPDF_VERSION','1.81'); class FPDF { -var $page; // current page number -var $n; // current object number -var $offsets; // array of object offsets -var $buffer; // buffer holding in-memory PDF -var $pages; // array containing pages -var $state; // current document state -var $compress; // compression flag -var $k; // scale factor (number of points in user unit) -var $DefOrientation; // default orientation -var $CurOrientation; // current orientation -var $StdPageSizes; // standard page sizes -var $DefPageSize; // default page size -var $CurPageSize; // current page size -var $PageSizes; // used for pages with non default sizes or orientations -var $wPt, $hPt; // dimensions of current page in points -var $w, $h; // dimensions of current page in user unit -var $lMargin; // left margin -var $tMargin; // top margin -var $rMargin; // right margin -var $bMargin; // page break margin -var $cMargin; // cell margin -var $x, $y; // current position in user unit -var $lasth; // height of last printed cell -var $LineWidth; // line width in user unit -var $fontpath; // path containing fonts -var $CoreFonts; // array of core font names -var $fonts; // array of used fonts -var $FontFiles; // array of font files -var $diffs; // array of encoding differences -var $FontFamily; // current font family -var $FontStyle; // current font style -var $underline; // underlining flag -var $CurrentFont; // current font info -var $FontSizePt; // current font size in points -var $FontSize; // current font size in user unit -var $DrawColor; // commands for drawing color -var $FillColor; // commands for filling color -var $TextColor; // commands for text color -var $ColorFlag; // indicates whether fill and text colors are different -var $ws; // word spacing -var $images; // array of used images -var $PageLinks; // array of links in pages -var $links; // array of internal links -var $AutoPageBreak; // automatic page breaking -var $PageBreakTrigger; // threshold used to trigger page breaks -var $InHeader; // flag set when processing header -var $InFooter; // flag set when processing footer -var $ZoomMode; // zoom display mode -var $LayoutMode; // layout display mode -var $title; // title -var $subject; // subject -var $author; // author -var $keywords; // keywords -var $creator; // creator -var $AliasNbPages; // alias for total number of pages -var $PDFVersion; // PDF version number +protected $page; // current page number +protected $n; // current object number +protected $offsets; // array of object offsets +protected $buffer; // buffer holding in-memory PDF +protected $pages; // array containing pages +protected $state; // current document state +protected $compress; // compression flag +protected $k; // scale factor (number of points in user unit) +protected $DefOrientation; // default orientation +protected $CurOrientation; // current orientation +protected $StdPageSizes; // standard page sizes +protected $DefPageSize; // default page size +protected $CurPageSize; // current page size +protected $CurRotation; // current page rotation +protected $PageInfo; // page-related data +protected $wPt, $hPt; // dimensions of current page in points +protected $w, $h; // dimensions of current page in user unit +protected $lMargin; // left margin +protected $tMargin; // top margin +protected $rMargin; // right margin +protected $bMargin; // page break margin +protected $cMargin; // cell margin +protected $x, $y; // current position in user unit +protected $lasth; // height of last printed cell +protected $LineWidth; // line width in user unit +protected $fontpath; // path containing fonts +protected $CoreFonts; // array of core font names +protected $fonts; // array of used fonts +protected $FontFiles; // array of font files +protected $encodings; // array of encodings +protected $cmaps; // array of ToUnicode CMaps +protected $FontFamily; // current font family +protected $FontStyle; // current font style +protected $underline; // underlining flag +protected $CurrentFont; // current font info +protected $FontSizePt; // current font size in points +protected $FontSize; // current font size in user unit +protected $DrawColor; // commands for drawing color +protected $FillColor; // commands for filling color +protected $TextColor; // commands for text color +protected $ColorFlag; // indicates whether fill and text colors are different +protected $WithAlpha; // indicates whether alpha channel is used +protected $ws; // word spacing +protected $images; // array of used images +protected $PageLinks; // array of links in pages +protected $links; // array of internal links +protected $AutoPageBreak; // automatic page breaking +protected $PageBreakTrigger; // threshold used to trigger page breaks +protected $InHeader; // flag set when processing header +protected $InFooter; // flag set when processing footer +protected $AliasNbPages; // alias for total number of pages +protected $ZoomMode; // zoom display mode +protected $LayoutMode; // layout display mode +protected $metadata; // document properties +protected $PDFVersion; // PDF version number /******************************************************************************* -* * * Public methods * -* * *******************************************************************************/ -function FPDF($orientation='P', $unit='mm', $size='A4') + +function __construct($orientation='P', $unit='mm', $size='A4') { // Some checks $this->_dochecks(); // Initialization of properties + $this->state = 0; $this->page = 0; $this->n = 2; $this->buffer = ''; $this->pages = array(); - $this->PageSizes = array(); - $this->state = 0; + $this->PageInfo = array(); $this->fonts = array(); $this->FontFiles = array(); - $this->diffs = array(); + $this->encodings = array(); + $this->cmaps = array(); $this->images = array(); $this->links = array(); $this->InHeader = false; @@ -100,6 +99,7 @@ function FPDF($orientation='P', $unit='mm', $size='A4') $this->FillColor = '0 g'; $this->TextColor = '0 g'; $this->ColorFlag = false; + $this->WithAlpha = false; $this->ws = 0; // Font path if(defined('FPDF_FONTPATH')) @@ -150,6 +150,8 @@ function FPDF($orientation='P', $unit='mm', $size='A4') $this->CurOrientation = $this->DefOrientation; $this->wPt = $this->w*$this->k; $this->hPt = $this->h*$this->k; + // Page rotation + $this->CurRotation = 0; // Page margins (1 cm) $margin = 28.35/$this->k; $this->SetMargins($margin,$margin); @@ -230,41 +232,31 @@ function SetCompression($compress) function SetTitle($title, $isUTF8=false) { // Title of document - if($isUTF8) - $title = $this->_UTF8toUTF16($title); - $this->title = $title; -} - -function SetSubject($subject, $isUTF8=false) -{ - // Subject of document - if($isUTF8) - $subject = $this->_UTF8toUTF16($subject); - $this->subject = $subject; + $this->metadata['Title'] = $isUTF8 ? $title : utf8_encode($title); } function SetAuthor($author, $isUTF8=false) { // Author of document - if($isUTF8) - $author = $this->_UTF8toUTF16($author); - $this->author = $author; + $this->metadata['Author'] = $isUTF8 ? $author : utf8_encode($author); +} + +function SetSubject($subject, $isUTF8=false) +{ + // Subject of document + $this->metadata['Subject'] = $isUTF8 ? $subject : utf8_encode($subject); } function SetKeywords($keywords, $isUTF8=false) { // Keywords of document - if($isUTF8) - $keywords = $this->_UTF8toUTF16($keywords); - $this->keywords = $keywords; + $this->metadata['Keywords'] = $isUTF8 ? $keywords : utf8_encode($keywords); } function SetCreator($creator, $isUTF8=false) { // Creator of document - if($isUTF8) - $creator = $this->_UTF8toUTF16($creator); - $this->creator = $creator; + $this->metadata['Creator'] = $isUTF8 ? $creator : utf8_encode($creator); } function AliasNbPages($alias='{nb}') @@ -276,13 +268,7 @@ function AliasNbPages($alias='{nb}') function Error($msg) { // Fatal error - die('FPDF error: '.$msg); -} - -function Open() -{ - // Begin document - $this->state = 1; + throw new Exception('FPDF error: '.$msg); } function Close() @@ -302,11 +288,11 @@ function Close() $this->_enddoc(); } -function AddPage($orientation='', $size='') +function AddPage($orientation='', $size='', $rotation=0) { // Start a new page - if($this->state==0) - $this->Open(); + if($this->state==3) + $this->Error('The document is closed'); $family = $this->FontFamily; $style = $this->FontStyle.($this->underline ? 'U' : ''); $fontsize = $this->FontSizePt; @@ -325,7 +311,7 @@ function AddPage($orientation='', $size='') $this->_endpage(); } // Start new page - $this->_beginpage($orientation,$size); + $this->_beginpage($orientation,$size,$rotation); // Set line cap style to square $this->_out('2 J'); // Set line width @@ -472,17 +458,6 @@ function AddFont($family, $style='', $file='') return; $info = $this->_loadfont($file); $info['i'] = count($this->fonts)+1; - if(!empty($info['diff'])) - { - // Search existing encodings - $n = array_search($info['diff'],$this->diffs); - if(!$n) - { - $n = count($this->diffs)+1; - $this->diffs[$n] = $info['diff']; - } - $info['diffn'] = $n; - } if(!empty($info['file'])) { // Embedded font @@ -582,6 +557,8 @@ function Link($x, $y, $w, $h, $link) function Text($x, $y, $txt) { // Output a string + if(!isset($this->CurrentFont)) + $this->Error('No font has been set'); $s = sprintf('BT %.2F %.2F Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt)); if($this->underline && $txt!='') $s .= ' '.$this->_dounderline($x,$y,$txt); @@ -610,7 +587,7 @@ function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link $this->ws = 0; $this->_out('0 Tw'); } - $this->AddPage($this->CurOrientation,$this->CurPageSize); + $this->AddPage($this->CurOrientation,$this->CurPageSize,$this->CurRotation); $this->x = $x; if($ws>0) { @@ -644,6 +621,8 @@ function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link } if($txt!=='') { + if(!isset($this->CurrentFont)) + $this->Error('No font has been set'); if($align=='R') $dx = $w-$this->cMargin-$this->GetStringWidth($txt); elseif($align=='C') @@ -652,8 +631,7 @@ function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link $dx = $this->cMargin; if($this->ColorFlag) $s .= 'q '.$this->TextColor.' '; - $txt2 = str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt))); - $s .= sprintf('BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2); + $s .= sprintf('BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$this->_escape($txt)); if($this->underline) $s .= ' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt); if($this->ColorFlag) @@ -678,6 +656,8 @@ function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false) { // Output text with automatic or explicit line breaks + if(!isset($this->CurrentFont)) + $this->Error('No font has been set'); $cw = &$this->CurrentFont['cw']; if($w==0) $w = $this->w-$this->rMargin-$this->x; @@ -791,6 +771,8 @@ function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false) function Write($h, $txt, $link='') { // Output text in flowing mode + if(!isset($this->CurrentFont)) + $this->Error('No font has been set'); $cw = &$this->CurrentFont['cw']; $w = $this->w-$this->rMargin-$this->x; $wmax = ($w-2*$this->cMargin)*1000/$this->FontSize; @@ -808,7 +790,7 @@ function Write($h, $txt, $link='') if($c=="\n") { // Explicit line break - $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link); + $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',false,$link); $i++; $sep = -1; $j = $i; @@ -843,11 +825,11 @@ function Write($h, $txt, $link='') } if($i==$j) $i++; - $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link); + $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',false,$link); } else { - $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link); + $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',false,$link); $i = $sep+1; } $sep = -1; @@ -866,12 +848,12 @@ function Write($h, $txt, $link='') } // Last chunk if($i!=$j) - $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link); + $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',false,$link); } function Ln($h=null) { - // Line feed; default value is last cell height + // Line feed; default value is the last cell height $this->x = $this->lMargin; if($h===null) $this->y += $this->lasth; @@ -882,6 +864,8 @@ function Ln($h=null) function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='') { // Put an image on the page + if($file=='') + $this->Error('Image file name is empty'); if(!isset($this->images[$file])) { // First use of this image, get info @@ -928,7 +912,7 @@ function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='') { // Automatic page break $x2 = $this->x; - $this->AddPage($this->CurOrientation,$this->CurPageSize); + $this->AddPage($this->CurOrientation,$this->CurPageSize,$this->CurRotation); $this->x = $x2; } $y = $this->y; @@ -942,6 +926,18 @@ function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='') $this->Link($x,$y,$w,$h,$link); } +function GetPageWidth() +{ + // Get current page width + return $this->w; +} + +function GetPageHeight() +{ + // Get current page height + return $this->h; +} + function GetX() { // Get x position @@ -963,40 +959,40 @@ function GetY() return $this->y; } -function SetY($y) +function SetY($y, $resetX=true) { - // Set y position and reset x - $this->x = $this->lMargin; + // Set y position and optionally reset x if($y>=0) $this->y = $y; else $this->y = $this->h+$y; + if($resetX) + $this->x = $this->lMargin; } function SetXY($x, $y) { // Set x and y positions - $this->SetY($y); $this->SetX($x); + $this->SetY($y,false); } -function Output($name='', $dest='') +function Output($dest='', $name='', $isUTF8=false) { // Output PDF to some destination - if($this->state<3) - $this->Close(); - $dest = strtoupper($dest); - if($dest=='') + $this->Close(); + if(strlen($name)==1 && strlen($dest)!=1) { - if($name=='') - { - $name = 'doc.pdf'; - $dest = 'I'; - } - else - $dest = 'F'; + // Fix parameter order + $tmp = $dest; + $dest = $name; + $name = $tmp; } - switch($dest) + if($dest=='') + $dest = 'I'; + if($name=='') + $name = 'doc.pdf'; + switch(strtoupper($dest)) { case 'I': // Send to standard output @@ -1005,7 +1001,7 @@ function Output($name='', $dest='') { // We send to a browser header('Content-Type: application/pdf'); - header('Content-Disposition: inline; filename="'.$name.'"'); + header('Content-Disposition: inline; '.$this->_httpencode('filename',$name,$isUTF8)); header('Cache-Control: private, max-age=0, must-revalidate'); header('Pragma: public'); } @@ -1015,18 +1011,15 @@ function Output($name='', $dest='') // Download file $this->_checkoutput(); header('Content-Type: application/x-download'); - header('Content-Disposition: attachment; filename="'.$name.'"'); + header('Content-Disposition: attachment; '.$this->_httpencode('filename',$name,$isUTF8)); header('Cache-Control: private, max-age=0, must-revalidate'); header('Pragma: public'); echo $this->buffer; break; case 'F': // Save to local file - $f = fopen($name,'wb'); - if(!$f) + if(!file_put_contents($name,$this->buffer)) $this->Error('Unable to create output file: '.$name); - fwrite($f,$this->buffer,strlen($this->buffer)); - fclose($f); break; case 'S': // Return as a string @@ -1038,15 +1031,11 @@ function Output($name='', $dest='') } /******************************************************************************* -* * * Protected methods * -* * *******************************************************************************/ -function _dochecks() + +protected function _dochecks() { - // Check availability of %F - if(sprintf('%.1F',1.0)!='1.0') - $this->Error('This version of PHP is not supported'); // Check mbstring overloading if(ini_get('mbstring.func_overload') & 2) $this->Error('mbstring overloading must be disabled'); @@ -1055,7 +1044,7 @@ function _dochecks() @set_magic_quotes_runtime(0); } -function _checkoutput() +protected function _checkoutput() { if(PHP_SAPI!='cli') { @@ -1075,7 +1064,7 @@ function _checkoutput() } } -function _getpagesize($size) +protected function _getpagesize($size) { if(is_string($size)) { @@ -1094,7 +1083,7 @@ function _getpagesize($size) } } -function _beginpage($orientation, $size) +protected function _beginpage($orientation, $size, $rotation) { $this->page++; $this->pages[$this->page] = ''; @@ -1131,41 +1120,62 @@ function _beginpage($orientation, $size) $this->CurPageSize = $size; } if($orientation!=$this->DefOrientation || $size[0]!=$this->DefPageSize[0] || $size[1]!=$this->DefPageSize[1]) - $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); + $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt); + if($rotation!=0) + { + if($rotation%90!=0) + $this->Error('Incorrect rotation value: '.$rotation); + $this->CurRotation = $rotation; + $this->PageInfo[$this->page]['rotation'] = $rotation; + } } -function _endpage() +protected function _endpage() { $this->state = 1; } -function _loadfont($font) +protected function _loadfont($font) { // Load a font definition file from the font directory + if(strpos($font,'/')!==false || strpos($font,"\\")!==false) + $this->Error('Incorrect font definition file name: '.$font); include($this->fontpath.$font); - $a = get_defined_vars(); - if(!isset($a['name'])) + if(!isset($name)) $this->Error('Could not include font definition file'); - return $a; + if(isset($enc)) + $enc = strtolower($enc); + if(!isset($subsetted)) + $subsetted = false; + return get_defined_vars(); } -function _escape($s) +protected function _isascii($s) { - // Escape special characters in strings - $s = str_replace('\\','\\\\',$s); - $s = str_replace('(','\\(',$s); - $s = str_replace(')','\\)',$s); - $s = str_replace("\r",'\\r',$s); - return $s; + // Test if string is ASCII + $nb = strlen($s); + for($i=0;$i<$nb;$i++) + { + if(ord($s[$i])>127) + return false; + } + return true; } -function _textstring($s) +protected function _httpencode($param, $value, $isUTF8) { - // Format a text string - return '('.$this->_escape($s).')'; + // Encode HTTP header field parameter + if($this->_isascii($value)) + return $param.'="'.$value.'"'; + if(!$isUTF8) + $value = utf8_encode($value); + if(strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')!==false) + return $param.'="'.rawurlencode($value).'"'; + else + return $param."*=UTF-8''".rawurlencode($value); } -function _UTF8toUTF16($s) +protected function _UTF8toUTF16($s) { // Convert UTF-8 to UTF-16BE with BOM $res = "\xFE\xFF"; @@ -1198,7 +1208,24 @@ function _UTF8toUTF16($s) return $res; } -function _dounderline($x, $y, $txt) +protected function _escape($s) +{ + // Escape special characters + if(strpos($s,'(')!==false || strpos($s,')')!==false || strpos($s,'\\')!==false || strpos($s,"\r")!==false) + return str_replace(array('\\','(',')',"\r"), array('\\\\','\\(','\\)','\\r'), $s); + else + return $s; +} + +protected function _textstring($s) +{ + // Format a text string + if(!$this->_isascii($s)) + $s = $this->_UTF8toUTF16($s); + return '('.$this->_escape($s).')'; +} + +protected function _dounderline($x, $y, $txt) { // Underline text $up = $this->CurrentFont['up']; @@ -1207,7 +1234,7 @@ function _dounderline($x, $y, $txt) return sprintf('%.2F %.2F %.2F %.2F re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt); } -function _parsejpg($file) +protected function _parsejpg($file) { // Extract info from a JPEG file $a = getimagesize($file); @@ -1226,7 +1253,7 @@ function _parsejpg($file) return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data); } -function _parsepng($file) +protected function _parsepng($file) { // Extract info from a PNG file $f = fopen($file,'rb'); @@ -1237,7 +1264,7 @@ function _parsepng($file) return $info; } -function _parsepngstream($f, $file) +protected function _parsepngstream($f, $file) { // Check signature if($this->_readstream($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) @@ -1355,6 +1382,7 @@ function _parsepngstream($f, $file) unset($data); $data = gzcompress($color); $info['smask'] = gzcompress($alpha); + $this->WithAlpha = true; if($this->PDFVersion<'1.4') $this->PDFVersion = '1.4'; } @@ -1362,7 +1390,7 @@ function _parsepngstream($f, $file) return $info; } -function _readstream($f, $n) +protected function _readstream($f, $n) { // Read n bytes from stream $res = ''; @@ -1379,14 +1407,14 @@ function _readstream($f, $n) return $res; } -function _readint($f) +protected function _readint($f) { // Read a 4-byte integer from stream $a = unpack('Ni',$this->_readstream($f,4)); return $a['i']; } -function _parsegif($file) +protected function _parsegif($file) { // Extract info from a GIF file (via PNG conversion) if(!function_exists('imagepng')) @@ -1397,141 +1425,149 @@ function _parsegif($file) if(!$im) $this->Error('Missing or incorrect image file: '.$file); imageinterlace($im,0); - $f = @fopen('php://temp','rb+'); - if($f) - { - // Perform conversion in memory - ob_start(); - imagepng($im); - $data = ob_get_clean(); - imagedestroy($im); - fwrite($f,$data); - rewind($f); - $info = $this->_parsepngstream($f,$file); - fclose($f); - } - else - { - // Use temporary file - $tmp = tempnam('.','gif'); - if(!$tmp) - $this->Error('Unable to create a temporary file'); - if(!imagepng($im,$tmp)) - $this->Error('Error while saving to temporary file'); - imagedestroy($im); - $info = $this->_parsepng($tmp); - unlink($tmp); - } + ob_start(); + imagepng($im); + $data = ob_get_clean(); + imagedestroy($im); + $f = fopen('php://temp','rb+'); + if(!$f) + $this->Error('Unable to create memory stream'); + fwrite($f,$data); + rewind($f); + $info = $this->_parsepngstream($f,$file); + fclose($f); return $info; } -function _newobj() -{ - // Begin a new object - $this->n++; - $this->offsets[$this->n] = strlen($this->buffer); - $this->_out($this->n.' 0 obj'); -} - -function _putstream($s) -{ - $this->_out('stream'); - $this->_out($s); - $this->_out('endstream'); -} - -function _out($s) +protected function _out($s) { // Add a line to the document if($this->state==2) $this->pages[$this->page] .= $s."\n"; - else - $this->buffer .= $s."\n"; + elseif($this->state==1) + $this->_put($s); + elseif($this->state==0) + $this->Error('No page has been added yet'); + elseif($this->state==3) + $this->Error('The document is closed'); } -function _putpages() +protected function _put($s) +{ + $this->buffer .= $s."\n"; +} + +protected function _getoffset() +{ + return strlen($this->buffer); +} + +protected function _newobj($n=null) +{ + // Begin a new object + if($n===null) + $n = ++$this->n; + $this->offsets[$n] = $this->_getoffset(); + $this->_put($n.' 0 obj'); +} + +protected function _putstream($data) +{ + $this->_put('stream'); + $this->_put($data); + $this->_put('endstream'); +} + +protected function _putstreamobject($data) +{ + if($this->compress) + { + $entries = '/Filter /FlateDecode '; + $data = gzcompress($data); + } + else + $entries = ''; + $entries .= '/Length '.strlen($data); + $this->_newobj(); + $this->_put('<<'.$entries.'>>'); + $this->_putstream($data); + $this->_put('endobj'); +} + +protected function _putpage($n) +{ + $this->_newobj(); + $this->_put('<_put('/Parent 1 0 R'); + if(isset($this->PageInfo[$n]['size'])) + $this->_put(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageInfo[$n]['size'][0],$this->PageInfo[$n]['size'][1])); + if(isset($this->PageInfo[$n]['rotation'])) + $this->_put('/Rotate '.$this->PageInfo[$n]['rotation']); + $this->_put('/Resources 2 0 R'); + if(isset($this->PageLinks[$n])) + { + // Links + $annots = '/Annots ['; + foreach($this->PageLinks[$n] as $pl) + { + $rect = sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]); + $annots .= '<_textstring($pl[4]).'>>>>'; + else + { + $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; + $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',$this->PageInfo[$l[0]]['n'],$h-$l[1]*$this->k); + } + } + $this->_put($annots.']'); + } + if($this->WithAlpha) + $this->_put('/Group <>'); + $this->_put('/Contents '.($this->n+1).' 0 R>>'); + $this->_put('endobj'); + // Page content + if(!empty($this->AliasNbPages)) + $this->pages[$n] = str_replace($this->AliasNbPages,$this->page,$this->pages[$n]); + $this->_putstreamobject($this->pages[$n]); +} + +protected function _putpages() { $nb = $this->page; - if(!empty($this->AliasNbPages)) - { - // Replace number of pages - for($n=1;$n<=$nb;$n++) - $this->pages[$n] = str_replace($this->AliasNbPages,$nb,$this->pages[$n]); - } + for($n=1;$n<=$nb;$n++) + $this->PageInfo[$n]['n'] = $this->n+1+2*($n-1); + for($n=1;$n<=$nb;$n++) + $this->_putpage($n); + // Pages root + $this->_newobj(1); + $this->_put('<PageInfo[$n]['n'].' 0 R '; + $this->_put($kids.']'); + $this->_put('/Count '.$nb); if($this->DefOrientation=='P') { - $wPt = $this->DefPageSize[0]*$this->k; - $hPt = $this->DefPageSize[1]*$this->k; + $w = $this->DefPageSize[0]; + $h = $this->DefPageSize[1]; } else { - $wPt = $this->DefPageSize[1]*$this->k; - $hPt = $this->DefPageSize[0]*$this->k; + $w = $this->DefPageSize[1]; + $h = $this->DefPageSize[0]; } - $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; - for($n=1;$n<=$nb;$n++) - { - // Page - $this->_newobj(); - $this->_out('<_out('/Parent 1 0 R'); - if(isset($this->PageSizes[$n])) - $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageSizes[$n][0],$this->PageSizes[$n][1])); - $this->_out('/Resources 2 0 R'); - if(isset($this->PageLinks[$n])) - { - // Links - $annots = '/Annots ['; - foreach($this->PageLinks[$n] as $pl) - { - $rect = sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]); - $annots .= '<_textstring($pl[4]).'>>>>'; - else - { - $l = $this->links[$pl[4]]; - $h = isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt; - $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',1+2*$l[0],$h-$l[1]*$this->k); - } - } - $this->_out($annots.']'); - } - if($this->PDFVersion>'1.3') - $this->_out('/Group <>'); - $this->_out('/Contents '.($this->n+1).' 0 R>>'); - $this->_out('endobj'); - // Page content - $p = ($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n]; - $this->_newobj(); - $this->_out('<<'.$filter.'/Length '.strlen($p).'>>'); - $this->_putstream($p); - $this->_out('endobj'); - } - // Pages root - $this->offsets[1] = strlen($this->buffer); - $this->_out('1 0 obj'); - $this->_out('<_out($kids.']'); - $this->_out('/Count '.$nb); - $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt)); - $this->_out('>>'); - $this->_out('endobj'); + $this->_put(sprintf('/MediaBox [0 0 %.2F %.2F]',$w*$this->k,$h*$this->k)); + $this->_put('>>'); + $this->_put('endobj'); } -function _putfonts() +protected function _putfonts() { - $nf = $this->n; - foreach($this->diffs as $diff) - { - // Encodings - $this->_newobj(); - $this->_out('<>'); - $this->_out('endobj'); - } foreach($this->FontFiles as $file=>$info) { // Font file embedding @@ -1543,58 +1579,89 @@ function _putfonts() $compressed = (substr($file,-2)=='.z'); if(!$compressed && isset($info['length2'])) $font = substr($font,6,$info['length1']).substr($font,6+$info['length1']+6,$info['length2']); - $this->_out('<_put('<_out('/Filter /FlateDecode'); - $this->_out('/Length1 '.$info['length1']); + $this->_put('/Filter /FlateDecode'); + $this->_put('/Length1 '.$info['length1']); if(isset($info['length2'])) - $this->_out('/Length2 '.$info['length2'].' /Length3 0'); - $this->_out('>>'); + $this->_put('/Length2 '.$info['length2'].' /Length3 0'); + $this->_put('>>'); $this->_putstream($font); - $this->_out('endobj'); + $this->_put('endobj'); } foreach($this->fonts as $k=>$font) { - // Font objects + // Encoding + if(isset($font['diff'])) + { + if(!isset($this->encodings[$font['enc']])) + { + $this->_newobj(); + $this->_put('<>'); + $this->_put('endobj'); + $this->encodings[$font['enc']] = $this->n; + } + } + // ToUnicode CMap + if(isset($font['uv'])) + { + if(isset($font['enc'])) + $cmapkey = $font['enc']; + else + $cmapkey = $font['name']; + if(!isset($this->cmaps[$cmapkey])) + { + $cmap = $this->_tounicodecmap($font['uv']); + $this->_putstreamobject($cmap); + $this->cmaps[$cmapkey] = $this->n; + } + } + // Font object $this->fonts[$k]['n'] = $this->n+1; $type = $font['type']; $name = $font['name']; + if($font['subsetted']) + $name = 'AAAAAA+'.$name; if($type=='Core') { // Core font $this->_newobj(); - $this->_out('<_out('/BaseFont /'.$name); - $this->_out('/Subtype /Type1'); + $this->_put('<_put('/BaseFont /'.$name); + $this->_put('/Subtype /Type1'); if($name!='Symbol' && $name!='ZapfDingbats') - $this->_out('/Encoding /WinAnsiEncoding'); - $this->_out('>>'); - $this->_out('endobj'); + $this->_put('/Encoding /WinAnsiEncoding'); + if(isset($font['uv'])) + $this->_put('/ToUnicode '.$this->cmaps[$cmapkey].' 0 R'); + $this->_put('>>'); + $this->_put('endobj'); } elseif($type=='Type1' || $type=='TrueType') { // Additional Type1 or TrueType/OpenType font $this->_newobj(); - $this->_out('<_out('/BaseFont /'.$name); - $this->_out('/Subtype /'.$type); - $this->_out('/FirstChar 32 /LastChar 255'); - $this->_out('/Widths '.($this->n+1).' 0 R'); - $this->_out('/FontDescriptor '.($this->n+2).' 0 R'); - if(isset($font['diffn'])) - $this->_out('/Encoding '.($nf+$font['diffn']).' 0 R'); + $this->_put('<_put('/BaseFont /'.$name); + $this->_put('/Subtype /'.$type); + $this->_put('/FirstChar 32 /LastChar 255'); + $this->_put('/Widths '.($this->n+1).' 0 R'); + $this->_put('/FontDescriptor '.($this->n+2).' 0 R'); + if(isset($font['diff'])) + $this->_put('/Encoding '.$this->encodings[$font['enc']].' 0 R'); else - $this->_out('/Encoding /WinAnsiEncoding'); - $this->_out('>>'); - $this->_out('endobj'); + $this->_put('/Encoding /WinAnsiEncoding'); + if(isset($font['uv'])) + $this->_put('/ToUnicode '.$this->cmaps[$cmapkey].' 0 R'); + $this->_put('>>'); + $this->_put('endobj'); // Widths $this->_newobj(); $cw = &$font['cw']; $s = '['; for($i=32;$i<=255;$i++) $s .= $cw[chr($i)].' '; - $this->_out($s.']'); - $this->_out('endobj'); + $this->_put($s.']'); + $this->_put('endobj'); // Descriptor $this->_newobj(); $s = '<FontFiles[$font['file']]['n'].' 0 R'; - $this->_out($s.'>>'); - $this->_out('endobj'); + $this->_put($s.'>>'); + $this->_put('endobj'); } else { @@ -1616,7 +1683,58 @@ function _putfonts() } } -function _putimages() +protected function _tounicodecmap($uv) +{ + $ranges = ''; + $nbr = 0; + $chars = ''; + $nbc = 0; + foreach($uv as $c=>$v) + { + if(is_array($v)) + { + $ranges .= sprintf("<%02X> <%02X> <%04X>\n",$c,$c+$v[1]-1,$v[0]); + $nbr++; + } + else + { + $chars .= sprintf("<%02X> <%04X>\n",$c,$v); + $nbc++; + } + } + $s = "/CIDInit /ProcSet findresource begin\n"; + $s .= "12 dict begin\n"; + $s .= "begincmap\n"; + $s .= "/CIDSystemInfo\n"; + $s .= "<0) + { + $s .= "$nbr beginbfrange\n"; + $s .= $ranges; + $s .= "endbfrange\n"; + } + if($nbc>0) + { + $s .= "$nbc beginbfchar\n"; + $s .= $chars; + $s .= "endbfchar\n"; + } + $s .= "endcmap\n"; + $s .= "CMapName currentdict /CMap defineresource pop\n"; + $s .= "end\n"; + $s .= "end"; + return $s; +} + +protected function _putimages() { foreach(array_keys($this->images) as $file) { @@ -1626,39 +1744,39 @@ function _putimages() } } -function _putimage(&$info) +protected function _putimage(&$info) { $this->_newobj(); $info['n'] = $this->n; - $this->_out('<_out('/Subtype /Image'); - $this->_out('/Width '.$info['w']); - $this->_out('/Height '.$info['h']); + $this->_put('<_put('/Subtype /Image'); + $this->_put('/Width '.$info['w']); + $this->_put('/Height '.$info['h']); if($info['cs']=='Indexed') - $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]'); + $this->_put('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]'); else { - $this->_out('/ColorSpace /'.$info['cs']); + $this->_put('/ColorSpace /'.$info['cs']); if($info['cs']=='DeviceCMYK') - $this->_out('/Decode [1 0 1 0 1 0 1 0]'); + $this->_put('/Decode [1 0 1 0 1 0 1 0]'); } - $this->_out('/BitsPerComponent '.$info['bpc']); + $this->_put('/BitsPerComponent '.$info['bpc']); if(isset($info['f'])) - $this->_out('/Filter /'.$info['f']); + $this->_put('/Filter /'.$info['f']); if(isset($info['dp'])) - $this->_out('/DecodeParms <<'.$info['dp'].'>>'); + $this->_put('/DecodeParms <<'.$info['dp'].'>>'); if(isset($info['trns']) && is_array($info['trns'])) { $trns = ''; for($i=0;$i_out('/Mask ['.$trns.']'); + $this->_put('/Mask ['.$trns.']'); } if(isset($info['smask'])) - $this->_out('/SMask '.($this->n+1).' 0 R'); - $this->_out('/Length '.strlen($info['data']).'>>'); + $this->_put('/SMask '.($this->n+1).' 0 R'); + $this->_put('/Length '.strlen($info['data']).'>>'); $this->_putstream($info['data']); - $this->_out('endobj'); + $this->_put('endobj'); // Soft mask if(isset($info['smask'])) { @@ -1668,137 +1786,113 @@ function _putimage(&$info) } // Palette if($info['cs']=='Indexed') - { - $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; - $pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal']; - $this->_newobj(); - $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>'); - $this->_putstream($pal); - $this->_out('endobj'); - } + $this->_putstreamobject($info['pal']); } -function _putxobjectdict() +protected function _putxobjectdict() { foreach($this->images as $image) - $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); + $this->_put('/I'.$image['i'].' '.$image['n'].' 0 R'); } -function _putresourcedict() +protected function _putresourcedict() { - $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); - $this->_out('/Font <<'); + $this->_put('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); + $this->_put('/Font <<'); foreach($this->fonts as $font) - $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); - $this->_out('>>'); - $this->_out('/XObject <<'); + $this->_put('/F'.$font['i'].' '.$font['n'].' 0 R'); + $this->_put('>>'); + $this->_put('/XObject <<'); $this->_putxobjectdict(); - $this->_out('>>'); + $this->_put('>>'); } -function _putresources() +protected function _putresources() { $this->_putfonts(); $this->_putimages(); // Resource dictionary - $this->offsets[2] = strlen($this->buffer); - $this->_out('2 0 obj'); - $this->_out('<<'); + $this->_newobj(2); + $this->_put('<<'); $this->_putresourcedict(); - $this->_out('>>'); - $this->_out('endobj'); + $this->_put('>>'); + $this->_put('endobj'); } -function _putinfo() +protected function _putinfo() { - $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION)); - if(!empty($this->title)) - $this->_out('/Title '.$this->_textstring($this->title)); - if(!empty($this->subject)) - $this->_out('/Subject '.$this->_textstring($this->subject)); - if(!empty($this->author)) - $this->_out('/Author '.$this->_textstring($this->author)); - if(!empty($this->keywords)) - $this->_out('/Keywords '.$this->_textstring($this->keywords)); - if(!empty($this->creator)) - $this->_out('/Creator '.$this->_textstring($this->creator)); - $this->_out('/CreationDate '.$this->_textstring('D:'.@date('YmdHis'))); + $this->metadata['Producer'] = 'FPDF '.FPDF_VERSION; + $this->metadata['CreationDate'] = 'D:'.@date('YmdHis'); + foreach($this->metadata as $key=>$value) + $this->_put('/'.$key.' '.$this->_textstring($value)); } -function _putcatalog() +protected function _putcatalog() { - $this->_out('/Type /Catalog'); - $this->_out('/Pages 1 0 R'); + $n = $this->PageInfo[1]['n']; + $this->_put('/Type /Catalog'); + $this->_put('/Pages 1 0 R'); if($this->ZoomMode=='fullpage') - $this->_out('/OpenAction [3 0 R /Fit]'); + $this->_put('/OpenAction ['.$n.' 0 R /Fit]'); elseif($this->ZoomMode=='fullwidth') - $this->_out('/OpenAction [3 0 R /FitH null]'); + $this->_put('/OpenAction ['.$n.' 0 R /FitH null]'); elseif($this->ZoomMode=='real') - $this->_out('/OpenAction [3 0 R /XYZ null null 1]'); + $this->_put('/OpenAction ['.$n.' 0 R /XYZ null null 1]'); elseif(!is_string($this->ZoomMode)) - $this->_out('/OpenAction [3 0 R /XYZ null null '.sprintf('%.2F',$this->ZoomMode/100).']'); + $this->_put('/OpenAction ['.$n.' 0 R /XYZ null null '.sprintf('%.2F',$this->ZoomMode/100).']'); if($this->LayoutMode=='single') - $this->_out('/PageLayout /SinglePage'); + $this->_put('/PageLayout /SinglePage'); elseif($this->LayoutMode=='continuous') - $this->_out('/PageLayout /OneColumn'); + $this->_put('/PageLayout /OneColumn'); elseif($this->LayoutMode=='two') - $this->_out('/PageLayout /TwoColumnLeft'); + $this->_put('/PageLayout /TwoColumnLeft'); } -function _putheader() +protected function _putheader() { - $this->_out('%PDF-'.$this->PDFVersion); + $this->_put('%PDF-'.$this->PDFVersion); } -function _puttrailer() +protected function _puttrailer() { - $this->_out('/Size '.($this->n+1)); - $this->_out('/Root '.$this->n.' 0 R'); - $this->_out('/Info '.($this->n-1).' 0 R'); + $this->_put('/Size '.($this->n+1)); + $this->_put('/Root '.$this->n.' 0 R'); + $this->_put('/Info '.($this->n-1).' 0 R'); } -function _enddoc() +protected function _enddoc() { $this->_putheader(); $this->_putpages(); $this->_putresources(); // Info $this->_newobj(); - $this->_out('<<'); + $this->_put('<<'); $this->_putinfo(); - $this->_out('>>'); - $this->_out('endobj'); + $this->_put('>>'); + $this->_put('endobj'); // Catalog $this->_newobj(); - $this->_out('<<'); + $this->_put('<<'); $this->_putcatalog(); - $this->_out('>>'); - $this->_out('endobj'); + $this->_put('>>'); + $this->_put('endobj'); // Cross-ref - $o = strlen($this->buffer); - $this->_out('xref'); - $this->_out('0 '.($this->n+1)); - $this->_out('0000000000 65535 f '); + $offset = $this->_getoffset(); + $this->_put('xref'); + $this->_put('0 '.($this->n+1)); + $this->_put('0000000000 65535 f '); for($i=1;$i<=$this->n;$i++) - $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i])); + $this->_put(sprintf('%010d 00000 n ',$this->offsets[$i])); // Trailer - $this->_out('trailer'); - $this->_out('<<'); + $this->_put('trailer'); + $this->_put('<<'); $this->_puttrailer(); - $this->_out('>>'); - $this->_out('startxref'); - $this->_out($o); - $this->_out('%%EOF'); + $this->_put('>>'); + $this->_put('startxref'); + $this->_put($offset); + $this->_put('%%EOF'); $this->state = 3; } -// End of class } - -// Handle special IE contype request -if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype') -{ - header('Content-Type: application/pdf'); - exit; -} - ?> diff --git a/share/pnp/application/vendor/fpdf/fpdf_tpl.php b/share/pnp/application/vendor/fpdf/fpdf_tpl.php index d829ff1..47592b2 100644 --- a/share/pnp/application/vendor/fpdf/fpdf_tpl.php +++ b/share/pnp/application/vendor/fpdf/fpdf_tpl.php @@ -1,81 +1,92 @@ page <= 0) - $this->error("You have to add a page to fpdf first!"); + 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; @@ -88,7 +99,7 @@ class FPDF_TPL extends FPDF { // Save settings $this->tpl++; - $tpl =& $this->tpls[$this->tpl]; + $tpl =& $this->_tpls[$this->tpl]; $tpl = array( 'o_x' => $this->x, 'o_y' => $this->y, @@ -99,6 +110,10 @@ class FPDF_TPL extends FPDF { '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, @@ -107,29 +122,43 @@ class FPDF_TPL extends FPDF { ); $this->SetAutoPageBreak(false); - - // Define own high and width to calculate possitions correct + + // 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); + $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 + * End template. * - * This method ends a template and reset initiated variables on beginTemplate. + * This method ends a template and reset initiated variables collected in {@link beginTemplate()}. * - * @return mixed If a template is opened, the ID is returned. If not a false is returned. + * @return int|boolean If a template is opened, the id is returned. If not a false is returned. */ - function endTemplate() { - if ($this->_intpl) { - $this->_intpl = false; - $tpl =& $this->tpls[$this->tpl]; + 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']; @@ -137,271 +166,381 @@ class FPDF_TPL extends FPDF { $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 + * 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 like you use the Image()-method. - * All parameters are optional. The width or height is calculated automaticaly + * 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() is used. + * {@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 - * @retrun array The height and width of the template + * @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 */ - function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) { - if ($this->page <= 0) - $this->error("You have to add a page to fpdf first!"); - - if (!isset($this->tpls[$tplidx])) - $this->error("Template does not exist!"); - - if ($this->_intpl) { - $this->_res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx]; + 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!'); } - - $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']; - - $tData = array( + + 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) + '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", $tData['scaleX'], $tData['scaleY'], $tData['tx']*$this->k, $tData['ty']*$this->k)); // Translate - $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); - $this->lastUsedTemplateData = $tData; - - return array("w" => $_w, "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 + * 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 + * @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' => ...)) */ - function getTemplateSize($tplidx, $_w=0, $_h=0) { - if (!$this->tpls[$tplidx]) + 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 and $_h == 0) { - $_w = $w; - $_h = $h; + $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); + if ($w == 0) + $w = $h * $_w / $_h; + if($h == 0) + $h = $w * $_h / $_w; + + return array("w" => $w, "h" => $h); } - + /** - * See FPDF/TCPDF-Documentation ;-) + * 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 */ - function SetFont($family, $style='', $size=0, $fontfile='') { - if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 3) { - $this->Error('More than 3 arguments for the SetFont method are only available in TCPDF.'); + 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); } - /** - * force the resetting of font changes in a template - */ - if ($this->_intpl) - $this->FontFamily = ''; - - parent::SetFont($family, $style, $size, $fontfile); - - $fontkey = $this->FontFamily.$this->FontStyle; - - if ($this->_intpl) { + + 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]; } } - + /** - * See FPDF/TCPDF-Documentation ;-) + * 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 */ - function Image($file, $x, $y, $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0) { - if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 7) { - $this->Error('More than 7 arguments for the Image method are only available in TCPDF.'); + 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); } - - parent::Image($file, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $ismask, $imgmask, $border); - if ($this->_intpl) { + + $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]; } - } - - /** - * See FPDF-Documentation ;-) - * - * AddPage is not available when you're "in" a template. - */ - function AddPage($orientation='', $format='') { - if ($this->_intpl) - $this->Error('Adding pages in templates isn\'t possible!'); - parent::AddPage($orientation, $format); + + return $ret; } /** - * Preserve adding Links in Templates ...won't work + * 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 */ - function Link($x, $y, $w, $h, $link, $spaces=0) { - if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 5) { - $this->Error('More than 7 arguments for the Image method are only available in TCPDF.'); + 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) - $this->Error('Using links in templates aren\'t possible!'); - parent::Link($x, $y, $w, $h, $link, $spaces); + + if ($this->_inTpl) { + throw new LogicException('Adding pages in templates is not possible!'); + } + + parent::AddPage($orientation, $format, $rotationOrKeepmargins); } - - function AddLink() { - if ($this->_intpl) - $this->Error('Adding links in templates aren\'t possible!'); + + /** + * 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(); } - - function SetLink($link, $y=0, $page=-1) { - if ($this->_intpl) - $this->Error('Setting links in templates aren\'t possible!'); + + /** + * 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); } - - /** - * Private Method that writes the form xobjects - */ - function _putformxobjects() { - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->tpls); - foreach($this->tpls AS $tplidx => $tpl) { - $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; - $this->_newobj(); - $this->tpls[$tplidx]['n'] = $this->n; - $this->_out('<<'.$filter.'/Type /XObject'); + /** + * 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'], + $tpl['x'] * $this->k, // lly - -$tpl['y'], + -$tpl['y'] * $this->k, // urx - ($tpl['w']+$tpl['x'])*$this->k, + ($tpl['w'] + $tpl['x']) * $this->k, // ury - ($tpl['h']-$tpl['y'])*$this->k + ($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 + -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 )); } - - $this->_out('/Resources '); + $this->_out('/Resources '); $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { - $this->_out('/Font <<'); - foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) - $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); - $this->_out('>>'); + + 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('>>'); + } } - if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || - isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) - { - $this->_out('/XObject <<'); - if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { - foreach($this->_res['tpl'][$tplidx]['images'] as $image) - $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); - } - if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { - foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) - $this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R'); - } - $this->_out('>>'); - } - $this->_out('>>'); - - $this->_out('/Length '.strlen($p).' >>'); - $this->_putstream($p); - $this->_out('endobj'); + + $this->_out('>>'); + + $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + $this->_out('/Length ' . strlen($buffer) . ' >>'); + $this->_putstream($buffer); + $this->_out('endobj'); } } - + /** - * Overwritten to add _putformxobjects() after _putimages() + * Output images. * + * Overwritten to add {@link _putformxobjects()} after _putimages(). */ - function _putimages() { + public function _putimages() + { parent::_putimages(); $this->_putformxobjects(); } - - function _putxobjectdict() { + + /** + * 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(); - - if (count($this->tpls)) { - foreach($this->tpls as $tplidx => $tpl) { - $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n'])); - } + + foreach($this->_tpls as $tplIdx => $tpl) { + $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n'])); } } /** - * Private Method + * Writes bytes to the resulting document. + * + * Overwritten to delegate the data to the template buffer. + * + * @param string $s */ - function _out($s) { - if ($this->state==2 && $this->_intpl) { - $this->tpls[$this->tpl]['buffer'] .= $s."\n"; + public function _out($s) + { + if ($this->state == 2 && $this->_inTpl) { + $this->_tpls[$this->tpl]['buffer'] .= $s . "\n"; } else { parent::_out($s); } diff --git a/share/pnp/application/vendor/fpdf/fpdi.php b/share/pnp/application/vendor/fpdf/fpdi.php index bd47686..926deb5 100644 --- a/share/pnp/application/vendor/fpdf/fpdi.php +++ b/share/pnp/application/vendor/fpdf/fpdi.php @@ -1,505 +1,705 @@ -current_filename = $filename; - $fn =& $this->current_filename; - - if (!isset($this->parsers[$fn])) - $this->parsers[$fn] = new fpdi_pdf_parser($fn, $this); - $this->current_parser =& $this->parsers[$fn]; - - return $this->parsers[$fn]->getPageCount(); - } - - /** - * Import a page - * - * @param int $pageno pagenumber - * @return int Index of imported page - to use with fpdf_tpl::useTemplate() - */ - function importPage($pageno, $boxName='/CropBox') { - if ($this->_intpl) { - return $this->error('Please import the desired pages before creating a new template.'); - } - - $fn =& $this->current_filename; - - // 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); - - $this->tpl++; - $this->tpls[$this->tpl] = array(); - $tpl =& $this->tpls[$this->tpl]; - $tpl['parser'] =& $parser; - $tpl['resources'] = $parser->getPageResources(); - $tpl['buffer'] = $parser->getContent(); - - if (!in_array($boxName, $parser->availableBoxes)) - return $this->Error(sprintf('Unknown box: %s', $boxName)); - $pageboxes = $parser->getPageBoxes($pageno); - - /** - * 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]; - $tpl['box'] = $box; - - // 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 everytime. Translation will be set in _putformxobjects() - $tpl['x'] = 0; - $tpl['y'] = 0; - - $page =& $parser->pages[$parser->pageno]; - - // 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; - - $tpl['_rotationAngle'] = $angle*-1; - } - - $this->_importedPages[$pageKey] = $this->tpl; - - return $this->tpl; - } - - function getLastUsedPageBox() { - return $this->lastUsedPageBox; - } - - 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); - $format = array($size['w'], $size['h']); - if ($format[0]!=$this->CurPageFormat[0] || $format[1]!=$this->CurPageFormat[1]) { - $this->w=$format[0]; - $this->h=$format[1]; - $this->wPt=$this->w*$this->k; - $this->hPt=$this->h*$this->k; - $this->PageBreakTrigger=$this->h-$this->bMargin; - $this->CurPageFormat=$format; - $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 - $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); - $this->_out('Q'); - return $s; - } - - /** - * Private method, that rebuilds all needed objects of source files - */ - function _putimportedobjects() { - if (is_array($this->parsers) && count($this->parsers) > 0) { - foreach($this->parsers AS $filename => $p) { - $this->current_parser =& $this->parsers[$filename]; - if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { - while(($n = key($this->_obj_stack[$filename])) !== null) { - $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->_obj_stack[$filename][$n][1]); - - $this->_newobj($this->_obj_stack[$filename][$n][0]); - - if ($nObj[0] == PDF_TYPE_STREAM) { - $this->pdf_write_value ($nObj); - } else { - $this->pdf_write_value ($nObj[1]); - } - - $this->_out('endobj'); - $this->_obj_stack[$filename][$n] = null; // free memory - unset($this->_obj_stack[$filename][$n]); - reset($this->_obj_stack[$filename]); - } - } - } - } - } - - - /** - * Private Method that writes the form xobjects - */ - function _putformxobjects() { - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->tpls); - foreach($this->tpls AS $tplidx => $tpl) { - $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; - $this->_newobj(); - $cN = $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 = 0; - 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->current_parser =& $tpl['parser']; - $this->pdf_write_value($tpl['resources']); // "n" will be changed - } else { - $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { - $this->_out('/Font <<'); - foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) - $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); - $this->_out('>>'); - } - if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || - isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) - { - $this->_out('/XObject <<'); - if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { - foreach($this->_res['tpl'][$tplidx]['images'] as $image) - $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); - } - if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { - foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) - $this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R'); - } - $this->_out('>>'); - } - $this->_out('>>'); - } - - $nN = $this->n; // TCPDF: rem new "n" - $this->n = $cN; // TCPDF: reset to current "n" - $this->_out('/Length '.strlen($p).' >>'); - $this->_putstream($p); - $this->_out('endobj'); - $this->n = $nN; // TCPDF: reset to new "n" - } - - $this->_putimportedobjects(); - } - - /** - * Rewritten to handle existing own defined objects - */ - function _newobj($obj_id=false,$onlynewobj=false) { - if (!$obj_id) { - $obj_id = ++$this->n; - } - - //Begin a new object - if (!$onlynewobj) { - $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); - $this->_out($obj_id.' 0 obj'); - $this->_current_obj_id = $obj_id; // for later use with encryption - } - return $obj_id; - } - - /** - * Writes a value - * Needed to rebuild the source document - * - * @param mixed $value A PDF-Value. Structure of values see cases in this method - */ - function pdf_write_value(&$value) - { - if (is_subclass_of($this, 'TCPDF')) { - parent::pdf_write_value($value); - } - - switch ($value[0]) { - - case PDF_TYPE_TOKEN : - $this->_straightOut($value[1] . ' '); - break; - case PDF_TYPE_NUMERIC : - case PDF_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_TYPE_ARRAY : - - // An array. Output the proper - // structure and move on. - - $this->_straightOut('['); - for ($i = 0; $i < count($value[1]); $i++) { - $this->pdf_write_value($value[1][$i]); - } - - $this->_out(']'); - break; - - case PDF_TYPE_DICTIONARY : - - // A dictionary. - $this->_straightOut('<<'); - - reset ($value[1]); - - while (list($k, $v) = each($value[1])) { - $this->_straightOut($k . ' '); - $this->pdf_write_value($v); - } - - $this->_straightOut('>>'); - break; - - case PDF_TYPE_OBJREF : - - // An indirect object reference - // Fill the object stack if needed - $cpfn =& $this->current_parser->filename; - - if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { - $this->_newobj(false,true); - $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); - $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! - } - $objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; - - $this->_out($objid.' 0 R'); - break; - - case PDF_TYPE_STRING : - - // A string. - $this->_straightOut('('.$value[1].')'); - - break; - - case PDF_TYPE_STREAM : - - // A stream. First, output the - // stream dictionary, then the - // stream data itself. - $this->pdf_write_value($value[1]); - $this->_out('stream'); - $this->_out($value[2][1]); - $this->_out('endstream'); - break; - case PDF_TYPE_HEX : - $this->_straightOut('<'.$value[1].'>'); - break; - - case PDF_TYPE_BOOLEAN : - $this->_straightOut($value[1] ? 'true ' : 'false '); - break; - - case PDF_TYPE_NULL : - // The null object. - - $this->_straightOut('null '); - break; - } - } - - - /** - * Modified so not each call will add a newline to the output. - */ - 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 (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { - // puts data before page footer - $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); - $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); - $this->setPageBuffer($this->page, $page.' '.$s."\n".$footer); - } else { - $this->setPageBuffer($this->page, $s, true); - } - } else { - $this->setBuffer($s); - } - } - } - - /** - * rewritten to close opened parsers - * - */ - function _enddoc() { - parent::_enddoc(); - $this->_closeParsers(); - } - - /** - * close all files opened by parsers - */ - function _closeParsers() { - if ($this->state > 2 && count($this->parsers) > 0) { - foreach ($this->parsers as $k => $_){ - $this->parsers[$k]->closeFile(); - $this->parsers[$k] = null; - unset($this->parsers[$k]); - } - return true; - } - return false; - } - -} +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: + * + * + * + * 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('<_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 <>'); + } + + $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 diff --git a/share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php b/share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php deleted file mode 100644 index 008c766..0000000 --- a/share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php +++ /dev/null @@ -1,171 +0,0 @@ -PDFVersion; - case 'k': - return $this->k; - default: - // Error handling - $this->Error('Cannot access protected property '.get_class($this).':$'.$name.' / Undefined property: '.get_class($this).'::$'.$name); - } - } - - function __set($name, $value) { - switch ($name) { - case 'PDFVersion': - $this->PDFVersion = $value; - break; - default: - // Error handling - $this->Error('Cannot access protected property '.get_class($this).':$'.$name.' / Undefined property: '.get_class($this).'::$'.$name); - } - } - - /** - * Encryption of imported data by FPDI - * - * @param array $value - */ - function pdf_write_value(&$value) { - switch ($value[0]) { - case PDF_TYPE_STRING : - if ($this->encrypted) { - $value[1] = $this->_unescape($value[1]); - $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]); - $value[1] = $this->_escape($value[1]); - } - break; - - case PDF_TYPE_STREAM : - if ($this->encrypted) { - $value[2][1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[2][1]); - } - break; - - case PDF_TYPE_HEX : - if ($this->encrypted) { - $value[1] = $this->hex2str($value[1]); - $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]); - - // remake hexstring of encrypted string - $value[1] = $this->str2hex($value[1]); - } - break; - } - } - - /** - * Unescapes a PDF string - * - * @param string $s - * @return string - */ - 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 $hex - * @return string - */ - function hex2str($hex) { - return pack('H*', str_replace(array("\r", "\n", ' '), '', $hex)); - } - - /** - * String to hexadecimal - * - * @param string $str - * @return string - */ - function str2hex($str) { - return current(unpack('H*', $str)); - } -} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/fpdi_bridge.php b/share/pnp/application/vendor/fpdf/fpdi_bridge.php new file mode 100644 index 0000000..8283876 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/fpdi_bridge.php @@ -0,0 +1,206 @@ +_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 diff --git a/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php b/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php index c5e37f6..0204b9c 100644 --- a/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php +++ b/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php @@ -1,384 +1,355 @@ -fpdi =& $fpdi; - - parent::pdf_parser($filename); - - // resolve Pages-Dictonary - $pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']); - - // Read pages - $this->read_pages($this->c, $pages, $this->pages); - - // count pages; - $this->page_count = count($this->pages); - } - - /** - * Overwrite parent::error() - * - * @param string $msg Error-Message - */ - function error($msg) { - $this->fpdi->error($msg); - } - - /** - * Get pagecount from sourcefile - * - * @return int - */ - function getPageCount() { - return $this->page_count; - } - - - /** - * Set pageno - * - * @param int $pageno Pagenumber to use - */ - function setPageno($pageno) { - $pageno = ((int) $pageno) - 1; - - if ($pageno < 0 || $pageno >= $this->getPageCount()) { - $this->fpdi->error('Pagenumber is wrong!'); - } - - $this->pageno = $pageno; - } - - /** - * Get page-resources from current page - * - * @return array - */ - function getPageResources() { - return $this->_getPageResources($this->pages[$this->pageno]); - } - - /** - * Get page-resources from /Page - * - * @param array $obj Array of pdf-data - */ - function _getPageResources ($obj) { // $obj = /Page - $obj = $this->pdf_resolve_object($this->c, $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->pdf_resolve_object($this->c, $obj[1][1]['/Resources']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } else { - if (!isset ($obj[1][1]['/Parent'])) { - return false; - } else { - $res = $this->_getPageResources($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } - } - } - - - /** - * Get content of current page - * - * If more /Contents is an array, the streams are concated - * - * @return string - */ - 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 $tmp_content) { - $buffer .= $this->_rebuildContentStream($tmp_content).' '; - } - } - - return $buffer; - } - - - /** - * Resolve all content-objects - * - * @param array $content_ref - * @return array - */ - function _getPageContent($content_ref) { - $contents = array(); - - if ($content_ref[0] == PDF_TYPE_OBJREF) { - $content = $this->pdf_resolve_object($this->c, $content_ref); - if ($content[1][0] == PDF_TYPE_ARRAY) { - $contents = $this->_getPageContent($content[1]); - } else { - $contents[] = $content; - } - } else if ($content_ref[0] == PDF_TYPE_ARRAY) { - foreach ($content_ref[1] AS $tmp_content_ref) { - $contents = array_merge($contents,$this->_getPageContent($tmp_content_ref)); - } - } - - return $contents; - } - - - /** - * Rebuild content-streams - * - * @param array $obj - * @return string - */ - function _rebuildContentStream($obj) { - $filters = array(); - - if (isset($obj[1][1]['/Filter'])) { - $_filter = $obj[1][1]['/Filter']; - - if ($_filter[0] == PDF_TYPE_TOKEN) { - $filters[] = $_filter; - } else if ($_filter[0] == PDF_TYPE_ARRAY) { - $filters = $_filter[1]; - } - } - - $stream = $obj[2][1]; - - foreach ($filters AS $_filter) { - switch ($_filter[1]) { - case '/FlateDecode': - if (function_exists('gzuncompress')) { - $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : ''; - } else { - $this->error(sprintf('To handle %s filter, please compile php with zlib support.',$_filter[1])); - } - if ($stream === false) { - $this->error('Error while decompressing stream.'); - } - break; - case '/LZWDecode': - include_once('filters/FilterLZW_FPDI.php'); - $decoder = new FilterLZW_FPDI($this->fpdi); - $stream = $decoder->decode($stream); - break; - case '/ASCII85Decode': - include_once('filters/FilterASCII85_FPDI.php'); - $decoder = new FilterASCII85_FPDI($this->fpdi); - $stream = $decoder->decode($stream); - break; - case null: - $stream = $stream; - break; - default: - $this->error(sprintf('Unsupported Filter: %s',$_filter[1])); - } - } - - return $stream; - } - - - /** - * Get a Box from a page - * Arrayformat is same as used by fpdf_tpl - * - * @param array $page a /Page - * @param string $box_index Type of Box @see $availableBoxes - * @return array - */ - function getPageBox($page, $box_index) { - $page = $this->pdf_resolve_object($this->c,$page); - $box = null; - if (isset($page[1][1][$box_index])) - $box =& $page[1][1][$box_index]; - - if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { - $tmp_box = $this->pdf_resolve_object($this->c,$box); - $box = $tmp_box[1]; - } - - if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { - $b =& $box[1]; - return array('x' => $b[0][1]/$this->fpdi->k, - 'y' => $b[1][1]/$this->fpdi->k, - 'w' => abs($b[0][1]-$b[2][1])/$this->fpdi->k, - 'h' => abs($b[1][1]-$b[3][1])/$this->fpdi->k, - 'llx' => min($b[0][1], $b[2][1])/$this->fpdi->k, - 'lly' => min($b[1][1], $b[3][1])/$this->fpdi->k, - 'urx' => max($b[0][1], $b[2][1])/$this->fpdi->k, - 'ury' => max($b[1][1], $b[3][1])/$this->fpdi->k, - ); - } else if (!isset ($page[1][1]['/Parent'])) { - return false; - } else { - return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index); - } - } - - function getPageBoxes($pageno) { - return $this->_getPageBoxes($this->pages[$pageno-1]); - } - - /** - * Get all Boxes from /Page - * - * @param array a /Page - * @return array - */ - function _getPageBoxes($page) { - $boxes = array(); - - foreach($this->availableBoxes AS $box) { - if ($_box = $this->getPageBox($page,$box)) { - $boxes[$box] = $_box; - } - } - - return $boxes; - } - - /** - * Get the page rotation by pageno - * - * @param integer $pageno - * @return array - */ - function getPageRotation($pageno) { - return $this->_getPageRotation($this->pages[$pageno-1]); - } - - function _getPageRotation ($obj) { // $obj = /Page - $obj = $this->pdf_resolve_object($this->c, $obj); - if (isset ($obj[1][1]['/Rotate'])) { - $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } else { - if (!isset ($obj[1][1]['/Parent'])) { - return false; - } else { - $res = $this->_getPageRotation($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } - } - } - - /** - * Read all /Page(es) - * - * @param object pdf_context - * @param array /Pages - * @param array the result-array - */ - function read_pages (&$c, &$pages, &$result) { - // Get the kids dictionary - $kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); - - if (!is_array($kids)) - $this->error('Cannot find /Kids in current /Page-Dictionary'); - foreach ($kids[1] as $v) { - $pg = $this->pdf_resolve_object ($c, $v); - if ($pg[1][1]['/Type'][1] === '/Pages') { - // If one of the kids is an embedded - // /Pages array, resolve it as well. - $this->read_pages ($c, $pg, $result); - } else { - $result[] = $pg; - } - } - } - - - - /** - * Get PDF-Version - * - * And reset the PDF Version used in FPDI if needed - */ - function getPDFVersion() { - parent::getPDFVersion(); - $this->fpdi->PDFVersion = max($this->fpdi->PDFVersion, $this->pdfVersion); - } - -} +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 diff --git a/share/pnp/application/vendor/fpdf/license.txt b/share/pnp/application/vendor/fpdf/license.txt index 6107ee4..fd811c6 100644 --- a/share/pnp/application/vendor/fpdf/license.txt +++ b/share/pnp/application/vendor/fpdf/license.txt @@ -1,6 +1,6 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software to use, copy, modify, distribute, sublicense, and/or sell -copies of the software, and to permit persons to whom the software is furnished -to do so. - +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software to use, copy, modify, distribute, sublicense, and/or sell +copies of the software, and to permit persons to whom the software is furnished +to do so. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/pdf_context.php b/share/pnp/application/vendor/fpdf/pdf_context.php index 535636c..dac38b4 100644 --- a/share/pnp/application/vendor/fpdf/pdf_context.php +++ b/share/pnp/application/vendor/fpdf/pdf_context.php @@ -1,97 +1,151 @@ -file =& $f; - if (is_string($this->file)) - $this->_mode = 1; - $this->reset(); - } - - // Optionally move the file - // pointer to a new location - // and reset the buffered data - - 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->increase_length($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 - - function ensure_content() { - if ($this->offset >= $this->length - 1) { - return $this->increase_length(); - } else { - return true; - } - } - - // Forcefully read more data into the buffer - - function increase_length($l=100) { - if ($this->_mode == 0 && feof($this->file)) { - return false; - } else if ($this->_mode == 0) { - $totalLength = $this->length + $l; - do { - $this->buffer .= fread($this->file, $totalLength-$this->length); - } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); - - return true; - } else { - return false; - } - } +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 diff --git a/share/pnp/application/vendor/fpdf/pdf_parser.php b/share/pnp/application/vendor/fpdf/pdf_parser.php index 3e65d6b..6151cb5 100644 --- a/share/pnp/application/vendor/fpdf/pdf_parser.php +++ b/share/pnp/application/vendor/fpdf/pdf_parser.php @@ -1,706 +1,925 @@ -filename = $filename; - - $this->f = @fopen($this->filename, 'rb'); - - if (!$this->f) - $this->error(sprintf('Cannot open %s !', $filename)); - - $this->getPDFVersion(); - - $this->c = new pdf_context($this->f); - - // Read xref-Data - $this->xref = array(); - $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); - - // Check for Encryption - $this->getEncryption(); - - // Read root - $this->pdf_read_root(); - } - - /** - * Close the opened file - */ - function closeFile() { - if (isset($this->f) && is_resource($this->f)) { - fclose($this->f); - unset($this->f); - } - } - - /** - * Print Error and die - * - * @param string $msg Error-Message - */ - function error($msg) { - die('PDF-Parser Error: '.$msg); - } - - /** - * Check Trailer for Encryption - */ - function getEncryption() { - if (isset($this->xref['trailer'][1]['/Encrypt'])) { - $this->error('File is encrypted!'); - } - } - - /** - * Find/Return /Root - * - * @return array - */ - function pdf_find_root() { - if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { - $this->error('Wrong Type of Root-Element! Must be an indirect reference'); - } - - return $this->xref['trailer'][1]['/Root']; - } - - /** - * Read the /Root - */ - function pdf_read_root() { - // read root - $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); - } - - /** - * Get PDF-Version - * - * And reset the PDF Version used in FPDI if needed - */ - function getPDFVersion() { - fseek($this->f, 0); - preg_match('/\d\.\d/',fread($this->f,16),$m); - if (isset($m[0])) - $this->pdfVersion = $m[0]; - return $this->pdfVersion; - } - - /** - * Find the xref-Table - */ - function pdf_find_xref() { - $toRead = 1500; - - $stat = fseek ($this->f, -$toRead, SEEK_END); - if ($stat === -1) { - fseek ($this->f, 0); - } - $data = fread($this->f, $toRead); - - $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); - $data = substr($data, $pos); - - if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { - $this->error('Unable to find pointer to xref table'); - } - - return (int) $matches[1]; - } - - /** - * Read xref-table - * - * @param array $result Array of xref-table - * @param integer $offset of xref-table - */ - function pdf_read_xref(&$result, $offset) { - - fseek($this->f, $o_pos = $offset-20); // set some bytes backwards to fetch errorious docs - - $data = fread($this->f, 100); - - $xrefPos = strrpos($data, 'xref'); - - if ($xrefPos === false) { - fseek($this->f, $offset); - $c = new pdf_context($this->f); - $xrefStreamObjDec = $this->pdf_read_value($c); - - if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == PDF_TYPE_OBJDEC) { - $this->error(sprintf('This document (%s) probably uses a compression technique which is not supported by the free parser shipped with FPDI.', $this->filename)); - } else { - $this->error('Unable to find xref table.'); - } - } - - if (!isset($result['xref_location'])) { - $result['xref_location'] = $o_pos+$xrefPos; - $result['max_object'] = 0; - } - - $cylces = -1; - $bytesPerCycle = 100; - - fseek($this->f, $o_pos = $o_pos+$xrefPos+4); // set the handle directly after the "xref"-keyword - $data = fread($this->f, $bytesPerCycle); - - while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle*$cylces++, 0))) === false && !feof($this->f)) { - $data .= fread($this->f, $bytesPerCycle); - } - - if ($trailerPos === false) { - $this->error('Trailer keyword not found after xref table'); - } - - $data = substr($data, 0, $trailerPos); - - // get Line-Ending - preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for linebreaks - - $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][1], $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['max_object']) - $result['max_object'] = $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: - $this->error('Unexpected data in xref table'); - } - } - } - - $lines = $pieces = $line = $start = $end = $gen = null; - unset($lines, $pieces, $line, $start, $end, $gen); - - fseek($this->f, $o_pos+$trailerPos+7); - - $c = new pdf_context($this->f); - $trailer = $this->pdf_read_value($c); - - $c = null; - unset($c); - - if (!isset($result['trailer'])) { - $result['trailer'] = $trailer; - } - - if (isset($trailer[1]['/Prev'])) { - $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); - } - - $trailer = null; - unset($trailer); - - return true; - } - - /** - * Reads an Value - * - * @param object $c pdf_context - * @param string $token a Token - * @return mixed - */ - function pdf_read_value(&$c, $token = null) { - if (is_null($token)) { - $token = $this->pdf_read_token($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->increase_length()) { - return false; - } else { - continue; - } - } - - $result = substr ($c->buffer, $c->offset, $match - $c->offset); - $c->offset = $match + 1; - - return array (PDF_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->pdf_read_token($c)) !== '>>') { - if ($key === false) { - return false; - } - - if (($value = $this->pdf_read_value($c)) === false) { - return false; - } - - // Catch missing value - if ($value[0] == PDF_TYPE_TOKEN && $value[1] == '>>') { - $result[$key] = array(PDF_TYPE_NULL); - break; - } - - $result[$key] = $value; - } - - return array (PDF_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->pdf_read_token($c)) !== ']') { - if ($token === false) { - return false; - } - - if (($value = $this->pdf_read_value($c, $token)) === false) { - return false; - } - - $result[] = $value; - } - - return array (PDF_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->increase_length()); - - $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); - $c->offset = $pos; - - return array (PDF_TYPE_STRING, $result); - - case 'stream': - $o_pos = ftell($c->file)-strlen($c->buffer); - $o_offset = $c->offset; - - $c->reset($startpos = $o_pos + $o_offset); - - $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->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { - $tmp_c = new pdf_context($this->f); - $tmp_length = $this->pdf_resolve_object($tmp_c,$this->actual_obj[1][1]['/Length']); - $length = $tmp_length[1][1]; - } else { - $length = $this->actual_obj[1][1]['/Length'][1]; - } - - if ($length > 0) { - $c->reset($startpos+$e,$length); - $v = $c->buffer; - } else { - $v = ''; - } - $c->reset($startpos+$e+$length+9); // 9 = strlen("endstream") - - return array(PDF_TYPE_STREAM, $v); - - default : - if (is_numeric ($token)) { - // A numeric token. Make sure that - // it is not part of something else. - if (($tok2 = $this->pdf_read_token ($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->pdf_read_token ($c)) !== false) { - switch ($tok3) { - case 'obj' : - return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); - case 'R' : - return array (PDF_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 (PDF_TYPE_NUMERIC, (int)$token); - else - return array (PDF_TYPE_REAL, (float)$token); - } else if ($token == 'true' || $token == 'false') { - return array (PDF_TYPE_BOOLEAN, $token == 'true'); - } else if ($token == 'null') { - return array (PDF_TYPE_NULL); - } else { - // Just a token. Return it. - return array (PDF_TYPE_TOKEN, $token); - } - } - } - - /** - * Resolve an object - * - * @param object $c pdf_context - * @param array $obj_spec The object-data - * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para - */ - function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { - // Exit if we get invalid data - if (!is_array($obj_spec)) { - $ret = false; - return $ret; - } - - if ($obj_spec[0] == PDF_TYPE_OBJREF) { - - // This is a reference, resolve it - if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[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) - - $old_pos = ftell($c->file); - - // Reposition the file pointer and - // load the object header. - - $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); - - $header = $this->pdf_read_value($c); - - if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { - $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); - } - - // 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(); - $this->actual_obj =& $result; - if ($encapsulate) { - $result = array ( - PDF_TYPE_OBJECT, - 'obj' => $obj_spec[1], - 'gen' => $obj_spec[2] - ); - } - - // Now simply read the object data until - // we encounter an end-of-object marker - while(1) { - $value = $this->pdf_read_value($c); - if ($value === false || count($result) > 4) { - // in this case the parser coudn't find an endobj so we break here - break; - } - - if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { - break; - } - - $result[] = $value; - } - - $c->reset($old_pos); - - if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { - $result[0] = PDF_TYPE_STREAM; - } - - return $result; - } - } else { - return $obj_spec; - } - } - - - - /** - * Reads a token from the file - * - * @param object $c pdf_context - * @return mixed - */ - function pdf_read_token(&$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->ensure_content()) { - return false; - } - $c->offset += strspn($c->buffer, " \n\r\t", $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->ensure_content()) { - 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->increase_length()) { - return false; - } else { - continue; - } - } - - $c->offset = $m[0][1]+strlen($m[0][0]); - - return $this->pdf_read_token($c); - } - - default: - - // This is "another" type of token (probably - // a dictionary entry or a numeric value) - // Find the end and return it. - - if (!$c->ensure_content()) { - return false; - } - - while(1) { - - // Determine the length of the token - - $pos = strcspn($c->buffer, " %[]<>()\r\n\t/", $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->increase_length(); - } - } - - $result = substr($c->buffer, $c->offset - 1, $pos + 1); - - $c->offset += $pos; - return $result; - } - } -} - -} +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