diff --git a/COPYRIGHT b/COPYRIGHT index 384fab6fd5c..c8e162b848d 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -13,12 +13,12 @@ Composant Version License Compatible GPL Usage PHP libraries: AdoDb-Date 0.21 Modified BSD License Yes Date convertion (not into rpm package) CKEditor 3.6.2 GPL or LGPL 2.1 or MPL 1.1 Yes Editor WYSIWYG -FPDI 1.4.1 Apache Software License 2.0 ? PDF templates management +FPDI 1.4.2 Apache Software License 2.0 No (GPLv3 only) PDF templates management (with FPDF_TPL 1.2) GeoIP 2004 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) OdtPHP 1.0.1 GPL 2.0 Yes Library to build/edit ODT files PHPExcel 1.7.6 LGPL 2.1 Yes Read/Write XLS files, read ODS files -TCPDF 5.9.156 LGPL 3.0 Yes PDF generation +TCPDF 5.9.180 LGPL 3.0 Yes PDF generation JS libraries: jQuery 1.7.2 GPL and MIT Licence Yes JS library @@ -29,7 +29,7 @@ jQuery Flot 0.7 MIT Licence Yes JS library to build graph jQuery FileUpload 5.0.3 GPL and MIT Licence Yes JS library to upload files jQuery JCrop 0.9.8 GPL and MIT Licence Yes JS library plugin Crop (to crop images) jQuery jeditable 1.7.1 GPL and MIT Licence Yes JS library plugin jeditable (to edit in place) -jQuery jNotify 1.1.00 Apache Software License 2.0 ? JS library plugin jNotify (to use ajax popups) +jQuery jNotify 1.1.00 Apache Software License 2.0 No (GPLv3 only) JS library plugin jNotify (to use ajax popups) jQuery jPicker 1.1.00 GPL and MIT Licence Yes JS library for color picker with not defined list of colors jQuery Layout 1.3.0 GPL and MIT Licence Yes JS library plugin Layout (RC-29.15) jQuery TableDnD 0.5 GPL and MIT Licence Yes JS library plugin TableDnD (to reorder table rows) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 33bc91637a3..3be9c1b03f9 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -1046,9 +1046,9 @@ function pdf_getlineupexcltax($object,$i,$outputlangs,$hidedetails=0,$hookmanage global $conf; $sign=1; - if ($object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1; + if (isset($object->type) && $object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1; - if (is_object($hookmanager) && ( ($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) ) + if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line))) { $special_code = $object->lines[$i]->special_code; if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line); @@ -1250,7 +1250,7 @@ function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0,$hookman global $conf; $sign=1; - if ($object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1; + if (isset($object->type) && $object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1; if ($object->lines[$i]->special_code == 3) { @@ -1258,7 +1258,7 @@ function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0,$hookman } else { - if (is_object($hookmanager) && ( ($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) ) + if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line))) { $special_code = $object->lines[$i]->special_code; if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line); diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 4a24f74c2a0..8aacca212b1 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -311,6 +311,10 @@ class pdf_azur extends ModelePDFPropales if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate.='*'; + if (! isset($this->tva[$vatrate])) $this->tva[$vatrate]=0; + if (! isset($this->localtax1[$localtax1rate])) $this->localtax1[$localtax1rate]=0; + if (! isset($this->localtax2[$localtax2rate])) $this->localtax2[$localtax2rate]=0; + $this->tva[$vatrate] += $tvaligne; $this->localtax1[$localtax1rate]+=$localtax1ligne; $this->localtax2[$localtax2rate]+=$localtax2ligne; @@ -455,7 +459,7 @@ class pdf_azur extends ModelePDFPropales } // Show shipping date - if ($object->type != 2 && $object->date_livraison) + if (isset($object->type) && $object->type != 2 && $object->date_livraison) { $outputlangs->load("sendings"); $pdf->SetFont('','B', $default_font_size - 2); @@ -469,7 +473,7 @@ class pdf_azur extends ModelePDFPropales $posy=$pdf->GetY()+1; } - elseif ($object->type != 2 && ($object->availability_code || $object->availability)) // Show availability conditions + elseif (isset($object->type) && $object->type != 2 && ($object->availability_code || $object->availability)) // Show availability conditions { $pdf->SetFont('','B', $default_font_size - 2); $pdf->SetXY($this->marge_gauche, $posy); @@ -486,7 +490,7 @@ class pdf_azur extends ModelePDFPropales } // Show payments conditions - if ($object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement)) + if (isset($object->type) && $object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement)) { $pdf->SetFont('','B', $default_font_size - 2); $pdf->SetXY($this->marge_gauche, $posy); @@ -503,7 +507,7 @@ class pdf_azur extends ModelePDFPropales } - if ($object->type != 2) + if (isset($object->type) && $object->type != 2) { // Check a payment mode is defined if (empty($object->mode_reglement_code) @@ -632,7 +636,7 @@ class pdf_azur extends ModelePDFPropales $this->atleastoneratenotnull=0; if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) { - $tvaisnull=((! empty($this->tva) && count($this->tva) == 1 && is_float($this->tva['0.000'])) ? true : false); + $tvaisnull=((! empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000'])) ? true : false); if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_ISNULL) && $tvaisnull) { // Nothing to do @@ -1049,7 +1053,7 @@ class pdf_azur extends ModelePDFPropales $carac_client_name=$outputlangs->convToOutputCharset($object->client->nom); } - $carac_client=pdf_build_address($outputlangs,$this->emetteur,$object->client,$object->contact,$usecontact,'target'); + $carac_client=pdf_build_address($outputlangs,$this->emetteur,$object->client,(! empty($object->contact)?$object->contact:''),$usecontact,'target'); // Show recipient $posy=42; diff --git a/htdocs/includes/fpdfi/filters/FilterASCII85.php b/htdocs/includes/fpdfi/filters/FilterASCII85.php index 092f3299b64..01402ba1dc6 100755 --- a/htdocs/includes/fpdfi/filters/FilterASCII85.php +++ b/htdocs/includes/fpdfi/filters/FilterASCII85.php @@ -1,6 +1,6 @@ ORD_u) { diff --git a/htdocs/includes/fpdfi/filters/FilterASCII85_FPDI.php b/htdocs/includes/fpdfi/filters/FilterASCII85_FPDI.php index d4687ee88f2..fb5600116bc 100755 --- a/htdocs/includes/fpdfi/filters/FilterASCII85_FPDI.php +++ b/htdocs/includes/fpdfi/filters/FilterASCII85_FPDI.php @@ -1,33 +1,33 @@ -fpdi =& $fpdi; - } - - function error($msg) { - $this->fpdi->error($msg); - } +fpdi =& $fpdi; + } + + function error($msg) { + $this->fpdi->error($msg); + } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/filters/FilterLZW.php b/htdocs/includes/fpdfi/filters/FilterLZW.php index 76d303d3803..292461d248d 100755 --- a/htdocs/includes/fpdfi/filters/FilterLZW.php +++ b/htdocs/includes/fpdfi/filters/FilterLZW.php @@ -1,6 +1,6 @@ sTable[$oldCode]; - $string = $string.$string[0]; + $string = $string . $string[0]; $uncompData .= $string; $this->addStringToTable($string); diff --git a/htdocs/includes/fpdfi/filters/FilterLZW_FPDI.php b/htdocs/includes/fpdfi/filters/FilterLZW_FPDI.php index fd9451e214f..e7a88119ff9 100755 --- a/htdocs/includes/fpdfi/filters/FilterLZW_FPDI.php +++ b/htdocs/includes/fpdfi/filters/FilterLZW_FPDI.php @@ -1,33 +1,33 @@ -fpdi =& $fpdi; - } - - function error($msg) { - $this->fpdi->error($msg); - } +fpdi =& $fpdi; + } + + function error($msg) { + $this->fpdi->error($msg); + } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/fpdf_tpl.php b/htdocs/includes/fpdfi/fpdf_tpl.php index 6e234bf9321..d21743e6374 100755 --- a/htdocs/includes/fpdfi/fpdf_tpl.php +++ b/htdocs/includes/fpdfi/fpdf_tpl.php @@ -1,449 +1,449 @@ -Error('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.'); - return; - } - - if ($this->page <= 0) - $this->error("You have to add a page to fpdf first!"); - - if ($x == null) - $x = 0; - if ($y == null) - $y = 0; - if ($w == null) - $w = $this->w; - if ($h == null) - $h = $this->h; - - // Save settings - $this->tpl++; - $tpl =& $this->tpls[$this->tpl]; - $tpl = array( - 'o_x' => $this->x, - 'o_y' => $this->y, - 'o_AutoPageBreak' => $this->AutoPageBreak, - 'o_bMargin' => $this->bMargin, - 'o_tMargin' => $this->tMargin, - 'o_lMargin' => $this->lMargin, - 'o_rMargin' => $this->rMargin, - 'o_h' => $this->h, - 'o_w' => $this->w, - 'buffer' => '', - 'x' => $x, - 'y' => $y, - 'w' => $w, - 'h' => $h - ); - - $this->SetAutoPageBreak(false); - - // Define own high and width to calculate possitions correct - $this->h = $h; - $this->w = $w; - - $this->_intpl = true; - $this->SetXY($x + $this->lMargin, $y + $this->tMargin); - $this->SetRightMargin($this->w - $w + $this->rMargin); - - return $this->tpl; - } - - /** - * End Template - * - * This method ends a template and reset initiated variables on beginTemplate. - * - * @return mixed If a template is opened, the ID is returned. If not a false is returned. - */ - function endTemplate() { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args); - } - - if ($this->_intpl) { - $this->_intpl = false; - $tpl =& $this->tpls[$this->tpl]; - $this->SetXY($tpl['o_x'], $tpl['o_y']); - $this->tMargin = $tpl['o_tMargin']; - $this->lMargin = $tpl['o_lMargin']; - $this->rMargin = $tpl['o_rMargin']; - $this->h = $tpl['o_h']; - $this->w = $tpl['o_w']; - $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']); - - return $this->tpl; - } else { - return false; - } - } - - /** - * Use a Template in current Page or other Template - * - * You can use a template in a page or in another template. - * You can give the used template a new size like you use the Image()-method. - * All parameters are optional. The width or height is calculated automaticaly - * if one is given. If no parameter is given the origin size as defined in - * beginTemplate() is used. - * The calculated or used width and height are returned as an array. - * - * @param int $tplidx A valid template-Id - * @param int $_x The x-position - * @param int $_y The y-position - * @param int $_w The new width of the template - * @param int $_h The new height of the template - * @retrun array The height and width of the template - */ - function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0) { - if ($this->page <= 0) - $this->error('You have to add a page first!'); - - if (!isset($this->tpls[$tplidx])) - $this->error('Template does not exist!'); - - if ($this->_intpl) { - $this->_res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx]; - } - - $tpl =& $this->tpls[$tplidx]; - $w = $tpl['w']; - $h = $tpl['h']; - - if ($_x == null) - $_x = 0; - if ($_y == null) - $_y = 0; - - $_x += $tpl['x']; - $_y += $tpl['y']; - - $wh = $this->getTemplateSize($tplidx, $_w, $_h); - $_w = $wh['w']; - $_h = $wh['h']; - - $tData = array( - 'x' => $this->x, - 'y' => $this->y, - 'w' => $_w, - 'h' => $_h, - 'scaleX' => ($_w / $w), - 'scaleY' => ($_h / $h), - 'tx' => $_x, - 'ty' => ($this->h - $_y - $_h), - 'lty' => ($this->h - $_y - $_h) - ($this->h - $h) * ($_h / $h) - ); - - $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', $tData['scaleX'], $tData['scaleY'], $tData['tx'] * $this->k, $tData['ty'] * $this->k)); // Translate - $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); - - // reset font in the outer graphic state - if ($this->FontFamily) { - $family = $this->FontFamily; - $this->FontFamily = ''; - $this->SetFont($family); - } - - $this->lastUsedTemplateData = $tData; - - return array('w' => $_w, 'h' => $_h); - } - - /** - * Get The calculated Size of a Template - * - * If one size is given, this method calculates the other one. - * - * @param int $tplidx A valid template-Id - * @param int $_w The width of the template - * @param int $_h The height of the template - * @return array The height and width of the template - */ - function getTemplateSize($tplidx, $_w = 0, $_h = 0) { - if (!$this->tpls[$tplidx]) - return false; - - $tpl =& $this->tpls[$tplidx]; - $w = $tpl['w']; - $h = $tpl['h']; - - if ($_w == 0 and $_h == 0) { - $_w = $w; - $_h = $h; - } - - if($_w == 0) - $_w = $_h * $w / $h; - if($_h == 0) - $_h = $_w * $h / $w; - - return array("w" => $_w, "h" => $_h); - } - - /** - * See FPDF/TCPDF-Documentation ;-) - */ - public function SetFont($family, $style = '', $size = 0) { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); - } - - /** - * force the resetting of font changes in a template - */ - if ($this->_intpl) - $this->FontFamily = ''; - - parent::SetFont($family, $style, $size); - - $fontkey = $this->FontFamily . $this->FontStyle; - - if ($this->_intpl) { - $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; - } else { - $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey]; - } - } - - /** - * See FPDF/TCPDF-Documentation ;-) - */ - function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '') { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::Image'), $args); - } - - $ret = parent::Image($file, $x, $y, $w, $h, $type, $link); - if ($this->_intpl) { - $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file]; - } else { - $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file]; - } - - return $ret; - } - - /** - * See FPDF-Documentation ;-) - * - * AddPage is not available when you're "in" a template. - */ - function AddPage($orientation = '', $format = '') { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); - } - - if ($this->_intpl) - $this->Error('Adding pages in templates isn\'t possible!'); - - parent::AddPage($orientation, $format); - } - - /** - * Preserve adding Links in Templates ...won't work - */ - function Link($x, $y, $w, $h, $link) { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::Link'), $args); - } - - if ($this->_intpl) - $this->Error('Using links in templates aren\'t possible!'); - - parent::Link($x, $y, $w, $h, $link); - } - - 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) - $this->Error('Adding links in templates aren\'t possible!'); - return parent::AddLink(); - } - - 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) - $this->Error('Setting links in templates aren\'t possible!'); - parent::SetLink($link, $y, $page); - } - - /** - * Private Method that writes the form xobjects - */ - function _putformxobjects() { - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->tpls); - foreach($this->tpls AS $tplidx => $tpl) { - - $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; - $this->_newobj(); - $this->tpls[$tplidx]['n'] = $this->n; - $this->_out('<<'.$filter.'/Type /XObject'); - $this->_out('/Subtype /Form'); - $this->_out('/FormType 1'); - $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', - // llx - $tpl['x'] * $this->k, - // lly - -$tpl['y'] * $this->k, - // urx - ($tpl['w'] + $tpl['x']) * $this->k, - // ury - ($tpl['h'] - $tpl['y']) * $this->k - )); - - if ($tpl['x'] != 0 || $tpl['y'] != 0) { - $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', - -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 - )); - } - - $this->_out('/Resources '); - - $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { - $this->_out('/Font <<'); - foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) - $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); - $this->_out('>>'); - } - if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || - isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) - { - $this->_out('/XObject <<'); - if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { - foreach($this->_res['tpl'][$tplidx]['images'] as $image) - $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); - } - if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { - foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) - $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); - } - $this->_out('>>'); - } - $this->_out('>>'); - - $this->_out('/Length ' . strlen($p) . ' >>'); - $this->_putstream($p); - $this->_out('endobj'); - } - } - - /** - * Overwritten to add _putformxobjects() after _putimages() - * - */ - function _putimages() { - parent::_putimages(); - $this->_putformxobjects(); - } - - function _putxobjectdict() { - parent::_putxobjectdict(); - - if (count($this->tpls)) { - foreach($this->tpls as $tplidx => $tpl) { - $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n'])); - } - } - } - - /** - * Private Method - */ - function _out($s) { - if ($this->state == 2 && $this->_intpl) { - $this->tpls[$this->tpl]['buffer'] .= $s . "\n"; - } else { - parent::_out($s); - } - } -} +Error('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.'); + return; + } + + if ($this->page <= 0) + $this->error("You have to add a page to fpdf first!"); + + if ($x == null) + $x = 0; + if ($y == null) + $y = 0; + if ($w == null) + $w = $this->w; + if ($h == null) + $h = $this->h; + + // Save settings + $this->tpl++; + $tpl =& $this->tpls[$this->tpl]; + $tpl = array( + 'o_x' => $this->x, + 'o_y' => $this->y, + 'o_AutoPageBreak' => $this->AutoPageBreak, + 'o_bMargin' => $this->bMargin, + 'o_tMargin' => $this->tMargin, + 'o_lMargin' => $this->lMargin, + 'o_rMargin' => $this->rMargin, + 'o_h' => $this->h, + 'o_w' => $this->w, + 'buffer' => '', + 'x' => $x, + 'y' => $y, + 'w' => $w, + 'h' => $h + ); + + $this->SetAutoPageBreak(false); + + // Define own high and width to calculate possitions correct + $this->h = $h; + $this->w = $w; + + $this->_intpl = true; + $this->SetXY($x + $this->lMargin, $y + $this->tMargin); + $this->SetRightMargin($this->w - $w + $this->rMargin); + + return $this->tpl; + } + + /** + * End Template + * + * This method ends a template and reset initiated variables on beginTemplate. + * + * @return mixed If a template is opened, the ID is returned. If not a false is returned. + */ + function endTemplate() { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args); + } + + if ($this->_intpl) { + $this->_intpl = false; + $tpl =& $this->tpls[$this->tpl]; + $this->SetXY($tpl['o_x'], $tpl['o_y']); + $this->tMargin = $tpl['o_tMargin']; + $this->lMargin = $tpl['o_lMargin']; + $this->rMargin = $tpl['o_rMargin']; + $this->h = $tpl['o_h']; + $this->w = $tpl['o_w']; + $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']); + + return $this->tpl; + } else { + return false; + } + } + + /** + * Use a Template in current Page or other Template + * + * You can use a template in a page or in another template. + * You can give the used template a new size like you use the Image()-method. + * All parameters are optional. The width or height is calculated automaticaly + * if one is given. If no parameter is given the origin size as defined in + * beginTemplate() is used. + * The calculated or used width and height are returned as an array. + * + * @param int $tplidx A valid template-Id + * @param int $_x The x-position + * @param int $_y The y-position + * @param int $_w The new width of the template + * @param int $_h The new height of the template + * @retrun array The height and width of the template + */ + function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0) { + if ($this->page <= 0) + $this->error('You have to add a page first!'); + + if (!isset($this->tpls[$tplidx])) + $this->error('Template does not exist!'); + + if ($this->_intpl) { + $this->_res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx]; + } + + $tpl =& $this->tpls[$tplidx]; + $w = $tpl['w']; + $h = $tpl['h']; + + if ($_x == null) + $_x = 0; + if ($_y == null) + $_y = 0; + + $_x += $tpl['x']; + $_y += $tpl['y']; + + $wh = $this->getTemplateSize($tplidx, $_w, $_h); + $_w = $wh['w']; + $_h = $wh['h']; + + $tData = array( + 'x' => $this->x, + 'y' => $this->y, + 'w' => $_w, + 'h' => $_h, + 'scaleX' => ($_w / $w), + 'scaleY' => ($_h / $h), + 'tx' => $_x, + 'ty' => ($this->h - $_y - $_h), + 'lty' => ($this->h - $_y - $_h) - ($this->h - $h) * ($_h / $h) + ); + + $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', $tData['scaleX'], $tData['scaleY'], $tData['tx'] * $this->k, $tData['ty'] * $this->k)); // Translate + $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); + + // reset font in the outer graphic state + if ($this->FontFamily) { + $family = $this->FontFamily; + $this->FontFamily = ''; + $this->SetFont($family); + } + + $this->lastUsedTemplateData = $tData; + + return array('w' => $_w, 'h' => $_h); + } + + /** + * Get The calculated Size of a Template + * + * If one size is given, this method calculates the other one. + * + * @param int $tplidx A valid template-Id + * @param int $_w The width of the template + * @param int $_h The height of the template + * @return array The height and width of the template + */ + function getTemplateSize($tplidx, $_w = 0, $_h = 0) { + if (!$this->tpls[$tplidx]) + return false; + + $tpl =& $this->tpls[$tplidx]; + $w = $tpl['w']; + $h = $tpl['h']; + + if ($_w == 0 and $_h == 0) { + $_w = $w; + $_h = $h; + } + + if($_w == 0) + $_w = $_h * $w / $h; + if($_h == 0) + $_h = $_w * $h / $w; + + return array("w" => $_w, "h" => $_h); + } + + /** + * See FPDF/TCPDF-Documentation ;-) + */ + public function SetFont($family, $style = '', $size = 0) { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); + } + + /** + * force the resetting of font changes in a template + */ + if ($this->_intpl) + $this->FontFamily = ''; + + parent::SetFont($family, $style, $size); + + $fontkey = $this->FontFamily . $this->FontStyle; + + if ($this->_intpl) { + $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; + } else { + $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey]; + } + } + + /** + * See FPDF/TCPDF-Documentation ;-) + */ + function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '') { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::Image'), $args); + } + + $ret = parent::Image($file, $x, $y, $w, $h, $type, $link); + if ($this->_intpl) { + $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file]; + } else { + $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file]; + } + + return $ret; + } + + /** + * See FPDF-Documentation ;-) + * + * AddPage is not available when you're "in" a template. + */ + function AddPage($orientation = '', $format = '') { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); + } + + if ($this->_intpl) + $this->Error('Adding pages in templates isn\'t possible!'); + + parent::AddPage($orientation, $format); + } + + /** + * Preserve adding Links in Templates ...won't work + */ + function Link($x, $y, $w, $h, $link) { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::Link'), $args); + } + + if ($this->_intpl) + $this->Error('Using links in templates aren\'t possible!'); + + parent::Link($x, $y, $w, $h, $link); + } + + 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) + $this->Error('Adding links in templates aren\'t possible!'); + return parent::AddLink(); + } + + 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) + $this->Error('Setting links in templates aren\'t possible!'); + parent::SetLink($link, $y, $page); + } + + /** + * Private Method that writes the form xobjects + */ + function _putformxobjects() { + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->tpls); + foreach($this->tpls AS $tplidx => $tpl) { + + $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + $this->_newobj(); + $this->tpls[$tplidx]['n'] = $this->n; + $this->_out('<<'.$filter.'/Type /XObject'); + $this->_out('/Subtype /Form'); + $this->_out('/FormType 1'); + $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', + // llx + $tpl['x'] * $this->k, + // lly + -$tpl['y'] * $this->k, + // urx + ($tpl['w'] + $tpl['x']) * $this->k, + // ury + ($tpl['h'] - $tpl['y']) * $this->k + )); + + if ($tpl['x'] != 0 || $tpl['y'] != 0) { + $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', + -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 + )); + } + + $this->_out('/Resources '); + + $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { + $this->_out('/Font <<'); + foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) + $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); + $this->_out('>>'); + } + if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || + isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) + { + $this->_out('/XObject <<'); + if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { + foreach($this->_res['tpl'][$tplidx]['images'] as $image) + $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); + } + if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { + foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) + $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); + } + $this->_out('>>'); + } + $this->_out('>>'); + + $this->_out('/Length ' . strlen($p) . ' >>'); + $this->_putstream($p); + $this->_out('endobj'); + } + } + + /** + * Overwritten to add _putformxobjects() after _putimages() + * + */ + function _putimages() { + parent::_putimages(); + $this->_putformxobjects(); + } + + function _putxobjectdict() { + parent::_putxobjectdict(); + + if (count($this->tpls)) { + foreach($this->tpls as $tplidx => $tpl) { + $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n'])); + } + } + } + + /** + * Private Method + */ + function _out($s) { + if ($this->state == 2 && $this->_intpl) { + $this->tpls[$this->tpl]['buffer'] .= $s . "\n"; + } else { + parent::_out($s); + } + } +} diff --git a/htdocs/includes/fpdfi/fpdi.php b/htdocs/includes/fpdfi/fpdi.php index faa1abe0f0d..0ae2c63741c 100755 --- a/htdocs/includes/fpdfi/fpdi.php +++ b/htdocs/includes/fpdfi/fpdi.php @@ -1,542 +1,571 @@ -current_filename = $filename; - - if (!isset($this->parsers[$filename])) - $this->parsers[$filename] = $this->_getPdfParser($filename); - $this->current_parser =& $this->parsers[$filename]; - - return $this->parsers[$filename]->getPageCount(); - } - - /** - * Returns a PDF parser object - * - * @param string $filename - * @return fpdi_pdf_parser - */ - function _getPdfParser($filename) { - return new fpdi_pdf_parser($filename, $this); - } - - /** - * Get the current PDF version - * - * @return string - */ - function getPDFVersion() { - return $this->PDFVersion; - } - - /** - * Set the PDF version - * - * @return string - */ - function setPDFVersion($version = '1.3') { - $this->PDFVersion = $version; - } - - /** - * Import a page - * - * @param int $pageno pagenumber - * @return int Index of imported page - to use with fpdf_tpl::useTemplate() - */ - function importPage($pageno, $boxName = '/CropBox') { - if ($this->_intpl) { - return $this->error('Please import the desired pages before creating a new template.'); - } - - $fn = $this->current_filename; - - // check if page already imported - $pageKey = $fn . '-' . ((int)$pageno) . $boxName; - if (isset($this->_importedPages[$pageKey])) - return $this->_importedPages[$pageKey]; - - $parser =& $this->parsers[$fn]; - $parser->setPageno($pageno); - - if (!in_array($boxName, $parser->availableBoxes)) - return $this->Error(sprintf('Unknown box: %s', $boxName)); - $pageboxes = $parser->getPageBoxes($pageno, $this->k); - - /** - * MediaBox - * CropBox: Default -> MediaBox - * BleedBox: Default -> CropBox - * TrimBox: Default -> CropBox - * ArtBox: Default -> CropBox - */ - if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) - $boxName = '/CropBox'; - if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox') - $boxName = '/MediaBox'; - - if (!isset($pageboxes[$boxName])) - return false; - $this->lastUsedPageBox = $boxName; - - $box = $pageboxes[$boxName]; - - $this->tpl++; - $this->tpls[$this->tpl] = array(); - $tpl =& $this->tpls[$this->tpl]; - $tpl['parser'] =& $parser; - $tpl['resources'] = $parser->getPageResources(); - $tpl['buffer'] = $parser->getContent(); - $tpl['box'] = $box; - - // To build an array that can be used by PDF_TPL::useTemplate() - $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl], $box); - - // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects() - $tpl['x'] = 0; - $tpl['y'] = 0; - - // handle rotated pages - $rotation = $parser->getPageRotation($pageno); - $tpl['_rotationAngle'] = 0; - if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) { - $steps = $angle / 90; - - $_w = $tpl['w']; - $_h = $tpl['h']; - $tpl['w'] = $steps % 2 == 0 ? $_w : $_h; - $tpl['h'] = $steps % 2 == 0 ? $_h : $_w; - - if ($angle < 0) - $angle += 360; - - $tpl['_rotationAngle'] = $angle * -1; - } - - $this->_importedPages[$pageKey] = $this->tpl; - - return $this->tpl; - } - - function getLastUsedPageBox() { - return $this->lastUsedPageBox; - } - - function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0, $adjustPageSize = false) { - if ($adjustPageSize == true && is_null($_x) && is_null($_y)) { - $size = $this->getTemplateSize($tplidx, $_w, $_h); - $format = array($size['w'], $size['h']); - if (is_subclass_of($this, 'TCPDF')) { - $this->setPageFormat($format, $format[0] > $format[1] ? 'L' : 'P'); - } else { - if ($format[0] != $this->CurPageFormat[0] || $format[1] != $this->CurPageFormat[1]) { - $this->w = $format[0]; - $this->h = $format[1]; - $this->wPt = $this->w * $this->k; - $this->hPt = $this->h * $this->k; - $this->PageBreakTrigger = $this->h - $this->bMargin; - $this->CurPageFormat = $format; - $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); - } - } - } - - $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values - $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); - $this->_out('Q'); - - return $s; - } - - /** - * Private method, that rebuilds all needed objects of source files - */ - function _putimportedobjects() { - if (is_array($this->parsers) && count($this->parsers) > 0) { - foreach($this->parsers AS $filename => $p) { - $this->current_parser =& $this->parsers[$filename]; - if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { - while(($n = key($this->_obj_stack[$filename])) !== null) { - $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]); - - $this->_newobj($this->_obj_stack[$filename][$n][0]); - - if ($nObj[0] == PDF_TYPE_STREAM) { - $this->pdf_write_value($nObj); - } else { - $this->pdf_write_value($nObj[1]); - } - - $this->_out('endobj'); - $this->_obj_stack[$filename][$n] = null; // free memory - unset($this->_obj_stack[$filename][$n]); - reset($this->_obj_stack[$filename]); - } - } - } - } - } - - - /** - * Private Method that writes the form xobjects - */ - function _putformxobjects() { - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->tpls); - foreach($this->tpls AS $tplidx => $tpl) { - $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; - $this->_newobj(); - $cN = $this->n; // TCPDF/Protection: rem current "n" - - $this->tpls[$tplidx]['n'] = $this->n; - $this->_out('<<' . $filter . '/Type /XObject'); - $this->_out('/Subtype /Form'); - $this->_out('/FormType 1'); - - $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', - (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x']) * $this->k, - (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y']) * $this->k, - (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x']) * $this->k, - (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h'] - $tpl['y']) * $this->k - )); - - $c = 1; - $s = 0; - $tx = 0; - $ty = 0; - - if (isset($tpl['box'])) { - $tx = -$tpl['box']['llx']; - $ty = -$tpl['box']['lly']; - - if ($tpl['_rotationAngle'] <> 0) { - $angle = $tpl['_rotationAngle'] * M_PI/180; - $c=cos($angle); - $s=sin($angle); - - switch($tpl['_rotationAngle']) { - case -90: - $tx = -$tpl['box']['lly']; - $ty = $tpl['box']['urx']; - break; - case -180: - $tx = $tpl['box']['urx']; - $ty = $tpl['box']['ury']; - break; - case -270: - $tx = $tpl['box']['ury']; - $ty = -$tpl['box']['llx']; - break; - } - } - } else if ($tpl['x'] != 0 || $tpl['y'] != 0) { - $tx = -$tpl['x']*2; - $ty = $tpl['y']*2; - } - - $tx *= $this->k; - $ty *= $this->k; - - if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) { - $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]', - $c, $s, -$s, $c, $tx, $ty - )); - } - - $this->_out('/Resources '); - - if (isset($tpl['resources'])) { - $this->current_parser =& $tpl['parser']; - $this->pdf_write_value($tpl['resources']); // "n" will be changed - } else { - $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { - $this->_out('/Font <<'); - foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) - $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); - $this->_out('>>'); - } - if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || - isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) - { - $this->_out('/XObject <<'); - if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { - foreach($this->_res['tpl'][$tplidx]['images'] as $image) - $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); - } - if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { - foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) - $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); - } - $this->_out('>>'); - } - $this->_out('>>'); - } - - $nN = $this->n; // TCPDF: rem new "n" - $this->n = $cN; // TCPDF: reset to current "n" - $this->_out('/Length ' . strlen($p) . ' >>'); - $this->_putstream($p); - $this->_out('endobj'); - $this->n = $nN; // TCPDF: reset to new "n" - } - - $this->_putimportedobjects(); - } - - /** - * Rewritten to handle existing own defined objects - */ - function _newobj($obj_id = false, $onlynewobj = false) { - if (!$obj_id) { - $obj_id = ++$this->n; - } - - //Begin a new object - if (!$onlynewobj) { - $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); - $this->_out($obj_id . ' 0 obj'); - $this->_current_obj_id = $obj_id; // for later use with encryption - } - - return $obj_id; - } - - /** - * Writes a value - * Needed to rebuild the source document - * - * @param mixed $value A PDF-Value. Structure of values see cases in this method - */ - function pdf_write_value(&$value) - { - if (is_subclass_of($this, 'TCPDF')) { - parent::pdf_write_value($value); - } - - switch ($value[0]) { - - case PDF_TYPE_TOKEN: - $this->_straightOut($value[1] . ' '); - break; - case PDF_TYPE_NUMERIC: - case PDF_TYPE_REAL: - if (is_float($value[1]) && $value[1] != 0) { - $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' '); - } else { - $this->_straightOut($value[1] . ' '); - } - break; - - case PDF_TYPE_ARRAY: - - // An array. Output the proper - // structure and move on. - - $this->_straightOut('['); - for ($i = 0; $i < count($value[1]); $i++) { - $this->pdf_write_value($value[1][$i]); - } - - $this->_out(']'); - break; - - case PDF_TYPE_DICTIONARY: - - // A dictionary. - $this->_straightOut('<<'); - - reset ($value[1]); - - while (list($k, $v) = each($value[1])) { - $this->_straightOut($k . ' '); - $this->pdf_write_value($v); - } - - $this->_straightOut('>>'); - break; - - case PDF_TYPE_OBJREF: - - // An indirect object reference - // Fill the object stack if needed - $cpfn =& $this->current_parser->filename; - - if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { - $this->_newobj(false, true); - $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); - $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! - } - $objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; - - $this->_out($objid . ' 0 R'); - break; - - case PDF_TYPE_STRING: - - // A string. - $this->_straightOut('(' . $value[1] . ')'); - - break; - - case PDF_TYPE_STREAM: - - // A stream. First, output the - // stream dictionary, then the - // stream data itself. - $this->pdf_write_value($value[1]); - $this->_out('stream'); - $this->_out($value[2][1]); - $this->_out('endstream'); - break; - - case PDF_TYPE_HEX: - $this->_straightOut('<' . $value[1] . '>'); - break; - - case PDF_TYPE_BOOLEAN: - $this->_straightOut($value[1] ? 'true ' : 'false '); - break; - - case PDF_TYPE_NULL: - // The null object. - - $this->_straightOut('null '); - break; - } - } - - - /** - * Modified so not each call will add a newline to the output. - */ - function _straightOut($s) { - if (!is_subclass_of($this, 'TCPDF')) { - if($this->state==2) - $this->pages[$this->page] .= $s; - else - $this->buffer .= $s; - } else { - if ($this->state == 2) { - if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { - // puts data before page footer - $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); - $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); - $this->setPageBuffer($this->page, $page . ' ' . $s . "\n" . $footer); - } else { - $this->setPageBuffer($this->page, $s, true); - } - } else { - $this->setBuffer($s); - } - } - } - - /** - * rewritten to close opened parsers - * - */ - function _enddoc() { - parent::_enddoc(); - $this->_closeParsers(); - } - - /** - * close all files opened by parsers - */ - function _closeParsers() { - if ($this->state > 2 && count($this->parsers) > 0) { - foreach ($this->parsers as $k => $_){ - $this->parsers[$k]->closeFile(); - $this->parsers[$k] = null; - unset($this->parsers[$k]); - } - return true; - } - return false; - } +current_filename = $filename; + + if (!isset($this->parsers[$filename])) + $this->parsers[$filename] = $this->_getPdfParser($filename); + $this->current_parser =& $this->parsers[$filename]; + + return $this->parsers[$filename]->getPageCount(); + } + + /** + * Returns a PDF parser object + * + * @param string $filename + * @return fpdi_pdf_parser + */ + function _getPdfParser($filename) { + return new fpdi_pdf_parser($filename, $this); + } + + /** + * Get the current PDF version + * + * @return string + */ + function getPDFVersion() { + return $this->PDFVersion; + } + + /** + * Set the PDF version + * + * @return string + */ + function setPDFVersion($version = '1.3') { + $this->PDFVersion = $version; + } + + /** + * Import a page + * + * @param int $pageno pagenumber + * @return int Index of imported page - to use with fpdf_tpl::useTemplate() + */ + function importPage($pageno, $boxName = '/CropBox') { + if ($this->_intpl) { + return $this->error('Please import the desired pages before creating a new template.'); + } + + $fn = $this->current_filename; + + // check if page already imported + $pageKey = $fn . '-' . ((int)$pageno) . $boxName; + if (isset($this->_importedPages[$pageKey])) + return $this->_importedPages[$pageKey]; + + $parser =& $this->parsers[$fn]; + $parser->setPageno($pageno); + + if (!in_array($boxName, $parser->availableBoxes)) + return $this->Error(sprintf('Unknown box: %s', $boxName)); + + $pageboxes = $parser->getPageBoxes($pageno, $this->k); + + /** + * MediaBox + * CropBox: Default -> MediaBox + * BleedBox: Default -> CropBox + * TrimBox: Default -> CropBox + * ArtBox: Default -> CropBox + */ + if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) + $boxName = '/CropBox'; + if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox') + $boxName = '/MediaBox'; + + if (!isset($pageboxes[$boxName])) + return false; + + $this->lastUsedPageBox = $boxName; + + $box = $pageboxes[$boxName]; + + $this->tpl++; + $this->tpls[$this->tpl] = array(); + $tpl =& $this->tpls[$this->tpl]; + $tpl['parser'] =& $parser; + $tpl['resources'] = $parser->getPageResources(); + $tpl['buffer'] = $parser->getContent(); + $tpl['box'] = $box; + + // To build an array that can be used by PDF_TPL::useTemplate() + $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl], $box); + + // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects() + $tpl['x'] = 0; + $tpl['y'] = 0; + + // handle rotated pages + $rotation = $parser->getPageRotation($pageno); + $tpl['_rotationAngle'] = 0; + if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) { + $steps = $angle / 90; + + $_w = $tpl['w']; + $_h = $tpl['h']; + $tpl['w'] = $steps % 2 == 0 ? $_w : $_h; + $tpl['h'] = $steps % 2 == 0 ? $_h : $_w; + + if ($angle < 0) + $angle += 360; + + $tpl['_rotationAngle'] = $angle * -1; + } + + $this->_importedPages[$pageKey] = $this->tpl; + + return $this->tpl; + } + + /** + * Returns the last used page box + * + * @return string + */ + function getLastUsedPageBox() { + return $this->lastUsedPageBox; + } + + + function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0, $adjustPageSize = false) { + if ($adjustPageSize == true && is_null($_x) && is_null($_y)) { + $size = $this->getTemplateSize($tplidx, $_w, $_h); + $orientation = $size['w'] > $size['h'] ? 'L' : 'P'; + $size = array($size['w'], $size['h']); + + if (is_subclass_of($this, 'TCPDF')) { + $this->setPageFormat($size, $orientation); + } else { + $size = $this->_getpagesize($size); + + if($orientation!=$this->CurOrientation || $size[0]!=$this->CurPageSize[0] || $size[1]!=$this->CurPageSize[1]) + { + // New size or orientation + if($orientation=='P') + { + $this->w = $size[0]; + $this->h = $size[1]; + } + else + { + $this->w = $size[1]; + $this->h = $size[0]; + } + $this->wPt = $this->w*$this->k; + $this->hPt = $this->h*$this->k; + $this->PageBreakTrigger = $this->h-$this->bMargin; + $this->CurOrientation = $orientation; + $this->CurPageSize = $size; + $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); + } + } + } + + $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values + $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); + $this->_out('Q'); + + return $s; + } + + /** + * Private method, that rebuilds all needed objects of source files + */ + function _putimportedobjects() { + if (is_array($this->parsers) && count($this->parsers) > 0) { + foreach($this->parsers AS $filename => $p) { + $this->current_parser =& $this->parsers[$filename]; + if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { + while(($n = key($this->_obj_stack[$filename])) !== null) { + $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]); + + $this->_newobj($this->_obj_stack[$filename][$n][0]); + + if ($nObj[0] == PDF_TYPE_STREAM) { + $this->pdf_write_value($nObj); + } else { + $this->pdf_write_value($nObj[1]); + } + + $this->_out('endobj'); + $this->_obj_stack[$filename][$n] = null; // free memory + unset($this->_obj_stack[$filename][$n]); + reset($this->_obj_stack[$filename]); + } + } + } + } + } + + + /** + * Private Method that writes the form xobjects + */ + function _putformxobjects() { + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->tpls); + foreach($this->tpls AS $tplidx => $tpl) { + $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + $this->_newobj(); + $cN = $this->n; // TCPDF/Protection: rem current "n" + + $this->tpls[$tplidx]['n'] = $this->n; + $this->_out('<<' . $filter . '/Type /XObject'); + $this->_out('/Subtype /Form'); + $this->_out('/FormType 1'); + + $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', + (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x']) * $this->k, + (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y']) * $this->k, + (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x']) * $this->k, + (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h'] - $tpl['y']) * $this->k + )); + + $c = 1; + $s = 0; + $tx = 0; + $ty = 0; + + if (isset($tpl['box'])) { + $tx = -$tpl['box']['llx']; + $ty = -$tpl['box']['lly']; + + if ($tpl['_rotationAngle'] <> 0) { + $angle = $tpl['_rotationAngle'] * M_PI/180; + $c=cos($angle); + $s=sin($angle); + + switch($tpl['_rotationAngle']) { + case -90: + $tx = -$tpl['box']['lly']; + $ty = $tpl['box']['urx']; + break; + case -180: + $tx = $tpl['box']['urx']; + $ty = $tpl['box']['ury']; + break; + case -270: + $tx = $tpl['box']['ury']; + $ty = -$tpl['box']['llx']; + break; + } + } + } else if ($tpl['x'] != 0 || $tpl['y'] != 0) { + $tx = -$tpl['x'] * 2; + $ty = $tpl['y'] * 2; + } + + $tx *= $this->k; + $ty *= $this->k; + + if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) { + $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]', + $c, $s, -$s, $c, $tx, $ty + )); + } + + $this->_out('/Resources '); + + if (isset($tpl['resources'])) { + $this->current_parser =& $tpl['parser']; + $this->pdf_write_value($tpl['resources']); // "n" will be changed + } else { + $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { + $this->_out('/Font <<'); + foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) + $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); + $this->_out('>>'); + } + if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || + isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) + { + $this->_out('/XObject <<'); + if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { + foreach($this->_res['tpl'][$tplidx]['images'] as $image) + $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); + } + if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { + foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) + $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); + } + $this->_out('>>'); + } + $this->_out('>>'); + } + + $nN = $this->n; // TCPDF: rem new "n" + $this->n = $cN; // TCPDF: reset to current "n" + if (is_subclass_of($this, 'TCPDF')) { + $p = $this->_getrawstream($p); + $this->_out('/Length ' . strlen($p) . ' >>'); + $this->_out("stream\n" . $p . "\nendstream"); + } else { + $this->_out('/Length ' . strlen($p) . ' >>'); + $this->_putstream($p); + } + $this->_out('endobj'); + $this->n = $nN; // TCPDF: reset to new "n" + } + + $this->_putimportedobjects(); + } + + /** + * Rewritten to handle existing own defined objects + */ + function _newobj($obj_id = false, $onlynewobj = false) { + if (!$obj_id) { + $obj_id = ++$this->n; + } + + //Begin a new object + if (!$onlynewobj) { + $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); + $this->_out($obj_id . ' 0 obj'); + $this->_current_obj_id = $obj_id; // for later use with encryption + } + + return $obj_id; + } + + /** + * Writes a value + * Needed to rebuild the source document + * + * @param mixed $value A PDF-Value. Structure of values see cases in this method + */ + function pdf_write_value(&$value) + { + if (is_subclass_of($this, 'TCPDF')) { + parent::pdf_write_value($value); + } + + switch ($value[0]) { + + case PDF_TYPE_TOKEN: + $this->_straightOut($value[1] . ' '); + break; + case PDF_TYPE_NUMERIC: + case PDF_TYPE_REAL: + if (is_float($value[1]) && $value[1] != 0) { + $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' '); + } else { + $this->_straightOut($value[1] . ' '); + } + break; + + case PDF_TYPE_ARRAY: + + // An array. Output the proper + // structure and move on. + + $this->_straightOut('['); + for ($i = 0; $i < count($value[1]); $i++) { + $this->pdf_write_value($value[1][$i]); + } + + $this->_out(']'); + break; + + case PDF_TYPE_DICTIONARY: + + // A dictionary. + $this->_straightOut('<<'); + + reset ($value[1]); + + while (list($k, $v) = each($value[1])) { + $this->_straightOut($k . ' '); + $this->pdf_write_value($v); + } + + $this->_straightOut('>>'); + break; + + case PDF_TYPE_OBJREF: + + // An indirect object reference + // Fill the object stack if needed + $cpfn =& $this->current_parser->filename; + + if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { + $this->_newobj(false, true); + $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); + $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! + } + $objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; + + $this->_out($objid . ' 0 R'); + break; + + case PDF_TYPE_STRING: + + // A string. + $this->_straightOut('(' . $value[1] . ')'); + + break; + + case PDF_TYPE_STREAM: + + // A stream. First, output the + // stream dictionary, then the + // stream data itself. + $this->pdf_write_value($value[1]); + $this->_out('stream'); + $this->_out($value[2][1]); + $this->_out('endstream'); + break; + + case PDF_TYPE_HEX: + $this->_straightOut('<' . $value[1] . '>'); + break; + + case PDF_TYPE_BOOLEAN: + $this->_straightOut($value[1] ? 'true ' : 'false '); + break; + + case PDF_TYPE_NULL: + // The null object. + + $this->_straightOut('null '); + break; + } + } + + + /** + * Modified so not each call will add a newline to the output. + */ + function _straightOut($s) { + if (!is_subclass_of($this, 'TCPDF')) { + if($this->state==2) + $this->pages[$this->page] .= $s; + else + $this->buffer .= $s; + } else { + if ($this->state == 2) { + if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { + // puts data before page footer + $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); + $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); + $this->setPageBuffer($this->page, $page . ' ' . $s . "\n" . $footer); + } else { + $this->setPageBuffer($this->page, $s, true); + } + } else { + $this->setBuffer($s); + } + } + } + + /** + * rewritten to close opened parsers + * + */ + function _enddoc() { + parent::_enddoc(); + $this->_closeParsers(); + } + + /** + * close all files opened by parsers + */ + function _closeParsers() { + if ($this->state > 2 && count($this->parsers) > 0) { + foreach ($this->parsers as $k => $_){ + $this->parsers[$k]->closeFile(); + $this->parsers[$k] = null; + unset($this->parsers[$k]); + } + return true; + } + return false; + } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php b/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php index 640700a8322..8a031a38c69 100755 --- a/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php +++ b/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php @@ -1,6 +1,6 @@ encrypted) { $value[1] = $this->_unescape($value[1]); - $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $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->_RC4($this->_objectkey($this->_current_obj_id), $value[2][1]); + $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->_RC4($this->_objectkey($this->_current_obj_id), $value[1]); + $value[1] = $this->_encrypt_data($this->_current_obj_id, $value[1]); // remake hexstring of encrypted string $value[1] = $this->str2hex($value[1]); diff --git a/htdocs/includes/fpdfi/fpdi_pdf_parser.php b/htdocs/includes/fpdfi/fpdi_pdf_parser.php index 1e87f891e87..fd2b4414c76 100755 --- a/htdocs/includes/fpdfi/fpdi_pdf_parser.php +++ b/htdocs/includes/fpdfi/fpdi_pdf_parser.php @@ -1,409 +1,408 @@ -fpdi =& $fpdi; - - parent::pdf_parser($filename); - - // resolve Pages-Dictonary - $pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']); - - // Read pages - $this->read_pages($this->c, $pages, $this->pages); - - // count pages; - $this->page_count = count($this->pages); - } - - /** - * Overwrite parent::error() - * - * @param string $msg Error-Message - */ - function error($msg) { - $this->fpdi->error($msg); - } - - /** - * Get pagecount from sourcefile - * - * @return int - */ - function getPageCount() { - return $this->page_count; - } - - - /** - * Set pageno - * - * @param int $pageno Pagenumber to use - */ - function setPageno($pageno) { - $pageno = ((int) $pageno) - 1; - - if ($pageno < 0 || $pageno >= $this->getPageCount()) { - $this->fpdi->error('Pagenumber is wrong!'); - } - - $this->pageno = $pageno; - } - - /** - * Get page-resources from current page - * - * @return array - */ - function getPageResources() { - return $this->_getPageResources($this->pages[$this->pageno]); - } - - /** - * Get page-resources from /Page - * - * @param array $obj Array of pdf-data - */ - function _getPageResources ($obj) { // $obj = /Page - $obj = $this->pdf_resolve_object($this->c, $obj); - - // If the current object has a resources - // dictionary associated with it, we use - // it. Otherwise, we move back to its - // parent object. - if (isset ($obj[1][1]['/Resources'])) { - $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Resources']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } else { - if (!isset ($obj[1][1]['/Parent'])) { - return false; - } else { - $res = $this->_getPageResources($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } - } - } - - - /** - * Get content of current page - * - * If more /Contents is an array, the streams are concated - * - * @return string - */ - function getContent() { - $buffer = ''; - - if (isset($this->pages[$this->pageno][1][1]['/Contents'])) { - $contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']); - foreach($contents AS $tmp_content) { - $buffer .= $this->_rebuildContentStream($tmp_content) . ' '; - } - } - - return $buffer; - } - - - /** - * Resolve all content-objects - * - * @param array $content_ref - * @return array - */ - function _getPageContent($content_ref) { - $contents = array(); - - if ($content_ref[0] == PDF_TYPE_OBJREF) { - $content = $this->pdf_resolve_object($this->c, $content_ref); - if ($content[1][0] == PDF_TYPE_ARRAY) { - $contents = $this->_getPageContent($content[1]); - } else { - $contents[] = $content; - } - } else if ($content_ref[0] == PDF_TYPE_ARRAY) { - foreach ($content_ref[1] AS $tmp_content_ref) { - $contents = array_merge($contents,$this->_getPageContent($tmp_content_ref)); - } - } - - return $contents; - } - - - /** - * Rebuild content-streams - * - * @param array $obj - * @return string - */ - function _rebuildContentStream($obj) { - $filters = array(); - - if (isset($obj[1][1]['/Filter'])) { - $_filter = $obj[1][1]['/Filter']; - - if ($_filter[0] == PDF_TYPE_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 string $box_index Type of Box @see $availableBoxes - * @param float Scale factor from user space units to points - * @return array - */ - function getPageBox($page, $box_index, $k) { - $page = $this->pdf_resolve_object($this->c, $page); - $box = null; - if (isset($page[1][1][$box_index])) - $box =& $page[1][1][$box_index]; - - if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { - $tmp_box = $this->pdf_resolve_object($this->c, $box); - $box = $tmp_box[1]; - } - - if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { - $b =& $box[1]; - return array('x' => $b[0][1]/$k, - 'y' => $b[1][1]/$k, - 'w' => abs($b[0][1]-$b[2][1])/$k, - 'h' => abs($b[1][1]-$b[3][1])/$k, - 'llx' => min($b[0][1], $b[2][1])/$k, - 'lly' => min($b[1][1], $b[3][1])/$k, - 'urx' => max($b[0][1], $b[2][1])/$k, - 'ury' => max($b[1][1], $b[3][1])/$k, - ); - } else if (!isset ($page[1][1]['/Parent'])) { - return false; - } else { - return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index, $k); - } - } - - /** - * Get all page boxes by page no - * - * @param int The page number - * @param float Scale factor from user space units to points - * @return array - */ - function getPageBoxes($pageno, $k) { - return $this->_getPageBoxes($this->pages[$pageno-1], $k); - } - - /** - * Get all boxes from /Page - * - * @param array a /Page - * @return array - */ - function _getPageBoxes($page, $k) { - $boxes = array(); - - foreach($this->availableBoxes AS $box) { - if ($_box = $this->getPageBox($page, $box, $k)) { - $boxes[$box] = $_box; - } - } - - return $boxes; - } - - /** - * Get the page rotation by pageno - * - * @param integer $pageno - * @return array - */ - function getPageRotation($pageno) { - return $this->_getPageRotation($this->pages[$pageno-1]); - } - - function _getPageRotation($obj) { // $obj = /Page - $obj = $this->pdf_resolve_object($this->c, $obj); - if (isset ($obj[1][1]['/Rotate'])) { - $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } else { - if (!isset ($obj[1][1]['/Parent'])) { - return false; - } else { - $res = $this->_getPageRotation($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } - } - } - - /** - * Read all /Page(es) - * - * @param object pdf_context - * @param array /Pages - * @param array the result-array - */ - function read_pages(&$c, &$pages, &$result) { - // Get the kids dictionary - $_kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); - - if (!is_array($_kids)) - $this->error('Cannot find /Kids in current /Page-Dictionary'); - - if ($_kids[1][0] == PDF_TYPE_ARRAY) { - $kids = $_kids[1][1]; - } else { - $kids = $_kids[1]; - } - - foreach ($kids as $v) { - $pg = $this->pdf_resolve_object ($c, $v); - if ($pg[1][1]['/Type'][1] === '/Pages') { - // If one of the kids is an embedded - // /Pages array, resolve it as well. - $this->read_pages($c, $pg, $result); - } else { - $result[] = $pg; - } - } - } - - - - /** - * Get PDF-Version - * - * And reset the PDF Version used in FPDI if needed - */ - function getPDFVersion() { - parent::getPDFVersion(); - $this->fpdi->setPDFVersion(max($this->fpdi->getPDFVersion(), $this->pdfVersion)); - } - +fpdi =& $fpdi; + + parent::pdf_parser($filename); + + // resolve Pages-Dictonary + $pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']); + + // Read pages + $this->read_pages($this->c, $pages, $this->pages); + + // count pages; + $this->page_count = count($this->pages); + } + + /** + * Overwrite parent::error() + * + * @param string $msg Error-Message + */ + function error($msg) { + $this->fpdi->error($msg); + } + + /** + * Get pagecount from sourcefile + * + * @return int + */ + function getPageCount() { + return $this->page_count; + } + + + /** + * Set pageno + * + * @param int $pageno Pagenumber to use + */ + function setPageno($pageno) { + $pageno = ((int) $pageno) - 1; + + if ($pageno < 0 || $pageno >= $this->getPageCount()) { + $this->fpdi->error('Pagenumber is wrong!'); + } + + $this->pageno = $pageno; + } + + /** + * Get page-resources from current page + * + * @return array + */ + function getPageResources() { + return $this->_getPageResources($this->pages[$this->pageno]); + } + + /** + * Get page-resources from /Page + * + * @param array $obj Array of pdf-data + */ + function _getPageResources ($obj) { // $obj = /Page + $obj = $this->pdf_resolve_object($this->c, $obj); + + // If the current object has a resources + // dictionary associated with it, we use + // it. Otherwise, we move back to its + // parent object. + if (isset ($obj[1][1]['/Resources'])) { + $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Resources']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } else { + if (!isset ($obj[1][1]['/Parent'])) { + return false; + } else { + $res = $this->_getPageResources($obj[1][1]['/Parent']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } + } + } + + + /** + * Get content of current page + * + * If more /Contents is an array, the streams are concated + * + * @return string + */ + function getContent() { + $buffer = ''; + + if (isset($this->pages[$this->pageno][1][1]['/Contents'])) { + $contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']); + foreach($contents AS $tmp_content) { + $buffer .= $this->_rebuildContentStream($tmp_content) . ' '; + } + } + + return $buffer; + } + + + /** + * Resolve all content-objects + * + * @param array $content_ref + * @return array + */ + function _getPageContent($content_ref) { + $contents = array(); + + if ($content_ref[0] == PDF_TYPE_OBJREF) { + $content = $this->pdf_resolve_object($this->c, $content_ref); + if ($content[1][0] == PDF_TYPE_ARRAY) { + $contents = $this->_getPageContent($content[1]); + } else { + $contents[] = $content; + } + } else if ($content_ref[0] == PDF_TYPE_ARRAY) { + foreach ($content_ref[1] AS $tmp_content_ref) { + $contents = array_merge($contents,$this->_getPageContent($tmp_content_ref)); + } + } + + return $contents; + } + + + /** + * Rebuild content-streams + * + * @param array $obj + * @return string + */ + function _rebuildContentStream($obj) { + $filters = array(); + + if (isset($obj[1][1]['/Filter'])) { + $_filter = $obj[1][1]['/Filter']; + + if ($_filter[0] == PDF_TYPE_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 string $box_index Type of Box @see $availableBoxes + * @param float Scale factor from user space units to points + * @return array + */ + function getPageBox($page, $box_index, $k) { + $page = $this->pdf_resolve_object($this->c, $page); + $box = null; + if (isset($page[1][1][$box_index])) + $box =& $page[1][1][$box_index]; + + if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { + $tmp_box = $this->pdf_resolve_object($this->c, $box); + $box = $tmp_box[1]; + } + + if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { + $b =& $box[1]; + return array('x' => $b[0][1] / $k, + 'y' => $b[1][1] / $k, + 'w' => abs($b[0][1] - $b[2][1]) / $k, + 'h' => abs($b[1][1] - $b[3][1]) / $k, + 'llx' => min($b[0][1], $b[2][1]) / $k, + 'lly' => min($b[1][1], $b[3][1]) / $k, + 'urx' => max($b[0][1], $b[2][1]) / $k, + 'ury' => max($b[1][1], $b[3][1]) / $k, + ); + } else if (!isset ($page[1][1]['/Parent'])) { + return false; + } else { + return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index, $k); + } + } + + /** + * Get all page boxes by page no + * + * @param int The page number + * @param float Scale factor from user space units to points + * @return array + */ + function getPageBoxes($pageno, $k) { + return $this->_getPageBoxes($this->pages[$pageno - 1], $k); + } + + /** + * Get all boxes from /Page + * + * @param array a /Page + * @return array + */ + function _getPageBoxes($page, $k) { + $boxes = array(); + + foreach($this->availableBoxes AS $box) { + if ($_box = $this->getPageBox($page, $box, $k)) { + $boxes[$box] = $_box; + } + } + + return $boxes; + } + + /** + * Get the page rotation by pageno + * + * @param integer $pageno + * @return array + */ + function getPageRotation($pageno) { + return $this->_getPageRotation($this->pages[$pageno - 1]); + } + + function _getPageRotation($obj) { // $obj = /Page + $obj = $this->pdf_resolve_object($this->c, $obj); + if (isset ($obj[1][1]['/Rotate'])) { + $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } else { + if (!isset ($obj[1][1]['/Parent'])) { + return false; + } else { + $res = $this->_getPageRotation($obj[1][1]['/Parent']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } + } + } + + /** + * Read all /Page(es) + * + * @param object pdf_context + * @param array /Pages + * @param array the result-array + */ + function read_pages(&$c, &$pages, &$result) { + // Get the kids dictionary + $_kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); + + if (!is_array($_kids)) + $this->error('Cannot find /Kids in current /Page-Dictionary'); + + if ($_kids[1][0] == PDF_TYPE_ARRAY) { + $kids = $_kids[1][1]; + } else { + $kids = $_kids[1]; + } + + foreach ($kids as $v) { + $pg = $this->pdf_resolve_object ($c, $v); + if ($pg[1][1]['/Type'][1] === '/Pages') { + // If one of the kids is an embedded + // /Pages array, resolve it as well. + $this->read_pages($c, $pg, $result); + } else { + $result[] = $pg; + } + } + } + + + + /** + * Get PDF-Version + * + * And reset the PDF Version used in FPDI if needed + */ + function getPDFVersion() { + parent::getPDFVersion(); + $this->fpdi->setPDFVersion(max($this->fpdi->getPDFVersion(), $this->pdfVersion)); + } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/pdf_context.php b/htdocs/includes/fpdfi/pdf_context.php index bd7f2be7f84..435df1e83da 100755 --- a/htdocs/includes/fpdfi/pdf_context.php +++ b/htdocs/includes/fpdfi/pdf_context.php @@ -1,104 +1,104 @@ -file =& $f; - if (is_string($this->file)) - $this->_mode = 1; - $this->reset(); - } - - // Optionally move the file - // pointer to a new location - // and reset the buffered data - - function reset($pos = null, $l = 100) { - if ($this->_mode == 0) { - if (!is_null ($pos)) { - fseek ($this->file, $pos); - } - - $this->buffer = $l > 0 ? fread($this->file, $l) : ''; - $this->length = strlen($this->buffer); - if ($this->length < $l) - $this->increase_length($l - $this->length); - } else { - $this->buffer = $this->file; - $this->length = strlen($this->buffer); - } - $this->offset = 0; - $this->stack = array(); - } - - // Make sure that there is at least one - // character beyond the current offset in - // the buffer to prevent the tokenizer - // from attempting to access data that does - // not exist - - function ensure_content() { - if ($this->offset >= $this->length - 1) { - return $this->increase_length(); - } else { - return true; - } - } - - // Forcefully read more data into the buffer - - function increase_length($l = 100) { - if ($this->_mode == 0 && feof($this->file)) { - return false; - } else if ($this->_mode == 0) { - $totalLength = $this->length + $l; - do { - $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 =& $f; + if (is_string($this->file)) + $this->_mode = 1; + $this->reset(); + } + + // Optionally move the file + // pointer to a new location + // and reset the buffered data + + function reset($pos = null, $l = 100) { + if ($this->_mode == 0) { + if (!is_null ($pos)) { + fseek ($this->file, $pos); + } + + $this->buffer = $l > 0 ? fread($this->file, $l) : ''; + $this->length = strlen($this->buffer); + if ($this->length < $l) + $this->increase_length($l - $this->length); + } else { + $this->buffer = $this->file; + $this->length = strlen($this->buffer); + } + $this->offset = 0; + $this->stack = array(); + } + + // Make sure that there is at least one + // character beyond the current offset in + // the buffer to prevent the tokenizer + // from attempting to access data that does + // not exist + + function ensure_content() { + if ($this->offset >= $this->length - 1) { + return $this->increase_length(); + } else { + return true; + } + } + + // Forcefully read more data into the buffer + + function increase_length($l = 100) { + if ($this->_mode == 0 && feof($this->file)) { + return false; + } else if ($this->_mode == 0) { + $totalLength = $this->length + $l; + do { + $toRead = $totalLength - $this->length; + if ($toRead < 1) + break; + + $this->buffer .= fread($this->file, $toRead); + } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); + + return true; + } else { + return false; + } + } + } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/pdf_parser.php b/htdocs/includes/fpdfi/pdf_parser.php index 3dbc557f493..4c6dd8e83e3 100755 --- a/htdocs/includes/fpdfi/pdf_parser.php +++ b/htdocs/includes/fpdfi/pdf_parser.php @@ -1,719 +1,719 @@ -filename = $filename; - - $this->f = @fopen($this->filename, 'rb'); - - if (!$this->f) - $this->error(sprintf('Cannot open %s !', $filename)); - - $this->getPDFVersion(); - - $this->c = new pdf_context($this->f); - - // Read xref-Data - $this->xref = array(); - $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); - - // Check for Encryption - $this->getEncryption(); - - // Read root - $this->pdf_read_root(); - } - - /** - * Close the opened file - */ - function closeFile() { - if (isset($this->f) && is_resource($this->f)) { - fclose($this->f); - unset($this->f); - } - } - - /** - * Print Error and die - * - * @param string $msg Error-Message - */ - function error($msg) { - die('PDF-Parser Error: '.$msg); - } - - /** - * Check Trailer for Encryption - */ - function getEncryption() { - if (isset($this->xref['trailer'][1]['/Encrypt'])) { - $this->error('File is encrypted!'); - } - } - - /** - * Find/Return /Root - * - * @return array - */ - function pdf_find_root() { - if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { - $this->error('Wrong Type of Root-Element! Must be an indirect reference'); - } - - return $this->xref['trailer'][1]['/Root']; - } - - /** - * Read the /Root - */ - function pdf_read_root() { - // read root - $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); - } - - /** - * Get PDF-Version - * - * And reset the PDF Version used in FPDI if needed - */ - function getPDFVersion() { - fseek($this->f, 0); - preg_match('/\d\.\d/',fread($this->f,16),$m); - if (isset($m[0])) - $this->pdfVersion = $m[0]; - return $this->pdfVersion; - } - - /** - * Find the xref-Table - */ - function pdf_find_xref() { - $toRead = 1500; - - $stat = fseek ($this->f, -$toRead, SEEK_END); - if ($stat === -1) { - fseek ($this->f, 0); - } - $data = fread($this->f, $toRead); - - $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); - $data = substr($data, $pos); - - if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { - $this->error('Unable to find pointer to xref table'); - } - - return (int) $matches[1]; - } - - /** - * Read xref-table - * - * @param array $result Array of xref-table - * @param integer $offset of xref-table - */ - function pdf_read_xref(&$result, $offset) { - $o_pos = $offset-min(20, $offset); - fseek($this->f, $o_pos); // set some bytes backwards to fetch errorious docs - - $data = fread($this->f, 100); - - $xrefPos = strrpos($data, 'xref'); - - if ($xrefPos === false) { - fseek($this->f, $offset); - $c = new pdf_context($this->f); - $xrefStreamObjDec = $this->pdf_read_value($c); - - if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == PDF_TYPE_OBJDEC) { - $this->error(sprintf('This document (%s) probably uses a compression technique which is not supported by the free parser shipped with FPDI.', $this->filename)); - } else { - $this->error('Unable to find xref table.'); - } - } - - if (!isset($result['xref_location'])) { - $result['xref_location'] = $o_pos+$xrefPos; - $result['max_object'] = 0; - } - - $cylces = -1; - $bytesPerCycle = 100; - - fseek($this->f, $o_pos = $o_pos+$xrefPos+4); // set the handle directly after the "xref"-keyword - $data = fread($this->f, $bytesPerCycle); - - while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle*$cylces++, 0))) === false && !feof($this->f)) { - $data .= fread($this->f, $bytesPerCycle); - } - - if ($trailerPos === false) { - $this->error('Trailer keyword not found after xref table'); - } - - $data = substr($data, 0, $trailerPos); - - // get Line-Ending - preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for linebreaks - - $differentLineEndings = count(array_unique($m[0])); - if ($differentLineEndings > 1) { - $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY); - } else { - $lines = explode($m[0][1], $data); - } - - $data = $differentLineEndings = $m = null; - unset($data, $differentLineEndings, $m); - - $linesCount = count($lines); - - $start = 1; - - for ($i = 0; $i < $linesCount; $i++) { - $line = trim($lines[$i]); - if ($line) { - $pieces = explode(' ', $line); - $c = count($pieces); - switch($c) { - case 2: - $start = (int)$pieces[0]; - $end = $start+(int)$pieces[1]; - if ($end > $result['max_object']) - $result['max_object'] = $end; - break; - case 3: - if (!isset($result['xref'][$start])) - $result['xref'][$start] = array(); - - if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) { - $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null; - } - $start++; - break; - default: - $this->error('Unexpected data in xref table'); - } - } - } - - $lines = $pieces = $line = $start = $end = $gen = null; - unset($lines, $pieces, $line, $start, $end, $gen); - - fseek($this->f, $o_pos+$trailerPos+7); - - $c = new pdf_context($this->f); - $trailer = $this->pdf_read_value($c); - - $c = null; - unset($c); - - if (!isset($result['trailer'])) { - $result['trailer'] = $trailer; - } - - if (isset($trailer[1]['/Prev'])) { - $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); - } - - $trailer = null; - unset($trailer); - - return true; - } - - /** - * Reads an Value - * - * @param object $c pdf_context - * @param string $token a Token - * @return mixed - */ - function pdf_read_value(&$c, $token = null) { - if (is_null($token)) { - $token = $this->pdf_read_token($c); - } - - if ($token === false) { - return false; - } - - switch ($token) { - case '<': - // This is a hex string. - // Read the value, then the terminator - - $pos = $c->offset; - - while(1) { - - $match = strpos ($c->buffer, '>', $pos); - - // If you can't find it, try - // reading more data from the stream - - if ($match === false) { - if (!$c->increase_length()) { - return false; - } else { - continue; - } - } - - $result = substr ($c->buffer, $c->offset, $match - $c->offset); - $c->offset = $match + 1; - - return array (PDF_TYPE_HEX, $result); - } - - break; - case '<<': - // This is a dictionary. - - $result = array(); - - // Recurse into this function until we reach - // the end of the dictionary. - while (($key = $this->pdf_read_token($c)) !== '>>') { - if ($key === false) { - return false; - } - - if (($value = $this->pdf_read_value($c)) === false) { - return false; - } - - // Catch missing value - if ($value[0] == PDF_TYPE_TOKEN && $value[1] == '>>') { - $result[$key] = array(PDF_TYPE_NULL); - break; - } - - $result[$key] = $value; - } - - return array (PDF_TYPE_DICTIONARY, $result); - - case '[': - // This is an array. - - $result = array(); - - // Recurse into this function until we reach - // the end of the array. - while (($token = $this->pdf_read_token($c)) !== ']') { - if ($token === false) { - return false; - } - - if (($value = $this->pdf_read_value($c, $token)) === false) { - return false; - } - - $result[] = $value; - } - - return array (PDF_TYPE_ARRAY, $result); - - case '(' : - // This is a string - $pos = $c->offset; - - $openBrackets = 1; - do { - for (; $openBrackets != 0 && $pos < $c->length; $pos++) { - switch (ord($c->buffer[$pos])) { - case 0x28: // '(' - $openBrackets++; - break; - case 0x29: // ')' - $openBrackets--; - break; - case 0x5C: // backslash - $pos++; - } - } - } while($openBrackets != 0 && $c->increase_length()); - - $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); - $c->offset = $pos; - - return array (PDF_TYPE_STRING, $result); - - case 'stream': - $o_pos = ftell($c->file)-strlen($c->buffer); - $o_offset = $c->offset; - - $c->reset($startpos = $o_pos + $o_offset); - - $e = 0; // ensure line breaks in front of the stream - if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) - $e++; - if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) - $e++; - - if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { - $tmp_c = new pdf_context($this->f); - $tmp_length = $this->pdf_resolve_object($tmp_c, $this->actual_obj[1][1]['/Length']); - $length = $tmp_length[1][1]; - } else { - $length = $this->actual_obj[1][1]['/Length'][1]; - } - - if ($length > 0) { - $c->reset($startpos+$e,$length); - $v = $c->buffer; - } else { - $v = ''; - } - $c->reset($startpos+$e+$length+9); // 9 = strlen("endstream") - - return array(PDF_TYPE_STREAM, $v); - - default : - if (is_numeric ($token)) { - // A numeric token. Make sure that - // it is not part of something else. - if (($tok2 = $this->pdf_read_token ($c)) !== false) { - if (is_numeric ($tok2)) { - - // Two numeric tokens in a row. - // In this case, we're probably in - // front of either an object reference - // or an object specification. - // Determine the case and return the data - if (($tok3 = $this->pdf_read_token ($c)) !== false) { - switch ($tok3) { - case 'obj' : - return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); - case 'R' : - return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2); - } - // If we get to this point, that numeric value up - // there was just a numeric value. Push the extra - // tokens back into the stack and return the value. - array_push ($c->stack, $tok3); - } - } - - array_push ($c->stack, $tok2); - } - - if ($token === (string)((int)$token)) - return array (PDF_TYPE_NUMERIC, (int)$token); - else - return array (PDF_TYPE_REAL, (float)$token); - } else if ($token == 'true' || $token == 'false') { - return array (PDF_TYPE_BOOLEAN, $token == 'true'); - } else if ($token == 'null') { - return array (PDF_TYPE_NULL); - } else { - // Just a token. Return it. - return array (PDF_TYPE_TOKEN, $token); - } - } - } - - /** - * Resolve an object - * - * @param object $c pdf_context - * @param array $obj_spec The object-data - * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para - */ - function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { - // Exit if we get invalid data - if (!is_array($obj_spec)) { - $ret = false; - return $ret; - } - - if ($obj_spec[0] == PDF_TYPE_OBJREF) { - - // This is a reference, resolve it - if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) { - - // Save current file position - // This is needed if you want to resolve - // references while you're reading another object - // (e.g.: if you need to determine the length - // of a stream) - - $old_pos = ftell($c->file); - - // Reposition the file pointer and - // load the object header. - - $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); - - $header = $this->pdf_read_value($c); - - if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { - $toSearchFor = $obj_spec[1].' '.$obj_spec[2].' obj'; - if (preg_match('/'.$toSearchFor.'/', $c->buffer)) { - $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor); - // reset stack - $c->stack = array(); - } else { - $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); - } - } - - // If we're being asked to store all the information - // about the object, we add the object ID and generation - // number for later use - $result = array(); - $this->actual_obj =& $result; - if ($encapsulate) { - $result = array ( - PDF_TYPE_OBJECT, - 'obj' => $obj_spec[1], - 'gen' => $obj_spec[2] - ); - } - - // Now simply read the object data until - // we encounter an end-of-object marker - while(1) { - $value = $this->pdf_read_value($c); - if ($value === false || count($result) > 4) { - // in this case the parser coudn't find an endobj so we break here - break; - } - - if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { - break; - } - - $result[] = $value; - } - - $c->reset($old_pos); - - if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { - $result[0] = PDF_TYPE_STREAM; - } - - return $result; - } - } else { - return $obj_spec; - } - } - - - - /** - * Reads a token from the file - * - * @param object $c pdf_context - * @return mixed - */ - function pdf_read_token(&$c) - { - // If there is a token available - // on the stack, pop it out and - // return it. - - if (count($c->stack)) { - return array_pop($c->stack); - } - - // Strip away any whitespace - - do { - if (!$c->ensure_content()) { - return false; - } - $c->offset += strspn($c->buffer, " \n\r\t", $c->offset); - } while ($c->offset >= $c->length - 1); - - // Get the first character in the stream - - $char = $c->buffer[$c->offset++]; - - switch ($char) { - - case '[': - case ']': - case '(': - case ')': - - // This is either an array or literal string - // delimiter, Return it - - return $char; - - case '<': - case '>': - - // This could either be a hex string or - // dictionary delimiter. Determine the - // appropriate case and return the token - - if ($c->buffer[$c->offset] == $char) { - if (!$c->ensure_content()) { - return false; - } - $c->offset++; - return $char . $char; - } else { - return $char; - } - - case '%': - - // This is a comment - jump over it! - - $pos = $c->offset; - while(1) { - $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); - if ($match === 0) { - if (!$c->increase_length()) { - return false; - } else { - continue; - } - } - - $c->offset = $m[0][1]+strlen($m[0][0]); - - return $this->pdf_read_token($c); - } - - default: - - // This is "another" type of token (probably - // a dictionary entry or a numeric value) - // Find the end and return it. - - if (!$c->ensure_content()) { - return false; - } - - while(1) { - - // Determine the length of the token - - $pos = strcspn($c->buffer, " %[]<>()\r\n\t/", $c->offset); - - if ($c->offset + $pos <= $c->length - 1) { - break; - } else { - // If the script reaches this point, - // the token may span beyond the end - // of the current buffer. Therefore, - // we increase the size of the buffer - // and try again--just to be safe. - - $c->increase_length(); - } - } - - $result = substr($c->buffer, $c->offset - 1, $pos + 1); - - $c->offset += $pos; - return $result; - } - } - } -} +filename = $filename; + + $this->f = @fopen($this->filename, 'rb'); + + if (!$this->f) + $this->error(sprintf('Cannot open %s !', $filename)); + + $this->getPDFVersion(); + + $this->c = new pdf_context($this->f); + + // Read xref-Data + $this->xref = array(); + $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); + + // Check for Encryption + $this->getEncryption(); + + // Read root + $this->pdf_read_root(); + } + + /** + * Close the opened file + */ + function closeFile() { + if (isset($this->f) && is_resource($this->f)) { + fclose($this->f); + unset($this->f); + } + } + + /** + * Print Error and die + * + * @param string $msg Error-Message + */ + function error($msg) { + die('PDF-Parser Error: ' . $msg); + } + + /** + * Check Trailer for Encryption + */ + function getEncryption() { + if (isset($this->xref['trailer'][1]['/Encrypt'])) { + $this->error('File is encrypted!'); + } + } + + /** + * Find/Return /Root + * + * @return array + */ + function pdf_find_root() { + if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { + $this->error('Wrong Type of Root-Element! Must be an indirect reference'); + } + + return $this->xref['trailer'][1]['/Root']; + } + + /** + * Read the /Root + */ + function pdf_read_root() { + // read root + $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); + } + + /** + * Get PDF-Version + * + * And reset the PDF Version used in FPDI if needed + */ + function getPDFVersion() { + fseek($this->f, 0); + preg_match('/\d\.\d/',fread($this->f, 16), $m); + if (isset($m[0])) + $this->pdfVersion = $m[0]; + return $this->pdfVersion; + } + + /** + * Find the xref-Table + */ + function pdf_find_xref() { + $toRead = 1500; + + $stat = fseek ($this->f, -$toRead, SEEK_END); + if ($stat === -1) { + fseek ($this->f, 0); + } + $data = fread($this->f, $toRead); + + $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); + $data = substr($data, $pos); + + if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { + $this->error('Unable to find pointer to xref table'); + } + + return (int) $matches[1]; + } + + /** + * Read xref-table + * + * @param array $result Array of xref-table + * @param integer $offset of xref-table + */ + function pdf_read_xref(&$result, $offset) { + $o_pos = $offset-min(20, $offset); + fseek($this->f, $o_pos); // set some bytes backwards to fetch errorious docs + + $data = fread($this->f, 100); + + $xrefPos = strrpos($data, 'xref'); + + if ($xrefPos === false) { + fseek($this->f, $offset); + $c = new pdf_context($this->f); + $xrefStreamObjDec = $this->pdf_read_value($c); + + if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == PDF_TYPE_OBJDEC) { + $this->error(sprintf('This document (%s) probably uses a compression technique which is not supported by the free parser shipped with FPDI.', $this->filename)); + } else { + $this->error('Unable to find xref table.'); + } + } + + if (!isset($result['xref_location'])) { + $result['xref_location'] = $o_pos + $xrefPos; + $result['max_object'] = 0; + } + + $cylces = -1; + $bytesPerCycle = 100; + + fseek($this->f, $o_pos = $o_pos + $xrefPos + 4); // set the handle directly after the "xref"-keyword + $data = fread($this->f, $bytesPerCycle); + + while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle * $cylces++, 0))) === false && !feof($this->f)) { + $data .= fread($this->f, $bytesPerCycle); + } + + if ($trailerPos === false) { + $this->error('Trailer keyword not found after xref table'); + } + + $data = substr($data, 0, $trailerPos); + + // get Line-Ending + preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for linebreaks + + $differentLineEndings = count(array_unique($m[0])); + if ($differentLineEndings > 1) { + $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY); + } else { + $lines = explode($m[0][1], $data); + } + + $data = $differentLineEndings = $m = null; + unset($data, $differentLineEndings, $m); + + $linesCount = count($lines); + + $start = 1; + + for ($i = 0; $i < $linesCount; $i++) { + $line = trim($lines[$i]); + if ($line) { + $pieces = explode(' ', $line); + $c = count($pieces); + switch($c) { + case 2: + $start = (int)$pieces[0]; + $end = $start + (int)$pieces[1]; + if ($end > $result['max_object']) + $result['max_object'] = $end; + break; + case 3: + if (!isset($result['xref'][$start])) + $result['xref'][$start] = array(); + + if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) { + $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null; + } + $start++; + break; + default: + $this->error('Unexpected data in xref table'); + } + } + } + + $lines = $pieces = $line = $start = $end = $gen = null; + unset($lines, $pieces, $line, $start, $end, $gen); + + fseek($this->f, $o_pos + $trailerPos + 7); + + $c = new pdf_context($this->f); + $trailer = $this->pdf_read_value($c); + + $c = null; + unset($c); + + if (!isset($result['trailer'])) { + $result['trailer'] = $trailer; + } + + if (isset($trailer[1]['/Prev'])) { + $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); + } + + $trailer = null; + unset($trailer); + + return true; + } + + /** + * Reads an Value + * + * @param object $c pdf_context + * @param string $token a Token + * @return mixed + */ + function pdf_read_value(&$c, $token = null) { + if (is_null($token)) { + $token = $this->pdf_read_token($c); + } + + if ($token === false) { + return false; + } + + switch ($token) { + case '<': + // This is a hex string. + // Read the value, then the terminator + + $pos = $c->offset; + + while(1) { + + $match = strpos ($c->buffer, '>', $pos); + + // If you can't find it, try + // reading more data from the stream + + if ($match === false) { + if (!$c->increase_length()) { + return false; + } else { + continue; + } + } + + $result = substr ($c->buffer, $c->offset, $match - $c->offset); + $c->offset = $match + 1; + + return array (PDF_TYPE_HEX, $result); + } + + break; + case '<<': + // This is a dictionary. + + $result = array(); + + // Recurse into this function until we reach + // the end of the dictionary. + while (($key = $this->pdf_read_token($c)) !== '>>') { + if ($key === false) { + return false; + } + + if (($value = $this->pdf_read_value($c)) === false) { + return false; + } + + // Catch missing value + if ($value[0] == PDF_TYPE_TOKEN && $value[1] == '>>') { + $result[$key] = array(PDF_TYPE_NULL); + break; + } + + $result[$key] = $value; + } + + return array (PDF_TYPE_DICTIONARY, $result); + + case '[': + // This is an array. + + $result = array(); + + // Recurse into this function until we reach + // the end of the array. + while (($token = $this->pdf_read_token($c)) !== ']') { + if ($token === false) { + return false; + } + + if (($value = $this->pdf_read_value($c, $token)) === false) { + return false; + } + + $result[] = $value; + } + + return array (PDF_TYPE_ARRAY, $result); + + case '(' : + // This is a string + $pos = $c->offset; + + $openBrackets = 1; + do { + for (; $openBrackets != 0 && $pos < $c->length; $pos++) { + switch (ord($c->buffer[$pos])) { + case 0x28: // '(' + $openBrackets++; + break; + case 0x29: // ')' + $openBrackets--; + break; + case 0x5C: // backslash + $pos++; + } + } + } while($openBrackets != 0 && $c->increase_length()); + + $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); + $c->offset = $pos; + + return array (PDF_TYPE_STRING, $result); + + case 'stream': + $o_pos = ftell($c->file)-strlen($c->buffer); + $o_offset = $c->offset; + + $c->reset($startpos = $o_pos + $o_offset); + + $e = 0; // ensure line breaks in front of the stream + if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) + $e++; + if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) + $e++; + + if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { + $tmp_c = new pdf_context($this->f); + $tmp_length = $this->pdf_resolve_object($tmp_c, $this->actual_obj[1][1]['/Length']); + $length = $tmp_length[1][1]; + } else { + $length = $this->actual_obj[1][1]['/Length'][1]; + } + + if ($length > 0) { + $c->reset($startpos + $e,$length); + $v = $c->buffer; + } else { + $v = ''; + } + $c->reset($startpos + $e + $length + 9); // 9 = strlen("endstream") + + return array(PDF_TYPE_STREAM, $v); + + default : + if (is_numeric ($token)) { + // A numeric token. Make sure that + // it is not part of something else. + if (($tok2 = $this->pdf_read_token ($c)) !== false) { + if (is_numeric ($tok2)) { + + // Two numeric tokens in a row. + // In this case, we're probably in + // front of either an object reference + // or an object specification. + // Determine the case and return the data + if (($tok3 = $this->pdf_read_token ($c)) !== false) { + switch ($tok3) { + case 'obj': + return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); + case 'R': + return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2); + } + // If we get to this point, that numeric value up + // there was just a numeric value. Push the extra + // tokens back into the stack and return the value. + array_push ($c->stack, $tok3); + } + } + + array_push ($c->stack, $tok2); + } + + if ($token === (string)((int)$token)) + return array (PDF_TYPE_NUMERIC, (int)$token); + else + return array (PDF_TYPE_REAL, (float)$token); + } else if ($token == 'true' || $token == 'false') { + return array (PDF_TYPE_BOOLEAN, $token == 'true'); + } else if ($token == 'null') { + return array (PDF_TYPE_NULL); + } else { + // Just a token. Return it. + return array (PDF_TYPE_TOKEN, $token); + } + } + } + + /** + * Resolve an object + * + * @param object $c pdf_context + * @param array $obj_spec The object-data + * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para + */ + function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { + // Exit if we get invalid data + if (!is_array($obj_spec)) { + $ret = false; + return $ret; + } + + if ($obj_spec[0] == PDF_TYPE_OBJREF) { + + // This is a reference, resolve it + if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) { + + // Save current file position + // This is needed if you want to resolve + // references while you're reading another object + // (e.g.: if you need to determine the length + // of a stream) + + $old_pos = ftell($c->file); + + // Reposition the file pointer and + // load the object header. + + $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); + + $header = $this->pdf_read_value($c); + + if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { + $toSearchFor = $obj_spec[1] . ' ' . $obj_spec[2] . ' obj'; + if (preg_match('/' . $toSearchFor . '/', $c->buffer)) { + $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor); + // reset stack + $c->stack = array(); + } else { + $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); + } + } + + // If we're being asked to store all the information + // about the object, we add the object ID and generation + // number for later use + $result = array(); + $this->actual_obj =& $result; + if ($encapsulate) { + $result = array ( + PDF_TYPE_OBJECT, + 'obj' => $obj_spec[1], + 'gen' => $obj_spec[2] + ); + } + + // Now simply read the object data until + // we encounter an end-of-object marker + while(1) { + $value = $this->pdf_read_value($c); + if ($value === false || count($result) > 4) { + // in this case the parser coudn't find an endobj so we break here + break; + } + + if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { + break; + } + + $result[] = $value; + } + + $c->reset($old_pos); + + if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { + $result[0] = PDF_TYPE_STREAM; + } + + return $result; + } + } else { + return $obj_spec; + } + } + + + + /** + * Reads a token from the file + * + * @param object $c pdf_context + * @return mixed + */ + function pdf_read_token(&$c) + { + // If there is a token available + // on the stack, pop it out and + // return it. + + if (count($c->stack)) { + return array_pop($c->stack); + } + + // Strip away any whitespace + + do { + if (!$c->ensure_content()) { + return false; + } + $c->offset += strspn($c->buffer, " \n\r\t", $c->offset); + } while ($c->offset >= $c->length - 1); + + // Get the first character in the stream + + $char = $c->buffer[$c->offset++]; + + switch ($char) { + + case '[': + case ']': + case '(': + case ')': + + // This is either an array or literal string + // delimiter, Return it + + return $char; + + case '<': + case '>': + + // This could either be a hex string or + // dictionary delimiter. Determine the + // appropriate case and return the token + + if ($c->buffer[$c->offset] == $char) { + if (!$c->ensure_content()) { + return false; + } + $c->offset++; + return $char . $char; + } else { + return $char; + } + + case '%': + + // This is a comment - jump over it! + + $pos = $c->offset; + while(1) { + $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); + if ($match === 0) { + if (!$c->increase_length()) { + return false; + } else { + continue; + } + } + + $c->offset = $m[0][1]+strlen($m[0][0]); + + return $this->pdf_read_token($c); + } + + default: + + // This is "another" type of token (probably + // a dictionary entry or a numeric value) + // Find the end and return it. + + if (!$c->ensure_content()) { + return false; + } + + while(1) { + + // Determine the length of the token + + $pos = strcspn($c->buffer, " %[]<>()\r\n\t/", $c->offset); + + if ($c->offset + $pos <= $c->length - 1) { + break; + } else { + // If the script reaches this point, + // the token may span beyond the end + // of the current buffer. Therefore, + // we increase the size of the buffer + // and try again--just to be safe. + + $c->increase_length(); + } + } + + $result = substr($c->buffer, $c->offset - 1, $pos + 1); + + $c->offset += $pos; + return $result; + } + } + } +} diff --git a/htdocs/includes/tcpdf/2dbarcodes.php b/htdocs/includes/tcpdf/2dbarcodes.php index e04b3073ce1..6490dfa7eaf 100644 --- a/htdocs/includes/tcpdf/2dbarcodes.php +++ b/htdocs/includes/tcpdf/2dbarcodes.php @@ -1,9 +1,9 @@ barcode_array['bcode'][$r][$c] == 1) { // draw a single barcode cell if ($imagick) { - $bar->rectangle($x, $y, ($x + $w), ($y + $h)); + $bar->rectangle($x, $y, ($x + $w - 1), ($y + $h - 1)); } else { - imagefilledrectangle($png, $x, $y, ($x + $w), ($y + $h), $fgcol); + imagefilledrectangle($png, $x, $y, ($x + $w - 1), ($y + $h - 1), $fgcol); } } $x += $w; diff --git a/htdocs/includes/tcpdf/CHANGELOG.TXT b/htdocs/includes/tcpdf/CHANGELOG.TXT index 23a14f9991d..d3c29f94068 100644 --- a/htdocs/includes/tcpdf/CHANGELOG.TXT +++ b/htdocs/includes/tcpdf/CHANGELOG.TXT @@ -1,3 +1,94 @@ +5.9.180 (2012-08-22) + - Bug item #3560493 "Problems with nested cells in HTML" was fixed. + +5.9.179 (2012-08-04) + - SVG 'use' tag was fixed for 'circle' and 'ellipse' shift problem. + - Alpha status is now correctly stored and restored by getGraphicVars() and SetGraphicVars() methods. + +5.9.178 (2012-08-02) + - SVG 'use' tag was fixed for 'circle' and 'ellipse'. + +5.9.177 (2012-08-02) + - An additional control on annotations was fixed. + +5.9.176 (2012-07-25) + - A bug related to stroke width was fixed. + - A problem related to font spacing in HTML was fixed. + +5.9.175 (2012-07-25) + - The problem of missing letter on hyphen break was fixed. + +5.9.174 (2012-07-25) + - The problem of wrong filename when downloading PDF from an Android device was fixed. + - The method setHeaderData() was extended to set text and line color for header (see example n. 1). + - The method setFooterData() was added to set text and line color for footer (see example n. 1). + - The methods setTextShadow() and getTextShadow() were added to set text shadows (see example n. 1). + - The GetCharWidth() method was fixed for negative character spacing. + - A 'none' border mode is now correctly recognized. + - Break on hyphen problem was fixed. + +5.9.173 (2012-07-23) + - Some additional control wher added on barcode methods. + - The option CURLOPT_FOLLOWLOCATION on Image method is now disabled if PHP safe_mode is on or open_basedir is set. + - Method Bookmark() was extended to include X parameter. + - Method setDestination() was extended to include X parameter. + - A problem with Thai language was fixed. + +5.9.172 (2012-07-02) + - A PNG color profile issue was fixed. + +5.9.171 (2012-07-01) + - Some SVG rendering problems were fixed. + +5.9.170 (2012-06-27) + - Bug #3538227 "Numerous errors inserting shared images" was fixed. + +5.9.169 (2012-06-25) + - Some SVG rendering problems were fixed. + +5.9.168 (2012-06-22) + - Thai language rendering was fixed. + +5.9.167 (2012-06-22) + - Thai language rendering was fixed and improved. + - Method isCharDefined() was improved. + - Protected method replaceChar() was added. + - Font "kerning" word was corrected to "tracking". + +5.9.166 (2012-06-21) + - Array to string conversion on file_id creation was fixed. + - Thai language rendering was fixed (thanks to Atsawin Chaowanakritsanakul). + +5.9.165 (2012-06-07) + - Some HTML form related bugs were fixed. + +5.9.164 (2012-06-06) + - A bug introduced on the latest release was fixed. + +5.9.163 (2012-06-05) + - Method getGDgamma() was changed. + - Rendering performances of PNG images with alpha channel were improved. + +5.9.162 (2012-05-11) + - A bug related to long text on TD cells was fixed. + +5.9.161 (2012-05-09) + - A bug on XREF table was fixed (Bug ID: 3525051). + - Deprecated Imagick:clone was replaced. + - Method objclone() was fixed for PHP4. + +5.9.160 (2012-05-03) + - A bug on tcpdf_parser.php was fixed. + +5.9.159 (2012-04-30) + - Barcode classes were updated to fix PNG export Bug (ID: 3522291). + +5.9.158 (2012-04-22) + - Some SVG-related bugs were fixed. + +5.9.157 (2012-04-16) + - Some SVG-related bugs were fixed. + 5.9.156 (2012-04-10) - Bug item #3515885 "TOC and booklet: left and right page exchanged". - SetAutoPageBreak(false) now works also in multicolumn mode. @@ -567,7 +658,7 @@ - The problem of blank page for nobr table higher than a single page was fixed. 5.9.000 (2010-10-06) - - Support for text stretching and spacing (kerning) was added, see example n. 63 and methods setFontStretching(), getFontStretching(), setFontSpacing(), getFontSpacing(). + - Support for text stretching and spacing (tracking) was added, see example n. 63 and methods setFontStretching(), getFontStretching(), setFontSpacing(), getFontSpacing(). - Support for CSS properties 'font-stretch' and 'letter-spacing' was added (see example n. 63). - The cMargin state was replaced by cell_padding array that can be set/get using setCellPadding() and getCellPadding() methods. - Methods getCellPaddings() and setCellPaddings() were added to fine tune cell paddings (see example n. 5). diff --git a/htdocs/includes/tcpdf/README.TXT b/htdocs/includes/tcpdf/README.TXT index 83520bb1272..ff86c9d23b0 100644 --- a/htdocs/includes/tcpdf/README.TXT +++ b/htdocs/includes/tcpdf/README.TXT @@ -8,8 +8,8 @@ http://sourceforge.net/donate/index.php?group_id=128076 ------------------------------------------------------------ Name: TCPDF -Version: 5.9.156 -Release date: 2012-04-10 +Version: 5.9.180 +Release date: 2012-08-22 Author: Nicola Asuni Copyright (c) 2002-2012: @@ -47,7 +47,7 @@ Main Features: * no-write page regions; * bookmarks, named destinations and table of content; * text hyphenation; - * text stretching and spacing (tracking/kerning); + * text stretching and spacing (tracking); * automatic page break, line break and text alignments including justification; * automatic page numbering and page groups; * move and delete pages; diff --git a/htdocs/includes/tcpdf/barcodes.php b/htdocs/includes/tcpdf/barcodes.php index 4027aa7109a..c6c0172e4a3 100644 --- a/htdocs/includes/tcpdf/barcodes.php +++ b/htdocs/includes/tcpdf/barcodes.php @@ -1,9 +1,9 @@ * @package com.tecnick.tcpdf - * @version 1.0.023 + * @version 1.0.024 * @author Nicola Asuni */ class TCPDFBarcode { @@ -201,9 +201,9 @@ class TCPDFBarcode { $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3); // draw a vertical bar if ($imagick) { - $bar->rectangle($x, $y, ($x + $bw), ($y + $bh)); + $bar->rectangle($x, $y, ($x + $bw - 1), ($y + $bh - 1)); } else { - imagefilledrectangle($png, $x, $y, ($x + $bw), ($y + $bh), $fgcol); + imagefilledrectangle($png, $x, $y, ($x + $bw - 1), ($y + $bh - 1), $fgcol); } } $x += $bw; diff --git a/htdocs/includes/tcpdf/config/lang/bul.php b/htdocs/includes/tcpdf/config/lang/bul.php index 00a44ef03e4..d7bbaaf6a30 100644 --- a/htdocs/includes/tcpdf/config/lang/bul.php +++ b/htdocs/includes/tcpdf/config/lang/bul.php @@ -1,47 +1,47 @@ -dataStr) > 0) { - if ($this->dataStr == '') { - return 0; - } $mode = $this->identifyMode(0); switch ($mode) { case QR_MODE_NM: { @@ -1476,6 +1474,7 @@ class QRcode { } $this->dataStr = substr($this->dataStr, $length); } + return 0; } /** @@ -2028,7 +2027,7 @@ class QRcode { if ($ver > $this->version) { $this->version = $ver; } - for (;;) { + while (true) { $cbs = $this->createBitStream($items); $items = $cbs[0]; $bits = $cbs[1]; @@ -2315,17 +2314,18 @@ class QRcode { /** * Return a version number that satisfies the input code length. - * @param $size (int) input code length (byte) + * @param $size (int) input code length (bytes) * @param $level (int) error correction level * @return int version number */ protected function getMinimumVersion($size, $level) { - for ($i=1; $i <= QRSPEC_VERSION_MAX; ++$i) { - $words = $this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level]; + for ($i = 1; $i <= QRSPEC_VERSION_MAX; ++$i) { + $words = ($this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level]); if ($words >= $size) { return $i; } } + // the size of input data is greater than QR capacity, try to lover the error correction mode return -1; } diff --git a/htdocs/includes/tcpdf/tcpdf.php b/htdocs/includes/tcpdf/tcpdf.php index 7c18096a52a..21da1606ed1 100644 --- a/htdocs/includes/tcpdf/tcpdf.php +++ b/htdocs/includes/tcpdf/tcpdf.php @@ -1,9 +1,9 @@ no-write page regions; *