[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 <jco@odoo.com>
This commit is contained in:
Antoine Dupuis (andu)
2023-04-18 19:29:08 +02:00
parent ac93d84388
commit 33a9db123a
+8 -10
View File
@@ -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'):