node_nibbler:自定义Base32/base64 encode/decode库

https://github.com/mattrobenolt/node_nibbler

可以将本源码复制到自己需要的JS文件中,比如下面这个文件,一个基于BASE64加密请求参数的REST工具:

【附件:】REST-TEST.html

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>REST-TEST</title>
<script type="text/javascript"
    src="http://libs.baidu.com/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
var Nibbler = function (options) {
    var construct,

        // options
        pad, dataBits, codeBits, keyString, arrayData,

        // private instance variables
        mask, group, max,

        // private methods
        gcd, translate,

        // public methods
        encode, decode,

        utf16to8, utf8to16;

    // pseudo-constructor
    construct = function () {
        var i, mag, prev;

        // options
        pad = options.pad || '';
        dataBits = options.dataBits;
        codeBits = options.codeBits;
        keyString = options.keyString;
        arrayData = options.arrayData;

        // bitmasks
        mag = Math.max(dataBits, codeBits);
        prev = 0;
        mask = [];
        for (i = 0; i < mag; i += 1) {
            mask.push(prev);
            prev += prev + 1;
        }
        max = prev;

        // ouput code characters in multiples of this number
        group = dataBits / gcd(dataBits, codeBits);
    };

    // greatest common divisor
    gcd = function (a, b) {
        var t;
        while (b !== 0) {
            t = b;
            b = a % b;
            a = t;
        }
        return a;
    };

    // the re-coder
    translate = function (input, bitsIn, bitsOut, decoding) {
        var i, len, chr, byteIn,
            buffer, size, output,
            write;

        // append a byte to the output
        write = function (n) {
            if (!decoding) {
                output.push(keyString.charAt(n));
            } else if (arrayData) {
                output.push(n);
            } else {
                output.push(String.fromCharCode(n));
            }
        };

        buffer = 0;
        size = 0;
        output = [];

        len = input.length;
        for (i = 0; i < len; i += 1) {
            // the new size the buffer will be after adding these bits
            size += bitsIn;

            // read a character
            if (decoding) {
                // decode it
                chr = input.charAt(i);
                byteIn = keyString.indexOf(chr);
                if (chr === pad) {
                    break;
                } else if (byteIn < 0) {
                    throw 'the character "' + chr + '" is not a member of ' + keyString;
                }
            } else {
                if (arrayData) {
                    byteIn = input[i];
                } else {
                    byteIn = input.charCodeAt(i);
                }
                if ((byteIn | max) !== max) {
                    throw byteIn + " is outside the range 0-" + max;
                }
            }

            // shift the buffer to the left and add the new bits
            buffer = (buffer << bitsIn) | byteIn;

            // as long as there's enough in the buffer for another output...
            while (size >= bitsOut) {
                // the new size the buffer will be after an output
                size -= bitsOut;

                // output the part that lies to the left of that number of bits
                // by shifting the them to the right
                write(buffer >> size);

                // remove the bits we wrote from the buffer
                // by applying a mask with the new size
                buffer &= mask[size];
            }
        }

        // If we're encoding and there's input left over, pad the output.
        // Otherwise, leave the extra bits off, 'cause they themselves are padding
        if (!decoding && size > 0) {

            // flush the buffer
            write(buffer << (bitsOut - size));

            // add padding keyString for the remainder of the group
            len = output.length % group;
            for (i = 0; i < len; i += 1) {
                output.push(pad);
            }
        }

        // string!
        return (arrayData && decoding) ? output : output.join('');
    };

    /**
     * Encode.  Input and output are strings.
     */
    encode = function (str) {
        //return translate(input, dataBits, codeBits, false);
        str = utf16to8(str);
        var out = "", i = 0, len = str.length, c1, c2, c3, base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                out += base64EncodeChars.charAt(c1 >> 2);
                out += base64EncodeChars.charAt((c1 & 0x3) << 4);
                out += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                out += base64EncodeChars.charAt(c1 >> 2);
                out += base64EncodeChars.charAt(((c1 & 0x3) << 4)
                        | ((c2 & 0xF0) >> 4));
                out += base64EncodeChars.charAt((c2 & 0xF) << 2);
                out += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt(((c1 & 0x3) << 4)
                    | ((c2 & 0xF0) >> 4));
            out += base64EncodeChars.charAt(((c2 & 0xF) << 2)
                    | ((c3 & 0xC0) >> 6));
            out += base64EncodeChars.charAt(c3 & 0x3F);
        }
        return out;
    };

    /**
     * Decode.  Input and output are strings.
     */
    decode = function (str) {
        //return translate(input, codeBits, dataBits, true);
       var c1, c2, c3, c4; var i, len,out;
       var base64DecodeChars = new Array(-1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53,54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1,0, 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, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1);len = str.length; i = 0; out = ""; while (i < len) { do { c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while (i < len && c1 == -1); if (c1 == -1) break; do { c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while (i < len && c2 == -1); if (c2 == -1) break; out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); do { c3 = str.charCodeAt(i++) & 0xff; if (c3 == 61) {out = utf8to16(out);return out;} c3 =     base64DecodeChars[c3]; } while (i < len && c3 == -1); if (c3 == -1) break; out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); do { c4 = str.charCodeAt(i++) & 0xff; if (c4 == 61) {out = utf8to16(out);return out;} c4 = base64DecodeChars[c4]; } while (i < len && c4 == -1); if (c4 == -1) break; out += String.fromCharCode(((c3 & 0x03) << 6) | c4); } out = utf8to16(out);return out;
    };

    utf16to8 = function (str){
        var out, i, len, c;
        out = "";
        len = str.length;
        for (i = 0; i < len; i++) {
            c = str.charCodeAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                out += str.charAt(i);
            } else if (c > 0x07FF) {
                out += String
                        .fromCharCode(0xE0 | ((c >> 12) & 0x0F));
                out += String
                        .fromCharCode(0x80 | ((c >> 6) & 0x3F));
                out += String
                        .fromCharCode(0x80 | ((c >> 0) & 0x3F));
            } else {
                out += String
                        .fromCharCode(0xC0 | ((c >> 6) & 0x1F));
                out += String
                        .fromCharCode(0x80 | ((c >> 0) & 0x3F));
            }
        }
        return out;
    };

    utf8to16 = function (str){
        var out, i, len, c; var char2,char3; out = ""; len = str.length; i = 0; while (i < len) { c = str.charCodeAt(i++); switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: out += str.charAt(i - 1); break; case 12: case 13: char2 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: char2 = str.charCodeAt(i++); char3 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out;
    }
    this.encode = encode;
    this.decode = decode;
    construct();
};
window.Base32 = new Nibbler({
    dataBits: 8,
    codeBits: 5,
    keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
    pad: '='
});
window.Base64 = new Nibbler({
    dataBits: 8,
    codeBits: 6,
    keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    pad: '='
});

window.JSON = new function(){
    var useHasOwn = !!{}.hasOwnProperty;
    var pad = function(n) {
        return n < 10 ? "0" + n : n;
    };

    var m = {
        "": '\b',
        "	": '\t',
        "
": '\n',
        "f": '\f',
        "
": '\r',
        '"' : '\"',
        "\": '\\'
    };

    var encodeString = function(s){
        if (/["\x00-x1f]/.test(s)) {
            return '"' + s.replace(/([x00-x1f\"])/g, function(a, b) {
                var c = m[b];
                if(c){
                    return c;
                }
                c = b.charCodeAt();
                return "\u00" +
                    Math.floor(c / 16).toString(16) +
                    (c % 16).toString(16);
            }) + '"';
        }
        return '"' + s + '"';
    };

    var encodeArray = function(o){
        var a = ["["], b, i, l = o.length, v;
            for (i = 0; i < l; i += 1) {
                v = o[i];
                switch (typeof v) {
                    case "undefined":
                    case "function":
                    case "unknown":
                        break;
                    default:
                        if (b) {
                            a.push(',');
                        }
                        a.push(v === null ? "null" : JSON.encode(v));
                        b = true;
                }
            }
            a.push("]");
            return a.join("");
    };

    var encodeDate = function(o){
        return '"' + o.getFullYear() + "-" +
                pad(o.getMonth() + 1) + "-" +
                pad(o.getDate()) + "T" +
                pad(o.getHours()) + ":" +
                pad(o.getMinutes()) + ":" +
                pad(o.getSeconds()) + '"';
    };

    this.encode = function(o){
        if(typeof o == "undefined" || o === null){
            return "null";
        }else if(o instanceof Array){
            return encodeArray(o);
        }else if(o instanceof Date){
            return encodeDate(o);
        }else if(typeof o == "string"){
            return encodeString(o);
        }else if(typeof o == "number"){
            return isFinite(o) ? String(o) : "null";
        }else if(typeof o == "boolean"){
            return String(o);
        }else {
            var a = ["{"], b, i, v;
            for (i in o) {
                if(!useHasOwn || o.hasOwnProperty(i)) {
                    v = o[i];
                    switch (typeof v) {
                    case "undefined":
                    case "function":
                    case "unknown":
                        break;
                    default:
                        if(b){
                            a.push(',');
                        }
                        a.push(this.encode(i), ":",
                                v === null ? "null" : this.encode(v));
                        b = true;
                    }
                }
            }
            a.push("}");
            return a.join("");
        }
    };
    this.decode = function(json){
        return eval("(" + json + ')');
    };
};
String.space = function (len) {
    var t = [], i;
    for (i = 0; i < len; i++) {
        t.push(' ');
    }
    return t.join('');
};
 function format(msg) {
                var text = msg.split("
").join(" ");
                var t = [];
                var tab = 0;
                var inString = false;
                for (var i = 0, len = text.length; i < len; i++) {
                    var c = text.charAt(i);
                    if (inString && c === inString) {
                        if (text.charAt(i - 1) !== '\') {
                            inString = false;
                        }
                    } else if (!inString && (c === '"' || c === "'")) {
                        inString = c;
                    } else if (!inString && (c === ' ' || c === "	")) {
                        c = '';
                    } else if (!inString && c === ':') {
                        c += ' ';
                    } else if (!inString && c === ',') {
                        c += "
" + String.space(tab * 2);
                    } else if (!inString && (c === '[' || c === '{')) {
                        tab++;
                        c += "
" + String.space(tab * 2);
                    } else if (!inString && (c === ']' || c === '}')) {
                        tab--;
                        c = "
" + String.space(tab * 2) + c;
                    }
                    t.push(c);
                }
                $("#resp").val(t.join(''));
            };
            function getRemoveWhiteSpace(msg) {
                var text =  msg.split("
").join(" ");
                var t = [];
                var inString = false;
                for (var i = 0, len = text.length; i < len; i++) {
                    var c = text.charAt(i);
                    if (inString && c === inString) {
                        // TODO: \"
                        if (text.charAt(i - 1) !== '\') {
                            inString = false;
                        }
                    } else if (!inString && (c === '"' || c === "'")) {
                        inString = c;
                    } else if (!inString && (c === ' ' || c === "	")) {
                        c = '';
                    }
                    t.push(c);
                }
                $("#resp").val(t.join(''));
            };
            $(document).ready(function(){
//                $("#reqMethod").change(function(e){
//                    if("GET"==$("#reqMethod").val()){
//                        $("#paramDiv").hide();
//                    }else{
//                        $("#paramDiv").show();
//                    }
//                }).change();
                $("#sub").click(function(e){
                var paramData=null;
//                if("POST"==$("#reqMethod").val()){
                    if(null!=$("#reqParam").val() && $("#reqParam").val().length>=2){
                        paramData=Base64.encode($("#reqParam").val());
                    }
//                };
                    $.ajax({
                    url:$("#reqUrl").val(),
                    type:$("#reqMethod").val(),
                    dataType:"text",
                    data:paramData,
                    success:function(msg){
                        $("#resp").val(msg);
                    },
                    error:function(XMLHttpRequest, textStatus, errorThrown){
                        $("#resp").val("请求有误");
                    }
                    });
                });
                $("#decode").click(function(e){
                    $("#resp").val(Base64.decode($("#resp").val()));
                });
                $("#encode").click(function(e){
                    $("#resp").val(Base64.encode($("#resp").val()));
                });
                $("#format").click(function(e){
                    format($("#resp").val());
                });
                $("#removeWhite").click(function(e){
                    getRemoveWhiteSpace($("#resp").val());
                });
                $("#clearLeft").click(function(e){
                    $("#reqUrl").val("");
                     $("#reqParam").val("");
                });
                $("#clearRight").click(function(e){
                    $("#resp").val("");
                });
        });
        </script>
</head>
<body bossAnalyOpType="add">
    <div style="float: left; padding-top: 20px;">
        <span>url:</span></br><textarea type="text" style=" 450px; height: 150px;" id="reqUrl"></textarea></br>
        </br> <span>方式:</span><select id="reqMethod"><option value="GET"
                selected="true">GET</option>
            <option value="POST">POST</option></select></br>
        </br>
        <div id="paramDiv">
            <div>参数:</div>
            <textarea id="reqParam" style=" 450px; height: 150px;"
                placeholder="编码前的参数"></textarea>
        </div>
    </div>
    <div style="float: left; padding-left: 50px; padding-top: 80px;">
        <button id="clearLeft" value="清空左侧">清空左侧</button></br></br>
        <button id="clearRight" value="清空右侧">清空右侧</button></br></br>
        <button id="sub" value="提交">提交</button>
    </div>
    <div style="float: left; padding-left: 50px;">
        <span>返回结果:</span></br>
        <div>
            <textarea id="resp" style=" 500px; height: 400px;"></textarea>
            </br>
            <button id="decode">base64解码</button>
            <button id="encode">base64编码</button>
            <button id="format">
                JSON格式化
                </buttion>
                <button id="removeWhite">
                    JSON反格式化
                    </buttion>
                    <div></div>
</body>
</html>
原文地址:https://www.cnblogs.com/fhtwins/p/5569921.html