Revision: 6470 Author: rj...@google.com Date: Mon Oct 26 15:00:20 2009 Log: Fix for issue 3374. This patch adds overloads of encodeComponent and decodeComponent to deal differently with spaces (keeping them as %20 rather than replacing them with +) and therefore allow their use for path segments (useful when using "RESTful services").
http://gwt-code-reviews.appspot.com/87806 Patch by: t.bro...@gmail.com Review by: rj...@google.com http://code.google.com/p/google-web-toolkit/source/detail?r=6470 Modified: /trunk/user/src/com/google/gwt/http/client/URL.java /trunk/user/test/com/google/gwt/http/client/URLTest.java ======================================= --- /trunk/user/src/com/google/gwt/http/client/URL.java Wed Apr 18 12:41:21 2007 +++ /trunk/user/src/com/google/gwt/http/client/URL.java Mon Oct 26 15:00:20 2009 @@ -56,6 +56,25 @@ encodedURLComponent); return decodeComponentImpl(encodedURLComponent); } + + /** + * Returns a string where all URL component escape sequences have been + * converted back to their original character representations. + * + * @param encodedURLComponent string containing encoded URL component + * sequences + * @param fromQueryString if <code>true</code>, +'s will be turned into + * spaces, otherwise they'll be kept as-is. + * @return string with no encoded URL component encoded sequences + * + * @throws NullPointerException if encodedURLComponent is <code>null</code> + */ + public static String decodeComponent(String encodedURLComponent, + boolean fromQueryString) { + StringValidator.throwIfNull("encodedURLComponent", encodedURLComponent); + return fromQueryString ? decodeComponentImpl(encodedURLComponent) + : decodeComponentRawImpl(encodedURLComponent); + } /** * Returns a string where all characters that are not valid for a complete URL @@ -130,6 +149,44 @@ decodedURLComponent); return encodeComponentImpl(decodedURLComponent); } + + /** + * Returns a string where all characters that are not valid for a URL + * component have been escaped. The escaping of a character is done by + * converting it into its UTF-8 encoding and then encoding each of the + * resulting bytes as a %xx hexadecimal escape sequence. + * + * <p> + * The following character sets are <em>not</em> escaped by this method: + * <ul> + * <li>ASCII digits or letters</li> + * <li>ASCII punctuation characters: <pre>- _ . ! ~ * ' ( )</pre></li> + * </ul> + * </p> + * + * <p> + * Notice that this method <em>does</em> encode the URL component delimiter + * characters:<blockquote> + * + * <pre> + * ; / ? : & = + $ , # + * </pre> + * + * </blockquote> + * </p> + * + * @param decodedURLComponent a string containing invalid URL characters + * @param queryStringSpaces if <code>true</code>, spaces will be encoded as +'s. + * @return a string with all invalid URL characters escaped + * + * @throws NullPointerException if decodedURLComponent is <code>null</code> + */ + public static String encodeComponent(String decodedURLComponent, + boolean queryStringSpaces) { + StringValidator.throwIfNull("decodedURLComponent", decodedURLComponent); + return queryStringSpaces ? encodeComponentImpl(decodedURLComponent) + : encodeComponentRawImpl(decodedURLComponent); + } /* * Note: this method will convert the space character escape short form, '+', @@ -140,6 +197,10 @@ return decodeURIComponent(encodedURLComponent.replace(regexp, "%20")); }-*/; + private static native String decodeComponentRawImpl(String encodedURLComponent) /*-{ + return decodeURIComponent(encodedURLComponent); + }-*/; + private static native String decodeImpl(String encodedURL) /*-{ return decodeURI(encodedURL); }-*/; @@ -153,6 +214,10 @@ return encodeURIComponent(decodedURLComponent).replace(regexp, "+"); }-*/; + private static native String encodeComponentRawImpl(String decodedURLComponent) /*-{ + return encodeURIComponent(decodedURLComponent); + }-*/; + private static native String encodeImpl(String decodedURL) /*-{ return encodeURI(decodedURL); }-*/; ======================================= --- /trunk/user/test/com/google/gwt/http/client/URLTest.java Wed Apr 18 12:41:21 2007 +++ /trunk/user/test/com/google/gwt/http/client/URLTest.java Mon Oct 26 15:00:20 2009 @@ -22,10 +22,11 @@ */ public class URLTest extends GWTTestCase { - private final String DECODED_URL = "http://www.foo \u00E9 bar.com/1_!~*'();/?@&=+$,#"; - private final String DECODED_URL_COMPONENT = "-_.!~*'():/#?@ \u00E9 "; - private final String ENCODED_URL = "http://www.foo%20%C3%A9%20bar.com/1_!~*'();/?@&=+$,#"; - private final String ENCODED_URL_COMPONENT = "-_.!~*'()%3A%2F%23%3F%40+%C3%A9+"; + private final String DECODED_URL = "http://www.foo \u00E9+bar.com/1_!~*'();/?@&=+$,#"; + private final String DECODED_URL_COMPONENT = "-_.!~*'():/#?@ \u00E9+"; + private final String ENCODED_URL = "http://www.foo%20%C3%A9+bar.com/1_!~*'();/?@&=+$,#"; + private final String ENCODED_URL_COMPONENT = "-_.!~*'()%3A%2F%23%3F%40%20%C3%A9%2B"; + private final String ENCODED_URL_COMPONENT_QS = "-_.!~*'()%3A%2F%23%3F%40+%C3%A9%2B"; public String getModuleName() { return "com.google.gwt.http.HttpSuite"; @@ -67,6 +68,37 @@ String actualURLComponent = URL.decodeComponent(ENCODED_URL_COMPONENT); assertEquals(DECODED_URL_COMPONENT, actualURLComponent); + + actualURLComponent = URL.decodeComponent(ENCODED_URL_COMPONENT_QS); + assertEquals(DECODED_URL_COMPONENT, actualURLComponent); + } + + /** + * Test method for + * {...@link com.google.gwt.http.client.URL#decodeComponent(java.lang.String,boolean)}. + */ + public void testDecodeComponent2() { + try { + URL.decodeComponent(null); + fail("Expected NullPointerException"); + } catch (NullPointerException ex) { + // expected exception was thrown + } + + assertEquals("", URL.decodeComponent("", false)); + assertEquals("", URL.decodeComponent("", true)); + assertEquals(" ", URL.decodeComponent(" ", false)); + assertEquals(" ", URL.decodeComponent(" ", true)); + assertEquals("+", URL.decodeComponent("+", false)); + assertEquals(" ", URL.decodeComponent("+", true)); + assertEquals(" ", URL.decodeComponent("%20", false)); + assertEquals(" ", URL.decodeComponent("%20", true)); + + String actualURLComponent = URL.decodeComponent(ENCODED_URL_COMPONENT, false); + assertEquals(DECODED_URL_COMPONENT, actualURLComponent); + + actualURLComponent = URL.decodeComponent(ENCODED_URL_COMPONENT_QS, true); + assertEquals(DECODED_URL_COMPONENT, actualURLComponent); } /** @@ -104,6 +136,37 @@ assertEquals("+", URL.encodeComponent(" ")); String actualURLComponent = URL.encodeComponent(DECODED_URL_COMPONENT); + assertEquals(ENCODED_URL_COMPONENT_QS, actualURLComponent); + } + + /** + * Test method for + * {...@link com.google.gwt.http.client.URL#encodeComponent(java.lang.String,boolean)}. + */ + public void testEncodeComponent2() { + try { + URL.encodeComponent(null, false); + fail("Expected NullPointerException"); + } catch (NullPointerException ex) { + // expected exception was thrown + } + + try { + URL.encodeComponent(null, true); + fail("Expected NullPointerException"); + } catch (NullPointerException ex) { + // expected exception was thrown + } + + assertEquals("", URL.encodeComponent("", false)); + assertEquals("", URL.encodeComponent("", true)); + assertEquals("%20", URL.encodeComponent(" ", false)); + assertEquals("+", URL.encodeComponent(" ", true)); + + String actualURLComponent = URL.encodeComponent(DECODED_URL_COMPONENT, false); assertEquals(ENCODED_URL_COMPONENT, actualURLComponent); + + actualURLComponent = URL.encodeComponent(DECODED_URL_COMPONENT, true); + assertEquals(ENCODED_URL_COMPONENT_QS, actualURLComponent); } } --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---