View: base64_encode

Function:
Description: Encodes string using MIME base64 algorithm.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function base64_encode (data) {
    // http://jsphp.co/jsphp/fn/view/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)
    // +   improved by: Rafał Kukawski (http://kukawski.pl)
    // -    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;
    }

    //UTF-8 encoding should be done outside base64_encode
    //JavaScript strings seem to be represented internally as UTF-16 (or higher)
    //data = this.utf8_encode(data + '');
    data = data + '';

    do { // pack three octets into four hexets
        o1 = data.charCodeAt(i++);
        o2 = data.charCodeAt(i++);
        o3 = data.charCodeAt(i++);

        if ( o1 > 255 || o2 > 255 || o3 > 255 ) { throw new Error( 'Cannot encode UTF-16 string.' ); }

        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('');
    
    var r = data.length % 3;
    
    return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);

}
Comment on base64_encode version 460
Tests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function base64_encode_tests() {

  // API reference: http://docs.jquery.com/QUnit
  module( "base64_encode" );

  function cycle( $value, $utf8_encode ) {

    var $clean_value = $utf8_encode ? utf8_encode( $value ) : $value;

    var $encoded = base64_encode( $clean_value );
    var $decoded = base64_decode( $encoded );

    if ( $utf8_encode ) { $decoded = utf8_decode( $decoded ); }

    equal( $decoded, $value, 'Encoded/decoded equals original value.' );

  }

  test( "base64_encode", function() {

    var data = [
      [ '', '', 0, false ],
      [ 'a', 'YQ==', 1, false ],
      [ 1, 'MQ==', 1, false ],
      [ '1', 'MQ==', 1, false ],
      [ '漢字仮名交じり文', '5ryi5a2X5Luu5ZCN5Lqk44GY44KK5paH', 24, true ]
    ];

    for ( var i in data ) {

      var is_utf16 = data[ i ][ 3 ];
      var utf8 = utf8_encode( data[ i ][ 0 ] );

      equal( base64_encode( utf8 ), data[ i ][ 1 ] );

      cycle( utf8, true );
      cycle( utf8, false );
      cycle( data[ i ][ 0 ], true );

      if ( is_utf16 ) {
        raises(
          function() { cycle( data[ i ][ 0 ], false ); },
          'Cannot encode UTF-16 string.',
          'Cannot encode UTF-16 string.'
        );
      }
      else {
        cycle( data[ i ][ 0 ], false );
      }

      //equal( data[ i ][ 0 ].length, data[ i ][ 2 ] );

    }

  } );

}
Comment on base64_encode version 23 tests
Benchmark
1
2
3
4
5
6
7
8
function base64_encode_benchmark() {

  for ( var i = 0; i < 10000; i++ ) {

    var result = base64_encode( 'hack the planet' );

  }
}
[top]

Comments

<<  <  >  >> Page 1 of 1: 1 Size: -10+10102050100Default
Subject From Date
: base64_encode version 460 John Elliot 2011-12-27 17:08
This function is a bit of a trick. The upstream developers at phpjs.org put in utf-8 encoding and decoding into the function. This is necessary to get the expected behaviour using JavaScript strings instead of PHP strings.

In PHP if you run

  strlen( '漢字仮名交じり文' )
You get 24. In JavaScript if you call

  '漢字仮名交じり文'.length
You get 8. The difference is in how the string is represented in memory. PHP uses binary strings, whereas it seems JavaScript is using a UTF-16 (or higher) representation. This means when you call charCodeAt in JavaScript you might get a value greater than 255.

Anyway, the UTF-8 encoding and decoding by the base64_* functions was creating a problem for me, because sometimes you're already dealing with a 'binary string' in JavaScript, which means the string shouldn't be UTF-8 encoded before base64 coding. So I've moved out the utf8 encoding, and if you want or need utf8 encoding you should do it yourself before passing a value to the base64_encode function.
<<  <  >  >> Page 1 of 1: 1 Size: -10+10102050100Default
Please Login or Register to post comments.