mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
WW-1938 Bug with multiple s:param tags inside s:url tag
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/branches/STRUTS_2_0_X@559146 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -338,12 +338,13 @@ public class Component {
|
||||
*/
|
||||
protected String determineActionURL(String action, String namespace, String method,
|
||||
HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme,
|
||||
boolean includeContext, boolean encodeResult) {
|
||||
boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort,
|
||||
boolean escapeAmp) {
|
||||
String finalAction = findString(action);
|
||||
String finalNamespace = determineNamespace(namespace, getStack(), req);
|
||||
ActionMapping mapping = new ActionMapping(finalAction, finalNamespace, method, parameters);
|
||||
String uri = actionMapper.getUriFromActionMapping(mapping);
|
||||
return UrlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult);
|
||||
return UrlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,6 +53,12 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
* additional request parameters.</p>
|
||||
*
|
||||
* <b>NOTE:</b>
|
||||
* <p>By default request parameters will be separated using escaped ampersands (i.e., &amp;).
|
||||
* This is necessary for XHTML compliance, however, when using the URL generated by this tag
|
||||
* with the <s:property> tag, the <b>escapeAmp</b> attribute should be used to disable
|
||||
* ampersand escaping.</p>
|
||||
*
|
||||
* <b>NOTE:</b>
|
||||
* <p>When includeParams is 'all' or 'get', the parameter defined in param tag will take
|
||||
* precedence and will not be overriden if they exists in the parameter submitted. For
|
||||
* example, in Example 3 below, if there is a id parameter in the url where the page this
|
||||
@@ -68,16 +74,20 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
* <ul>
|
||||
* <li>action (String) - (value or action choose either one, if both exist value takes precedence) action's name (alias) <li>
|
||||
* <li>value (String) - (value or action choose either one, if both exist value takes precedence) the url itself</li>
|
||||
* <li>scheme (String) - http scheme (http, https) default to the scheme this request is in</li>
|
||||
* <li>scheme (String) - http scheme (http, https) defaults to the scheme this request is in</li>
|
||||
* <li>namespace - action's namespace</li>
|
||||
* <li>method (String) - action's method, default to execute() </li>
|
||||
* <li>encode (Boolean) - url encode the generated url. Default is true</li>
|
||||
* <li>includeParams (String) - The includeParams attribute may have the value 'none', 'get' or 'all'. Default is 'get'.
|
||||
* <li>method (String) - action's method name, defaults to 'execute'</li>
|
||||
* <li>encode (Boolean) - url encode the generated url. Defaults to 'true'.</li>
|
||||
* <li>includeParams (String) - The includeParams attribute may have the value 'none', 'get' or 'all'. Defaults to 'get'.
|
||||
* none - include no parameters in the URL
|
||||
* get - include only GET parameters in the URL (default)
|
||||
* all - include both GET and POST parameters in the URL
|
||||
* </li>
|
||||
* <li>includeContext (Boolean) - determine wheather to include the web app context path. Default is true.</li>
|
||||
* <li>includeContext (Boolean) - Specifies whether to include the web app context path. Defaults to 'true'.</li>
|
||||
* <li>escapeAmp (Boolean) - Specifies whether to escape ampersand (&) to (&amp;) or not. Defaults to 'true'.</li>
|
||||
* <li>portletMode (String) - The resulting portlet mode.</li>
|
||||
* <li>windowState (String) - The resulting portlet window state.</li>
|
||||
* <li>portletUrlType (String) - Specifies if this should be a portlet render or action URL.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: params -->
|
||||
@@ -135,6 +145,7 @@ public class URL extends Component {
|
||||
protected String method;
|
||||
protected boolean encode = true;
|
||||
protected boolean includeContext = true;
|
||||
protected boolean escapeAmp = true;
|
||||
protected String portletMode;
|
||||
protected String windowState;
|
||||
protected String portletUrlType;
|
||||
@@ -240,7 +251,7 @@ public class URL extends Component {
|
||||
result = PortletUrlHelper.buildUrl(action, namespace, parameters, portletUrlType, portletMode, windowState);
|
||||
}
|
||||
else {
|
||||
result = determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encode);
|
||||
result = determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encode, false, escapeAmp);
|
||||
}
|
||||
} else {
|
||||
if(Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest()) {
|
||||
@@ -254,7 +265,7 @@ public class URL extends Component {
|
||||
if (_value != null && _value.indexOf("?") > 0) {
|
||||
_value = _value.substring(0, _value.indexOf("?"));
|
||||
}
|
||||
result = UrlHelper.buildUrl(_value, req, res, parameters, scheme, includeContext, encode);
|
||||
result = UrlHelper.buildUrl(_value, req, res, parameters, scheme, includeContext, encode, false, escapeAmp);
|
||||
}
|
||||
}
|
||||
if ( anchor != null && anchor.length() > 0 ) {
|
||||
@@ -338,6 +349,11 @@ public class URL extends Component {
|
||||
this.anchor = anchor;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Specifies whether to escape ampersand (&) to (&amp;) or not", type="Boolean", defaultValue="true")
|
||||
public void setEscapeAmp(boolean escapeAmp) {
|
||||
this.escapeAmp = escapeAmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge request parameters into current parameters. If a parameter is
|
||||
|
||||
@@ -44,6 +44,7 @@ public class URLTag extends ComponentTagSupport {
|
||||
protected String method;
|
||||
protected String encode;
|
||||
protected String includeContext;
|
||||
protected String escapeAmp;
|
||||
protected String portletMode;
|
||||
protected String windowState;
|
||||
protected String portletUrlType;
|
||||
@@ -74,6 +75,9 @@ public class URLTag extends ComponentTagSupport {
|
||||
if (includeContext != null) {
|
||||
url.setIncludeContext(Boolean.valueOf(includeContext).booleanValue());
|
||||
}
|
||||
if (escapeAmp != null) {
|
||||
url.setEscapeAmp(Boolean.valueOf(escapeAmp).booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void setEncode(String encode) {
|
||||
@@ -84,6 +88,10 @@ public class URLTag extends ComponentTagSupport {
|
||||
this.includeContext = includeContext;
|
||||
}
|
||||
|
||||
public void setEscapeAmp(String escapeAmp) {
|
||||
this.escapeAmp = escapeAmp;
|
||||
}
|
||||
|
||||
public void setIncludeParams(String name) {
|
||||
includeParams = name;
|
||||
}
|
||||
|
||||
@@ -91,6 +91,10 @@ public class UrlHelper {
|
||||
}
|
||||
|
||||
public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
|
||||
return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true);
|
||||
}
|
||||
|
||||
public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) {
|
||||
StringBuffer link = new StringBuffer();
|
||||
|
||||
boolean changedScheme = false;
|
||||
@@ -169,7 +173,11 @@ public class UrlHelper {
|
||||
}
|
||||
|
||||
//if the action was not explicitly set grab the params from the request
|
||||
buildParametersString(params, link);
|
||||
if (escapeAmp) {
|
||||
buildParametersString(params, link);
|
||||
} else {
|
||||
buildParametersString(params, link, "&");
|
||||
}
|
||||
|
||||
String result;
|
||||
|
||||
|
||||
@@ -51,6 +51,14 @@ Please do not edit it directly.
|
||||
<td align="left" valign="top">Boolean</td>
|
||||
<td align="left" valign="top">Whether to encode parameters</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">escapeAmp</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">true</td>
|
||||
<td align="left" valign="top">true</td>
|
||||
<td align="left" valign="top">Boolean</td>
|
||||
<td align="left" valign="top">Specifies whether to escape ampersand (&) to (&amp;) or not</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">id</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
|
||||
@@ -348,6 +348,19 @@ public class URLTagTest extends AbstractUITagTest {
|
||||
assertEquals("/team.action?section=team&company=acme+inc", writer.toString());
|
||||
}
|
||||
|
||||
public void testRequestURIActionIncludeGetDoNotEscapeAmp() throws Exception {
|
||||
request.setRequestURI("/public/about");
|
||||
request.setQueryString("section=team&company=acme inc");
|
||||
|
||||
tag.setAction("team");
|
||||
tag.setIncludeParams("get");
|
||||
tag.setEscapeAmp("false");
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
|
||||
assertEquals("/team.action?section=team&company=acme+inc", writer.toString());
|
||||
}
|
||||
|
||||
public void testRequestURINoActionIncludeNone() throws Exception {
|
||||
request.setRequestURI("/public/about");
|
||||
request.setQueryString("section=team&company=acme inc");
|
||||
|
||||
@@ -144,6 +144,22 @@ public class UrlHelperTest extends StrutsTestCase {
|
||||
assertEquals(expectedString, urlString);
|
||||
}
|
||||
|
||||
public void testBuildUrlCorrectlyAddsDoNotEscapeAmp() {
|
||||
String expectedString = "my.actionName?foo=bar&hello=world";
|
||||
Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
|
||||
mockHttpServletRequest.expectAndReturn("getScheme", "http");
|
||||
Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
|
||||
mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString);
|
||||
|
||||
String actionName = "my.actionName";
|
||||
TreeMap params = new TreeMap();
|
||||
params.put("hello", "world");
|
||||
params.put("foo", "bar");
|
||||
|
||||
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, null, true, true, false, false);
|
||||
assertEquals(expectedString, urlString);
|
||||
}
|
||||
|
||||
public void testBuildUrlWithStringArray() {
|
||||
String expectedString = "my.actionName?foo=bar&hello=earth&hello=mars";
|
||||
Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
|
||||
|
||||
Reference in New Issue
Block a user