|
1 | 1 | /* |
2 | | - * $Id: base64.js,v 1.2 2011/12/27 14:34:49 dankogai Exp dankogai $ |
| 2 | + * $Id: base64.js,v 2.6 2012/08/24 05:23:18 dankogai Exp dankogai $ |
3 | 3 | * |
4 | 4 | * Licensed under the MIT license. |
5 | 5 | * http://www.opensource.org/licenses/mit-license.php |
6 | 6 | * |
| 7 | + * References: |
| 8 | + * http://en.wikipedia.org/wiki/Base64 |
7 | 9 | */ |
8 | 10 |
|
9 | | -(function(global){ |
10 | | - |
11 | | -if (global.Base64) return; |
12 | | - |
13 | | -var b64chars |
| 11 | +(function(global) { |
| 12 | +'use strict'; |
| 13 | +// if node.js, we use Buffer |
| 14 | +var buffer; |
| 15 | +if (typeof module !== 'undefined' && module.exports) { |
| 16 | + buffer = require('buffer').Buffer; |
| 17 | +} |
| 18 | +// constants |
| 19 | +var b64chars |
14 | 20 | = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
15 | | -var b64tab = function(bin){ |
| 21 | +var b64tab = function(bin) { |
16 | 22 | var t = {}; |
17 | 23 | for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i; |
18 | 24 | return t; |
19 | 25 | }(b64chars); |
20 | | - |
21 | | -var sub_toBase64 = function(m){ |
22 | | - var n = (m.charCodeAt(0) << 16) |
23 | | - | (m.charCodeAt(1) << 8) |
24 | | - | (m.charCodeAt(2) ); |
25 | | - return b64chars.charAt( n >>> 18) |
26 | | - + b64chars.charAt((n >>> 12) & 63) |
27 | | - + b64chars.charAt((n >>> 6) & 63) |
28 | | - + b64chars.charAt( n & 63); |
| 26 | +var fromCharCode = String.fromCharCode; |
| 27 | +// encoder stuff |
| 28 | +var cb_utob = function(c) { |
| 29 | + var cc = c.charCodeAt(0); |
| 30 | + return cc < 0x80 ? c |
| 31 | + : cc < 0x800 ? fromCharCode(0xc0 | (cc >>> 6)) |
| 32 | + + fromCharCode(0x80 | (cc & 0x3f)) |
| 33 | + : fromCharCode(0xe0 | ((cc >>> 12) & 0x0f)) |
| 34 | + + fromCharCode(0x80 | ((cc >>> 6) & 0x3f)) |
| 35 | + + fromCharCode(0x80 | ( cc & 0x3f)); |
29 | 36 | }; |
30 | | - |
31 | | -var toBase64 = function(bin){ |
32 | | - if (bin.match(/[^\x00-\xFF]/)) throw 'unsupported character found' ; |
33 | | - var padlen = 0; |
34 | | - while(bin.length % 3) { |
35 | | - bin += '\0'; |
36 | | - padlen++; |
37 | | - }; |
38 | | - var b64 = bin.replace(/[\x00-\xFF]{3}/g, sub_toBase64); |
39 | | - if (!padlen) return b64; |
40 | | - b64 = b64.substr(0, b64.length - padlen); |
41 | | - while(padlen--) b64 += '='; |
42 | | - return b64; |
| 37 | +var utob = function(u) { |
| 38 | + return u.replace(/[^\x00-\x7F]/g, cb_utob); |
43 | 39 | }; |
44 | | - |
45 | | -var btoa = global.btoa || toBase64; |
46 | | - |
47 | | -var sub_fromBase64 = function(m){ |
48 | | - var n = (b64tab[ m.charAt(0) ] << 18) |
49 | | - | (b64tab[ m.charAt(1) ] << 12) |
50 | | - | (b64tab[ m.charAt(2) ] << 6) |
51 | | - | (b64tab[ m.charAt(3) ]); |
52 | | - return String.fromCharCode( n >> 16 ) |
53 | | - + String.fromCharCode( (n >> 8) & 0xff ) |
54 | | - + String.fromCharCode( n & 0xff ); |
| 40 | +var cb_encode = function(ccc) { |
| 41 | + var padlen = [0, 2, 1][ccc.length % 3], |
| 42 | + ord = ccc.charCodeAt(0) << 16 |
| 43 | + | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8) |
| 44 | + | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)), |
| 45 | + chars = [ |
| 46 | + b64chars.charAt( ord >>> 18), |
| 47 | + b64chars.charAt((ord >>> 12) & 63), |
| 48 | + padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63), |
| 49 | + padlen >= 1 ? '=' : b64chars.charAt(ord & 63) |
| 50 | + ]; |
| 51 | + return chars.join(''); |
55 | 52 | }; |
56 | | - |
57 | | -var fromBase64 = function(b64){ |
58 | | - b64 = b64.replace(/[^A-Za-z0-9\+\/]/g, ''); |
59 | | - var padlen = 0; |
60 | | - while(b64.length % 4){ |
61 | | - b64 += 'A'; |
62 | | - padlen++; |
63 | | - } |
64 | | - var bin = b64.replace(/[A-Za-z0-9\+\/]{4}/g, sub_fromBase64); |
65 | | - if (padlen >= 2) |
66 | | - bin = bin.substring(0, bin.length - [0,0,2,1][padlen]); |
67 | | - return bin; |
| 53 | +var btoa = global.btoa || function(b) { |
| 54 | + return b.replace(/[\s\S]{1,3}/g, cb_encode); |
68 | 55 | }; |
69 | | - |
70 | | -var atob = global.atob || fromBase64; |
71 | | - |
72 | | -var re_char_nonascii = /[^\x00-\x7F]/g; |
73 | | - |
74 | | -var sub_char_nonascii = function(m){ |
75 | | - var n = m.charCodeAt(0); |
76 | | - return n < 0x800 ? String.fromCharCode(0xc0 | (n >>> 6)) |
77 | | - + String.fromCharCode(0x80 | (n & 0x3f)) |
78 | | - : String.fromCharCode(0xe0 | ((n >>> 12) & 0x0f)) |
79 | | - + String.fromCharCode(0x80 | ((n >>> 6) & 0x3f)) |
80 | | - + String.fromCharCode(0x80 | (n & 0x3f)) |
81 | | - ; |
| 56 | +var _encode = buffer |
| 57 | + ? function (u) { return (new buffer(u)).toString('base64') } |
| 58 | + : function (u) { return btoa(utob(u)) } |
| 59 | + ; |
| 60 | +var encode = function(u, urisafe) { |
| 61 | + return !urisafe |
| 62 | + ? _encode(u) |
| 63 | + : _encode(u).replace(/[+\/]/g, function(m0) { |
| 64 | + return m0 == '+' ? '-' : '_'; |
| 65 | + }); |
82 | 66 | }; |
83 | | - |
84 | | -var utob = function(uni){ |
85 | | - return uni.replace(re_char_nonascii, sub_char_nonascii); |
| 67 | +var encodeURI = function(u) { return encode(u, true) }; |
| 68 | +// decoder stuff |
| 69 | +var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}/g; |
| 70 | +var cb_btou = function(ccc) { |
| 71 | + return fromCharCode( |
| 72 | + ccc.length < 3 ? ((0x1f & ccc.charCodeAt(0)) << 6) |
| 73 | + | (0x3f & ccc.charCodeAt(1)) |
| 74 | + : ((0x0f & ccc.charCodeAt(0)) << 12) |
| 75 | + | ((0x3f & ccc.charCodeAt(1)) << 6) |
| 76 | + | (0x3f & ccc.charCodeAt(2)) |
| 77 | + ); |
86 | 78 | }; |
87 | | - |
88 | | -var re_bytes_nonascii |
89 | | - = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g; |
90 | | - |
91 | | -var sub_bytes_nonascii = function(m){ |
92 | | - var c0 = m.charCodeAt(0); |
93 | | - var c1 = m.charCodeAt(1); |
94 | | - if(c0 < 0xe0){ |
95 | | - return String.fromCharCode(((c0 & 0x1f) << 6) | (c1 & 0x3f)); |
96 | | - }else{ |
97 | | - var c2 = m.charCodeAt(2); |
98 | | - return String.fromCharCode( |
99 | | - ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f) |
100 | | - ); |
101 | | - } |
| 79 | +var btou = function(b) { |
| 80 | + return b.replace(re_btou, cb_btou); |
102 | 81 | }; |
103 | | - |
104 | | -var btou = function(bin){ |
105 | | - return bin.replace(re_bytes_nonascii, sub_bytes_nonascii); |
| 82 | +var cb_decode = function(cccc) { |
| 83 | + var len = cccc.length, |
| 84 | + padlen = len % 4, |
| 85 | + n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0) |
| 86 | + | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0) |
| 87 | + | (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0) |
| 88 | + | (len > 3 ? b64tab[cccc.charAt(3)] : 0), |
| 89 | + chars = [ |
| 90 | + fromCharCode( n >>> 16), |
| 91 | + fromCharCode((n >>> 8) & 0xff), |
| 92 | + fromCharCode( n & 0xff) |
| 93 | + ]; |
| 94 | + chars.length -= [0, 0, 2, 1][padlen]; |
| 95 | + return chars.join(''); |
106 | 96 | }; |
107 | | - |
| 97 | +var atob = global.atob || function(a){ |
| 98 | + return a.replace(/[\s\S]{1,4}/g, cb_decode); |
| 99 | +}; |
| 100 | +var _decode = buffer |
| 101 | + ? function(a) { return (new buffer(a, 'base64')).toString() } |
| 102 | + : function(a) { return btou(atob(a)) } |
| 103 | + ; |
| 104 | +var decode = function(a){ |
| 105 | + return _decode( |
| 106 | + a.replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' }) |
| 107 | + .replace(/[^A-Za-z0-9\+\/]/g, '') |
| 108 | + ); |
| 109 | +}; |
| 110 | +// export Base64 |
108 | 111 | global.Base64 = { |
109 | | - fromBase64:fromBase64, |
110 | | - toBase64:toBase64, |
111 | | - atob:atob, |
112 | | - btoa:btoa, |
113 | | - utob:utob, |
114 | | - btou:btou, |
115 | | - encode:function(u){ return btoa(utob(u)) }, |
116 | | - encodeURI:function(u){ |
117 | | - return btoa(utob(u)).replace(/[+\/]/g, function(m0){ |
118 | | - return m0 == '+' ? '-' : '_'; |
119 | | - }).replace(/=+$/, ''); |
120 | | - }, |
121 | | - decode:function(a){ |
122 | | - return btou(atob(a.replace(/[-_]/g, function(m0){ |
123 | | - return m0 == '-' ? '+' : '/'; |
124 | | - }))); |
125 | | - } |
| 112 | + atob: atob, |
| 113 | + btoa: btoa, |
| 114 | + fromBase64: decode, |
| 115 | + toBase64: encode, |
| 116 | + utob: utob, |
| 117 | + encode: encode, |
| 118 | + encodeURI: encodeURI, |
| 119 | + btou: btou, |
| 120 | + decode: decode |
126 | 121 | }; |
127 | | - |
| 122 | +// if ES5 is available, make Base64.extendString() available |
| 123 | +if (typeof Object.defineProperty === 'function') { |
| 124 | + var noEnum = function(v){ |
| 125 | + return {value:v,enumerable:false,writable:true,configurable:true}; |
| 126 | + }; |
| 127 | + global.Base64.extendString = function () { |
| 128 | + Object.defineProperty( |
| 129 | + String.prototype, 'fromBase64', noEnum(function () { |
| 130 | + return decode(this) |
| 131 | + })); |
| 132 | + Object.defineProperty( |
| 133 | + String.prototype, 'toBase64', noEnum(function (urisafe) { |
| 134 | + return encode(this, urisafe) |
| 135 | + })); |
| 136 | + }; |
| 137 | +} |
| 138 | +// that's it! |
128 | 139 | })(this); |
0 commit comments