Fix com.google.gwt.http.client.UrlBuilder to encode the query string using URL.encodeQueryString().
This fixes cases when "+" or ":" or "&" is part of a query string.
Requires to fix WindowTest as the URL in the test contains a parameter "ip:port" pointing to the code server.

Review at http://gwt-code-reviews.appspot.com/1586804

Review by: jlabanca@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10734 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/http/client/UrlBuilder.java b/user/src/com/google/gwt/http/client/UrlBuilder.java
index 5d954cd..5e80bdc 100644
--- a/user/src/com/google/gwt/http/client/UrlBuilder.java
+++ b/user/src/com/google/gwt/http/client/UrlBuilder.java
@@ -50,11 +50,11 @@
     StringBuilder url = new StringBuilder();
 
     // http://
-    url.append(protocol).append("://");
+    url.append(URL.encode(protocol)).append("://");
 
     // http://www.google.com
     if (host != null) {
-      url.append(host);
+      url.append(URL.encode(host));
     }
 
     // http://www.google.com:80
@@ -64,7 +64,7 @@
 
     // http://www.google.com:80/path/to/file.html
     if (path != null && !"".equals(path)) {
-      url.append("/").append(path);
+      url.append("/").append(URL.encode(path));
     }
 
     // Generate the query string.
@@ -72,9 +72,12 @@
     char prefix = '?';
     for (Map.Entry<String, String[]> entry : listParamMap.entrySet()) {
       for (String val : entry.getValue()) {
-        url.append(prefix).append(entry.getKey()).append('=');
+        url.append(prefix)
+            .append(URL.encodeQueryString(entry.getKey()))
+            .append('=');
         if (val != null) {
-          url.append(val);
+          // Also encodes +,& etc.
+          url.append(URL.encodeQueryString(val));
         }
         prefix = '&';
       }
@@ -82,10 +85,10 @@
 
     // http://www.google.com:80/path/to/file.html?k0=v0&k1=v1#token
     if (hash != null) {
-      url.append("#").append(hash);
+      url.append("#").append(URL.encode(hash));
     }
 
-    return URL.encode(url.toString());
+    return url.toString();
   }
 
   /**
diff --git a/user/test/com/google/gwt/http/client/UrlBuilderTest.java b/user/test/com/google/gwt/http/client/UrlBuilderTest.java
index e072e14..0a510d6 100644
--- a/user/test/com/google/gwt/http/client/UrlBuilderTest.java
+++ b/user/test/com/google/gwt/http/client/UrlBuilderTest.java
@@ -38,8 +38,25 @@
     builder.setHost("google.com");
     builder.setPath("path to file");
     builder.setParameter("the key", "the value");
-    assertEquals("http://google.com/path%20to%20file?the%20key=the%20value",
+    assertEquals("http://google.com/path%20to%20file?the+key=the+value",
         builder.buildString());
+
+    builder = new UrlBuilder();
+    builder.setHost("google.com");
+    builder.setPath("path");
+    builder.setHash("hash");
+
+    builder.setParameter("a_b", "a+b");
+    assertEquals("http://google.com/path?a_b=a%2Bb#hash",
+                 builder.buildString());
+
+    builder.setParameter("a_b", "a&b");
+    assertEquals("http://google.com/path?a_b=a%26b#hash",
+                 builder.buildString());
+
+    builder.setParameter("a_b", "a%b");
+    assertEquals("http://google.com/path?a_b=a%25b#hash",
+                 builder.buildString());
   }
 
   public void testBuildStringEntireUrl() {
diff --git a/user/test/com/google/gwt/user/client/WindowTest.java b/user/test/com/google/gwt/user/client/WindowTest.java
index 800122f..ca21f4d 100644
--- a/user/test/com/google/gwt/user/client/WindowTest.java
+++ b/user/test/com/google/gwt/user/client/WindowTest.java
@@ -20,6 +20,7 @@
 import com.google.gwt.event.logical.shared.ResizeHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.http.client.UrlBuilder;
+import com.google.gwt.http.client.URL;
 import com.google.gwt.junit.DoNotRunWith;
 import com.google.gwt.junit.Platform;
 import com.google.gwt.junit.client.GWTTestCase;
@@ -120,7 +121,9 @@
         assertEquals(expectedPairs.length, actualPairs.length);
         for (String actualPair : actualPairs) {
           String[] kv = actualPair.split("=");
-          assertEquals(Location.getParameter(kv[0]), kv.length > 1 ? kv[1] : "");
+          assertEquals(Location.getParameter(kv[0]),
+                       // has a URL encoded ':' in a parameter
+                       kv.length > 1 ? URL.decodeQueryString(kv[1]) : "");
         }
       }
       expected = expectedParts[0];