|
|
|
@ -9,7 +9,7 @@
|
|
|
|
|
* ZIP format: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
|
|
|
|
|
* DEFLATE format: http://tools.ietf.org/html/rfc1951
|
|
|
|
|
*/
|
|
|
|
|
/* global bitjs */
|
|
|
|
|
/* global bitjs, importScripts, Uint8Array*/
|
|
|
|
|
|
|
|
|
|
// This file expects to be invoked as a Worker (see onmessage below).
|
|
|
|
|
importScripts("io.js");
|
|
|
|
@ -44,12 +44,10 @@ var zLocalFileHeaderSignature = 0x04034b50;
|
|
|
|
|
var zArchiveExtraDataSignature = 0x08064b50;
|
|
|
|
|
var zCentralFileHeaderSignature = 0x02014b50;
|
|
|
|
|
var zDigitalSignatureSignature = 0x05054b50;
|
|
|
|
|
var zEndOfCentralDirSignature = 0x06064b50;
|
|
|
|
|
var zEndOfCentralDirLocatorSignature = 0x07064b50;
|
|
|
|
|
|
|
|
|
|
// takes a ByteStream and parses out the local file information
|
|
|
|
|
var ZipLocalFile = function(bstream) {
|
|
|
|
|
if (typeof bstream != typeof {} || !bstream.readNumber || typeof bstream.readNumber != typeof function(){}) {
|
|
|
|
|
if (typeof bstream != typeof {} || !bstream.readNumber || typeof bstream.readNumber != typeof function() {}) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -112,7 +110,7 @@ ZipLocalFile.prototype.unzip = function() {
|
|
|
|
|
|
|
|
|
|
// Zip Version 1.0, no compression (store only)
|
|
|
|
|
if (this.compressionMethod == 0 ) {
|
|
|
|
|
info("ZIP v"+this.version+", store only: " + this.filename + " (" + this.compressedSize + " bytes)");
|
|
|
|
|
info("ZIP v" + this.version + ", store only: " + this.filename + " (" + this.compressedSize + " bytes)");
|
|
|
|
|
currentBytesUnarchivedInFile = this.compressedSize;
|
|
|
|
|
currentBytesUnarchived += this.compressedSize;
|
|
|
|
|
}
|
|
|
|
@ -158,7 +156,7 @@ var unzip = function(arrayBuffer) {
|
|
|
|
|
totalFilesInArchive = localFiles.length;
|
|
|
|
|
|
|
|
|
|
// got all local files, now sort them
|
|
|
|
|
localFiles.sort(function(a,b) {
|
|
|
|
|
localFiles.sort(function(a, b) {
|
|
|
|
|
var aname = a.filename.toLowerCase();
|
|
|
|
|
var bname = b.filename.toLowerCase();
|
|
|
|
|
return aname > bname ? 1 : -1;
|
|
|
|
@ -239,7 +237,7 @@ var unzip = function(arrayBuffer) {
|
|
|
|
|
postProgress();
|
|
|
|
|
postMessage(new bitjs.archive.UnarchiveFinishEvent());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// returns a table of Huffman codes
|
|
|
|
|
// each entry's index is its code and its value is a JavaScript object
|
|
|
|
@ -253,7 +251,7 @@ function getHuffmanCodes(bitLengths) {
|
|
|
|
|
|
|
|
|
|
// Reference: http://tools.ietf.org/html/rfc1951#page-8
|
|
|
|
|
var numLengths = bitLengths.length,
|
|
|
|
|
bl_count = [],
|
|
|
|
|
blCount = [],
|
|
|
|
|
MAX_BITS = 1;
|
|
|
|
|
|
|
|
|
|
// Step 1: count up how many codes of each length we have
|
|
|
|
@ -265,22 +263,22 @@ function getHuffmanCodes(bitLengths) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
// increment the appropriate bitlength count
|
|
|
|
|
if (bl_count[length] == undefined) bl_count[length] = 0;
|
|
|
|
|
if (blCount[length] == undefined) blCount[length] = 0;
|
|
|
|
|
// a length of zero means this symbol is not participating in the huffman coding
|
|
|
|
|
if (length > 0) bl_count[length]++;
|
|
|
|
|
if (length > 0) blCount[length]++;
|
|
|
|
|
|
|
|
|
|
if (length > MAX_BITS) MAX_BITS = length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 2: Find the numerical value of the smallest code for each code length
|
|
|
|
|
var next_code = [],
|
|
|
|
|
var nextCode = [],
|
|
|
|
|
code = 0;
|
|
|
|
|
for (var bits = 1; bits <= MAX_BITS; ++bits) {
|
|
|
|
|
var length = bits-1;
|
|
|
|
|
var length = bits - 1;
|
|
|
|
|
// ensure undefined lengths are zero
|
|
|
|
|
if (bl_count[length] == undefined) bl_count[length] = 0;
|
|
|
|
|
code = (code + bl_count[bits-1]) << 1;
|
|
|
|
|
next_code[bits] = code;
|
|
|
|
|
if (blCount[length] == undefined) blCount[length] = 0;
|
|
|
|
|
code = (code + blCount[bits - 1]) << 1;
|
|
|
|
|
nextCode [bits] = code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 3: Assign numerical values to all codes
|
|
|
|
@ -288,9 +286,9 @@ function getHuffmanCodes(bitLengths) {
|
|
|
|
|
for (var n = 0; n < numLengths; ++n) {
|
|
|
|
|
var len = bitLengths[n];
|
|
|
|
|
if (len != 0) {
|
|
|
|
|
table[next_code[len]] = { length: len, symbol: n }; //, bitstring: binaryValueToString(next_code[len],len) };
|
|
|
|
|
table[nextCode [len]] = { length: len, symbol: n }; //, bitstring: binaryValueToString(nextCode [len],len) };
|
|
|
|
|
tableLength++;
|
|
|
|
|
next_code[len]++;
|
|
|
|
|
nextCode [len]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
table.maxLength = tableLength;
|
|
|
|
@ -321,7 +319,8 @@ function getFixedLiteralTable() {
|
|
|
|
|
// create once
|
|
|
|
|
if (!fixedHCtoLiteral) {
|
|
|
|
|
var bitlengths = new Array(288);
|
|
|
|
|
for (var i = 0; i <= 143; ++i) bitlengths[i] = 8;
|
|
|
|
|
var i;
|
|
|
|
|
for (i = 0; i <= 143; ++i) bitlengths[i] = 8;
|
|
|
|
|
for (i = 144; i <= 255; ++i) bitlengths[i] = 9;
|
|
|
|
|
for (i = 256; i <= 279; ++i) bitlengths[i] = 7;
|
|
|
|
|
for (i = 280; i <= 287; ++i) bitlengths[i] = 8;
|
|
|
|
@ -335,7 +334,9 @@ function getFixedDistanceTable() {
|
|
|
|
|
// create once
|
|
|
|
|
if (!fixedHCtoDistance) {
|
|
|
|
|
var bitlengths = new Array(32);
|
|
|
|
|
for (var i = 0; i < 32; ++i) { bitlengths[i] = 5; }
|
|
|
|
|
for (var i = 0; i < 32; ++i) {
|
|
|
|
|
bitlengths[i] = 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get huffman code table
|
|
|
|
|
fixedHCtoDistance = getHuffmanCodes(bitlengths);
|
|
|
|
@ -347,13 +348,12 @@ function getFixedDistanceTable() {
|
|
|
|
|
// then return that symbol
|
|
|
|
|
function decodeSymbol(bstream, hcTable) {
|
|
|
|
|
var code = 0, len = 0;
|
|
|
|
|
var match = false;
|
|
|
|
|
|
|
|
|
|
// loop until we match
|
|
|
|
|
for (;;) {
|
|
|
|
|
// read in next bit
|
|
|
|
|
var bit = bstream.readBits(1);
|
|
|
|
|
code = (code<<1) | bit;
|
|
|
|
|
code = (code << 1) | bit;
|
|
|
|
|
++len;
|
|
|
|
|
|
|
|
|
|
// check against Huffman Code table and break if found
|
|
|
|
@ -372,47 +372,47 @@ function decodeSymbol(bstream, hcTable) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var CodeLengthCodeOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
|
|
|
|
|
/*
|
|
|
|
|
Extra Extra Extra
|
|
|
|
|
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
|
|
|
|
---- ---- ------ ---- ---- ------- ---- ---- -------
|
|
|
|
|
257 0 3 267 1 15,16 277 4 67-82
|
|
|
|
|
258 0 4 268 1 17,18 278 4 83-98
|
|
|
|
|
259 0 5 269 2 19-22 279 4 99-114
|
|
|
|
|
260 0 6 270 2 23-26 280 4 115-130
|
|
|
|
|
261 0 7 271 2 27-30 281 5 131-162
|
|
|
|
|
262 0 8 272 2 31-34 282 5 163-194
|
|
|
|
|
263 0 9 273 3 35-42 283 5 195-226
|
|
|
|
|
264 0 10 274 3 43-50 284 5 227-257
|
|
|
|
|
265 1 11,12 275 3 51-58 285 0 258
|
|
|
|
|
266 1 13,14 276 3 59-66
|
|
|
|
|
/*
|
|
|
|
|
Extra Extra Extra
|
|
|
|
|
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
|
|
|
|
---- ---- ------ ---- ---- ------- ---- ---- -------
|
|
|
|
|
257 0 3 267 1 15,16 277 4 67-82
|
|
|
|
|
258 0 4 268 1 17,18 278 4 83-98
|
|
|
|
|
259 0 5 269 2 19-22 279 4 99-114
|
|
|
|
|
260 0 6 270 2 23-26 280 4 115-130
|
|
|
|
|
261 0 7 271 2 27-30 281 5 131-162
|
|
|
|
|
262 0 8 272 2 31-34 282 5 163-194
|
|
|
|
|
263 0 9 273 3 35-42 283 5 195-226
|
|
|
|
|
264 0 10 274 3 43-50 284 5 227-257
|
|
|
|
|
265 1 11,12 275 3 51-58 285 0 258
|
|
|
|
|
266 1 13,14 276 3 59-66
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
*/
|
|
|
|
|
var LengthLookupTable = [
|
|
|
|
|
[0,3], [0,4], [0,5], [0,6],
|
|
|
|
|
[0,7], [0,8], [0,9], [0,10],
|
|
|
|
|
[1,11], [1,13], [1,15], [1,17],
|
|
|
|
|
[2,19], [2,23], [2,27], [2,31],
|
|
|
|
|
[3,35], [3,43], [3,51], [3,59],
|
|
|
|
|
[4,67], [4,83], [4,99], [4,115],
|
|
|
|
|
[5,131], [5,163], [5,195], [5,227],
|
|
|
|
|
[0,258]
|
|
|
|
|
[0,3], [0,4], [0,5], [0,6],
|
|
|
|
|
[0,7], [0,8], [0,9], [0,10],
|
|
|
|
|
[1,11], [1,13], [1,15], [1,17],
|
|
|
|
|
[2,19], [2,23], [2,27], [2,31],
|
|
|
|
|
[3,35], [3,43], [3,51], [3,59],
|
|
|
|
|
[4,67], [4,83], [4,99], [4,115],
|
|
|
|
|
[5,131], [5,163], [5,195], [5,227],
|
|
|
|
|
[0,258]
|
|
|
|
|
];
|
|
|
|
|
/*
|
|
|
|
|
Extra Extra Extra
|
|
|
|
|
Code Bits Dist Code Bits Dist Code Bits Distance
|
|
|
|
|
---- ---- ---- ---- ---- ------ ---- ---- --------
|
|
|
|
|
0 0 1 10 4 33-48 20 9 1025-1536
|
|
|
|
|
1 0 2 11 4 49-64 21 9 1537-2048
|
|
|
|
|
2 0 3 12 5 65-96 22 10 2049-3072
|
|
|
|
|
3 0 4 13 5 97-128 23 10 3073-4096
|
|
|
|
|
4 1 5,6 14 6 129-192 24 11 4097-6144
|
|
|
|
|
5 1 7,8 15 6 193-256 25 11 6145-8192
|
|
|
|
|
6 2 9-12 16 7 257-384 26 12 8193-12288
|
|
|
|
|
7 2 13-16 17 7 385-512 27 12 12289-16384
|
|
|
|
|
8 3 17-24 18 8 513-768 28 13 16385-24576
|
|
|
|
|
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
|
|
|
|
*/
|
|
|
|
|
/*
|
|
|
|
|
Extra Extra Extra
|
|
|
|
|
Code Bits Dist Code Bits Dist Code Bits Distance
|
|
|
|
|
---- ---- ---- ---- ---- ------ ---- ---- --------
|
|
|
|
|
0 0 1 10 4 33-48 20 9 1025-1536
|
|
|
|
|
1 0 2 11 4 49-64 21 9 1537-2048
|
|
|
|
|
2 0 3 12 5 65-96 22 10 2049-3072
|
|
|
|
|
3 0 4 13 5 97-128 23 10 3073-4096
|
|
|
|
|
4 1 5,6 14 6 129-192 24 11 4097-6144
|
|
|
|
|
5 1 7,8 15 6 193-256 25 11 6145-8192
|
|
|
|
|
6 2 9-12 16 7 257-384 26 12 8193-12288
|
|
|
|
|
7 2 13-16 17 7 385-512 27 12 12289-16384
|
|
|
|
|
8 3 17-24 18 8 513-768 28 13 16385-24576
|
|
|
|
|
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
|
|
|
|
*/
|
|
|
|
|
var DistLookupTable = [
|
|
|
|
|
[0,1], [0,2], [0,3], [0,4],
|
|
|
|
|
[1,5], [1,7],
|
|
|
|
@ -446,10 +446,9 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
|
|
|
|
stream, and copy length bytes from this
|
|
|
|
|
position to the output stream.
|
|
|
|
|
*/
|
|
|
|
|
var numSymbols = 0, blockSize = 0;
|
|
|
|
|
var blockSize = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
var symbol = decodeSymbol(bstream, hcLiteralTable);
|
|
|
|
|
++numSymbols;
|
|
|
|
|
if (symbol < 256) {
|
|
|
|
|
// copy literal byte to output
|
|
|
|
|
buffer.insertByte(symbol);
|
|
|
|
@ -461,7 +460,7 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var lengthLookup = LengthLookupTable[symbol-257],
|
|
|
|
|
var lengthLookup = LengthLookupTable[symbol - 257],
|
|
|
|
|
length = lengthLookup[1] + bstream.readBits(lengthLookup[0]),
|
|
|
|
|
distLookup = DistLookupTable[decodeSymbol(bstream, hcDistanceTable)],
|
|
|
|
|
distance = distLookup[1] + bstream.readBits(distLookup[0]);
|
|
|
|
@ -479,13 +478,13 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
|
|
|
|
// loop for each character
|
|
|
|
|
var ch = buffer.ptr - distance;
|
|
|
|
|
blockSize += length;
|
|
|
|
|
if(length > distance) {
|
|
|
|
|
var data = buffer.data;
|
|
|
|
|
while (length--) {
|
|
|
|
|
buffer.insertByte(data[ch++]);
|
|
|
|
|
}
|
|
|
|
|
if (length > distance) {
|
|
|
|
|
var data = buffer.data;
|
|
|
|
|
while (length--) {
|
|
|
|
|
buffer.insertByte(data[ch++]);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
buffer.insertBytes(buffer.data.subarray(ch, ch + length))
|
|
|
|
|
buffer.insertBytes(buffer.data.subarray(ch, ch + length));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // length-distance pair
|
|
|
|
@ -516,11 +515,11 @@ function inflate(compressedData, numDecompressedBytes) {
|
|
|
|
|
if (bType == 0) {
|
|
|
|
|
// skip remaining bits in this byte
|
|
|
|
|
while (bstream.bitPtr != 0) bstream.readBits(1);
|
|
|
|
|
var len = bstream.readBits(16),
|
|
|
|
|
nlen = bstream.readBits(16);
|
|
|
|
|
// TODO: check if nlen is the ones-complement of len?
|
|
|
|
|
var len = bstream.readBits(16);
|
|
|
|
|
bstream.readBits(16);
|
|
|
|
|
// TODO: check if nlen is the ones-complement of len?
|
|
|
|
|
|
|
|
|
|
if(len > 0) buffer.insertBytes(bstream.readBytes(len));
|
|
|
|
|
if (len > 0) buffer.insertBytes(bstream.readBytes(len));
|
|
|
|
|
blockSize = len;
|
|
|
|
|
}
|
|
|
|
|
// fixed Huffman codes
|
|
|
|
@ -593,9 +592,8 @@ function inflate(compressedData, numDecompressedBytes) {
|
|
|
|
|
var hcLiteralTable = getHuffmanCodes(literalCodeLengths),
|
|
|
|
|
hcDistanceTable = getHuffmanCodes(distanceCodeLengths);
|
|
|
|
|
blockSize = inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer);
|
|
|
|
|
}
|
|
|
|
|
// error
|
|
|
|
|
else {
|
|
|
|
|
} else {
|
|
|
|
|
// error
|
|
|
|
|
err("Error! Encountered deflate block of type 3");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|