Mercurial > hg > LGMap
comparison geotemco/lib/jszip/jszip.js @ 0:57bde4830927
first commit
author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
---|---|
date | Tue, 24 Mar 2015 11:37:17 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:57bde4830927 |
---|---|
1 /** | |
2 | |
3 JSZip - A Javascript class for generating and reading zip files | |
4 <http://stuartk.com/jszip> | |
5 | |
6 (c) 2009-2012 Stuart Knightley <stuart [at] stuartk.com> | |
7 Dual licenced under the MIT license or GPLv3. See LICENSE.markdown. | |
8 | |
9 Usage: | |
10 zip = new JSZip(); | |
11 zip.file("hello.txt", "Hello, World!").add("tempfile", "nothing"); | |
12 zip.folder("images").file("smile.gif", base64Data, {base64: true}); | |
13 zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")}); | |
14 zip.remove("tempfile"); | |
15 | |
16 base64zip = zip.generate(); | |
17 | |
18 **/ | |
19 | |
20 /** | |
21 * Representation a of zip file in js | |
22 * @constructor | |
23 * @param {String=|ArrayBuffer=|Uint8Array=} data the data to load, if any (optional). | |
24 * @param {Object=} options the options for creating this objects (optional). | |
25 */ | |
26 var JSZip = function(data, options) { | |
27 // object containing the files : | |
28 // { | |
29 // "folder/" : {...}, | |
30 // "folder/data.txt" : {...} | |
31 // } | |
32 this.files = {}; | |
33 | |
34 // Where we are in the hierarchy | |
35 this.root = ""; | |
36 | |
37 if (data) { | |
38 this.load(data, options); | |
39 } | |
40 }; | |
41 | |
42 JSZip.signature = { | |
43 LOCAL_FILE_HEADER : "\x50\x4b\x03\x04", | |
44 CENTRAL_FILE_HEADER : "\x50\x4b\x01\x02", | |
45 CENTRAL_DIRECTORY_END : "\x50\x4b\x05\x06", | |
46 ZIP64_CENTRAL_DIRECTORY_LOCATOR : "\x50\x4b\x06\x07", | |
47 ZIP64_CENTRAL_DIRECTORY_END : "\x50\x4b\x06\x06", | |
48 DATA_DESCRIPTOR : "\x50\x4b\x07\x08" | |
49 }; | |
50 | |
51 // Default properties for a new file | |
52 JSZip.defaults = { | |
53 base64: false, | |
54 binary: false, | |
55 dir: false, | |
56 date: null | |
57 }; | |
58 | |
59 | |
60 JSZip.prototype = (function () { | |
61 /** | |
62 * A simple object representing a file in the zip file. | |
63 * @constructor | |
64 * @param {string} name the name of the file | |
65 * @param {string} data the data | |
66 * @param {Object} options the options of the file | |
67 */ | |
68 var ZipObject = function (name, data, options) { | |
69 this.name = name; | |
70 this.data = data; | |
71 this.options = options; | |
72 }; | |
73 | |
74 ZipObject.prototype = { | |
75 /** | |
76 * Return the content as UTF8 string. | |
77 * @return {string} the UTF8 string. | |
78 */ | |
79 asText : function () { | |
80 var result = this.data; | |
81 if (result === null || typeof result === "undefined") { | |
82 return ""; | |
83 } | |
84 if (this.options.base64) { | |
85 result = JSZipBase64.decode(result); | |
86 } | |
87 if (this.options.binary) { | |
88 result = JSZip.prototype.utf8decode(result); | |
89 } | |
90 return result; | |
91 }, | |
92 /** | |
93 * Returns the binary content. | |
94 * @return {string} the content as binary. | |
95 */ | |
96 asBinary : function () { | |
97 var result = this.data; | |
98 if (result === null || typeof result === "undefined") { | |
99 return ""; | |
100 } | |
101 if (this.options.base64) { | |
102 result = JSZipBase64.decode(result); | |
103 } | |
104 if (!this.options.binary) { | |
105 result = JSZip.prototype.utf8encode(result); | |
106 } | |
107 return result; | |
108 }, | |
109 /** | |
110 * Returns the content as an Uint8Array. | |
111 * @return {Uint8Array} the content as an Uint8Array. | |
112 */ | |
113 asUint8Array : function () { | |
114 return JSZip.utils.string2Uint8Array(this.asBinary()); | |
115 }, | |
116 /** | |
117 * Returns the content as an ArrayBuffer. | |
118 * @return {ArrayBuffer} the content as an ArrayBufer. | |
119 */ | |
120 asArrayBuffer : function () { | |
121 return JSZip.utils.string2Uint8Array(this.asBinary()).buffer; | |
122 } | |
123 }; | |
124 | |
125 /** | |
126 * Transform an integer into a string in hexadecimal. | |
127 * @private | |
128 * @param {number} dec the number to convert. | |
129 * @param {number} bytes the number of bytes to generate. | |
130 * @returns {string} the result. | |
131 */ | |
132 var decToHex = function(dec, bytes) { | |
133 var hex = "", i; | |
134 for(i = 0; i < bytes; i++) { | |
135 hex += String.fromCharCode(dec&0xff); | |
136 dec=dec>>>8; | |
137 } | |
138 return hex; | |
139 }; | |
140 | |
141 /** | |
142 * Merge the objects passed as parameters into a new one. | |
143 * @private | |
144 * @param {...Object} var_args All objects to merge. | |
145 * @return {Object} a new object with the data of the others. | |
146 */ | |
147 var extend = function () { | |
148 var result = {}, i, attr; | |
149 for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers | |
150 for (attr in arguments[i]) { | |
151 if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { | |
152 result[attr] = arguments[i][attr]; | |
153 } | |
154 } | |
155 } | |
156 return result; | |
157 }; | |
158 | |
159 /** | |
160 * Transforms the (incomplete) options from the user into the complete | |
161 * set of options to create a file. | |
162 * @private | |
163 * @param {Object} o the options from the user. | |
164 * @return {Object} the complete set of options. | |
165 */ | |
166 var prepareFileAttrs = function (o) { | |
167 o = o || {}; | |
168 if (o.base64 === true && o.binary == null) { | |
169 o.binary = true; | |
170 } | |
171 o = extend(o, JSZip.defaults); | |
172 o.date = o.date || new Date(); | |
173 | |
174 return o; | |
175 }; | |
176 | |
177 /** | |
178 * Add a file in the current folder. | |
179 * @private | |
180 * @param {string} name the name of the file | |
181 * @param {String|ArrayBuffer|Uint8Array} data the data of the file | |
182 * @param {Object} o the options of the file | |
183 * @return {Object} the new file. | |
184 */ | |
185 var fileAdd = function (name, data, o) { | |
186 // be sure sub folders exist | |
187 var parent = parentFolder(name); | |
188 if (parent) { | |
189 folderAdd.call(this, parent); | |
190 } | |
191 | |
192 o = prepareFileAttrs(o); | |
193 | |
194 if (o.dir || data === null || typeof data === "undefined") { | |
195 o.base64 = false; | |
196 o.binary = false; | |
197 data = null; | |
198 } else if (JSZip.support.uint8array && data instanceof Uint8Array) { | |
199 o.base64 = false; | |
200 o.binary = true; | |
201 data = JSZip.utils.uint8Array2String(data); | |
202 } else if (JSZip.support.arraybuffer && data instanceof ArrayBuffer) { | |
203 o.base64 = false; | |
204 o.binary = true; | |
205 var bufferView = new Uint8Array(data); | |
206 data = JSZip.utils.uint8Array2String(bufferView); | |
207 } else if (o.binary && !o.base64) { | |
208 // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask | |
209 if (o.optimizedBinaryString !== true) { | |
210 // this is a string, not in a base64 format. | |
211 // Be sure that this is a correct "binary string" | |
212 data = JSZip.utils.string2binary(data); | |
213 } | |
214 // we remove this option since it's only relevant here | |
215 delete o.optimizedBinaryString; | |
216 } | |
217 | |
218 return this.files[name] = new ZipObject(name, data, o); | |
219 }; | |
220 | |
221 | |
222 /** | |
223 * Find the parent folder of the path. | |
224 * @private | |
225 * @param {string} path the path to use | |
226 * @return {string} the parent folder, or "" | |
227 */ | |
228 var parentFolder = function (path) { | |
229 if (path.slice(-1) == '/') { | |
230 path = path.substring(0, path.length - 1); | |
231 } | |
232 var lastSlash = path.lastIndexOf('/'); | |
233 return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; | |
234 }; | |
235 | |
236 /** | |
237 * Add a (sub) folder in the current folder. | |
238 * @private | |
239 * @param {string} name the folder's name | |
240 * @return {Object} the new folder. | |
241 */ | |
242 var folderAdd = function (name) { | |
243 // Check the name ends with a / | |
244 if (name.slice(-1) != "/") { | |
245 name += "/"; // IE doesn't like substr(-1) | |
246 } | |
247 | |
248 // Does this folder already exist? | |
249 if (!this.files[name]) { | |
250 // be sure sub folders exist | |
251 var parent = parentFolder(name); | |
252 if (parent) { | |
253 folderAdd.call(this, parent); | |
254 } | |
255 | |
256 fileAdd.call(this, name, null, {dir:true}); | |
257 } | |
258 return this.files[name]; | |
259 }; | |
260 | |
261 /** | |
262 * Generate the data found in the local header of a zip file. | |
263 * Do not create it now, as some parts are re-used later. | |
264 * @private | |
265 * @param {Object} file the file to use. | |
266 * @param {string} utfEncodedFileName the file name, utf8 encoded. | |
267 * @param {string} compressionType the compression to use. | |
268 * @return {Object} an object containing header and compressedData. | |
269 */ | |
270 var prepareLocalHeaderData = function(file, utfEncodedFileName, compressionType) { | |
271 var useUTF8 = utfEncodedFileName !== file.name, | |
272 data = file.asBinary(), | |
273 o = file.options, | |
274 dosTime, | |
275 dosDate; | |
276 | |
277 // date | |
278 // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html | |
279 // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html | |
280 // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html | |
281 | |
282 dosTime = o.date.getHours(); | |
283 dosTime = dosTime << 6; | |
284 dosTime = dosTime | o.date.getMinutes(); | |
285 dosTime = dosTime << 5; | |
286 dosTime = dosTime | o.date.getSeconds() / 2; | |
287 | |
288 dosDate = o.date.getFullYear() - 1980; | |
289 dosDate = dosDate << 4; | |
290 dosDate = dosDate | (o.date.getMonth() + 1); | |
291 dosDate = dosDate << 5; | |
292 dosDate = dosDate | o.date.getDate(); | |
293 | |
294 var hasData = data !== null && data.length !== 0; | |
295 | |
296 var compression = JSZip.compressions[compressionType]; | |
297 var compressedData = hasData ? compression.compress(data) : ''; | |
298 | |
299 var header = ""; | |
300 | |
301 // version needed to extract | |
302 header += "\x0A\x00"; | |
303 // general purpose bit flag | |
304 // set bit 11 if utf8 | |
305 header += useUTF8 ? "\x00\x08" : "\x00\x00"; | |
306 // compression method | |
307 header += hasData ? compression.magic : JSZip.compressions['STORE'].magic; | |
308 // last mod file time | |
309 header += decToHex(dosTime, 2); | |
310 // last mod file date | |
311 header += decToHex(dosDate, 2); | |
312 // crc-32 | |
313 header += hasData ? decToHex(this.crc32(data), 4) : '\x00\x00\x00\x00'; | |
314 // compressed size | |
315 header += hasData ? decToHex(compressedData.length, 4) : '\x00\x00\x00\x00'; | |
316 // uncompressed size | |
317 header += hasData ? decToHex(data.length, 4) : '\x00\x00\x00\x00'; | |
318 // file name length | |
319 header += decToHex(utfEncodedFileName.length, 2); | |
320 // extra field length | |
321 header += "\x00\x00"; | |
322 | |
323 return { | |
324 header:header, | |
325 compressedData:compressedData | |
326 }; | |
327 }; | |
328 | |
329 | |
330 // return the actual prototype of JSZip | |
331 return { | |
332 /** | |
333 * Read an existing zip and merge the data in the current JSZip object. | |
334 * The implementation is in jszip-load.js, don't forget to include it. | |
335 * @param {String|ArrayBuffer|Uint8Array} stream The stream to load | |
336 * @param {Object} options Options for loading the stream. | |
337 * options.base64 : is the stream in base64 ? default : false | |
338 * @return {JSZip} the current JSZip object | |
339 */ | |
340 load : function (stream, options) { | |
341 throw new Error("Load method is not defined. Is the file jszip-load.js included ?"); | |
342 }, | |
343 | |
344 /** | |
345 * Filter nested files/folders with the specified function. | |
346 * @param {Function} search the predicate to use : | |
347 * function (relativePath, file) {...} | |
348 * It takes 2 arguments : the relative path and the file. | |
349 * @return {Array} An array of matching elements. | |
350 */ | |
351 filter : function (search) { | |
352 var result = [], filename, relativePath, file, fileClone; | |
353 for (filename in this.files) { | |
354 if ( !this.files.hasOwnProperty(filename) ) { continue; } | |
355 file = this.files[filename]; | |
356 // return a new object, don't let the user mess with our internal objects :) | |
357 fileClone = new ZipObject(file.name, file.data, extend(file.options)); | |
358 relativePath = filename.slice(this.root.length, filename.length); | |
359 if (filename.slice(0, this.root.length) === this.root && // the file is in the current root | |
360 search(relativePath, fileClone)) { // and the file matches the function | |
361 result.push(fileClone); | |
362 } | |
363 } | |
364 return result; | |
365 }, | |
366 | |
367 /** | |
368 * Add a file to the zip file, or search a file. | |
369 * @param {string|RegExp} name The name of the file to add (if data is defined), | |
370 * the name of the file to find (if no data) or a regex to match files. | |
371 * @param {String|ArrayBuffer|Uint8Array} data The file data, either raw or base64 encoded | |
372 * @param {Object} o File options | |
373 * @return {JSZip|Object|Array} this JSZip object (when adding a file), | |
374 * a file (when searching by string) or an array of files (when searching by regex). | |
375 */ | |
376 file : function(name, data, o) { | |
377 if (arguments.length === 1) { | |
378 if (name instanceof RegExp) { | |
379 var regexp = name; | |
380 return this.filter(function(relativePath, file) { | |
381 return !file.options.dir && regexp.test(relativePath); | |
382 }); | |
383 } else { // text | |
384 return this.filter(function (relativePath, file) { | |
385 return !file.options.dir && relativePath === name; | |
386 })[0]||null; | |
387 } | |
388 } else { // more than one argument : we have data ! | |
389 name = this.root+name; | |
390 fileAdd.call(this, name, data, o); | |
391 } | |
392 return this; | |
393 }, | |
394 | |
395 /** | |
396 * Add a directory to the zip file, or search. | |
397 * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. | |
398 * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. | |
399 */ | |
400 folder : function(arg) { | |
401 if (!arg) { | |
402 return this; | |
403 } | |
404 | |
405 if (arg instanceof RegExp) { | |
406 return this.filter(function(relativePath, file) { | |
407 return file.options.dir && arg.test(relativePath); | |
408 }); | |
409 } | |
410 | |
411 // else, name is a new folder | |
412 var name = this.root + arg; | |
413 var newFolder = folderAdd.call(this, name); | |
414 | |
415 // Allow chaining by returning a new object with this folder as the root | |
416 var ret = this.clone(); | |
417 ret.root = newFolder.name; | |
418 return ret; | |
419 }, | |
420 | |
421 /** | |
422 * Delete a file, or a directory and all sub-files, from the zip | |
423 * @param {string} name the name of the file to delete | |
424 * @return {JSZip} this JSZip object | |
425 */ | |
426 remove : function(name) { | |
427 name = this.root + name; | |
428 var file = this.files[name]; | |
429 if (!file) { | |
430 // Look for any folders | |
431 if (name.slice(-1) != "/") { | |
432 name += "/"; | |
433 } | |
434 file = this.files[name]; | |
435 } | |
436 | |
437 if (file) { | |
438 if (!file.options.dir) { | |
439 // file | |
440 delete this.files[name]; | |
441 } else { | |
442 // folder | |
443 var kids = this.filter(function (relativePath, file) { | |
444 return file.name.slice(0, name.length) === name; | |
445 }); | |
446 for (var i = 0; i < kids.length; i++) { | |
447 delete this.files[kids[i].name]; | |
448 } | |
449 } | |
450 } | |
451 | |
452 return this; | |
453 }, | |
454 | |
455 /** | |
456 * Generate the complete zip file | |
457 * @param {Object} options the options to generate the zip file : | |
458 * - base64, (deprecated, use type instead) true to generate base64. | |
459 * - compression, "STORE" by default. | |
460 * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. | |
461 * @return {String|Uint8Array|ArrayBuffer|Blob} the zip file | |
462 */ | |
463 generate : function(options) { | |
464 options = extend(options || {}, { | |
465 base64 : true, | |
466 compression : "STORE", | |
467 type : "base64" | |
468 }); | |
469 var compression = options.compression.toUpperCase(); | |
470 | |
471 // The central directory, and files data | |
472 var directory = [], files = [], fileOffset = 0; | |
473 | |
474 if (!JSZip.compressions[compression]) { | |
475 throw compression + " is not a valid compression method !"; | |
476 } | |
477 | |
478 for (var name in this.files) { | |
479 if ( !this.files.hasOwnProperty(name) ) { continue; } | |
480 | |
481 var file = this.files[name]; | |
482 | |
483 var utfEncodedFileName = this.utf8encode(file.name); | |
484 | |
485 var fileRecord = "", | |
486 dirRecord = "", | |
487 data = prepareLocalHeaderData.call(this, file, utfEncodedFileName, compression); | |
488 fileRecord = JSZip.signature.LOCAL_FILE_HEADER + data.header + utfEncodedFileName + data.compressedData; | |
489 | |
490 dirRecord = JSZip.signature.CENTRAL_FILE_HEADER + | |
491 // version made by (00: DOS) | |
492 "\x14\x00" + | |
493 // file header (common to file and central directory) | |
494 data.header + | |
495 // file comment length | |
496 "\x00\x00" + | |
497 // disk number start | |
498 "\x00\x00" + | |
499 // internal file attributes TODO | |
500 "\x00\x00" + | |
501 // external file attributes | |
502 (this.files[name].options.dir===true?"\x10\x00\x00\x00":"\x00\x00\x00\x00")+ | |
503 // relative offset of local header | |
504 decToHex(fileOffset, 4) + | |
505 // file name | |
506 utfEncodedFileName; | |
507 | |
508 fileOffset += fileRecord.length; | |
509 | |
510 files.push(fileRecord); | |
511 directory.push(dirRecord); | |
512 } | |
513 | |
514 var fileData = files.join(""); | |
515 var dirData = directory.join(""); | |
516 | |
517 var dirEnd = ""; | |
518 | |
519 // end of central dir signature | |
520 dirEnd = JSZip.signature.CENTRAL_DIRECTORY_END + | |
521 // number of this disk | |
522 "\x00\x00" + | |
523 // number of the disk with the start of the central directory | |
524 "\x00\x00" + | |
525 // total number of entries in the central directory on this disk | |
526 decToHex(files.length, 2) + | |
527 // total number of entries in the central directory | |
528 decToHex(files.length, 2) + | |
529 // size of the central directory 4 bytes | |
530 decToHex(dirData.length, 4) + | |
531 // offset of start of central directory with respect to the starting disk number | |
532 decToHex(fileData.length, 4) + | |
533 // .ZIP file comment length | |
534 "\x00\x00"; | |
535 | |
536 var zip = fileData + dirData + dirEnd; | |
537 | |
538 | |
539 switch(options.type.toLowerCase()) { | |
540 case "uint8array" : | |
541 return JSZip.utils.string2Uint8Array(zip); | |
542 case "arraybuffer" : | |
543 return JSZip.utils.string2Uint8Array(zip).buffer; | |
544 case "blob" : | |
545 return JSZip.utils.string2Blob(zip); | |
546 case "base64" : | |
547 return (options.base64) ? JSZipBase64.encode(zip) : zip; | |
548 default : // case "string" : | |
549 return zip; | |
550 } | |
551 }, | |
552 | |
553 /** | |
554 * | |
555 * Javascript crc32 | |
556 * http://www.webtoolkit.info/ | |
557 * | |
558 */ | |
559 crc32 : function(str, crc) { | |
560 | |
561 if (str === "" || typeof str === "undefined") { | |
562 return 0; | |
563 } | |
564 | |
565 var table = [ | |
566 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, | |
567 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, | |
568 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, | |
569 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, | |
570 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, | |
571 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, | |
572 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, | |
573 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, | |
574 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, | |
575 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, | |
576 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, | |
577 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, | |
578 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, | |
579 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, | |
580 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, | |
581 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, | |
582 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, | |
583 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, | |
584 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, | |
585 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, | |
586 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, | |
587 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, | |
588 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, | |
589 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, | |
590 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, | |
591 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, | |
592 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, | |
593 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, | |
594 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, | |
595 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, | |
596 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, | |
597 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, | |
598 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, | |
599 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, | |
600 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, | |
601 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, | |
602 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, | |
603 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, | |
604 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, | |
605 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, | |
606 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, | |
607 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, | |
608 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, | |
609 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, | |
610 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, | |
611 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, | |
612 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, | |
613 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, | |
614 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, | |
615 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, | |
616 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, | |
617 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, | |
618 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, | |
619 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, | |
620 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, | |
621 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, | |
622 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, | |
623 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, | |
624 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, | |
625 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, | |
626 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, | |
627 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, | |
628 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, | |
629 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D | |
630 ]; | |
631 | |
632 if (typeof(crc) == "undefined") { crc = 0; } | |
633 var x = 0; | |
634 var y = 0; | |
635 | |
636 crc = crc ^ (-1); | |
637 for( var i = 0, iTop = str.length; i < iTop; i++ ) { | |
638 y = ( crc ^ str.charCodeAt( i ) ) & 0xFF; | |
639 x = table[y]; | |
640 crc = ( crc >>> 8 ) ^ x; | |
641 } | |
642 | |
643 return crc ^ (-1); | |
644 }, | |
645 | |
646 // Inspired by http://my.opera.com/GreyWyvern/blog/show.dml/1725165 | |
647 clone : function() { | |
648 var newObj = new JSZip(); | |
649 for (var i in this) { | |
650 if (typeof this[i] !== "function") { | |
651 newObj[i] = this[i]; | |
652 } | |
653 } | |
654 return newObj; | |
655 }, | |
656 | |
657 | |
658 /** | |
659 * http://www.webtoolkit.info/javascript-utf8.html | |
660 */ | |
661 utf8encode : function (string) { | |
662 string = string.replace(/\r\n/g,"\n"); | |
663 var utftext = ""; | |
664 | |
665 for (var n = 0; n < string.length; n++) { | |
666 | |
667 var c = string.charCodeAt(n); | |
668 | |
669 if (c < 128) { | |
670 utftext += String.fromCharCode(c); | |
671 } else if ((c > 127) && (c < 2048)) { | |
672 utftext += String.fromCharCode((c >> 6) | 192); | |
673 utftext += String.fromCharCode((c & 63) | 128); | |
674 } else { | |
675 utftext += String.fromCharCode((c >> 12) | 224); | |
676 utftext += String.fromCharCode(((c >> 6) & 63) | 128); | |
677 utftext += String.fromCharCode((c & 63) | 128); | |
678 } | |
679 | |
680 } | |
681 | |
682 return utftext; | |
683 }, | |
684 | |
685 /** | |
686 * http://www.webtoolkit.info/javascript-utf8.html | |
687 */ | |
688 utf8decode : function (utftext) { | |
689 var string = ""; | |
690 var i = 0; | |
691 var c = 0, c1 = 0, c2 = 0, c3 = 0; | |
692 | |
693 while ( i < utftext.length ) { | |
694 | |
695 c = utftext.charCodeAt(i); | |
696 | |
697 if (c < 128) { | |
698 string += String.fromCharCode(c); | |
699 i++; | |
700 } else if ((c > 191) && (c < 224)) { | |
701 c2 = utftext.charCodeAt(i+1); | |
702 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); | |
703 i += 2; | |
704 } else { | |
705 c2 = utftext.charCodeAt(i+1); | |
706 c3 = utftext.charCodeAt(i+2); | |
707 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); | |
708 i += 3; | |
709 } | |
710 | |
711 } | |
712 | |
713 return string; | |
714 } | |
715 }; | |
716 }()); | |
717 | |
718 /* | |
719 * Compression methods | |
720 * This object is filled in as follow : | |
721 * name : { | |
722 * magic // the 2 bytes indentifying the compression method | |
723 * compress // function, take the uncompressed content and return it compressed. | |
724 * uncompress // function, take the compressed content and return it uncompressed. | |
725 * } | |
726 * | |
727 * STORE is the default compression method, so it's included in this file. | |
728 * Other methods should go to separated files : the user wants modularity. | |
729 */ | |
730 JSZip.compressions = { | |
731 "STORE" : { | |
732 magic : "\x00\x00", | |
733 compress : function (content) { | |
734 return content; // no compression | |
735 }, | |
736 uncompress : function (content) { | |
737 return content; // no compression | |
738 } | |
739 } | |
740 }; | |
741 | |
742 /* | |
743 * List features that require a modern browser, and if the current browser support them. | |
744 */ | |
745 JSZip.support = { | |
746 // contains true if JSZip can read/generate ArrayBuffer, false otherwise. | |
747 arraybuffer : (function(){ | |
748 return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; | |
749 })(), | |
750 // contains true if JSZip can read/generate Uint8Array, false otherwise. | |
751 uint8array : (function(){ | |
752 return typeof Uint8Array !== "undefined"; | |
753 })(), | |
754 // contains true if JSZip can read/generate Blob, false otherwise. | |
755 blob : (function(){ | |
756 // the spec started with BlobBuilder then replaced it with a construtor for Blob. | |
757 // Result : we have browsers that : | |
758 // * know the BlobBuilder (but with prefix) | |
759 // * know the Blob constructor | |
760 // * know about Blob but not about how to build them | |
761 // About the "=== 0" test : if given the wrong type, it may be converted to a string. | |
762 // Instead of an empty content, we will get "[object Uint8Array]" for example. | |
763 if (typeof ArrayBuffer === "undefined") { | |
764 return false; | |
765 } | |
766 var buffer = new ArrayBuffer(0); | |
767 try { | |
768 return new Blob([buffer], { type: "application/zip" }).size === 0; | |
769 } | |
770 catch(e) {} | |
771 | |
772 try { | |
773 var builder = new (window.BlobBuilder || window.WebKitBlobBuilder || | |
774 window.MozBlobBuilder || window.MSBlobBuilder)(); | |
775 builder.append(buffer); | |
776 return builder.getBlob('application/zip').size === 0; | |
777 } | |
778 catch(e) {} | |
779 | |
780 return false; | |
781 })() | |
782 }; | |
783 | |
784 JSZip.utils = { | |
785 /** | |
786 * Convert a string to a "binary string" : a string containing only char codes between 0 and 255. | |
787 * @param {string} str the string to transform. | |
788 * @return {String} the binary string. | |
789 */ | |
790 string2binary : function (str) { | |
791 var result = ""; | |
792 for (var i = 0; i < str.length; i++) { | |
793 result += String.fromCharCode(str.charCodeAt(i) & 0xff); | |
794 } | |
795 return result; | |
796 }, | |
797 /** | |
798 * Create a Uint8Array from the string. | |
799 * @param {string} str the string to transform. | |
800 * @return {Uint8Array} the typed array. | |
801 * @throws {Error} an Error if the browser doesn't support the requested feature. | |
802 */ | |
803 string2Uint8Array : function (str) { | |
804 if (!JSZip.support.uint8array) { | |
805 throw new Error("Uint8Array is not supported by this browser"); | |
806 } | |
807 var buffer = new ArrayBuffer(str.length); | |
808 var bufferView = new Uint8Array(buffer); | |
809 for(var i = 0; i < str.length; i++) { | |
810 bufferView[i] = str.charCodeAt(i); | |
811 } | |
812 | |
813 return bufferView; | |
814 }, | |
815 | |
816 /** | |
817 * Create a string from the Uint8Array. | |
818 * @param {Uint8Array} array the array to transform. | |
819 * @return {string} the string. | |
820 * @throws {Error} an Error if the browser doesn't support the requested feature. | |
821 */ | |
822 uint8Array2String : function (array) { | |
823 if (!JSZip.support.uint8array) { | |
824 throw new Error("Uint8Array is not supported by this browser"); | |
825 } | |
826 var result = ""; | |
827 for(var i = 0; i < array.length; i++) { | |
828 result += String.fromCharCode(array[i]); | |
829 } | |
830 | |
831 return result; | |
832 }, | |
833 /** | |
834 * Create a blob from the given string. | |
835 * @param {string} str the string to transform. | |
836 * @return {Blob} the string. | |
837 * @throws {Error} an Error if the browser doesn't support the requested feature. | |
838 */ | |
839 string2Blob : function (str) { | |
840 if (!JSZip.support.blob) { | |
841 throw new Error("Blob is not supported by this browser"); | |
842 } | |
843 | |
844 var buffer = JSZip.utils.string2Uint8Array(str).buffer; | |
845 try { | |
846 // Blob constructor | |
847 return new Blob([buffer], { type: "application/zip" }); | |
848 } | |
849 catch(e) {} | |
850 | |
851 try { | |
852 // deprecated, browser only, old way | |
853 var builder = new (window.BlobBuilder || window.WebKitBlobBuilder || | |
854 window.MozBlobBuilder || window.MSBlobBuilder)(); | |
855 builder.append(buffer); | |
856 return builder.getBlob('application/zip'); | |
857 } | |
858 catch(e) {} | |
859 | |
860 // well, fuck ?! | |
861 throw new Error("Bug : can't construct the Blob."); | |
862 } | |
863 }; | |
864 | |
865 /** | |
866 * | |
867 * Base64 encode / decode | |
868 * http://www.webtoolkit.info/ | |
869 * | |
870 * Hacked so that it doesn't utf8 en/decode everything | |
871 **/ | |
872 var JSZipBase64 = (function() { | |
873 // private property | |
874 var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
875 | |
876 return { | |
877 // public method for encoding | |
878 encode : function(input, utf8) { | |
879 var output = ""; | |
880 var chr1, chr2, chr3, enc1, enc2, enc3, enc4; | |
881 var i = 0; | |
882 | |
883 while (i < input.length) { | |
884 | |
885 chr1 = input.charCodeAt(i++); | |
886 chr2 = input.charCodeAt(i++); | |
887 chr3 = input.charCodeAt(i++); | |
888 | |
889 enc1 = chr1 >> 2; | |
890 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); | |
891 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); | |
892 enc4 = chr3 & 63; | |
893 | |
894 if (isNaN(chr2)) { | |
895 enc3 = enc4 = 64; | |
896 } else if (isNaN(chr3)) { | |
897 enc4 = 64; | |
898 } | |
899 | |
900 output = output + | |
901 _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + | |
902 _keyStr.charAt(enc3) + _keyStr.charAt(enc4); | |
903 | |
904 } | |
905 | |
906 return output; | |
907 }, | |
908 | |
909 // public method for decoding | |
910 decode : function(input, utf8) { | |
911 var output = ""; | |
912 var chr1, chr2, chr3; | |
913 var enc1, enc2, enc3, enc4; | |
914 var i = 0; | |
915 | |
916 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); | |
917 | |
918 while (i < input.length) { | |
919 | |
920 enc1 = _keyStr.indexOf(input.charAt(i++)); | |
921 enc2 = _keyStr.indexOf(input.charAt(i++)); | |
922 enc3 = _keyStr.indexOf(input.charAt(i++)); | |
923 enc4 = _keyStr.indexOf(input.charAt(i++)); | |
924 | |
925 chr1 = (enc1 << 2) | (enc2 >> 4); | |
926 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | |
927 chr3 = ((enc3 & 3) << 6) | enc4; | |
928 | |
929 output = output + String.fromCharCode(chr1); | |
930 | |
931 if (enc3 != 64) { | |
932 output = output + String.fromCharCode(chr2); | |
933 } | |
934 if (enc4 != 64) { | |
935 output = output + String.fromCharCode(chr3); | |
936 } | |
937 | |
938 } | |
939 | |
940 return output; | |
941 | |
942 } | |
943 }; | |
944 }()); | |
945 | |
946 // enforcing Stuk's coding style | |
947 // vim: set shiftwidth=3 softtabstop=3: |