Add simple android client.
[odfkit:webodf.git] / android / assets / lib / core / Base64.js
1 /*jslint bitwise: false*/
2 /*global core runtime*/
3 /*
4  * $Id: base64.js,v 0.9 2009/03/01 20:51:18 dankogai Exp dankogai $
5  */
6 /**
7  * @namespace
8  */
9 core.Base64 = (function () {
10     var b64chars
11         = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
12     
13         b64charcodes = (function () {
14             var a = [], i,
15                 codeA = 'A'.charCodeAt(0),
16                 codea = 'a'.charCodeAt(0),
17                 code0 = '0'.charCodeAt(0);
18             for (i = 0; i < 26; i += 1) {
19                 a.push(codeA + i);
20             }
21             for (i = 0; i < 26; i += 1) {
22                 a.push(codea + i);
23             }
24             for (i = 0; i < 10; i += 1) {
25                 a.push(code0 + i);
26             }
27             a.push('+'.charCodeAt(0));
28             a.push('/'.charCodeAt(0));
29             return a;
30         }()),
31     
32         b64tab = (function (bin) {
33             var t = {}, i, l;
34             for (i = 0, l = bin.length; i < l; i += 1) {
35                 t[bin.charAt(i)] = i;
36             }
37             return t;
38         }(b64chars)),
39         convertUTF16StringToBase64,
40         convertBase64ToUTF16String,
41         btoa, atob;
42
43     /**
44      * @param {!string} s
45      * @return {!Array}
46      */
47     function stringToArray(s) {
48         var a = [], i, l = s.length;
49         for (i = 0; i < l; i += 1) {
50             a[i] = s.charCodeAt(i) & 0xff;
51         }
52         return a;
53     }
54     
55     function convertUTF8ArrayToBase64(bin) {
56         var padlen = 0,
57             b64 = [],
58             i, l = bin.length,
59             c0, c1, c2, n;
60         while (bin.length % 3) {
61             bin.push(0);
62             padlen += 1;
63         }
64         for (i = 0; i < l; i += 3) {
65             c0 = bin[i];
66             c1 = bin[i + 1];
67             c2 = bin[i + 2];
68             if (c0 >= 256 || c1 >= 256 || c2 >= 256) {
69                 throw 'unsupported character found ' + c0 + ' ' + c1 + ' ' + c2;
70             }
71             n = (c0 << 16) | (c1 << 8) | c2;
72             b64.push(
73                 b64charcodes[n >>> 18],
74                 b64charcodes[(n >>> 12) & 63],
75                 b64charcodes[(n >>>  6) & 63],
76                 b64charcodes[n          & 63]
77             );
78         }
79         for (padlen -= 1; padlen >= 0; padlen -= 1) {
80             b64[b64.length - padlen - 1] = '='.charCodeAt(0);
81         }
82         return String.fromCharCode.apply(String, b64);
83     }
84     
85     function convertBase64ToUTF8Array(b64) {
86         b64 = b64.replace(/[^A-Za-z0-9+\/]+/g, '');
87         var bin = [],
88             padlen = b64.length % 4,
89             i, l = b64.length, n;
90         for (i = 0; i < l; i += 4) {
91             n = ((b64tab[b64.charAt(i)]     || 0) << 18) |
92                 ((b64tab[b64.charAt(i + 1)] || 0) << 12) |
93                 ((b64tab[b64.charAt(i + 2)] || 0) <<  6) |
94                 ((b64tab[b64.charAt(i + 3)] || 0));
95             bin.push(
96                 (n >> 16),
97                 ((n >>  8) & 0xff),
98                 (n         & 0xff)
99             );
100         }
101         bin.length -= [0, 0, 2, 1][padlen];
102         return bin;
103     }
104     
105     function convertUTF16ArrayToUTF8Array(uni) {
106         var bin = [], i, l = uni.length, n;
107         for (i = 0; i < l; i += 1) {
108             n = uni[i];
109             if (n < 0x80) {
110                 bin.push(n);
111             } else if (n < 0x800) {
112                 bin.push(
113                     0xc0 | (n >>>  6),
114                     0x80 | (n & 0x3f));
115             } else {
116                 bin.push(
117                     0xe0 | ((n >>> 12) & 0x0f),
118                     0x80 | ((n >>>  6) & 0x3f),
119                     0x80 |  (n         & 0x3f));
120             }
121         }
122         return bin;
123     }
124     
125     function convertUTF8ArrayToUTF16Array(bin) {
126         var uni = [], i, l = bin.length,
127             c0, c1, c2;
128         for (i = 0; i < l; i += 1) {
129             c0 = bin[i];
130             if (c0 < 0x80) {
131                 uni.push(c0);
132             } else {
133                 i += 1;
134                 c1 = bin[i];
135                 if (c0 < 0xe0) {
136                     uni.push(((c0 & 0x1f) << 6) | (c1 & 0x3f));
137                 } else {
138                     i += 1;
139                     c2 = bin[i];
140                     uni.push(((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) |
141                             (c2 & 0x3f)
142                     );
143                 }
144             }
145         }
146         return uni;
147     }
148     
149     function convertUTF8StringToBase64(bin) {
150         return convertUTF8ArrayToBase64(stringToArray(bin));
151     }
152     
153     function convertBase64ToUTF8String(b64) {
154         return String.fromCharCode.apply(String, convertBase64ToUTF8Array(b64));
155     }
156     
157     function convertUTF8StringToUTF16Array(bin) {
158         return convertUTF8ArrayToUTF16Array(stringToArray(bin));
159     }
160     
161     function convertUTF8ArrayToUTF16String(bin) {
162         return String.fromCharCode.apply(String, convertUTF8ArrayToUTF16Array(bin));
163     }
164     /**
165      * @param {!Array.<number>|!string} bin
166      * @param {!number} i
167      * @param {!number} end
168      * @return {!string}
169      */
170     function convertUTF8StringToUTF16String_internal(bin, i, end) {
171         var str = "", c0, c1, c2;
172         for (; i < end; i += 1) {
173             c0 = bin.charCodeAt(i) & 0xff;
174             if (c0 < 0x80) {
175                 str += String.fromCharCode(c0);
176             } else {
177                 i += 1;
178                 c1 = bin.charCodeAt(i) & 0xff;
179                 if (c0 < 0xe0) {
180                     str += String.fromCharCode(((c0 & 0x1f) << 6)|(c1 & 0x3f));
181                 } else {
182                     i += 1;
183                     c2 = bin.charCodeAt(i) & 0xff;
184                     str += String.fromCharCode(((c0 & 0x0f) << 12) |
185                             ((c1 & 0x3f) << 6) | (c2 & 0x3f));
186                 }
187             }
188         }
189         return str;
190     }
191
192     /**
193      * Convert a utf-8 array into a utf-16 string.
194      * The input array is treated as a list of values between 0 and 255.
195      * This function works with a callback and splits the work up in parts
196      * between which it yields to the main thread.
197      * After each part the progress is reported with the callback function that
198      * also passes a booleant that indicates if the job has finished.
199      * If the conversion should stop, the callback should return false.
200      *
201      * @param {!Array.<number>|!string} bin
202      * @param {!function(!string, boolean):boolean} callback
203      * @return {undefined}
204      */
205     function convertUTF8StringToUTF16String(bin, callback) {
206         var partsize = 100000,
207             numparts = bin.length / partsize,
208             str = "",
209             pos = 0;
210         if (bin.length < partsize) {
211             callback(convertUTF8StringToUTF16String_internal(bin, 0,
212                     bin.length), true);
213             return;
214         }
215         // make a local copy if the input is a string, to avoid modification
216         if (typeof bin !== "string") {
217             bin = bin.slice();
218         }
219         function f() {
220             var end = pos + partsize;
221             if (end > bin.length) {
222                 end = bin.length;
223             }
224             str += convertUTF8StringToUTF16String_internal(bin, pos, end);
225             pos = end;
226             end = pos === bin.length;
227             if (callback(str, end) && !end) {
228                 runtime.setTimeout(f, 0);
229             }
230         }
231         f();
232     }
233     
234     function convertUTF16StringToUTF8Array(uni) {
235         return convertUTF16ArrayToUTF8Array(stringToArray(uni));
236     }
237     
238     function convertUTF16ArrayToUTF8String(uni) {
239         return String.fromCharCode.apply(String, convertUTF16ArrayToUTF8Array(uni));
240     }
241     
242     function convertUTF16StringToUTF8String(uni) {
243         return String.fromCharCode.apply(String, convertUTF16ArrayToUTF8Array(stringToArray(uni)));
244     }
245
246     btoa = runtime.getWindow() && runtime.getWindow().btoa; 
247     if (btoa) {
248         convertUTF16StringToBase64 = function (uni) {
249             return btoa(convertUTF16StringToUTF8String(uni));
250         };
251     } else {
252         btoa = convertUTF8StringToBase64;
253         convertUTF16StringToBase64 = function (uni) {
254             return convertUTF8ArrayToBase64(convertUTF16StringToUTF8Array(uni));
255         };
256     }
257     atob = runtime.getWindow() && runtime.getWindow().atob;
258     if (atob) {
259         convertBase64ToUTF16String = function (b64) {
260             var b = atob(b64);
261             return convertUTF8StringToUTF16String_internal(b, 0, b.length);
262         };
263     } else {
264         atob = convertBase64ToUTF8String;
265         convertBase64ToUTF16String = function (b64) {
266             return convertUTF8ArrayToUTF16String(convertBase64ToUTF8Array(b64));
267         };
268     }
269
270     /**
271      * @constructor
272      */ 
273     function Base64() {
274         this.convertUTF8ArrayToBase64 = convertUTF8ArrayToBase64;
275         this.convertByteArrayToBase64 = convertUTF8ArrayToBase64;
276         this.convertBase64ToUTF8Array = convertBase64ToUTF8Array;
277         this.convertBase64ToByteArray = convertBase64ToUTF8Array;
278         this.convertUTF16ArrayToUTF8Array = convertUTF16ArrayToUTF8Array;
279         this.convertUTF16ArrayToByteArray = convertUTF16ArrayToUTF8Array;
280         this.convertUTF8ArrayToUTF16Array = convertUTF8ArrayToUTF16Array;
281         this.convertByteArrayToUTF16Array = convertUTF8ArrayToUTF16Array;
282         this.convertUTF8StringToBase64 = convertUTF8StringToBase64;
283         this.convertBase64ToUTF8String = convertBase64ToUTF8String;
284         this.convertUTF8StringToUTF16Array = convertUTF8StringToUTF16Array;
285         this.convertUTF8ArrayToUTF16String = convertUTF8ArrayToUTF16String;
286         this.convertByteArrayToUTF16String = convertUTF8ArrayToUTF16String;
287         this.convertUTF8StringToUTF16String = convertUTF8StringToUTF16String;
288         this.convertUTF16StringToUTF8Array = convertUTF16StringToUTF8Array;
289         this.convertUTF16StringToByteArray = convertUTF16StringToUTF8Array;
290         this.convertUTF16ArrayToUTF8String = convertUTF16ArrayToUTF8String;
291         this.convertUTF16StringToUTF8String = convertUTF16StringToUTF8String;
292         this.convertUTF16StringToBase64 = convertUTF16StringToBase64;
293         this.convertBase64ToUTF16String = convertBase64ToUTF16String;
294         this.fromBase64 = convertBase64ToUTF8String;
295         this.toBase64 = convertUTF8StringToBase64;
296         this.atob = atob;
297         this.btoa = btoa;
298         this.utob = convertUTF16StringToUTF8String;
299         this.btou = convertUTF8StringToUTF16String;
300         this.encode = convertUTF16StringToBase64;
301         this.encodeURI = function (u) {
302             return convertUTF16StringToBase64(u).replace(/[+\/]/g,
303                     function (m0) {
304                 return m0 === '+' ? '-' : '_';
305             }).replace(/=+$/, '');
306         };
307         this.decode =function(a){
308             return convertBase64ToUTF16String(a.replace(/[-_]/g, function(m0){
309                 return m0 == '-' ? '+' : '/';
310             }));
311         };
312     };
313     return Base64;
314 })();