zip-js 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,153 @@
1
+ /* jshint worker:true */
2
+ (function main(global) {
3
+ "use strict";
4
+
5
+ if (global.zWorkerInitialized)
6
+ throw new Error('z-worker.js should be run only once');
7
+ global.zWorkerInitialized = true;
8
+
9
+ addEventListener("message", function(event) {
10
+ var message = event.data, type = message.type, sn = message.sn;
11
+ var handler = handlers[type];
12
+ if (handler) {
13
+ try {
14
+ handler(message);
15
+ } catch (e) {
16
+ onError(type, sn, e);
17
+ }
18
+ }
19
+ //for debug
20
+ //postMessage({type: 'echo', originalType: type, sn: sn});
21
+ });
22
+
23
+ var handlers = {
24
+ importScripts: doImportScripts,
25
+ newTask: newTask,
26
+ append: processData,
27
+ flush: processData,
28
+ };
29
+
30
+ // deflater/inflater tasks indexed by serial numbers
31
+ var tasks = {};
32
+
33
+ function doImportScripts(msg) {
34
+ if (msg.scripts && msg.scripts.length > 0)
35
+ importScripts.apply(undefined, msg.scripts);
36
+ postMessage({type: 'importScripts'});
37
+ }
38
+
39
+ function newTask(msg) {
40
+ var CodecClass = global[msg.codecClass];
41
+ var sn = msg.sn;
42
+ if (tasks[sn])
43
+ throw Error('duplicated sn');
44
+ tasks[sn] = {
45
+ codec: new CodecClass(msg.options),
46
+ crcInput: msg.crcType === 'input',
47
+ crcOutput: msg.crcType === 'output',
48
+ crc: new Crc32(),
49
+ };
50
+ postMessage({type: 'newTask', sn: sn});
51
+ }
52
+
53
+ // performance may not be supported
54
+ var now = global.performance ? global.performance.now.bind(global.performance) : Date.now;
55
+
56
+ function processData(msg) {
57
+ var sn = msg.sn, type = msg.type, input = msg.data;
58
+ var task = tasks[sn];
59
+ // allow creating codec on first append
60
+ if (!task && msg.codecClass) {
61
+ newTask(msg);
62
+ task = tasks[sn];
63
+ }
64
+ var isAppend = type === 'append';
65
+ var start = now();
66
+ var output;
67
+ if (isAppend) {
68
+ try {
69
+ output = task.codec.append(input, function onprogress(loaded) {
70
+ postMessage({type: 'progress', sn: sn, loaded: loaded});
71
+ });
72
+ } catch (e) {
73
+ delete tasks[sn];
74
+ throw e;
75
+ }
76
+ } else {
77
+ delete tasks[sn];
78
+ output = task.codec.flush();
79
+ }
80
+ var codecTime = now() - start;
81
+
82
+ start = now();
83
+ if (input && task.crcInput)
84
+ task.crc.append(input);
85
+ if (output && task.crcOutput)
86
+ task.crc.append(output);
87
+ var crcTime = now() - start;
88
+
89
+ var rmsg = {type: type, sn: sn, codecTime: codecTime, crcTime: crcTime};
90
+ var transferables = [];
91
+ if (output) {
92
+ rmsg.data = output;
93
+ transferables.push(output.buffer);
94
+ }
95
+ if (!isAppend && (task.crcInput || task.crcOutput))
96
+ rmsg.crc = task.crc.get();
97
+
98
+ // posting a message with transferables will fail on IE10
99
+ try {
100
+ postMessage(rmsg, transferables);
101
+ } catch(ex) {
102
+ postMessage(rmsg); // retry without transferables
103
+ }
104
+ }
105
+
106
+ function onError(type, sn, e) {
107
+ var msg = {
108
+ type: type,
109
+ sn: sn,
110
+ error: formatError(e)
111
+ };
112
+ postMessage(msg);
113
+ }
114
+
115
+ function formatError(e) {
116
+ return { message: e.message, stack: e.stack };
117
+ }
118
+
119
+ // Crc32 code copied from file zip.js
120
+ function Crc32() {
121
+ this.crc = -1;
122
+ }
123
+ Crc32.prototype.append = function append(data) {
124
+ var crc = this.crc | 0, table = this.table;
125
+ for (var offset = 0, len = data.length | 0; offset < len; offset++)
126
+ crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
127
+ this.crc = crc;
128
+ };
129
+ Crc32.prototype.get = function get() {
130
+ return ~this.crc;
131
+ };
132
+ Crc32.prototype.table = (function() {
133
+ var i, j, t, table = []; // Uint32Array is actually slower than []
134
+ for (i = 0; i < 256; i++) {
135
+ t = i;
136
+ for (j = 0; j < 8; j++)
137
+ if (t & 1)
138
+ t = (t >>> 1) ^ 0xEDB88320;
139
+ else
140
+ t = t >>> 1;
141
+ table[i] = t;
142
+ }
143
+ return table;
144
+ })();
145
+
146
+ // "no-op" codec
147
+ function NOOP() {}
148
+ global.NOOP = NOOP;
149
+ NOOP.prototype.append = function append(bytes, onprogress) {
150
+ return bytes;
151
+ };
152
+ NOOP.prototype.flush = function flush() {};
153
+ })(this);
@@ -0,0 +1,242 @@
1
+ /*
2
+ Copyright (c) 2013 Gildas Lormeau. All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the distribution.
13
+
14
+ 3. The names of the authors may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ (function() {
30
+ "use strict";
31
+
32
+ var ERR_HTTP_RANGE = "HTTP Range not supported.";
33
+
34
+ var Reader = zip.Reader;
35
+ var Writer = zip.Writer;
36
+
37
+ var ZipDirectoryEntry;
38
+
39
+ var appendABViewSupported;
40
+ try {
41
+ appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
42
+ } catch (e) {
43
+ }
44
+
45
+ function HttpReader(url) {
46
+ var that = this;
47
+
48
+ function getData(callback, onerror) {
49
+ var request;
50
+ if (!that.data) {
51
+ request = new XMLHttpRequest();
52
+ request.addEventListener("load", function() {
53
+ if (!that.size)
54
+ that.size = Number(request.getResponseHeader("Content-Length"));
55
+ that.data = new Uint8Array(request.response);
56
+ callback();
57
+ }, false);
58
+ request.addEventListener("error", onerror, false);
59
+ request.open("GET", url);
60
+ request.responseType = "arraybuffer";
61
+ request.send();
62
+ } else
63
+ callback();
64
+ }
65
+
66
+ function init(callback, onerror) {
67
+ var request = new XMLHttpRequest();
68
+ request.addEventListener("load", function() {
69
+ that.size = Number(request.getResponseHeader("Content-Length"));
70
+ callback();
71
+ }, false);
72
+ request.addEventListener("error", onerror, false);
73
+ request.open("HEAD", url);
74
+ request.send();
75
+ }
76
+
77
+ function readUint8Array(index, length, callback, onerror) {
78
+ getData(function() {
79
+ callback(new Uint8Array(that.data.subarray(index, index + length)));
80
+ }, onerror);
81
+ }
82
+
83
+ that.size = 0;
84
+ that.init = init;
85
+ that.readUint8Array = readUint8Array;
86
+ }
87
+ HttpReader.prototype = new Reader();
88
+ HttpReader.prototype.constructor = HttpReader;
89
+
90
+ function HttpRangeReader(url) {
91
+ var that = this;
92
+
93
+ function init(callback, onerror) {
94
+ var request = new XMLHttpRequest();
95
+ request.addEventListener("load", function() {
96
+ that.size = Number(request.getResponseHeader("Content-Length"));
97
+ if (request.getResponseHeader("Accept-Ranges") == "bytes")
98
+ callback();
99
+ else
100
+ onerror(ERR_HTTP_RANGE);
101
+ }, false);
102
+ request.addEventListener("error", onerror, false);
103
+ request.open("HEAD", url);
104
+ request.send();
105
+ }
106
+
107
+ function readArrayBuffer(index, length, callback, onerror) {
108
+ var request = new XMLHttpRequest();
109
+ request.open("GET", url);
110
+ request.responseType = "arraybuffer";
111
+ request.setRequestHeader("Range", "bytes=" + index + "-" + (index + length - 1));
112
+ request.addEventListener("load", function() {
113
+ callback(request.response);
114
+ }, false);
115
+ request.addEventListener("error", onerror, false);
116
+ request.send();
117
+ }
118
+
119
+ function readUint8Array(index, length, callback, onerror) {
120
+ readArrayBuffer(index, length, function(arraybuffer) {
121
+ callback(new Uint8Array(arraybuffer));
122
+ }, onerror);
123
+ }
124
+
125
+ that.size = 0;
126
+ that.init = init;
127
+ that.readUint8Array = readUint8Array;
128
+ }
129
+ HttpRangeReader.prototype = new Reader();
130
+ HttpRangeReader.prototype.constructor = HttpRangeReader;
131
+
132
+ function ArrayBufferReader(arrayBuffer) {
133
+ var that = this;
134
+
135
+ function init(callback, onerror) {
136
+ that.size = arrayBuffer.byteLength;
137
+ callback();
138
+ }
139
+
140
+ function readUint8Array(index, length, callback, onerror) {
141
+ callback(new Uint8Array(arrayBuffer.slice(index, index + length)));
142
+ }
143
+
144
+ that.size = 0;
145
+ that.init = init;
146
+ that.readUint8Array = readUint8Array;
147
+ }
148
+ ArrayBufferReader.prototype = new Reader();
149
+ ArrayBufferReader.prototype.constructor = ArrayBufferReader;
150
+
151
+ function ArrayBufferWriter() {
152
+ var array, that = this;
153
+
154
+ function init(callback, onerror) {
155
+ array = new Uint8Array();
156
+ callback();
157
+ }
158
+
159
+ function writeUint8Array(arr, callback, onerror) {
160
+ var tmpArray = new Uint8Array(array.length + arr.length);
161
+ tmpArray.set(array);
162
+ tmpArray.set(arr, array.length);
163
+ array = tmpArray;
164
+ callback();
165
+ }
166
+
167
+ function getData(callback) {
168
+ callback(array.buffer);
169
+ }
170
+
171
+ that.init = init;
172
+ that.writeUint8Array = writeUint8Array;
173
+ that.getData = getData;
174
+ }
175
+ ArrayBufferWriter.prototype = new Writer();
176
+ ArrayBufferWriter.prototype.constructor = ArrayBufferWriter;
177
+
178
+ function FileWriter(fileEntry, contentType) {
179
+ var writer, that = this;
180
+
181
+ function init(callback, onerror) {
182
+ fileEntry.createWriter(function(fileWriter) {
183
+ writer = fileWriter;
184
+ callback();
185
+ }, onerror);
186
+ }
187
+
188
+ function writeUint8Array(array, callback, onerror) {
189
+ var blob = new Blob([ appendABViewSupported ? array : array.buffer ], {
190
+ type : contentType
191
+ });
192
+ writer.onwrite = function() {
193
+ writer.onwrite = null;
194
+ callback();
195
+ };
196
+ writer.onerror = onerror;
197
+ writer.write(blob);
198
+ }
199
+
200
+ function getData(callback) {
201
+ fileEntry.file(callback);
202
+ }
203
+
204
+ that.init = init;
205
+ that.writeUint8Array = writeUint8Array;
206
+ that.getData = getData;
207
+ }
208
+ FileWriter.prototype = new Writer();
209
+ FileWriter.prototype.constructor = FileWriter;
210
+
211
+ zip.FileWriter = FileWriter;
212
+ zip.HttpReader = HttpReader;
213
+ zip.HttpRangeReader = HttpRangeReader;
214
+ zip.ArrayBufferReader = ArrayBufferReader;
215
+ zip.ArrayBufferWriter = ArrayBufferWriter;
216
+
217
+ if (zip.fs) {
218
+ ZipDirectoryEntry = zip.fs.ZipDirectoryEntry;
219
+ ZipDirectoryEntry.prototype.addHttpContent = function(name, URL, useRangeHeader) {
220
+ function addChild(parent, name, params, directory) {
221
+ if (parent.directory)
222
+ return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new zip.fs.ZipFileEntry(parent.fs, name, params, parent);
223
+ else
224
+ throw "Parent entry is not a directory.";
225
+ }
226
+
227
+ return addChild(this, name, {
228
+ data : URL,
229
+ Reader : useRangeHeader ? HttpRangeReader : HttpReader
230
+ });
231
+ };
232
+ ZipDirectoryEntry.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
233
+ this.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror);
234
+ };
235
+ zip.fs.FS.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
236
+ this.entries = [];
237
+ this.root = new ZipDirectoryEntry(this);
238
+ this.root.importHttpContent(URL, useRangeHeader, onend, onerror);
239
+ };
240
+ }
241
+
242
+ })();
@@ -0,0 +1,541 @@
1
+ /*
2
+ Copyright (c) 2013 Gildas Lormeau. All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the distribution.
13
+
14
+ 3. The names of the authors may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ (function() {
30
+ "use strict";
31
+
32
+ var CHUNK_SIZE = 512 * 1024;
33
+
34
+ var TextWriter = zip.TextWriter, //
35
+ BlobWriter = zip.BlobWriter, //
36
+ Data64URIWriter = zip.Data64URIWriter, //
37
+ Reader = zip.Reader, //
38
+ TextReader = zip.TextReader, //
39
+ BlobReader = zip.BlobReader, //
40
+ Data64URIReader = zip.Data64URIReader, //
41
+ createReader = zip.createReader, //
42
+ createWriter = zip.createWriter;
43
+
44
+ function ZipBlobReader(entry) {
45
+ var that = this, blobReader;
46
+
47
+ function init(callback) {
48
+ that.size = entry.uncompressedSize;
49
+ callback();
50
+ }
51
+
52
+ function getData(callback) {
53
+ if (that.data)
54
+ callback();
55
+ else
56
+ entry.getData(new BlobWriter(), function(data) {
57
+ that.data = data;
58
+ blobReader = new BlobReader(data);
59
+ callback();
60
+ }, null, that.checkCrc32);
61
+ }
62
+
63
+ function readUint8Array(index, length, callback, onerror) {
64
+ getData(function() {
65
+ blobReader.readUint8Array(index, length, callback, onerror);
66
+ }, onerror);
67
+ }
68
+
69
+ that.size = 0;
70
+ that.init = init;
71
+ that.readUint8Array = readUint8Array;
72
+ }
73
+ ZipBlobReader.prototype = new Reader();
74
+ ZipBlobReader.prototype.constructor = ZipBlobReader;
75
+ ZipBlobReader.prototype.checkCrc32 = false;
76
+
77
+ function getTotalSize(entry) {
78
+ var size = 0;
79
+
80
+ function process(entry) {
81
+ size += entry.uncompressedSize || 0;
82
+ entry.children.forEach(process);
83
+ }
84
+
85
+ process(entry);
86
+ return size;
87
+ }
88
+
89
+ function initReaders(entry, onend, onerror) {
90
+ var index = 0;
91
+
92
+ function next() {
93
+ index++;
94
+ if (index < entry.children.length)
95
+ process(entry.children[index]);
96
+ else
97
+ onend();
98
+ }
99
+
100
+ function process(child) {
101
+ if (child.directory)
102
+ initReaders(child, next, onerror);
103
+ else {
104
+ child.reader = new child.Reader(child.data, onerror);
105
+ child.reader.init(function() {
106
+ child.uncompressedSize = child.reader.size;
107
+ next();
108
+ });
109
+ }
110
+ }
111
+
112
+ if (entry.children.length)
113
+ process(entry.children[index]);
114
+ else
115
+ onend();
116
+ }
117
+
118
+ function detach(entry) {
119
+ var children = entry.parent.children;
120
+ children.forEach(function(child, index) {
121
+ if (child.id == entry.id)
122
+ children.splice(index, 1);
123
+ });
124
+ }
125
+
126
+ function exportZip(zipWriter, entry, onend, onprogress, totalSize) {
127
+ var currentIndex = 0;
128
+
129
+ function process(zipWriter, entry, onend, onprogress, totalSize) {
130
+ var childIndex = 0;
131
+
132
+ function exportChild() {
133
+ var child = entry.children[childIndex];
134
+ if (child)
135
+ zipWriter.add(child.getFullname(), child.reader, function() {
136
+ currentIndex += child.uncompressedSize || 0;
137
+ process(zipWriter, child, function() {
138
+ childIndex++;
139
+ exportChild();
140
+ }, onprogress, totalSize);
141
+ }, function(index) {
142
+ if (onprogress)
143
+ onprogress(currentIndex + index, totalSize);
144
+ }, {
145
+ directory : child.directory,
146
+ version : child.zipVersion
147
+ });
148
+ else
149
+ onend();
150
+ }
151
+
152
+ exportChild();
153
+ }
154
+
155
+ process(zipWriter, entry, onend, onprogress, totalSize);
156
+ }
157
+
158
+ function addFileEntry(zipEntry, fileEntry, onend, onerror) {
159
+ function getChildren(fileEntry, callback) {
160
+ if (fileEntry.isDirectory)
161
+ fileEntry.createReader().readEntries(callback);
162
+ if (fileEntry.isFile)
163
+ callback([]);
164
+ }
165
+
166
+ function process(zipEntry, fileEntry, onend) {
167
+ getChildren(fileEntry, function(children) {
168
+ var childIndex = 0;
169
+
170
+ function addChild(child) {
171
+ function nextChild(childFileEntry) {
172
+ process(childFileEntry, child, function() {
173
+ childIndex++;
174
+ processChild();
175
+ });
176
+ }
177
+
178
+ if (child.isDirectory)
179
+ nextChild(zipEntry.addDirectory(child.name));
180
+ if (child.isFile)
181
+ child.file(function(file) {
182
+ var childZipEntry = zipEntry.addBlob(child.name, file);
183
+ childZipEntry.uncompressedSize = file.size;
184
+ nextChild(childZipEntry);
185
+ }, onerror);
186
+ }
187
+
188
+ function processChild() {
189
+ var child = children[childIndex];
190
+ if (child)
191
+ addChild(child);
192
+ else
193
+ onend();
194
+ }
195
+
196
+ processChild();
197
+ });
198
+ }
199
+
200
+ if (fileEntry.isDirectory)
201
+ process(zipEntry, fileEntry, onend);
202
+ else
203
+ fileEntry.file(function(file) {
204
+ zipEntry.addBlob(fileEntry.name, file);
205
+ onend();
206
+ }, onerror);
207
+ }
208
+
209
+ function getFileEntry(fileEntry, entry, onend, onprogress, onerror, totalSize, checkCrc32) {
210
+ var currentIndex = 0;
211
+
212
+ function process(fileEntry, entry, onend, onprogress, onerror, totalSize) {
213
+ var childIndex = 0;
214
+
215
+ function addChild(child) {
216
+ function nextChild(childFileEntry) {
217
+ currentIndex += child.uncompressedSize || 0;
218
+ process(childFileEntry, child, function() {
219
+ childIndex++;
220
+ processChild();
221
+ }, onprogress, onerror, totalSize);
222
+ }
223
+
224
+ if (child.directory)
225
+ fileEntry.getDirectory(child.name, {
226
+ create : true
227
+ }, nextChild, onerror);
228
+ else
229
+ fileEntry.getFile(child.name, {
230
+ create : true
231
+ }, function(file) {
232
+ child.getData(new zip.FileWriter(file, zip.getMimeType(child.name)), nextChild, function(index) {
233
+ if (onprogress)
234
+ onprogress(currentIndex + index, totalSize);
235
+ }, checkCrc32);
236
+ }, onerror);
237
+ }
238
+
239
+ function processChild() {
240
+ var child = entry.children[childIndex];
241
+ if (child)
242
+ addChild(child);
243
+ else
244
+ onend();
245
+ }
246
+
247
+ processChild();
248
+ }
249
+
250
+ if (entry.directory)
251
+ process(fileEntry, entry, onend, onprogress, onerror, totalSize);
252
+ else
253
+ entry.getData(new zip.FileWriter(fileEntry, zip.getMimeType(entry.name)), onend, onprogress, checkCrc32);
254
+ }
255
+
256
+ function resetFS(fs) {
257
+ fs.entries = [];
258
+ fs.root = new ZipDirectoryEntry(fs);
259
+ }
260
+
261
+ function bufferedCopy(reader, writer, onend, onprogress, onerror) {
262
+ var chunkIndex = 0;
263
+
264
+ function stepCopy() {
265
+ var index = chunkIndex * CHUNK_SIZE;
266
+ if (onprogress)
267
+ onprogress(index, reader.size);
268
+ if (index < reader.size)
269
+ reader.readUint8Array(index, Math.min(CHUNK_SIZE, reader.size - index), function(array) {
270
+ writer.writeUint8Array(new Uint8Array(array), function() {
271
+ chunkIndex++;
272
+ stepCopy();
273
+ });
274
+ }, onerror);
275
+ else
276
+ writer.getData(onend);
277
+ }
278
+
279
+ stepCopy();
280
+ }
281
+
282
+ function addChild(parent, name, params, directory) {
283
+ if (parent.directory)
284
+ return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
285
+ else
286
+ throw "Parent entry is not a directory.";
287
+ }
288
+
289
+ function ZipEntry() {
290
+ }
291
+
292
+ ZipEntry.prototype = {
293
+ init : function(fs, name, params, parent) {
294
+ var that = this;
295
+ if (fs.root && parent && parent.getChildByName(name))
296
+ throw "Entry filename already exists.";
297
+ if (!params)
298
+ params = {};
299
+ that.fs = fs;
300
+ that.name = name;
301
+ that.id = fs.entries.length;
302
+ that.parent = parent;
303
+ that.children = [];
304
+ that.zipVersion = params.zipVersion || 0x14;
305
+ that.uncompressedSize = 0;
306
+ fs.entries.push(that);
307
+ if (parent)
308
+ that.parent.children.push(that);
309
+ },
310
+ getFileEntry : function(fileEntry, onend, onprogress, onerror, checkCrc32) {
311
+ var that = this;
312
+ initReaders(that, function() {
313
+ getFileEntry(fileEntry, that, onend, onprogress, onerror, getTotalSize(that), checkCrc32);
314
+ }, onerror);
315
+ },
316
+ moveTo : function(target) {
317
+ var that = this;
318
+ if (target.directory) {
319
+ if (!target.isDescendantOf(that)) {
320
+ if (that != target) {
321
+ if (target.getChildByName(that.name))
322
+ throw "Entry filename already exists.";
323
+ detach(that);
324
+ that.parent = target;
325
+ target.children.push(that);
326
+ }
327
+ } else
328
+ throw "Entry is a ancestor of target entry.";
329
+ } else
330
+ throw "Target entry is not a directory.";
331
+ },
332
+ getFullname : function() {
333
+ var that = this, fullname = that.name, entry = that.parent;
334
+ while (entry) {
335
+ fullname = (entry.name ? entry.name + "/" : "") + fullname;
336
+ entry = entry.parent;
337
+ }
338
+ return fullname;
339
+ },
340
+ isDescendantOf : function(ancestor) {
341
+ var entry = this.parent;
342
+ while (entry && entry.id != ancestor.id)
343
+ entry = entry.parent;
344
+ return !!entry;
345
+ }
346
+ };
347
+ ZipEntry.prototype.constructor = ZipEntry;
348
+
349
+ var ZipFileEntryProto;
350
+
351
+ function ZipFileEntry(fs, name, params, parent) {
352
+ var that = this;
353
+ ZipEntry.prototype.init.call(that, fs, name, params, parent);
354
+ that.Reader = params.Reader;
355
+ that.Writer = params.Writer;
356
+ that.data = params.data;
357
+ if (params.getData) {
358
+ that.getData = params.getData;
359
+ }
360
+ }
361
+
362
+ ZipFileEntry.prototype = ZipFileEntryProto = new ZipEntry();
363
+ ZipFileEntryProto.constructor = ZipFileEntry;
364
+ ZipFileEntryProto.getData = function(writer, onend, onprogress, onerror) {
365
+ var that = this;
366
+ if (!writer || (writer.constructor == that.Writer && that.data))
367
+ onend(that.data);
368
+ else {
369
+ if (!that.reader)
370
+ that.reader = new that.Reader(that.data, onerror);
371
+ that.reader.init(function() {
372
+ writer.init(function() {
373
+ bufferedCopy(that.reader, writer, onend, onprogress, onerror);
374
+ }, onerror);
375
+ });
376
+ }
377
+ };
378
+
379
+ ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32, encoding) {
380
+ this.getData(new TextWriter(encoding), onend, onprogress, checkCrc32);
381
+ };
382
+ ZipFileEntryProto.getBlob = function(mimeType, onend, onprogress, checkCrc32) {
383
+ this.getData(new BlobWriter(mimeType), onend, onprogress, checkCrc32);
384
+ };
385
+ ZipFileEntryProto.getData64URI = function(mimeType, onend, onprogress, checkCrc32) {
386
+ this.getData(new Data64URIWriter(mimeType), onend, onprogress, checkCrc32);
387
+ };
388
+
389
+ var ZipDirectoryEntryProto;
390
+
391
+ function ZipDirectoryEntry(fs, name, params, parent) {
392
+ var that = this;
393
+ ZipEntry.prototype.init.call(that, fs, name, params, parent);
394
+ that.directory = true;
395
+ }
396
+
397
+ ZipDirectoryEntry.prototype = ZipDirectoryEntryProto = new ZipEntry();
398
+ ZipDirectoryEntryProto.constructor = ZipDirectoryEntry;
399
+ ZipDirectoryEntryProto.addDirectory = function(name) {
400
+ return addChild(this, name, null, true);
401
+ };
402
+ ZipDirectoryEntryProto.addText = function(name, text) {
403
+ return addChild(this, name, {
404
+ data : text,
405
+ Reader : TextReader,
406
+ Writer : TextWriter
407
+ });
408
+ };
409
+ ZipDirectoryEntryProto.addBlob = function(name, blob) {
410
+ return addChild(this, name, {
411
+ data : blob,
412
+ Reader : BlobReader,
413
+ Writer : BlobWriter
414
+ });
415
+ };
416
+ ZipDirectoryEntryProto.addData64URI = function(name, dataURI) {
417
+ return addChild(this, name, {
418
+ data : dataURI,
419
+ Reader : Data64URIReader,
420
+ Writer : Data64URIWriter
421
+ });
422
+ };
423
+ ZipDirectoryEntryProto.addFileEntry = function(fileEntry, onend, onerror) {
424
+ addFileEntry(this, fileEntry, onend, onerror);
425
+ };
426
+ ZipDirectoryEntryProto.addData = function(name, params) {
427
+ return addChild(this, name, params);
428
+ };
429
+ ZipDirectoryEntryProto.importBlob = function(blob, onend, onerror) {
430
+ this.importZip(new BlobReader(blob), onend, onerror);
431
+ };
432
+ ZipDirectoryEntryProto.importText = function(text, onend, onerror) {
433
+ this.importZip(new TextReader(text), onend, onerror);
434
+ };
435
+ ZipDirectoryEntryProto.importData64URI = function(dataURI, onend, onerror) {
436
+ this.importZip(new Data64URIReader(dataURI), onend, onerror);
437
+ };
438
+ ZipDirectoryEntryProto.exportBlob = function(onend, onprogress, onerror) {
439
+ this.exportZip(new BlobWriter("application/zip"), onend, onprogress, onerror);
440
+ };
441
+ ZipDirectoryEntryProto.exportText = function(onend, onprogress, onerror) {
442
+ this.exportZip(new TextWriter(), onend, onprogress, onerror);
443
+ };
444
+ ZipDirectoryEntryProto.exportFileEntry = function(fileEntry, onend, onprogress, onerror) {
445
+ this.exportZip(new zip.FileWriter(fileEntry, "application/zip"), onend, onprogress, onerror);
446
+ };
447
+ ZipDirectoryEntryProto.exportData64URI = function(onend, onprogress, onerror) {
448
+ this.exportZip(new Data64URIWriter("application/zip"), onend, onprogress, onerror);
449
+ };
450
+ ZipDirectoryEntryProto.importZip = function(reader, onend, onerror) {
451
+ var that = this;
452
+ createReader(reader, function(zipReader) {
453
+ zipReader.getEntries(function(entries) {
454
+ entries.forEach(function(entry) {
455
+ var parent = that, path = entry.filename.split("/"), name = path.pop();
456
+ path.forEach(function(pathPart) {
457
+ parent = parent.getChildByName(pathPart) || new ZipDirectoryEntry(that.fs, pathPart, null, parent);
458
+ });
459
+ if (!entry.directory)
460
+ addChild(parent, name, {
461
+ data : entry,
462
+ Reader : ZipBlobReader
463
+ });
464
+ });
465
+ onend();
466
+ });
467
+ }, onerror);
468
+ };
469
+ ZipDirectoryEntryProto.exportZip = function(writer, onend, onprogress, onerror) {
470
+ var that = this;
471
+ initReaders(that, function() {
472
+ createWriter(writer, function(zipWriter) {
473
+ exportZip(zipWriter, that, function() {
474
+ zipWriter.close(onend);
475
+ }, onprogress, getTotalSize(that));
476
+ }, onerror);
477
+ }, onerror);
478
+ };
479
+ ZipDirectoryEntryProto.getChildByName = function(name) {
480
+ var childIndex, child, that = this;
481
+ for (childIndex = 0; childIndex < that.children.length; childIndex++) {
482
+ child = that.children[childIndex];
483
+ if (child.name == name)
484
+ return child;
485
+ }
486
+ };
487
+
488
+ function FS() {
489
+ resetFS(this);
490
+ }
491
+ FS.prototype = {
492
+ remove : function(entry) {
493
+ detach(entry);
494
+ this.entries[entry.id] = null;
495
+ },
496
+ find : function(fullname) {
497
+ var index, path = fullname.split("/"), node = this.root;
498
+ for (index = 0; node && index < path.length; index++)
499
+ node = node.getChildByName(path[index]);
500
+ return node;
501
+ },
502
+ getById : function(id) {
503
+ return this.entries[id];
504
+ },
505
+ importBlob : function(blob, onend, onerror) {
506
+ resetFS(this);
507
+ this.root.importBlob(blob, onend, onerror);
508
+ },
509
+ importText : function(text, onend, onerror) {
510
+ resetFS(this);
511
+ this.root.importText(text, onend, onerror);
512
+ },
513
+ importData64URI : function(dataURI, onend, onerror) {
514
+ resetFS(this);
515
+ this.root.importData64URI(dataURI, onend, onerror);
516
+ },
517
+ exportBlob : function(onend, onprogress, onerror) {
518
+ this.root.exportBlob(onend, onprogress, onerror);
519
+ },
520
+ exportText : function(onend, onprogress, onerror) {
521
+ this.root.exportText(onend, onprogress, onerror);
522
+ },
523
+ exportFileEntry : function(fileEntry, onend, onprogress, onerror) {
524
+ this.root.exportFileEntry(fileEntry, onend, onprogress, onerror);
525
+ },
526
+ exportData64URI : function(onend, onprogress, onerror) {
527
+ this.root.exportData64URI(onend, onprogress, onerror);
528
+ }
529
+ };
530
+
531
+ zip.fs = {
532
+ FS : FS,
533
+ ZipDirectoryEntry : ZipDirectoryEntry,
534
+ ZipFileEntry : ZipFileEntry
535
+ };
536
+
537
+ zip.getMimeType = function() {
538
+ return "application/octet-stream";
539
+ };
540
+
541
+ })();