@ -9,7 +9,7 @@
* ZIP format : http : //www.pkware.com/documents/casestudies/APPNOTE.TXT
* ZIP format : http : //www.pkware.com/documents/casestudies/APPNOTE.TXT
* DEFLATE format : http : //tools.ietf.org/html/rfc1951
* 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).
// This file expects to be invoked as a Worker (see onmessage below).
importScripts ( "io.js" ) ;
importScripts ( "io.js" ) ;
@ -44,12 +44,10 @@ var zLocalFileHeaderSignature = 0x04034b50;
var zArchiveExtraDataSignature = 0x08064b50 ;
var zArchiveExtraDataSignature = 0x08064b50 ;
var zCentralFileHeaderSignature = 0x02014b50 ;
var zCentralFileHeaderSignature = 0x02014b50 ;
var zDigitalSignatureSignature = 0x05054b50 ;
var zDigitalSignatureSignature = 0x05054b50 ;
var zEndOfCentralDirSignature = 0x06064b50 ;
var zEndOfCentralDirLocatorSignature = 0x07064b50 ;
// takes a ByteStream and parses out the local file information
// takes a ByteStream and parses out the local file information
var ZipLocalFile = function ( bstream ) {
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 ;
return null ;
}
}
@ -112,7 +110,7 @@ ZipLocalFile.prototype.unzip = function() {
// Zip Version 1.0, no compression (store only)
// Zip Version 1.0, no compression (store only)
if ( this . compressionMethod == 0 ) {
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 ;
currentBytesUnarchivedInFile = this . compressedSize ;
currentBytesUnarchived += this . compressedSize ;
currentBytesUnarchived += this . compressedSize ;
}
}
@ -158,7 +156,7 @@ var unzip = function(arrayBuffer) {
totalFilesInArchive = localFiles . length ;
totalFilesInArchive = localFiles . length ;
// got all local files, now sort them
// got all local files, now sort them
localFiles . sort ( function ( a , b ) {
localFiles . sort ( function ( a , b ) {
var aname = a . filename . toLowerCase ( ) ;
var aname = a . filename . toLowerCase ( ) ;
var bname = b . filename . toLowerCase ( ) ;
var bname = b . filename . toLowerCase ( ) ;
return aname > bname ? 1 : - 1 ;
return aname > bname ? 1 : - 1 ;
@ -239,7 +237,7 @@ var unzip = function(arrayBuffer) {
postProgress ( ) ;
postProgress ( ) ;
postMessage ( new bitjs . archive . UnarchiveFinishEvent ( ) ) ;
postMessage ( new bitjs . archive . UnarchiveFinishEvent ( ) ) ;
}
}
}
} ;
// returns a table of Huffman codes
// returns a table of Huffman codes
// each entry's index is its code and its value is a JavaScript object
// 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
// Reference: http://tools.ietf.org/html/rfc1951#page-8
var numLengths = bitLengths . length ,
var numLengths = bitLengths . length ,
bl _c ount = [ ] ,
bl C ount = [ ] ,
MAX _BITS = 1 ;
MAX _BITS = 1 ;
// Step 1: count up how many codes of each length we have
// Step 1: count up how many codes of each length we have
@ -265,22 +263,22 @@ function getHuffmanCodes(bitLengths) {
return null ;
return null ;
}
}
// increment the appropriate bitlength count
// increment the appropriate bitlength count
if ( bl _count [ length ] == undefined ) bl _c ount[ length ] = 0 ;
if ( bl Count[ length ] == undefined ) blC ount[ length ] = 0 ;
// a length of zero means this symbol is not participating in the huffman coding
// a length of zero means this symbol is not participating in the huffman coding
if ( length > 0 ) bl _c ount[ length ] ++ ;
if ( length > 0 ) bl C ount[ length ] ++ ;
if ( length > MAX _BITS ) MAX _BITS = length ;
if ( length > MAX _BITS ) MAX _BITS = length ;
}
}
// Step 2: Find the numerical value of the smallest code for each code length
// Step 2: Find the numerical value of the smallest code for each code length
var next _c ode = [ ] ,
var next C ode = [ ] ,
code = 0 ;
code = 0 ;
for ( var bits = 1 ; bits <= MAX _BITS ; ++ bits ) {
for ( var bits = 1 ; bits <= MAX _BITS ; ++ bits ) {
var length = bits - 1 ;
var length = bits - 1 ;
// ensure undefined lengths are zero
// ensure undefined lengths are zero
if ( bl _count [ length ] == undefined ) bl _c ount[ length ] = 0 ;
if ( bl Count[ length ] == undefined ) blC ount[ length ] = 0 ;
code = ( code + bl _count [ bits - 1 ] ) << 1 ;
code = ( code + bl Count[ bits - 1 ] ) << 1 ;
next _code [ bits ] = code ;
next Code [ bits ] = code ;
}
}
// Step 3: Assign numerical values to all codes
// Step 3: Assign numerical values to all codes
@ -288,9 +286,9 @@ function getHuffmanCodes(bitLengths) {
for ( var n = 0 ; n < numLengths ; ++ n ) {
for ( var n = 0 ; n < numLengths ; ++ n ) {
var len = bitLengths [ n ] ;
var len = bitLengths [ n ] ;
if ( len != 0 ) {
if ( len != 0 ) {
table [ next _code [ len ] ] = { length : len , symbol : n } ; //, bitstring: binaryValueToString(next _code [len],len) };
table [ next Code [ len ] ] = { length : len , symbol : n } ; //, bitstring: binaryValueToString(next Code [len],len) };
tableLength ++ ;
tableLength ++ ;
next _code [ len ] ++ ;
next Code [ len ] ++ ;
}
}
}
}
table . maxLength = tableLength ;
table . maxLength = tableLength ;
@ -321,7 +319,8 @@ function getFixedLiteralTable() {
// create once
// create once
if ( ! fixedHCtoLiteral ) {
if ( ! fixedHCtoLiteral ) {
var bitlengths = new Array ( 288 ) ;
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 = 144 ; i <= 255 ; ++ i ) bitlengths [ i ] = 9 ;
for ( i = 256 ; i <= 279 ; ++ i ) bitlengths [ i ] = 7 ;
for ( i = 256 ; i <= 279 ; ++ i ) bitlengths [ i ] = 7 ;
for ( i = 280 ; i <= 287 ; ++ i ) bitlengths [ i ] = 8 ;
for ( i = 280 ; i <= 287 ; ++ i ) bitlengths [ i ] = 8 ;
@ -335,7 +334,9 @@ function getFixedDistanceTable() {
// create once
// create once
if ( ! fixedHCtoDistance ) {
if ( ! fixedHCtoDistance ) {
var bitlengths = new Array ( 32 ) ;
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
// get huffman code table
fixedHCtoDistance = getHuffmanCodes ( bitlengths ) ;
fixedHCtoDistance = getHuffmanCodes ( bitlengths ) ;
@ -347,13 +348,12 @@ function getFixedDistanceTable() {
// then return that symbol
// then return that symbol
function decodeSymbol ( bstream , hcTable ) {
function decodeSymbol ( bstream , hcTable ) {
var code = 0 , len = 0 ;
var code = 0 , len = 0 ;
var match = false ;
// loop until we match
// loop until we match
for ( ; ; ) {
for ( ; ; ) {
// read in next bit
// read in next bit
var bit = bstream . readBits ( 1 ) ;
var bit = bstream . readBits ( 1 ) ;
code = ( code << 1 ) | bit ;
code = ( code << 1 ) | bit ;
++ len ;
++ len ;
// check against Huffman Code table and break if found
// check against Huffman Code table and break if found
@ -372,10 +372,10 @@ 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 ] ;
var CodeLengthCodeOrder = [ 16 , 17 , 18 , 0 , 8 , 7 , 9 , 6 , 10 , 5 , 11 , 4 , 12 , 3 , 13 , 2 , 14 , 1 , 15 ] ;
/ *
/ *
Extra Extra Extra
Extra Extra Extra
Code Bits Length ( s ) Code Bits Lengths Code Bits Length ( s )
Code Bits Length ( s ) Code Bits Lengths Code Bits Length ( s )
-- -- -- -- -- -- -- -- -- -- -- -- -- -- - -- -- -- -- -- -- -- -
-- -- -- -- -- -- -- -- -- -- -- -- -- -- - -- -- -- -- -- -- -- -
257 0 3 267 1 15 , 16 277 4 67 - 82
257 0 3 267 1 15 , 16 277 4 67 - 82
258 0 4 268 1 17 , 18 278 4 83 - 98
258 0 4 268 1 17 , 18 278 4 83 - 98
259 0 5 269 2 19 - 22 279 4 99 - 114
259 0 5 269 2 19 - 22 279 4 99 - 114
@ -387,7 +387,7 @@ var CodeLengthCodeOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2
265 1 11 , 12 275 3 51 - 58 285 0 258
265 1 11 , 12 275 3 51 - 58 285 0 258
266 1 13 , 14 276 3 59 - 66
266 1 13 , 14 276 3 59 - 66
* /
* /
var LengthLookupTable = [
var LengthLookupTable = [
[ 0 , 3 ] , [ 0 , 4 ] , [ 0 , 5 ] , [ 0 , 6 ] ,
[ 0 , 3 ] , [ 0 , 4 ] , [ 0 , 5 ] , [ 0 , 6 ] ,
[ 0 , 7 ] , [ 0 , 8 ] , [ 0 , 9 ] , [ 0 , 10 ] ,
[ 0 , 7 ] , [ 0 , 8 ] , [ 0 , 9 ] , [ 0 , 10 ] ,
@ -398,7 +398,7 @@ var LengthLookupTable = [
[ 5 , 131 ] , [ 5 , 163 ] , [ 5 , 195 ] , [ 5 , 227 ] ,
[ 5 , 131 ] , [ 5 , 163 ] , [ 5 , 195 ] , [ 5 , 227 ] ,
[ 0 , 258 ]
[ 0 , 258 ]
] ;
] ;
/ *
/ *
Extra Extra Extra
Extra Extra Extra
Code Bits Dist Code Bits Dist Code Bits Distance
Code Bits Dist Code Bits Dist Code Bits Distance
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
@ -412,7 +412,7 @@ var LengthLookupTable = [
7 2 13 - 16 17 7 385 - 512 27 12 12289 - 16384
7 2 13 - 16 17 7 385 - 512 27 12 12289 - 16384
8 3 17 - 24 18 8 513 - 768 28 13 16385 - 24576
8 3 17 - 24 18 8 513 - 768 28 13 16385 - 24576
9 3 25 - 32 19 8 769 - 1024 29 13 24577 - 32768
9 3 25 - 32 19 8 769 - 1024 29 13 24577 - 32768
* /
* /
var DistLookupTable = [
var DistLookupTable = [
[ 0 , 1 ] , [ 0 , 2 ] , [ 0 , 3 ] , [ 0 , 4 ] ,
[ 0 , 1 ] , [ 0 , 2 ] , [ 0 , 3 ] , [ 0 , 4 ] ,
[ 1 , 5 ] , [ 1 , 7 ] ,
[ 1 , 5 ] , [ 1 , 7 ] ,
@ -446,10 +446,9 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
stream , and copy length bytes from this
stream , and copy length bytes from this
position to the output stream .
position to the output stream .
* /
* /
var numSymbols = 0 , blockSize = 0 ;
var blockSize = 0 ;
for ( ; ; ) {
for ( ; ; ) {
var symbol = decodeSymbol ( bstream , hcLiteralTable ) ;
var symbol = decodeSymbol ( bstream , hcLiteralTable ) ;
++ numSymbols ;
if ( symbol < 256 ) {
if ( symbol < 256 ) {
// copy literal byte to output
// copy literal byte to output
buffer . insertByte ( symbol ) ;
buffer . insertByte ( symbol ) ;
@ -461,7 +460,7 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
break ;
break ;
}
}
else {
else {
var lengthLookup = LengthLookupTable [ symbol - 257 ] ,
var lengthLookup = LengthLookupTable [ symbol - 257 ] ,
length = lengthLookup [ 1 ] + bstream . readBits ( lengthLookup [ 0 ] ) ,
length = lengthLookup [ 1 ] + bstream . readBits ( lengthLookup [ 0 ] ) ,
distLookup = DistLookupTable [ decodeSymbol ( bstream , hcDistanceTable ) ] ,
distLookup = DistLookupTable [ decodeSymbol ( bstream , hcDistanceTable ) ] ,
distance = distLookup [ 1 ] + bstream . readBits ( distLookup [ 0 ] ) ;
distance = distLookup [ 1 ] + bstream . readBits ( distLookup [ 0 ] ) ;
@ -479,13 +478,13 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
// loop for each character
// loop for each character
var ch = buffer . ptr - distance ;
var ch = buffer . ptr - distance ;
blockSize += length ;
blockSize += length ;
if ( length > distance ) {
if ( length > distance ) {
var data = buffer . data ;
var data = buffer . data ;
while ( length -- ) {
while ( length -- ) {
buffer . insertByte ( data [ ch ++ ] ) ;
buffer . insertByte ( data [ ch ++ ] ) ;
}
}
} else {
} else {
buffer . insertBytes ( buffer . data . subarray ( ch , ch + length ) )
buffer . insertBytes ( buffer . data . subarray ( ch , ch + length ) ) ;
}
}
} // length-distance pair
} // length-distance pair
@ -516,11 +515,11 @@ function inflate(compressedData, numDecompressedBytes) {
if ( bType == 0 ) {
if ( bType == 0 ) {
// skip remaining bits in this byte
// skip remaining bits in this byte
while ( bstream . bitPtr != 0 ) bstream . readBits ( 1 ) ;
while ( bstream . bitPtr != 0 ) bstream . readBits ( 1 ) ;
var len = bstream . readBits ( 16 ) ,
var len = bstream . readBits ( 16 ) ;
nlen = bstream . readBits ( 16 ) ;
bstream . readBits ( 16 ) ;
// TODO: check if nlen is the ones-complement of len?
// 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 ;
blockSize = len ;
}
}
// fixed Huffman codes
// fixed Huffman codes
@ -593,9 +592,8 @@ function inflate(compressedData, numDecompressedBytes) {
var hcLiteralTable = getHuffmanCodes ( literalCodeLengths ) ,
var hcLiteralTable = getHuffmanCodes ( literalCodeLengths ) ,
hcDistanceTable = getHuffmanCodes ( distanceCodeLengths ) ;
hcDistanceTable = getHuffmanCodes ( distanceCodeLengths ) ;
blockSize = inflateBlockData ( bstream , hcLiteralTable , hcDistanceTable , buffer ) ;
blockSize = inflateBlockData ( bstream , hcLiteralTable , hcDistanceTable , buffer ) ;
}
} else {
// error
// error
else {
err ( "Error! Encountered deflate block of type 3" ) ;
err ( "Error! Encountered deflate block of type 3" ) ;
return null ;
return null ;
}
}