From 33a9db123a3f2c90f4d8d70145329f834cf540a1 Mon Sep 17 00:00:00 2001 From: "Antoine Dupuis (andu)" Date: Thu, 13 Apr 2023 13:07:24 +0000 Subject: [PATCH] [FIX] tools: XSD: handle ZIP files with URL not ending in .zip In the case of the Basque country EDI, the ZIP archive containing the XSD files is located at https://www.gipuzkoa.eus/documents/2456431/13761107/Esquemas+de+archivos+XSD+de+env%C3%ADo+y+anulaci%C3%B3n+de+factura_1_2.zip/2d116f8e-4d3a-bff0-7b03-df1cbb07ec52 which does not end in .zip due to the hash at the end. The current mechanism for detecting whether the file is an XSD or a ZIP does not handle this, so the ZIP can't be downloaded. Instead of trying to guess the file type from the URL, we therefore try to open the file as a ZIP, and if that fails, we assume it's an XSD. closes odoo/odoo#118933 X-original-commit: 0f1b128a8bcb01ecd5ca8a8db1dfa41230ecadda Signed-off-by: Josse Colpaert --- odoo/tools/xml_utils.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/odoo/tools/xml_utils.py b/odoo/tools/xml_utils.py index 957bcadde2d..be0d5878677 100644 --- a/odoo/tools/xml_utils.py +++ b/odoo/tools/xml_utils.py @@ -6,6 +6,7 @@ import requests import zipfile from io import BytesIO from lxml import etree +import contextlib from odoo.exceptions import UserError @@ -176,11 +177,6 @@ def load_xsd_files_from_url(env, url, file_name=None, force_reload=False, :rtype: odoo.api.ir.attachment | bool :return: every XSD attachment created/fetched or False if an error occurred (see warning logs) """ - if not url.endswith(('.xsd', '.zip')): - _logger.warning("The given URL (%s) needs to lead to an XSD file or a ZIP archive", url) - return False - is_zip = url.endswith('.zip') - try: _logger.info("Fetching file/archive from given URL: %s", url) response = requests.get(url, timeout=request_max_timeout) @@ -199,10 +195,14 @@ def load_xsd_files_from_url(env, url, file_name=None, force_reload=False, if not content: _logger.warning("The HTTP response from %s is empty (no content)", url) return False - if modify_xsd_content and not is_zip: - content = modify_xsd_content(content) - if not is_zip: + archive = None + with contextlib.suppress(zipfile.BadZipFile): + archive = zipfile.ZipFile(BytesIO(content)) + + if archive is None: + if modify_xsd_content: + content = modify_xsd_content(content) if not file_name: file_name = f"{url.split('/')[-1]}" _logger.info("XSD name not provided, defaulting to %s", file_name) @@ -221,8 +221,6 @@ def load_xsd_files_from_url(env, url, file_name=None, force_reload=False, 'public': True, }) - _logger.info("Unzipping loaded archive") - archive = zipfile.ZipFile(BytesIO(content)) saved_attachments = env['ir.attachment'] for file_path in archive.namelist(): if not file_path.endswith('.xsd'):