diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java index d77d68fc5868ffcccc6e948e73fc72b250dd4723..14763b6b56ba64d0fdf9bcc4e3968be80d7121da 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java @@ -162,8 +162,8 @@ public class FileElementImpl extends FormItemImpl } uploadFilename = form.getRequestMultipartFileName(component.getFormDispatchId()); - // prevent an issue with Firefox - uploadFilename = FileUtils.normalizeFilenameWithSuffix(uploadFilename); + // prevent an issue with different operation systems and . + uploadFilename = FileUtils.cleanFilename(uploadFilename); // use mime-type from file name to have deterministic mime types uploadMimeType = WebappHelper.getMimeType(uploadFilename); if (uploadMimeType == null) { diff --git a/src/main/java/org/olat/core/util/FileUtils.java b/src/main/java/org/olat/core/util/FileUtils.java index 00e65b8c823d13610d4657908ffc46011a8587a7..62a71d5060545fa0e36729d7040b83f42a88d2d0 100644 --- a/src/main/java/org/olat/core/util/FileUtils.java +++ b/src/main/java/org/olat/core/util/FileUtils.java @@ -75,8 +75,9 @@ public class FileUtils { //windows: invalid characters for filenames: \ / : * ? " < > | //linux: invalid characters for file/folder names: /, but you have to escape certain chars, like ";$%&*" + //zip: may cause errors: = //OLAT reserved char: ":" - public static char[] FILE_NAME_FORBIDDEN_CHARS = { '/', '\n', '\r', '\t', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':', ',' }; + public static char[] FILE_NAME_FORBIDDEN_CHARS = { '/', '\n', '\r', '\t', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':', ',', '=' }; //private static char[] FILE_NAME_ACCEPTED_CHARS = { 'ä', 'Ä', 'ü', 'Ü', 'ö', 'Ö', ' '}; public static char[] FILE_NAME_ACCEPTED_CHARS = { '\u0228', '\u0196', '\u0252', '\u0220', '\u0246', '\u0214', ' '}; // known metadata files @@ -893,7 +894,15 @@ public class FileUtils { return nameSanitized; } - public static String normalizeFilenameWithSuffix(String filename) { + /** + * Cleans the filename from invalid character to make a filename compatible for + * the usual operating systems and browsers.. Suffixes are preserved. This + * method is not as strict as {@link #normalizeFilename(String)}. + * + * @param filename + * @return the cleaned filename + */ + public static String cleanFilename(String filename) { boolean hasExtension = false; String name = filename; String extension = getFileSuffix(filename); @@ -902,14 +911,23 @@ public class FileUtils { name = filename.substring(0, filename.length() - extension.length() - 1); } StringBuilder normalizedFilename = new StringBuilder(); - normalizedFilename.append(normalizeFilename(name)); + normalizedFilename.append(cleanFilenamePart(name)); if (hasExtension) { normalizedFilename.append("."); - normalizedFilename.append(normalizeFilename(extension)); + normalizedFilename.append(cleanFilenamePart(extension)); } return normalizedFilename.toString(); } + private static String cleanFilenamePart(String filename) { + String cleaned = Normalizer.normalize(filename, Normalizer.Form.NFKD); + cleaned = cleaned.replaceAll("\\p{InCombiningDiacriticalMarks}+",""); + for (char character: FILE_NAME_FORBIDDEN_CHARS) { + cleaned = cleaned.replace(character, '_'); + } + return cleaned; + } + /** * Creates a new directory in the specified directory, using the given prefix and suffix strings to generate its name. * It uses File.createTempFile() and should provide a unique name. diff --git a/src/test/java/org/olat/core/util/FileUtilsTest.java b/src/test/java/org/olat/core/util/FileUtilsTest.java index 2c193d28265b97616c906c47e258925a8acaff86..a0dcf57264e46aef50b24892f637f00a3f60f93e 100644 --- a/src/test/java/org/olat/core/util/FileUtilsTest.java +++ b/src/test/java/org/olat/core/util/FileUtilsTest.java @@ -37,7 +37,6 @@ public class FileUtilsTest { String normalizedAccents = FileUtils.normalizeFilename("Dépéchons-nous!"); Assert.assertEquals(normalizedAccents, "Depechonsnous"); - } @Test @@ -46,7 +45,32 @@ public class FileUtilsTest { String normalized = FileUtils.normalizeFilename(smorrebrod); Assert.assertEquals(normalized, "Smorrebrod"); } + + @Test + public void cleanedFilename() { + assertCleanedFilename("test.xml", "test.xml"); + assertCleanedFilename("abc/abc", "abc_abc"); + assertCleanedFilename("abc\\abc", "abc_abc"); + assertCleanedFilename("qwe\nqwe", "qwe_qwe"); + assertCleanedFilename("wer\rwer", "wer_wer"); + assertCleanedFilename("ert\tert", "ert_ert"); + assertCleanedFilename("rtz\frtz", "rtz_rtz"); + assertCleanedFilename("tzu'tzu", "tzu'tzu"); + assertCleanedFilename("zui?zui", "zui_zui"); + assertCleanedFilename("uio*uio", "uio_uio"); + assertCleanedFilename("asd<asd", "asd_asd"); + assertCleanedFilename("sdf>sdf", "sdf_sdf"); + assertCleanedFilename("dfg|dfg", "dfg_dfg"); + assertCleanedFilename("fgh\"fgh", "fgh_fgh"); + assertCleanedFilename("fgh:ghj", "fgh_ghj"); + assertCleanedFilename("fgh,ghj", "fgh_ghj"); + assertCleanedFilename("fgh=ghj", "fgh_ghj"); + } + private void assertCleanedFilename(String raw, String expected) { + String cleaned = FileUtils.cleanFilename(raw); + Assert.assertEquals(expected, cleaned); + } @Test public void testMetaFiles() { @@ -64,7 +88,6 @@ public class FileUtilsTest { Assert.assertTrue(FileUtils.isMetaFilename("._")); Assert.assertTrue(FileUtils.isMetaFilename("._gugus")); - } }