Fixed and improved API and CLI.

This commit is contained in:
Franco Masotti 2020-07-06 12:43:31 +02:00
parent 0743ec77e1
commit 9bae9bd820
Signed by: frnmst
GPG Key ID: 24116ED85666780A
4 changed files with 322 additions and 251 deletions

View File

@ -23,14 +23,14 @@
from .api import (
is_xml_file_conforming_to_schema, parse_xml_file, get_invoice_filename,
is_invoice_file_signed, invoice_file_checksum_matches, get_remote_file,
get_ca_certificates, is_invoice_file_authentic, remove_signature_from_invoice_file,
is_p7m_file_signed, invoice_file_checksum_matches, get_remote_file,
get_ca_certificates, is_p7m_file_authentic, remove_signature_from_p7m_file,
extract_attachments_from_invoice_file, get_invoice_as_html, patch_invoice_schema_file,
create_appdirs, define_appdirs_user_data_dir_file_path, define_appdirs_user_config_dir_file_path,
write_configuration_file, load_configuration, pipeline)
from .cli import (CliInterface)
from .exceptions import (InvoiceFileDoesNotHaveACoherentCryptographicalSignature,
InvoiceFileChecksumFailed, InvoiceFileNotAuthentic,
CannotExtractOriginalInvoiceFile, MissingTagInMetadataFile,
from .exceptions import (P7MFileDoesNotHaveACoherentCryptographicalSignature,
InvoiceFileChecksumFailed, P7MFileNotAuthentic,
CannotExtractOriginalP7MFile, MissingTagInMetadataFile,
XMLFileNotConformingToSchema, ExtractedAttachmentNotInExtensionWhitelist,
ExtractedAttachmentNotInFileTypeWhitelist)

View File

@ -34,9 +34,9 @@ import atomicwrites
import filetype
import appdirs
import configparser
from .exceptions import (InvoiceFileDoesNotHaveACoherentCryptographicalSignature,
InvoiceFileChecksumFailed, InvoiceFileNotAuthentic,
CannotExtractOriginalInvoiceFile,
from .exceptions import (P7MFileDoesNotHaveACoherentCryptographicalSignature,
InvoiceFileChecksumFailed, P7MFileNotAuthentic,
CannotExtractOriginalP7MFile,
MissingTagInMetadataFile, XMLFileNotConformingToSchema,
ExtractedAttachmentNotInExtensionWhitelist,
ExtractedAttachmentNotInFileTypeWhitelist)
@ -93,18 +93,17 @@ def get_invoice_filename(metadata_file_xml_root,
metadata_file_xml_namespace).text
def is_invoice_file_signed(invoice_file: str) -> bool:
def is_p7m_file_signed(p7m_file: str) -> bool:
r"""Check if the invoice file is signed with a PKCS#7 signature.
:param invoice_file: the path of the invoice file.
:type invoice_file: str
:param p7m_file: the path of the invoice file.
:type p7m_file: str
:returns: True if the file is signed, False otherwise.
:rtype: bool
:raises: a subprocess or a built-in exception.
"""
command = 'openssl pkcs7 -print_certs -text -noout -inform DER -in {}'.format(
shlex.quote(invoice_file))
print(command)
shlex.quote(p7m_file))
return True if subprocess.run(
shlex.split(command)).returncode == 0 else False
@ -209,19 +208,19 @@ def get_ca_certificates(trusted_list_xml_root: str,
f.write(stricttextualmsg)
def is_invoice_file_authentic(invoice_file: str,
def is_p7m_file_authentic(p7m_file: str,
ca_certificate_pem_file: str,
ignore_signature_check: bool = False,
ignore_signers_certificate_check: bool = False):
r"""Check authenticity of the invoice file on various levels.
:param invoice_file: the path of the signed invoice file.
:param p7m_file: the path of the signed invoice file.
:param ca_certificate_pem_file: the certificates file in PEM format.
:param ignore_signature_check: avoid checking the signature.
Defaults to ``False``.
:param ignore_signers_certificate_check: avoid checking the signer's
certificate. Defaults to ``False``.
:type invoice_file: str
:type p7m_file: str
:type ca_certificate_pem_file: str
:type ignore_signature_check: bool
:type ignore_signers_certificate_check: bool
@ -238,25 +237,25 @@ def is_invoice_file_authentic(invoice_file: str,
command = (
'openssl smime ' + pre + ' -verify ' + post + ' -CAfile {}'.format(
shlex.quote(ca_certificate_pem_file)) + ' -in {}'.format(
shlex.quote(invoice_file)) + ' -inform DER -out /dev/null')
shlex.quote(p7m_file)) + ' -inform DER -out /dev/null')
return True if subprocess.run(
shlex.split(command)).returncode == 0 else False
def remove_signature_from_invoice_file(invoice_file: str,
def remove_signature_from_p7m_file(p7m_file: str,
output_file: str) -> bool:
r"""Remove signature from the signed invoice file and save the original one.
:param invoice_file: the path of the invoice file.
:param p7m_file: the path of the invoice file.
:param output_file: the path of the destination file.
:type invoice_file: str
:type p7m_file: str
:type output_file: str
:returns: ``True`` if the operation is successful, ``False`` otherwise.
:rtype: bool
:raises: a subprocess or built-in exception.
"""
command = ('openssl smime -nosigs -verify -noverify -in {}'.format(
shlex.quote(invoice_file)) + ' -inform DER -out {}'.format(
shlex.quote(p7m_file)) + ' -inform DER -out {}'.format(
shlex.quote(output_file)))
return True if subprocess.run(
shlex.split(command)).returncode == 0 else False
@ -504,61 +503,48 @@ def load_configuration(configuration_file: str):
return configuration
def pipeline(metadata_file: str,
configuration_file: str = None,
invoice_filename: str = None,
ignore_signature_check: bool = False,
ignore_signers_certificate_check: bool = False,
no_checksum_check: bool = False,
extract_attachments: bool = False,
generate_html_output: bool = False,
keep_original_invoice: bool = False,
force_trusted_list_file_download: bool = False,
force_invoice_xml_stylesheet_file_download: bool = False,
force_invoice_schema_file_download: bool = False,
no_invoice_xml_validation: bool = False,
invoice_xslt_type: str = 'ordinaria',
ignore_attachment_extension_whitelist: bool = False,
ignore_attachment_filetype_whitelist: bool = False,
write_default_configuration_file: bool = False,
invoice_file_is_not_p7m: bool = False,
generic_p7m_file = False):
def assert_data_structure(source: str, file_type: str, data: dict):
pass
def pipeline(source: str, file_type: str, data: dict):
r"""Run the pipeline."""
assert_data_structure(source, file_type, data)
project_name = 'fattura_elettronica_reader'
create_appdirs(project_name)
configuration_file = data['configuration file']
if configuration_file is None:
configuration_file = define_appdirs_user_config_dir_file_path(project_name, Paths['configuration file'])
if write_default_configuration_file:
write_configuration_file(configuration_file)
if data['write default configuration file']:
write_configuration_file(data['configuration file'])
config = load_configuration(configuration_file)
# Define all the paths for the static elements.
trusted_list_file = define_appdirs_user_data_dir_file_path(project_name, Paths['trusted list file'])
ca_certificate_pem_file = define_appdirs_user_data_dir_file_path(project_name, Paths['CA certificate pem file'])
invoice_schema_file = define_appdirs_user_data_dir_file_path(project_name,Paths['invoice file']['XSD']['default'])
w3c_schema_file_for_xml_signatures = define_appdirs_user_data_dir_file_path(project_name,Paths['invoice file']['XSD']['W3C Schema for XML Signatures'])
invoice_xslt_ordinaria_file = define_appdirs_user_data_dir_file_path(project_name, Paths['invoice file']['XSLT']['ordinaria'])
invoice_xslt_PA_file = define_appdirs_user_data_dir_file_path(project_name, Paths['invoice file']['XSLT']['PA'])
if invoice_xslt_type == 'ordinaria':
invoice_xslt_file = invoice_xslt_ordinaria_file
elif invoice_xslt_type == 'PA':
invoice_xslt_file = invoice_xslt_PA_file
else:
invoice_xslt_file = invoice_xslt_ordinaria_file
if source == 'invoice':
invoice_schema_file = define_appdirs_user_data_dir_file_path(project_name,Paths['invoice file']['XSD']['default'])
invoice_xslt_file = define_appdirs_user_data_dir_file_path(project_name, Paths['invoice file']['XSLT'][data['invoice xslt type']])
if not generic_p7m_file:
# See also:
# https://www.fatturapa.gov.it/export/fatturazione/sdi/messaggi/v1.0/MT_v1.0.xsl
metadata_root = parse_xml_file(metadata_file)
if invoice_filename is None:
metadata_root = parse_xml_file(data['metadata file'])
if data['invoice filename'] is None:
invoice_filename = get_invoice_filename(
metadata_root, 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']
if not no_checksum_check:
# 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(invoice_filename)))
if not data['no checksum check']:
checksum_matches, checksum = invoice_file_checksum_matches(
metadata_root, invoice_filename,
config['metadata file']['XML invoice checksum tag'],
@ -568,97 +554,101 @@ def pipeline(metadata_file: str,
if not checksum_matches:
raise InvoiceFileChecksumFailed
file_to_consider = invoice_filename
elif source == 'generic':
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
# corroborating this but it happened at least one.
if not invoice_file_is_not_p7m:
if not is_invoice_file_signed(invoice_filename):
raise InvoiceFileDoesNotHaveACoherentCryptographicalSignature
if (source == 'invoice' and file_type == 'p7m') or (source == 'generic' and file_type == 'p7m'):
if not is_p7m_file_signed(file_to_consider):
raise P7MFileDoesNotHaveACoherentCryptographicalSignature
if force_trusted_list_file_download or not pathlib.Path(
trusted_list_file).exists():
get_remote_file(trusted_list_file,
config['trusted list file']['download'])
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'])
trusted_list_xml_root = parse_xml_file(trusted_list_file)
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'])
get_ca_certificates(trusted_list_xml_root, ca_certificate_pem_file,
config['trusted list file']['XML namespace'],
config['trusted list file']['XML certificate tag'])
if not invoice_file_is_not_p7m:
if not is_invoice_file_authentic(invoice_filename, ca_certificate_pem_file,
ignore_signature_check,
ignore_signers_certificate_check):
raise InvoiceFileNotAuthentic
if not generic_p7m_file or not no_invoice_xml_validation:
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']):
raise P7MFileNotAuthentic
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).exists():
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'])
if force_invoice_schema_file_download or not pathlib.Path(invoice_schema_file).exists():
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'])
patch_invoice_schema_file(invoice_schema_file, Patch['invoice file']['XSD']['line'][0]['offending'],Patch['invoice file']['XSD']['line'][0]['fix'])
if not generic_p7m_file:
# Create a temporary directory to store the original XML invoice file.
with tempfile.TemporaryDirectory() as tmpdirname:
# invoice_original_file is the path of the non-signed invoice file. If an invoice file is signed,
# the filename usually ends in '.p7m' so the destination file must end with '.xml'
# to be transformed into an xml file. On the contrary, the filename of non-signed invoice files
# already ends in '.xml'.
if invoice_file_is_not_p7m:
invoice_original_file = invoice_filename
else:
invoice_original_file = invoice_filename + '.xml'
# Create a temporary directory to store the original XML invoice file.
with tempfile.TemporaryDirectory() as tmpdirname:
# file_to_consider_original is the path of the non-signed p7m file. signed files
# end in '.p7m' so the destination file (original) must end with '.xml' or '.generic'
# to be transformed into an xml file. On the contrary, the filename of non-signed files
# already ends with the correct extension.
if source == 'invoice' and file_type == 'plain':
file_to_consider_original = file_to_consider
elif source == 'invoice' and file_type == 'p7m':
file_to_consider_original = file_to_consider + '.xml'
elif source == 'generic' and file_type == 'p7m':
file_to_consider_original = file_to_consider + '.generic'
# In case absolute paths are passed to this function the concatenation of an absolute path
# and a temporary directory name, which is also an absolue path, would not work as expected.
invoice_original_file_relative = pathlib.Path(invoice_original_file).name
# In case absolute paths are passed to this function the concatenation of an absolute path
# and a temporary directory name, which is also an absolue path, would not work as expected.
file_to_consider_original_relative = pathlib.Path(file_to_consider_original).name
if invoice_file_is_not_p7m:
# There is no signature to extract but we need to copy the file in the temporary store.
shutil.copyfile(invoice_original_file, str(pathlib.Path(tmpdirname, invoice_original_file_relative)))
else:
# Extract the original invoice and copy it in the temporary store.
if not remove_signature_from_invoice_file(invoice_filename,
str(pathlib.Path(tmpdirname, invoice_original_file_relative))):
raise CannotExtractOriginalInvoiceFile
if source == 'invoice' and file_type == 'plain':
# There is no signature to extract but we need to copy the file in the temporary storage.
shutil.copyfile(file_to_consider_original, str(pathlib.Path(tmpdirname, file_to_consider_original_relative)))
elif (source == 'invoice' and file_type == 'p7m') or (source == 'generic' and file_type == 'p7m'):
# Extract the original invoice and copy it in the temporary store.
if not remove_signature_from_p7m_file(file_to_consider,
str(pathlib.Path(tmpdirname, file_to_consider_original_relative))):
raise CannotExtractOriginalP7MFile
if not no_invoice_xml_validation:
if not is_xml_file_conforming_to_schema(str(pathlib.Path(tmpdirname, invoice_original_file_relative)), invoice_schema_file):
if source == 'invoice':
if not data['no invoice xml validation']:
if not is_xml_file_conforming_to_schema(str(pathlib.Path(tmpdirname, file_to_consider_original_relative)), invoice_schema_file):
raise XMLFileNotConformingToSchema
invoice_root = parse_xml_file(str(pathlib.Path(tmpdirname, invoice_original_file_relative)))
invoice_root = parse_xml_file(str(pathlib.Path(tmpdirname, file_to_consider_original_relative)))
if 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'],
ignore_attachment_extension_whitelist,
ignore_attachment_filetype_whitelist,
data['ignore attachment extension whitelist'],
data['ignore attachment filetype whitelist'],
config['invoice file']['attachment extension whitelist'],
config['invoice file']['attachment filetype whitelist'])
if generate_html_output:
if force_invoice_xml_stylesheet_file_download or not pathlib.Path(
invoice_xslt_file).exists():
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 ' + invoice_xslt_type + ' download'])
invoice_xslt_root = parse_xml_file(invoice_xslt_file)
html_output = invoice_filename + '.html'
html_output = file_to_consider + '.html'
get_invoice_as_html(invoice_root, invoice_xslt_root, html_output,
config['invoice file']['text encoding'])
if keep_original_invoice:
shutil.move(str(pathlib.Path(tmpdirname, invoice_original_file_relative)), invoice_original_file)
if data['keep original file']:
shutil.move(str(pathlib.Path(tmpdirname, file_to_consider_original_relative)), file_to_consider_original)
if __name__ == '__main__':

View File

@ -27,7 +27,7 @@ from pkg_resources import (get_distribution, DistributionNotFound)
from .api import pipeline
from .constants import File
PROGRAM_DESCRIPTION = 'fattura-elettronica-reader: Validate, extract, and generate printables\nof electronic invoice files received from the "Sistema di Interscambio"'
PROGRAM_DESCRIPTION = 'fattura-elettronica-reader: Validate, extract, and generate printables\nof electronic invoice files received from the "Sistema di Interscambio"\nas well as other P7M files'
VERSION_NAME = 'fattura_elettronica_reader'
try:
VERSION_NUMBER = str(get_distribution('fattura_elettronica_reader').version)
@ -40,38 +40,66 @@ PROGRAM_EPILOG = RETURN_VALUES + '\n\n' + VERSION_COPYRIGHT + '\n' + VERSION_LIC
class CliToApi():
"""An interface between the CLI and API functions."""
r"""An interface between the CLI and API functions."""
def run(self, args):
"""Run the pipeline."""
if args.keep_all:
args.extract_attachments = True
args.generate_html_output = True
args.keep_original_invoice = True
if args.generic_p7m_file:
# The generic p7m file might not be an XML file.
args.no_invoice_xml_validation = True
for metadata_file in args.metadata_file:
pipeline(
metadata_file=metadata_file,
configuration_file=args.configuration_file,
invoice_filename=args.invoice_filename,
ignore_signature_check=args.ignore_signature_check,
ignore_signers_certificate_check=args.ignore_signers_certificate_check,
no_checksum_check=args.no_checksum_check,
extract_attachments=args.extract_attachments,
generate_html_output=args.generate_html_output,
keep_original_invoice = args.keep_original_invoice,
force_trusted_list_file_download=args.force_trusted_list_file_download,
force_invoice_xml_stylesheet_file_download=args.force_invoice_xml_stylesheet_file_download,
force_invoice_schema_file_download=args.force_invoice_schema_file_download,
no_invoice_xml_validation=args.no_invoice_xml_validation,
invoice_xslt_type=args.invoice_xslt_type,
ignore_attachment_extension_whitelist=args.ignore_attachment_extension_whitelist,
ignore_attachment_filetype_whitelist=args.ignore_attachment_filetype_whitelist,
write_default_configuration_file=args.write_default_configuration_file,
invoice_file_is_not_p7m=args.invoice_file_is_not_p7m,
generic_p7m_file=args.generic_p7m_file)
r"""Run the pipeline."""
common_data = {
'patched': False,
'configuration file': args.configuration_file,
'write default configuration file': args.write_default_configuration_file,
}
# Prepare the data structure.
if args.source == 'invoice':
data = {
'extract attachments': args.extract_attachments,
'metadata files': args.metadata_file,
'invoice xslt type': args.invoice_xslt_type,
'no invoice xml validation': args.no_invoice_xml_validation,
'force invoice schema file download': args.force_invoice_schema_file_download,
'generate html output': args.generate_html_output,
'invoice filename': args.invoice_filename,
'no checksum check': args.no_checksum_check,
'force invoice xml stylesheet file download': args.force_invoice_xml_stylesheet_file_download,
'ignore attachment extension whitelist': args.ignore_attachment_extension_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 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
elif args.file_type == 'plain':
pass
elif args.source == 'generic':
data = {
'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': args.force_trusted_list_file_download,
'keep original file': args.keep_original_file,
}
print(args.configuration_file)
data = {**common_data, **data}
print(data)
if args.source == 'invoice':
iterator = data['metadata files']
elif args.source == 'generic':
iterator = data['p7m files']
for i in iterator:
# patch data with single files
data['patched'] = True
if args.source == 'invoice':
data['metadata file'] = i
elif args.source == 'generic':
data['p7m file'] = i
pipeline(args.source, args.file_type, data)
class CliInterface():
"""The interface exposed to the final user."""
@ -87,11 +115,169 @@ class CliInterface():
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent(PROGRAM_EPILOG))
parser.add_argument(
source_subparsers = parser.add_subparsers(title='source',
dest='source',
required=True)
###########
# Sources #
###########
invoice_parser = source_subparsers.add_parser('invoice', help='invoice file')
generic_parser = source_subparsers.add_parser('generic', help='generic file')
invoice_parser.add_argument(
'-X',
'--invoice-xslt-type',
choices=['ordinaria','PA'],
default='ordinaria',
help='select the XML stylesheet file for the invoice. Defaults to "ordinaria". This option is ignored if "-H" is not set')
invoice_parser.add_argument(
'-V',
'--no-invoice-xml-validation',
action='store_true',
help='do not perform XML validation of the invoice file')
invoice_parser.add_argument(
'-a',
'--extract-attachments',
action='store_true',
help='extract embedded attachments')
invoice_parser.add_argument(
'-E',
'--force-invoice-schema-file-download',
action='store_true',
help='force download of the XML schema necessary for the validation of the invoice file')
invoice_parser.add_argument(
'-H',
'--generate-html-output',
action='store_true',
help='generate the HTML output')
invoice_parser.add_argument(
'-i',
'--invoice-filename',
help='override the invoice file name specified in the metadata file')
invoice_parser.add_argument(
'-k',
'--no-checksum-check',
action='store_true',
help='do not perform a file integrity check of the invoice file')
invoice_parser.add_argument(
'-y',
'--force-invoice-xml-stylesheet-file-download',
action='store_true',
help='force download of the XML stylesheet file')
invoice_parser.add_argument(
'-w',
'--ignore-attachment-extension-whitelist',
action='store_true',
help='do not perform file extension checks for the attachments. This option is ignored if "-a" is not set')
invoice_parser.add_argument(
'-W',
'--ignore-attachment-filetype-whitelist',
action='store_true',
help='do not perform filetype checks for the attachments. This option is ignored if "-a" is not set')
###########
# Invoice #
###########
invoice_subparsers = invoice_parser.add_subparsers(title='file type',
dest='file_type',
required=True)
invoice_p7m_parser = invoice_subparsers.add_parser('p7m',
help='p7m')
invoice_p7m_parser.add_argument(
'-s',
'--ignore-signature-check',
default=False,
action='store_true',
help='avoids checking the cryptographic signature of the invoice file')
invoice_p7m_parser.add_argument(
'-S',
'--ignore-signers-certificate-check',
action='store_true',
help='avoids checking the cryptographic certificate')
invoice_p7m_parser.add_argument(
'-t',
'--force-trusted-list-file-download',
action='store_true',
help='force download of the trusted list file')
invoice_p7m_parser.add_argument(
'-o',
'--keep-original-file',
action='store_true',
help='keep the original file')
invoice_p7m_parser.add_argument(
'metadata_file',
nargs='+',
help='the metadata file names')
invoice_plain_parser = invoice_subparsers.add_parser('plain',
help='plain')
invoice_plain_parser.add_argument(
'metadata_file',
nargs='+',
help='the metadata file names')
###########
# Generic #
###########
generic_subparsers = generic_parser.add_subparsers(title='file type',
dest='file_type',
required=True)
generic_p7m_parser = generic_subparsers.add_parser('p7m',
help='p7m')
generic_p7m_parser.add_argument(
'-s',
'--ignore-signature-check',
default=False,
action='store_true',
help='avoids checking the cryptographic signature of the p7m file')
generic_p7m_parser.add_argument(
'-S',
'--ignore-signers-certificate-check',
action='store_true',
help='avoids checking the cryptographic certificate')
generic_p7m_parser.add_argument(
'-t',
'--force-trusted-list-file-download',
action='store_true',
help='force download of the trusted list file')
generic_p7m_parser.add_argument(
'-o',
'--keep-original-file',
action='store_true',
help='keep the original file')
generic_p7m_parser.add_argument(
'p7m_file',
nargs='+',
help='the p7m file names')
###########
# Common #
###########
parser.add_argument(
'-c',
'--configuration-file',
@ -103,111 +289,6 @@ class CliInterface():
action='store_true',
help='write the default configuration file')
parser.add_argument(
'-g',
'--generic-p7m-file',
action='store_true',
help=("""the input file is a generic p7m file, not a p7m invoice file.
You need to provide a dummy metadata file"""))
parser.add_argument(
'-i',
'--invoice-filename',
help='defaults to the one specified in the metadata file')
parser.add_argument(
'-A',
'--keep-all',
action='store_true',
help='keep all extracted and generated files. This is the same as "-Hao"')
parser.add_argument(
'-H',
'--generate-html-output',
action='store_true',
help='generate the HTML output of the invoice file')
parser.add_argument(
'-a',
'--extract-attachments',
action='store_true',
help='extract embedded attachments')
parser.add_argument(
'-o',
'--keep-original-invoice',
action='store_true',
help='keep the original invoice XML file')
parser.add_argument(
'-X',
'--invoice-xslt-type',
choices=['ordinaria','PA'],
default='ordinaria',
help='select the XML stylesheet file for the invoice. Defaults to "ordinaria". This option is ignored if "-H" is not set')
parser.add_argument(
'-V',
'--no-invoice-xml-validation',
action='store_true',
help='do not perform XML validation of the invoice file')
parser.add_argument(
'-E',
'--force-invoice-schema-file-download',
action='store_true',
help='force download of the XML schema necessary for the validation of the invoice file')
parser.add_argument(
'-b',
'--invoice-file-is-not-p7m',
default=False,
action='store_true',
help='avoids running any type of cryptographical signature and certificate checks. This is useful for certain B2B invoice files.')
parser.add_argument(
'-s',
'--ignore-signature-check',
default=False,
action='store_true',
help='avoids checking the cryptographic signature of the invoice file')
parser.add_argument(
'-S',
'--ignore-signers-certificate-check',
action='store_true',
help='avoids checking the cryptographic certificate')
parser.add_argument(
'-k',
'--no-checksum-check',
action='store_true',
help='do not perform a file integrity check of the invoice file')
parser.add_argument(
'-t',
'--force-trusted-list-file-download',
action='store_true',
help='force download of the trusted list file')
parser.add_argument(
'-y',
'--force-invoice-xml-stylesheet-file-download',
action='store_true',
help='force download of the XML stylesheet file')
parser.add_argument(
'-w',
'--ignore-attachment-extension-whitelist',
action='store_true',
help='do not perform file extension checks for the attachments. This option is ignored if "-a" is not set')
parser.add_argument(
'-W',
'--ignore-attachment-filetype-whitelist',
action='store_true',
help='do not perform filetype checks for the attachments. This option is ignored if "-a" is not set')
parser.add_argument(
'-v',
'--version',

View File

@ -22,16 +22,16 @@
"""Exceptions file."""
class InvoiceFileDoesNotHaveACoherentCryptographicalSignature(Exception):
"""Invoice does not have a PKCS#7 signature."""
class P7MFileDoesNotHaveACoherentCryptographicalSignature(Exception):
"""Not a PKCS#7 signature."""
class InvoiceFileChecksumFailed(Exception):
"""Checksum of the invoice file does not match the one in the metadata file."""
class InvoiceFileNotAuthentic(Exception):
class P7MFileNotAuthentic(Exception):
"""An error with the signature or the signers certificate of the invoice."""
class CannotExtractOriginalInvoiceFile(Exception):
class CannotExtractOriginalP7MFile(Exception):
"""The cryptographical signature from the invoice file cannot be removed."""
class MissingTagInMetadataFile(Exception):