We’ve got a menu in out web app that uses <a> tags to load pages in the main frame.
A typical item in the menu would be something like:
<a target="mainframe" href="/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3¶m3=val4">Menu Item 1</a>
We needed to add some JavaScript validation before the link is requested so I changed it to:
<a target="mainframe" href="javascript:validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3¶m3=val4')">Menu Item 1</a>
(I know that javascript:function in a link is bad practice but we use a 3rd party library to generate the menu so I can’t change this part of the code)
Servlet1 expects:
param1=’val1′
param2=’servlet2?s2p1=val2%26s2p2=val3′
param3=’val4′
Servlet1 then forwards to the value of param2 so Servlet2 expects:
s2p1=’val2′
s2p2=’val3′
However when I put an alert in my validate function to check what is passed in:
function validate(href) {
alert(href);
...validation code...
}
it is giving:
/servlet1?param1=val1&parma2=servlet2?s2p1=val2**&**s2p2=val3¶m3=val4 (note the bold & which was %26 in the above function call)
The %26 is getting converted to an & when it is passed into the JS function which would not normally happen until the request is forwarded to Servlet2. Because the %26 has already been changed to an & the s2p2 request parameter gets picked up by servlet1 instead of servlet2.
Basically my question is why does the %26 get converted to a & at this point just by passing it as a parameter to the function from the href attribute when if you do onClick="validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3¶m3=val4')"
it stays as %26 as you’d expect?
Urgh. You have a URL, embedded in a URL, all embedded in another URL! That’s too many levels of escaping for the human mind to cope with.This:
is itself a URL. Albeit a
javascript:pseudo-URL, which you should never use. It is decoded to the JavaScript command:at which point you have already lost the %26. Now when you use that as a URL itself, it will fail.
Avoid multiple-encoding problems by moving the scripting out into a JavaScript block (or external script) instead of an HTML attribute:
(Note here also the necessary HTML-escaping of ampersands.) Then from script do:
Then in your validate function simply return
trueif all is OK and you want the link to be followed, orfalseto stop it.