2
0
forked from Wavyzz/dolibarr

Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur
2015-02-20 23:49:06 +01:00
18 changed files with 2431 additions and 1875 deletions

View File

@@ -12,11 +12,10 @@ Dolibarr uses some external libraries released under different licenses. This is
Component Version License GPL Compatible Usage Component Version License GPL Compatible Usage
------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------
PHP libraries: PHP libraries:
AdoDb-Date 0.32 Modified BSD License Yes Date convertion (not into rpm package) AdoDb-Date 0.33 Modified BSD License Yes Date convertion (not into rpm package)
ChromePHP 4.3.3 Apache Software License 2.0 Yes Return server log to chrome browser console ChromePHP 4.3.3 Apache Software License 2.0 Yes Return server log to chrome browser console
CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG
FPDI 1.4.2 Apache Software License 2.0 Yes PDF templates management FPDI 1.5.2 Apache Software License 2.0 Yes PDF templates management
FPDF_TPL 1.2 Apache Software License 2.0 Yes PDF templates management
GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package) GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package)
NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package)
odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files

View File

@@ -131,6 +131,7 @@ For users:
- Fix: [ bug #1535 ] Supplier invoice Extrafields are not shown - Fix: [ bug #1535 ] Supplier invoice Extrafields are not shown
- Fix: datepicker first day of week can be monday by setting into display setup - Fix: datepicker first day of week can be monday by setting into display setup
- Fix: [ bug #575 ] GED doesn't works if there is "/" in a mask - Fix: [ bug #575 ] GED doesn't works if there is "/" in a mask
- Fix: [ task #1728 ] Deactivate RIB suggest in proposals / invoices / orders
For users, new experimental module (need to set feature level of instance to experimental to see them): For users, new experimental module (need to set feature level of instance to experimental to see them):
- New: Module Accounting Expert to manage accountancy - New: Module Accounting Expert to manage accountancy

View File

@@ -197,7 +197,7 @@ $form=new Form($db);
$sql = "SELECT s.rowid, s.nom as name, s.zip, s.town, s.datec, s.status as status, s.code_client, s.client,"; $sql = "SELECT s.rowid, s.nom as name, s.zip, s.town, s.datec, s.status as status, s.code_client, s.client,";
$sql.= " st.libelle as stcomm, s.prefix_comm, s.fk_stcomm, s.fk_prospectlevel,"; $sql.= " st.libelle as stcomm, s.prefix_comm, s.fk_stcomm, s.fk_prospectlevel,";
$sql.= " d.nom as departement"; $sql.= " d.nom as departement";
if ((!$user->rights->societe->client->voir && !$socid) || $search_sale) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) if ((!$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
$sql .= " FROM ".MAIN_DB_PREFIX."c_stcomm as st"; $sql .= " FROM ".MAIN_DB_PREFIX."c_stcomm as st";
$sql.= ", ".MAIN_DB_PREFIX."societe as s"; $sql.= ", ".MAIN_DB_PREFIX."societe as s";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d on (d.rowid = s.fk_departement)"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d on (d.rowid = s.fk_departement)";

View File

@@ -910,6 +910,8 @@ class Account extends CommonObject
$langs->load("banks"); $langs->load("banks");
$now=dol_now(); $now=dol_now();
require_once DOL_DOCUMENT_ROOT.'/core/class/WorkboardResponse.class.php';
$response = new WorkboardResponse(); $response = new WorkboardResponse();
$response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24; $response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24;
$response->label=$langs->trans("TransactionsToConciliate"); $response->label=$langs->trans("TransactionsToConciliate");

View File

@@ -535,6 +535,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default
$cury+=3; $cury+=3;
} }
/*
if (empty($onlynumber)) $pdf->line($curx+1, $cury+1, $curx+1, $cury+8); if (empty($onlynumber)) $pdf->line($curx+1, $cury+1, $curx+1, $cury+8);
if ($usedetailedbban == 1) if ($usedetailedbban == 1)
@@ -598,6 +599,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default
$curx=$savcurx; $curx=$savcurx;
$cury+=9; $cury+=9;
*/
} }
else else
{ {

View File

@@ -194,7 +194,7 @@ class modProjet extends DolibarrModules
's.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.code_compta'=>'Text','s.code_compta_fournisseur'=>'Text', 's.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.code_compta'=>'Text','s.code_compta_fournisseur'=>'Text',
'p.rowid'=>"List:projet:ref",'p.ref'=>"Text",'p.datec'=>"Date",'p.dateo'=>"Date",'p.datee'=>"Date",'p.fk_statut'=>'Status','p.description'=>"Text", 'p.rowid'=>"List:projet:ref",'p.ref'=>"Text",'p.datec'=>"Date",'p.dateo'=>"Date",'p.datee'=>"Date",'p.fk_statut'=>'Status','p.description'=>"Text",
'pt.dateo'=>"Date",'pt.datee'=>"Date",'pt.duration_effective'=>"Duree",'pt.planned_workload'=>"Number",'pt.progress'=>"Number",'pt.description'=>"Text", 'pt.dateo'=>"Date",'pt.datee'=>"Date",'pt.duration_effective'=>"Duree",'pt.planned_workload'=>"Number",'pt.progress'=>"Number",'pt.description'=>"Text",
'ptt.task_date'=>'Date','ptt.task_duration'=>"Duree",'ptt.fk_user'=>"List:user:Name",'ptt.note'=>"Text"); 'ptt.task_date'=>'Date','ptt.task_duration'=>"Duree",'ptt.fk_user'=>"List:user:CONCAT(lastname,' ',firstname)",'ptt.note'=>"Text");
$this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company', $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company',
's.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company', 's.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company',

View File

@@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.4.2 // FPDI - Version 1.5.2
// //
// Copyright 2004-2011 Setasign - Jan Slabon // Copyright 2004-2014 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,85 +17,98 @@
// limitations under the License. // limitations under the License.
// //
if (!defined('ORD_z')) /**
define('ORD_z',ord('z')); * Class FilterASCII85
if (!defined('ORD_exclmark')) */
define('ORD_exclmark', ord('!')); class FilterASCII85
if (!defined('ORD_u')) {
define('ORD_u', ord('u')); /**
if (!defined('ORD_tilde')) * Decode ASCII85 encoded string
define('ORD_tilde', ord('~')); *
* @param string $in
* @return string
* @throws Exception
*/
public function decode($in)
{
$ord = array(
'~' => ord('~'),
'z' => ord('z'),
'u' => ord('u'),
'z' => ord('z'),
'!' => ord('!')
);
if (!class_exists('FilterASCII85', false)) { $out = '';
$state = 0;
$chn = null;
class FilterASCII85 { $l = strlen($in);
function error($msg) { for ($k = 0; $k < $l; ++$k) {
die($msg); $ch = ord($in[$k]) & 0xff;
}
if ($ch == $ord['~']) {
function decode($in) { break;
$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) {
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 (preg_match('/^\s$/',chr($ch))) {
continue;
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) { if ($ch == $ord['z'] && $state == 0) {
$r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85; $out .= chr(0) . chr(0) . chr(0) . chr(0);
$out .= chr($r >> 24); continue;
$out .= chr($r >> 16);
} }
else if ($state == 4) { if ($ch < $ord['!'] || $ch > $ord['u']) {
$r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ; throw new Exception('Illegal character in ASCII85Decode.');
}
$chn[$state++] = $ch - $ord['!'];
if ($state == 5) {
$state = 0;
$r = 0;
for ($j = 0; $j < 5; ++$j)
$r = $r * 85 + $chn[$j];
$out .= chr($r >> 24); $out .= chr($r >> 24);
$out .= chr($r >> 16); $out .= chr($r >> 16);
$out .= chr($r >> 8); $out .= chr($r >> 8);
$out .= chr($r);
} }
return $out;
} }
$r = 0;
function encode($in) {
return $this->error("ASCII85 encoding not implemented."); if ($state == 1) {
throw new Exception('Illegal length in ASCII85Decode.');
} }
if ($state == 2) {
$r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85;
$out .= chr($r >> 24);
} else if ($state == 3) {
$r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85;
$out .= chr($r >> 24);
$out .= chr($r >> 16);
} else if ($state == 4) {
$r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ;
$out .= chr($r >> 24);
$out .= chr($r >> 16);
$out .= chr($r >> 8);
}
return $out;
} }
}
/**
* NOT IMPLEMENTED
*
* @param string $in
* @return string
* @throws LogicException
*/
public function encode($in)
{
throw new LogicException("ASCII85 encoding not implemented.");
}
}

View File

@@ -0,0 +1,52 @@
<?php
//
// FPDI - Version 1.5.2
//
// Copyright 2004-2014 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.
//
/**
* Class FilterASCIIHexDecode
*/
class FilterASCIIHexDecode
{
/**
* Converts an ASCII hexadecimal encoded string into it's binary representation.
*
* @param string $data The input string
* @return string
*/
public function decode($data)
{
$data = preg_replace('/[^0-9A-Fa-f]/', '', rtrim($data, '>'));
if ((strlen($data) % 2) == 1) {
$data .= '0';
}
return pack('H*', $data);
}
/**
* Converts a string into ASCII hexadecimal representation.
*
* @param string $data The input string
* @param boolean $leaveEOD
* @return string
*/
public function encode($data, $leaveEOD = false)
{
return current(unpack('H*', $data)) . ($leaveEOD ? '' : '>');
}
}

View File

@@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.4.2 // FPDI - Version 1.5.2
// //
// Copyright 2004-2011 Setasign - Jan Slabon // Copyright 2004-2014 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,141 +17,157 @@
// limitations under the License. // limitations under the License.
// //
if (!class_exists('FilterLZW', false)) { /**
* Class FilterLZW
*/
class FilterLZW
{
protected $_sTable = array();
protected $_data = null;
protected $_dataLength = 0;
protected $_tIdx;
protected $_bitsToGet = 9;
protected $_bytePointer;
protected $_bitPointer;
protected $_nextData = 0;
protected $_nextBits = 0;
protected $_andTable = array(511, 1023, 2047, 4095);
class FilterLZW { /**
* Decodes LZW compressed data.
var $sTable = array(); *
var $data = null; * @param string $data The compressed data.
var $dataLength = 0; * @throws Exception
var $tIdx; * @return string
var $bitsToGet = 9; */
var $bytePointer; public function decode($data)
var $bitPointer; {
var $nextData = 0; if ($data[0] == 0x00 && $data[1] == 0x01) {
var $nextBits = 0; throw new Exception('LZW flavour not supported.');
var $andTable = array(511, 1023, 2047, 4095);
function error($msg) {
die($msg);
} }
/** $this->_initsTable();
* Method to decode LZW compressed data.
* $this->_data = $data;
* @param string data The compressed data. $this->_dataLength = strlen($data);
*/
function decode($data) { // Initialize pointers
$this->_bytePointer = 0;
if($data[0] == 0x00 && $data[1] == 0x01) { $this->_bitPointer = 0;
$this->error('LZW flavour not supported.');
} $this->_nextData = 0;
$this->_nextBits = 0;
$this->initsTable();
$oldCode = 0;
$this->data = $data;
$this->dataLength = strlen($data); $unCompData = '';
// Initialize pointers while (($code = $this->_getNextCode()) != 257) {
$this->bytePointer = 0; if ($code == 256) {
$this->bitPointer = 0; $this->_initsTable();
$code = $this->_getNextCode();
$this->nextData = 0;
$this->nextBits = 0; if ($code == 257) {
break;
$oldCode = 0; }
$string = ''; if (!isset($this->_sTable[$code])) {
$uncompData = ''; throw new Exception('Error while decompression LZW compressed data.');
}
while (($code = $this->getNextCode()) != 257) {
if ($code == 256) { $unCompData .= $this->_sTable[$code];
$this->initsTable(); $oldCode = $code;
$code = $this->getNextCode();
} else {
if ($code == 257) {
break; if ($code < $this->_tIdx) {
} $string = $this->_sTable[$code];
$unCompData .= $string;
$uncompData .= $this->sTable[$code];
$this->_addStringToTable($this->_sTable[$oldCode], $string[0]);
$oldCode = $code; $oldCode = $code;
} else { } else {
$string = $this->_sTable[$oldCode];
if ($code < $this->tIdx) { $string = $string . $string[0];
$string = $this->sTable[$code]; $unCompData .= $string;
$uncompData .= $string;
$this->_addStringToTable($string);
$this->addStringToTable($this->sTable[$oldCode], $string[0]); $oldCode = $code;
$oldCode = $code;
} else {
$string = $this->sTable[$oldCode];
$string = $string . $string[0];
$uncompData .= $string;
$this->addStringToTable($string);
$oldCode = $code;
}
} }
} }
return $uncompData;
} }
return $unCompData;
/** }
* Initialize the string table.
*/
function initsTable() { /**
$this->sTable = array(); * Initialize the string table.
*/
for ($i = 0; $i < 256; $i++) protected function _initsTable()
$this->sTable[$i] = chr($i); {
$this->_sTable = array();
$this->tIdx = 258;
$this->bitsToGet = 9; for ($i = 0; $i < 256; $i++)
} $this->_sTable[$i] = chr($i);
/** $this->_tIdx = 258;
* Add a new string to the string table. $this->_bitsToGet = 9;
*/ }
function addStringToTable ($oldString, $newString='') {
$string = $oldString.$newString; /**
* Add a new string to the string table.
// Add this new String to the table */
$this->sTable[$this->tIdx++] = $string; protected function _addStringToTable($oldString, $newString = '')
{
if ($this->tIdx == 511) { $string = $oldString . $newString;
$this->bitsToGet = 10;
} else if ($this->tIdx == 1023) { // Add this new String to the table
$this->bitsToGet = 11; $this->_sTable[$this->_tIdx++] = $string;
} else if ($this->tIdx == 2047) {
$this->bitsToGet = 12; if ($this->_tIdx == 511) {
} $this->_bitsToGet = 10;
} } else if ($this->_tIdx == 1023) {
$this->_bitsToGet = 11;
// Returns the next 9, 10, 11 or 12 bits } else if ($this->_tIdx == 2047) {
function getNextCode() { $this->_bitsToGet = 12;
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.");
} }
} }
}
/**
* Returns the next 9, 10, 11 or 12 bits
*
* @return int
*/
protected function _getNextCode()
{
if ($this->_bytePointer == $this->_dataLength) {
return 257;
}
$this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff);
$this->_nextBits += 8;
if ($this->_nextBits < $this->_bitsToGet) {
$this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff);
$this->_nextBits += 8;
}
$code = ($this->_nextData >> ($this->_nextBits - $this->_bitsToGet)) & $this->_andTable[$this->_bitsToGet-9];
$this->_nextBits -= $this->_bitsToGet;
return $code;
}
/**
* NOT IMPLEMENTED
*
* @param string $in
* @return string
* @throws LogicException
*/
public function encode($in)
{
throw new LogicException("LZW encoding not implemented.");
}
}

View File

@@ -1,8 +1,8 @@
<?php <?php
// //
// FPDF_TPL - Version 1.2 // FPDI - Version 1.5.2
// //
// Copyright 2004-2010 Setasign - Jan Slabon // Copyright 2004-2014 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,70 +17,83 @@
// limitations under the License. // limitations under the License.
// //
class FPDF_TPL extends FPDF { require_once('fpdi_bridge.php');
/**
* Class FPDF_TPL
*/
class FPDF_TPL extends fpdi_bridge
{
/** /**
* Array of Tpl-Data * Array of template data
*
* @var array * @var array
*/ */
var $tpls = array(); protected $_tpls = array();
/** /**
* Current Template-ID * Current Template-Id
*
* @var int * @var int
*/ */
var $tpl = 0; public $tpl = 0;
/**
* "In Template"-Flag
* @var boolean
*/
var $_intpl = false;
/**
* Nameprefix of Templates used in Resources-Dictonary
* @var string A String defining the Prefix used as Template-Object-Names. Have to beginn with an /
*/
var $tplprefix = "/TPL";
/** /**
* Resources used By Templates and Pages * "In Template"-Flag
* @var array *
* @var boolean
*/ */
var $_res = array(); protected $_inTpl = false;
/** /**
* Last used Template data * Name prefix of templates used in Resources dictionary
*
* @var string A String defining the Prefix used as Template-Object-Names. Have to begin with an /
*/
public $tplPrefix = "/TPL";
/**
* Resources used by templates and pages
* *
* @var array * @var array
*/ */
var $lastUsedTemplateData = array(); protected $_res = array();
/** /**
* Start a Template * Last used template data
*
* @var array
*/
public $lastUsedTemplateData = array();
/**
* Start a template.
* *
* This method starts a template. You can give own coordinates to build an own sized * This method starts a template. You can give own coordinates to build an own sized
* Template. Pay attention, that the margins are adapted to the new templatesize. * template. Pay attention, that the margins are adapted to the new template size.
* If you want to write outside the template, for example to build a clipped Template, * If you want to write outside the template, for example to build a clipped template,
* you have to set the Margins and "Cursor"-Position manual after beginTemplate-Call. * you have to set the margins and "cursor"-position manual after beginTemplate()-call.
* *
* If no parameter is given, the template uses the current page-size. * If no parameter is given, the template uses the current page-size.
* The Method returns an ID of the current Template. This ID is used later for using this template. * The method returns an id of the current template. This id is used later for using this template.
* Warning: A created Template is used in PDF at all events. Still if you don't use it after creation! * Warning: A created template is saved in the resulting PDF at all events. Also if you don't use it after creation!
* *
* @param int $x The x-coordinate given in user-unit * @param int $x The x-coordinate given in user-unit
* @param int $y The y-coordinate given in user-unit * @param int $y The y-coordinate given in user-unit
* @param int $w The width given in user-unit * @param int $w The width given in user-unit
* @param int $h The height given in user-unit * @param int $h The height given in user-unit
* @return int The ID of new created Template * @return int The id of new created template
* @throws LogicException
*/ */
function beginTemplate($x = null, $y = null, $w = null, $h = null) { public function beginTemplate($x = null, $y = null, $w = null, $h = null)
if (is_subclass_of($this, 'TCPDF')) { {
$this->Error('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.'); if (is_subclass_of($this, 'TCPDF')) {
return; throw new LogicException('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.');
} }
if ($this->page <= 0) if ($this->page <= 0) {
$this->error("You have to add a page to fpdf first!"); throw new LogicException("You have to add at least a page first!");
}
if ($x == null) if ($x == null)
$x = 0; $x = 0;
@@ -93,7 +106,7 @@ class FPDF_TPL extends FPDF {
// Save settings // Save settings
$this->tpl++; $this->tpl++;
$tpl =& $this->tpls[$this->tpl]; $tpl =& $this->_tpls[$this->tpl];
$tpl = array( $tpl = array(
'o_x' => $this->x, 'o_x' => $this->x,
'o_y' => $this->y, 'o_y' => $this->y,
@@ -104,6 +117,10 @@ class FPDF_TPL extends FPDF {
'o_rMargin' => $this->rMargin, 'o_rMargin' => $this->rMargin,
'o_h' => $this->h, 'o_h' => $this->h,
'o_w' => $this->w, 'o_w' => $this->w,
'o_FontFamily' => $this->FontFamily,
'o_FontStyle' => $this->FontStyle,
'o_FontSizePt' => $this->FontSizePt,
'o_FontSize' => $this->FontSize,
'buffer' => '', 'buffer' => '',
'x' => $x, 'x' => $x,
'y' => $y, 'y' => $y,
@@ -112,34 +129,43 @@ class FPDF_TPL extends FPDF {
); );
$this->SetAutoPageBreak(false); $this->SetAutoPageBreak(false);
// Define own high and width to calculate possitions correct // Define own high and width to calculate correct positions
$this->h = $h; $this->h = $h;
$this->w = $w; $this->w = $w;
$this->_intpl = true; $this->_inTpl = true;
$this->SetXY($x + $this->lMargin, $y + $this->tMargin); $this->SetXY($x + $this->lMargin, $y + $this->tMargin);
$this->SetRightMargin($this->w - $w + $this->rMargin); $this->SetRightMargin($this->w - $w + $this->rMargin);
if ($this->CurrentFont) {
$fontKey = $this->FontFamily . $this->FontStyle;
if ($fontKey) {
$this->_res['tpl'][$this->tpl]['fonts'][$fontKey] =& $this->fonts[$fontKey];
$this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
}
}
return $this->tpl; return $this->tpl;
} }
/** /**
* End Template * End template.
* *
* This method ends a template and reset initiated variables on beginTemplate. * This method ends a template and reset initiated variables collected in {@link beginTemplate()}.
* *
* @return mixed If a template is opened, the ID is returned. If not a false is returned. * @return int|boolean If a template is opened, the id is returned. If not a false is returned.
*/ */
function endTemplate() { public function endTemplate()
if (is_subclass_of($this, 'TCPDF')) { {
$args = func_get_args(); if (is_subclass_of($this, 'TCPDF')) {
return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args); $args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args);
} }
if ($this->_intpl) { if ($this->_inTpl) {
$this->_intpl = false; $this->_inTpl = false;
$tpl =& $this->tpls[$this->tpl]; $tpl = $this->_tpls[$this->tpl];
$this->SetXY($tpl['o_x'], $tpl['o_y']); $this->SetXY($tpl['o_x'], $tpl['o_y']);
$this->tMargin = $tpl['o_tMargin']; $this->tMargin = $tpl['o_tMargin'];
$this->lMargin = $tpl['o_lMargin']; $this->lMargin = $tpl['o_lMargin'];
@@ -147,226 +173,285 @@ class FPDF_TPL extends FPDF {
$this->h = $tpl['o_h']; $this->h = $tpl['o_h'];
$this->w = $tpl['o_w']; $this->w = $tpl['o_w'];
$this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']); $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
$this->FontFamily = $tpl['o_FontFamily'];
$this->FontStyle = $tpl['o_FontStyle'];
$this->FontSizePt = $tpl['o_FontSizePt'];
$this->FontSize = $tpl['o_FontSize'];
$fontKey = $this->FontFamily . $this->FontStyle;
if ($fontKey)
$this->CurrentFont =& $this->fonts[$fontKey];
return $this->tpl; return $this->tpl;
} else { } else {
return false; return false;
} }
} }
/** /**
* Use a Template in current Page or other Template * Use a template in current page or other template.
* *
* You can use a template in a page or in another template. * You can 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. * You can give the used template a new size.
* All parameters are optional. The width or height is calculated automaticaly * All parameters are optional. The width or height is calculated automatically
* if one is given. If no parameter is given the origin size as defined in * if one is given. If no parameter is given the origin size as defined in
* beginTemplate() is used. * {@link beginTemplate()} method is used.
*
* The calculated or used width and height are returned as an array. * The calculated or used width and height are returned as an array.
* *
* @param int $tplidx A valid template-Id * @param int $tplIdx A valid template-id
* @param int $_x The x-position * @param int $x The x-position
* @param int $_y The y-position * @param int $y The y-position
* @param int $_w The new width of the template * @param int $w The new width of the template
* @param int $_h The new height of the template * @param int $h The new height of the template
* @retrun array The height and width of the template * @return array The height and width of the template (array('w' => ..., 'h' => ...))
* @throws LogicException|InvalidArgumentException
*/ */
function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0) { public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0)
if ($this->page <= 0) {
$this->error('You have to add a page first!'); if ($this->page <= 0) {
throw new LogicException('You have to add at least a page 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]; if (!isset($this->_tpls[$tplIdx])) {
$w = $tpl['w']; throw new InvalidArgumentException('Template does not exist!');
$h = $tpl['h']; }
if ($_x == null) if ($this->_inTpl) {
$_x = 0; $this->_res['tpl'][$this->tpl]['tpls'][$tplIdx] =& $this->_tpls[$tplIdx];
if ($_y == null) }
$_y = 0;
$tpl = $this->_tpls[$tplIdx];
$_x += $tpl['x']; $_w = $tpl['w'];
$_y += $tpl['y']; $_h = $tpl['h'];
$wh = $this->getTemplateSize($tplidx, $_w, $_h); if ($x == null) {
$_w = $wh['w']; $x = 0;
$_h = $wh['h']; }
$tData = array( if ($y == null) {
$y = 0;
}
$x += $tpl['x'];
$y += $tpl['y'];
$wh = $this->getTemplateSize($tplIdx, $w, $h);
$w = $wh['w'];
$h = $wh['h'];
$tplData = array(
'x' => $this->x, 'x' => $this->x,
'y' => $this->y, 'y' => $this->y,
'w' => $_w, 'w' => $w,
'h' => $_h, 'h' => $h,
'scaleX' => ($_w / $w), 'scaleX' => ($w / $_w),
'scaleY' => ($_h / $h), 'scaleY' => ($h / $_h),
'tx' => $_x, 'tx' => $x,
'ty' => ($this->h - $_y - $_h), 'ty' => ($this->h - $y - $h),
'lty' => ($this->h - $_y - $_h) - ($this->h - $h) * ($_h / $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));
// reset font in the outer graphic state $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm',
if ($this->FontFamily) { $tplData['scaleX'], $tplData['scaleY'], $tplData['tx'] * $this->k, $tplData['ty'] * $this->k)
$family = $this->FontFamily; ); // Translate
$this->FontFamily = ''; $this->_out(sprintf('%s%d Do Q', $this->tplPrefix, $tplIdx));
$this->SetFont($family);
} $this->lastUsedTemplateData = $tplData;
$this->lastUsedTemplateData = $tData; return array('w' => $w, 'h' => $h);
return array('w' => $_w, 'h' => $_h);
} }
/** /**
* Get The calculated Size of a Template * Get the calculated size of a template.
* *
* If one size is given, this method calculates the other one. * If one size is given, this method calculates the other one.
* *
* @param int $tplidx A valid template-Id * @param int $tplIdx A valid template-id
* @param int $_w The width of the template * @param int $w The width of the template
* @param int $_h The height of the template * @param int $h The height of the template
* @return array The height and width of the template * @return array The height and width of the template (array('w' => ..., 'h' => ...))
*/ */
function getTemplateSize($tplidx, $_w = 0, $_h = 0) { public function getTemplateSize($tplIdx, $w = 0, $h = 0)
if (!$this->tpls[$tplidx]) {
if (!isset($this->_tpls[$tplIdx]))
return false; return false;
$tpl =& $this->tpls[$tplidx]; $tpl = $this->_tpls[$tplIdx];
$w = $tpl['w']; $_w = $tpl['w'];
$h = $tpl['h']; $_h = $tpl['h'];
if ($_w == 0 and $_h == 0) { if ($w == 0 && $h == 0) {
$_w = $w; $w = $_w;
$_h = $h; $h = $_h;
} }
if($_w == 0) if ($w == 0)
$_w = $_h * $w / $h; $w = $h * $_w / $_h;
if($_h == 0) if($h == 0)
$_h = $_w * $h / $w; $h = $w * $_h / $_w;
return array("w" => $_w, "h" => $_h); return array("w" => $w, "h" => $h);
} }
/** /**
* See FPDF/TCPDF-Documentation ;-) * Sets the font used to print character strings.
*
* See FPDF/TCPDF documentation.
*
* @see http://fpdf.org/en/doc/setfont.htm
* @see http://www.tcpdf.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045
*/ */
public function SetFont($family, $style = '', $size = 0) { public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true)
{
if (is_subclass_of($this, 'TCPDF')) { if (is_subclass_of($this, 'TCPDF')) {
$args = func_get_args(); $args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); return call_user_func_array(array($this, 'TCPDF::SetFont'), $args);
} }
/**
* force the resetting of font changes in a template
*/
if ($this->_intpl)
$this->FontFamily = '';
parent::SetFont($family, $style, $size); parent::SetFont($family, $style, $size);
$fontkey = $this->FontFamily . $this->FontStyle; $fontkey = $this->FontFamily . $this->FontStyle;
if ($this->_intpl) { if ($this->_inTpl) {
$this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];
} else { } else {
$this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey]; $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];
} }
} }
/** /**
* See FPDF/TCPDF-Documentation ;-) * Puts an image.
*
* See FPDF/TCPDF documentation.
*
* @see http://fpdf.org/en/doc/image.htm
* @see http://www.tcpdf.org/doc/code/classTCPDF.html#a714c2bee7d6b39d4d6d304540c761352
*/ */
function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '') { public function Image(
$file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false,
$dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false,
$hidden = false, $fitonpage = false, $alt = false, $altimgs = array()
)
{
if (is_subclass_of($this, 'TCPDF')) { if (is_subclass_of($this, 'TCPDF')) {
$args = func_get_args(); $args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::Image'), $args); return call_user_func_array(array($this, 'TCPDF::Image'), $args);
} }
$ret = parent::Image($file, $x, $y, $w, $h, $type, $link); $ret = parent::Image($file, $x, $y, $w, $h, $type, $link);
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 {
$this->_res['page'][$this->page]['images'][$file] =& $this->images[$file]; $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file];
} }
return $ret; return $ret;
} }
/** /**
* See FPDF-Documentation ;-) * Adds a new page to the document.
* *
* AddPage is not available when you're "in" a template. * See FPDF/TCPDF documentation.
*
* This method cannot be used if you'd started a template.
*
* @see http://fpdf.org/en/doc/addpage.htm
* @see http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced
*/ */
function AddPage($orientation = '', $format = '') { public function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false)
if (is_subclass_of($this, 'TCPDF')) { {
$args = func_get_args(); if (is_subclass_of($this, 'TCPDF')) {
return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); $args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::AddPage'), $args);
} }
if ($this->_intpl) if ($this->_inTpl) {
$this->Error('Adding pages in templates isn\'t possible!'); throw new LogicException('Adding pages in templates is not possible!');
}
parent::AddPage($orientation, $format); parent::AddPage($orientation, $format);
} }
/** /**
* Preserve adding Links in Templates ...won't work * Puts a link on a rectangular area of the page.
*
* Overwritten because adding links in a template will not work.
*
* @see http://fpdf.org/en/doc/link.htm
* @see http://www.tcpdf.org/doc/code/classTCPDF.html#ab87bf1826384fbfe30eb499d42f1d994
*/ */
function Link($x, $y, $w, $h, $link) { public function Link($x, $y, $w, $h, $link, $spaces = 0)
{
if (is_subclass_of($this, 'TCPDF')) { if (is_subclass_of($this, 'TCPDF')) {
$args = func_get_args(); $args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::Link'), $args); return call_user_func_array(array($this, 'TCPDF::Link'), $args);
} }
if ($this->_intpl) if ($this->_inTpl) {
$this->Error('Using links in templates aren\'t possible!'); throw new LogicException('Using links in templates is not posible!');
}
parent::Link($x, $y, $w, $h, $link); parent::Link($x, $y, $w, $h, $link);
} }
function AddLink() { /**
if (is_subclass_of($this, 'TCPDF')) { * Creates a new internal link and returns its identifier.
$args = func_get_args(); *
return call_user_func_array(array($this, 'TCPDF::AddLink'), $args); * Overwritten because adding links in a template will not work.
*
* @see http://fpdf.org/en/doc/addlink.htm
* @see http://www.tcpdf.org/doc/code/classTCPDF.html#a749522038ed7786c3e1701435dcb891e
*/
public function AddLink()
{
if (is_subclass_of($this, 'TCPDF')) {
$args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::AddLink'), $args);
} }
if ($this->_intpl) if ($this->_inTpl) {
$this->Error('Adding links in templates aren\'t possible!'); throw new LogicException('Adding links in templates is not possible!');
}
return parent::AddLink(); return parent::AddLink();
} }
function SetLink($link, $y = 0, $page = -1) { /**
if (is_subclass_of($this, 'TCPDF')) { * Defines the page and position a link points to.
$args = func_get_args(); *
return call_user_func_array(array($this, 'TCPDF::SetLink'), $args); * Overwritten because adding links in a template will not work.
*
* @see http://fpdf.org/en/doc/setlink.htm
* @see http://www.tcpdf.org/doc/code/classTCPDF.html#ace5be60e7857953ea5e2b89cb90df0ae
*/
public function SetLink($link, $y = 0, $page = -1)
{
if (is_subclass_of($this, 'TCPDF')) {
$args = func_get_args();
return call_user_func_array(array($this, 'TCPDF::SetLink'), $args);
} }
if ($this->_intpl) if ($this->_inTpl) {
$this->Error('Setting links in templates aren\'t possible!'); throw new LogicException('Setting links in templates is not possible!');
}
parent::SetLink($link, $y, $page); 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(); * Writes the form XObjects to the PDF document.
$this->tpls[$tplidx]['n'] = $this->n; */
$this->_out('<<'.$filter.'/Type /XObject'); protected function _putformxobjects()
{
$filter=($this->compress) ? '/Filter /FlateDecode ' : '';
reset($this->_tpls);
foreach($this->_tpls AS $tplIdx => $tpl) {
$this->_newobj();
$this->_tpls[$tplIdx]['n'] = $this->n;
$this->_out('<<'.$filter.'/Type /XObject');
$this->_out('/Subtype /Form'); $this->_out('/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]',
@@ -379,69 +464,90 @@ class FPDF_TPL extends FPDF {
// ury // ury
($tpl['h'] - $tpl['y']) * $this->k ($tpl['h'] - $tpl['y']) * $this->k
)); ));
if ($tpl['x'] != 0 || $tpl['y'] != 0) { if ($tpl['x'] != 0 || $tpl['y'] != 0) {
$this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',
-$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2
)); ));
} }
$this->_out('/Resources ');
$this->_out('/Resources ');
$this->_out('<</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'])) {
$this->_out('/Font <<'); if (isset($this->_res['tpl'][$tplIdx])) {
foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) $res = $this->_res['tpl'][$tplIdx];
$this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); if (isset($res['fonts']) && count($res['fonts'])) {
$this->_out('>>'); $this->_out('/Font <<');
foreach($res['fonts'] as $font) {
$this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
}
$this->_out('>>');
}
if(isset($res['images']) || isset($res['tpls'])) {
$this->_out('/XObject <<');
if (isset($res['images'])) {
foreach($res['images'] as $image)
$this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
}
if (isset($res['tpls'])) {
foreach($res['tpls'] as $i => $_tpl)
$this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
}
$this->_out('>>');
}
} }
if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) ||
isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) $this->_out('>>');
{
$this->_out('/XObject <<'); $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { $this->_out('/Length ' . strlen($buffer) . ' >>');
foreach($this->_res['tpl'][$tplidx]['images'] as $image) $this->_putstream($buffer);
$this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); $this->_out('endobj');
}
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() * Output images.
* *
* Overwritten to add {@link _putformxobjects()} after _putimages().
*/ */
function _putimages() { public function _putimages()
{
parent::_putimages(); parent::_putimages();
$this->_putformxobjects(); $this->_putformxobjects();
} }
function _putxobjectdict() { /**
* Writes the references of XObject resources to the document.
*
* Overwritten to add the the templates to the XObject resource dictionary.
*/
public function _putxobjectdict()
{
parent::_putxobjectdict(); parent::_putxobjectdict();
if (count($this->tpls)) { foreach($this->_tpls as $tplIdx => $tpl) {
foreach($this->tpls as $tplidx => $tpl) { $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']));
$this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n']));
}
} }
} }
/** /**
* Private Method * Writes bytes to the resulting document.
*
* Overwritten to delegate the data to the template buffer.
*
* @param string $s
*/ */
function _out($s) { public function _out($s)
if ($this->state == 2 && $this->_intpl) { {
$this->tpls[$this->tpl]['buffer'] .= $s . "\n"; if ($this->state == 2 && $this->_inTpl) {
$this->_tpls[$this->tpl]['buffer'] .= $s . "\n";
} else { } else {
parent::_out($s); parent::_out($s);
} }

View File

@@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.4.2 // FPDI - Version 1.5.2
// //
// Copyright 2004-2011 Setasign - Jan Slabon // Copyright 2004-2014 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,78 +17,101 @@
// limitations under the License. // limitations under the License.
// //
define('FPDI_VERSION', '1.4.2');
// Check for TCPDF and remap TCPDF to FPDF
if (class_exists('TCPDF', false)) {
require_once('fpdi2tcpdf_bridge.php');
}
require_once('fpdf_tpl.php'); require_once('fpdf_tpl.php');
require_once('fpdi_pdf_parser.php');
/**
* Class FPDI
*/
class FPDI extends FPDF_TPL
{
/**
* FPDI version
*
* @string
*/
const VERSION = '1.5.2';
class FPDI extends FPDF_TPL {
/** /**
* Actual filename * Actual filename
*
* @var string * @var string
*/ */
var $current_filename; public $currentFilename;
/** /**
* Parser-Objects * Parser-Objects
* @var array *
* @var fpdi_pdf_parser[]
*/ */
var $parsers; public $parsers = array();
/** /**
* Current parser * Current parser
* @var object *
* @var fpdi_pdf_parser
*/ */
var $current_parser; public $currentParser;
/** /**
* object stack * The name of the last imported page box
*
* @var string
*/
public $lastUsedPageBox;
/**
* Object stack
*
* @var array * @var array
*/ */
var $_obj_stack; protected $_objStack;
/** /**
* done object stack * Done object stack
*
* @var array * @var array
*/ */
var $_don_obj_stack; protected $_doneObjStack;
/** /**
* Current Object Id. * Current Object Id.
*
* @var integer * @var integer
*/ */
var $_current_obj_id; protected $_currentObjId;
/**
* The name of the last imported page box
* @var string
*/
var $lastUsedPageBox;
/** /**
* Cache for imported pages/template ids * Cache for imported pages/template ids
*
* @var array * @var array
*/ */
var $_importedPages = array(); protected $_importedPages = array();
/** /**
* Set a source-file * Set a source-file.
* *
* @param string $filename a valid filename * Depending on the PDF version of the used document the PDF version of the resulting document will
* @return int number of available pages * be adjusted to the higher version.
*
* @param string $filename A valid path to the PDF document from which pages should be imported from
* @return int The number of pages in the document
*/ */
function setSourceFile($filename) { public function setSourceFile($filename)
$this->current_filename = $filename; {
$_filename = realpath($filename);
if (false !== $_filename)
$filename = $_filename;
$this->currentFilename = $filename;
if (!isset($this->parsers[$filename])) if (!isset($this->parsers[$filename])) {
$this->parsers[$filename] = $this->_getPdfParser($filename); $this->parsers[$filename] = $this->_getPdfParser($filename);
$this->current_parser =& $this->parsers[$filename]; $this->setPdfVersion(
max($this->getPdfVersion(), $this->parsers[$filename]->getPdfVersion())
);
}
$this->currentParser =& $this->parsers[$filename];
return $this->parsers[$filename]->getPageCount(); return $this->parsers[$filename]->getPageCount();
} }
@@ -99,53 +122,80 @@ class FPDI extends FPDF_TPL {
* @param string $filename * @param string $filename
* @return fpdi_pdf_parser * @return fpdi_pdf_parser
*/ */
function _getPdfParser($filename) { protected function _getPdfParser($filename)
return new fpdi_pdf_parser($filename, $this); {
require_once('fpdi_pdf_parser.php');
return new fpdi_pdf_parser($filename);
} }
/** /**
* Get the current PDF version * Get the current PDF version.
* *
* @return string * @return string
*/ */
function getPDFVersion() { public function getPdfVersion()
{
return $this->PDFVersion; return $this->PDFVersion;
} }
/** /**
* Set the PDF version * Set the PDF version.
* *
* @return string * @param string $version
*/ */
function setPDFVersion($version = '1.3') { public function setPdfVersion($version = '1.3')
$this->PDFVersion = $version; {
} $this->PDFVersion = sprintf('%.1F', $version);
}
/** /**
* Import a page * Import a page.
* *
* @param int $pageno pagenumber * The second parameter defines the bounding box that should be used to transform the page into a
* @return int Index of imported page - to use with fpdf_tpl::useTemplate() * form XObject.
*
* Following values are available: MediaBox, CropBox, BleedBox, TrimBox, ArtBox.
* If a box is not especially defined its default box will be used:
*
* <ul>
* <li>CropBox: Default -> MediaBox</li>
* <li>BleedBox: Default -> CropBox</li>
* <li>TrimBox: Default -> CropBox</li>
* <li>ArtBox: Default -> CropBox</li>
* </ul>
*
* It is possible to get the used page box by the {@link getLastUsedPageBox()} method.
*
* @param int $pageNo The page number
* @param string $boxName The boundary box to use when transforming the page into a form XObject
* @param boolean $groupXObject Define the form XObject as a group XObject to support transparency (if used)
* @return int An id of the imported page/template to use with e.g. fpdf_tpl::useTemplate()
* @throws LogicException|InvalidArgumentException
* @see getLastUsedPageBox()
*/ */
function importPage($pageno, $boxName = '/CropBox') { public function importPage($pageNo, $boxName = 'CropBox', $groupXObject = true)
if ($this->_intpl) { {
return $this->error('Please import the desired pages before creating a new template.'); if ($this->_inTpl) {
throw new LogicException('Please import the desired pages before creating a new template.');
} }
$fn = $this->current_filename; $fn = $this->currentFilename;
$boxName = '/' . ltrim($boxName, '/');
// check if page already imported
$pageKey = $fn . '-' . ((int)$pageno) . $boxName;
if (isset($this->_importedPages[$pageKey]))
return $this->_importedPages[$pageKey];
$parser =& $this->parsers[$fn];
$parser->setPageno($pageno);
if (!in_array($boxName, $parser->availableBoxes)) // check if page already imported
return $this->Error(sprintf('Unknown box: %s', $boxName)); $pageKey = $fn . '-' . ((int)$pageNo) . $boxName;
if (isset($this->_importedPages[$pageKey])) {
return $this->_importedPages[$pageKey];
}
$parser = $this->parsers[$fn];
$parser->setPageNo($pageNo);
if (!in_array($boxName, $parser->availableBoxes)) {
throw new InvalidArgumentException(sprintf('Unknown box: %s', $boxName));
}
$pageboxes = $parser->getPageBoxes($pageno, $this->k); $pageBoxes = $parser->getPageBoxes($pageNo, $this->k);
/** /**
* MediaBox * MediaBox
@@ -154,35 +204,39 @@ class FPDI extends FPDF_TPL {
* TrimBox: Default -> CropBox * TrimBox: Default -> CropBox
* ArtBox: Default -> CropBox * ArtBox: Default -> CropBox
*/ */
if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) if (!isset($pageBoxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox'))
$boxName = '/CropBox'; $boxName = '/CropBox';
if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox') if (!isset($pageBoxes[$boxName]) && $boxName == '/CropBox')
$boxName = '/MediaBox'; $boxName = '/MediaBox';
if (!isset($pageboxes[$boxName])) if (!isset($pageBoxes[$boxName]))
return false; return false;
$this->lastUsedPageBox = $boxName; $this->lastUsedPageBox = $boxName;
$box = $pageboxes[$boxName]; $box = $pageBoxes[$boxName];
$this->tpl++; $this->tpl++;
$this->tpls[$this->tpl] = array(); $this->_tpls[$this->tpl] = array();
$tpl =& $this->tpls[$this->tpl]; $tpl =& $this->_tpls[$this->tpl];
$tpl['parser'] =& $parser; $tpl['parser'] = $parser;
$tpl['resources'] = $parser->getPageResources(); $tpl['resources'] = $parser->getPageResources();
$tpl['buffer'] = $parser->getContent(); $tpl['buffer'] = $parser->getContent();
$tpl['box'] = $box; $tpl['box'] = $box;
$tpl['groupXObject'] = $groupXObject;
if ($groupXObject) {
$this->setPdfVersion(max($this->getPdfVersion(), 1.4));
}
// To build an array that can be used by PDF_TPL::useTemplate() // To build an array that can be used by PDF_TPL::useTemplate()
$this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl], $box); $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() // An imported page will start at 0,0 all the time. Translation will be set in _putformxobjects()
$tpl['x'] = 0; $tpl['x'] = 0;
$tpl['y'] = 0; $tpl['y'] = 0;
// handle rotated pages // handle rotated pages
$rotation = $parser->getPageRotation($pageno); $rotation = $parser->getPageRotation($pageNo);
$tpl['_rotationAngle'] = 0; $tpl['_rotationAngle'] = 0;
if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) { if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) {
$steps = $angle / 90; $steps = $angle / 90;
@@ -204,18 +258,41 @@ class FPDI extends FPDF_TPL {
} }
/** /**
* Returns the last used page box * Returns the last used page boundary box.
* *
* @return string * @return string The used boundary box: MediaBox, CropBox, BleedBox, TrimBox or ArtBox
*/ */
function getLastUsedPageBox() { public function getLastUsedPageBox()
{
return $this->lastUsedPageBox; return $this->lastUsedPageBox;
} }
/**
function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0, $adjustPageSize = false) { * Use a template or imported page in current page or other template.
if ($adjustPageSize == true && is_null($_x) && is_null($_y)) { *
$size = $this->getTemplateSize($tplidx, $_w, $_h); * You can use a template in a page or in another template.
* You can give the used template a new size. All parameters are optional.
* The width or height is calculated automatically if one is given. If no
* parameter is given the origin size as defined in beginTemplate() or of
* the imported page is used.
*
* The calculated or used width and height are returned as an array.
*
* @param int $tplIdx A valid template-id
* @param int $x The x-position
* @param int $y The y-position
* @param int $w The new width of the template
* @param int $h The new height of the template
* @param boolean $adjustPageSize If set to true the current page will be resized to fit the dimensions
* of the template
*
* @return array The height and width of the template (array('w' => ..., 'h' => ...))
* @throws LogicException|InvalidArgumentException
*/
public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0, $adjustPageSize = false)
{
if ($adjustPageSize == true && is_null($x) && is_null($y)) {
$size = $this->getTemplateSize($tplIdx, $w, $h);
$orientation = $size['w'] > $size['h'] ? 'L' : 'P'; $orientation = $size['w'] > $size['h'] ? 'L' : 'P';
$size = array($size['w'], $size['h']); $size = array($size['w'], $size['h']);
@@ -224,22 +301,21 @@ class FPDI extends FPDF_TPL {
} else { } else {
$size = $this->_getpagesize($size); $size = $this->_getpagesize($size);
if($orientation!=$this->CurOrientation || $size[0]!=$this->CurPageSize[0] || $size[1]!=$this->CurPageSize[1]) if($orientation != $this->CurOrientation ||
{ $size[0] != $this->CurPageSize[0] ||
$size[1] != $this->CurPageSize[1]
) {
// New size or orientation // New size or orientation
if($orientation=='P') if ($orientation=='P') {
{
$this->w = $size[0]; $this->w = $size[0];
$this->h = $size[1]; $this->h = $size[1];
} } else {
else
{
$this->w = $size[1]; $this->w = $size[1];
$this->h = $size[0]; $this->h = $size[0];
} }
$this->wPt = $this->w*$this->k; $this->wPt = $this->w * $this->k;
$this->hPt = $this->h*$this->k; $this->hPt = $this->h * $this->k;
$this->PageBreakTrigger = $this->h-$this->bMargin; $this->PageBreakTrigger = $this->h - $this->bMargin;
$this->CurOrientation = $orientation; $this->CurOrientation = $orientation;
$this->CurPageSize = $size; $this->CurPageSize = $size;
$this->PageSizes[$this->page] = array($this->wPt, $this->hPt); $this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
@@ -248,54 +324,57 @@ class FPDI extends FPDF_TPL {
} }
$this->_out('q 0 J 1 w 0 j 0 G 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); $size = parent::useTemplate($tplIdx, $x, $y, $w, $h);
$this->_out('Q'); $this->_out('Q');
return $s; return $size;
} }
/** /**
* Private method, that rebuilds all needed objects of source files * Copy all imported objects to the resulting document.
*/ */
function _putimportedobjects() { protected function _putimportedobjects()
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->currentParser =& $p;
if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { if (!isset($this->_objStack[$filename]) || !is_array($this->_objStack[$filename])) {
while(($n = key($this->_obj_stack[$filename])) !== null) { continue;
$nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]); }
while(($n = key($this->_objStack[$filename])) !== null) {
$this->_newobj($this->_obj_stack[$filename][$n][0]); try {
$nObj = $this->currentParser->resolveObject($this->_objStack[$filename][$n][1]);
if ($nObj[0] == PDF_TYPE_STREAM) { } catch (Exception $e) {
$this->pdf_write_value($nObj); $nObj = array(pdf_parser::TYPE_OBJECT, pdf_parser::TYPE_NULL);
} 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]);
}
} }
$this->_newobj($this->_objStack[$filename][$n][0]);
if ($nObj[0] == pdf_parser::TYPE_STREAM) {
$this->_writeValue($nObj);
} else {
$this->_writeValue($nObj[1]);
}
$this->_out("\nendobj");
$this->_objStack[$filename][$n] = null; // free memory
unset($this->_objStack[$filename][$n]);
reset($this->_objStack[$filename]);
} }
} }
} }
/** /**
* Private Method that writes the form xobjects * Writes the form XObjects to the PDF document.
*/ */
function _putformxobjects() { protected function _putformxobjects()
$filter=($this->compress) ? '/Filter /FlateDecode ' : ''; {
reset($this->tpls); $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
foreach($this->tpls AS $tplidx => $tpl) { reset($this->_tpls);
$p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; foreach($this->_tpls AS $tplIdx => $tpl) {
$this->_newobj(); $this->_newobj();
$cN = $this->n; // TCPDF/Protection: rem current "n" $currentN = $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');
@@ -318,8 +397,8 @@ class FPDI extends FPDF_TPL {
if ($tpl['_rotationAngle'] <> 0) { if ($tpl['_rotationAngle'] <> 0) {
$angle = $tpl['_rotationAngle'] * M_PI/180; $angle = $tpl['_rotationAngle'] * M_PI/180;
$c=cos($angle); $c = cos($angle);
$s=sin($angle); $s = sin($angle);
switch($tpl['_rotationAngle']) { switch($tpl['_rotationAngle']) {
case -90: case -90:
@@ -353,87 +432,107 @@ class FPDI extends FPDF_TPL {
$this->_out('/Resources '); $this->_out('/Resources ');
if (isset($tpl['resources'])) { if (isset($tpl['resources'])) {
$this->current_parser =& $tpl['parser']; $this->currentParser = $tpl['parser'];
$this->pdf_write_value($tpl['resources']); // "n" will be changed $this->_writeValue($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])) {
$this->_out('/Font <<'); $res = $this->_res['tpl'][$tplIdx];
foreach($this->_res['tpl'][$tplidx]['fonts'] as $font)
$this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); if (isset($res['fonts']) && count($res['fonts'])) {
$this->_out('>>'); $this->_out('/Font <<');
} foreach ($res['fonts'] as $font)
if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) $this->_out('>>');
{
$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'])) { if (isset($res['images']) && count($res['images']) ||
foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) isset($res['tpls']) && count($res['tpls']))
$this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); {
$this->_out('/XObject <<');
if (isset($res['images'])) {
foreach ($res['images'] as $image)
$this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
}
if (isset($res['tpls'])) {
foreach ($res['tpls'] as $i => $_tpl)
$this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
}
$this->_out('>>');
} }
$this->_out('>>'); $this->_out('>>');
} }
$this->_out('>>');
} }
$nN = $this->n; // TCPDF: rem new "n" if (isset($tpl['groupXObject']) && $tpl['groupXObject']) {
$this->n = $cN; // TCPDF: reset to current "n" $this->_out('/Group <</Type/Group/S/Transparency>>');
}
$newN = $this->n; // TCPDF: rem new "n"
$this->n = $currentN; // TCPDF: reset to current "n"
$buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
if (is_subclass_of($this, 'TCPDF')) { if (is_subclass_of($this, 'TCPDF')) {
$p = $this->_getrawstream($p); $buffer = $this->_getrawstream($buffer);
$this->_out('/Length ' . strlen($p) . ' >>'); $this->_out('/Length ' . strlen($buffer) . ' >>');
$this->_out("stream\n" . $p . "\nendstream"); $this->_out("stream\n" . $buffer . "\nendstream");
} else { } else {
$this->_out('/Length ' . strlen($p) . ' >>'); $this->_out('/Length ' . strlen($buffer) . ' >>');
$this->_putstream($p); $this->_putstream($buffer);
} }
$this->_out('endobj'); $this->_out('endobj');
$this->n = $nN; // TCPDF: reset to new "n" $this->n = $newN; // TCPDF: reset to new "n"
} }
$this->_putimportedobjects(); $this->_putimportedobjects();
} }
/** /**
* Creates and optionally write the object definition to the document.
*
* Rewritten to handle existing own defined objects * Rewritten to handle existing own defined objects
*
* @param bool $objId
* @param bool $onlyNewObj
* @return bool|int
*/ */
function _newobj($obj_id = false, $onlynewobj = false) { public function _newobj($objId = false, $onlyNewObj = false)
if (!$obj_id) { {
$obj_id = ++$this->n; if (!$objId) {
$objId = ++$this->n;
} }
//Begin a new object //Begin a new object
if (!$onlynewobj) { if (!$onlyNewObj) {
$this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); $this->offsets[$objId] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer);
$this->_out($obj_id . ' 0 obj'); $this->_out($objId . ' 0 obj');
$this->_current_obj_id = $obj_id; // for later use with encryption $this->_currentObjId = $objId; // for later use with encryption
} }
return $obj_id; return $objId;
} }
/** /**
* Writes a value * Writes a PDF value to the resulting document.
*
* Needed to rebuild the source document * Needed to rebuild the source document
* *
* @param mixed $value A PDF-Value. Structure of values see cases in this method * @param mixed $value A PDF-Value. Structure of values see cases in this method
*/ */
function pdf_write_value(&$value) protected function _writeValue(&$value)
{ {
if (is_subclass_of($this, 'TCPDF')) { if (is_subclass_of($this, 'TCPDF')) {
parent::pdf_write_value($value); parent::_prepareValue($value);
} }
switch ($value[0]) { switch ($value[0]) {
case PDF_TYPE_TOKEN: case pdf_parser::TYPE_TOKEN:
$this->_straightOut($value[1] . ' '); $this->_straightOut($value[1] . ' ');
break; break;
case PDF_TYPE_NUMERIC: case pdf_parser::TYPE_NUMERIC:
case PDF_TYPE_REAL: case pdf_parser::TYPE_REAL:
if (is_float($value[1]) && $value[1] != 0) { if (is_float($value[1]) && $value[1] != 0) {
$this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' '); $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ');
} else { } else {
@@ -441,20 +540,20 @@ class FPDI extends FPDF_TPL {
} }
break; break;
case PDF_TYPE_ARRAY: case pdf_parser::TYPE_ARRAY:
// An array. Output the proper // An array. Output the proper
// structure and move on. // structure and move on.
$this->_straightOut('['); $this->_straightOut('[');
for ($i = 0; $i < count($value[1]); $i++) { for ($i = 0; $i < count($value[1]); $i++) {
$this->pdf_write_value($value[1][$i]); $this->_writeValue($value[1][$i]);
} }
$this->_out(']'); $this->_out(']');
break; break;
case PDF_TYPE_DICTIONARY: case pdf_parser::TYPE_DICTIONARY:
// A dictionary. // A dictionary.
$this->_straightOut('<<'); $this->_straightOut('<<');
@@ -463,55 +562,54 @@ class FPDI extends FPDF_TPL {
while (list($k, $v) = each($value[1])) { while (list($k, $v) = each($value[1])) {
$this->_straightOut($k . ' '); $this->_straightOut($k . ' ');
$this->pdf_write_value($v); $this->_writeValue($v);
} }
$this->_straightOut('>>'); $this->_straightOut('>>');
break; break;
case PDF_TYPE_OBJREF: case pdf_parser::TYPE_OBJREF:
// An indirect object reference // An indirect object reference
// Fill the object stack if needed // Fill the object stack if needed
$cpfn =& $this->current_parser->filename; $cpfn =& $this->currentParser->filename;
if (!isset($this->_doneObjStack[$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->_objStack[$cpfn][$value[1]] = array($this->n, $value);
$this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! $this->_doneObjStack[$cpfn][$value[1]] = array($this->n, $value);
} }
$objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; $objId = $this->_doneObjStack[$cpfn][$value[1]][0];
$this->_out($objid . ' 0 R'); $this->_out($objId . ' 0 R');
break; break;
case PDF_TYPE_STRING: case pdf_parser::TYPE_STRING:
// A string. // A string.
$this->_straightOut('(' . $value[1] . ')'); $this->_straightOut('(' . $value[1] . ')');
break; break;
case PDF_TYPE_STREAM: case pdf_parser::TYPE_STREAM:
// A stream. First, output the // A stream. First, output the
// stream dictionary, then the // stream dictionary, then the
// stream data itself. // stream data itself.
$this->pdf_write_value($value[1]); $this->_writeValue($value[1]);
$this->_out('stream'); $this->_out('stream');
$this->_out($value[2][1]); $this->_out($value[2][1]);
$this->_out('endstream'); $this->_straightOut("endstream");
break; break;
case PDF_TYPE_HEX: case pdf_parser::TYPE_HEX:
$this->_straightOut('<' . $value[1] . '>'); $this->_straightOut('<' . $value[1] . '>');
break; break;
case PDF_TYPE_BOOLEAN: case pdf_parser::TYPE_BOOLEAN:
$this->_straightOut($value[1] ? 'true ' : 'false '); $this->_straightOut($value[1] ? 'true ' : 'false ');
break; break;
case PDF_TYPE_NULL: case pdf_parser::TYPE_NULL:
// The null object. // The null object.
$this->_straightOut('null '); $this->_straightOut('null ');
@@ -521,51 +619,77 @@ class FPDI extends FPDF_TPL {
/** /**
* Modified so not each call will add a newline to the output. * Modified _out() method so not each call will add a newline to the output.
*/ */
function _straightOut($s) { protected function _straightOut($s)
{
if (!is_subclass_of($this, 'TCPDF')) { if (!is_subclass_of($this, 'TCPDF')) {
if($this->state==2) if ($this->state == 2) {
$this->pages[$this->page] .= $s; $this->pages[$this->page] .= $s;
else } else {
$this->buffer .= $s; $this->buffer .= $s;
}
} else { } else {
if ($this->state == 2) { if ($this->state == 2) {
if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { if ($this->inxobj) {
// we are inside an XObject template
$this->xobjects[$this->xobjid]['outdata'] .= $s;
} else if ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
// puts data before page footer // puts data before page footer
$page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); $pagebuff = $this->getPageBuffer($this->page);
$footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); $page = substr($pagebuff, 0, -$this->footerlen[$this->page]);
$this->setPageBuffer($this->page, $page . ' ' . $s . "\n" . $footer); $footer = substr($pagebuff, -$this->footerlen[$this->page]);
$this->setPageBuffer($this->page, $page . $s . $footer);
// update footer position
$this->footerpos[$this->page] += strlen($s);
} else { } else {
// set page data
$this->setPageBuffer($this->page, $s, true); $this->setPageBuffer($this->page, $s, true);
} }
} else { } else if ($this->state > 0) {
// set general data
$this->setBuffer($s); $this->setBuffer($s);
} }
} }
} }
/** /**
* rewritten to close opened parsers * Ends the document
* *
* Overwritten to close opened parsers
*/ */
function _enddoc() { public function _enddoc()
{
parent::_enddoc(); parent::_enddoc();
$this->_closeParsers(); $this->_closeParsers();
} }
/** /**
* close all files opened by parsers * Close all files opened by parsers.
*
* @return boolean
*/ */
function _closeParsers() { protected function _closeParsers()
if ($this->state > 2 && count($this->parsers) > 0) { {
foreach ($this->parsers as $k => $_){ if ($this->state > 2) {
$this->parsers[$k]->closeFile(); $this->cleanUp();
$this->parsers[$k] = null;
unset($this->parsers[$k]);
}
return true; return true;
} }
return false; return false;
} }
/**
* Removes cycled references and closes the file handles of the parser objects.
*/
public function cleanUp()
{
while (($parser = array_pop($this->parsers)) !== null) {
/**
* @var fpdi_pdf_parser $parser
*/
$parser->closeFile();
}
}
} }

View File

@@ -1,167 +0,0 @@
<?php
//
// FPDI - Version 1.4.2
//
// Copyright 2004-2011 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 {
function _putstream($s) {
$this->_out($this->_getstream($s));
}
function _getxobjectdict() {
$out = parent::_getxobjectdict();
if (count($this->tpls)) {
foreach($this->tpls as $tplidx => $tpl) {
$out .= sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n']);
}
}
return $out;
}
/**
* 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->_encrypt_data($this->_current_obj_id, $value[1]);
$value[1] = $this->_escape($value[1]);
}
break;
case PDF_TYPE_STREAM:
if ($this->encrypted) {
$value[2][1] = $this->_encrypt_data($this->_current_obj_id, $value[2][1]);
$value[1][1]['/Length'] = array(
PDF_TYPE_NUMERIC,
strlen($value[2][1])
);
}
break;
case PDF_TYPE_HEX:
if ($this->encrypted) {
$value[1] = $this->hex2str($value[1]);
$value[1] = $this->_encrypt_data($this->_current_obj_id, $value[1]);
// remake hexstring of encrypted string
$value[1] = $this->str2hex($value[1]);
}
break;
}
}
/**
* Unescapes a PDF string
*
* @param string $s
* @return string
*/
function _unescape($s) {
$out = '';
for ($count = 0, $n = strlen($s); $count < $n; $count++) {
if ($s[$count] != '\\' || $count == $n-1) {
$out .= $s[$count];
} else {
switch ($s[++$count]) {
case ')':
case '(':
case '\\':
$out .= $s[$count];
break;
case 'f':
$out .= chr(0x0C);
break;
case 'b':
$out .= chr(0x08);
break;
case 't':
$out .= chr(0x09);
break;
case 'r':
$out .= chr(0x0D);
break;
case 'n':
$out .= chr(0x0A);
break;
case "\r":
if ($count != $n-1 && $s[$count+1] == "\n")
$count++;
break;
case "\n":
break;
default:
// Octal-Values
if (ord($s[$count]) >= ord('0') &&
ord($s[$count]) <= ord('9')) {
$oct = ''. $s[$count];
if (ord($s[$count+1]) >= ord('0') &&
ord($s[$count+1]) <= ord('9')) {
$oct .= $s[++$count];
if (ord($s[$count+1]) >= ord('0') &&
ord($s[$count+1]) <= ord('9')) {
$oct .= $s[++$count];
}
}
$out .= chr(octdec($oct));
} else {
$out .= $s[$count];
}
}
}
}
return $out;
}
/**
* Hexadecimal to string
*
* @param string $hex
* @return string
*/
function hex2str($hex) {
return pack('H*', str_replace(array("\r", "\n", ' '), '', $hex));
}
/**
* String to hexadecimal
*
* @param string $str
* @return string
*/
function str2hex($str) {
return current(unpack('H*', $str));
}
}

View File

@@ -0,0 +1,215 @@
<?php
//
// FPDI - Version 1.5.2
//
// Copyright 2004-2014 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 file is used as a bridge between TCPDF or FPDF
* It will dynamically create the class extending the available
* class FPDF or TCPDF.
*
* This way it is possible to use FPDI for both FPDF and TCPDF with one FPDI version.
*/
if (!class_exists('TCPDF', false)) {
/**
* Class fpdi_bridge
*/
class fpdi_bridge extends FPDF
{
// empty body
}
} else {
/**
* Class fpdi_bridge
*/
class fpdi_bridge extends TCPDF
{
/**
* Array of Tpl-Data
*
* @var array
*/
protected $_tpls = array();
/**
* Name-prefix of Templates used in Resources-Dictionary
*
* @var string A String defining the Prefix used as Template-Object-Names. Have to begin with an /
*/
public $tplPrefix = "/TPL";
/**
* Current Object Id.
*
* @var integer
*/
protected $_currentObjId;
/**
* Return XObjects Dictionary.
*
* Overwritten to add additional XObjects to the resources dictionary of TCPDF
*
* @return string
*/
protected function _getxobjectdict()
{
$out = parent::_getxobjectdict();
foreach ($this->_tpls as $tplIdx => $tpl) {
$out .= sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']);
}
return $out;
}
/**
* Writes a PDF value to the resulting document.
*
* Prepares the value for encryption of imported data by FPDI
*
* @param array $value
*/
protected function _prepareValue(&$value)
{
switch ($value[0]) {
case pdf_parser::TYPE_STRING:
if ($this->encrypted) {
$value[1] = $this->_unescape($value[1]);
$value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]);
$value[1] = TCPDF_STATIC::_escape($value[1]);
}
break;
case pdf_parser::TYPE_STREAM:
if ($this->encrypted) {
$value[2][1] = $this->_encrypt_data($this->_currentObjId, $value[2][1]);
$value[1][1]['/Length'] = array(
pdf_parser::TYPE_NUMERIC,
strlen($value[2][1])
);
}
break;
case pdf_parser::TYPE_HEX:
if ($this->encrypted) {
$value[1] = $this->hex2str($value[1]);
$value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]);
// remake hexstring of encrypted string
$value[1] = $this->str2hex($value[1]);
}
break;
}
}
/**
* Un-escapes a PDF string
*
* @param string $s
* @return string
*/
protected function _unescape($s)
{
$out = '';
for ($count = 0, $n = strlen($s); $count < $n; $count++) {
if ($s[$count] != '\\' || $count == $n-1) {
$out .= $s[$count];
} else {
switch ($s[++$count]) {
case ')':
case '(':
case '\\':
$out .= $s[$count];
break;
case 'f':
$out .= chr(0x0C);
break;
case 'b':
$out .= chr(0x08);
break;
case 't':
$out .= chr(0x09);
break;
case 'r':
$out .= chr(0x0D);
break;
case 'n':
$out .= chr(0x0A);
break;
case "\r":
if ($count != $n-1 && $s[$count+1] == "\n")
$count++;
break;
case "\n":
break;
default:
// Octal-Values
if (ord($s[$count]) >= ord('0') &&
ord($s[$count]) <= ord('9')) {
$oct = ''. $s[$count];
if (ord($s[$count+1]) >= ord('0') &&
ord($s[$count+1]) <= ord('9')) {
$oct .= $s[++$count];
if (ord($s[$count+1]) >= ord('0') &&
ord($s[$count+1]) <= ord('9')) {
$oct .= $s[++$count];
}
}
$out .= chr(octdec($oct));
} else {
$out .= $s[$count];
}
}
}
}
return $out;
}
/**
* Hexadecimal to string
*
* @param string $data
* @return string
*/
public function hex2str($data)
{
$data = preg_replace('/[^0-9A-Fa-f]/', '', rtrim($data, '>'));
if ((strlen($data) % 2) == 1) {
$data .= '0';
}
return pack('H*', $data);
}
/**
* String to hexadecimal
*
* @param string $str
* @return string
*/
public function str2hex($str)
{
return current(unpack('H*', $str));
}
}
}

View File

@@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.4.2 // FPDI - Version 1.5.2
// //
// Copyright 2004-2011 Setasign - Jan Slabon // Copyright 2004-2014 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.
@@ -19,313 +19,255 @@
require_once('pdf_parser.php'); require_once('pdf_parser.php');
class fpdi_pdf_parser extends pdf_parser { /**
* Class fpdi_pdf_parser
*/
class fpdi_pdf_parser extends pdf_parser
{
/** /**
* Pages * Pages
* Index beginns at 0 *
* Index begins at 0
* *
* @var array * @var array
*/ */
var $pages; protected $_pages;
/** /**
* Page count * Page count
*
* @var integer * @var integer
*/ */
var $page_count; protected $_pageCount;
/** /**
* actual page number * Current page number
*
* @var integer * @var integer
*/ */
var $pageno; public $pageNo;
/** /**
* PDF Version of imported Document * PDF version of imported document
*
* @var string * @var string
*/ */
var $pdfVersion; public $_pdfVersion;
/**
* FPDI Reference
* @var object
*/
var $fpdi;
/** /**
* Available BoxTypes * Available BoxTypes
* *
* @var array * @var array
*/ */
var $availableBoxes = array('/MediaBox', '/CropBox', '/BleedBox', '/TrimBox', '/ArtBox'); public $availableBoxes = array('/MediaBox', '/CropBox', '/BleedBox', '/TrimBox', '/ArtBox');
/** /**
* Constructor * The constructor.
* *
* @param string $filename Source-Filename * @param string $filename The source filename
* @param object $fpdi Object of type fpdi
*/ */
function fpdi_pdf_parser($filename, &$fpdi) { public function __construct($filename)
$this->fpdi =& $fpdi; {
parent::__construct($filename);
parent::pdf_parser($filename);
// resolve Pages-Dictonary // resolve Pages-Dictonary
$pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']); $pages = $this->resolveObject($this->_root[1][1]['/Pages']);
// Read pages // Read pages
$this->read_pages($this->c, $pages, $this->pages); $this->_readPages($pages, $this->_pages);
// count pages; // count pages;
$this->page_count = count($this->pages); $this->_pageCount = count($this->_pages);
} }
/** /**
* Overwrite parent::error() * Get page count from source file.
*
* @param string $msg Error-Message
*/
function error($msg) {
$this->fpdi->error($msg);
}
/**
* Get pagecount from sourcefile
* *
* @return int * @return int
*/ */
function getPageCount() { public function getPageCount()
return $this->page_count; {
return $this->_pageCount;
} }
/** /**
* Set pageno * Set the page number.
* *
* @param int $pageno Pagenumber to use * @param int $pageNo Page number to use
* @throws InvalidArgumentException
*/ */
function setPageno($pageno) { public function setPageNo($pageNo)
$pageno = ((int) $pageno) - 1; {
$pageNo = ((int) $pageNo) - 1;
if ($pageno < 0 || $pageno >= $this->getPageCount()) { if ($pageNo < 0 || $pageNo >= $this->getPageCount()) {
$this->fpdi->error('Pagenumber is wrong!'); throw new InvalidArgumentException('Invalid page number!');
} }
$this->pageno = $pageno; $this->pageNo = $pageNo;
} }
/** /**
* Get page-resources from current page * Get page-resources from current page
* *
* @return array * @return array|boolean
*/ */
function getPageResources() { public function getPageResources()
return $this->_getPageResources($this->pages[$this->pageno]); {
return $this->_getPageResources($this->_pages[$this->pageNo]);
} }
/** /**
* Get page-resources from /Page * Get page-resources from a /Page dictionary.
* *
* @param array $obj Array of pdf-data * @param array $obj Array of pdf-data
* @return array|boolean
*/ */
function _getPageResources ($obj) { // $obj = /Page protected function _getPageResources($obj)
$obj = $this->pdf_resolve_object($this->c, $obj); {
$obj = $this->resolveObject($obj);
// If the current object has a resources // If the current object has a resources
// dictionary associated with it, we use // dictionary associated with it, we use
// it. Otherwise, we move back to its // it. Otherwise, we move back to its
// parent object. // parent object.
if (isset ($obj[1][1]['/Resources'])) { if (isset($obj[1][1]['/Resources'])) {
$res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Resources']); $res = $this->resolveObject($obj[1][1]['/Resources']);
if ($res[0] == PDF_TYPE_OBJECT) if ($res[0] == pdf_parser::TYPE_OBJECT)
return $res[1]; return $res[1];
return $res; 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;
}
} }
if (!isset($obj[1][1]['/Parent'])) {
return false;
}
$res = $this->_getPageResources($obj[1][1]['/Parent']);
if ($res[0] == pdf_parser::TYPE_OBJECT)
return $res[1];
return $res;
} }
/** /**
* Get content of current page * Get content of current page.
* *
* If more /Contents is an array, the streams are concated * If /Contents is an array, the streams are concatenated
* *
* @return string * @return string
*/ */
function getContent() { public function getContent()
{
$buffer = ''; $buffer = '';
if (isset($this->pages[$this->pageno][1][1]['/Contents'])) { if (isset($this->_pages[$this->pageNo][1][1]['/Contents'])) {
$contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']); $contents = $this->_getPageContent($this->_pages[$this->pageNo][1][1]['/Contents']);
foreach($contents AS $tmp_content) { foreach ($contents AS $tmpContent) {
$buffer .= $this->_rebuildContentStream($tmp_content) . ' '; $buffer .= $this->_unFilterStream($tmpContent) . ' ';
} }
} }
return $buffer; return $buffer;
} }
/** /**
* Resolve all content-objects * Resolve all content objects.
* *
* @param array $content_ref * @param array $contentRef
* @return array * @return array
*/ */
function _getPageContent($content_ref) { protected function _getPageContent($contentRef)
{
$contents = array(); $contents = array();
if ($content_ref[0] == PDF_TYPE_OBJREF) { if ($contentRef[0] == pdf_parser::TYPE_OBJREF) {
$content = $this->pdf_resolve_object($this->c, $content_ref); $content = $this->resolveObject($contentRef);
if ($content[1][0] == PDF_TYPE_ARRAY) { if ($content[1][0] == pdf_parser::TYPE_ARRAY) {
$contents = $this->_getPageContent($content[1]); $contents = $this->_getPageContent($content[1]);
} else { } else {
$contents[] = $content; $contents[] = $content;
} }
} else if ($content_ref[0] == PDF_TYPE_ARRAY) { } else if ($contentRef[0] == pdf_parser::TYPE_ARRAY) {
foreach ($content_ref[1] AS $tmp_content_ref) { foreach ($contentRef[1] AS $tmp_content_ref) {
$contents = array_merge($contents,$this->_getPageContent($tmp_content_ref)); $contents = array_merge($contents, $this->_getPageContent($tmp_content_ref));
} }
} }
return $contents; return $contents;
} }
/** /**
* Rebuild content-streams * Get a boundary box from a page
* *
* @param array $obj * Array format is same as used by FPDF_TPL.
* @return string
*/
function _rebuildContentStream($obj) {
$filters = array();
if (isset($obj[1][1]['/Filter'])) {
$_filter = $obj[1][1]['/Filter'];
if ($_filter[0] == PDF_TYPE_OBJREF) {
$tmpFilter = $this->pdf_resolve_object($this->c, $_filter);
$_filter = $tmpFilter[1];
}
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':
case '/Fl':
// $stream .= "\x0F\x0D"; // in an errorious stream this suffix could work
// $stream .= "\x0A";
// $stream .= "\x0D";
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 array $page a /Page dictionary
* @param string $box_index Type of Box @see $availableBoxes * @param string $boxIndex Type of box {see {@link $availableBoxes})
* @param float Scale factor from user space units to points * @param float Scale factor from user space units to points
* @return array *
* @return array|boolean
*/ */
function getPageBox($page, $box_index, $k) { protected function _getPageBox($page, $boxIndex, $k)
$page = $this->pdf_resolve_object($this->c, $page); {
$page = $this->resolveObject($page);
$box = null; $box = null;
if (isset($page[1][1][$box_index])) if (isset($page[1][1][$boxIndex])) {
$box =& $page[1][1][$box_index]; $box = $page[1][1][$boxIndex];
}
if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { if (!is_null($box) && $box[0] == pdf_parser::TYPE_OBJREF) {
$tmp_box = $this->pdf_resolve_object($this->c, $box); $tmp_box = $this->resolveObject($box);
$box = $tmp_box[1]; $box = $tmp_box[1];
} }
if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { if (!is_null($box) && $box[0] == pdf_parser::TYPE_ARRAY) {
$b =& $box[1]; $b = $box[1];
return array('x' => $b[0][1] / $k, return array(
'y' => $b[1][1] / $k, 'x' => $b[0][1] / $k,
'w' => abs($b[0][1] - $b[2][1]) / $k, 'y' => $b[1][1] / $k,
'h' => abs($b[1][1] - $b[3][1]) / $k, 'w' => abs($b[0][1] - $b[2][1]) / $k,
'llx' => min($b[0][1], $b[2][1]) / $k, 'h' => abs($b[1][1] - $b[3][1]) / $k,
'lly' => min($b[1][1], $b[3][1]) / $k, 'llx' => min($b[0][1], $b[2][1]) / $k,
'urx' => max($b[0][1], $b[2][1]) / $k, 'lly' => min($b[1][1], $b[3][1]) / $k,
'ury' => max($b[1][1], $b[3][1]) / $k, 'urx' => max($b[0][1], $b[2][1]) / $k,
); 'ury' => max($b[1][1], $b[3][1]) / $k,
} else if (!isset ($page[1][1]['/Parent'])) { );
} else if (!isset($page[1][1]['/Parent'])) {
return false; return false;
} else { } else {
return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index, $k); return $this->_getPageBox($this->resolveObject($page[1][1]['/Parent']), $boxIndex, $k);
} }
} }
/** /**
* Get all page boxes by page no * Get all page boundary boxes by page number
* *
* @param int The page number * @param int $pageNo The page number
* @param float Scale factor from user space units to points * @param float $k Scale factor from user space units to points
* @return array * @return array
* @throws InvalidArgumentException
*/ */
function getPageBoxes($pageno, $k) { public function getPageBoxes($pageNo, $k)
return $this->_getPageBoxes($this->pages[$pageno - 1], $k); {
if (!isset($this->_pages[$pageNo - 1])) {
throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.');
}
return $this->_getPageBoxes($this->_pages[$pageNo - 1], $k);
} }
/** /**
* Get all boxes from /Page * Get all boxes from /Page dictionary
* *
* @param array a /Page * @param array $page A /Page dictionary
* @param float $k Scale factor from user space units to points
* @return array * @return array
*/ */
function _getPageBoxes($page, $k) { protected function _getPageBoxes($page, $k)
{
$boxes = array(); $boxes = array();
foreach($this->availableBoxes AS $box) { foreach($this->availableBoxes AS $box) {
if ($_box = $this->getPageBox($page, $box, $k)) { if ($_box = $this->_getPageBox($page, $box, $k)) {
$boxes[$box] = $_box; $boxes[$box] = $_box;
} }
} }
@@ -334,75 +276,79 @@ class fpdi_pdf_parser extends pdf_parser {
} }
/** /**
* Get the page rotation by pageno * Get the page rotation by page number
* *
* @param integer $pageno * @param integer $pageNo
* @throws InvalidArgumentException
* @return array * @return array
*/ */
function getPageRotation($pageno) { public function getPageRotation($pageNo)
return $this->_getPageRotation($this->pages[$pageno - 1]); {
if (!isset($this->_pages[$pageNo - 1])) {
throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.');
}
return $this->_getPageRotation($this->_pages[$pageNo - 1]);
} }
function _getPageRotation($obj) { // $obj = /Page /**
$obj = $this->pdf_resolve_object($this->c, $obj); * Get the rotation value of a page
if (isset ($obj[1][1]['/Rotate'])) { *
$res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']); * @param array $obj A /Page dictionary
if ($res[0] == PDF_TYPE_OBJECT) * @return array|bool
*/
protected function _getPageRotation($obj)
{
$obj = $this->resolveObject($obj);
if (isset($obj[1][1]['/Rotate'])) {
$res = $this->resolveObject($obj[1][1]['/Rotate']);
if ($res[0] == pdf_parser::TYPE_OBJECT)
return $res[1]; return $res[1];
return $res; 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;
}
} }
}
if (!isset($obj[1][1]['/Parent'])) {
/** return false;
* 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];
} }
$res = $this->_getPageRotation($obj[1][1]['/Parent']);
if ($res[0] == pdf_parser::TYPE_OBJECT)
return $res[1];
return $res;
}
/**
* Read all pages
*
* @param array $pages /Pages dictionary
* @param array $result The result array
* @throws Exception
*/
protected function _readPages(&$pages, &$result)
{
// Get the kids dictionary
$_kids = $this->resolveObject($pages[1][1]['/Kids']);
if (!is_array($_kids)) {
throw new Exception('Cannot find /Kids in current /Page-Dictionary');
}
if ($_kids[0] === self::TYPE_OBJECT) {
$_kids = $_kids[1];
}
$kids = $_kids[1];
foreach ($kids as $v) { foreach ($kids as $v) {
$pg = $this->pdf_resolve_object ($c, $v); $pg = $this->resolveObject($v);
if ($pg[1][1]['/Type'][1] === '/Pages') { if ($pg[1][1]['/Type'][1] === '/Pages') {
// If one of the kids is an embedded // If one of the kids is an embedded
// /Pages array, resolve it as well. // /Pages array, resolve it as well.
$this->read_pages($c, $pg, $result); $this->_readPages($pg, $result);
} else { } else {
$result[] = $pg; $result[] = $pg;
} }
} }
} }
/**
* Get PDF-Version
*
* And reset the PDF Version used in FPDI if needed
*/
function getPDFVersion() {
parent::getPDFVersion();
$this->fpdi->setPDFVersion(max($this->fpdi->getPDFVersion(), $this->pdfVersion));
}
} }

View File

@@ -1,8 +1,8 @@
<?php <?php
// //
// FPDI - Version 1.4.2 // FPDI - Version 1.5.2
// //
// Copyright 2004-2011 Setasign - Jan Slabon // Copyright 2004-2014 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,88 +17,137 @@
// limitations under the License. // limitations under the License.
// //
if (!class_exists('pdf_context', false)) { /**
* Class pdf_context
class pdf_context { */
class pdf_context
/** {
* Modi /**
* * Mode
* @var integer 0 = file | 1 = string *
*/ * @var integer 0 = file | 1 = string
var $_mode = 0; */
protected $_mode = 0;
var $file;
var $buffer; /**
var $offset; * @var resource|string
var $length; */
public $file;
var $stack;
/**
// Constructor * @var string
*/
function pdf_context(&$f) { public $buffer;
$this->file =& $f;
if (is_string($this->file)) /**
$this->_mode = 1; * @var integer
$this->reset(); */
} public $offset;
// Optionally move the file /**
// pointer to a new location * @var integer
// and reset the buffered data */
public $length;
function reset($pos = null, $l = 100) {
if ($this->_mode == 0) { /**
if (!is_null ($pos)) { * @var array
fseek ($this->file, $pos); */
} public $stack;
$this->buffer = $l > 0 ? fread($this->file, $l) : ''; /**
$this->length = strlen($this->buffer); * The constructor
if ($this->length < $l) *
$this->increase_length($l - $this->length); * @param resource $f
} else { */
$this->buffer = $this->file; public function __construct(&$f)
$this->length = strlen($this->buffer); {
} $this->file =& $f;
$this->offset = 0; if (is_string($this->file))
$this->stack = array(); $this->_mode = 1;
}
$this->reset();
// 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 * Get the position in the file stream
// not exist *
* @return int
function ensure_content() { */
if ($this->offset >= $this->length - 1) { public function getPos()
return $this->increase_length(); {
} else { if ($this->_mode == 0) {
return true; return ftell($this->file);
} } else {
} return 0;
}
// Forcefully read more data into the buffer }
function increase_length($l = 100) { /**
if ($this->_mode == 0 && feof($this->file)) { * Reset the position in the file stream.
return false; *
} else if ($this->_mode == 0) { * Optionally move the file pointer to a new location and reset the buffered data.
$totalLength = $this->length + $l; *
do { * @param null $pos
$toRead = $totalLength - $this->length; * @param int $l
if ($toRead < 1) */
break; public function reset($pos = null, $l = 100)
{
$this->buffer .= fread($this->file, $toRead); if ($this->_mode == 0) {
} while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); if (!is_null($pos)) {
fseek ($this->file, $pos);
return true; }
} else {
return false; $this->buffer = $l > 0 ? fread($this->file, $l) : '';
} $this->length = strlen($this->buffer);
} if ($this->length < $l)
$this->increaseLength($l - $this->length);
} else {
$this->buffer = $this->file;
$this->length = strlen($this->buffer);
}
$this->offset = 0;
$this->stack = array();
}
/**
* Make sure that there is at least one character beyond the current offset in the buffer.
*
* To prevent the tokenizer from attempting to access data that does not exist.
*
* @return bool
*/
public function ensureContent()
{
if ($this->offset >= $this->length - 1) {
return $this->increaseLength();
} else {
return true;
}
}
/**
* Forcefully read more data into the buffer
*
* @param int $l
* @return bool
*/
public function increaseLength($l = 100)
{
if ($this->_mode == 0 && feof($this->file)) {
return false;
} else if ($this->_mode == 0) {
$totalLength = $this->length + $l;
do {
$toRead = $totalLength - $this->length;
if ($toRead < 1)
break;
$this->buffer .= fread($this->file, $toRead);
} while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file));
return true;
} else {
return false;
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -152,7 +152,7 @@ BackToAccount=Back to account
ShowAllAccounts=Show for all accounts ShowAllAccounts=Show for all accounts
FutureTransaction=Transaction in futur. No way to conciliate. FutureTransaction=Transaction in futur. No way to conciliate.
SelectChequeTransactionAndGenerate=Select/filter checks to include into the check deposit receipt and click on "Create". SelectChequeTransactionAndGenerate=Select/filter checks to include into the check deposit receipt and click on "Create".
InputReceiptNumber=Choose the bank statement related with the conciliation. Use a sortable numeric value (such as, YYYYMM) InputReceiptNumber=Choose the bank statement related with the conciliation. Use a sortable numeric value: YYYYMM or YYYYMMDD
EventualyAddCategory=Eventually, specify a category in which to classify the records EventualyAddCategory=Eventually, specify a category in which to classify the records
ToConciliate=To conciliate? ToConciliate=To conciliate?
ThenCheckLinesAndConciliate=Then, check the lines present in the bank statement and click ThenCheckLinesAndConciliate=Then, check the lines present in the bank statement and click

View File

@@ -242,30 +242,34 @@ if (empty($reshook))
} }
// Check for duplicate or mandatory prof id // Check for duplicate or mandatory prof id
for ($i = 1; $i < 5; $i++) // Only for companies
if (!($object->particulier || $private))
{ {
$slabel="idprof".$i; for ($i = 1; $i < 5; $i++)
$_POST[$slabel]=trim($_POST[$slabel]); {
$vallabel=$_POST[$slabel]; $slabel="idprof".$i;
if ($vallabel && $object->id_prof_verifiable($i)) $_POST[$slabel]=trim($_POST[$slabel]);
{ $vallabel=$_POST[$slabel];
if($object->id_prof_exists($i,$vallabel,$object->id)) if ($vallabel && $object->id_prof_verifiable($i))
{
if($object->id_prof_exists($i,$vallabel,$object->id))
{
$langs->load("errors");
$error++; $errors[] = $langs->transcountry('ProfId'.$i, $object->country_code)." ".$langs->trans("ErrorProdIdAlreadyExist", $vallabel);
$action = (($action=='add'||$action=='create')?'create':'edit');
}
}
$idprof_mandatory ='SOCIETE_IDPROF'.($i).'_MANDATORY';
if (! $vallabel && ! empty($conf->global->$idprof_mandatory))
{ {
$langs->load("errors"); $langs->load("errors");
$error++; $errors[] = $langs->transcountry('ProfId'.$i, $object->country_code)." ".$langs->trans("ErrorProdIdAlreadyExist", $vallabel); $error++;
$action = (($action=='add'||$action=='create')?'create':'edit'); $errors[] = $langs->trans("ErrorProdIdIsMandatory", $langs->transcountry('ProfId'.$i, $object->country_code));
$action = (($action=='add'||$action=='create')?'create':'edit');
} }
} }
$idprof_mandatory ='SOCIETE_IDPROF'.($i).'_MANDATORY';
if (! $vallabel && ! empty($conf->global->$idprof_mandatory))
{
$langs->load("errors");
$error++;
$errors[] = $langs->trans("ErrorProdIdIsMandatory", $langs->transcountry('ProfId'.$i, $object->country_code));
$action = (($action=='add'||$action=='create')?'create':'edit');
}
} }
} }