From e509d7f57f00335e1b157079d46f243495560bd7 Mon Sep 17 00:00:00 2001 From: Tomi Virtanen Date: Fri, 15 Nov 2024 13:00:17 +0200 Subject: [PATCH] fix: fix ServletFileUpload header encoding This change will set ServletFileUpload's header encoding always to UTF-8 in StreamReceiverHandler when request character encoding is null. This ensures that system's default character encoding is not applied when parsing filename of the uploaded file, unless request's character encoding is set otherwise. Only for setups without multipart config for servlet. Fixes: #20417 --- .../communication/StreamReceiverHandler.java | 13 ++++++++- .../StreamReceiverHandlerTest.java | 28 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/flow-server/src/main/java/com/vaadin/flow/server/communication/StreamReceiverHandler.java b/flow-server/src/main/java/com/vaadin/flow/server/communication/StreamReceiverHandler.java index be8c574d559..1f698394fed 100644 --- a/flow-server/src/main/java/com/vaadin/flow/server/communication/StreamReceiverHandler.java +++ b/flow-server/src/main/java/com/vaadin/flow/server/communication/StreamReceiverHandler.java @@ -632,11 +632,22 @@ protected Collection getParts(VaadinRequest request) protected FileItemIterator getItemIterator(VaadinRequest request) throws FileUploadException, IOException { + ServletFileUpload upload = createServletFileUpload(request); + return upload.getItemIterator((HttpServletRequest) request); + } + + // protected for testing purposes only + protected ServletFileUpload createServletFileUpload(VaadinRequest request) { ServletFileUpload upload = new ServletFileUpload(); upload.setSizeMax(requestSizeMax); upload.setFileSizeMax(fileSizeMax); upload.setFileCountMax(fileCountMax); - return upload.getItemIterator((HttpServletRequest) request); + if (request.getCharacterEncoding() == null) { + // Request body's file upload headers are expected to be encoded in + // UTF-8 if not explicitly set otherwise in the request. + upload.setHeaderEncoding(StandardCharsets.UTF_8.name()); + } + return upload; } public void setRequestSizeMax(long requestSizeMax) { diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java index 20569e41bd2..d60b21a0139 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Optional; +import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -95,6 +96,7 @@ public class StreamReceiverHandlerTest { private List parts; private boolean isGetContentLengthLongCalled; + private String requestCharacterEncoding; @Before public void setup() throws Exception { @@ -189,6 +191,11 @@ public long getContentLengthLong() { isGetContentLengthLongCalled = true; return 0; } + + @Override + public String getCharacterEncoding() { + return requestCharacterEncoding; + } }; } @@ -299,6 +306,27 @@ public void doHandleMultipartFileUpload_noPart_uploadFailed_responseStatusIs500_ Assert.assertTrue(isGetContentLengthLongCalled); } + @Test + public void createServletFileUpload_useUTF8HeaderCharacterEncodingWhenRequestCharEncodingIsNotSet() { + ServletFileUpload servletFileUpload = handler + .createServletFileUpload(request); + Assert.assertNotNull(servletFileUpload); + Assert.assertEquals( + "Header encoding should be UTF-8 when request character encoding is null", + "UTF-8", servletFileUpload.getHeaderEncoding()); + } + + @Test + public void createServletFileUpload_dontSetHeaderCharEncodingWhenRequestCharEncodingIsSet() { + requestCharacterEncoding = "ASCII"; + ServletFileUpload servletFileUpload = handler + .createServletFileUpload(request); + Assert.assertNotNull(servletFileUpload); + Assert.assertNull( + "Header encoding should not be set by Flow when request character encoding is set", + servletFileUpload.getHeaderEncoding()); + } + @Test public void doHandleMultipartFileUpload_hasParts_uploadFailed_responseStatusIs500() throws IOException {