Update FPDFI to support FPDF 1.6 and fix bug in FPDFI

This commit is contained in:
Laurent Destailleur 2009-01-21 17:20:36 +00:00
parent 21343804b8
commit f53f3989c1
9 changed files with 574 additions and 378 deletions

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -93,5 +93,3 @@ class ASCII85Decode {
return $out; return $out;
} }
} }
?>

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -38,7 +38,7 @@ class LZWDecode {
* *
* @param string data The compressed data. * @param string data The compressed data.
*/ */
function decode(&$data) { function decode($data) {
if($data[0] == 0x00 && $data[1] == 0x01) { if($data[0] == 0x00 && $data[1] == 0x01) {
$this->fpdi->error("LZW flavour not supported."); $this->fpdi->error("LZW flavour not supported.");
@ -46,7 +46,7 @@ class LZWDecode {
$this->initsTable(); $this->initsTable();
$this->data =& $data; $this->data = $data;
// Initialize pointers // Initialize pointers
$this->bytePointer = 0; $this->bytePointer = 0;
@ -145,7 +145,3 @@ class LZWDecode {
return $code; return $code;
} }
} }
?>

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDF_TPL - Version 1.1.1 // FPDF_TPL - Version 1.1.2
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -17,7 +17,10 @@
// limitations under the License. // limitations under the License.
// //
// DOLCHANGE
require_once(FPDF_PATH."fpdf.php"); require_once(FPDF_PATH."fpdf.php");
//require_once('E:/Mes Developpements/dolibarr/htdocs/includes/fpdf/fpdf/fpdf.php');
//require_once('C:/temp/16/fpdf.php');
class FPDF_TPL extends FPDF { class FPDF_TPL extends FPDF {
/** /**
@ -50,17 +53,6 @@ class FPDF_TPL extends FPDF {
*/ */
var $_res = array(); var $_res = array();
/**
* Constructor
* See FPDF-Documentation
* @param string $orientation
* @param string $unit
* @param mixed $format
*/
function fpdf_tpl($orientation='P',$unit='mm',$format='A4') {
parent::fpdf($orientation,$unit,$format);
}
/** /**
* Start a Template * Start a Template
* *
@ -192,7 +184,7 @@ class FPDF_TPL extends FPDF {
$_w = $wh['w']; $_w = $wh['w'];
$_h = $wh['h']; $_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(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"); $this->_out($this->tplprefix.$tplidx." Do Q");
return array("w" => $_w, "h" => $_h); return array("w" => $_w, "h" => $_h);
@ -251,10 +243,14 @@ class FPDF_TPL extends FPDF {
} }
/** /**
* See FPDF-Documentation ;-) * See FPDF/TCPDF-Documentation ;-)
*/ */
function Image($file,$x,$y,$w=0,$h=0,$type='',$link='') { function Image($file, $x, $y, $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300) {
parent::Image($file,$x,$y,$w,$h,$type,$link); 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) { if ($this->_intpl) {
$this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file]; $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];
} else { } else {
@ -267,10 +263,10 @@ class FPDF_TPL extends FPDF {
* *
* AddPage is not available when you're "in" a template. * AddPage is not available when you're "in" a template.
*/ */
function AddPage($orientation='') { function AddPage($orientation='', $format='') {
if ($this->_intpl) if ($this->_intpl)
$this->Error('Adding pages in templates isn\'t possible!'); $this->Error('Adding pages in templates isn\'t possible!');
parent::AddPage($orientation); parent::AddPage($orientation, $format);
} }
/** /**
@ -308,7 +304,7 @@ class FPDF_TPL extends FPDF {
$this->_out('<<'.$filter.'/Type /XObject'); $this->_out('<<'.$filter.'/Type /XObject');
$this->_out('/Subtype /Form'); $this->_out('/Subtype /Form');
$this->_out('/FormType 1'); $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(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('/Resources ');
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
@ -344,6 +340,7 @@ class FPDF_TPL extends FPDF {
* Private Method * Private Method
*/ */
function _putresources() { function _putresources() {
if (!is_subclass_of($this, 'TCPDF')) {
$this->_putfonts(); $this->_putfonts();
$this->_putimages(); $this->_putimages();
$this->_putformxobjects(); $this->_putformxobjects();
@ -354,6 +351,32 @@ class FPDF_TPL extends FPDF {
$this->_putresourcedict(); $this->_putresourcedict();
$this->_out('>>'); $this->_out('>>');
$this->_out('endobj'); $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() { function _putxobjectdict() {
@ -370,16 +393,10 @@ class FPDF_TPL extends FPDF {
* Private Method * Private Method
*/ */
function _out($s) { function _out($s) {
//Add a line to the document if ($this->state==2 && $this->_intpl) {
if ($this->state==2) {
if (!$this->_intpl)
$this->pages[$this->page].=$s."\n";
else
$this->tpls[$this->tpl]['buffer'] .= $s."\n"; $this->tpls[$this->tpl]['buffer'] .= $s."\n";
} else { } else {
$this->buffer.=$s."\n"; parent::_out($s);
} }
} }
} }
?>

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -17,9 +17,12 @@
// limitations under the License. // limitations under the License.
// //
define('FPDI_VERSION','1.2'); define('FPDI_VERSION','1.2.1');
ini_set('auto_detect_line_endings',1); // Strongly required! // Check for TCPDF and remap TCPDF to FPDF
if (class_exists('TCPDF')) {
require_once('fpdi2tcpdf_bridge.php');
}
require_once("fpdf_tpl.php"); require_once("fpdf_tpl.php");
require_once("fpdi_pdf_parser.php"); require_once("fpdi_pdf_parser.php");
@ -44,12 +47,6 @@ class FPDI extends FPDF_TPL {
*/ */
var $current_parser; var $current_parser;
/**
* Highest version of imported PDF
* @var double
*/
var $importVersion = 1.3;
/** /**
* object stack * object stack
* @var array * @var array
@ -74,13 +71,8 @@ class FPDI extends FPDF_TPL {
*/ */
var $lastUsedPageBox; var $lastUsedPageBox;
/** var $_importedPages = array();
* Constructor
* See FPDF-Manual
*/
function FPDI($orientation='P',$unit='mm',$format='A4') {
parent::FPDF_TPL($orientation,$unit,$format);
}
/** /**
* Set a source-file * Set a source-file
@ -112,6 +104,11 @@ class FPDI extends FPDF_TPL {
$fn =& $this->current_filename; $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 =& $this->parsers[$fn];
$parser->setPageno($pageno); $parser->setPageno($pageno);
@ -179,9 +176,11 @@ class FPDI extends FPDF_TPL {
$c=cos($angle); $c=cos($angle);
$s=sin($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']); $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; return $this->tpl;
} }
@ -190,7 +189,7 @@ class FPDI extends FPDF_TPL {
} }
function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) { function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) {
$this->_out('q 0 J 1 w 0 j 0 G'); // reset standard values $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values
$s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h);
$this->_out('Q'); $this->_out('Q');
return $s; return $s;
@ -203,7 +202,7 @@ class FPDI extends FPDF_TPL {
if (is_array($this->parsers) && count($this->parsers) > 0) { if (is_array($this->parsers) && count($this->parsers) > 0) {
foreach($this->parsers AS $filename => $p) { foreach($this->parsers AS $filename => $p) {
$this->current_parser =& $this->parsers[$filename]; $this->current_parser =& $this->parsers[$filename];
if (is_array($this->_obj_stack[$filename])) { if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) {
while($n = key($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]); $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->_obj_stack[$filename][$n][1]);
@ -225,17 +224,11 @@ class FPDI extends FPDF_TPL {
} }
} }
/**
* Sets the PDF Version to the highest of imported documents
*/
function setVersion() {
$this->PDFVersion = max($this->importVersion, $this->PDFVersion);
}
/** /**
* Put resources * Put resources
*/ */
function _putresources() { function _putresources() {
if (!is_subclass_of($this, 'TCPDF')) {
$this->_putfonts(); $this->_putfonts();
$this->_putimages(); $this->_putimages();
$this->_putformxobjects(); $this->_putformxobjects();
@ -247,6 +240,34 @@ class FPDI extends FPDF_TPL {
$this->_putresourcedict(); $this->_putresourcedict();
$this->_out('>>'); $this->_out('>>');
$this->_out('endobj'); $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');
}
}
} }
/** /**
@ -258,12 +279,14 @@ class FPDI extends FPDF_TPL {
foreach($this->tpls AS $tplidx => $tpl) { foreach($this->tpls AS $tplidx => $tpl) {
$p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
$this->_newobj(); $this->_newobj();
$cN = $this->n; // TCPDF/Protection: rem current "n"
$this->tpls[$tplidx]['n'] = $this->n; $this->tpls[$tplidx]['n'] = $this->n;
$this->_out('<<'.$filter.'/Type /XObject'); $this->_out('<<'.$filter.'/Type /XObject');
$this->_out('/Subtype /Form'); $this->_out('/Subtype /Form');
$this->_out('/FormType 1'); $this->_out('/FormType 1');
$this->_out(sprintf('/BBox [%.2f %.2f %.2f %.2f]', $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
($tpl['x'] + (isset($tpl['box']['x'])?$tpl['box']['x']:0))*$this->k, ($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['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['w'] + (isset($tpl['box']['x'])?$tpl['box']['x']:0))*$this->k,
@ -271,13 +294,13 @@ class FPDI extends FPDF_TPL {
); );
if (isset($tpl['box'])) 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(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',-$tpl['box']['x']*$this->k, -$tpl['box']['y']*$this->k));
$this->_out('/Resources '); $this->_out('/Resources ');
if (isset($tpl['resources'])) { if (isset($tpl['resources'])) {
$this->current_parser =& $tpl['parser']; $this->current_parser =& $tpl['parser'];
$this->pdf_write_value($tpl['resources']); $this->pdf_write_value($tpl['resources']); // "n" will be changed
} else { } else {
$this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {
@ -303,9 +326,12 @@ class FPDI extends FPDF_TPL {
$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->_out('/Length '.strlen($p).' >>');
$this->_putstream($p); $this->_putstream($p);
$this->_out('endobj'); $this->_out('endobj');
$this->n = $nN; // TCPDF: reset to new "n"
} }
} }
@ -323,7 +349,6 @@ class FPDI extends FPDF_TPL {
$this->_out($obj_id.' 0 obj'); $this->_out($obj_id.' 0 obj');
$this->_current_obj_id = $obj_id; // for later use with encryption $this->_current_obj_id = $obj_id; // for later use with encryption
} }
} }
/** /**
@ -334,11 +359,15 @@ class FPDI extends FPDF_TPL {
*/ */
function pdf_write_value(&$value) function pdf_write_value(&$value)
{ {
if (is_subclass_of($this, 'TCPDF')) {
parent::pdf_write_value($value);
}
switch ($value[0]) { switch ($value[0]) {
case PDF_TYPE_NUMERIC : case PDF_TYPE_NUMERIC :
case PDF_TYPE_TOKEN : case PDF_TYPE_TOKEN :
case PDF_TYPE_REAL :
// A numeric value or a token. // A numeric value or a token.
// Simply output them // Simply output them
$this->_out($value[1]." ", false); $this->_out($value[1]." ", false);
@ -380,11 +409,11 @@ class FPDI extends FPDF_TPL {
if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
$this->_newobj(false,true); $this->_newobj(false,true);
$this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
$this->_don_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]; $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
$this->_out("{$objid} 0 R"); //{$value[2]} $this->_out("{$objid} 0 R");
break; break;
case PDF_TYPE_STRING : case PDF_TYPE_STRING :
@ -409,6 +438,10 @@ class FPDI extends FPDF_TPL {
$this->_out("<".$value[1].">"); $this->_out("<".$value[1].">");
break; break;
case PDF_TYPE_BOOLEAN :
$this->_out($value[1] ? 'true ' : 'false ', false);
break;
case PDF_TYPE_NULL : case PDF_TYPE_NULL :
// The null object. // The null object.
@ -419,14 +452,21 @@ class FPDI extends FPDF_TPL {
/** /**
* Private Method * Modified so not each call will add a newline to the output.
*/ */
function _out($s, $ln=true) { function _out($s, $ln=true) {
//Add a line to the document //Add a line to the document
if ($this->state==2) { if ($this->state==2) {
if (!$this->_intpl) 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" : ''); $this->pages[$this->page] .= $s.($ln == true ? "\n" : '');
else }
} else
$this->tpls[$this->tpl]['buffer'] .= $s.($ln == true ? "\n" : ''); $this->tpls[$this->tpl]['buffer'] .= $s.($ln == true ? "\n" : '');
} else { } else {
$this->buffer.=$s.($ln == true ? "\n" : ''); $this->buffer.=$s.($ln == true ? "\n" : '');
@ -458,9 +498,3 @@ class FPDI extends FPDF_TPL {
} }
} }
// for PHP5
if (!class_exists('fpdi')) {
class fpdi extends FPDI {}
}
?>

View File

@ -0,0 +1,134 @@
<?php
//
// FPDI - Version 1.2.1
//
// Copyright 2004-2008 Setasign - Jan Slabon
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/**
* This class is used as a bridge between TCPDF and FPDI
* and will create the possibility to use both FPDF and TCPDF
* via one FPDI version.
*
* We'll simply remap TCPDF to FPDF again.
*
* It'll be loaded and extended by FPDF_TPL.
*/
class FPDF extends TCPDF {
/**
* Missing in TCPDF
*
* @var string
*/
var $padding;
function __get($name) {
switch ($name) {
case 'PDFVersion':
return $this->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);
}
}
function __set($name, $value) {
switch ($name) {
case 'PDFVersion':
$this->PDFVersion = $value;
break;
default:
// Error handling
$this->Error('Cannot access protected property '.get_class($this).':$'.$name.' / Undefined property: '.get_class($this).'::$'.$name);
}
}
/**
* Encryption of imported data by FPDI
*
* @param array $value
*/
function pdf_write_value(&$value) {
switch ($value[0]) {
case PDF_TYPE_STRING :
if ($this->encrypted) {
$value[1] = $this->_unescape($value[1]);
$value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]);
$value[1] = $this->_escape($value[1]);
}
break;
case PDF_TYPE_STREAM :
if ($this->encrypted) {
$value[2][1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[2][1]);
}
break;
case PDF_TYPE_HEX :
if ($this->encrypted) {
$value[1] = $this->hex2str($value[1]);
$value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]);
// remake hexstring of encrypted string
$value[1] = $this->str2hex($value[1]);
}
break;
}
}
/**
* Unescapes a PDF string
*
* @param string $s
* @return string
*/
function _unescape($s) {
return strtr($s, array(
'\\\\' => "\\",
'\)' => ')',
'\(' => '(',
'\\f' => chr(0x0C),
'\\b' => chr(0x08),
'\\t' => chr(0x09),
'\\r' => chr(0x0D),
'\\n' => chr(0x0A),
));
}
/**
* Hexadecimal to string
*
* @param string $hex
* @return string
*/
function hex2str($hex) {
return pack("H*", str_replace(array("\r", "\n", " "), "", $hex));
}
/**
* String to hexadecimal
*
* @param string $str
* @return string
*/
function str2hex($str) {
return current(unpack("H*", $str));
}
}

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -311,6 +311,12 @@ class fpdi_pdf_parser extends pdf_parser {
return $boxes; return $boxes;
} }
/**
* Get the page rotation by pageno
*
* @param integer $pageno
* @return array
*/
function getPageRotation($pageno) { function getPageRotation($pageno) {
return $this->_getPageRotation($this->pages[$pageno-1]); return $this->_getPageRotation($this->pages[$pageno-1]);
} }
@ -368,12 +374,7 @@ class fpdi_pdf_parser extends pdf_parser {
*/ */
function getPDFVersion() { function getPDFVersion() {
parent::getPDFVersion(); parent::getPDFVersion();
$this->fpdi->PDFVersion = max($this->fpdi->PDFVersion, $this->pdfVersion);
if (isset($this->fpdi->importVersion) && $this->pdfVersion > $this->fpdi->importVersion) {
$this->fpdi->importVersion = $this->pdfVersion;
}
} }
} }
?>

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -43,8 +43,10 @@ class pdf_context {
} }
$this->buffer = $l > 0 ? fread($this->file, $l) : ''; $this->buffer = $l > 0 ? fread($this->file, $l) : '';
$this->offset = 0;
$this->length = strlen($this->buffer); $this->length = strlen($this->buffer);
if ($this->length < $l)
$this->increase_length($l - $this->length);
$this->offset = 0;
$this->stack = array(); $this->stack = array();
} }
@ -68,11 +70,13 @@ class pdf_context {
if (feof($this->file)) { if (feof($this->file)) {
return false; return false;
} else { } else {
$this->buffer .= fread($this->file, $l); $totalLength = $this->length + $l;
$this->length = strlen($this->buffer); do {
$this->buffer .= fread($this->file, $totalLength-$this->length);
} while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file));
return true; return true;
} }
} }
} }
?>

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -39,6 +39,10 @@ if (!defined ('PDF_TYPE_OBJECT'))
define ('PDF_TYPE_OBJECT', 9); define ('PDF_TYPE_OBJECT', 9);
if (!defined ('PDF_TYPE_STREAM')) if (!defined ('PDF_TYPE_STREAM'))
define ('PDF_TYPE_STREAM', 10); define ('PDF_TYPE_STREAM', 10);
if (!defined ('PDF_TYPE_BOOLEAN'))
define ('PDF_TYPE_BOOLEAN', 11);
if (!defined ('PDF_TYPE_REAL'))
define ('PDF_TYPE_REAL', 12);
require_once("pdf_context.php"); require_once("pdf_context.php");
require_once("wrapper_functions.php"); require_once("wrapper_functions.php");
@ -75,6 +79,11 @@ class pdf_parser {
*/ */
var $root; var $root;
/**
* PDF version of the loaded document
* @var string
*/
var $pdfVersion;
/** /**
* Constructor * Constructor
@ -158,15 +167,22 @@ class pdf_parser {
function getPDFVersion() { function getPDFVersion() {
fseek($this->f, 0); fseek($this->f, 0);
preg_match("/\d\.\d/",fread($this->f,16),$m); preg_match("/\d\.\d/",fread($this->f,16),$m);
if (isset($m[0]))
$this->pdfVersion = $m[0]; $this->pdfVersion = $m[0];
return $this->pdfVersion;
} }
/** /**
* Find the xref-Table * Find the xref-Table
*/ */
function pdf_find_xref() { function pdf_find_xref() {
fseek ($this->f, -min(filesize($this->filename),1500), SEEK_END); $toRead = 1500;
$data = fread($this->f, 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')); $pos = strlen($data) - strpos(strrev($data), strrev('startxref'));
$data = substr($data, $pos); $data = substr($data, $pos);
@ -183,105 +199,107 @@ class pdf_parser {
* *
* @param array $result Array of xref-table * @param array $result Array of xref-table
* @param integer $offset of xref-table * @param integer $offset of xref-table
* @param integer $start start-position in xref-table
* @param integer $end end-position in xref-table
*/ */
function pdf_read_xref(&$result, $offset, $start = null, $end = null) { function pdf_read_xref(&$result, $offset) {
if (is_null ($start) || is_null ($end)) { fseek($this->f, $o_pos = $offset-20); // set some bytes backwards to fetch errorious docs
fseek($this->f, $o_pos = $offset);
$data = trim(fgets($this->f,1024));
if (strlen($data) == 0) $data = fread($this->f, 100);
$data = trim(fgets($this->f,1024));
if ($data !== 'xref') { $xrefPos = strpos($data, 'xref');
fseek($this->f, $o_pos);
$data = trim(_fgets($this->f, true));
if ($data !== 'xref') {
if (preg_match('/(.*xref)(.*)/m', $data, $m)) { // xref 0 128 - in one line
fseek($this->f, $o_pos+strlen($m[1]));
} elseif (preg_match('/(x|r|e|f)+/', $data, $m)) { // correct invalid xref-pointer
$tmpOffset = $offset-4+strlen($m[0]);
$this->pdf_read_xref($result, $tmpOffset, $start, $end);
return;
} else {
$this->error("Unable to find xref table - Maybe a Problem with 'auto_detect_line_endings'");
}
}
}
$o_pos = ftell($this->f); if ($xrefPos === false) {
$data = explode(' ', trim(fgets($this->f,1024))); $this->error('Unable to find xref table.');
if (count($data) != 2) {
fseek($this->f, $o_pos);
$data = explode(' ', trim(_fgets($this->f, true)));
if (count($data) != 2) {
if (count($data) > 2) { // no lineending
$n_pos = $o_pos+strlen($data[0])+strlen($data[1])+2;
fseek($this->f, $n_pos);
} else {
$this->error("Unexpected header in xref table");
}
}
}
$start = $data[0];
$end = $start + $data[1];
} }
if (!isset($result['xref_location'])) { if (!isset($result['xref_location'])) {
$result['xref_location'] = $offset; $result['xref_location'] = $o_pos+$xrefPos;
$result['max_object'] = 0;
} }
if (!isset($result['max_object']) || $end > $result['max_object']) { $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; $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');
} }
for (; $start < $end; $start++) {
$data = ltrim(fread($this->f, 20)); // Spezifications says: 20 bytes including newlines
$offset = substr($data, 0, 10);
$generation = substr($data, 11, 5);
if (!isset ($result['xref'][$start][(int) $generation])) {
$result['xref'][$start][(int) $generation] = (int) $offset;
} }
} }
$o_pos = ftell($this->f); $lines = $pieces = $line = $start = $end = $gen = null;
$data = fgets($this->f,1024); unset($lines, $pieces, $line, $start, $end, $gen);
if (strlen(trim($data)) == 0)
$data = fgets($this->f, 1024);
if (preg_match("/trailer/",$data)) { fseek($this->f, $o_pos+$trailerPos+7);
if (preg_match("/(.*trailer[ \n\r]*)/",$data,$m)) {
fseek($this->f, $o_pos+strlen($m[1]));
}
$c =& new pdf_context($this->f); $c =& new pdf_context($this->f);
$trailer = $this->pdf_read_value($c); $trailer = $this->pdf_read_value($c);
if (isset($trailer[1]['/Prev'])) { $c = null;
$this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); unset($c);
$result['trailer'][1] = array_merge($result['trailer'][1], $trailer[1]);
} else { if (!isset($result['trailer'])) {
$result['trailer'] = $trailer; $result['trailer'] = $trailer;
} }
} else {
$data = explode(' ', trim($data));
if (count($data) != 2) { if (isset($trailer[1]['/Prev'])) {
fseek($this->f, $o_pos); $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]);
$data = explode(' ', trim (_fgets ($this->f, true)));
if (count($data) != 2) {
$this->error("Unexpected data in xref table");
}
} }
$this->pdf_read_xref($result, null, (int) $data[0], (int) $data[0] + (int) $data[1]); $trailer = null;
} unset($trailer);
}
return true;
}
/** /**
* Reads an Value * Reads an Value
@ -371,44 +389,29 @@ class pdf_parser {
case '(' : case '(' :
// This is a string // This is a string
$pos = $c->offset; $pos = $c->offset;
while(1) { $openBrackets = 1;
do {
// Start by finding the next closed for (; $openBrackets != 0 && $pos < $c->length; $pos++) {
// parenthesis switch (ord($c->buffer[$pos])) {
case 0x28: // '('
$match = strpos ($c->buffer, ')', $pos); $openBrackets++;
break;
// If you can't find it, try case 0x29: // ')'
// reading more data from the stream $openBrackets--;
break;
if ($match === false) { case 0x5C: // backslash
if (!$c->increase_length()) { $pos++;
return false;
} else {
continue;
} }
} }
} while($openBrackets != 0 && $c->increase_length());
// Make sure that there is no backslash $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1);
// before the parenthesis. If there is, $c->offset = $pos;
// move on. Otherwise, return the string.
$esc = preg_match('/([\\\\]+)$/', $tmpresult = substr($c->buffer, $c->offset, $match - $c->offset), $m);
if ($esc === 0 || strlen($m[1]) % 2 == 0) {
$result = $tmpresult;
$c->offset = $match + 1;
return array (PDF_TYPE_STRING, $result); return array (PDF_TYPE_STRING, $result);
} else {
$pos = $match + 1;
if ($pos > $c->offset + $c->length) {
$c->increase_length();
}
}
}
case "stream": case "stream":
$o_pos = ftell($c->file)-strlen($c->buffer); $o_pos = ftell($c->file)-strlen($c->buffer);
@ -440,6 +443,30 @@ class pdf_parser {
return array(PDF_TYPE_STREAM, $v); 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 : default :
if (is_numeric ($token)) { if (is_numeric ($token)) {
// A numeric token. Make sure that // A numeric token. Make sure that
@ -469,7 +496,12 @@ class pdf_parser {
array_push ($c->stack, $tok2); array_push ($c->stack, $tok2);
} }
return array (PDF_TYPE_NUMERIC, $token); 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 { } else {
// Just a token. Return it. // Just a token. Return it.
@ -656,5 +688,3 @@ class pdf_parser {
} }
?>

View File

@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.2 // FPDI - Version 1.2.1
// //
// Copyright 2004-2007 Setasign - Jan Slabon // Copyright 2004-2008 Setasign - Jan Slabon
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -68,21 +68,3 @@ function _strcspn($str1, $str2, $start=null, $length=null) {
return strcspn($str1, $str2, $start, $length); return strcspn($str1, $str2, $start, $length);
} }
} }
/**
* ensure that fgets works correct if php-version < 4.3
*/
function _fgets (&$h, $force=false) {
$startpos = ftell($h);
$s = fgets($h, 1024);
if ((PHP_VER_LOWER43 == 1 || $force) && preg_match("/^([^\r\n]*[\r\n]{1,2})(.)/",trim($s), $ns)) {
$s = $ns[1];
fseek($h,$startpos+strlen($s));
}
return $s;
}
?>