I need to URL decode a string in a VBScript. The string may contain Unicode characters which are encoded as multiple bytes as per UTF-8. So for example "Paris%20%E2%86%92%20Z%C3%BCrich" would decode to "Paris → Zürich".
To do the job, I'm using a piece of code that looks like this:
Function URLDecode(str)
set list = CreateObject("System.Collections.ArrayList")
strLen = Len(str)
for i = 1 to strLen
sT = mid(str, i, 1)
if sT = "%" then
if i + 2 <= strLen then
list.Add cbyte("&H" & mid(str, i + 1, 2))
i = i + 2
end if
else
list.Add asc(sT)
end if
next
depth = 0
for each by in list.ToArray()
if by and &h80 then
if (by and &h40) = 0 then
if depth = 0 then Err.Raise 5
val = val * 2 ^ 6 + (by and &h3f)
depth = depth - 1
if depth = 0 then
sR = sR & chrw(val)
val = 0
end if
elseif (by and &h20) = 0 then
if depth > 0 then Err.Raise 5
val = by and &h1f
depth = 1
elseif (by and &h10) = 0 then
if depth > 0 then Err.Raise 5
val = by and &h0f
depth = 2
else
Err.Raise 5
end if
else
if depth > 0 then Err.Raise 5
sR = sR & chrw(by)
end if
next
if depth > 0 then Err.Raise 5
URLDecode = sR
End Function
This seems to be working well, but it looks exaggeratedly complex to me. In times of HTML5 and web standards, there must be a simpler way to get this done without a bunch of hand-made loops and conditions. Any suggestions?
I want to show three methods for three vary environments. All of these methods requires JScript's encodeURIComponent
and decodeURIComponent
functions.
1. In ASP, using server-side JavaScript is one of most appropriate solutions :
<script language="javascript" runat="server">
URL = {
encode : function(s){return encodeURIComponent(s).replace(/'/g,"%27").replace(/"/g,"%22")},
decode : function(s){return decodeURIComponent(s.replace(/\+/g, " "))}
}
</script>
<%
Response.Write URL.decode("Paris%20%E2%86%92%20Z%C3%BCrich")
Response.Write URL.encode("Paris → Zürich")
%>
2. 32-Bit only (due to MSScriptControl.ScriptControl is 32-bit only component) in any other WSH :
Dim JSEngine
Set JSEngine = CreateObject("MSScriptControl.ScriptControl")
JSEngine.Language = "JScript"
Function UrlEncode(s)
UrlEncode = JSEngine.CodeObject.encodeURIComponent(s)
UrlEncode = Replace(UrlEncode, "'", "%27")
UrlEncode = Replace(UrlEncode, """", "%22")
End Function
Function UrlDecode(s)
UrlDecode = Replace(s, "+", " ")
UrlDecode = JSEngine.CodeObject.decodeURIComponent(UrlDecode)
End Function
WScript.Echo UrlDecode("Paris%20%E2%86%92%20Z%C3%BCrich")
WScript.Echo UrlEncode("Paris → Zürich")
3. With 64-bit support in any other WSH using a WSC:
urlencdec.wsc (created by using WSC Wizard)
<?xml version="1.0"?>
<component>
<?component error="true" debug="true"?>
<registration
description="Url Encode / Decode Helper"
progid="JSEngine.Url"
version="1.0"
classid="{80246bcc-45d4-4e92-95dc-4fd9a93d8529}"
/>
<public>
<method name="encode">
<PARAMETER name="s"/>
</method>
<method name="decode">
<PARAMETER name="s"/>
</method>
</public>
<script language="JScript">
<![CDATA[
var description = new UrlEncodeDecodeHelper;
function UrlEncodeDecodeHelper() {
this.encode = encode;
this.decode = decode;
}
function encode(s) {
return encodeURIComponent(s).replace(/'/g,"%27").replace(/"/g,"%22");
}
function decode(s) {
return decodeURIComponent(s.replace(/\+/g, " "));
}
]]>
</script>
</component>
and vbs code :
Dim JSEngine
Set JSEngine = GetObject("Script:C:\urlencdec.wsc")
WScript.Echo JSEngine.decode("Paris%20%E2%86%92%20Z%C3%BCrich")
WScript.Echo JSEngine.encode("Paris → Zürich")