diff options
author | Sauli Tähkäpää <sauli@vaadin.com> | 2015-02-03 15:02:45 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2015-02-13 10:51:12 +0000 |
commit | af6dd56e89db8ea8c88f607c4214abcde50dfc94 (patch) | |
tree | ee6cf0625f444c23e7ab05383b38e4a759803fba /server | |
parent | 93ab31a485730394018ac7358f3fb00b258037ad (diff) | |
download | vaadin-framework-af6dd56e89db8ea8c88f607c4214abcde50dfc94.tar.gz vaadin-framework-af6dd56e89db8ea8c88f607c4214abcde50dfc94.zip |
Encode filenames to UTF-8 in Content-Disposition header. (#16556)
Change-Id: Ie2cf41f2176d05105663cdb84934379efa826f03
Diffstat (limited to 'server')
-rw-r--r-- | server/src/com/vaadin/server/DownloadStream.java | 30 | ||||
-rw-r--r-- | server/src/com/vaadin/server/FileDownloader.java | 6 | ||||
-rw-r--r-- | server/tests/src/com/vaadin/server/FileDownloaderTests.java | 41 |
3 files changed, 61 insertions, 16 deletions
diff --git a/server/src/com/vaadin/server/DownloadStream.java b/server/src/com/vaadin/server/DownloadStream.java index 681c438967..8b2b933bcc 100644 --- a/server/src/com/vaadin/server/DownloadStream.java +++ b/server/src/com/vaadin/server/DownloadStream.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -280,16 +282,9 @@ public class DownloadStream implements Serializable { } } - // suggest local filename from DownloadStream if - // Content-Disposition - // not explicitly set - String contentDispositionValue = getParameter("Content-Disposition"); - if (contentDispositionValue == null) { - contentDispositionValue = "filename=\"" + getFileName() - + "\""; - response.setHeader("Content-Disposition", - contentDispositionValue); - } + // Content-Disposition: attachment generally forces download + response.setHeader("Content-Disposition", + getContentDispositionValue()); int bufferSize = getBufferSize(); if (bufferSize <= 0 || bufferSize > Constants.MAX_BUFFER_SIZE) { @@ -317,6 +312,21 @@ public class DownloadStream implements Serializable { } } + private String getContentDispositionValue() + throws UnsupportedEncodingException { + String contentDispositionValue = getParameter("Content-Disposition"); + + if (contentDispositionValue == null) { + String encodedFilename = URLEncoder.encode(getFileName(), "utf-8"); + + contentDispositionValue = String.format( + "attachment; filename=\"%s\"; filename*=utf-8''%s", + encodedFilename, encodedFilename); + } + + return contentDispositionValue; + } + /** * Helper method that tries to close an output stream and ignores any * exceptions. diff --git a/server/src/com/vaadin/server/FileDownloader.java b/server/src/com/vaadin/server/FileDownloader.java index 42c2f76e1a..bea9922c50 100644 --- a/server/src/com/vaadin/server/FileDownloader.java +++ b/server/src/com/vaadin/server/FileDownloader.java @@ -141,12 +141,6 @@ public class FileDownloader extends AbstractExtension { } stream = ((ConnectorResource) resource).getStream(); - if (stream.getParameter("Content-Disposition") == null) { - // Content-Disposition: attachment generally forces download - stream.setParameter("Content-Disposition", - "attachment; filename=\"" + stream.getFileName() + "\""); - } - // Content-Type to block eager browser plug-ins from hijacking // the file if (isOverrideContentType()) { diff --git a/server/tests/src/com/vaadin/server/FileDownloaderTests.java b/server/tests/src/com/vaadin/server/FileDownloaderTests.java new file mode 100644 index 0000000000..4e9478c570 --- /dev/null +++ b/server/tests/src/com/vaadin/server/FileDownloaderTests.java @@ -0,0 +1,41 @@ +package com.vaadin.server; + +import static org.mockito.Matchers.contains; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; + +import org.junit.Before; +import org.junit.Test; + +public class FileDownloaderTests { + private String filename = "日本語.png"; + private DownloadStream stream; + + @Before + public void setup() { + stream = new DownloadStream(mock(InputStream.class), "", filename); + } + + @Test + public void contentDispositionFilenameIsUtf8Encoded() throws IOException { + VaadinResponse response = mock(VaadinResponse.class); + + stream.writeResponse(mock(VaadinRequest.class), response); + + verify(response).setHeader(eq("Content-Disposition"), + contains("attachment;")); + String encodedFileName = URLEncoder.encode(filename, "utf-8"); + verify(response).setHeader(eq("Content-Disposition"), + contains(String.format("filename=\"%s\";", encodedFileName))); + verify(response) + .setHeader( + eq("Content-Disposition"), + contains(String.format("filename*=utf-8''%s", + encodedFileName))); + } +} |