From b6bc747425bd82065261bf03b5e43c25cf71120a Mon Sep 17 00:00:00 2001 From: Thomas Zilio Date: Wed, 13 Feb 2019 11:26:56 +0100 Subject: [PATCH 1/3] Miglioramento support P7M --- plugins/importFE/list.php | 5 ++ plugins/importFE/src/FatturaElettronica.php | 11 +++ src/Util/XML.php | 80 ++++++++++++++++++++- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/plugins/importFE/list.php b/plugins/importFE/list.php index 15e63d270..58d5be638 100644 --- a/plugins/importFE/list.php +++ b/plugins/importFE/list.php @@ -76,6 +76,11 @@ function download(button, file) { buttonRestore(button, restore); $(button).prop("disabled", true); } + }, + error: function(xhr) { + alert("'.tr('Errore').': " + xhr.responseJSON.error.message); + + buttonRestore(button, restore); } }); } diff --git a/plugins/importFE/src/FatturaElettronica.php b/plugins/importFE/src/FatturaElettronica.php index 33eba7fbf..30de1d221 100644 --- a/plugins/importFE/src/FatturaElettronica.php +++ b/plugins/importFE/src/FatturaElettronica.php @@ -37,6 +37,17 @@ class FatturaElettronica public function __construct($file) { $this->file = static::getImportDirectory().'/'.$file; + + if (ends_with($file, '.p7m')) { + $file = XML::decodeP7M($this->file); + + if ($file !== false) { + delete($this->file); + + $this->file = $file; + } + } + $this->xml = XML::readFile($this->file); // Individuazione fattura pre-esistente diff --git a/src/Util/XML.php b/src/Util/XML.php index b8b702ddb..4e116f406 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -39,13 +39,87 @@ class XML /** * Interpreta i contenuti di un file XML. * - * @param string $path + * @param string $file * * @return array */ - public static function readFile($path) + public static function readFile($file) { - return static::read(file_get_contents($path)); + return static::read(file_get_contents($file)); + } + + /** + * Interpreta i contenuti di un file XML. + * + * @param string $file + * + * @return string|bool + */ + public static function decodeP7M($file) + { + $content = file_get_contents($file); + + $base64 = base64_decode($content, true); + if ($base64 !== false) { + $content = $base64; + } + + file_put_contents($file, self::removeBOM($content)); + + $directory = pathinfo($file, PATHINFO_DIRNAME); + $final_file = $directory.'/'.basename($file, '.p7m'); + + exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$final_file.'"', $output, $cmd); + if ($cmd != 0) { + self::der2smime($file); + + $result = openssl_pkcs7_verify($file, PKCS7_NOVERIFY, '', [], '', $final_file); + + if ($result == -1) { + return false; + } + } + + return $final_file; + } + + /** + * Remove UTF8 BOM. + * + * @param $text + * + * @return string + * + * @source https://stackoverflow.com/questions/10290849/how-to-remove-multiple-utf-8-bom-sequences + */ + protected static function removeBOM($text) + { + $bom = pack('H*', 'EFBBBF'); + $text = preg_replace("/^$bom/", '', $text); + + return $text; + } + + /** + * @param $file + * + * @return bool|int + * + * @source http://php.net/manual/en/function.openssl-pkcs7-verify.php#123118 + */ + protected static function der2smime($file) + { + $to = << Date: Wed, 13 Feb 2019 12:04:36 +0100 Subject: [PATCH 2/3] Miglioramento controlli --- plugins/importFE/src/FatturaElettronica.php | 2 +- src/Util/XML.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/importFE/src/FatturaElettronica.php b/plugins/importFE/src/FatturaElettronica.php index 30de1d221..b03aeeec2 100644 --- a/plugins/importFE/src/FatturaElettronica.php +++ b/plugins/importFE/src/FatturaElettronica.php @@ -41,7 +41,7 @@ class FatturaElettronica if (ends_with($file, '.p7m')) { $file = XML::decodeP7M($this->file); - if ($file !== false) { + if (!empty($file)) { delete($this->file); $this->file = $file; diff --git a/src/Util/XML.php b/src/Util/XML.php index 4e116f406..ef38320d4 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -70,12 +70,12 @@ class XML $final_file = $directory.'/'.basename($file, '.p7m'); exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$final_file.'"', $output, $cmd); - if ($cmd != 0) { + if (!file_exists($final_file)) { self::der2smime($file); $result = openssl_pkcs7_verify($file, PKCS7_NOVERIFY, '', [], '', $final_file); - if ($result == -1) { + if ($result == -1 || $result === false) { return false; } } From 8dcc704676f53f39c41fa28c157821511effc9aa Mon Sep 17 00:00:00 2001 From: Thomas Zilio Date: Sat, 23 Mar 2019 17:43:42 +0100 Subject: [PATCH 3/3] Fix finali --- plugins/importFE/src/FatturaElettronica.php | 2 +- src/Util/XML.php | 112 ++++++-------------- 2 files changed, 31 insertions(+), 83 deletions(-) diff --git a/plugins/importFE/src/FatturaElettronica.php b/plugins/importFE/src/FatturaElettronica.php index 083bada1c..4297e82f7 100644 --- a/plugins/importFE/src/FatturaElettronica.php +++ b/plugins/importFE/src/FatturaElettronica.php @@ -38,7 +38,7 @@ class FatturaElettronica { $this->file = static::getImportDirectory().'/'.$name; - if (ends_with($file, '.p7m')) { + if (ends_with($name, '.p7m')) { $file = XML::decodeP7M($this->file); if (!empty($file)) { diff --git a/src/Util/XML.php b/src/Util/XML.php index ef38320d4..96897429d 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -20,7 +20,7 @@ class XML */ public static function read($string) { - $content = static::stripP7MData($string); + $content = $string; libxml_use_internal_errors(true); @@ -57,30 +57,50 @@ class XML */ public static function decodeP7M($file) { + $directory = pathinfo($file, PATHINFO_DIRNAME); $content = file_get_contents($file); - $base64 = base64_decode($content, true); + $base64 = base64_decode(base64_encode($content), true); if ($base64 !== false) { $content = $base64; } file_put_contents($file, self::removeBOM($content)); - $directory = pathinfo($file, PATHINFO_DIRNAME); - $final_file = $directory.'/'.basename($file, '.p7m'); + $output_file = $directory.'/'.basename($file, '.p7m'); + + exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$output_file.'"', $output, $cmd); + if (!file_exists($output_file)) { + $signer = $directory.'/signer'; + + self::decode($file, $output_file, $signer); - exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$final_file.'"', $output, $cmd); - if (!file_exists($final_file)) { self::der2smime($file); + self::decode($file, $output_file, $signer); - $result = openssl_pkcs7_verify($file, PKCS7_NOVERIFY, '', [], '', $final_file); - - if ($result == -1 || $result === false) { + if (!file_exists($output_file)) { return false; } } - return $final_file; + return $output_file; + } + + /** + * Decodifica il file utilizzando le funzioni native PHP. + * + * @param $file + * @param $output_file + * @param $signer + * + * @return mixed + */ + protected static function decode($file, $output_file, $signer) + { + openssl_pkcs7_verify($file, PKCS7_NOVERIFY | PKCS7_NOSIGS, $signer); + $result = openssl_pkcs7_verify($file, PKCS7_NOVERIFY | PKCS7_NOSIGS, $signer, [], $signer, $output_file); + + return $result; } /** @@ -121,76 +141,4 @@ TXT; return file_put_contents($file, $to); } - - /** - * Removes the PKCS#7 header and the signature info footer from a digitally-signed .xml.p7m file using CAdES format. - * - * TODO: controllare il funzionamento con gli allegati (https://forum.italia.it/t/in-produzione-xml-ricevuto-non-leggibile/5695/2). - * - * @param string $string File content - * - * @return string An arguably-valid XML string with the .p7m header and footer stripped away. - * - * @source https://www.ryadel.com/php-estrarre-contenuto-file-xml-p7m-cades-fattura-elettronica-pa/ - */ - protected static function stripP7MData($string) - { - // skip everything before the XML content - $string = substr($string, strpos($string, '/', $string, $matches, PREG_OFFSET_CAPTURE); - $lastMatch = end($matches[0]); - - $result = substr($string, 0, $lastMatch[1] + strlen($lastMatch[0]) + 1); - - return static::sanitizeXML($result); - } - - /** - * Removes invalid characters from a UTF-8 XML string. - * - * @param string a XML string potentially containing invalid characters - * - * @return string - * - * @source https://www.ryadel.com/php-eliminare-caratteri-non-validi-file-stringa-xml-utf8-utf-8/ - */ - protected static function sanitizeXML($string) - { - if (!empty($string)) { - $regex = '/( - [\xC0-\xC1] # Invalid UTF-8 Bytes - | [\xF5-\xFF] # Invalid UTF-8 Bytes - | \xE0[\x80-\x9F] # Overlong encoding of prior code point - | \xF0[\x80-\x8F] # Overlong encoding of prior code point - | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start - | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start - | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start - | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle - | (?= 0x20) && ($current <= 0xD7FF)) || - (($current >= 0xE000) && ($current <= 0xFFFD)) || - (($current >= 0x10000) && ($current <= 0x10FFFF))) { - $result .= chr($current); - } - } - $string = $result; - } - - return $string; - } }