diff --git a/COPYRIGHT b/COPYRIGHT
index 60242009dad..ab9564ecfb3 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -14,10 +14,10 @@ ArtiChow 1.07 Public Domain Yes Graphics
Php-barcode 0.3pl1 GPL 2.0 Yes Bar code generation
EFC/XFSS 1.0.1 LGPL 3.0 Yes Enhanced File Crypt/Extended File Stealth System
FCKEditor 2.6.4 LGPL 2.1 or Mozilla PL 1.0 Yes Editor WYSIWYG
-FPDF 1.53 Public domain Yes PDF generation (original code is modified)
-FPDF_TPL 1.1.2 Apache Software License 2.0 No GPL3 only PDF templates management
-FPDI 1.2.1 Apache Software License 2.0 No GPL3 only PDF templates management
-FPDI_Protection 1.0.2 Apache Software License 2.0 No GPL3 only PDF encryption (8 files)
+FPDF 1.6 Public domain Yes PDF generation (original code is modified)
+FPDF_TPL 1.1.4 Apache Software License 2.0 No GPL3 only PDF templates management
+FPDI 1.3.2 Apache Software License 2.0 No GPL3 only PDF templates management
+FPDI_Protection 1.0.3 Apache Software License 2.0 No GPL3 only PDF encryption (8 files)
GeoIP x.x Yes GeoIP Maxmind conversion
iWebkit 4.6.2 LGPL 3.0 Yes Iphone templates framework
JCrop 0.9.8 MIT Licence Yes JS library to crop images
diff --git a/htdocs/includes/fpdf/fpdfi/decoders/ASCII85Decode.php b/htdocs/includes/fpdf/fpdfi/decoders/ASCII85Decode.php
deleted file mode 100644
index 1f9492c143e..00000000000
--- a/htdocs/includes/fpdf/fpdfi/decoders/ASCII85Decode.php
+++ /dev/null
@@ -1,95 +0,0 @@
-fpdi =& $fpdi;
- }
-
-
- 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) {
- break;
- }
- if (preg_match("/^\s$/",chr($ch))) {
- continue;
- }
- if ($ch == ORD_z && $state == 0) {
- $out .= chr(0).chr(0).chr(0).chr(0);
- continue;
- }
- if ($ch < ORD_exclmark || $ch > ORD_u) {
- $this->fpdi->error("Illegal character in ASCII85Decode.");
- }
-
- $chn[$state++] = $ch - ORD_exclmark;
-
- if ($state == 5) {
- $state = 0;
- $r = 0;
- for ($j = 0; $j < 5; ++$j)
- $r = $r * 85 + $chn[$j];
- $out .= chr($r >> 24);
- $out .= chr($r >> 16);
- $out .= chr($r >> 8);
- $out .= chr($r);
- }
- }
- $r = 0;
-
- if ($state == 1)
- $this->fpdi->error("Illegal length in ASCII85Decode.");
- if ($state == 2) {
- $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85;
- $out .= chr($r >> 24);
- }
- else if ($state == 3) {
- $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85;
- $out .= chr($r >> 24);
- $out .= chr($r >> 16);
- }
- else if ($state == 4) {
- $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ;
- $out .= chr($r >> 24);
- $out .= chr($r >> 16);
- $out .= chr($r >> 8);
- }
-
- return $out;
- }
-}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/decoders/LZWDecode.php b/htdocs/includes/fpdf/fpdfi/decoders/LZWDecode.php
deleted file mode 100644
index 59d1b487f8b..00000000000
--- a/htdocs/includes/fpdf/fpdfi/decoders/LZWDecode.php
+++ /dev/null
@@ -1,147 +0,0 @@
-fpdi =& $fpdi;
- }
-
- /**
- * Method to decode LZW compressed data.
- *
- * @param string data The compressed data.
- */
- function decode($data) {
-
- if($data[0] == 0x00 && $data[1] == 0x01) {
- $this->fpdi->error("LZW flavour not supported.");
- }
-
- $this->initsTable();
-
- $this->data = $data;
-
- // Initialize pointers
- $this->bytePointer = 0;
- $this->bitPointer = 0;
-
- $this->nextData = 0;
- $this->nextBits = 0;
-
- $oldCode = 0;
-
- $string = "";
- $uncompData = "";
-
- while (($code = $this->getNextCode()) != 257) {
- if ($code == 256) {
- $this->initsTable();
- $code = $this->getNextCode();
-
- if ($code == 257) {
- break;
- }
-
- $uncompData .= $this->sTable[$code];
- $oldCode = $code;
-
- } else {
-
- if ($code < $this->tIdx) {
- $string = $this->sTable[$code];
- $uncompData .= $string;
-
- $this->addStringToTable($this->sTable[$oldCode], $string[0]);
- $oldCode = $code;
- } else {
- $string = $this->sTable[$oldCode];
- $string = $string.$string[0];
- $uncompData .= $string;
-
- $this->addStringToTable($string);
- $oldCode = $code;
- }
- }
- }
-
- return $uncompData;
- }
-
-
- /**
- * Initialize the string table.
- */
- function initsTable() {
- $this->sTable = array();
-
- for ($i = 0; $i < 256; $i++)
- $this->sTable[$i] = chr($i);
-
- $this->tIdx = 258;
- $this->bitsToGet = 9;
- }
-
- /**
- * Add a new string to the string table.
- */
- function addStringToTable ($oldString, $newString="") {
- $string = $oldString.$newString;
-
- // Add this new String to the table
- $this->sTable[$this->tIdx++] = $string;
-
- if ($this->tIdx == 511) {
- $this->bitsToGet = 10;
- } else if ($this->tIdx == 1023) {
- $this->bitsToGet = 11;
- } else if ($this->tIdx == 2047) {
- $this->bitsToGet = 12;
- }
- }
-
- // Returns the next 9, 10, 11 or 12 bits
- function getNextCode() {
- if ($this->bytePointer == strlen($this->data))
- return 257;
-
- $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff);
- $this->nextBits += 8;
-
- if ($this->nextBits < $this->bitsToGet) {
- $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff);
- $this->nextBits += 8;
- }
-
- $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet-9];
- $this->nextBits -= $this->bitsToGet;
-
- return $code;
- }
-}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/filters/FilterASCII85.php b/htdocs/includes/fpdf/fpdfi/filters/FilterASCII85.php
new file mode 100644
index 00000000000..149ccda2491
--- /dev/null
+++ b/htdocs/includes/fpdf/fpdfi/filters/FilterASCII85.php
@@ -0,0 +1,104 @@
+ ORD_u) {
+ return $this->error('Illegal character in ASCII85Decode.');
+ }
+
+ $chn[$state++] = $ch - ORD_exclmark;
+
+ if ($state == 5) {
+ $state = 0;
+ $r = 0;
+ for ($j = 0; $j < 5; ++$j)
+ $r = $r * 85 + $chn[$j];
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ $out .= chr($r >> 8);
+ $out .= chr($r);
+ }
+ }
+ $r = 0;
+
+ if ($state == 1)
+ return $this->error('Illegal length in ASCII85Decode.');
+ if ($state == 2) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85;
+ $out .= chr($r >> 24);
+ }
+ else if ($state == 3) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85;
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ }
+ else if ($state == 4) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ;
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ $out .= chr($r >> 8);
+ }
+
+ return $out;
+ }
+
+ function encode($in) {
+ return $this->error("ASCII85 encoding not implemented.");
+ }
+ }
+}
+
+unset($__tmp);
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/filters/FilterASCII85_FPDI.php b/htdocs/includes/fpdf/fpdfi/filters/FilterASCII85_FPDI.php
new file mode 100644
index 00000000000..8ab8924dbd3
--- /dev/null
+++ b/htdocs/includes/fpdf/fpdfi/filters/FilterASCII85_FPDI.php
@@ -0,0 +1,33 @@
+fpdi =& $fpdi;
+ }
+
+ function error($msg) {
+ $this->fpdi->error($msg);
+ }
+}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/filters/FilterLZW.php b/htdocs/includes/fpdf/fpdfi/filters/FilterLZW.php
new file mode 100644
index 00000000000..dd75de0b278
--- /dev/null
+++ b/htdocs/includes/fpdf/fpdfi/filters/FilterLZW.php
@@ -0,0 +1,160 @@
+error('LZW flavour not supported.');
+ }
+
+ $this->initsTable();
+
+ $this->data = $data;
+ $this->dataLength = strlen($data);
+
+ // Initialize pointers
+ $this->bytePointer = 0;
+ $this->bitPointer = 0;
+
+ $this->nextData = 0;
+ $this->nextBits = 0;
+
+ $oldCode = 0;
+
+ $string = '';
+ $uncompData = '';
+
+ while (($code = $this->getNextCode()) != 257) {
+ if ($code == 256) {
+ $this->initsTable();
+ $code = $this->getNextCode();
+
+ if ($code == 257) {
+ break;
+ }
+
+ $uncompData .= $this->sTable[$code];
+ $oldCode = $code;
+
+ } else {
+
+ if ($code < $this->tIdx) {
+ $string = $this->sTable[$code];
+ $uncompData .= $string;
+
+ $this->addStringToTable($this->sTable[$oldCode], $string[0]);
+ $oldCode = $code;
+ } else {
+ $string = $this->sTable[$oldCode];
+ $string = $string.$string[0];
+ $uncompData .= $string;
+
+ $this->addStringToTable($string);
+ $oldCode = $code;
+ }
+ }
+ }
+
+ return $uncompData;
+ }
+
+
+ /**
+ * Initialize the string table.
+ */
+ function initsTable() {
+ $this->sTable = array();
+
+ for ($i = 0; $i < 256; $i++)
+ $this->sTable[$i] = chr($i);
+
+ $this->tIdx = 258;
+ $this->bitsToGet = 9;
+ }
+
+ /**
+ * Add a new string to the string table.
+ */
+ function addStringToTable ($oldString, $newString='') {
+ $string = $oldString.$newString;
+
+ // Add this new String to the table
+ $this->sTable[$this->tIdx++] = $string;
+
+ if ($this->tIdx == 511) {
+ $this->bitsToGet = 10;
+ } else if ($this->tIdx == 1023) {
+ $this->bitsToGet = 11;
+ } else if ($this->tIdx == 2047) {
+ $this->bitsToGet = 12;
+ }
+ }
+
+ // Returns the next 9, 10, 11 or 12 bits
+ function getNextCode() {
+ if ($this->bytePointer == $this->dataLength) {
+ return 257;
+ }
+
+ $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff);
+ $this->nextBits += 8;
+
+ if ($this->nextBits < $this->bitsToGet) {
+ $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff);
+ $this->nextBits += 8;
+ }
+
+ $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet-9];
+ $this->nextBits -= $this->bitsToGet;
+
+ return $code;
+ }
+
+ function encode($in) {
+ $this->error("LZW encoding not implemented.");
+ }
+ }
+}
+
+unset($__tmp);
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/filters/FilterLZW_FPDI.php b/htdocs/includes/fpdf/fpdfi/filters/FilterLZW_FPDI.php
new file mode 100644
index 00000000000..d1d4731197b
--- /dev/null
+++ b/htdocs/includes/fpdf/fpdfi/filters/FilterLZW_FPDI.php
@@ -0,0 +1,33 @@
+fpdi =& $fpdi;
+ }
+
+ function error($msg) {
+ $this->fpdi->error($msg);
+ }
+}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/fpdf_tpl.php b/htdocs/includes/fpdf/fpdfi/fpdf_tpl.php
index 50ae3c1f0c3..bcca8fa2568 100644
--- a/htdocs/includes/fpdf/fpdfi/fpdf_tpl.php
+++ b/htdocs/includes/fpdf/fpdfi/fpdf_tpl.php
@@ -1,402 +1,412 @@
-page <= 0)
- $this->error("You have to add a page to fpdf first!");
-
- if ($x == null)
- $x = 0;
- if ($y == null)
- $y = 0;
- if ($w == null)
- $w = $this->w;
- if ($h == null)
- $h = $this->h;
-
- // Save settings
- $this->tpl++;
- $tpl =& $this->tpls[$this->tpl];
- $tpl = array(
- 'o_x' => $this->x,
- 'o_y' => $this->y,
- 'o_AutoPageBreak' => $this->AutoPageBreak,
- 'o_bMargin' => $this->bMargin,
- 'o_tMargin' => $this->tMargin,
- 'o_lMargin' => $this->lMargin,
- 'o_rMargin' => $this->rMargin,
- 'o_h' => $this->h,
- 'o_w' => $this->w,
- 'buffer' => '',
- 'x' => $x,
- 'y' => $y,
- 'w' => $w,
- 'h' => $h
- );
-
- $this->SetAutoPageBreak(false);
-
- // Define own high and width to calculate possitions correct
- $this->h = $h;
- $this->w = $w;
-
- $this->_intpl = true;
- $this->SetXY($x+$this->lMargin, $y+$this->tMargin);
- $this->SetRightMargin($this->w-$w+$this->rMargin);
-
- return $this->tpl;
- }
-
- /**
- * End Template
- *
- * This method ends a template and reset initiated variables on beginTemplate.
- *
- * @return mixed 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];
- $this->SetXY($tpl['o_x'], $tpl['o_y']);
- $this->tMargin = $tpl['o_tMargin'];
- $this->lMargin = $tpl['o_lMargin'];
- $this->rMargin = $tpl['o_rMargin'];
- $this->h = $tpl['o_h'];
- $this->w = $tpl['o_w'];
- $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
-
- return $this->tpl;
- } else {
- return false;
- }
- }
-
- /**
- * Use a Template in current Page or other Template
- *
- * You can use a template in a page or in another template.
- * You can give the used template a new size like you use the Image()-method.
- * All parameters are optional. The width or height is calculated automaticaly
- * if one is given. If no parameter is given the origin size as defined in
- * beginTemplate() 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
- */
- 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];
- }
-
- $tpl =& $this->tpls[$tplidx];
- $x = $tpl['x'];
- $y = $tpl['y'];
- $w = $tpl['w'];
- $h = $tpl['h'];
-
- if ($_x == null)
- $_x = $x;
- if ($_y == null)
- $_y = $y;
- $wh = $this->getTemplateSize($tplidx, $_w, $_h);
- $_w = $wh['w'];
- $_h = $wh['h'];
-
- $this->_out(sprintf("q %.4F 0 0 %.4F %.2F %.2F cm", ($_w/$w), ($_h/$h), $_x*$this->k, ($this->h-($_y+$_h))*$this->k)); // Translate
- $this->_out($this->tplprefix.$tplidx." Do Q");
-
- return array("w" => $_w, "h" => $_h);
- }
-
- /**
- * Get The calculated Size of a Template
- *
- * If one size is given, this method calculates the other one.
- *
- * @param int $tplidx A valid template-Id
- * @param int $_w The width of the template
- * @param int $_h The height of the template
- * @return array The height and width of the template
- */
- function getTemplateSize($tplidx, $_w=0, $_h=0) {
- if (!$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;
- }
-
- if($_w==0)
- $_w = $_h*$w/$h;
- if($_h==0)
- $_h = $_w*$h/$w;
-
- return array("w" => $_w, "h" => $_h);
- }
-
- /**
- * See FPDF-Documentation ;-)
- */
- function SetFont($family, $style='', $size=0) {
- /**
- * force the resetting of font changes in a template
- */
- if ($this->_intpl)
- $this->FontFamily = '';
-
- 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 ;-)
- */
- function Image($file, $x, $y, $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300) {
- 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.');
- }
-
- parent::Image($file, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi);
- 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);
- }
-
- /**
- * Preserve adding Links in Templates ...won't work
- */
- function Link($x, $y, $w, $h, $link) {
- if ($this->_intpl)
- $this->Error('Using links in templates aren\'t possible!');
- parent::Link($x, $y, $w, $h, $link);
- }
-
- function AddLink() {
- if ($this->_intpl)
- $this->Error('Adding links in templates aren\'t possible!');
- return parent::AddLink();
- }
-
- function SetLink($link, $y=0, $page=-1) {
- if ($this->_intpl)
- $this->Error('Setting links in templates aren\'t 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');
- $this->_out('/Subtype /Form');
- $this->_out('/FormType 1');
- $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',$tpl['x']*$this->k, ($tpl['h']-$tpl['y'])*$this->k, $tpl['w']*$this->k, ($tpl['h']-$tpl['y']-$tpl['h'])*$this->k));
- $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]['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');
- }
- }
-
- /**
- * Private Method
- */
- function _putresources() {
- if (!is_subclass_of($this, 'TCPDF')) {
- $this->_putfonts();
- $this->_putimages();
- $this->_putformxobjects();
- //Resource dictionary
- $this->offsets[2]=strlen($this->buffer);
- $this->_out('2 0 obj');
- $this->_out('<<');
- $this->_putresourcedict();
- $this->_out('>>');
- $this->_out('endobj');
- } else {
- $this->_putextgstates();
- $this->_putocg();
- $this->_putfonts();
- $this->_putimages();
- $this->_putshaders();
- $this->_putformxobjects();
- //Resource dictionary
- $this->offsets[2]=strlen($this->buffer);
- $this->_out('2 0 obj');
- $this->_out('<<');
- $this->_putresourcedict();
- $this->_out('>>');
- $this->_out('endobj');
- $this->_putjavascript();
- $this->_putbookmarks();
- // encryption
- if ($this->encrypted) {
- $this->_newobj();
- $this->enc_obj_id = $this->n;
- $this->_out('<<');
- $this->_putencryption();
- $this->_out('>>');
- $this->_out('endobj');
- }
- }
- }
-
- function _putxobjectdict() {
- parent::_putxobjectdict();
-
- if (count($this->tpls)) {
- foreach($this->tpls as $tplidx => $tpl) {
- $this->_out($this->tplprefix.$tplidx.' '.$tpl['n'].' 0 R');
- }
- }
- }
-
- /**
- * Private Method
- */
- function _out($s) {
- if ($this->state==2 && $this->_intpl) {
- $this->tpls[$this->tpl]['buffer'] .= $s."\n";
- } else {
- parent::_out($s);
- }
- }
-}
+page <= 0)
+ $this->error("You have to add a page to fpdf first!");
+
+ if ($x == null)
+ $x = 0;
+ if ($y == null)
+ $y = 0;
+ if ($w == null)
+ $w = $this->w;
+ if ($h == null)
+ $h = $this->h;
+
+ // Save settings
+ $this->tpl++;
+ $tpl =& $this->tpls[$this->tpl];
+ $tpl = array(
+ 'o_x' => $this->x,
+ 'o_y' => $this->y,
+ 'o_AutoPageBreak' => $this->AutoPageBreak,
+ 'o_bMargin' => $this->bMargin,
+ 'o_tMargin' => $this->tMargin,
+ 'o_lMargin' => $this->lMargin,
+ 'o_rMargin' => $this->rMargin,
+ 'o_h' => $this->h,
+ 'o_w' => $this->w,
+ 'buffer' => '',
+ 'x' => $x,
+ 'y' => $y,
+ 'w' => $w,
+ 'h' => $h
+ );
+
+ $this->SetAutoPageBreak(false);
+
+ // Define own high and width to calculate possitions correct
+ $this->h = $h;
+ $this->w = $w;
+
+ $this->_intpl = true;
+ $this->SetXY($x+$this->lMargin, $y+$this->tMargin);
+ $this->SetRightMargin($this->w-$w+$this->rMargin);
+
+ return $this->tpl;
+ }
+
+ /**
+ * End Template
+ *
+ * This method ends a template and reset initiated variables on beginTemplate.
+ *
+ * @return mixed 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];
+ $this->SetXY($tpl['o_x'], $tpl['o_y']);
+ $this->tMargin = $tpl['o_tMargin'];
+ $this->lMargin = $tpl['o_lMargin'];
+ $this->rMargin = $tpl['o_rMargin'];
+ $this->h = $tpl['o_h'];
+ $this->w = $tpl['o_w'];
+ $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
+
+ return $this->tpl;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Use a Template in current Page or other Template
+ *
+ * You can use a template in a page or in another template.
+ * You can give the used template a new size like you use the Image()-method.
+ * All parameters are optional. The width or height is calculated automaticaly
+ * if one is given. If no parameter is given the origin size as defined in
+ * beginTemplate() 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
+ */
+ 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];
+ }
+
+ $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(
+ 'x' => $this->x,
+ 'y' => $this->y,
+ 'w' => $_w,
+ 'h' => $_h,
+ 'scaleX' => ($_w/$w),
+ 'scaleY' => ($_h/$h),
+ 'tx' => $_x,
+ 'ty' => ($this->h-$_y-$_h),
+ 'lty' => ($this->h-$_y-$_h) - ($this->h-$h) * ($_h/$h)
+ );
+
+ $this->_out(sprintf("q %.4F 0 0 %.4F %.4F %.4F cm", $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);
+ }
+
+ /**
+ * 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
+ */
+ function getTemplateSize($tplidx, $_w=0, $_h=0) {
+ if (!$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;
+ }
+
+ if($_w==0)
+ $_w = $_h*$w/$h;
+ if($_h==0)
+ $_h = $_w*$h/$w;
+
+ return array("w" => $_w, "h" => $_h);
+ }
+
+ /**
+ * See FPDF/TCPDF-Documentation ;-)
+ */
+ 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.');
+ }
+ /**
+ * 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) {
+ $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 ;-)
+ */
+ 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) {
+ 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.');
+ }
+
+ parent::Image($file, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $ismask, $imgmask, $border, $fitbox, $hidden);
+ 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);
+ }
+
+ /**
+ * Preserve adding Links in Templates ...won't work
+ */
+ function Link($x, $y, $w, $h, $link, $spaces=0) {
+ if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 5) {
+ $this->Error('More than 5 arguments for the Image method are only available in TCPDF.');
+ }
+
+ if ($this->_intpl)
+ $this->Error('Using links in templates aren\'t possible!');
+ parent::Link($x, $y, $w, $h, $link, $spaces);
+ }
+
+ function AddLink() {
+ if ($this->_intpl)
+ $this->Error('Adding links in templates aren\'t possible!');
+ return parent::AddLink();
+ }
+
+ function SetLink($link, $y=0, $page=-1) {
+ if ($this->_intpl)
+ $this->Error('Setting links in templates aren\'t 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');
+ $this->_out('/Subtype /Form');
+ $this->_out('/FormType 1');
+ $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
+ // llx
+ $tpl['x']*$this->k,
+ // lly
+ -$tpl['y']*$this->k,
+ // urx
+ ($tpl['w']+$tpl['x'])*$this->k,
+ // ury
+ ($tpl['h']-$tpl['y'])*$this->k
+ ));
+
+ if ($tpl['x'] != 0 || $tpl['y'] != 0) {
+ $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',
+ -$tpl['x']*$this->k*2, $tpl['y']*$this->k*2
+ ));
+ }
+
+ $this->_out('/Resources ');
+
+ $this->_out('<_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('>>');
+
+ $this->_out('/Length '.strlen($p).' >>');
+ $this->_putstream($p);
+ $this->_out('endobj');
+ }
+ }
+
+ /**
+ * Overwritten to add _putformxobjects() after _putimages()
+ *
+ */
+ function _putimages() {
+ parent::_putimages();
+ $this->_putformxobjects();
+ }
+
+ 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']));
+ }
+ }
+ }
+
+ /**
+ * Private Method
+ */
+ function _out($s) {
+ if ($this->state==2 && $this->_intpl) {
+ $this->tpls[$this->tpl]['buffer'] .= $s."\n";
+ } else {
+ parent::_out($s);
+ }
+ }
+}
diff --git a/htdocs/includes/fpdf/fpdfi/fpdi.php b/htdocs/includes/fpdf/fpdfi/fpdi.php
index fb376135481..fbcffb846dd 100644
--- a/htdocs/includes/fpdf/fpdfi/fpdi.php
+++ b/htdocs/includes/fpdf/fpdfi/fpdi.php
@@ -1,500 +1,504 @@
-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];
-
- // fix for rotated pages
- $rotation = $parser->getPageRotation($pageno);
- 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 ($steps % 2 != 0) {
- $x = $y = ($steps == 1 || $steps == -3) ? $tpl['h'] : $tpl['w'];
- } else {
- $x = $tpl['w'];
- $y = $tpl['h'];
- }
-
- $cx=($x/2+$tpl['box']['x'])*$this->k;
- $cy=($y/2+$tpl['box']['y'])*$this->k;
-
- $angle*=-1;
-
- $angle*=M_PI/180;
- $c=cos($angle);
- $s=sin($angle);
-
- $tpl['buffer'] = sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm %s Q',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy, $tpl['buffer']);
- }
-
- $this->_importedPages[$pageKey] = $this->tpl;
-
- return $this->tpl;
- }
-
- function getLastUsedPageBox() {
- return $this->lastUsedPageBox;
- }
-
- function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) {
- $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])) {
- $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]);
- }
- }
- }
- }
- }
-
- /**
- * Put resources
- */
- function _putresources() {
- if (!is_subclass_of($this, 'TCPDF')) {
- $this->_putfonts();
- $this->_putimages();
- $this->_putformxobjects();
- $this->_putimportedobjects();
- //Resource dictionary
- $this->offsets[2]=strlen($this->buffer);
- $this->_out('2 0 obj');
- $this->_out('<<');
- $this->_putresourcedict();
- $this->_out('>>');
- $this->_out('endobj');
-
- } else { // TCPDF - Part
- $this->_putextgstates();
- $this->_putocg();
- $this->_putfonts();
- $this->_putimages();
- $this->_putshaders();
- $this->_putformxobjects();
- $this->_putimportedobjects();
- //Resource dictionary
- $this->offsets[2]=strlen($this->buffer);
- $this->_out('2 0 obj');
- $this->_out('<<');
- $this->_putresourcedict();
- $this->_out('>>');
- $this->_out('endobj');
- $this->_putjavascript();
- $this->_putbookmarks();
- // encryption
- if ($this->encrypted) {
- $this->_newobj();
- $this->enc_obj_id = $this->n;
- $this->_out('<<');
- $this->_putencryption();
- $this->_out('>>');
- $this->_out('endobj');
- }
- }
- }
-
- /**
- * 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]',
- ($tpl['x'] + (isset($tpl['box']['x'])?$tpl['box']['x']:0))*$this->k,
- ($tpl['h'] + (isset($tpl['box']['y'])?$tpl['box']['y']:0) - $tpl['y'])*$this->k,
- ($tpl['w'] + (isset($tpl['box']['x'])?$tpl['box']['x']:0))*$this->k,
- ($tpl['h'] + (isset($tpl['box']['y'])?$tpl['box']['y']:0) - $tpl['y']-$tpl['h'])*$this->k)
- );
-
- if (isset($tpl['box']))
- $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',-$tpl['box']['x']*$this->k, -$tpl['box']['y']*$this->k));
-
- $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"
- }
- }
-
- /**
- * 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] = strlen($this->buffer);
- $this->_out($obj_id.' 0 obj');
- $this->_current_obj_id = $obj_id; // for later use with encryption
- }
- }
-
- /**
- * 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_NUMERIC :
- case PDF_TYPE_TOKEN :
- case PDF_TYPE_REAL :
- // A numeric value or a token.
- // Simply output them
- $this->_out($value[1]." ", false);
- break;
-
- case PDF_TYPE_ARRAY :
-
- // An array. Output the proper
- // structure and move on.
-
- $this->_out("[",false);
- 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->_out("<<",false);
-
- reset ($value[1]);
-
- while (list($k, $v) = each($value[1])) {
- $this->_out($k . " ",false);
- $this->pdf_write_value($v);
- }
-
- $this->_out(">>");
- 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->_out('('.$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->_out("<".$value[1].">");
- break;
-
- case PDF_TYPE_BOOLEAN :
- $this->_out($value[1] ? 'true ' : 'false ', false);
- break;
-
- case PDF_TYPE_NULL :
- // The null object.
-
- $this->_out("null");
- break;
- }
- }
-
-
- /**
- * Modified so not each call will add a newline to the output.
- */
- function _out($s, $ln=true) {
- //Add a line to the document
- if ($this->state==2) {
- if (!$this->_intpl) {
- if (is_subclass_of($this, 'TCPDF') && isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
- // puts data before page footer
- $page = substr($this->pages[$this->page], 0, -$this->footerlen[$this->page]);
- $footer = substr($this->pages[$this->page], -$this->footerlen[$this->page]);
- $this->pages[$this->page] = $page." ".$s."\n".$footer;
- } else {
- $this->pages[$this->page] .= $s.($ln == true ? "\n" : '');
- }
- } else
- $this->tpls[$this->tpl]['buffer'] .= $s.($ln == true ? "\n" : '');
- } else {
- $this->buffer.=$s.($ln == true ? "\n" : '');
- }
- }
-
- /**
- * 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;
- }
-
+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);
+
+ 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];
+
+ $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;
+
+ // 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;
+
+ // 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 = -$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->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;
+ }
}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/fpdi2tcpdf_bridge.php b/htdocs/includes/fpdf/fpdfi/fpdi2tcpdf_bridge.php
index 72cee145512..95994b4c162 100644
--- a/htdocs/includes/fpdf/fpdfi/fpdi2tcpdf_bridge.php
+++ b/htdocs/includes/fpdf/fpdfi/fpdi2tcpdf_bridge.php
@@ -1,8 +1,8 @@
PDFVersion;
case 'k':
return $this->k;
- case 'lastUsedPageBox':
- return $this->lastUsedPageBox;
default:
// Error handling
$this->Error('Cannot access protected property '.get_class($this).':$'.$name.' / Undefined property: '.get_class($this).'::$'.$name);
@@ -100,16 +91,62 @@ class FPDF extends TCPDF {
* @return string
*/
function _unescape($s) {
- return strtr($s, array(
- '\\\\' => "\\",
- '\)' => ')',
- '\(' => '(',
- '\\f' => chr(0x0C),
- '\\b' => chr(0x08),
- '\\t' => chr(0x09),
- '\\r' => chr(0x0D),
- '\\n' => chr(0x0A),
- ));
+ $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;
}
/**
@@ -119,7 +156,7 @@ class FPDF extends TCPDF {
* @return string
*/
function hex2str($hex) {
- return pack("H*", str_replace(array("\r", "\n", " "), "", $hex));
+ return pack('H*', str_replace(array("\r", "\n", ' '), '', $hex));
}
/**
@@ -129,6 +166,6 @@ class FPDF extends TCPDF {
* @return string
*/
function str2hex($str) {
- return current(unpack("H*", $str));
+ return current(unpack('H*', $str));
}
}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/fpdi_pdf_parser.php b/htdocs/includes/fpdf/fpdfi/fpdi_pdf_parser.php
index 8d9288e453c..8ace548a9e1 100644
--- a/htdocs/includes/fpdf/fpdfi/fpdi_pdf_parser.php
+++ b/htdocs/includes/fpdf/fpdfi/fpdi_pdf_parser.php
@@ -1,380 +1,391 @@
-fpdi =& $fpdi;
- $this->filename = $filename;
-
- 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->fpdi->error(sprintf("To handle %s filter, please compile php with zlib support.",$_filter[1]));
- }
- if ($stream === false) {
- $this->fpdi->error("Error while decompressing stream.");
- }
- break;
- case null:
- $stream = $stream;
- break;
- default:
- if (preg_match("/^\/[a-z85]*$/i", $_filter[1], $filterName) && @include_once('decoders'.$_filter[1].'.php')) {
- $filterName = substr($_filter[1],1);
- if (class_exists($filterName)) {
- $decoder = new $filterName($this->fpdi);
- $stream = $decoder->decode(trim($stream));
- } else {
- $this->fpdi->error(sprintf("Unsupported Filter: %s",$_filter[1]));
- }
- } else {
- $this->fpdi->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);
- } 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->fpdi->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);
- }
-
+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');
+
+ if ($_kids[1][0] == PDF_TYPE_ARRAY) {
+ $kids = $_kids[1][1];
+ } else {
+ $kids = $_kids[1];
+ }
+
+ foreach ($kids 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);
+ }
+
}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/fpdi_protection.php b/htdocs/includes/fpdf/fpdfi/fpdi_protection.php
index 34475a6482b..2c0e2a6671f 100644
--- a/htdocs/includes/fpdf/fpdfi/fpdi_protection.php
+++ b/htdocs/includes/fpdf/fpdfi/fpdi_protection.php
@@ -1,269 +1,319 @@
-_current_obj_id =& $this->current_obj_id; // for FPDI 1.1 compatibility
-
- $this->encrypted=false;
- $this->last_rc4_key = '';
- $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08".
- "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
- }
-
- /**
- * Function to set permissions as well as user and owner passwords
- *
- * - permissions is an array with values taken from the following list:
- * 40bit: copy, print, modify, annot-forms
- * 128bit: fill-in, screenreaders, assemble, degraded-print
- * If a value is present it means that the permission is granted
- * - If a user password is set, user will be prompted before document is opened
- * - If an owner password is set, document can be opened in privilege mode with no
- * restriction if that password is entered
- */
- function SetProtection($permissions=array(),$user_pass='',$owner_pass=null)
- {
- $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 );
- $protection = 192;
- foreach($permissions as $permission){
- if (!isset($options[$permission]))
- $this->Error('Incorrect permission: '.$permission);
- $protection += $options[$permission];
- }
- if ($owner_pass === null)
- $owner_pass = uniqid(mt_rand());
- $this->encrypted = true;
- $this->_generateencryptionkey($user_pass, $owner_pass, $protection);
- }
-
-
- function _putstream($s)
- {
- if ($this->encrypted) {
- $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
- }
- parent::_putstream($s);
- }
-
-
- function _textstring($s)
- {
- if ($this->encrypted) {
- $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
- }
- return parent::_textstring($s);
- }
-
-
- /**
- * Compute key depending on object number where the encrypted data is stored
- */
- function _objectkey($n)
- {
- return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10);
- }
-
-
- /**
- * Escape special characters
- */
- function _escape($s)
- {
- return str_replace(
- array('\\',')','(',"\r"),
- array('\\\\','\\)','\\(','\\r'),$s);
- }
-
- function _putresources()
- {
- parent::_putresources();
- if ($this->encrypted) {
- $this->_newobj();
- $this->enc_obj_id = $this->_current_obj_id;
- $this->_out('<<');
- $this->_putencryption();
- $this->_out('>>');
- }
- }
-
- function _putencryption()
- {
- $this->_out('/Filter /Standard');
- $this->_out('/V 1');
- $this->_out('/R 2');
- $this->_out('/O ('.$this->_escape($this->Ovalue).')');
- $this->_out('/U ('.$this->_escape($this->Uvalue).')');
- $this->_out('/P '.$this->Pvalue);
- }
-
-
- function _puttrailer()
- {
- parent::_puttrailer();
- if ($this->encrypted) {
- $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
- $id = isset($this->fileidentifier) ? $this->fileidentifier : '';
- $this->_out('/ID [<'.$id.'><'.$id.'>]');
- }
- }
-
-
- /**
- * RC4 is the standard encryption algorithm used in PDF format
- */
- function _RC4($key, $text)
- {
- if ($this->last_rc4_key != $key) {
- $k = str_repeat($key, 256/strlen($key)+1);
- $rc4 = range(0,255);
- $j = 0;
- for ($i=0; $i<256; $i++){
- $t = $rc4[$i];
- $j = ($j + $t + ord($k{$i})) % 256;
- $rc4[$i] = $rc4[$j];
- $rc4[$j] = $t;
- }
- $this->last_rc4_key = $key;
- $this->last_rc4_key_c = $rc4;
- } else {
- $rc4 = $this->last_rc4_key_c;
- }
-
- $len = strlen($text);
- $a = 0;
- $b = 0;
- $out = '';
- for ($i=0; $i<$len; $i++){
- $a = ($a+1)%256;
- $t= $rc4[$a];
- $b = ($b+$t)%256;
- $rc4[$a] = $rc4[$b];
- $rc4[$b] = $t;
- $k = $rc4[($rc4[$a]+$rc4[$b])%256];
- $out.=chr(ord($text{$i}) ^ $k);
- }
-
- return $out;
- }
-
-
- /**
- * Get MD5 as binary string
- */
- function _md5_16($string)
- {
- return pack('H*',md5($string));
- }
-
- /**
- * Compute O value
- */
- function _Ovalue($user_pass, $owner_pass)
- {
- $tmp = $this->_md5_16($owner_pass);
- $owner_RC4_key = substr($tmp,0,5);
- return $this->_RC4($owner_RC4_key, $user_pass);
- }
-
-
- /**
- * Compute U value
- */
- function _Uvalue()
- {
- return $this->_RC4($this->encryption_key, $this->padding);
- }
-
-
- /**
- * Compute encryption key
- */
- function _generateencryptionkey($user_pass, $owner_pass, $protection)
- {
- // Pad passwords
- $user_pass = substr($user_pass.$this->padding,0,32);
- $owner_pass = substr($owner_pass.$this->padding,0,32);
- // Compute O value
- $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
- // Compute encyption key
- $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF");
- $this->encryption_key = substr($tmp,0,5);
- // Compute U value
- $this->Uvalue = $this->_Uvalue();
- // Compute P value
- $this->Pvalue = -(($protection^255)+1);
- }
-
-
- function pdf_write_value(&$value) {
- switch ($value[0]) {
- case PDF_TYPE_STRING :
- if ($this->encrypted) {
- $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;
- }
-
- parent::pdf_write_value($value);
- }
-
-
- function hex2str($hex) {
- return pack("H*", str_replace(array("\r","\n"," "),"", $hex));
- }
-
- function str2hex($str) {
- return current(unpack("H*",$str));
- }
-}
-
-?>
\ No newline at end of file
+_current_obj_id =& $this->current_obj_id; // for FPDI 1.1 compatibility
+
+ $this->encrypted=false;
+ $this->last_rc4_key = '';
+ $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08".
+ "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
+ }
+*/
+
+ /**
+ * Function to set permissions as well as user and owner passwords
+ *
+ * - permissions is an array with values taken from the following list:
+ * 40bit: copy, print, modify, annot-forms
+ * 128bit: fill-in, screenreaders, assemble, degraded-print
+ * If a value is present it means that the permission is granted
+ * - If a user password is set, user will be prompted before document is opened
+ * - If an owner password is set, document can be opened in privilege mode with no
+ * restriction if that password is entered
+ */
+ function SetProtection($permissions=array(), $user_pass='', $owner_pass=null) {
+ $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 );
+ $protection = 192;
+ foreach($permissions as $permission){
+ if (!isset($options[$permission]))
+ $this->Error('Incorrect permission: '.$permission);
+ $protection += $options[$permission];
+ }
+ if ($owner_pass === null)
+ $owner_pass = uniqid(rand());
+ $this->encrypted = true;
+ $this->_generateencryptionkey($user_pass, $owner_pass, $protection);
+ }
+
+
+ function _putstream($s) {
+ if ($this->encrypted) {
+ $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
+ }
+ parent::_putstream($s);
+ }
+
+
+ function _textstring($s) {
+ if ($this->encrypted) {
+ $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
+ }
+ return parent::_textstring($s);
+ }
+
+
+ /**
+ * Compute key depending on object number where the encrypted data is stored
+ */
+ function _objectkey($n) {
+ return substr($this->_md5_16($this->encryption_key.pack('VXxx', $n)), 0, 10);
+ }
+
+
+ /**
+ * Escape special characters
+ */
+ function _escape($s) {
+ return str_replace(
+ array('\\',')','(',"\r", "\n", "\t"),
+ array('\\\\','\\)','\\(','\\r', '\\n', '\\t'),$s);
+ }
+
+ function _putresources() {
+ parent::_putresources();
+ if ($this->encrypted) {
+ $this->_newobj();
+ $this->enc_obj_id = $this->_current_obj_id;
+ $this->_out('<<');
+ $this->_putencryption();
+ $this->_out('>>');
+ }
+ }
+
+ function _putencryption() {
+ $this->_out('/Filter /Standard');
+ $this->_out('/V 1');
+ $this->_out('/R 2');
+ $this->_out('/O ('.$this->_escape($this->Ovalue).')');
+ $this->_out('/U ('.$this->_escape($this->Uvalue).')');
+ $this->_out('/P '.$this->Pvalue);
+ }
+
+
+ function _puttrailer() {
+ parent::_puttrailer();
+ if ($this->encrypted) {
+ $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
+ $this->_out('/ID [()()]');
+ }
+ }
+
+
+ /**
+ * RC4 is the standard encryption algorithm used in PDF format
+ */
+ function _RC4($key, $text) {
+ if ($this->last_rc4_key != $key) {
+ $k = str_repeat($key, 256/strlen($key)+1);
+ $rc4 = range(0,255);
+ $j = 0;
+ for ($i=0; $i<256; $i++){
+ $t = $rc4[$i];
+ $j = ($j + $t + ord($k{$i})) % 256;
+ $rc4[$i] = $rc4[$j];
+ $rc4[$j] = $t;
+ }
+ $this->last_rc4_key = $key;
+ $this->last_rc4_key_c = $rc4;
+ } else {
+ $rc4 = $this->last_rc4_key_c;
+ }
+
+ $len = strlen($text);
+ $a = 0;
+ $b = 0;
+ $out = '';
+ for ($i=0; $i<$len; $i++){
+ $a = ($a+1)%256;
+ $t= $rc4[$a];
+ $b = ($b+$t)%256;
+ $rc4[$a] = $rc4[$b];
+ $rc4[$b] = $t;
+ $k = $rc4[($rc4[$a]+$rc4[$b])%256];
+ $out.=chr(ord($text{$i}) ^ $k);
+ }
+
+ return $out;
+ }
+
+
+ /**
+ * Get MD5 as binary string
+ */
+ function _md5_16($string) {
+ return pack('H*',md5($string));
+ }
+
+ /**
+ * Compute O value
+ */
+ function _Ovalue($user_pass, $owner_pass) {
+ $tmp = $this->_md5_16($owner_pass);
+ $owner_RC4_key = substr($tmp,0,5);
+ return $this->_RC4($owner_RC4_key, $user_pass);
+ }
+
+
+ /**
+ * Compute U value
+ */
+ function _Uvalue() {
+ return $this->_RC4($this->encryption_key, $this->padding);
+ }
+
+
+ /**
+ * Compute encryption key
+ */
+ function _generateencryptionkey($user_pass, $owner_pass, $protection) {
+ // Pad passwords
+ $user_pass = substr($user_pass.$this->padding,0,32);
+ $owner_pass = substr($owner_pass.$this->padding,0,32);
+ // Compute O value
+ $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
+ // Compute encyption key
+ $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF");
+ $this->encryption_key = substr($tmp,0,5);
+ // Compute U value
+ $this->Uvalue = $this->_Uvalue();
+ // Compute P value
+ $this->Pvalue = -(($protection^255)+1);
+ }
+
+
+ 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;
+ }
+
+ parent::pdf_write_value($value);
+ }
+
+
+ function hex2str($hex) {
+ return pack('H*', str_replace(array("\r","\n",' '),'', $hex));
+ }
+
+ function str2hex($str) {
+ return current(unpack('H*',$str));
+ }
+
+ /**
+ * Deescape special characters
+ */
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/pdf_context.php b/htdocs/includes/fpdf/fpdfi/pdf_context.php
index ce0b0e0c2c2..966fc10c418 100644
--- a/htdocs/includes/fpdf/fpdfi/pdf_context.php
+++ b/htdocs/includes/fpdf/fpdfi/pdf_context.php
@@ -1,82 +1,103 @@
-file = $f;
- $this->reset();
- }
-
- // Optionally move the file
- // pointer to a new location
- // and reset the buffered data
-
- function reset($pos = null, $l = 100) {
- 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);
- $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 (feof($this->file)) {
- return false;
- } else {
- $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;
- }
- }
-
-}
\ No newline at end of file
+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;
+ }
+ }
+ }
+}
+
+unset($__tmp);
\ No newline at end of file
diff --git a/htdocs/includes/fpdf/fpdfi/pdf_parser.php b/htdocs/includes/fpdf/fpdfi/pdf_parser.php
index b47ea7ac83d..34ea5753d51 100644
--- a/htdocs/includes/fpdf/fpdfi/pdf_parser.php
+++ b/htdocs/includes/fpdf/fpdfi/pdf_parser.php
@@ -1,690 +1,708 @@
-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->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)) {
- 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 = strpos($data, 'xref');
-
- if ($xrefPos === false) {
- $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;
- }
- $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);
-
- case '%':
- // this is a comment - just jump over it
- $pos = $c->offset;
- while(1) {
- // PHP 4.3.3 required
- #$match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos);
- // alternative
- $match = preg_match("/(\r\n|\r|\n)/", substr($c->buffer, $pos), $m);
- if ($match === false) {
- if (!$c->increase_length()) {
- return false;
- } else {
- continue;
- }
- }
-
- // PHP 4.3.3 required
- #$c->offset = $m[0][1]+strlen($m[0][0]);
- // alternative
- $c->offset = strpos($c->buffer, $m[0], $pos)+strlen($m[0]);
-
- return $this->pdf_read_value($c);
- }
-
- 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 {
-
- // 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)) {
- return false;
- }
-
- 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,null,true);
-
- 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
- $this->actual_obj =& $result;
- if ($encapsulate) {
- $result = array (
- PDF_TYPE_OBJECT,
- 'obj' => $obj_spec[1],
- 'gen' => $obj_spec[2]
- );
- } else {
- $result = array();
- }
-
- // 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;
- }
-
- 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;
- }
- }
-
-
-}
\ No newline at end of file
+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;
+ }
+ }
+ }
+}
+
+unset($__tmp);
\ No newline at end of file