Repository: brooklyn-server Updated Branches: refs/heads/master 5c5d578f4 -> 422e025ea
Urls.encode(String) specifies UTF-8 Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/fa387821 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/fa387821 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/fa387821 Branch: refs/heads/master Commit: fa387821a0594fbd107f0edcb1ee73144a30987b Parents: 5c5d578 Author: Aled Sage <aled.s...@gmail.com> Authored: Mon Feb 6 12:55:03 2017 +0000 Committer: Aled Sage <aled.s...@gmail.com> Committed: Mon Feb 6 13:08:44 2017 +0000 ---------------------------------------------------------------------- .../java/org/apache/brooklyn/util/net/Urls.java | 36 +++++++++++++++--- .../org/apache/brooklyn/util/net/UrlsTest.java | 40 +++++++++++++++++++- 2 files changed, 68 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/fa387821/utils/common/src/main/java/org/apache/brooklyn/util/net/Urls.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/net/Urls.java b/utils/common/src/main/java/org/apache/brooklyn/util/net/Urls.java index 717e8a2..ac60c96 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/net/Urls.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/net/Urls.java @@ -19,6 +19,7 @@ package org.apache.brooklyn.util.net; import java.io.File; +import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -30,6 +31,7 @@ import java.util.List; import javax.annotation.Nullable; +import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.text.Strings; import com.google.common.base.Function; @@ -177,16 +179,38 @@ public class Urls { return result.toString(); } - /** encodes the string suitable for use in a URL, using default character set - * (non-deprecated version of URLEncoder.encode) */ - @SuppressWarnings("deprecation") + /** + * Encodes the string suitable for use in a URL, using default UTF-8 + * (version of URLEncoder.encode that does not throw checked exception) + */ public static String encode(String text) { - return URLEncoder.encode(text); + /* + * TODO URLEncoder.encode is a HTML encoder, to make strings safe to use in + * x-www-form-urlencoded. There is huge overlap between that and url-encoding, but + * they are not the same (e.g. space is converted to "+" rather than "%20", and + * "*" is not converted to "%2A"). + * + * Correct URL-encoding depends on which part of the URL it is. For example, guava's + * UrlEscapers has separate escapers for path and fragment. Neither of these is + * appropriate for escaping the password in "http://myusername@mypassword:myhost". + * + * org.apache.commons.codec.net.URLCodec behaves the same as java.net.URLEncoder: it + * is for "www-form-urlencoded". + */ + try { + return URLEncoder.encode(text, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw Exceptions.propagate(e); + } } + /** As {@link #encode(String)} */ - @SuppressWarnings("deprecation") public static String decode(String text) { - return URLDecoder.decode(text); + try { + return URLDecoder.decode(text, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw Exceptions.propagate(e); + } } /** returns the protocol (e.g. http) if one appears to be specified, or else null; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/fa387821/utils/common/src/test/java/org/apache/brooklyn/util/net/UrlsTest.java ---------------------------------------------------------------------- diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/net/UrlsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/net/UrlsTest.java index f775826..285fd8a 100644 --- a/utils/common/src/test/java/org/apache/brooklyn/util/net/UrlsTest.java +++ b/utils/common/src/test/java/org/apache/brooklyn/util/net/UrlsTest.java @@ -32,7 +32,7 @@ public class UrlsTest { Assert.assertEquals(Urls.toUrl(u).toString(), u); Assert.assertEquals(Urls.toUri(u).toString(), u); Assert.assertEquals(Urls.toUri(Urls.toUrl(u)).toString(), u); - Assert.assertEquals(Urls.toUrl(Urls.toUri(u)).toString(), u); + Assert.assertEquals(Urls.toUrl(Urls.toUri(u)).toString(), u); } @Test @@ -50,7 +50,29 @@ public class UrlsTest { @Test public void testPathEncode() throws Exception { - assertEquals(Urls.encode("name_with/%!"), "name_with%2F%25%21"); + encodeAndDecodeUrl("simple", "simple"); + encodeAndDecodeUrl("name_with/%!", "name_with%2F%25%21"); + + StringBuilder allcharsBuilder = new StringBuilder(); + for (int i = 1; i < 128; i++) { + if (i == 32 || i == 42) continue; // See testUserOrPasswordOrHostEncode() + allcharsBuilder.append((char)i); + } + String allchars = allcharsBuilder.toString(); + encodeAndDecodeUrl(allchars, "%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%21%22%23%24%25%26%27%28%29%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F"); + } + + // TODO java.net.URLEncoder.encode() gets it wrong for: + // " " (i.e. space - char %20). It turns that into "+" in the url. + // "*" (i.e char %2A) is not escaped - this is wrong according to https://en.wikipedia.org/wiki/Percent-encoding (RFC 3986). + @Test(groups="Broken") + public void testUserOrPasswordOrHostEncode() throws Exception { + StringBuilder passwordBuilder = new StringBuilder(); + for (int i = 1; i < 128; i++) { + passwordBuilder.append((char)i); + } + String allchars = passwordBuilder.toString(); + encodeAndDecodeUrl(allchars, "%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F"); } @Test @@ -88,4 +110,18 @@ public class UrlsTest { // tests for parsing are in core in ResourceUtilsTest } + + @Test + public void testEncodeAndDecodeUrl() throws Exception { + encodeAndDecodeUrl("simple", "simple"); + encodeAndDecodeUrl("!@#$%^&*", "%21%40%23%24%25%5E%26*"); // TODO "*" should really be encoded! + encodeAndDecodeUrl("a/b", "a%2Fb"); + } + + private void encodeAndDecodeUrl(String val, String expectedEncoding) { + String actualEncoding = Urls.encode(val); + String actualDecoded = Urls.decode(actualEncoding); + assertEquals(actualDecoded, val, "Encode+decode does not match original: orig="+val+"; decoded="+actualDecoded); + assertEquals(actualEncoding, expectedEncoding, "Does not match expected encoding: orig="+val+"; decoded="+actualDecoded); + } }