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?
<a target="mainframe" href="javascript:validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3¶m3=val4')">Menu Item 1</a>
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:
javascript:validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3¶m3=val4')
is itself a URL. Albeit a javascript:
pseudo-URL, which you should never use. It is decoded to the JavaScript command:
validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2&s2p2=val3¶m3=val4')
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:
<a target="mainframe" class="validateme" href="/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3&param3=val4">Menu Item 1</a>
(Note here also the necessary HTML-escaping of ampersands.) Then from script do:
// find 'validateme' links and add event handler
//
for (var i= document.links; i-->0;)
if (document.links[i].className==='validateme')
document.links[i].onclick= validate;
Then in your validate function simply return true
if all is OK and you want the link to be followed, or false
to stop it.
No, the %26
is (correctly) interpreted as & when the HTML file is first read into the browser, and not when passed into the JavaScript function. If you want the literal sequence of characters "percent two six", then you must encode that as %2526
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With