All variables are now in snake case: API change.

This commit is contained in:
Franco Masotti 2022-01-14 23:45:47 +01:00
parent 1030f44ee3
commit 5649bee23e
Signed by: frnmst
GPG Key ID: 24116ED85666780A
3 changed files with 237 additions and 238 deletions

View File

@ -45,11 +45,10 @@ from .exceptions import (AssetsChecksumDoesNotMatch,
P7MFileDoesNotHaveACoherentCryptographicalSignature,
P7MFileNotAuthentic, XMLFileNotConformingToSchema)
#######
# API #
#######
def is_xml_file_conforming_to_schema(xml_file: str,
xml_schema_file: str) -> bool:
r"""Check that the XML file follows its schema.
@ -470,44 +469,44 @@ def write_configuration_file(configuration_file: str):
:raises: a configparser or a built-in exception.
"""
config = dict()
config['metadata file'] = {
'XML namespace':
const.XML['metadata file']['namespaces']['default'],
'XML invoice checksum tag':
const.XML['metadata file']['tags']['invoice checksum'],
'XML invoice filename tag':
const.XML['metadata file']['tags']['invoice filename'],
'XML system id tag':
const.XML['metadata file']['tags']['system id']
config['metadata_file'] = {
'xml_namespace':
const.xml['metadata_file']['namespaces']['default'],
'xml_invoice_checksum_tag':
const.xml['metadata_file']['tags']['invoice_checksum'],
'xml_invoice_filename_tag':
const.xml['metadata_file']['tags']['invoice_filename'],
'xml_system_id_tag':
const.xml['metadata_file']['tags']['system_id']
}
config['trusted list file'] = {
'XML namespace': const.XML['trusted list file']['namespaces']['default'],
'XML certificate tag': const.XML['trusted list file']['tags']['certificate'],
'download': const.Downloads['trusted list file']['default'],
config['trusted_list_file'] = {
'xml_namespace': const.xml['trusted_list_file']['namespaces']['default'],
'xml_certificate_tag': const.xml['trusted_list_file']['tags']['certificate'],
'download': const.downloads['trusted_list_file']['default'],
}
config['invoice file'] = {
'XML namespace':
const.XML['invoice file']['namespaces']['default'],
'XML attachment tag':
const.XML['invoice file']['tags']['attachment'],
'XML attachment filename tag':
const.XML['invoice file']['tags']['attachment filename'],
'XML attachment XPath':
const.XML['invoice file']['XPath']['attachment'],
'text encoding':
const.XML['invoice file']['proprieties']['text encoding'],
'XSD download':
const.Downloads['invoice file']['XSD']['default'],
'W3C XSD download':
const.Downloads['invoice file']['XSD']['W3C Schema for XML Signatures'],
'XSLT ordinaria download':
const.Downloads['invoice file']['XSLT']['ordinaria'],
'XSLT PA download':
const.Downloads['invoice file']['XSLT']['PA'],
'attachment extension whitelist':
const.File['invoice']['attachment']['extension whitelist'],
'attachment filetype whitelist':
const.File['invoice']['attachment']['filetype whitelist']
config['invoice_file'] = {
'xml_namespace':
const.xml['invoice_file']['namespaces']['default'],
'xml_attachment_tag':
const.xml['invoice_file']['tags']['attachment'],
'xml_attachment_filename_tag':
const.xml['invoice_file']['tags']['attachment_filename'],
'xml_attachment_xpath':
const.xml['invoice_file']['xpath']['attachment'],
'text_encoding':
const.xml['invoice_file']['proprieties']['text_encoding'],
'xsd_download':
const.downloads['invoice_file']['xsd']['default'],
'w3c_xsd_download':
const.downloads['invoice_file']['xsd']['w3c_schema_for_xml_signatures'],
'xslt_ordinaria_download':
const.downloads['invoice_file']['xslt']['ordinaria'],
'xslt_pa_download':
const.downloads['invoice_file']['xslt']['pa'],
'attachment_extension_whitelist':
const.file['invoice']['attachment']['extension_whitelist'],
'attachment_filetype_whitelist':
const.file['invoice']['attachment']['filetype_whitelist']
}
with open(configuration_file, 'w') as configfile:
@ -537,136 +536,136 @@ def assert_data_structure(source: str, file_type: str, data: dict):
if 'patched' not in data:
raise ValueError
if 'configuration file' not in data:
if 'configuration_file' not in data:
raise ValueError
if 'write default configuration file' not in data:
if 'write_default_configuration_file' not in data:
raise ValueError
if 'ignore assets checksum' not in data:
if 'ignore_assets_checksum' not in data:
raise ValueError
if not isinstance(data['patched'], bool):
raise TypeError
if not isinstance(data['configuration file'], str):
if not isinstance(data['configuration_file'], str):
raise TypeError
if not isinstance(data['write default configuration file'], bool):
if not isinstance(data['write_default_configuration_file'], bool):
raise TypeError
if not isinstance(data['ignore assets checksum'], bool):
if not isinstance(data['ignore_assets_checksum'], bool):
raise TypeError
if source == 'invoice':
if 'extract attachments' not in data:
if 'extract_attachments' not in data:
raise ValueError
if 'invoice xslt type' not in data:
if 'invoice_xslt_type' not in data:
raise ValueError
if 'no invoice xml validation' not in data:
if 'no_invoice_xml_validation' not in data:
raise ValueError
if 'force invoice schema file download' not in data:
if 'force_invoice_schema_file_download' not in data:
raise ValueError
if 'generate html output' not in data:
if 'generate_html_output' not in data:
raise ValueError
if 'invoice filename' not in data:
if 'invoice_filename' not in data:
raise ValueError
if 'no checksum check' not in data:
if 'no_checksum_check' not in data:
raise ValueError
if 'force invoice xml stylesheet file download' not in data:
if 'force_invoice_xml_stylesheet_file_download' not in data:
raise ValueError
if 'ignore attachment extension whitelist' not in data:
if 'ignore_attachment_extension_whitelist' not in data:
raise ValueError
if 'ignore attachment filetype whitelist' not in data:
if 'ignore_attachment_filetype_whitelist' not in data:
raise ValueError
if not isinstance(data['extract attachments'], bool):
if not isinstance(data['extract_attachments'], bool):
raise TypeError
if not isinstance(data['invoice xslt type'], str):
if not isinstance(data['invoice_xslt_type'], str):
raise TypeError
if not isinstance(data['no invoice xml validation'], bool):
if not isinstance(data['no_invoice_xml_validation'], bool):
raise TypeError
if not isinstance(data['force invoice schema file download'], bool):
if not isinstance(data['force_invoice_schema_file_download'], bool):
raise TypeError
if not isinstance(data['generate html output'], bool):
if not isinstance(data['generate_html_output'], bool):
raise TypeError
if not isinstance(data['invoice filename'], str):
if not isinstance(data['invoice_filename'], str):
raise TypeError
if not isinstance(data['no checksum check'], bool):
if not isinstance(data['no_checksum_check'], bool):
raise TypeError
if not isinstance(data['force invoice xml stylesheet file download'],
if not isinstance(data['force_invoice_xml_stylesheet_file_download'],
bool):
raise TypeError
if not isinstance(data['ignore attachment extension whitelist'], bool):
if not isinstance(data['ignore_attachment_extension_whitelist'], bool):
raise TypeError
if not isinstance(data['ignore attachment filetype whitelist'], bool):
if not isinstance(data['ignore_attachment_filetype_whitelist'], bool):
raise TypeError
if data['patched']:
if 'metadata file' not in data:
if 'metadata_file' not in data:
raise ValueError
if not isinstance(data['metadata file'], str):
if not isinstance(data['metadata_file'], str):
raise TypeError
else:
if 'metadata files' not in data:
if 'metadata_files' not in data:
raise ValueError
if not isinstance(data['metadata files'], list):
if not isinstance(data['metadata_files'], list):
raise TypeError
for m in data['metadata files']:
for m in data['metadata_files']:
if not isinstance(m, str):
raise TypeError
if file_type == 'p7m':
if 'ignore signature check' not in data:
if 'ignore_signature_check' not in data:
raise ValueError
if 'ignore signers certificate check' not in data:
if 'ignore_signers_certificate_check' not in data:
raise ValueError
if 'force trusted list file download' not in data:
if 'force_trusted_list_file_download' not in data:
raise ValueError
if 'keep original file' not in data:
if 'keep_original_file' not in data:
raise ValueError
if not isinstance(data['ignore signature check'], bool):
if not isinstance(data['ignore_signature_check'], bool):
raise TypeError
if not isinstance(data['ignore signers certificate check'], bool):
if not isinstance(data['ignore_signers_certificate_check'], bool):
raise TypeError
if not isinstance(data['force trusted list file download'], bool):
if not isinstance(data['force_trusted_list_file_download'], bool):
raise TypeError
if not isinstance(data['keep original file'], bool):
if not isinstance(data['keep_original_file'], bool):
raise TypeError
ok = True
elif file_type == 'plain':
ok = True
elif source == 'generic':
if file_type == 'p7m':
if 'ignore signature check' not in data:
if 'ignore_signature_check' not in data:
raise ValueError
if 'ignore signers certificate check' not in data:
if 'ignore_signers_certificate_check' not in data:
raise ValueError
if 'force trusted list file download' not in data:
if 'force_trusted_list_file_download' not in data:
raise ValueError
if 'keep original file' not in data:
if 'keep_original_file' not in data:
raise ValueError
if not isinstance(data['ignore signature check'], bool):
if not isinstance(data['ignore_signature_check'], bool):
raise TypeError
if not isinstance(data['ignore signers certificate check'], bool):
if not isinstance(data['ignore_signers_certificate_check'], bool):
raise TypeError
if not isinstance(data['force trusted list file download'], bool):
if not isinstance(data['force_trusted_list_file_download'], bool):
raise TypeError
if not isinstance(data['keep original file'], bool):
if not isinstance(data['keep_original_file'], bool):
raise TypeError
if data['patched']:
if 'p7m file' not in data:
if 'p7m_file' not in data:
raise ValueError
if not isinstance(data['p7m file'], str):
if not isinstance(data['p7m_file'], str):
raise TypeError
else:
if 'p7m files' not in data:
if 'p7m_files' not in data:
raise ValueError
if not isinstance(data['p7m files'], list):
if not isinstance(data['p7m_files'], list):
raise TypeError
for p in data['p7m files']:
for p in data['p7m_files']:
if not isinstance(p, str):
raise TypeError
ok = True
elif source == 'NOOP':
if file_type == 'NOOP':
if 'write default configuration file' not in data:
if 'write_default_configuration_file' not in data:
raise ValueError
if not isinstance(data['write default configuration file'], bool):
if not isinstance(data['write_default_configuration_file'], bool):
raise TypeError
if not data['write default configuration file']:
if not data['write_default_configuration_file']:
raise ValueError
ok = True
@ -686,7 +685,7 @@ def asset_checksum_matches(file: str) -> bool:
m = hashlib.sha512()
matches = False
m.update(open(file, 'rb').read())
if m.hexdigest() == const.Checksum[pathlib.Path(file).name]:
if m.hexdigest() == const.checksum[pathlib.Path(file).name]:
matches = True
return matches
@ -715,59 +714,59 @@ def pipeline(source: str, file_type: str, data: dict):
project_name = 'fattura_elettronica_reader'
create_appdirs(project_name)
configuration_file = data['configuration file']
configuration_file = data['configuration_file']
if configuration_file == str():
configuration_file = define_appdirs_user_config_dir_file_path(
project_name, const.Paths['configuration file'])
if not pathlib.Path(configuration_file).is_file() or data['write default configuration file']:
project_name, const.paths['configuration_file'])
if not pathlib.Path(configuration_file).is_file() or data['write_default_configuration_file']:
write_configuration_file(configuration_file)
pathlib.Path(data['destination directory']).mkdir(mode=0o700, parents=True, exist_ok=True)
pathlib.Path(data['destination_directory']).mkdir(mode=0o700, parents=True, exist_ok=True)
if source != 'NOOP' and file_type != 'NOOP':
config = yaml.load(open(configuration_file, 'r'), Loader=yaml.SafeLoader)
# Define all the paths for the static elements.
trusted_list_file = define_appdirs_user_data_dir_file_path(
project_name, const.Paths['trusted list file'])
project_name, const.paths['trusted_list_file'])
ca_certificate_pem_file = define_appdirs_user_data_dir_file_path(
project_name, const.Paths['CA certificate pem file'])
project_name, const.paths['ca_certificate_pem_file'])
w3c_schema_file_for_xml_signatures = define_appdirs_user_data_dir_file_path(
project_name,
const.Paths['invoice file']['XSD']['W3C Schema for XML Signatures'])
const.paths['invoice_file']['xsd']['w3c_schema_for_xml_signatures'])
if source == 'invoice':
invoice_schema_file = define_appdirs_user_data_dir_file_path(
project_name, const.Paths['invoice file']['XSD']['default'])
project_name, const.paths['invoice_file']['xsd']['default'])
invoice_xslt_file = define_appdirs_user_data_dir_file_path(
project_name,
const.Paths['invoice file']['XSLT'][data['invoice xslt type']])
const.paths['invoice_file']['xslt'][data['invoice_xslt_type']])
# See also:
# https://www.fatturapa.gov.it/export/fatturazione/sdi/messaggi/v1.0/MT_v1.0.xsl
metadata_root = parse_xml_file(data['metadata file'])
if data['invoice filename'] == str():
metadata_root = parse_xml_file(data['metadata_file'])
if data['invoice_filename'] == str():
invoice_filename = get_invoice_filename(
metadata_root,
config['metadata file']['XML invoice filename tag'],
dict(default=config['metadata file']['XML namespace']))
config['metadata_file']['xml_invoice_filename_tag'],
dict(default=config['metadata_file']['xml_namespace']))
if invoice_filename is None:
raise MissingTagInMetadataFile
else:
invoice_filename = data['invoice filename']
invoice_filename = data['invoice_filename']
# Assume the invoice file is in the same directory of the metadata file.
if not pathlib.Path(invoice_filename).is_file():
invoice_filename = str(
pathlib.Path(
pathlib.Path(data['metadata file']).parent,
pathlib.Path(data['metadata_file']).parent,
pathlib.Path(invoice_filename)))
if not data['no checksum check']:
if not data['no_checksum_check']:
checksum_matches, checksum = invoice_file_checksum_matches(
metadata_root, invoice_filename,
config['metadata file']['XML invoice checksum tag'],
dict(default=config['metadata file']['XML namespace']))
config['metadata_file']['xml_invoice_checksum_tag'],
dict(default=config['metadata_file']['xml_namespace']))
if checksum is None:
raise MissingTagInMetadataFile
if not checksum_matches:
@ -775,7 +774,7 @@ def pipeline(source: str, file_type: str, data: dict):
file_to_consider = invoice_filename
elif source == 'generic':
file_to_consider = data['p7m file']
file_to_consider = data['p7m_file']
# Apparently, invoices must be signed for 'PA' and not necessarly for
# 'B2B' and other cases. I could not find official documentation
@ -786,49 +785,49 @@ def pipeline(source: str, file_type: str, data: dict):
if not is_p7m_file_signed(file_to_consider):
raise P7MFileDoesNotHaveACoherentCryptographicalSignature
if data['force trusted list file download'] or not pathlib.Path(
if data['force_trusted_list_file_download'] or not pathlib.Path(
trusted_list_file).is_file():
get_remote_file(trusted_list_file,
config['trusted list file']['download'])
config['trusted_list_file']['download'])
if not data['ignore assets checksum']:
if not data['ignore_assets_checksum']:
if not asset_checksum_matches(trusted_list_file):
raise AssetsChecksumDoesNotMatch("Run the program with the '--ignore-assets-checksum' option, contact the developer or open a pull request. Have a look at " + const.Docs['assets url'])
raise AssetsChecksumDoesNotMatch("Run the program with the '--ignore-assets-checksum' option, contact the developer or open a pull request. Have a look at " + const.docs['assets url'])
trusted_list_xml_root = parse_xml_file(trusted_list_file)
get_ca_certificates(trusted_list_xml_root, ca_certificate_pem_file,
config['trusted list file']['XML namespace'],
config['trusted list file']['XML certificate tag'])
config['trusted_list_file']['xml_namespace'],
config['trusted_list_file']['xml_certificate_tag'])
if (not (source == 'invoice' and file_type == 'plain')) or (
source == 'invoice'
and file_type == 'p7m') or (source == 'generic'
and file_type == 'p7m'):
if not is_p7m_file_authentic(file_to_consider, ca_certificate_pem_file,
data['ignore signature check'],
data['ignore signers certificate check']):
data['ignore_signature_check'],
data['ignore_signers_certificate_check']):
raise P7MFileNotAuthentic
if source == 'invoice' or ('no invoice xml validation' in data and
(not data['no invoice xml validation'])):
if source == 'invoice' or ('no_invoice_xml_validation' in data and
(not data['no_invoice_xml_validation'])):
# This W3C file should not change any time soon so we can avoid the force download option.
if not pathlib.Path(w3c_schema_file_for_xml_signatures).is_file():
get_remote_file(w3c_schema_file_for_xml_signatures,
config['invoice file']['W3C XSD download'])
config['invoice_file']['W3C XSD download'])
if data['force invoice schema file download'] or not pathlib.Path(
if data['force_invoice_schema_file_download'] or not pathlib.Path(
invoice_schema_file).is_file():
get_remote_file(invoice_schema_file,
config['invoice file']['XSD download'])
config['invoice_file']['XSD download'])
patch_invoice_schema_file(
invoice_schema_file,
const.Patch['invoice file']['XSD']['line'][0]['offending'],
const.Patch['invoice file']['XSD']['line'][0]['fix'])
const.patch['invoice_file']['xsd']['line'][0]['offending'],
const.patch['invoice_file']['xsd']['line'][0]['fix'])
# Verify the checksum of the patched file.
if not data['ignore assets checksum']:
if not data['ignore_assets_checksum']:
if not asset_checksum_matches(invoice_schema_file):
raise AssetsChecksumDoesNotMatch("Run the program with the '--ignore-assets-checksum' option, contact the developer or open a pull request. Have a look at https://frnmst.github.io/fattura-elettronica-reader/assets.html")
@ -869,7 +868,7 @@ def pipeline(source: str, file_type: str, data: dict):
raise CannotExtractOriginalP7MFile
if source == 'invoice':
if not data['no invoice xml validation']:
if not data['no_invoice_xml_validation']:
if not is_xml_file_conforming_to_schema(
str(
pathlib.Path(tmpdirname,
@ -882,29 +881,29 @@ def pipeline(source: str, file_type: str, data: dict):
pathlib.Path(tmpdirname,
file_to_consider_original_relative)))
if data['extract attachments']:
if data['extract_attachments']:
extract_attachments_from_invoice_file(
invoice_root,
config['invoice file']['XML attachment XPath'],
config['invoice file']['XML attachment tag'],
config['invoice file']['XML attachment filename tag'],
config['invoice file']['text encoding'],
data['ignore attachment extension whitelist'],
data['ignore attachment filetype whitelist'],
config['invoice file']['attachment extension whitelist'],
config['invoice file']['attachment filetype whitelist'],
data['destination directory'])
config['invoice_file']['xml_attachment_xpath'],
config['invoice_file']['xml_attachment_tag'],
config['invoice_file']['xml_attachment_filename_tag'],
config['invoice_file']['text_encoding'],
data['ignore_attachment_extension_whitelist'],
data['ignore_attachment_filetype_whitelist'],
config['invoice_file']['attachment_extension_whitelist'],
config['invoice_file']['attachment_filetype_whitelist'],
data['destination_directory'])
if data['generate html output']:
if data['force invoice xml stylesheet file download'] or not pathlib.Path(
if data['generate_html_output']:
if data['force_invoice_xml_stylesheet_file_download'] or not pathlib.Path(
invoice_xslt_file).is_file():
get_remote_file(
invoice_xslt_file,
config['invoice file']['XSLT ' +
data['invoice xslt type'] +
' download'])
config['invoice_file']['xslt_' +
data['invoice_xslt_type'] +
'_download'])
if not data['ignore assets checksum']:
if not data['ignore_assets_checksum']:
if not asset_checksum_matches(invoice_xslt_file):
raise AssetsChecksumDoesNotMatch("Run the program with the '--ignore-assets-checksum' option, contact the developer or open a pull request. Have a look at https://frnmst.github.io/fattura-elettronica-reader/assets.html")
@ -913,18 +912,18 @@ def pipeline(source: str, file_type: str, data: dict):
get_invoice_as_html(invoice_root, invoice_xslt_root,
html_output,
config['invoice file']['text encoding'],
data['destination directory'])
config['invoice_file']['text_encoding'],
data['destination_directory'])
if (source == 'invoice'
and file_type == 'p7m') or (source == 'generic'
and file_type == 'p7m'):
if data['keep original file']:
if data['keep_original_file']:
shutil.move(
str(
pathlib.Path(tmpdirname,
file_to_consider_original_relative)),
str(pathlib.Path(data['destination directory'], file_to_consider_original_relative)))
str(pathlib.Path(data['destination_directory'], file_to_consider_original_relative)))
if __name__ == '__main__':

View File

@ -2,7 +2,7 @@
# cli.py
#
# Copyright (c) 2018 Enio Carboni - Italy
# Copyright (C) 2019-2020 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
# Copyright (C) 2019-2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
#
# This file is part of fattura-elettronica-reader.
#
@ -50,85 +50,85 @@ class CliToApi():
common_data = {
'patched':
False,
'configuration file':
'configuration_file':
args.configuration_file,
'write default configuration file':
'write_default_configuration_file':
args.write_default_configuration_file,
'ignore assets checksum':
'ignore_assets_checksum':
args.ignore_assets_checksum,
'destination directory':
'destination_directory':
args.destination_directory,
}
# Prepare the data structure.
if args.source == 'invoice':
data = {
'extract attachments':
'extract_attachments':
args.extract_attachments,
'metadata files':
'metadata_files':
args.metadata_file,
'invoice xslt type':
'invoice_xslt_type':
args.invoice_xslt_type,
'no invoice xml validation':
'no_invoice_xml_validation':
args.no_invoice_xml_validation,
'force invoice schema file download':
'force_invoice_schema_file_download':
args.force_invoice_schema_file_download,
'generate html output':
'generate_html_output':
args.generate_html_output,
'invoice filename':
'invoice_filename':
args.invoice_filename,
'no checksum check':
'no_checksum_check':
args.no_checksum_check,
'force invoice xml stylesheet file download':
'force_invoice_xml_stylesheet_file_download':
args.force_invoice_xml_stylesheet_file_download,
'ignore attachment extension whitelist':
'ignore_attachment_extension_whitelist':
args.ignore_attachment_extension_whitelist,
'ignore attachment filetype whitelist':
'ignore_attachment_filetype_whitelist':
args.ignore_attachment_filetype_whitelist,
}
if args.file_type == 'p7m':
data['ignore signature check'] = args.ignore_signature_check
data['ignore_signature_check'] = args.ignore_signature_check
data[
'ignore signers certificate check'] = args.ignore_signers_certificate_check
'ignore_signers_certificate_check'] = args.ignore_signers_certificate_check
data[
'force trusted list file download'] = args.force_trusted_list_file_download
data['keep original file'] = args.keep_original_file
'force_trusted_list_file_download'] = args.force_trusted_list_file_download
data['keep_original_file'] = args.keep_original_file
elif args.file_type == 'plain':
pass
elif args.source == 'generic':
if args.file_type == 'p7m':
data = {
'p7m files': args.p7m_file,
'ignore signature check': args.ignore_signature_check,
'ignore signers certificate check':
'p7m_files': args.p7m_file,
'ignore_signature_check': args.ignore_signature_check,
'ignore_signers_certificate_check':
args.ignore_signers_certificate_check,
'force trusted list file download':
'force_trusted_list_file_download':
args.force_trusted_list_file_download,
'keep original file': args.keep_original_file,
'keep_original_file': args.keep_original_file,
}
else:
data = {'write default configuration file': True}
data = {'write_default_configuration_file': True}
# Merge the dicts.
data = {**common_data, **data}
if args.source == 'invoice':
iterator = data['metadata files']
iterator = data['metadata_files']
elif args.source == 'generic':
iterator = data['p7m files']
iterator = data['p7m_files']
else:
# Write the config file and quit.
iterator = ['config file']
iterator = ['config_file']
for i in iterator:
# Patch data with single files.
data['patched'] = True
if args.source == 'invoice':
data['metadata file'] = i
data['metadata_file'] = i
source = args.source
file_type = args.file_type
elif args.source == 'generic':
data['p7m file'] = i
data['p7m_file'] = i
source = args.source
file_type = args.file_type
else:
@ -265,7 +265,7 @@ class CliInterface():
invoice_p7m_parser.add_argument('-o',
'--keep-original-file',
action='store_true',
help='keep the original file')
help='extract the plain XML file')
invoice_p7m_parser.add_argument('metadata_file',
nargs='+',

View File

@ -2,7 +2,7 @@
# constants.py
#
# Copyright (c) 2018 Enio Carboni - Italy
# Copyright (C) 2019-2021 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
# Copyright (C) 2019-2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
#
# This file is part of fattura-elettronica-reader.
#
@ -24,75 +24,75 @@
from pathlib import Path
common_defaults = dict()
common_defaults = {'home directory': Path.home()}
common_defaults = {'home_directory': Path.home()}
XML = dict()
XML['metadata file'] = dict()
XML['trusted list file'] = dict()
XML['invoice file'] = dict()
xml = dict()
xml['metadata_file'] = dict()
xml['trusted_list_file'] = dict()
xml['invoice_file'] = dict()
XML['metadata file']['namespaces'] = {
xml['metadata_file']['namespaces'] = {
'default':
'http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fattura/messaggi/v1.0'
}
XML['metadata file']['tags'] = {
'invoice checksum': 'Hash',
'invoice filename': 'NomeFile',
'system id': 'IdentificativoSdI'
xml['metadata_file']['tags'] = {
'invoice_checksum': 'Hash',
'invoice_filename': 'NomeFile',
'system_id': 'IdentificativoSdI'
}
XML['trusted list file']['namespaces'] = {
xml['trusted_list_file']['namespaces'] = {
'default': 'http://uri.etsi.org/02231/v2#'
}
XML['trusted list file']['tags'] = {'certificate': 'X509Certificate'}
xml['trusted_list_file']['tags'] = {'certificate': 'X509Certificate'}
XML['invoice file']['namespaces'] = {
xml['invoice_file']['namespaces'] = {
'default': 'http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2'
}
XML['invoice file']['tags'] = {
xml['invoice_file']['tags'] = {
'attachment': 'Attachment',
'attachment filename': 'NomeAttachment'
'attachment_filename': 'NomeAttachment'
}
XML['invoice file']['XPath'] = {
xml['invoice_file']['xpath'] = {
'attachment': './FatturaElettronicaBody/Allegati'
}
# See:
# https://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2.1/Schema_del_file_xml_FatturaPA_versione_1.2.1.xsd
XML['invoice file']['proprieties'] = {'text encoding': 'UTF-8'}
xml['invoice_file']['proprieties'] = {'text_encoding': 'UTF-8'}
# Download urls.
Downloads = dict()
downloads = dict()
Downloads['invoice file'] = dict()
Downloads['invoice file']['XSLT'] = {
downloads['invoice_file'] = dict()
downloads['invoice_file']['xslt'] = {
# Pubblica Amministrazione.
'PA':
'pa':
'https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2.1/Foglio_di_stile_fatturaPA_v1.2.1.xsl',
'ordinaria':
'https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2.1/Foglio_di_stile_fatturaordinaria_v1.2.1.xsl'
}
Downloads['invoice file']['XSD'] = {
downloads['invoice_file']['xsd'] = {
'default':
'https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2.1/Schema_del_file_xml_FatturaPA_versione_1.2.1a.xsd',
'W3C Schema for XML Signatures':
'w3c_schema_for_xml_signatures':
'https://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd'
}
Downloads['trusted list file'] = {
downloads['trusted_list_file'] = {
'default': 'https://eidas.agid.gov.it/TL/TSL-IT.xml'
}
# File Patches.
Patch = dict()
Patch['invoice file'] = dict()
Patch['invoice file']['XSD'] = dict()
Patch['invoice file']['XSD']['line'] = dict()
Patch['invoice file']['XSD']['line'][0] = {
# file patches.
patch = dict()
patch['invoice_file'] = dict()
patch['invoice_file']['xsd'] = dict()
patch['invoice_file']['xsd']['line'] = dict()
patch['invoice_file']['xsd']['line'][0] = {
'offending':
2 * ' ' +
'<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd" />\n',
@ -102,51 +102,51 @@ Patch['invoice file']['XSD']['line'][0] = {
}
# Relative paths.
Paths = dict()
Paths['trusted list file'] = 'trusted_list.xml'
Paths['CA certificate pem file'] = 'CA.pem'
Paths['invoice file'] = dict()
paths = dict()
paths['trusted_list_file'] = 'trusted_list.xml'
paths['ca_certificate_pem_file'] = 'CA.pem'
paths['invoice_file'] = dict()
# Invoice stylesheet files.
Paths['invoice file']['XSLT'] = {
'PA': 'invoice_stylesheet_PA.xslt',
paths['invoice_file']['xslt'] = {
'pa': 'invoice_stylesheet_PA.xslt',
'ordinaria': 'invoice_stylesheet_ordinaria.xslt'
}
# Invoice schema files.
Paths['invoice file']['XSD'] = {
# Invoice schema files (xsd).
paths['invoice_file']['xsd'] = {
'default': 'invoice_schema.xsd',
'W3C Schema for XML Signatures': 'xmldsig-core-schema.xsd'
'w3c_schema_for_xml_signatures': 'xmldsig-core-schema.xsd'
}
Paths['configuration file'] = 'fattura_elettronica_reader.conf'
paths['configuration_file'] = 'fattura_elettronica_reader.conf'
# Stuff related generically to files.
File = dict()
File['invoice'] = dict()
File['invoice']['attachment'] = {
'extension whitelist': ['PDF', 'pdf'],
file = dict()
file['invoice'] = dict()
file['invoice']['attachment'] = {
'extension_whitelist': ['PDF', 'pdf'],
# Uses mimes.
'filetype whitelist': ['application/pdf']
'filetype_whitelist': ['application/pdf']
}
#############
# Checksums #
# checksums #
#############
# SHA-512 checksum of the assets.
Checksum = dict()
Checksum[Paths['invoice file']['XSLT']['PA']] = 'd1ca406c6bb174aa351eae4d6ca162b459e00ab3993d87f977c118c0edfe4201c8aec54c7498f324285a56677885cb11bba5de02ae0c9e46b63ab679eb7aa4a2'
Checksum[Paths['invoice file']['XSLT']['ordinaria']] = '2c315cbb04126e98192c0afa585fe3b264ed4fada044504cf9ad77f2272e26106916239e86238dc250f15f5b22a33383e2e690ae28a5f5eb7a8a3b84d3f393b3'
checksum = dict()
checksum[paths['invoice_file']['xslt']['pa']] = 'd1ca406c6bb174aa351eae4d6ca162b459e00ab3993d87f977c118c0edfe4201c8aec54c7498f324285a56677885cb11bba5de02ae0c9e46b63ab679eb7aa4a2'
checksum[paths['invoice_file']['xslt']['ordinaria']] = '2c315cbb04126e98192c0afa585fe3b264ed4fada044504cf9ad77f2272e26106916239e86238dc250f15f5b22a33383e2e690ae28a5f5eb7a8a3b84d3f393b3'
# Checksum of the patched schema file, not of the original one which is
# checksum of the patched schema file, not of the original one which is
# 2a7c3f2913ee390c167e41ae5618c303b481f548f9b2a8d60dddc36804ddd3ebf7cb5003e5cc6996480c67d085b82b438aff7cc0f74d7c104225449785cb575b
#
# The XML schema file for FatturaPA version 1.2.1 needs to be patched. fattura_elettronica_reader
# The xml schema file for FatturaPA version 1.2.1 needs to be patched. fattura_elettronica_reader
# runs the SHA-512 checksum on the patched version of that file which corresponds to:
Checksum[Paths['invoice file']['XSD']['default']] = 'a1b02818f81ac91f35358260dd12e1bf4480e1545bb457caffa0d434200a1bd05bedd88df2d897969485a989dda78922850ebe978b92524778a37cb0afacba27'
checksum[paths['invoice_file']['xsd']['default']] = 'a1b02818f81ac91f35358260dd12e1bf4480e1545bb457caffa0d434200a1bd05bedd88df2d897969485a989dda78922850ebe978b92524778a37cb0afacba27'
# TSL-IT.xml
Checksum[Paths['trusted list file']] = 'd6b8c13a5574fb34f658f1122c3c4cd72fd7f9b59f51b3ab9e3972e6aebc19ab432de4706b4473d467f4bd6966fe49296389b3f9164ba593cac9c81843a83155'
checksum[paths['trusted_list_file']] = 'd6b8c13a5574fb34f658f1122c3c4cd72fd7f9b59f51b3ab9e3972e6aebc19ab432de4706b4473d467f4bd6966fe49296389b3f9164ba593cac9c81843a83155'
Docs = dict()
Docs['assets url'] = 'https://docs.franco.net.eu.org/fattura-elettronica-reader/assets.html'
docs = dict()
docs['assets_url'] = 'https://docs.franco.net.eu.org/fattura-elettronica-reader/assets.html'
if __name__ == '__main__':
pass