From dad9e915a03aed98772698fd76ac4faa5e78589f Mon Sep 17 00:00:00 2001 From: Nicola Asuni Date: Sat, 26 Oct 2024 10:29:48 +0100 Subject: [PATCH] Multiple PRs (#755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update tcpdf.php Since the version 6.7.4, the "0" is considered like empty string and not displayed * Update tcpdf.php Co-authored-by: William Desportes * Fixed handling of transparency in PDF/A mode in addExtGState method The condition allowed to add ExtGState in all PDF/A modes and disallowed in default mode. This fix inlines the condition with setExtGState to allow transparency parameters for non-PDF/A and PDF/A > 1 documents. The state condition is copied from 'setExtGState'. * Encrypt /DA string when document is encrypted When document is encrypted then /DA string must be encrypted, without this Acrobat cannot allow fill form fields. * Improve quality of generated seed, avoid potential security pitfall * Try to use random_bytes() first if it's available * Do not include the server parameters in the generated seed, as they might contain sensitive data As all current usages of getRandomSeed() directly hash the seed, there should be no BC breaking changes. The main source of entropy is more than enough on its own if random_bytes() or openssl_random_pseudo_bytes() are available. * Fix bug on _getannotsrefs when there are empty signature appearances but not other annot on a page * Fix SVG coordinate parser that caused drawing artifacts * Remove usage of xml_set_object() function The xml_set_object() function will be deprecated in PHP 8.4 as well as passing non-callable strings to the xml_set_*_handler() functions. Instead of using xml_set_object(), the string method names in xml_set_element_handler() and xml_set_character_data_handler() should be replaced with callables. - https://wiki.php.net/rfc/deprecations_php_8_4#xml_set_object_and_xml_set_handler_with_string_method_names Signed-off-by: Maurício Meneghini Fauth --------- Signed-off-by: Maurício Meneghini Fauth Co-authored-by: jlouche <61839660+jlouche@users.noreply.github.com> Co-authored-by: William Desportes Co-authored-by: stollr Co-authored-by: Robert Jędrzejczyk Co-authored-by: Andreas Erhard Co-authored-by: Alejandro Precioso Co-authored-by: davidrod Co-authored-by: sslldavid <119080321+sslldavid@users.noreply.github.com> Co-authored-by: Alejandro Co-authored-by: Maurício Meneghini Fauth --- include/tcpdf_static.php | 7 +++++-- tcpdf.php | 27 +++++++++++++-------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/tcpdf_static.php b/include/tcpdf_static.php index b4f7c5f4..4cee355e 100644 --- a/include/tcpdf_static.php +++ b/include/tcpdf_static.php @@ -379,7 +379,10 @@ public static function getRandomSeed($seed='') { if (function_exists('posix_getpid')) { $rnd .= posix_getpid(); } - if (function_exists('openssl_random_pseudo_bytes') AND (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { + + if (function_exists('random_bytes')) { + $rnd .= random_bytes(512); + } elseif (function_exists('openssl_random_pseudo_bytes') AND (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // this is not used on windows systems because it is very slow for a know bug $rnd .= openssl_random_pseudo_bytes(512); } else { @@ -387,7 +390,7 @@ public static function getRandomSeed($seed='') { $rnd .= uniqid('', true); } } - return $rnd.$seed.__FILE__.serialize($_SERVER).microtime(true); + return $rnd.$seed.__FILE__.microtime(true); } /** diff --git a/tcpdf.php b/tcpdf.php index 429f4a99..1abf622a 100644 --- a/tcpdf.php +++ b/tcpdf.php @@ -8164,7 +8164,7 @@ protected function _putpages() { * @since 5.0.010 (2010-05-17) */ protected function _getannotsrefs($n) { - if (!(isset($this->PageAnnots[$n]) OR ($this->sign AND isset($this->signature_data['cert_type'])))) { + if (!(isset($this->PageAnnots[$n]) OR count($this->empty_signature_appearance)>0 OR ($this->sign AND isset($this->signature_data['cert_type'])))) { return ''; } $out = ' /Annots ['; @@ -8532,7 +8532,7 @@ protected function _putannotsobjs() { } case 'freetext': { if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) { - $annots .= ' /DA ('.$pl['opt']['da'].')'; + $annots .= ' /DA '.$this->_datastring($pl['opt']['da']); } if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) { $annots .= ' /Q '.intval($pl['opt']['q']); @@ -8789,7 +8789,7 @@ protected function _putannotsobjs() { $annots .= ' /AA << '.$pl['opt']['aa'].' >>'; } if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) { - $annots .= ' /DA ('.$pl['opt']['da'].')'; + $annots .= ' /DA '.$this->_datastring($pl['opt']['da']); } if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) { $annots .= ' /Q '.intval($pl['opt']['q']); @@ -9939,7 +9939,7 @@ protected function _putcatalog() { $out .= ' >> >>'; } $font = $this->getFontBuffer((($this->pdfa_mode) ? 'pdfa' : '') .'helvetica'); - $out .= ' /DA (/F'.$font['i'].' 0 Tf 0 g)'; + $out .= ' /DA ' . $this->_datastring('/F'.$font['i'].' 0 Tf 0 g'); $out .= ' /Q '.(($this->rtl)?'2':'0'); //$out .= ' /XFA '; $out .= ' >>'; @@ -11046,7 +11046,7 @@ public function setProtection($permissions=array('print', 'modify', 'copy', 'ann $this->encryptdata['V'] = 4; $this->encryptdata['Length'] = 128; $this->encryptdata['CF']['CFM'] = 'AESV2'; - $this->encryptdata['CF']['Length'] = 128; + $this->encryptdata['CF']['Length'] = 16; if ($this->encryptdata['pubkey']) { $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5'; $this->encryptdata['Recipients'] = array(); @@ -11057,7 +11057,7 @@ public function setProtection($permissions=array('print', 'modify', 'copy', 'ann $this->encryptdata['V'] = 5; $this->encryptdata['Length'] = 256; $this->encryptdata['CF']['CFM'] = 'AESV3'; - $this->encryptdata['CF']['Length'] = 256; + $this->encryptdata['CF']['Length'] = 32; if ($this->encryptdata['pubkey']) { $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5'; $this->encryptdata['Recipients'] = array(); @@ -13936,8 +13936,8 @@ public function setVisibility($v) { * @since 3.0.000 (2008-03-27) */ protected function addExtGState($parms) { - if ($this->pdfa_mode || $this->pdfa_version >= 2) { - // transparencies are not allowed in PDF/A mode + if (($this->pdfa_mode && $this->pdfa_version < 2) || ($this->state != 2)) { + // transparency is not allowed in PDF/A-1 mode return; } // check if this ExtGState already exist @@ -16440,7 +16440,7 @@ protected function getHtmlDomArray($html) { ) ); - if(empty($html)) { + if($html === '' || $html === null) { return $dom; } // array of CSS styles ( selector => properties). @@ -23173,14 +23173,12 @@ public function ImageSVG($file, $x=null, $y=null, $w=0, $h=0, $link='', $align=' $this->_out(sprintf('%F %F %F %F %F %F cm', $svgscale_x, 0, 0, $svgscale_y, ($e + $svgoffset_x), ($f + $svgoffset_y))); // creates a new XML parser to be used by the other XML functions $parser = xml_parser_create('UTF-8'); - // the following function allows to use parser inside object - xml_set_object($parser, $this); // disable case-folding for this XML parser xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); // sets the element handler functions for the XML parser - xml_set_element_handler($parser, 'startSVGElementHandler', 'endSVGElementHandler'); + xml_set_element_handler($parser, [$this, 'startSVGElementHandler'], [$this, 'endSVGElementHandler']); // sets the character data handler function for the XML parser - xml_set_character_data_handler($parser, 'segSVGContentHandler'); + xml_set_character_data_handler($parser, [$this, 'segSVGContentHandler']); // start parsing an XML document if (!xml_parse($parser, $svgdata)) { $error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser)); @@ -23642,7 +23640,8 @@ protected function SVGPath($d, $style='') { $params = array(); if (isset($val[2])) { // get curve parameters - $rawparams = preg_split('/([\,\s]+)/si', trim($val[2])); + preg_match_all('/-?\d*\.?\d+/', trim($val[2]), $matches); + $rawparams = $matches[0]; $params = array(); foreach ($rawparams as $ck => $cp) { $params[$ck] = $this->getHTMLUnitToUnits($cp, 0, $this->svgunit, false);