changeset 360:01ed07070c3c

Fixed behavior when encoded/characters needed encoding included in url (PR811)
author Jiri Vanek <jvanek@redhat.com>
date Tue, 03 Jul 2012 13:38:23 +0200
parents a49edd57b1b3
children d5cec52b3c5b
files ChangeLog NEWS netx/net/sourceforge/jnlp/cache/CacheUtil.java netx/net/sourceforge/jnlp/cache/ResourceTracker.java
diffstat 4 files changed, 172 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jun 28 12:00:07 2012 -0400
+++ b/ChangeLog	Tue Jul 03 13:38:23 2012 +0200
@@ -1,3 +1,17 @@
+2012-05-18  Jiri Vanek  <jvanek@redhat.com>
+
+	Fixed behavior when encoded/characters needed encoding included in url
+	* NEWS: mentioned PR811
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java: (urlEquals) Enhanced
+	to be able compare encoded/decoded urls correctly.
+	(notNullUrlEquals) new method to separate comparing of individual parts of
+	url from null checks
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java: (addResource)
+	is now encoding url if needed. (normalizeUrl) new method to encode path in
+	url of all except file protocol. (normalizeChunk) New method for encoding
+	of atomic piece.
+
+
 2012-06-28  Adam Domurad  <adomurad@redhat.com>
 
 	Allow passing of plugin tables and browser tables in NP_Initialize that
--- a/NEWS	Thu Jun 28 12:00:07 2012 -0400
+++ b/NEWS	Tue Jul 03 13:38:23 2012 +0200
@@ -11,6 +11,7 @@
 New in release 1.2.1 (2012-XX-XX):
 * NetX
   - PR898: signed applications with big jnlp-file doesn't start (webstart affect like "frozen")
+  - PR811: javaws is not handling urls with spaces (and other characters needing encoding) correctly
 * Plugin
   - PR863: Error passing strings to applet methods in Chromium
   - PR895: IcedTea-Web searches for missing classes on each loadClass or findClass
--- a/netx/net/sourceforge/jnlp/cache/CacheUtil.java	Thu Jun 28 12:00:07 2012 -0400
+++ b/netx/net/sourceforge/jnlp/cache/CacheUtil.java	Tue Jul 03 13:38:23 2012 +0200
@@ -61,22 +61,40 @@
      * ie sourceforge.net and www.sourceforge.net).
      */
     public static boolean urlEquals(URL u1, URL u2) {
-        if (u1 == u2)
+        if (u1 == u2) {
             return true;
-        if (u1 == null || u2 == null)
+        }
+        if (u1 == null || u2 == null) {
             return false;
+        }
 
-        if (!compare(u1.getProtocol(), u2.getProtocol(), true) ||
-                !compare(u1.getHost(), u2.getHost(), true) ||
-                //u1.getDefaultPort() != u2.getDefaultPort() || // only in 1.4
-                !compare(u1.getPath(), u2.getPath(), false) ||
-                !compare(u1.getQuery(), u2.getQuery(), false) ||
-                !compare(u1.getRef(), u2.getRef(), false))
-            return false;
-        else
+        if (notNullUrlEquals(u1, u2)) {
             return true;
+        }
+        try {
+            URL nu1 = ResourceTracker.normalizeUrl(u1, false);
+            URL nu2 = ResourceTracker.normalizeUrl(u2, false);
+            if (notNullUrlEquals(nu1, nu2)) {
+                return true;
+            }
+        } catch (Exception ex) {
+            //keep silent here and return false
+        }
+        return false;
     }
 
+    private static boolean notNullUrlEquals(URL u1, URL u2) {
+        if (!compare(u1.getProtocol(), u2.getProtocol(), true)
+                || !compare(u1.getHost(), u2.getHost(), true)
+                || //u1.getDefaultPort() != u2.getDefaultPort() || // only in 1.4
+                !compare(u1.getPath(), u2.getPath(), false)
+                || !compare(u1.getQuery(), u2.getQuery(), false)
+                || !compare(u1.getRef(), u2.getRef(), false)) {
+            return false;
+        } else {
+            return true;
+        }
+    }
     /**
      * Caches a resource and returns a URL for it in the cache;
      * blocks until resource is cached.  If the resource location is
--- a/netx/net/sourceforge/jnlp/cache/ResourceTracker.java	Thu Jun 28 12:00:07 2012 -0400
+++ b/netx/net/sourceforge/jnlp/cache/ResourceTracker.java	Tue Jul 03 13:38:23 2012 +0200
@@ -24,10 +24,13 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
@@ -108,6 +111,15 @@
     private static final int ERROR = Resource.ERROR;
     private static final int STARTED = Resource.STARTED;
 
+    // normalization of url
+    private static final char PATH_DELIMITER_MARK = '/';
+    private static final String PATH_DELIMITER = "" + PATH_DELIMITER_MARK;
+    private static final char QUERY_DELIMITER_MARK = '&';
+    private static final String QUERY_DELIMITER = "" + QUERY_DELIMITER_MARK;
+    private static final char QUERY_MARK = '?';
+    private static final char HREF_MARK = '#';
+    private static final String UTF8 = "utf-8";
+
     /** max threads */
     private static final int maxThreads = 5;
 
@@ -173,7 +185,12 @@
     public void addResource(URL location, Version version, DownloadOptions options, UpdatePolicy updatePolicy) {
         if (location == null)
             throw new IllegalArgumentException("location==null");
-
+        try {
+            location = normalizeUrl(location, JNLPRuntime.isDebug());
+        } catch (Exception ex) {
+            System.err.println("Normalization of " + location.toString() + " have failed");
+            ex.printStackTrace();
+        }
         Resource resource = Resource.getResource(location, version, updatePolicy);
         boolean downloaded = false;
 
@@ -1127,4 +1144,115 @@
         }
     };
 
+    private static String normalizeChunk(String base, boolean debug) throws UnsupportedEncodingException {
+        if (base == null) {
+            return base;
+        }
+        if ("".equals(base)) {
+            return base;
+        }
+        String result = base;
+        String ssE = URLDecoder.decode(base, UTF8);
+        //            System.out.println("*" + base + "*");
+        //            System.out.println("-" + ssE + "-");
+        if (base.equals(ssE)) {
+            result = URLEncoder.encode(base, UTF8);
+            if (debug) {
+                System.out.println(base + " chunk needs to be encoded => " + result);
+            }
+        } else {
+            if (debug) {
+                System.out.println(base + " chunk already encoded");
+            }
+        }
+        return result;
+    }
+
+    public static URL normalizeUrl(URL u, boolean debug) throws MalformedURLException, UnsupportedEncodingException {
+        if (u == null) {
+            return null;
+        }
+        String protocol = u.getProtocol();
+        if (protocol == null || "file".equals(protocol)) {
+            return u;
+        }
+        String file = u.getPath();
+        if (file == null) {
+            return u;
+        }
+        String host = u.getHost();
+        String ref = u.getRef();
+        int port = u.getPort();
+        String query = u.getQuery();
+        String[] qq = {};
+        if (query != null) {
+            qq = query.split(QUERY_DELIMITER);
+        }
+        String[] ss = file.split(PATH_DELIMITER);
+        int normalized = 0;
+        if (debug) {
+            System.out.println("normalizing path " + file + " in " + u.toString());
+        }
+        for (int i = 0; i < ss.length; i++) {
+            String base = ss[i];
+            String r = normalizeChunk(base, debug);
+            if (!r.equals(ss[i])) {
+                normalized++;
+            }
+            ss[i] = r;
+        }
+        if (debug) {
+            System.out.println("normalizing query " + query + " in " + u.toString());
+        }
+        for (int i = 0; i < qq.length; i++) {
+            String base = qq[i];
+            String r = normalizeChunk(base, debug);
+            if (!r.equals(qq[i])) {
+                normalized++;
+            }
+            qq[i] = r;
+        }
+        if (normalized == 0) {
+            if (debug) {
+                System.out.println("Nothing was normalized in this url");
+            }
+            return u;
+        } else {
+            if (debug) {
+                System.out.println(normalized + " chunks normalized, rejoining url");
+            }
+        }
+        StringBuilder composed = new StringBuilder("");
+        for (int i = 0; i < ss.length; i++) {
+            String string = ss[i];
+            if (ss.length <= 1 || (string != null && !"".equals(string))) {
+                composed.append(PATH_DELIMITER_MARK).append(string);
+            }
+        }
+        String composed1 = composed.toString();
+        if (query != null && !query.trim().equals("")) {
+            composed.append(QUERY_MARK);
+            for (int i = 0; i < qq.length; i++) {
+                String string = qq[i];
+                if ((string != null && !"".equals(string))) {
+                    composed.append(string);
+                    if (i != qq.length - 1) {
+                        composed.append(QUERY_DELIMITER_MARK);
+                    }
+                }
+            }
+        }
+        String composed2 = composed.substring(composed1.length() - 1);
+        if (ref != null && !ref.trim().equals("")) {
+            composed.append(HREF_MARK).append(ref);
+        }
+
+        URL result = new URL(protocol, host, port, composed.toString());
+
+        if (debug) {
+            System.out.println("normalized `" + composed1 + "` and `" + composed2 + "` in " + result.toString());
+        }
+        return result;
+
+    }
 }