package org.simantics.history.csv;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
-import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.Format;
i.history = history;
i.label = label!=null?label:"";
i.variableReference = variableReference!=null?variableReference:"";
- i.variableReference = unescape(i.variableReference);
+ i.variableReference = URIs.safeUnescape(i.variableReference);
i.historyItemId = historyItemId;
i.unit = unit;
if ( !items.contains(i) ) items.add( i );
}
- private static String unescape(String url) {
- try {
- return URLDecoder.decode(url, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- return url;
- }
- }
-
/**
* Sort items by variableId, label1, label2
*/
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.history.csv;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.30.0, 1.28.1
+ */
+class URIs {
+
+ public static String safeUnescape(String uri) {
+ try {
+ return unescape(uri);
+ } catch (IllegalArgumentException e) {
+ return uri;
+ }
+ }
+
+ public static String unescape(String uri) {
+ try {
+ if (!needsUnescaping(uri))
+ return uri;
+
+ int len = uri.length();
+ String unicode = uri;
+ char result[] = new char[len];
+ int in = 0;
+ int out = 0;
+ while (in < len) {
+ char inCh = unicode.charAt(in++);
+ if (inCh == '%' && in+1 < len) {
+ char d1 = unicode.charAt(in);
+ char d2 = unicode.charAt(in+1);
+ if (d1 > 127 || d2 > 127)
+ throw new IllegalArgumentException("Invalid hex digit escape sequence in " + uri + " at " + in);
+ result[out++] = (char) (hexDecode(d1) * 16 | hexDecode(d2));
+ in += 2;
+ } else {
+ result[out++] = inCh;
+ }
+ }
+ return new String(result, 0, out);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Problem while unescaping string: " + uri, e);
+ } catch (IndexOutOfBoundsException ee) {
+ throw new IllegalArgumentException("Incomplete hex digit escape sequence in " + uri);
+ }
+ }
+
+ private static boolean needsUnescaping(String s) {
+ int l = s.length();
+ for (int i = -1; i < l;) {
+ i = s.indexOf('%', i+1);
+ if (i < 0)
+ break;
+ if (i+2 < l
+ && isHexDigit(s.charAt(i+1))
+ && isHexDigit(s.charAt(i+2)))
+ return true;
+ }
+ return false;
+ }
+
+ private static int hexDecode(char c) {
+ switch (c) {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ return ((c) & 255) - 'a' + 10;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ return c - 'A' + 10;
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ return c - '0';
+ default:
+ throw new IllegalArgumentException("Bad Hex escape character: " + ((c)&255) );
+ }
+ }
+
+ private static boolean isHexDigit(char c) {
+ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
+ }
+
+// public static void main(String[] args) {
+// System.out.println(unescape("%"));
+// System.out.println(unescape("%.AI"));
+// System.out.println(unescape("%6B"));
+// System.out.println(unescape("%6g"));
+// System.out.println(unescape("%g5"));
+// System.out.println(unescape("%f5"));
+// System.out.println(unescape("%A1"));
+// System.out.println(unescape("%A"));
+// System.out.println(unescape("%A."));
+// System.out.println(unescape("%AI"));
+// }
+
+}