From: Tuukka Lehtonen Date: Wed, 14 Jun 2017 16:22:30 +0000 (+0300) Subject: Added URIUtil.encodeFilename2 which encodes only necessary characters. X-Git-Tag: v1.31.0~321 X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=75809ec96a58c23cc89131637fbc65435ac482af Added URIUtil.encodeFilename2 which encodes only necessary characters. The new method uses the same '%' URI style encoding as URIUtil.encodeFilename but encodes only characters that cannot be present in Windows file names, i.e. the following: <>:"/\|?* This method can be used to convert arbitrary user-given names to valid file names in wizards etc. refs #7301 Change-Id: Ia7e264e5304ff0533376c73f5ae9312e197ccf15 --- diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/URIUtil.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/URIUtil.java index b1e5b8ec4..0bfc3b1b1 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/URIUtil.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/URIUtil.java @@ -221,5 +221,72 @@ public final class URIUtil { public static String decodeIdentifier(String str) { return decode(str.getBytes(), (byte) '$', true); } - + + /** + * Escape any of the following characters: <>:"/\|?* with %nn. + * + * @param str a file name, not a full file path + * @return original string or escaped file name if encoding is needed + */ + public static String encodeFilename2(String str) { + return encodeFilename2(str, '%'); + } + + private static String encodeFilename2(String str, char escapeChar) { + // First calculate the length + int originalLength = str.length(); + int length = originalLength; + for (int i = 0; i < originalLength; ++i) { + char c = str.charAt(i); + if (c < 128 && fileNameEncodeTable[(int) c] == -1) + length += 2; + } + + if (length == originalLength) + return str; + + char[] result = new char[length]; + int pos = 0; + for (int i = 0; i < originalLength; ++i) { + char c = str.charAt(i); + int ic = c; + if (c >= 128) { + // Never escape any non-ASCII characters. Those should work. + result[pos++] = c; + } else { + int ec = fileNameEncodeTable[ic]; + if (ec >= 0) { + result[pos++] = (char) ec; + } else { + result[pos++] = escapeChar; + result[pos++] = Character.forDigit(ic >> 4, 16); + result[pos++] = Character.forDigit(ic & 15, 16); + } + } + } + return new String(result); + } + + static final int[] fileNameEncodeTable = new int[128]; // for UTF-16 non-bijection filenames + + static { + for (int i = 0; i < fileNameEncodeTable.length; ++i) { + if (i < 32) { + // Control characters are all in need of escapes + fileNameEncodeTable[i] = -1; + } else { + switch ((char) i) { + // Denied characters in windows file names + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx + case '<': case '>': case ':': case '"': case '/': case '\\': case '|': case '?': case '*': + fileNameEncodeTable[i] = -1; + break; + default: + fileNameEncodeTable[i] = i; + break; + } + } + } + } + }