SPR-6296 Spring:url tag should not use application/x-www-form-urlencoded encoding

Work around for application/x-www-form-urlencoded encoding.  Replaces '+' from java.net.URLDecoder with charset specific encoded space value ('%20' for most charsets).

The custom urlEncode method should be replaced with calls to a true URL encoder once available.
This commit is contained in:
Scott Andrews
2009-11-03 21:01:23 +00:00
parent 868cf09b2d
commit 67b5781dab
2 changed files with 56 additions and 14 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.web.servlet.tags;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@@ -23,6 +24,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
@@ -65,7 +67,7 @@ import org.springframework.web.util.TagUtils;
* <spring:param name="variableName" value="more than JSTL c:url" />
* &lt;/spring:url&gt;</pre>
* Results in:
* <code>/currentApplicationContext/url/path/more+than+JSTL+c%3Aurl</code>
* <code>/currentApplicationContext/url/path/more%20than%20JSTL%20c%3Aurl</code>
*
* @author Scott Andrews
* @since 3.0
@@ -269,7 +271,6 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
*/
protected String replaceUriTemplateParams(String uri, List<Param> params, Set<String> usedParams)
throws JspException {
for (Param param : params) {
String template = URL_TEMPLATE_DELIMITER_PREFIX + param.getName() + URL_TEMPLATE_DELIMITER_SUFFIX;
if (uri.contains(template)) {
@@ -281,7 +282,11 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
}
/**
* URL-encode the providedSstring using the character encoding for the response.
* URL-encode the provided String using the character encoding for the response.
* <p>This method will <strong>not</strong> URL-encode according to the
* <code>application/x-www-form-urlencoded</code> MIME format. Spaces will
* encoded as regular character instead of <code>+</code>. In <code>UTF-8</code>
* a space encodes to <code>%20</code>.
* @param value the value to encode
* @return the URL encoded value
* @throws JspException if the character encoding is invalid
@@ -291,13 +296,41 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
return null;
}
try {
return URLEncoder.encode(value, pageContext.getResponse().getCharacterEncoding());
String encoding = pageContext.getResponse().getCharacterEncoding();
String formUrlEncodedValue = URLEncoder.encode(value, encoding);
if (!formUrlEncodedValue.contains("+")) {
return formUrlEncodedValue;
}
String spaceEncoding = this.urlEncode(' ', encoding);
return formUrlEncodedValue.replace("+", spaceEncoding);
}
catch (UnsupportedEncodingException ex) {
throw new JspException(ex);
}
}
/*
* based on URLCodec from Apache Commons Codec
*/
protected String urlEncode(Character c, String enc) throws UnsupportedEncodingException {
if (c == null) {
return null;
}
byte[] bytes = c.toString().getBytes(enc);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
int b = bytes[i];
if (b < 0) {
b = 256 + b;
}
char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
builder.append('%');
builder.append(hex1);
builder.append(hex2);
}
return builder.toString();
}
/**
* Internal enum that classifies URLs by type.