diff --git a/tests/workflow/test_export_to_model.py b/tests/workflow/test_export_to_model.py
index 5bdbfd019..57e7ab2cf 100644
--- a/tests/workflow/test_export_to_model.py
+++ b/tests/workflow/test_export_to_model.py
@@ -4,6 +4,7 @@ import time
import zipfile
import pytest
+from django.utils.encoding import force_bytes
from PIL import Image
from pyzbar.pyzbar import ZBarSymbol
from pyzbar.pyzbar import decode as zbar_decode_qrcode
@@ -299,10 +300,6 @@ def test_export_to_model_django_template(pub):
def test_export_to_model_xml(pub):
- LoggedError = pub.loggederror_class
- if LoggedError:
- LoggedError.wipe()
-
formdef = FormDef()
formdef.name = 'foo-export-to-template-with-django'
formdef.fields = [
@@ -320,9 +317,10 @@ def test_export_to_model_xml(pub):
item.attach_to_history = True
def run(template, filename='/foo/template.xml', content_type='application/xml'):
+ pub.loggederror_class.wipe()
upload = QuixoteUpload(filename, content_type=content_type)
upload.fp = io.BytesIO()
- upload.fp.write(template.encode())
+ upload.fp.write(force_bytes(template))
upload.fp.seek(0)
item.model_file = UploadedFile(pub.app_dir, None, upload)
item.convert_to_pdf = False
@@ -340,18 +338,23 @@ def test_export_to_model_xml(pub):
assert run(template='{{ form_var_string }}', filename='/foo/template.svg') == 'écho'
# unknown file format
- with pytest.raises(UploadValidationError):
+ with pytest.raises(UploadValidationError) as e:
run(
template='{{ form_var_string }}',
filename='/foo/template.txt',
content_type='application/octet-stream',
)
+ assert str(e.value) == 'Only OpenDocument and XML files can be used.'
+
+ # invalid UTF-8
+ with pytest.raises(UploadValidationError) as e:
+ assert run(template=b'test \xE0 {{form_var_string}}') == ''
+ assert str(e.value) == 'XML model files must be UTF-8.'
# malformed XML
- assert not LoggedError or LoggedError.count() == 0
assert run(template='{{ form_var_string }}') == 'écho'
# on error in the XML correctness no exception is raised but an error is logged
- assert not LoggedError or LoggedError.count() == 1
+ assert pub.loggederror_class.count() == 1
@pytest.mark.parametrize('filename', ['template-form-details.odt', 'template-form-details-no-styles.odt'])
diff --git a/wcs/wf/export_to_model.py b/wcs/wf/export_to_model.py
index 0d1248389..e27e561d0 100644
--- a/wcs/wf/export_to_model.py
+++ b/wcs/wf/export_to_model.py
@@ -361,13 +361,18 @@ class ExportToModel(WorkflowStatusItem):
# XML
fp.seek(0)
- xml_prefix = fp.read(1)
+ xml_content = fp.read()
fp.seek(0)
if (upload.content_type and upload.content_type in ('text/xml', 'application/xml')) or (
- upload.base_filename and upload.base_filename.endswith('.xml') and xml_prefix == b'<'
+ upload.base_filename and upload.base_filename.endswith('.xml') and xml_content.startswith(b'<')
):
+ # check XML content is valid UTF-8
+ try:
+ xml_content.decode('utf-8')
+ except UnicodeDecodeError:
+ raise UploadValidationError(_('XML model files must be UTF-8.'))
return 'xml'
- raise UploadValidationError(_('Only OpenDocument and XML files can be used'))
+ raise UploadValidationError(_('Only OpenDocument and XML files can be used.'))
def get_parameters(self):
parameters = ('model_file',)