UNPKG

27.2 kBJavaScriptView Raw
1/**
2
3JSZip - A Javascript class for generating and reading zip files
4<http://stuartk.com/jszip>
5
6(c) 2011 David Duponchel <d.duponchel@gmail.com>
7Dual licenced under the MIT license or GPLv3. See LICENSE.markdown.
8
9**/
10/*global JSZip */
11(function (root) {
12 "use strict";
13
14 var JSZip = root.JSZip;
15
16 var MAX_VALUE_16BITS = 65535;
17 var MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1
18
19 /**
20 * Prettify a string read as binary.
21 * @param {string} str the string to prettify.
22 * @return {string} a pretty string.
23 */
24 var pretty = function (str) {
25 var res = '', code, i;
26 for (i = 0; i < (str||"").length; i++) {
27 code = str.charCodeAt(i);
28 res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase();
29 }
30 return res;
31 };
32
33 /**
34 * Find a compression registered in JSZip.
35 * @param {string} compressionMethod the method magic to find.
36 * @return {Object|null} the JSZip compression object, null if none found.
37 */
38 var findCompression = function (compressionMethod) {
39 for (var method in JSZip.compressions) {
40 if( !JSZip.compressions.hasOwnProperty(method) ) { continue; }
41 if (JSZip.compressions[method].magic === compressionMethod) {
42 return JSZip.compressions[method];
43 }
44 }
45 return null;
46 };
47
48 // class DataReader {{{
49 /**
50 * Read bytes from a source.
51 * Developer tip : when debugging, a watch on pretty(this.reader.data.slice(this.reader.index))
52 * is very useful :)
53 * @constructor
54 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read.
55 */
56 function DataReader(data) {
57 this.data = null; // type : see implementation
58 this.length = 0;
59 this.index = 0;
60 }
61 DataReader.prototype = {
62 /**
63 * Check that the offset will not go too far.
64 * @param {string} offset the additional offset to check.
65 * @throws {Error} an Error if the offset is out of bounds.
66 */
67 checkOffset : function (offset) {
68 this.checkIndex(this.index + offset);
69 },
70 /**
71 * Check that the specifed index will not be too far.
72 * @param {string} newIndex the index to check.
73 * @throws {Error} an Error if the index is out of bounds.
74 */
75 checkIndex : function (newIndex) {
76 if (this.length < newIndex || newIndex < 0) {
77 throw new Error("End of data reached (data length = " +
78 this.length + ", asked index = " +
79 (newIndex) + "). Corrupted zip ?");
80 }
81 },
82 /**
83 * Change the index.
84 * @param {number} newIndex The new index.
85 * @throws {Error} if the new index is out of the data.
86 */
87 setIndex : function (newIndex) {
88 this.checkIndex(newIndex);
89 this.index = newIndex;
90 },
91 /**
92 * Skip the next n bytes.
93 * @param {number} n the number of bytes to skip.
94 * @throws {Error} if the new index is out of the data.
95 */
96 skip : function (n) {
97 this.setIndex(this.index + n);
98 },
99 /**
100 * Get the byte at the specified index.
101 * @param {number} i the index to use.
102 * @return {number} a byte.
103 */
104 byteAt : function(i) {
105 // see implementations
106 },
107 /**
108 * Get the next number with a given byte size.
109 * @param {number} size the number of bytes to read.
110 * @return {number} the corresponding number.
111 */
112 readInt : function (size) {
113 var result = 0, i;
114 this.checkOffset(size);
115 for(i = this.index + size - 1; i >= this.index; i--) {
116 result = (result << 8) + this.byteAt(i);
117 }
118 this.index += size;
119 return result;
120 },
121 /**
122 * Get the next string with a given byte size.
123 * @param {number} size the number of bytes to read.
124 * @return {string} the corresponding string.
125 */
126 readString : function (size) {
127 return JSZip.utils.transformTo("string", this.readData(size));
128 },
129 /**
130 * Get raw data without conversion, <size> bytes.
131 * @param {number} size the number of bytes to read.
132 * @return {Object} the raw data, implementation specific.
133 */
134 readData : function (size) {
135 // see implementations
136 },
137 /**
138 * Find the last occurence of a zip signature (4 bytes).
139 * @param {string} sig the signature to find.
140 * @return {number} the index of the last occurence, -1 if not found.
141 */
142 lastIndexOfSignature : function (sig) {
143 // see implementations
144 },
145 /**
146 * Get the next date.
147 * @return {Date} the date.
148 */
149 readDate : function () {
150 var dostime = this.readInt(4);
151 return new Date(
152 ((dostime >> 25) & 0x7f) + 1980, // year
153 ((dostime >> 21) & 0x0f) - 1, // month
154 (dostime >> 16) & 0x1f, // day
155 (dostime >> 11) & 0x1f, // hour
156 (dostime >> 5) & 0x3f, // minute
157 (dostime & 0x1f) << 1); // second
158 }
159 };
160
161
162 /**
163 * Read bytes from a string.
164 * @constructor
165 * @param {String} data the data to read.
166 */
167 function StringReader(data, optimizedBinaryString) {
168 this.data = data;
169 if (!optimizedBinaryString) {
170 this.data = JSZip.utils.string2binary(this.data);
171 }
172 this.length = this.data.length;
173 this.index = 0;
174 }
175 StringReader.prototype = new DataReader();
176 /**
177 * @see DataReader.byteAt
178 */
179 StringReader.prototype.byteAt = function(i) {
180 return this.data.charCodeAt(i);
181 };
182 /**
183 * @see DataReader.lastIndexOfSignature
184 */
185 StringReader.prototype.lastIndexOfSignature = function (sig) {
186 return this.data.lastIndexOf(sig);
187 };
188 /**
189 * @see DataReader.readData
190 */
191 StringReader.prototype.readData = function (size) {
192 this.checkOffset(size);
193 // this will work because the constructor applied the "& 0xff" mask.
194 var result = this.data.slice(this.index, this.index + size);
195 this.index += size;
196 return result;
197 };
198
199
200 /**
201 * Read bytes from an Uin8Array.
202 * @constructor
203 * @param {Uint8Array} data the data to read.
204 */
205 function Uint8ArrayReader(data) {
206 if (data) {
207 this.data = data;
208 this.length = this.data.length;
209 this.index = 0;
210 }
211 }
212 Uint8ArrayReader.prototype = new DataReader();
213 /**
214 * @see DataReader.byteAt
215 */
216 Uint8ArrayReader.prototype.byteAt = function(i) {
217 return this.data[i];
218 };
219 /**
220 * @see DataReader.lastIndexOfSignature
221 */
222 Uint8ArrayReader.prototype.lastIndexOfSignature = function (sig) {
223 var sig0 = sig.charCodeAt(0),
224 sig1 = sig.charCodeAt(1),
225 sig2 = sig.charCodeAt(2),
226 sig3 = sig.charCodeAt(3);
227 for(var i = this.length - 4;i >= 0;--i) {
228 if (this.data[i] === sig0 && this.data[i+1] === sig1 && this.data[i+2] === sig2 && this.data[i+3] === sig3) {
229 return i;
230 }
231 }
232
233 return -1;
234 };
235 /**
236 * @see DataReader.readData
237 */
238 Uint8ArrayReader.prototype.readData = function (size) {
239 this.checkOffset(size);
240 var result = this.data.subarray(this.index, this.index + size);
241 this.index += size;
242 return result;
243 };
244
245 /**
246 * Read bytes from a Buffer.
247 * @constructor
248 * @param {Buffer} data the data to read.
249 */
250 function NodeBufferReader(data) {
251 this.data = data;
252 this.length = this.data.length;
253 this.index = 0;
254 }
255 NodeBufferReader.prototype = new Uint8ArrayReader();
256
257 /**
258 * @see DataReader.readData
259 */
260 NodeBufferReader.prototype.readData = function (size) {
261 this.checkOffset(size);
262 var result = this.data.slice(this.index, this.index + size);
263 this.index += size;
264 return result;
265 };
266 // }}} end of DataReader
267
268 // class ZipEntry {{{
269 /**
270 * An entry in the zip file.
271 * @constructor
272 * @param {Object} options Options of the current file.
273 * @param {Object} loadOptions Options for loading the data.
274 */
275 function ZipEntry(options, loadOptions) {
276 this.options = options;
277 this.loadOptions = loadOptions;
278 }
279 ZipEntry.prototype = {
280 /**
281 * say if the file is encrypted.
282 * @return {boolean} true if the file is encrypted, false otherwise.
283 */
284 isEncrypted : function () {
285 // bit 1 is set
286 return (this.bitFlag & 0x0001) === 0x0001;
287 },
288 /**
289 * say if the file has utf-8 filename/comment.
290 * @return {boolean} true if the filename/comment is in utf-8, false otherwise.
291 */
292 useUTF8 : function () {
293 // bit 11 is set
294 return (this.bitFlag & 0x0800) === 0x0800;
295 },
296 /**
297 * Prepare the function used to generate the compressed content from this ZipFile.
298 * @param {DataReader} reader the reader to use.
299 * @param {number} from the offset from where we should read the data.
300 * @param {number} length the length of the data to read.
301 * @return {Function} the callback to get the compressed content (the type depends of the DataReader class).
302 */
303 prepareCompressedContent : function (reader, from, length) {
304 return function () {
305 var previousIndex = reader.index;
306 reader.setIndex(from);
307 var compressedFileData = reader.readData(length);
308 reader.setIndex(previousIndex);
309
310 return compressedFileData;
311 };
312 },
313 /**
314 * Prepare the function used to generate the uncompressed content from this ZipFile.
315 * @param {DataReader} reader the reader to use.
316 * @param {number} from the offset from where we should read the data.
317 * @param {number} length the length of the data to read.
318 * @param {JSZip.compression} compression the compression used on this file.
319 * @param {number} uncompressedSize the uncompressed size to expect.
320 * @return {Function} the callback to get the uncompressed content (the type depends of the DataReader class).
321 */
322 prepareContent : function (reader, from, length, compression, uncompressedSize) {
323 return function () {
324
325 var compressedFileData = JSZip.utils.transformTo(compression.uncompressInputType, this.getCompressedContent());
326 var uncompressedFileData = compression.uncompress(compressedFileData);
327
328 if (uncompressedFileData.length !== uncompressedSize) {
329 throw new Error("Bug : uncompressed data size mismatch");
330 }
331
332 return uncompressedFileData;
333 };
334 },
335 /**
336 * Read the local part of a zip file and add the info in this object.
337 * @param {DataReader} reader the reader to use.
338 */
339 readLocalPart : function(reader) {
340 var compression, localExtraFieldsLength;
341
342 // we already know everything from the central dir !
343 // If the central dir data are false, we are doomed.
344 // On the bright side, the local part is scary : zip64, data descriptors, both, etc.
345 // The less data we get here, the more reliable this should be.
346 // Let's skip the whole header and dash to the data !
347 reader.skip(22);
348 // in some zip created on windows, the filename stored in the central dir contains \ instead of /.
349 // Strangely, the filename here is OK.
350 // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes
351 // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators...
352 // Search "unzip mismatching "local" filename continuing with "central" filename version" on
353 // the internet.
354 //
355 // I think I see the logic here : the central directory is used to display
356 // content and the local directory is used to extract the files. Mixing / and \
357 // may be used to display \ to windows users and use / when extracting the files.
358 // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394
359 this.fileNameLength = reader.readInt(2);
360 localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir
361 this.fileName = reader.readString(this.fileNameLength);
362 reader.skip(localExtraFieldsLength);
363
364 if (this.compressedSize == -1 || this.uncompressedSize == -1) {
365 throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " +
366 "(compressedSize == -1 || uncompressedSize == -1)");
367 }
368
369 compression = findCompression(this.compressionMethod);
370 if (compression === null) { // no compression found
371 throw new Error("Corrupted zip : compression " + pretty(this.compressionMethod) +
372 " unknown (inner file : " + this.fileName + ")");
373 }
374 this.decompressed = new JSZip.CompressedObject();
375 this.decompressed.compressedSize = this.compressedSize;
376 this.decompressed.uncompressedSize = this.uncompressedSize;
377 this.decompressed.crc32 = this.crc32;
378 this.decompressed.compressionMethod = this.compressionMethod;
379 this.decompressed.getCompressedContent = this.prepareCompressedContent(reader, reader.index, this.compressedSize, compression);
380 this.decompressed.getContent = this.prepareContent(reader, reader.index, this.compressedSize, compression, this.uncompressedSize);
381
382 // we need to compute the crc32...
383 if (this.loadOptions.checkCRC32) {
384 this.decompressed = JSZip.utils.transformTo("string", this.decompressed.getContent());
385 if (JSZip.prototype.crc32(this.decompressed) !== this.crc32) {
386 throw new Error("Corrupted zip : CRC32 mismatch");
387 }
388 }
389 },
390
391 /**
392 * Read the central part of a zip file and add the info in this object.
393 * @param {DataReader} reader the reader to use.
394 */
395 readCentralPart : function(reader) {
396 this.versionMadeBy = reader.readString(2);
397 this.versionNeeded = reader.readInt(2);
398 this.bitFlag = reader.readInt(2);
399 this.compressionMethod = reader.readString(2);
400 this.date = reader.readDate();
401 this.crc32 = reader.readInt(4);
402 this.compressedSize = reader.readInt(4);
403 this.uncompressedSize = reader.readInt(4);
404 this.fileNameLength = reader.readInt(2);
405 this.extraFieldsLength = reader.readInt(2);
406 this.fileCommentLength = reader.readInt(2);
407 this.diskNumberStart = reader.readInt(2);
408 this.internalFileAttributes = reader.readInt(2);
409 this.externalFileAttributes = reader.readInt(4);
410 this.localHeaderOffset = reader.readInt(4);
411
412 if (this.isEncrypted()) {
413 throw new Error("Encrypted zip are not supported");
414 }
415
416 this.fileName = reader.readString(this.fileNameLength);
417 this.readExtraFields(reader);
418 this.parseZIP64ExtraField(reader);
419 this.fileComment = reader.readString(this.fileCommentLength);
420
421 // warning, this is true only for zip with madeBy == DOS (plateform dependent feature)
422 this.dir = this.externalFileAttributes & 0x00000010 ? true : false;
423 },
424 /**
425 * Parse the ZIP64 extra field and merge the info in the current ZipEntry.
426 * @param {DataReader} reader the reader to use.
427 */
428 parseZIP64ExtraField : function(reader) {
429
430 if(!this.extraFields[0x0001]) {
431 return;
432 }
433
434 // should be something, preparing the extra reader
435 var extraReader = new StringReader(this.extraFields[0x0001].value);
436
437 // I really hope that these 64bits integer can fit in 32 bits integer, because js
438 // won't let us have more.
439 if(this.uncompressedSize === MAX_VALUE_32BITS) {
440 this.uncompressedSize = extraReader.readInt(8);
441 }
442 if(this.compressedSize === MAX_VALUE_32BITS) {
443 this.compressedSize = extraReader.readInt(8);
444 }
445 if(this.localHeaderOffset === MAX_VALUE_32BITS) {
446 this.localHeaderOffset = extraReader.readInt(8);
447 }
448 if(this.diskNumberStart === MAX_VALUE_32BITS) {
449 this.diskNumberStart = extraReader.readInt(4);
450 }
451 },
452 /**
453 * Read the central part of a zip file and add the info in this object.
454 * @param {DataReader} reader the reader to use.
455 */
456 readExtraFields : function(reader) {
457 var start = reader.index,
458 extraFieldId,
459 extraFieldLength,
460 extraFieldValue;
461
462 this.extraFields = this.extraFields || {};
463
464 while (reader.index < start + this.extraFieldsLength) {
465 extraFieldId = reader.readInt(2);
466 extraFieldLength = reader.readInt(2);
467 extraFieldValue = reader.readString(extraFieldLength);
468
469 this.extraFields[extraFieldId] = {
470 id: extraFieldId,
471 length: extraFieldLength,
472 value: extraFieldValue
473 };
474 }
475 },
476 /**
477 * Apply an UTF8 transformation if needed.
478 */
479 handleUTF8 : function() {
480 if (this.useUTF8()) {
481 this.fileName = JSZip.prototype.utf8decode(this.fileName);
482 this.fileComment = JSZip.prototype.utf8decode(this.fileComment);
483 }
484 }
485 };
486 // }}} end of ZipEntry
487
488 // class ZipEntries {{{
489 /**
490 * All the entries in the zip file.
491 * @constructor
492 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary data to load.
493 * @param {Object} loadOptions Options for loading the data.
494 */
495 function ZipEntries(data, loadOptions) {
496 this.files = [];
497 this.loadOptions = loadOptions;
498 if (data) {
499 this.load(data);
500 }
501 }
502 ZipEntries.prototype = {
503 /**
504 * Check that the reader is on the speficied signature.
505 * @param {string} expectedSignature the expected signature.
506 * @throws {Error} if it is an other signature.
507 */
508 checkSignature : function(expectedSignature) {
509 var signature = this.reader.readString(4);
510 if (signature !== expectedSignature) {
511 throw new Error("Corrupted zip or bug : unexpected signature " +
512 "(" + pretty(signature) + ", expected " + pretty(expectedSignature) + ")");
513 }
514 },
515 /**
516 * Read the end of the central directory.
517 */
518 readBlockEndOfCentral : function () {
519 this.diskNumber = this.reader.readInt(2);
520 this.diskWithCentralDirStart = this.reader.readInt(2);
521 this.centralDirRecordsOnThisDisk = this.reader.readInt(2);
522 this.centralDirRecords = this.reader.readInt(2);
523 this.centralDirSize = this.reader.readInt(4);
524 this.centralDirOffset = this.reader.readInt(4);
525
526 this.zipCommentLength = this.reader.readInt(2);
527 this.zipComment = this.reader.readString(this.zipCommentLength);
528 },
529 /**
530 * Read the end of the Zip 64 central directory.
531 * Not merged with the method readEndOfCentral :
532 * The end of central can coexist with its Zip64 brother,
533 * I don't want to read the wrong number of bytes !
534 */
535 readBlockZip64EndOfCentral : function () {
536 this.zip64EndOfCentralSize = this.reader.readInt(8);
537 this.versionMadeBy = this.reader.readString(2);
538 this.versionNeeded = this.reader.readInt(2);
539 this.diskNumber = this.reader.readInt(4);
540 this.diskWithCentralDirStart = this.reader.readInt(4);
541 this.centralDirRecordsOnThisDisk = this.reader.readInt(8);
542 this.centralDirRecords = this.reader.readInt(8);
543 this.centralDirSize = this.reader.readInt(8);
544 this.centralDirOffset = this.reader.readInt(8);
545
546 this.zip64ExtensibleData = {};
547 var extraDataSize = this.zip64EndOfCentralSize - 44,
548 index = 0,
549 extraFieldId,
550 extraFieldLength,
551 extraFieldValue;
552 while(index < extraDataSize) {
553 extraFieldId = this.reader.readInt(2);
554 extraFieldLength = this.reader.readInt(4);
555 extraFieldValue = this.reader.readString(extraFieldLength);
556 this.zip64ExtensibleData[extraFieldId] = {
557 id: extraFieldId,
558 length: extraFieldLength,
559 value: extraFieldValue
560 };
561 }
562 },
563 /**
564 * Read the end of the Zip 64 central directory locator.
565 */
566 readBlockZip64EndOfCentralLocator : function () {
567 this.diskWithZip64CentralDirStart = this.reader.readInt(4);
568 this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8);
569 this.disksCount = this.reader.readInt(4);
570 if (this.disksCount > 1) {
571 throw new Error("Multi-volumes zip are not supported");
572 }
573 },
574 /**
575 * Read the local files, based on the offset read in the central part.
576 */
577 readLocalFiles : function() {
578 var i, file;
579 for(i = 0; i < this.files.length; i++) {
580 file = this.files[i];
581 this.reader.setIndex(file.localHeaderOffset);
582 this.checkSignature(JSZip.signature.LOCAL_FILE_HEADER);
583 file.readLocalPart(this.reader);
584 file.handleUTF8();
585 }
586 },
587 /**
588 * Read the central directory.
589 */
590 readCentralDir : function() {
591 var file;
592
593 this.reader.setIndex(this.centralDirOffset);
594 while(this.reader.readString(4) === JSZip.signature.CENTRAL_FILE_HEADER) {
595 file = new ZipEntry({
596 zip64: this.zip64
597 }, this.loadOptions);
598 file.readCentralPart(this.reader);
599 this.files.push(file);
600 }
601 },
602 /**
603 * Read the end of central directory.
604 */
605 readEndOfCentral : function() {
606 var offset = this.reader.lastIndexOfSignature(JSZip.signature.CENTRAL_DIRECTORY_END);
607 if (offset === -1) {
608 throw new Error("Corrupted zip : can't find end of central directory");
609 }
610 this.reader.setIndex(offset);
611 this.checkSignature(JSZip.signature.CENTRAL_DIRECTORY_END);
612 this.readBlockEndOfCentral();
613
614
615 /* extract from the zip spec :
616 4) If one of the fields in the end of central directory
617 record is too small to hold required data, the field
618 should be set to -1 (0xFFFF or 0xFFFFFFFF) and the
619 ZIP64 format record should be created.
620 5) The end of central directory record and the
621 Zip64 end of central directory locator record must
622 reside on the same disk when splitting or spanning
623 an archive.
624 */
625 if (this.diskNumber === MAX_VALUE_16BITS ||
626 this.diskWithCentralDirStart === MAX_VALUE_16BITS ||
627 this.centralDirRecordsOnThisDisk === MAX_VALUE_16BITS ||
628 this.centralDirRecords === MAX_VALUE_16BITS ||
629 this.centralDirSize === MAX_VALUE_32BITS ||
630 this.centralDirOffset === MAX_VALUE_32BITS
631 ) {
632 this.zip64 = true;
633
634 /*
635 Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from
636 the zip file can fit into a 32bits integer. This cannot be solved : Javascript represents
637 all numbers as 64-bit double precision IEEE 754 floating point numbers.
638 So, we have 53bits for integers and bitwise operations treat everything as 32bits.
639 see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators
640 and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5
641 */
642
643 // should look for a zip64 EOCD locator
644 offset = this.reader.lastIndexOfSignature(JSZip.signature.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
645 if (offset === -1) {
646 throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");
647 }
648 this.reader.setIndex(offset);
649 this.checkSignature(JSZip.signature.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
650 this.readBlockZip64EndOfCentralLocator();
651
652 // now the zip64 EOCD record
653 this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir);
654 this.checkSignature(JSZip.signature.ZIP64_CENTRAL_DIRECTORY_END);
655 this.readBlockZip64EndOfCentral();
656 }
657 },
658 prepareReader : function (data) {
659 var type = JSZip.utils.getTypeOf(data);
660 if (type === "string" && !JSZip.support.uint8array) {
661 this.reader = new StringReader(data, this.loadOptions.optimizedBinaryString);
662 } else if (type === "nodebuffer") {
663 this.reader = new NodeBufferReader(data);
664 } else {
665 this.reader = new Uint8ArrayReader(JSZip.utils.transformTo("uint8array", data));
666 }
667 },
668 /**
669 * Read a zip file and create ZipEntries.
670 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file.
671 */
672 load : function(data) {
673 this.prepareReader(data);
674 this.readEndOfCentral();
675 this.readCentralDir();
676 this.readLocalFiles();
677 }
678 };
679 // }}} end of ZipEntries
680
681 /**
682 * Implementation of the load method of JSZip.
683 * It uses the above classes to decode a zip file, and load every files.
684 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to load.
685 * @param {Object} options Options for loading the data.
686 * options.base64 : is the data in base64 ? default : false
687 */
688 JSZip.prototype.load = function(data, options) {
689 var files, zipEntries, i, input;
690 options = options || {};
691 if(options.base64) {
692 data = JSZip.base64.decode(data);
693 }
694
695 zipEntries = new ZipEntries(data, options);
696 files = zipEntries.files;
697 for (i = 0; i < files.length; i++) {
698 input = files[i];
699 this.file(input.fileName, input.decompressed, {
700 binary:true,
701 optimizedBinaryString:true,
702 date:input.date,
703 dir:input.dir
704 });
705 }
706
707 return this;
708 };
709
710}(this));
711// enforcing Stuk's coding style
712// vim: set shiftwidth=3 softtabstop=3 foldmethod=marker: