Please have a look at the following JSP/JSTL snippet: <a href="<c:url value="action.jsp"> <c:param name="param1" value="value1"/> <c:param name="param2" value="value2"/> </c:url>">action</a> When requested by an HTTP client, the following response is returned: <a href="action.jsp?param1=value1¶m2=value2">action</a> BUG: The ampersand between the two parameters should be escaped, for example by using & For testing, I created a demo under http://schildbach.de/test-jstl-c-out.jsp Please use the W3C validator (http://validator.w3.org/) and enter my test URL, and you will get the 6 errors I attached below. I am using Tomcat 4.1.27, JDK 1.4.2 and JSTL 1.03 --- > # Line 13, column 81: cannot generate system identifier for general > entity "param2" > > ...E16EDEC5EAFDA47DCBBB44?param1=value1¶m2=value2">action</a> > ^ > > # Line 13, column 81: general entity "param2" not defined and > no default > entity (explain...). > > ...E16EDEC5EAFDA47DCBBB44?param1=value1¶m2=value2">action</a> > ^ > > # Line 13, column 87: reference not terminated by REFC delimiter > > ...C5EAFDA47DCBBB44?param1=value1¶m2=value2">action</a> > ^ > > # Line 13, column 87: reference to external entity in attribute value > > ...C5EAFDA47DCBBB44?param1=value1¶m2=value2">action</a> > ^ > > # Line 13, column 87: reference to entity "param2" for which > no system > identifier could be generated > > ...C5EAFDA47DCBBB44?param1=value1¶m2=value2">action</a> > ^ > > # Line 13, column 80: entity was defined here > > ...2E16EDEC5EAFDA47DCBBB44?param1=value1¶m2=value2">action</a>
Thanks for the report. A fix is ready but unfortunately it breaks in Tomcat's RequestDispatcher when "&" is used instead of "&" (with <c:import>). (all actions that make use of <c:param> share the same param generation code). I have pinged the Tomcat team on that issue. It is possible to do a fix for only <c:url>, but I'll wait to hear from them before going ahead.
OK. Cleared up the situation with tomcat and this is indeed a problem that has to be fixed at the level of <c:url>. This will however require a change to the spec. Unfortunately, the JSTL 1.1 Maintenance Release spec is now frozen and the fix will have to wait for the next release. The change that the expert group has agreed on so far is to add one new attribute to <c:url>, 'escapeAmp', to escape the ampersand character. Default value for that attribute will be false, for backwards compatibility.
I don't understand the rationale behind defaulting to generating invalid HTML (according to W3C). In the case of <c:url>, I don't understand the need for that escapeAmp attribute at all, because why would I ever _not_ escape an ampersand if I get invalid HTML otherwise? If the reason for that behaviour is that the same routines are being shared between <c:url> and other related code, maybe this is a hint that the code should not be shared any longer or should be refactored to accommodate the two different cases. Anyway, perhaps it would be possible to apply or at least describe a workaround for JSTL 1.0.
Andreas, I understand your point, and it makes a lot of sense. The problem though is that we have to deal with what's currently in the spec and its impact on backwards compatibility. If it had been clearly spelled out in the spec that the output of <c:url> were to be used strictly for URIs used in HTML element attribute values, then I'd agree with you. The problem though is that the output of <c:url> may also be used in other contexts. For example (not the best example, but just to make the point), one could have used <c:url> as follows: <c:url value="foo" var="myUrl"> <c:param name="param1" value="value1"/> <c:param name="param2" value="value2"/> </c:url> <c:redirect url="${myUrl}"/> In that context, we don't want the ampersands to be escaped. It would break <c:redirect> which expects parameters to be separated by '&' and not '&'. Since the escaping of '&' to '&' has not been clearly spelled out in the spec, we would not be backwards compatible.
*** Bug 28652 has been marked as a duplicate of this bug. ***
This is not yet resolved. Will be in the next JSTL Maintenance Release.
CC'ing the taglibs-dev address to all Standard bugs.
Changing Severity to Enhancement since this issue cannot be resolved in the implementation until the specification is clarified. Will be addressed by next JSTL specification maintenance release.
As far as I can tell, there were no changes to the spec related to this. The JSTL 1.2 spec for c:param and c:url is identical to the 1.1 and 1.0 specs. So this remains an issue for the EG team and not this particular codebase. Reading the spec, it does state for c:url that: "If the URL contains characters that should be encoded (e.g. space), it is the user's responsibility to encode them. " c:param on the other hand says: "Moreover, it has been designed such that the attributes name and value are automatically URL encoded. " The two sections seem to contradict each other.
I've reported this to the 1.2 RI: https://glassfish.dev.java.net/issues/show_bug.cgi?id=1743 We won't be fixing it unless the spec changes.
I'm getting my url encoding and xml escaping muddled. Ignore my quotes from the spec.