JavaScript base64_encode
Encodes string using MIME base64 algorithm
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 4546 47 48 49 5051 52 53 54 5556 57 58 | function base64_encode (data) { // Encodes string using MIME base64 algorithm // // version: 909.322 // discuss at: http://phpjs.org/functions/base64_encode // + original by: Tyler Akins (http://rumkin.com) // + improved by: Bayron Guevara // + improved by: Thunder.m // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Pellentesque Malesuada // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // - depends on: utf8_encode // * example 1: base64_encode('Kevin van Zonneveld'); // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' // mozilla has this native // - but breaks in 2.0.0.12! //if (typeof this.window['atob'] == 'function') { // return atob(data); //} var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = []; if (!data) { return data; } data = this.utf8_encode(data+''); do { // pack three octets into four hexets o1 = data.charCodeAt(i++); o2 = data.charCodeAt(i++); o3 = data.charCodeAt(i++); bits = o1<<16 | o2<<8 | o3; h1 = bits>>18 & 0x3f; h2 = bits>>12 & 0x3f; h3 = bits>>6 & 0x3f; h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); } while (i < data.length); enc = tmp_arr.join(''); switch (data.length % 3) { case 1: enc = enc.slice(0, -2) + '=='; break; case 2: enc = enc.slice(0, -1) + '='; break; } return enc; } |
Examples
Running
1 | base64_encode('Kevin van Zonneveld'); |
Should return
1 | 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' |
Dependencies
In order to use this function, you also need:
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have base64_encode goodness in JavaScript.
_.encode = function( a )
{
return ( a + '' ).replace( /[^\x00-\xFF]/g, function( a )
{
a = a.charCodeAt();
return a < 2048 ? _.unicode( a >> 6 | 192 ) + _.unicode( a & 63 | 128 ) : _.unicode( a >> 12 | 224 ) + _.unicode( a >> 6 & 63 | 128 ) + _.unicode( a & 63 | 128 );
} );
},
_.base64_encode = function( a )
{
a = _.encode( a );
for ( var s = 0, d = a.length, f = '', r; s < d; r = a.charCodeAt( s++ ) << 16 | a.charCodeAt( s++ ) << 8 | a.charCodeAt( s++ ), f += base64.charAt( r >> 18 & 0x3F ) + base64.charAt( r >> 12 & 0x3F ) + base64.charAt( r >> 6 & 0x3F ) + base64.charAt( r & 0x3F ) );
return ( d %= 3 ) ? d > 1 ? f.slice( 0, -1 ) + '=' : f.slice( 0, -2 ) + '==' : f;
},
@Ulrich: I assume the function creators were trying to just make it more convenient for themselves in handling newlines in a uniform way, but as you are correct that this is not the PHP way, and it should not be the job of this function to streamline newlines, I've applied your fix in SVN (i.e., removing the newline replaces).
Ok, I was a bit wrong with my previouse post...
It looks like if JavaScript is handling strings in a different way and not as byte arrays, so utf8_encode seems to be required. But I still wonder why \r has to be replaced.
I don't understand, why you are doing an utf8-encoding before encoding the data with base64. If we assume that our string "data" is just a byte array, it does not have any encoding. Base64 will work on a byte array and it shouldn't care about encoding. As far as I can see utf8-encoding is also destroying the data. If \r gets replaced by \n, for example, information is lost.
PHP example (File encoding is UTF-8):
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 | <?php $str1_1 = chr(0xc4); // iso 8859-1 "Ä" $str1_2 = "Ä"; $str2 = "\n";$str3 = "\r"; $str4 = "\r\n"; echo $str1_1, "\n"; echo $str1_2, "\n";echo $str2, "\n"; echo $str3, "\n"; echo $str4, "\n"; echo "---\n"; echo base64_encode($str1_1), "\n"; echo base64_encode($str1_2), "\n"; echo base64_encode($str2), "\n"; echo base64_encode($str3), "\n";echo base64_encode($str4), "\n"; echo "===\n"; echo utf8_encode($str1_1), "\n";echo utf8_encode($str1_2), "\n"; echo utf8_encode($str2), "\n"; echo utf8_encode($str3), "\n"; echo utf8_encode($str4), "\n"; echo "---\n"; echo base64_encode(utf8_encode($str1_1)), "\n"; echo base64_encode(utf8_encode($str1_2)), "\n"; echo base64_encode(utf8_encode($str2)), "\n";echo base64_encode(utf8_encode($str3)), "\n"; echo base64_encode(utf8_encode($str4)), "\n"; ?> |
RESULT:
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 | $ php php_test.php Ä --- xA==w4Q= Cg== DQ== DQo= ===Ä Ã --- w4Q= w4PChA==Cg== DQ== DQo= |
Or does JavaScript handles strings in a different way?
@ Thunder.m: Thank you for testing it in 2.0.0.12. It appears various versions handle atob() functions differently. Doing a browser version check isn't very reliable, so I guess I will fall back to the original function which works consistently in all JavaScript browsers. The fixed version will be visible shortly.
Hi, the mozilla atob function is not working well in my Firefox 2.0.0.12, there are some realy serious issues, so i think it shuld be removed, or tested more intensively.
@ Howard Yeend & TXGruppi: I've added a:
1 2 3 4 | // mozilla has this native if (typeof window['atob'] == 'function') { return atob(data); } |
To make use of mozilla's native base64 functions.
This function (base64_encode and decode) is not correct for utf strings.
Here is working solution: http://www.webtoolkit.info/javascript-base64.html
"check on the existance of the btoa function and then decide which method to use"
oops. just read that.
Confirmed btoa and atob working on:
* Safaru 3.0.4 under windows
* Firefox 2.0.0.13 under windows
Not working in:
* Any version of MSIE.
Instead of using a UA check, why not do this:
1 2 3 4 56 7 8 9 1011 | if(!function_exists(atob)) { function atob() { // funky b64 code here } } if(!function_exists(btoa)) { function btoa() { // funky b64 code here }} |
@ TXGruppi: Wow didn't know about that. Googling gave me the idea that this is mozilla only however. Can you confirm this? If so, we can always build in a browsercheck or a check on the existance of the btoa function and then decide which method to use
Reading the functions I found the base64_encode and base64_decode in a way very complicated.
There are the functions btoa and atob in JavaScript that make this conversion.
1
2
3
4
56
| var name = 'JavaScript'; var enc = btoa(name); var dec = atob(enc); alert(name); // JavaScript alert(enc); // SmF2YVNjcmlwdA==alert(dec); // JavaScript |
Any questions send me an email: txgruppi@gmail.com
Translated by: Google Translator
@ Bayron Guevara: Thank you I've updated the function and credited you in the comments! If you have thoughts on new functions as well, let me know!
I suggest the following code, because I think is faster:
function base64_encode(data) {
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
do { // pack three octets into four hexets
o1 = data.charCodeAt(i++);
o2 = data.charCodeAt(i++);
o3 = data.charCodeAt(i++);
bits = o1<<16 | o2<<8 | o3;
h1 = bits>>18 & 0x3f;
h2 = bits>>12 & 0x3f;
h3 = bits>>6 & 0x3f;
h4 = bits & 0x3f;
// use hexets to index into b64, and append result to encoded string
enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
} while (i < data.length);
switch( data.length % 3 ){
case 1:
enc = enc.slice(0, -2) + '==';
break;
case 2:
enc = enc.slice(0, -1) + '=';
}
return enc;
}



zeroneta
Jan 5th