diff --git a/src/main/java/org/olat/core/commons/modules/bc/components/CrumbRenderer.java b/src/main/java/org/olat/core/commons/modules/bc/components/CrumbRenderer.java index f7a4e2bfc326aaaef6839ee049ff1c3d44ba40ab..c9dc843954e04bba2a4540bf5c5cbea684782bfc 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/components/CrumbRenderer.java +++ b/src/main/java/org/olat/core/commons/modules/bc/components/CrumbRenderer.java @@ -31,7 +31,6 @@ import java.util.StringTokenizer; import org.olat.core.gui.control.winmgr.AJAXFlags; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.render.URLBuilder; -import org.olat.core.util.StringHelper; /** * Initial Date: 08.07.2003 @@ -72,7 +71,7 @@ public class CrumbRenderer { StringTokenizer st = new StringTokenizer(fc.getCurrentContainerPath(), "/", false); while (st.hasMoreElements()) { String token = st.nextToken(); - pathLink.append(StringHelper.urlEncodeUTF8(token)); + pathLink.append(ubu.encodeUrl(token)); sb.append(" / "); if (st.hasMoreElements() && renderLinks) { sb.append("<a href=\""); diff --git a/src/main/java/org/olat/core/gui/media/FileMediaResource.java b/src/main/java/org/olat/core/gui/media/FileMediaResource.java index 860d8f93660a02dcc4f6d894b46da482600cac33..4ffb9fc521edaf98771dbd75e5639ffb5e17dc9c 100644 --- a/src/main/java/org/olat/core/gui/media/FileMediaResource.java +++ b/src/main/java/org/olat/core/gui/media/FileMediaResource.java @@ -141,8 +141,8 @@ public class FileMediaResource implements MediaResource { if (deliverAsAttachment) { // encode filename in ISO8859-1; does not really help but prevents from filename not being displayed at all // if it contains non-US-ASCII characters which are not allowed in header fields. - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file.getName()) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(file.getName())); + hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(file.getName())); + hres.setHeader("Content-Description",StringHelper.urlEncodeUTF8(file.getName())); } else { hres.setHeader("Content-Disposition", "inline"); } diff --git a/src/main/java/org/olat/core/gui/media/NamedFileMediaResource.java b/src/main/java/org/olat/core/gui/media/NamedFileMediaResource.java index 454752eca4aa820c39c1087abe95a61cf2121303..1d3f80b99350c9a687e71909fcf9f2066586ea0e 100644 --- a/src/main/java/org/olat/core/gui/media/NamedFileMediaResource.java +++ b/src/main/java/org/olat/core/gui/media/NamedFileMediaResource.java @@ -84,8 +84,8 @@ public class NamedFileMediaResource extends FileMediaResource { public void prepare(HttpServletResponse hres) { // encode filename in ISO8859-1; does not really help but prevents from filename not being displayed at all // if it contains non-US-ASCII characters which are not allowed in header fields. - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(fileName) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(fileDescription)); + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(fileName)); + hres.setHeader("Content-Description", StringHelper.urlEncodeUTF8(fileDescription)); } diff --git a/src/main/java/org/olat/core/gui/render/URLBuilder.java b/src/main/java/org/olat/core/gui/render/URLBuilder.java index eecfa312eb0550cc0abea69dd2a73ade6de2b23a..38a8abea9d1396d7ff969ea3f677f92efb2f72cd 100644 --- a/src/main/java/org/olat/core/gui/render/URLBuilder.java +++ b/src/main/java/org/olat/core/gui/render/URLBuilder.java @@ -26,18 +26,25 @@ package org.olat.core.gui.render; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.regex.Pattern; + import org.olat.core.gui.GUIInterna; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.control.winmgr.AJAXFlags; import org.olat.core.gui.control.winmgr.WindowBackOfficeImpl; -import org.olat.core.util.StringHelper; +import org.olat.core.logging.AssertException; /** * * @author Felix Jost */ public class URLBuilder { + + private static final Pattern p1 = Pattern.compile("\\+"); + private static final Pattern p2 = Pattern.compile("%2F"); private final String uriPrefix; @@ -135,16 +142,6 @@ public class URLBuilder { else buf.append(quote); } - - /*public boolean isAjaxOn() { - return true; - }*/ - - /*public void buildNonAjaxURI(StringOutput buf, String[] keys, String[] values, String modURI) { - buildURI(buf, keys, values, modURI, AJAXFlags.MODE_TOBGIFRAME); - }*/ - - /** * builds an uri. neither key nor values may contain the character * UserRequest.PARAM_DELIM which is a ":" (colon). in case you think you @@ -184,7 +181,7 @@ public class URLBuilder { result.append('/'); if (modURI != null) result.append(modURI); //FIXME:fj:a urlEncodeUTF8 is slow; improve the regexp, also convert only the modURI to utf-8? - buf.append(StringHelper.urlEncodeUTF8(result.toString())); + buf.append(encodeUrl(result.toString())); } public void buildURI(StringOutput buf, String[] keys, String[] values, String modURI) { @@ -244,6 +241,27 @@ public class URLBuilder { */ return result; } + + /** + * @param url + * @return encoded string + */ + public String encodeUrl(String url) { + String encodedURL; + try { + encodedURL = URLEncoder.encode(url, "UTF-8"); + } catch (UnsupportedEncodingException e) { + /* + * from java.nio.Charset Standard charsets Every implementation of the + * Java platform is required to support the following standard charsets... + * ... UTF-8 Eight-bit UCS Transformation Format ... + */ + throw new AssertException("utf-8 encoding is needed for proper encoding, but not offered on this java platform????"); + } + encodedURL = p1.matcher(encodedURL).replaceAll("%20"); + encodedURL = p2.matcher(encodedURL).replaceAll("/"); + return encodedURL; + } /** * used for OLAT-1973 only: if in replayable-url-mode for performance testing diff --git a/src/main/java/org/olat/core/util/StringHelper.java b/src/main/java/org/olat/core/util/StringHelper.java index 2e65edb4d67b4e862192be4bfafdf97ce02cc19e..c3bc38653ca141c035a8974bba89f464209362bf 100644 --- a/src/main/java/org/olat/core/util/StringHelper.java +++ b/src/main/java/org/olat/core/util/StringHelper.java @@ -68,9 +68,6 @@ public class StringHelper { private static final String WHITESPACE_REGEXP = "^\\s*$"; private static final Pattern WHITESPACE_PATTERN = Pattern.compile(WHITESPACE_REGEXP); - private static final Pattern p1 = Pattern.compile("\\+"); - private static final Pattern p2 = Pattern.compile("%2F"); - /** * regex for not allowing * <code>;,:</code> <code>ALL_WITHOUT_COMMA_2POINT_STRPNT</code> @@ -194,21 +191,7 @@ public class StringHelper { numFormatter.setMaximumFractionDigits(fractionDigits); return numFormatter.format(f); } - - /** - * @param url - * @return encoded string - */ - public static String urlEncodeISO88591(String url) { - String part; - try { - part = URLEncoder.encode(url, "iso-8859-1"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("encoding failed (iso-8859-1) for :" + url); - } - return part; - } - + /** * @param url * @return encoded string @@ -225,13 +208,8 @@ public class StringHelper { */ throw new AssertException("utf-8 encoding is needed for proper encoding, but not offered on this java platform????"); } - encodedURL = p1.matcher(encodedURL).replaceAll("%20"); - encodedURL = p2.matcher(encodedURL).replaceAll("/"); return encodedURL; } - - - /** * Converts all keys of a hash map to a string array. diff --git a/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java b/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java index 1bd5932b0eeb4c0fd6c6f87878f2249afc1a0bed..9a1ebec95bb8a1b5ed5b4cc22cf8b45518561d01 100644 --- a/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java +++ b/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java @@ -27,14 +27,13 @@ package org.olat.core.util.vfs; import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import javax.servlet.http.HttpServletResponse; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.FilesInfoMBean; import org.olat.core.gui.media.MediaResource; +import org.olat.core.util.StringHelper; import org.olat.core.util.WebappHelper; public class VFSMediaResource implements MediaResource { @@ -93,15 +92,12 @@ public class VFSMediaResource implements MediaResource { * @see org.olat.core.gui.media.MediaResource#prepare(javax.servlet.http.HttpServletResponse) */ public void prepare(HttpServletResponse hres) { - //http headers are ASCII only therefore we encode filenames - String filename = ""; - try { - filename = URLEncoder.encode(vfsLeaf.getName(), "utf-8"); - } catch (UnsupportedEncodingException wontHappen) { - //nothing}; + String filename = StringHelper.urlEncodeUTF8(vfsLeaf.getName()); + if (unknownMimeType) { + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + filename); + } else { + hres.setHeader("Content-Disposition", "filename*=UTF-8''" + filename); } - if (unknownMimeType) hres.setHeader("Content-Disposition", "attachment; filename=" + filename); - else hres.setHeader("Content-Disposition", "filename=" + filename); } public void release() { diff --git a/src/main/java/org/olat/core/util/vfs/VFSRevisionMediaResource.java b/src/main/java/org/olat/core/util/vfs/VFSRevisionMediaResource.java index f172b7056d7314170e1a0bb3fe22a20673fa542a..b34b382ecab58e727f923670da27026348ae08c4 100644 --- a/src/main/java/org/olat/core/util/vfs/VFSRevisionMediaResource.java +++ b/src/main/java/org/olat/core/util/vfs/VFSRevisionMediaResource.java @@ -20,12 +20,11 @@ package org.olat.core.util.vfs; import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import javax.servlet.http.HttpServletResponse; import org.olat.core.gui.media.MediaResource; +import org.olat.core.util.StringHelper; import org.olat.core.util.WebappHelper; import org.olat.core.util.vfs.version.VFSRevision; @@ -77,16 +76,12 @@ public class VFSRevisionMediaResource implements MediaResource { } public void prepare(HttpServletResponse hres) { - String filename = ""; - try { - filename = URLEncoder.encode(revision.getName(), "utf-8"); - } catch (UnsupportedEncodingException wontHappen) { - //nothing + String filename = StringHelper.urlEncodeUTF8(revision.getName()); + if (forceDownload || unknownMimeType) { + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + filename); + } else { + hres.setHeader("Content-Disposition", "filename*=UTF-8''" + filename); } - if (forceDownload || unknownMimeType) - hres.setHeader("Content-Disposition", "attachment; filename=" + filename); - else - hres.setHeader("Content-Disposition", "filename=" + filename); } public void release() { diff --git a/src/main/java/org/olat/course/archiver/ArchiveResource.java b/src/main/java/org/olat/course/archiver/ArchiveResource.java index afd4f5998fc5d7fe928e45ce2e4eb0cc8cec931d..5f0249100335ade32b3fab363fca3f6da20f92e7 100644 --- a/src/main/java/org/olat/course/archiver/ArchiveResource.java +++ b/src/main/java/org/olat/course/archiver/ArchiveResource.java @@ -93,8 +93,8 @@ public class ArchiveResource implements MediaResource { + StringHelper.transformDisplayNameToFileSystemName(courseNode.getShortName()) + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())) + ".zip"; - String urlEncodedLabel = StringHelper.urlEncodeISO88591(label); - hres.setHeader("Content-Disposition","attachment; filename=\"" + urlEncodedLabel + "\""); + String urlEncodedLabel = StringHelper.urlEncodeUTF8(label); + hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + urlEncodedLabel); hres.setHeader("Content-Description", urlEncodedLabel); ZipOutputStream zout = null; diff --git a/src/main/java/org/olat/course/db/CourseDBMediaResource.java b/src/main/java/org/olat/course/db/CourseDBMediaResource.java index 4ad40aefc5ddc12f9affa900048aa426a9fe866c..45e0c3fbda52841098de521bd91f56bd157fd9c1 100644 --- a/src/main/java/org/olat/course/db/CourseDBMediaResource.java +++ b/src/main/java/org/olat/course/db/CourseDBMediaResource.java @@ -70,8 +70,9 @@ public class CourseDBMediaResource implements MediaResource { @Override public void prepare(HttpServletResponse hres) { - hres.setHeader("Content-Disposition","filename=\"" + StringHelper.urlEncodeISO88591(fileName) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(fileName)); + String encodedFileName = StringHelper.urlEncodeUTF8(fileName); + hres.setHeader("Content-Disposition","filename*=UTF-8''" + encodedFileName); + hres.setHeader("Content-Description",encodedFileName); } diff --git a/src/main/java/org/olat/ims/qti/export/QTIWordExport.java b/src/main/java/org/olat/ims/qti/export/QTIWordExport.java index d60379bce2fab487c03c365408731436ef6a65aa..9e2eddccaa309552d6da423c5fb90883149de4d9 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIWordExport.java +++ b/src/main/java/org/olat/ims/qti/export/QTIWordExport.java @@ -122,8 +122,8 @@ public class QTIWordExport implements MediaResource { String secureLabel = StringHelper.transformDisplayNameToFileSystemName(label); String file = secureLabel + ".zip"; - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(label)); + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(file)); + hres.setHeader("Content-Description", StringHelper.urlEncodeUTF8(label)); zout = new ZipOutputStream(hres.getOutputStream()); zout.setLevel(9); diff --git a/src/main/java/org/olat/ims/qti/qpool/QTIPoolWordExport.java b/src/main/java/org/olat/ims/qti/qpool/QTIPoolWordExport.java index c47cbb6a0fa45d26bd24d44e6c782868fefebcf0..fdc91bb8ee24cd5c1c720c8a7b8f419933978b61 100644 --- a/src/main/java/org/olat/ims/qti/qpool/QTIPoolWordExport.java +++ b/src/main/java/org/olat/ims/qti/qpool/QTIPoolWordExport.java @@ -122,8 +122,8 @@ class QTIPoolWordExport implements MediaResource { List<QuestionItemFull> fullItems = questionItemDao.loadByIds(itemKeys); String file = secureLabel + ".zip"; - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(label)); + hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(file)); + hres.setHeader("Content-Description", StringHelper.urlEncodeUTF8(label)); zout = new ZipOutputStream(hres.getOutputStream()); zout.setLevel(9); diff --git a/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java b/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java index dd433c7bf672d1433282dbeb3396ebcd99cdeb2d..195ead4bc34ccbe5a642769149fc2bfb11e57ef7 100644 --- a/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java +++ b/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java @@ -85,8 +85,8 @@ public abstract class AbstractExportTestResource implements MediaResource { String label = "Test"; String file = StringHelper.transformDisplayNameToFileSystemName(label) + ".zip"; - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(label)); + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(file)); + hres.setHeader("Content-Description", StringHelper.urlEncodeUTF8(label)); ZipOutputStream zout = null; try { diff --git a/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java b/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java index 540d0b32e98a5caf52e5a76d9c671132333b4679..654e814424f5d3d4a6f98f6e8166e46ba30465df 100644 --- a/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java +++ b/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java @@ -84,8 +84,9 @@ public class ExportQItemResource implements MediaResource { String label = item.getTitle(); String file = StringHelper.transformDisplayNameToFileSystemName(label) + ".zip"; - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(label)); + String encodedFileName = StringHelper.urlEncodeUTF8(file); + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName); + hres.setHeader("Content-Description", encodedFileName); ZipOutputStream zout = null; try { diff --git a/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java b/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java index 51f3fd1cf6a6f3c0c4943bf5556f74e209ae2376..df8c1cbc668ae6495f6ebebc3926841ec290edc1 100644 --- a/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java +++ b/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java @@ -85,8 +85,9 @@ public class ExportQItemsZipResource implements MediaResource { String label = "ExportItems"; String file = StringHelper.transformDisplayNameToFileSystemName(label) + ".zip"; - hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file) + "\""); - hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(label)); + String encodedFileName = StringHelper.urlEncodeUTF8(file); + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName); + hres.setHeader("Content-Description", encodedFileName); ZipOutputStream zout = null; try {