utf-8vbscripturldecode

Decoding URL encoded UTF-8 strings in VBScript


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?


Solution

  • 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")