1

In JavaScript, how can i decode a string that was encoded in C# using HttpServerUtility.UrlTokenEncode?

There are some equivalents in other languages but i couldn't rewrite them in JS. Any help would be appreciated.

This is the Java version.

This is the Objective-C version.

Update:

C#'s URLTokenEncode is not the same as base64 encoding. For example the last character is always the number of padding characters. So some characters need to be replaced properly. Java and Objective-C version of the code show which characters need to be replaced with what.

I tried decodeURIComponent but it was not decoded successfully. That makes sense because the string is encoded by a particular method. It's not base64.

For example, This is just a part of a C#'s UrlTokenEncode String:

vj4_fv7__7-_Pr6-ff3_Pr6_vz8_________________f____79_vP1_vb3_vz8____________________AAA1

And this is the correct decoded version using Objective-C/Java method:

vj4/fv7//7+/Pr6+ff3/Pr6/vz8/////////////////f////79/vP1/vb3/vz8////////////////////AAA=

2
  • 5
    decodeURIComponent Commented Aug 18, 2015 at 8:18
  • Please see my update @Tushar Commented Aug 18, 2015 at 9:32

4 Answers 4

2

I finally managed to convert the Objective-c version of URLTokenDecode by Jeffrey Thomas to JavaScript and it worked.

Here is the function:

function URLTokenDecode(token) {

    if (token.length == 0) return null;

    // The last character in the token is the number of padding characters.
    var numberOfPaddingCharacters = token.slice(-1);

    // The Base64 string is the token without the last character.
    token = token.slice(0, -1);

    // '-'s are '+'s and '_'s are '/'s.
    token = token.replace(/-/g, '+');
    token = token.replace(/_/g, '/');

    // Pad the Base64 string out with '='s
    for (var i = 0; i < numberOfPaddingCharacters; i++)
        token += "=";

    return token;
}

Here is the $filter if you are using AngularJS:

app.filter('URLTokenDecode', function () {
        return function (token) {

            if (token.length == 0) return null;

            // The last character in the token is the number of padding characters.
            var numberOfPaddingCharacters = token.slice(-1);

            // The Base64 string is the token without the last character.
            token = token.slice(0, -1);

            // '-'s are '+'s and '_'s are '/'s.
            token = token.replace(/-/g, '+');
            token = token.replace(/_/g, '/');

            // Pad the Base64 string out with '='s
            for (var i = 0; i < numberOfPaddingCharacters; i++)
                token += "=";

            return token;
        }

});
Sign up to request clarification or add additional context in comments.

5 Comments

Doesn't seem to be correct. You're missing out on the "int equalsCount = (int)(((char)bytes[inputLength]) - 0x30);"
@Stefan, because of how str.replace() works in Javascript, i don't need to know the length of my input. That goes the same when i'm padding with '=', no need to know the length. So this should work.
Can't really say I understand why anybody does it this way instead of just url-encoding a base-64 encoding, or what's the logic behind this method, but anyway, it would surprise me if this decoding method would work correctly IN ALL CASES. Note that while it may work correctly in a few cases, this doesn't necessarely mean it works correctly for all cases.
@StefanSteiger, I'm sending a binary image from my webservice and if i send it with Base64 encoding then in some cases it sends empty. But UrlTokenEncode works with the same case. So that's why i'm using this. About this method , I'd say it should work because it does what the algorithm says. I'd be surprised if it doesn't work in all cases.
Thanks a lot @Sobhan - I wasted a lot of time converting to hex then modify (with no exact solution) - until I found your solution
0

I guess that would be decodeuricomponent:
http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp

To decode a UTF8-base64-encoded string in JavaScript:

var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);

To encode a UTF8-JavaScript-string as such in JavaScript:

var str = "äöüÄÖÜçéèñ";
var b64 = window.btoa(unescape(encodeURIComponent(str)))
console.log(b64);

Seems UrlTokenDecode is a little bit more complicated.
The best method to be 100% sure is to call UrlTokenDecode on the server-side with AJAX, then return a simple base64-encoded string.

public static byte[] UrlTokenDecode (string input)
{
    if (input == null)
        throw new ArgumentNullException ("input");
    if (input.Length < 1)
        return new byte[0];
    byte[] bytes = Encoding.ASCII.GetBytes (input);
    int inputLength = input.Length - 1;
    int equalsCount = (int)(((char)bytes[inputLength]) - 0x30);
    char[] ret = new char[inputLength + equalsCount];
    int i = 0;
    for (; i < inputLength; i++) {
        switch ((char)bytes[i]) {
            case '-':
                ret[i] = '+';
                break;

            case '_':
                ret[i] = '/';
                break;

            default:
                ret[i] = (char)bytes[i];
                break;
        }
    }
    while (equalsCount > 0) {
        ret[i++] = '=';
        equalsCount--;
    }

    return Convert.FromBase64CharArray (ret, 0, ret.Length);
}

Source

2 Comments

this would not work because my string is not a base64 encoded string. It's encoded in C# using URLTokenEncode which is a bit different than base 64. Please see my update. Thanks.
Thanks @Stefan, but i have the limitation that the string i'm sending from server-side should always be UrlTokenEncoded because if it's encoded by Base64 then in some cases it doesn't work. So i have to decode it client-side.
0

This is possibly against the posting rules as its not an answer to the question but, I found this page whilst looking for the UrlTokenEncode method (not decode) so using the info here I made the following method which I hope helps someone else out:

function urlTokenEncode(str) {
    var b64 = btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
            function(match, t) {
                return String.fromCharCode('0x' + t);
            })),
        padChars = b64.match(/=/g);
    return b64.replace(/=/g, "") + (padChars == null ? 0 : padChars.length);
}

Tested and working with C# HttpServerUtility.UrlTokenEncode and HttpServerUtility.UrlTokenEncode

Comments

-1

read this artical in MDN which describes the problem & solution:

https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="

1 Comment

this would not work because my string is not a base64 encoded string. It's encoded in C# using URLTokenEncode which is a bit different than base64. Please see my update. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.