diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4c6ac3f758..fe1c78d327 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -17,6 +17,7 @@ Changelog * Simplify generic admin view templates plus ensure `page_title` and `page_subtitle` are used consistently (Matt Westcott) * Extend support for collapsing edit panels from just MultiFieldPanels to all kinds of panels (Fabien Le Frapper, Robbie Mackay) * Add object count to header within modeladmin listing view (Jonathan "Yoni" Knoll) + * Add ability to return HTML in multiple image upload errors (Gordon Pendleton) * Fix: Delete button is now correct colour on snippets and modeladmin listings (Brandon Murch) * Fix: Ensure that StreamBlock / ListBlock-level validation errors are counted towards error counts (Matt Westcott) * Fix: InlinePanel add button is now keyboard navigatable (Jesse Menn) diff --git a/docs/releases/2.15.rst b/docs/releases/2.15.rst index c1a1916ff7..5a15299ae9 100644 --- a/docs/releases/2.15.rst +++ b/docs/releases/2.15.rst @@ -28,6 +28,7 @@ Other features * Simplify generic admin view templates plus ensure ``page_title`` and ``page_subtitle`` are used consistently (Matt Westcott) * Extend support for :ref:`collapsing edit panels ` from just MultiFieldPanels to all kinds of panels (Fabien Le Frapper, Robbie Mackay) * Add object count to header within modeladmin listing view (Jonathan "Yoni" Knoll) + * Add ability to return HTML in multiple image upload errors (Gordon Pendleton) Bug fixes ~~~~~~~~~ diff --git a/wagtail/images/static_src/wagtailimages/js/add-multiple.js b/wagtail/images/static_src/wagtailimages/js/add-multiple.js index 3da27dc15a..183b0f89ff 100644 --- a/wagtail/images/static_src/wagtailimages/js/add-multiple.js +++ b/wagtail/images/static_src/wagtailimages/js/add-multiple.js @@ -59,7 +59,7 @@ $(function() { data.context.each(function(index) { var error = data.files[index].error; if (error) { - $(this).find('.error_messages').text(error); + $(this).find('.error_messages').html(error); } }); } diff --git a/wagtail/images/templates/wagtailimages/multiple/add.html b/wagtail/images/templates/wagtailimages/multiple/add.html index 0595104e4d..f51c06fc66 100644 --- a/wagtail/images/templates/wagtailimages/multiple/add.html +++ b/wagtail/images/templates/wagtailimages/multiple/add.html @@ -107,8 +107,8 @@ accepted_file_types: /\.({{ allowed_extensions|join:"|" }})$/i, //must be regex max_file_size: {{ max_filesize|stringformat:"s"|default:"null" }}, //numeric format errormessages: { - max_file_size: "{{ error_max_file_size }}", - accepted_file_types: "{{ error_accepted_file_types }}" + max_file_size: "{{ error_max_file_size|escapejs }}", + accepted_file_types: "{{ error_accepted_file_types|escapejs }}" } } window.tagit_opts = { diff --git a/wagtail/images/tests/test_admin_views.py b/wagtail/images/tests/test_admin_views.py index 4857007bc4..052743f6a9 100644 --- a/wagtail/images/tests/test_admin_views.py +++ b/wagtail/images/tests/test_admin_views.py @@ -3,9 +3,13 @@ import json from django.contrib.auth.models import Group, Permission from django.core.files.uploadedfile import SimpleUploadedFile from django.template.defaultfilters import filesizeformat -from django.test import TestCase, override_settings +from django.template.loader import render_to_string +from django.test import RequestFactory, TestCase, override_settings from django.urls import reverse +from django.utils.encoding import force_str +from django.utils.html import escapejs from django.utils.http import RFC3986_SUBDELIMS, urlquote +from django.utils.safestring import mark_safe from wagtail.core.models import Collection, GroupCollectionPermission, get_root_collection_id from wagtail.images.models import UploadedImage @@ -1296,7 +1300,7 @@ class TestMultipleImageUploader(TestCase, WagtailTestUtils): This tests the multiple image upload views located in wagtailimages/views/multiple.py """ def setUp(self): - self.login() + self.user = self.login() # Create an image for running tests on self.image = Image.objects.create( @@ -1329,6 +1333,54 @@ class TestMultipleImageUploader(TestCase, WagtailTestUtils): response.context['error_max_file_size'], "This file is too big. Maximum filesize 1000\xa0bytes." ) + def test_add_error_max_file_size_escaped(self): + url = reverse('wagtailimages:add_multiple') + template_name = 'wagtailimages/multiple/add.html' + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, template_name) + + value = "Too big.

Try this." + response_content = force_str(response.content) + self.assertNotIn(value, response_content) + self.assertNotIn(escapejs(value), response_content) + + request = RequestFactory().get(url) + request.user = self.user + context = response.context_data.copy() + context['error_max_file_size'] = mark_safe(force_str(value)) + data = render_to_string( + template_name, + context=context, + request=request, + ) + self.assertNotIn(value, data) + self.assertIn(escapejs(value), data) + + def test_add_error_accepted_file_types_escaped(self): + url = reverse('wagtailimages:add_multiple') + template_name = 'wagtailimages/multiple/add.html' + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, template_name) + + value = "Invalid image type. Get help." + response_content = force_str(response.content) + self.assertNotIn(value, response_content) + self.assertNotIn(escapejs(value), response_content) + + request = RequestFactory().get(url) + request.user = self.user + context = response.context_data.copy() + context['error_accepted_file_types'] = mark_safe(force_str(value)) + data = render_to_string( + template_name, + context=context, + request=request, + ) + self.assertNotIn(value, data) + self.assertIn(escapejs(value), data) + def test_add_post(self): """ This tests that a POST request to the add view saves the image and returns an edit form