From 82fc97bf1c74c8dbe62b1d3cc6d10fa4b87e0262 Mon Sep 17 00:00:00 2001 From: nicolaasuni Date: Mon, 25 Mar 2024 23:52:22 +0000 Subject: [PATCH] Squash multiple fixes --- CHANGELOG.TXT | 24 +++ LICENSE.TXT | 2 +- README.md | 7 +- VERSION | 2 +- config/tcpdf_config.php | 8 + examples/config/tcpdf_config_alt.php | 8 + examples/example_049.php | 34 +++-- examples/example_066.php | 4 +- include/barcodes/qrcode.php | 1 + include/tcpdf_fonts.php | 50 +++--- include/tcpdf_static.php | 10 +- phpstan.neon.dist | 2 - tcpdf.php | 221 ++++++++++++++++----------- tcpdf_autoconfig.php | 4 + tcpdf_barcodes_1d.php | 6 +- tests/composer.json | 14 +- 16 files changed, 237 insertions(+), 160 deletions(-) diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index 39970db3..c70e22bf 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -1,3 +1,27 @@ +6.7.4 (2024-03-24) + - Upgrade tcpdf tag encryption algorithm. + - Fix regression issue #699. + - Fix security issue. + - [BREAKING CHANGE] The tcpdf HTML tag syntax has changed, see example_049.php. + - New K_ALLOWED_TCPDF_TAGS configuration constant to set the allowed methods for the tcdpf HTML tag. + - Raised minimum PHP version to PHP 5.5.0. + +6.6.5 (2023-09-02) + - Fix corrupted file. + - Fix GitHub automation tests. + - Fix SPDX license ID (#591) + - Fix warning "array offset on value of type null" (#620) + - Improve the README about the status of this library (#589) + - Fix deprecation warning with PHP 8.1 (#614) + - Fixes for PHP 8.2 in tcpdf_fonts.php (#632) + - Fix some php 8+ edge cases (#630) + - Fix composite glyph output (#581) + - Fix "access array offset on value of type bool" with PDF/A (#583) + - Fix non-numeric value warning (#627) + - Fix issues with S25 barcode (#611) + - Fix return type annotations (#613) + - Fix some inconsistencies in type hints (#598) + 6.6.2 (2022-12-17) - Ensure pregSplit return type is always array. - Add ability to run tests on various operating systems (#566) diff --git a/LICENSE.TXT b/LICENSE.TXT index ec191e2a..ec7968a7 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -7,7 +7,7 @@ published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - 2002-2022 Nicola Asuni - Tecnick.com LTD + 2002-2024 Nicola Asuni - Tecnick.com LTD ********************************************************************** ********************************************************************** diff --git a/README.md b/README.md index cf843227..f59f6633 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,14 @@ * **category** Library * **author** Nicola Asuni -* **copyright** 2002-2022 Nicola Asuni - Tecnick.com LTD +* **copyright** 2002-2024 Nicola Asuni - Tecnick.com LTD * **license** http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT) * **link** http://www.tcpdf.org * **source** https://github.com/tecnickcom/TCPDF -## IMPORTANT -A new version of this library is under development at https://github.com/tecnickcom/tc-lib-pdf and as a consequence this version will not receive any additional development or support. -This version should be considered obsolete, new projects should use the new version as soon it will become stable. +## NOTE +A new version of this library is under development at https://github.com/tecnickcom/tc-lib-pdf and as a consequence this library is in support only mode. diff --git a/VERSION b/VERSION index 28179fc1..29310f45 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.6.2 +6.7.4 diff --git a/config/tcpdf_config.php b/config/tcpdf_config.php index 92317b12..9888a677 100644 --- a/config/tcpdf_config.php +++ b/config/tcpdf_config.php @@ -212,6 +212,14 @@ */ define('K_TCPDF_CALLS_IN_HTML', false); +/** + * List of TCPDF methods that are allowed to be called using HTML syntax. + * Note: each method name must end with surrounded with | (pipe) character. + * The constant K_TCPDF_CALLS_IN_HTML must be set to true. + * IMPORTANT: For security reason, disable this feature if you are allowing user HTML content. + */ +define('K_ALLOWED_TCPDF_TAGS', ''); + /** * If true and PHP version is greater than 5, then the Error() method throw new exception instead of terminating the execution. */ diff --git a/examples/config/tcpdf_config_alt.php b/examples/config/tcpdf_config_alt.php index d61b1ba7..ef15ab27 100644 --- a/examples/config/tcpdf_config_alt.php +++ b/examples/config/tcpdf_config_alt.php @@ -212,6 +212,14 @@ */ define('K_TCPDF_CALLS_IN_HTML', true); +/** + * List of TCPDF methods that are allowed to be called using HTML syntax. + * Note: each method name must end with surrounded with | (pipe) character. + * The constant K_TCPDF_CALLS_IN_HTML must be set to true. + * IMPORTANT: For security reason, disable this feature if you are allowing user HTML content. + */ +define('K_ALLOWED_TCPDF_TAGS', '|AddPage|Rect|SetDrawColor|write1DBarcode|'); + /** * If true and PHP version is greater than 5, then the Error() method throw new exception instead of terminating the execution. */ diff --git a/examples/example_049.php b/examples/example_049.php index d2a46ada..5ebefc66 100644 --- a/examples/example_049.php +++ b/examples/example_049.php @@ -2,7 +2,7 @@ //============================================================+ // File name : example_049.php // Begin : 2009-04-03 -// Last Update : 2014-12-10 +// Last Update : 2024-03-18 // // Description : Example 049 for TCPDF class // WriteHTML with TCPDF callback functions @@ -78,11 +78,11 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * IMPORTANT: -If you are printing user-generated content, tcpdf tag can be unsafe. -You can disable this tag by setting to false the K_TCPDF_CALLS_IN_HTML -constant on TCPDF configuration file. +If you are printing user-generated content, the tcpdf tag should be considered unsafe. +This tag is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file. +Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code. -For security reasons, the parameters for the 'params' attribute of TCPDF +For security reasons, the parameters for the 'params' attribute of TCPDF tag must be prepared as an array and encoded with the serializeTCPDFtagParameters() method (see the example below). @@ -91,23 +91,25 @@ $html = '

Test TCPDF Methods in HTML

IMPORTANT:

-If you are using user-generated content, the tcpdf tag can be unsafe.
-You can disable this tag by setting to false the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file.
+If you are using user-generated content, the tcpdf tag should be considered unsafe.
+Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.
+This feature is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file.

write1DBarcode method in HTML

'; -$params = $pdf->serializeTCPDFtagParameters(array('CODE 39', 'C39', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N')); -$html .= ''; +$data = $pdf->serializeTCPDFtag('write1DBarcode', array('CODE 39', 'C39', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N')); +$html .= ''; -$params = $pdf->serializeTCPDFtagParameters(array('CODE 128', 'C128', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N')); -$html .= ''; +$data = $pdf->serializeTCPDFtag('write1DBarcode', array('CODE 128', 'C128', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N')); +$html .= ''; -$html .= '

Graphic Functions

'; +$data = $pdf->serializeTCPDFtag('AddPage'); +$html .= '

Graphic Functions

'; -$params = $pdf->serializeTCPDFtagParameters(array(0)); -$html .= ''; +$data = $pdf->serializeTCPDFtag('SetDrawColor', array(0)); +$html .= ''; -$params = $pdf->serializeTCPDFtagParameters(array(50, 50, 40, 10, 'DF', array(), array(0,128,255))); -$html .= ''; +$data = $pdf->serializeTCPDFtag('Rect', array(50, 50, 40, 10, 'DF', array(), array(0,128,255))); +$html .= ''; // output the HTML content diff --git a/examples/example_066.php b/examples/example_066.php index c7304c7a..41b8b472 100644 --- a/examples/example_066.php +++ b/examples/example_066.php @@ -18,8 +18,8 @@ * @group pdf */ -// Load the autoloader, move one folder back from examples -require_once __DIR__ . '/../vendor/autoload.php'; +// Include the main TCPDF library (search for installation path). +require_once('tcpdf_include.php'); // create new PDF document $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false, true); diff --git a/include/barcodes/qrcode.php b/include/barcodes/qrcode.php index 322cace3..1a64a4cb 100644 --- a/include/barcodes/qrcode.php +++ b/include/barcodes/qrcode.php @@ -888,6 +888,7 @@ protected function getCode() { if ($col >= $this->rsblocks[0]['dataLength']) { $row += $this->b1; } + $row = (int) $row; $ret = $this->rsblocks[$row]['data'][$col]; } elseif ($this->count < $this->dataLength + $this->eccLength) { $row = ($this->count - $this->dataLength) % $this->blocks; diff --git a/include/tcpdf_fonts.php b/include/tcpdf_fonts.php index 30053d3e..a71c84b7 100644 --- a/include/tcpdf_fonts.php +++ b/include/tcpdf_fonts.php @@ -1323,43 +1323,43 @@ public static function _getTrueTypeFontSubset($font, $subsetchars) { // set the checkSumAdjustment to 0 $table[$tag]['data'] = substr($table[$tag]['data'], 0, 8)."\x0\x0\x0\x0".substr($table[$tag]['data'], 12); } - $pad = 4 - ($table[$tag]['length'] % 4); - if ($pad != 4) { - // the length of a table must be a multiple of four bytes - $table[$tag]['length'] += $pad; - $table[$tag]['data'] .= str_repeat("\x0", $pad); - } $table[$tag]['offset'] = $offset; $offset += $table[$tag]['length']; + $numPad = ($offset + 3 & ~3) - $offset; + if($numPad > 0) { + $table[$tag]['data'] .= str_repeat("\x0", $numPad); + $offset += $numPad; + } // check sum is not changed (so keep the following line commented) - //$table[$tag]['checkSum'] = self::_getTTFtableChecksum($table[$tag]['data'], $table[$tag]['length']); + //$table[$tag]['checkSum'] = self::_getTTFtableChecksum($table[$tag]['data'], $table[$tag]['length'] + $numPad); } else { unset($table[$tag]); } } // add loca + $table['loca'] = array(); $table['loca']['data'] = $loca; $table['loca']['length'] = strlen($loca); - $pad = 4 - ($table['loca']['length'] % 4); - if ($pad != 4) { - // the length of a table must be a multiple of four bytes - $table['loca']['length'] += $pad; - $table['loca']['data'] .= str_repeat("\x0", $pad); - } $table['loca']['offset'] = $offset; - $table['loca']['checkSum'] = self::_getTTFtableChecksum($table['loca']['data'], $table['loca']['length']); $offset += $table['loca']['length']; + $numPad = ($offset + 3 & ~3) - $offset; + if($numPad > 0) { + $table['loca']['data'] .= str_repeat("\x0", $numPad); + $offset += $numPad; + } + $table['loca']['checkSum'] = self::_getTTFtableChecksum($table['loca']['data'], $table['loca']['length'] + $numPad); // add glyf + $table['glyf'] = array(); $table['glyf']['data'] = $glyf; $table['glyf']['length'] = strlen($glyf); - $pad = 4 - ($table['glyf']['length'] % 4); - if ($pad != 4) { - // the length of a table must be a multiple of four bytes - $table['glyf']['length'] += $pad; - $table['glyf']['data'] .= str_repeat("\x0", $pad); - } $table['glyf']['offset'] = $offset; - $table['glyf']['checkSum'] = self::_getTTFtableChecksum($table['glyf']['data'], $table['glyf']['length']); + $offset += $table['glyf']['length']; + $numPad = ($offset + 3 & ~3) - $offset; + if($numPad > 0) { + $table['glyf']['data'] .= str_repeat("\x0", $numPad); + $offset += $numPad; + } + $table['glyf']['checkSum'] = self::_getTTFtableChecksum($table['glyf']['data'], $table['glyf']['length'] + $numPad); // rebuild font $font = ''; $font .= pack('N', 0x10000); // sfnt version @@ -1383,7 +1383,7 @@ public static function _getTrueTypeFontSubset($font, $subsetchars) { } // set checkSumAdjustment on head table $checkSumAdjustment = 0xB1B0AFBA - self::_getTTFtableChecksum($font, strlen($font)); - $font = substr($font, 0, $table['head']['offset'] + 8).pack('N', $checkSumAdjustment).substr($font, $table['head']['offset'] + 12); + $font = substr($font, 0, $table['head']['offset'] + $offset + 8).pack('N', $checkSumAdjustment).substr($font, $table['head']['offset'] + $offset + 12); return $font; } @@ -1780,9 +1780,9 @@ public static function arrUTF8ToUTF16BE($unicode, $setbom=false) { */ public static function UTF8ArrayToUniArray($ta, $isunicode=true) { if ($isunicode) { - return array_map(array('TCPDF_FONTS', 'unichrUnicode'), $ta); + return array_map(get_called_class().'::unichrUnicode', $ta); } - return array_map(array('TCPDF_FONTS', 'unichrASCII'), $ta); + return array_map(get_called_class().'::unichrASCII', $ta); } /** @@ -2002,7 +2002,7 @@ public static function UTF8StringToArray($str, $isunicode, &$currentfont) { if ($isunicode) { // requires PCRE unicode support turned on $chars = TCPDF_STATIC::pregSplit('//','u', $str, -1, PREG_SPLIT_NO_EMPTY); - $carr = array_map(array('TCPDF_FONTS', 'uniord'), $chars); + $carr = array_map(get_called_class().'::uniord', $chars); } else { $chars = str_split($str); $carr = array_map('ord', $chars); diff --git a/include/tcpdf_static.php b/include/tcpdf_static.php index 57006552..1fb3c787 100644 --- a/include/tcpdf_static.php +++ b/include/tcpdf_static.php @@ -3,11 +3,11 @@ // File name : tcpdf_static.php // Version : 1.1.4 // Begin : 2002-08-03 -// Last Update : 2022-08-12 +// Last Update : 2023-09-06 // Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) // ------------------------------------------------------------------- -// Copyright (C) 2002-2022 Nicola Asuni - Tecnick.com LTD +// Copyright (C) 2002-2023 Nicola Asuni - Tecnick.com LTD // // This file is part of TCPDF software library. // @@ -55,7 +55,7 @@ class TCPDF_STATIC { * Current TCPDF version. * @private static */ - private static $tcpdf_version = '6.6.2'; + private static $tcpdf_version = '6.7.4'; /** * String alias for total number of pages. @@ -1780,7 +1780,7 @@ public static function pregSplit($pattern, $modifiers, $subject, $limit=NULL, $f if ($ret === false) { return array(); } - return $ret; + return is_array($ret) ? $ret : array(); } // preg_split is bugged - try alternative solution $ret = array(); @@ -2124,7 +2124,7 @@ public static function _freadint($f) { * Array of page formats * measures are calculated in this way: (inches * 72) or (millimeters * 72 / 25.4) * @public static - * + * * @var array */ public static $page_formats = array( diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a5e7a433..3f7bb1bd 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -4,8 +4,6 @@ parameters: - ./ excludePaths: - vendor/ - # remove once https://github.com/phpstan/phpstan/issues/7955 is fixed - - fonts/ - tests/ scanFiles: diff --git a/tcpdf.php b/tcpdf.php index 667b004f..7f5bbfb8 100644 --- a/tcpdf.php +++ b/tcpdf.php @@ -1,13 +1,13 @@ * @package com.tecnick.tcpdf * @author Nicola Asuni - * @version 6.6.2 + * @version 6.6.5 */ // TCPDF configuration @@ -128,7 +128,7 @@ * TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.
* @package com.tecnick.tcpdf * @brief PHP class for generating PDF documents without requiring external extensions. - * @version 6.6.2 + * @version 6.7.4 * @author Nicola Asuni - info@tecnick.com * @IgnoreAnnotation("protected") * @IgnoreAnnotation("public") @@ -574,12 +574,14 @@ class TCPDF { /** * Minimum distance between header and top page margin. * @protected + * @var float */ protected $header_margin; /** * Minimum distance between footer and bottom page margin. * @protected + * @var float */ protected $footer_margin; @@ -836,6 +838,13 @@ class TCPDF { */ protected $file_id; + /** + * Internal secret used to encrypt data. + * @protected + * @since 6.7.4 (2024-03-21) + */ + protected $hash_key; + // --- bookmark --- /** @@ -1878,10 +1887,10 @@ public function __construct($orientation='P', $unit='mm', $format='A4', $unicode // set file ID for trailer $serformat = (is_array($format) ? json_encode($format) : $format); $this->file_id = md5(TCPDF_STATIC::getRandomSeed('TCPDF'.$orientation.$unit.$serformat.$encoding)); + $this->hash_key = hash_hmac('sha256', TCPDF_STATIC::getRandomSeed($this->file_id), TCPDF_STATIC::getRandomSeed('TCPDF'), false); $this->font_obj_ids = array(); $this->page_obj_id = array(); $this->form_obj_id = array(); - // set pdf/a mode if ($pdfa != false) { $this->pdfa_mode = true; @@ -2461,7 +2470,7 @@ public function setLastH($h) { */ public function getCellHeight($fontsize, $padding=TRUE) { $height = ($fontsize * $this->cell_height_ratio); - if ($padding) { + if ($padding && !empty($this->cell_padding)) { $height += ($this->cell_padding['T'] + $this->cell_padding['B']); } return round($height, 6); @@ -3372,7 +3381,7 @@ public function getHeaderData() { /** * Set header margin. * (minimum distance between header and top page margin) - * @param int $hm distance in user units + * @param float $hm distance in user units * @public */ public function setHeaderMargin($hm=10) { @@ -3392,7 +3401,7 @@ public function getHeaderMargin() { /** * Set footer margin. * (minimum distance between footer and bottom page margin) - * @param int $fm distance in user units + * @param float $fm distance in user units * @public */ public function setFooterMargin($fm=10) { @@ -4102,6 +4111,7 @@ public function setTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, * @param float $fontsize Font size in points. The default value is the current size. * @param boolean $getarray if true returns an array of characters widths, if false returns the total length. * @return float[]|float total string length or array of characted widths + * @phpstan-return ($getarray is true ? float[] : float) total string length or array of characted widths * @author Nicola Asuni * @public * @since 1.2 @@ -4118,6 +4128,7 @@ public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $ge * @param float $fontsize Font size in points. The default value is the current size. * @param boolean $getarray if true returns an array of characters widths, if false returns the total length. * @return float[]|float total string length or array of characted widths + * @phpstan-return ($getarray is true ? float[] : float) total string length or array of characted widths * @author Nicola Asuni * @public * @since 2.4.000 (2008-03-06) @@ -4423,7 +4434,7 @@ public function AddFont($family, $style='', $fontfile='', $subset='default') { $this->Error('Unknow font type: '.$type.''); } // set name if unset - if (!isset($name) OR empty($name)) { + if (empty($name)) { $name = $fontkey; } // create artificial font style variations if missing (only works with non-embedded fonts) @@ -4466,7 +4477,7 @@ public function AddFont($family, $style='', $fontfile='', $subset='default') { // we are inside an XObject template $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $this->numfonts; } - if (isset($diff) AND (!empty($diff))) { + if (!empty($diff)) { //Search existing encodings $d = 0; $nb = count($this->diffs); @@ -6409,7 +6420,7 @@ public function Write($h, $txt, $link='', $fill=false, $align='', $ln=false, $st // calculate maximum width for a single character on string $chrw = $this->GetArrStringWidth($chars, '', '', 0, true); array_walk($chrw, array($this, 'getRawCharWidth')); - $maxchwidth = max($chrw); + $maxchwidth = ((is_array($chrw) || $chrw instanceof Countable) && count($chrw) > 0) ? max($chrw) : 0; // get array of chars $uchars = TCPDF_FONTS::UTF8ArrayToUniArray($chars, $this->isunicode); // get the number of characters @@ -6872,6 +6883,8 @@ protected function fitBlock($w, $h, $x, $y, $fitonpage=false) { } // resize the block to be contained on the remaining available page or column space if ($fitonpage) { + // fallback to avoid division by zero + $h = $h == 0 ? 1 : $h; $ratio_wh = ($w / $h); if (($y + $h) > $this->PageBreakTrigger) { $h = $this->PageBreakTrigger - $y; @@ -9925,7 +9938,7 @@ protected function _putcatalog() { } $out .= ' >> >>'; } - $font = $this->getFontBuffer('helvetica'); + $font = $this->getFontBuffer((($this->pdfa_mode) ? 'pdfa' : '') .'helvetica'); $out .= ' /DA (/F'.$font['i'].' 0 Tf 0 g)'; $out .= ' /Q '.(($this->rtl)?'2':'0'); //$out .= ' /XFA '; @@ -16383,6 +16396,53 @@ public function getHTMLFontUnits($val, $refsize=12, $parent_size=12, $defaultuni * @since 3.2.000 (2008-06-20) */ protected function getHtmlDomArray($html) { + // set inheritable properties fot the first void element + // possible inheritable properties are: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, empty-cells, font, font-family, font-stretch, font-size, font-size-adjust, font-style, font-variant, font-weight, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, orphans, page, page-break-inside, quotes, speak, speak-header, text-align, text-indent, text-transform, volume, white-space, widows, word-spacing + $dom = array( + array( + 'tag' => false, + 'block' => false, + 'value' => '', + 'parent' => 0, + 'hide' => false, + 'fontname' => $this->FontFamily, + 'fontstyle' => $this->FontStyle, + 'fontsize' => $this->FontSizePt, + 'font-stretch' => $this->font_stretching, + 'letter-spacing' => $this->font_spacing, + 'stroke' => $this->textstrokewidth, + 'fill' => (($this->textrendermode % 2) == 0), + 'clip' => ($this->textrendermode > 3), + 'line-height' => $this->cell_height_ratio, + 'bgcolor' => false, + 'fgcolor' => $this->fgcolor, // color + 'strokecolor' => $this->strokecolor, + 'align' => '', + 'listtype' => '', + 'text-indent' => 0, + 'text-transform' => '', + 'border' => array(), + 'dir' => $this->rtl?'rtl':'ltr', + 'width' => 0, + 'height' => 0, + 'x' => 0, + 'y' => 0, + 'w' => 0, + 'h' => 0, + 'l' => 0, + 't' => 0, + 'r' => 0, + 'b' => 0, + 'padding' => array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0), + 'margin' => array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0), + 'border-spacing' => array('H' => 0, 'V' => 0), + 'border-collapse' => 'separate', + ) + ); + + if(empty($html)) { + return $dom; + } // array of CSS styles ( selector => properties). $css = array(); // get CSS array defined at previous call @@ -16527,37 +16587,8 @@ protected function getHtmlDomArray($html) { // count elements $maxel = count($a); $elkey = 0; - $key = 0; - // create an array of elements - $dom = array(); - $dom[$key] = array(); - // set inheritable properties fot the first void element - // possible inheritable properties are: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, empty-cells, font, font-family, font-stretch, font-size, font-size-adjust, font-style, font-variant, font-weight, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, orphans, page, page-break-inside, quotes, speak, speak-header, text-align, text-indent, text-transform, volume, white-space, widows, word-spacing - $dom[$key]['tag'] = false; - $dom[$key]['block'] = false; - $dom[$key]['value'] = ''; - $dom[$key]['parent'] = 0; - $dom[$key]['hide'] = false; - $dom[$key]['fontname'] = $this->FontFamily; - $dom[$key]['fontstyle'] = $this->FontStyle; - $dom[$key]['fontsize'] = $this->FontSizePt; - $dom[$key]['font-stretch'] = $this->font_stretching; - $dom[$key]['letter-spacing'] = $this->font_spacing; - $dom[$key]['stroke'] = $this->textstrokewidth; - $dom[$key]['fill'] = (($this->textrendermode % 2) == 0); - $dom[$key]['clip'] = ($this->textrendermode > 3); - $dom[$key]['line-height'] = $this->cell_height_ratio; - $dom[$key]['bgcolor'] = false; - $dom[$key]['fgcolor'] = $this->fgcolor; // color - $dom[$key]['strokecolor'] = $this->strokecolor; - $dom[$key]['align'] = ''; - $dom[$key]['listtype'] = ''; - $dom[$key]['text-indent'] = 0; - $dom[$key]['text-transform'] = ''; - $dom[$key]['border'] = array(); - $dom[$key]['dir'] = $this->rtl?'rtl':'ltr'; $thead = false; // true when we are inside the THEAD tag - ++$key; + $key = 1; $level = array(); array_push($level, 0); // root while ($elkey < $maxel) { @@ -17194,41 +17225,59 @@ protected function getSpaceString() { } /** - * Return an hash code used to ensure that the serialized data has been generated by this TCPDF instance. - * @param string $data serialized data - * @return string - * @public static + * Calculates the hash value of the given data. + * + * @param string $data The data to be hashed. + * @return string The hashed value of the data. */ - protected function getHashForTCPDFtagParams($data) { - return md5(strlen($data).$this->file_id.$data); + protected function hashTCPDFtag($data) { + return hash_hmac('sha256', $data, $this->hash_key, false); } /** - * Serialize an array of parameters to be used with TCPDF tag in HTML code. - * @param array $data parameters array - * @return string containing serialized data + * Serialize data to be used with TCPDF tag in HTML code. + * @param string $method TCPDF method name + * @param array $params Method parameters + * @return string Serialized data * @public static */ - public function serializeTCPDFtagParameters($data) { + public function serializeTCPDFtag($method, $params=array()) { + $data = array('m' => $method, 'p' => $params); $encoded = urlencode(json_encode($data)); - return $this->getHashForTCPDFtagParams($encoded).$encoded; + $hash = $this->hashTCPDFtag($encoded); + return strlen($hash).'+'.$hash.'+'.$encoded; } /** - * Unserialize parameters to be used with TCPDF tag in HTML code. + * Unserialize data to be used with TCPDF tag in HTML code. * @param string $data serialized data * @return array containing unserialized data * @protected static */ - protected function unserializeTCPDFtagParameters($data) { - $hash = substr($data, 0, 32); - $encoded = substr($data, 32); - if ($hash != $this->getHashForTCPDFtagParams($encoded)) { + protected function unserializeTCPDFtag($data) { + $hpos = strpos($data, '+'); + $hlen = intval(substr($data, 0, $hpos)); + $hash = substr($data, $hpos + 1, $hlen); + $encoded = substr($data, $hpos + 2 + $hlen); + if ($hash != $this->hashTCPDFtag($encoded)) { $this->Error('Invalid parameters'); } return json_decode(urldecode($encoded), true); } + /** + * Check if a TCPDF tag is allowed + * @param string $method TCPDF method name + * @return boolean + * @protected + */ + protected function allowedTCPDFtag($method) { + if (defined('K_ALLOWED_TCPDF_TAGS')) { + return (strpos(K_ALLOWED_TCPDF_TAGS, '|'.$method.'|') !== false); + } + return false; + } + /** * Prints a cell (rectangular area) with optional borders, background color and html text string. * The upper-left corner of the cell corresponds to the current position. After the call, the current position moves to the right or to the next line.
@@ -17242,8 +17291,7 @@ protected function unserializeTCPDFtagParameters($data) { * @param float|null $y upper-left corner Y coordinate * @param string $html html text to print. Default value: empty string. * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
  • 0: no border (default)
  • 1: frame
or a string containing some or all of the following characters (in any order):
  • L: left
  • T: top
  • R: right
  • B: bottom
or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param int $ln Indicates where the current position should go after the call. Possible values are:
  • 0: to the right (or left for RTL language)
  • 1: to the beginning of the next line
  • 2: below
-Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. + * @param int $ln Indicates where the current position should go after the call. Possible values are:
  • 0: to the right (or left for RTL language)
  • 1: to the beginning of the next line
  • 2: below
Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). * @param boolean $reseth if true reset the last cell height (default true). * @param string $align Allows to center or align the text. Possible values are:
  • L : left align
  • C : center
  • R : right align
  • '' : empty string : left for LTR or right for RTL
@@ -19504,17 +19552,14 @@ protected function openHTMLTagHandler($dom, $key, $cell) { case 'tcpdf': { if (defined('K_TCPDF_CALLS_IN_HTML') AND (K_TCPDF_CALLS_IN_HTML === true)) { // Special tag used to call TCPDF methods - if (isset($tag['attribute']['method'])) { - $tcpdf_method = $tag['attribute']['method']; - if (method_exists($this, $tcpdf_method)) { - if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) { - $params = $this->unserializeTCPDFtagParameters($tag['attribute']['params']); - call_user_func_array(array($this, $tcpdf_method), $params); - } else { - $this->$tcpdf_method(); - } - $this->newline = true; + // This tag is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file. + // Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code. + if (!empty($tag['attribute']['data'])) { + $tcpdf_tag_data = $this->unserializeTCPDFtag($tag['attribute']['data']); + if ($this->allowedTCPDFtag($tcpdf_tag_data['m'])) { + call_user_func_array(array($this, $tcpdf_tag_data['m']), $tcpdf_tag_data['p']); } + $this->newline = true; } } break; @@ -21861,25 +21906,23 @@ public function commitTransaction() { * @since 4.5.029 (2009-03-19) */ public function rollbackTransaction($self=false) { - if (isset($this->objcopy)) { - $objcopy = $this->objcopy; - $this->_destroy(true, true); - if ($self) { - $objvars = get_object_vars($objcopy); - foreach ($objvars as $key => $value) { - $this->$key = $value; - } - $objcopy->_destroy(true, true); - /* The unique file_id should not be used during cleanup again */ - $objcopy->file_id = NULL; - unset($objcopy); - return $this; + if (!isset($this->objcopy)) { + return $this; + } + $file_id = $this->file_id; + $objcopy = $this->objcopy; + $this->_destroy(true, true); + if ($self) { + $objvars = get_object_vars($objcopy); + foreach ($objvars as $key => $value) { + $this->$key = $value; } - /* The unique file_id should not be used during cleanup again */ - $this->file_id = NULL; - return $objcopy; + $objcopy->_destroy(true, true); + unset($objcopy); + return $this; } - return $this; + $this->file_id = $file_id; + return $objcopy; } // --- MULTI COLUMNS METHODS ----------------------- @@ -22055,7 +22098,7 @@ public function getNumberOfColumns() { public function setTextRenderingMode($stroke=0, $fill=true, $clip=false) { // Ref.: PDF 32000-1:2008 - 9.3.6 Text Rendering Mode // convert text rendering parameters - if ($stroke < 0) { + if ($stroke < 0 || !is_numeric($stroke)) { $stroke = 0; } if ($fill === true) { diff --git a/tcpdf_autoconfig.php b/tcpdf_autoconfig.php index 6ec9ce83..2bcfccb8 100644 --- a/tcpdf_autoconfig.php +++ b/tcpdf_autoconfig.php @@ -228,6 +228,10 @@ define('K_TCPDF_CALLS_IN_HTML', false); } +if (!defined('K_ALLOWED_TCPDF_TAGS')) { + define('K_ALLOWED_TCPDF_TAGS', ''); +} + if (!defined('K_TCPDF_THROW_EXCEPTION_ERROR')) { define('K_TCPDF_THROW_EXCEPTION_ERROR', false); } diff --git a/tcpdf_barcodes_1d.php b/tcpdf_barcodes_1d.php index 10a79a72..45d35616 100644 --- a/tcpdf_barcodes_1d.php +++ b/tcpdf_barcodes_1d.php @@ -828,7 +828,7 @@ protected function barcode_s25($code, $checksum=false) { $chr['5'] = '11101011101010'; $chr['6'] = '10111011101010'; $chr['7'] = '10101011101110'; - $chr['8'] = '10101110111010'; + $chr['8'] = '11101010111010'; $chr['9'] = '10111010111010'; if ($checksum) { // add checksum @@ -838,7 +838,7 @@ protected function barcode_s25($code, $checksum=false) { // add leading zero if code-length is odd $code = '0'.$code; } - $seq = '11011010'; + $seq = '1110111010'; $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { $digit = $code[$i]; @@ -848,7 +848,7 @@ protected function barcode_s25($code, $checksum=false) { } $seq .= $chr[$digit]; } - $seq .= '1101011'; + $seq .= '111010111'; $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); return $this->binseq_to_array($seq, $bararray); } diff --git a/tests/composer.json b/tests/composer.json index 065fcbeb..3edd4a90 100644 --- a/tests/composer.json +++ b/tests/composer.json @@ -2,13 +2,8 @@ "name": "tecnickcom/tcpdf-tests", "type": "metapackage", "description": "Dependencies for the test suite", - "keywords": [ - "PDF", - "tcpdf", - "test" - ], "homepage": "http://www.tcpdf.org/", - "license": "LGPL-3.0-only", + "license": "LGPL-3.0-or-later", "authors": [ { "name": "Philippe Jausions", @@ -18,7 +13,7 @@ ], "require": { "PHP": ">=5.3.0", - "cs278/mktemp": "*" + "cs278/mktemp": "^1.2.0" }, "suggest": { "rosell-dk/locate-binaries": "Allows to detect executables such as pdfinfo" @@ -27,10 +22,5 @@ "psr-4": { "Tecnickcom\\TCPDF\\Tests\\": "src/" } - }, - "archive": { - "exclude": [ - "/examples" - ] } }