Skip to content

Instantly share code, notes, and snippets.

@jmccay-work
Forked from chrisveness/base64.js
Last active March 10, 2022 15:03
Show Gist options
  • Save jmccay-work/f528e37a422e3e7f57f7cd1e84e8c67d to your computer and use it in GitHub Desktop.
Save jmccay-work/f528e37a422e3e7f57f7cd1e84e8c67d to your computer and use it in GitHub Desktop.

Revisions

  1. jmccay-work revised this gist Mar 10, 2022. 1 changed file with 82 additions and 67 deletions.
    149 changes: 82 additions & 67 deletions base64.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,12 @@
    /**
    * base64.js
    * Original author: Chris Veness
    * Repository: https://gist.github.com/chrisveness/e121cffb51481bd1c142
    * License: MIT (According to a comment).
    *
    * 03/09/2022 JLM Updated to ES6 and strict.
    */

    /**
    * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].
    * As per RFC 4648, no newlines are added.
    @@ -9,72 +18,78 @@
    * @param {string} str ASCII/ISO-8859-1 string to be encoded as base-64.
    * @returns {string} Base64-encoded string.
    */
    function Base64Encode(str) {
    if (/([^\u0000-\u00ff])/.test(str)) throw Error('String must be ASCII');

    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c;

    c = str.length % 3; // pad string to length of multiple of 3
    if (c > 0) { while (c++ < 3) { pad += '='; str += '\0'; } }
    // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars

    for (c=0; c<str.length; c+=3) { // pack three octets into four hexets
    o1 = str.charCodeAt(c);
    o2 = str.charCodeAt(c+1);
    o3 = str.charCodeAt(c+2);

    bits = o1<<16 | o2<<8 | o3;

    h1 = bits>>18 & 0x3f;
    h2 = bits>>12 & 0x3f;
    h3 = bits>>6 & 0x3f;
    h4 = bits & 0x3f;

    // use hextets to index into code string
    e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    }
    str = e.join(''); // use Array.join() for better performance than repeated string appends

    // replace 'A's from padded nulls with '='s
    str = str.slice(0, str.length-pad.length) + pad;

    return str;
    }

    /**
    * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].
    * As per RFC 4648, newlines are not catered for.
    *
    * Can be achieved JavaScript with atob(), but this approach may be useful in other languages.
    *
    * @param {string} str Base64-encoded string.
    * @returns {string} Decoded ASCII/ISO-8859-1 string.
    */
    function Base64Decode(str) {
    if (!(/^[a-z0-9+/]+={0,2}$/i.test(str)) || str.length%4 != 0) throw Error('Not base64 string');

    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, d=[];

    for (var c=0; c<str.length; c+=4) { // unpack four hexets into three octets
    h1 = b64.indexOf(str.charAt(c));
    h2 = b64.indexOf(str.charAt(c+1));
    h3 = b64.indexOf(str.charAt(c+2));
    h4 = b64.indexOf(str.charAt(c+3));

    bits = h1<<18 | h2<<12 | h3<<6 | h4;

    o1 = bits>>>16 & 0xff;
    o2 = bits>>>8 & 0xff;
    o3 = bits & 0xff;
    'use strict'

    d[c/4] = String.fromCharCode(o1, o2, o3);
    // check for padding
    if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2);
    if (h3 == 0x40) d[c/4] = String.fromCharCode(o1);
    }
    str = d.join(''); // use Array.join() for better performance than repeated string appends
    //function base64Encode(str) {
    const base64Encode = (str) => {
    if (/([^\u0000-\u00ff])/.test(str)) throw Error('String must be ASCII');

    let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    let o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c;

    c = str.length % 3; // pad string to length of multiple of 3
    if (c > 0) { while (c++ < 3) { pad += '='; str += '\0'; } }
    // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars

    for (c=0; c<str.length; c+=3) { // pack three octets into four hexets
    o1 = str.charCodeAt(c);
    o2 = str.charCodeAt(c+1);
    o3 = str.charCodeAt(c+2);

    bits = o1<<16 | o2<<8 | o3;

    h1 = bits>>18 & 0x3f;
    h2 = bits>>12 & 0x3f;
    h3 = bits>>6 & 0x3f;
    h4 = bits & 0x3f;

    // use hextets to index into code string
    e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    }
    str = e.join(''); // use Array.join() for better performance than repeated string appends

    // replace 'A's from padded nulls with '='s
    str = str.slice(0, str.length-pad.length) + pad;

    return str;
    }

    /**
    * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].
    * As per RFC 4648, newlines are not catered for.
    *
    * Can be achieved JavaScript with atob(), but this approach may be useful in other languages.
    *
    * @param {string} str Base64-encoded string.
    * @returns {string} Decoded ASCII/ISO-8859-1 string.
    */
    //function Base64Decode(str) {
    const base64Decode = (str) => {
    if (!(/^[a-z0-9+/]+={0,2}$/i.test(str)) || str.length%4 != 0) throw Error('Not base64 string');

    let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    let o1, o2, o3, h1, h2, h3, h4, bits, d=[];

    for (let c=0; c<str.length; c+=4) { // unpack four hexets into three octets
    h1 = b64.indexOf(str.charAt(c));
    h2 = b64.indexOf(str.charAt(c+1));
    h3 = b64.indexOf(str.charAt(c+2));
    h4 = b64.indexOf(str.charAt(c+3));

    bits = h1<<18 | h2<<12 | h3<<6 | h4;

    o1 = bits>>>16 & 0xff;
    o2 = bits>>>8 & 0xff;
    o3 = bits & 0xff;

    d[c/4] = String.fromCharCode(o1, o2, o3);
    // check for padding
    if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2);
    if (h3 == 0x40) d[c/4] = String.fromCharCode(o1);
    }
    str = d.join(''); // use Array.join() for better performance than repeated string appends

    return str;
    }

    return str;
    }

  2. @chrisveness chrisveness revised this gist Mar 17, 2015. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions base64.js
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,8 @@
    * @returns {string} Base64-encoded string.
    */
    function Base64Encode(str) {
    if (/([^\u0000-\u00ff])/.test(str)) throw Error('String must be ASCII');

    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c;

    @@ -50,6 +52,8 @@ function Base64Encode(str) {
    * @returns {string} Decoded ASCII/ISO-8859-1 string.
    */
    function Base64Decode(str) {
    if (!(/^[a-z0-9+/]+={0,2}$/i.test(str)) || str.length%4 != 0) throw Error('Not base64 string');

    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, d=[];

  3. @chrisveness chrisveness created this gist Jun 26, 2014.
    76 changes: 76 additions & 0 deletions base64.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,76 @@
    /**
    * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].
    * As per RFC 4648, no newlines are added.
    *
    * Characters in str must be within ISO-8859-1 with Unicode code point <= 256.
    *
    * Can be achieved JavaScript with btoa(), but this approach may be useful in other languages.
    *
    * @param {string} str ASCII/ISO-8859-1 string to be encoded as base-64.
    * @returns {string} Base64-encoded string.
    */
    function Base64Encode(str) {
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c;

    c = str.length % 3; // pad string to length of multiple of 3
    if (c > 0) { while (c++ < 3) { pad += '='; str += '\0'; } }
    // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars

    for (c=0; c<str.length; c+=3) { // pack three octets into four hexets
    o1 = str.charCodeAt(c);
    o2 = str.charCodeAt(c+1);
    o3 = str.charCodeAt(c+2);

    bits = o1<<16 | o2<<8 | o3;

    h1 = bits>>18 & 0x3f;
    h2 = bits>>12 & 0x3f;
    h3 = bits>>6 & 0x3f;
    h4 = bits & 0x3f;

    // use hextets to index into code string
    e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    }
    str = e.join(''); // use Array.join() for better performance than repeated string appends

    // replace 'A's from padded nulls with '='s
    str = str.slice(0, str.length-pad.length) + pad;

    return str;
    }

    /**
    * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].
    * As per RFC 4648, newlines are not catered for.
    *
    * Can be achieved JavaScript with atob(), but this approach may be useful in other languages.
    *
    * @param {string} str Base64-encoded string.
    * @returns {string} Decoded ASCII/ISO-8859-1 string.
    */
    function Base64Decode(str) {
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, d=[];

    for (var c=0; c<str.length; c+=4) { // unpack four hexets into three octets
    h1 = b64.indexOf(str.charAt(c));
    h2 = b64.indexOf(str.charAt(c+1));
    h3 = b64.indexOf(str.charAt(c+2));
    h4 = b64.indexOf(str.charAt(c+3));

    bits = h1<<18 | h2<<12 | h3<<6 | h4;

    o1 = bits>>>16 & 0xff;
    o2 = bits>>>8 & 0xff;
    o3 = bits & 0xff;

    d[c/4] = String.fromCharCode(o1, o2, o3);
    // check for padding
    if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2);
    if (h3 == 0x40) d[c/4] = String.fromCharCode(o1);
    }
    str = d.join(''); // use Array.join() for better performance than repeated string appends

    return str;
    }