Comparing version 0.1.2 to 0.1.3
204
adm-zip.js
@@ -9,6 +9,8 @@ var fs = require("fs"), | ||
module.exports = function(/*String*/inPath) { | ||
var _zip = undefined; | ||
var _zip = undefined, | ||
_filename = ""; | ||
if (inPath && typeof inPath === "string") { // load zip file | ||
if (pth.existsSync(inPath)) { | ||
_filename = inPath; | ||
_zip = new ZipFile(fs.readFileSync(inPath)); | ||
@@ -39,2 +41,6 @@ } else { | ||
//process.on('uncaughtException', function (err) { | ||
// console.log('Caught exception: ' + err); | ||
//}); | ||
return { | ||
@@ -49,8 +55,23 @@ /** | ||
var item = getEntry(entry); | ||
return item && entry.data || null; | ||
return item && item.getData() || null; | ||
}, | ||
/** | ||
* Asynchronous readFile | ||
* @param entry ZipEntry object or String with the full path of the entry | ||
* @param callback | ||
* | ||
* @return Buffer or Null in case of error | ||
*/ | ||
readFileAsync : function(/*Object*/entry, /*Function*/callback) { | ||
var item = getEntry(entry); | ||
if (item) { | ||
item.getData(callback); | ||
} else { | ||
callback(null) | ||
} | ||
}, | ||
/** | ||
* Extracts the given entry from the archive and returns the content as plain text in the given encoding | ||
* @param entry ZipEntry object or String with the full path of the entry | ||
* @param encoding If no encoding is specified utf8 is used | ||
* @param encoding Optional. If no encoding is specified utf8 is used | ||
* | ||
@@ -62,3 +83,3 @@ * @return String | ||
if (item) { | ||
var data = entry.data; | ||
var data = item.getData(); | ||
if (data && data.length) { | ||
@@ -70,38 +91,77 @@ return data.toString(encoding || "utf8"); | ||
}, | ||
/** | ||
* Asynchronous readAsText | ||
* @param entry ZipEntry object or String with the full path of the entry | ||
* @param callback | ||
* @param encoding Optional. If no encoding is specified utf8 is used | ||
* | ||
* @return String | ||
*/ | ||
readAsTextAsync : function(/*Object*/entry, /*Function*/callback, /*String - Optional*/encoding) { | ||
var item = getEntry(entry); | ||
if (item) { | ||
item.getData(function(data) { | ||
if (data && data.length) { | ||
callback(data.toString(encoding || "utf8")); | ||
} | ||
}) | ||
} else { | ||
callback(""); | ||
} | ||
}, | ||
deleteFile : function(/*Object*/entry, /*Boolean*/writeZip) { | ||
/** | ||
* Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory | ||
* | ||
* @param entry | ||
*/ | ||
deleteFile : function(/*Object*/entry) { | ||
var item = getEntry(entry); | ||
if (item) { | ||
_zip.deleteEntry(item.entryName); | ||
if (writeZip) { | ||
throw Utils.Errors.NOT_IMPLEMENTED | ||
} | ||
} | ||
}, | ||
addZipComment : function(/*String*/comment, /*Boolean*/writeZip) { | ||
/** | ||
* Adds a comment to the zip. The zip must be rewritten after adding the comment. | ||
* | ||
* @param comment | ||
*/ | ||
addZipComment : function(/*String*/comment) { | ||
_zip.comment = comment; | ||
if (writeZip) { | ||
throw Utils.Errors.NOT_IMPLEMENTED | ||
} | ||
}, | ||
/** | ||
* Returns the zip comment | ||
* | ||
* @return String | ||
*/ | ||
getZipComment : function() { | ||
return _zip.comment; | ||
return _zip.comment || ''; | ||
}, | ||
addZipEntryComment : function(/*Object*/entry,/*String*/comment, /*Boolean*/writeZip) { | ||
/** | ||
* Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment | ||
* The comment cannot exceed 65535 characters in length | ||
* | ||
* @param entry | ||
* @param comment | ||
*/ | ||
addZipEntryComment : function(/*Object*/entry,/*String*/comment) { | ||
var item = getEntry(entry); | ||
if (item) { | ||
item.comment = comment; | ||
if (writeZip) { | ||
throw Utils.Errors.NOT_IMPLEMENTED; | ||
} | ||
} | ||
}, | ||
/** | ||
* Returns the comment of the specified entry | ||
* | ||
* @param entry | ||
* @return String | ||
*/ | ||
getZipEntryComment : function(/*Object*/entry) { | ||
var item = getEntry(entry); | ||
if (item) { | ||
return item.comment; | ||
return item.comment || ''; | ||
} | ||
@@ -111,15 +171,23 @@ return '' | ||
updateFile : function(/*Object*/entry, /*Buffer*/content, /*Boolean*/writeZip) { | ||
/** | ||
* Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content | ||
* | ||
* @param entry | ||
* @param content | ||
*/ | ||
updateFile : function(/*Object*/entry, /*Buffer*/content) { | ||
var item = getEntry(entry); | ||
if (item) { | ||
item.data = content; | ||
if (writeZip) { | ||
throw Utils.Errors.NOT_IMPLEMENTED; | ||
} | ||
item.setData(content); | ||
} | ||
}, | ||
addLocalFile : function(/*String*/localPath, /*Boolean*/writeZip) { | ||
/** | ||
* Adds a file from the disk to the archive | ||
* | ||
* @param localPath | ||
*/ | ||
addLocalFile : function(/*String*/localPath) { | ||
if (pth.existsSync(localPath)) { | ||
// do stuff | ||
} else { | ||
@@ -130,5 +198,32 @@ throw Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath); | ||
addLocalFolder : function(/*String*/localPath, /*Boolean*/writeZip) { | ||
/** | ||
* Adds a local directory and all its nested files and directories to the archive | ||
* | ||
* @param localPath | ||
*/ | ||
addLocalFolder : function(/*String*/localPath) { | ||
if (localPath.charAt(localPath.length - 1) != "/") | ||
localPath += "/"; | ||
if (pth.existsSync(localPath)) { | ||
var items = Utils.findFiles(localPath); | ||
if (items.length) { | ||
items.forEach(function(path) { | ||
var entry = new ZipEntry(); | ||
entry.entryName = path.replace(localPath, ""); | ||
var stats = fs.statSync(path); | ||
if (stats.isDirectory()) { | ||
entry.setData(""); | ||
entry.header.inAttr = stats.mode; | ||
entry.header.attr = stats.mode | ||
} else { | ||
entry.setData(fs.readFileSync(path)); | ||
entry.header.inAttr = stats.mode; | ||
entry.header.attr = stats.mode | ||
} | ||
entry.attr = stats.mode; | ||
entry.header.time = stats.mtime; | ||
_zip.setEntry(entry); | ||
}); | ||
} | ||
} else { | ||
@@ -139,2 +234,12 @@ throw Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath); | ||
/** | ||
* Allows you to programmatically create a entry (file or directory) in the zip file. | ||
* If you want to create a directory the entryName must end in / and a null buffer should be provided. | ||
* Comment and attributes are optional | ||
* | ||
* @param entryName | ||
* @param content | ||
* @param comment | ||
* @param attr | ||
*/ | ||
addFile : function(/*String*/entryName, /*Buffer*/content, /*String*/comment, /*Number*/attr) { | ||
@@ -148,3 +253,3 @@ var entry = new ZipEntry(); | ||
} | ||
entry.data = content; | ||
entry.setData(content); | ||
entry.header.time = new Date(); | ||
@@ -167,2 +272,8 @@ _zip.setEntry(entry); | ||
/** | ||
* Returns a ZipEntry object representing the file or folder specified by ``name``. | ||
* | ||
* @param name | ||
* @return ZipEntry | ||
*/ | ||
getEntry : function(/*String*/name) { | ||
@@ -178,3 +289,3 @@ return getEntry(name); | ||
* @param targetPath Target folder where to write the file | ||
* @param maintainEntryPath If full path is true and the entry is inside a folder, the entry folder | ||
* @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder | ||
* will be created in targetPath as well. Default is TRUE | ||
@@ -202,9 +313,12 @@ * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true. | ||
if (child.isDirectory) return; | ||
var content = child.data; | ||
if (!content) throw Utils.Errors.CANT_EXTRACT_FILE; | ||
var content = child.getData(); | ||
if (!content) { | ||
throw Utils.Errors.CANT_EXTRACT_FILE; | ||
} | ||
Utils.writeFileTo(pth.resolve(targetPath, maintainEntryPath ? child.entryName : child.entryName.substr(item.entryName.length)), content, overwrite); | ||
}) | ||
}); | ||
return true; | ||
} | ||
var content = item.data; | ||
var content = item.getData(); | ||
if (!content) throw Utils.Errors.CANT_EXTRACT_FILE; | ||
@@ -221,3 +335,3 @@ | ||
/** | ||
* Extracts the entire archive to the givn location | ||
* Extracts the entire archive to the given location | ||
* | ||
@@ -235,5 +349,7 @@ * @param targetPath Target location | ||
_zip.entries.forEach(function(entry) { | ||
if (entry.isDirectory) return; | ||
var content = entry.data; | ||
if (!content) throw Utils.Errors.CANT_EXTRACT_FILE; | ||
if (entry.isDirectory) return; | ||
var content = entry.getData(); | ||
if (!content) { | ||
throw Utils.Errors.CANT_EXTRACT_FILE + "2"; | ||
} | ||
Utils.writeFileTo(pth.resolve(targetPath, entry.entryName), content, overwrite); | ||
@@ -243,3 +359,12 @@ }) | ||
/** | ||
* Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip | ||
* | ||
* @param targetFileName | ||
*/ | ||
writeZip : function(/*String*/targetFileName) { | ||
if (!targetFileName && _filename) { | ||
targetFileName = _filename; | ||
} | ||
if (!targetFileName) return; | ||
var zipData = _zip.toBuffer(); | ||
@@ -251,2 +376,7 @@ if (zipData) { | ||
/** | ||
* Returns the content of the entire zip file as a Buffer object | ||
* | ||
* @return Buffer | ||
*/ | ||
toBuffer : function() { | ||
@@ -253,0 +383,0 @@ return _zip.toBuffer() |
@@ -6,3 +6,3 @@ var Utils = require("../util"), | ||
module.exports = function () { | ||
var _version = 0, | ||
var _version = 0x0A, | ||
_flags = 0, | ||
@@ -19,3 +19,3 @@ _method = 0, | ||
get version () { return _version; }, | ||
set version (val) { _version = val }, | ||
set version (val) { _version = 0x0A }, | ||
@@ -22,0 +22,0 @@ get flags () { return _flags }, |
@@ -6,3 +6,3 @@ var Utils = require("../util"), | ||
module.exports = function () { | ||
var _verMade = 0, | ||
var _verMade = 0x0A, | ||
_version = 10, | ||
@@ -9,0 +9,0 @@ _flags = 0, |
@@ -0,9 +1,1050 @@ | ||
function JSDeflater(/*inbuff*/inbuf) { | ||
var WSIZE = 0x8000, // Sliding Window size | ||
WINDOW_SIZE = 0x10000, | ||
/* for deflate */ | ||
MIN_MATCH = 0x03, | ||
MAX_MATCH = 0x102, | ||
LIT_BUFSIZE = 0x2000, | ||
MAX_DIST = 0x7EFA, | ||
MAX_BITS = 0x0F, | ||
MAX_BL_BITS = 0x07, | ||
L_CODES = 0x11E, | ||
D_CODES = 0x1E, | ||
BL_CODES = 0x13, | ||
REP_3_6 = 0x10, | ||
REPZ_3_10 = 0x11, | ||
REPZ_11_138 = 0x12, | ||
HEAP_SIZE = 2 * L_CODES + 1, | ||
H_SHIFT = parseInt((0x10 + MIN_MATCH - 1) / MIN_MATCH), | ||
/* variables */ | ||
freeQueue, | ||
qHead, qTail, | ||
initFlag, | ||
outbuf = null, | ||
outcnt, outoff, | ||
complete, | ||
window, | ||
dBuf, | ||
lBuf, | ||
prev, | ||
biBuf, | ||
biValid, | ||
blockStart, | ||
zip_ins_h, | ||
hashHead, | ||
prevMatch, | ||
matchAvailable, | ||
matchLength, | ||
matchStart, | ||
prevLength, | ||
dataStart, | ||
eofile, | ||
lookahead, | ||
maxChainLength, | ||
maxLazyMatch, | ||
compression_level, | ||
goodMatch, | ||
dynLTree = [], | ||
dynDTree = [], | ||
staticLTree = [], | ||
staticDTree = [], | ||
blTree = [], | ||
lDesc, | ||
dDesc, | ||
blDesc, | ||
blCount, | ||
zip_heap, | ||
heapLen, | ||
heapMax, | ||
depth, | ||
lengthCode, | ||
distCode, | ||
baseLength, | ||
baseDist, | ||
flagBuf, | ||
lastLit, | ||
lastDist, | ||
lastFlags, | ||
flags, | ||
flagBit, | ||
optLen, | ||
staticLen, | ||
deflateData, | ||
deflatePos, | ||
elbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], | ||
edbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13], | ||
eblbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], | ||
blorder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; | ||
function deflateTreeDesc() { | ||
return { | ||
dyn_tree : null, // the dynamic tree | ||
static_tree : null, // corresponding static tree or NULL | ||
extra_bits : null, // extra bits for each code or NULL | ||
extra_base : 0, // base index for extra_bits | ||
elems : 0, // max number of elements in the tree | ||
max_length : 0, // max bit length for the codes | ||
max_code : 0 | ||
} | ||
} | ||
function deflateStart(level) { | ||
var i; | ||
compression_level = !level && 9 || level > 9 && 9 || level; | ||
initFlag = false; | ||
eofile = false; | ||
if(outbuf != null) | ||
return; | ||
freeQueue = qHead = qTail = null; | ||
outbuf = new Buffer(LIT_BUFSIZE); | ||
window = new Buffer(WINDOW_SIZE); | ||
dBuf = new Array(LIT_BUFSIZE); | ||
lBuf = new Array(inbuf.length + 0x64); // 0x64 extra buffer length | ||
prev = new Array(0x10000); | ||
for(i = 0; i < HEAP_SIZE; i++) dynLTree[i] = {fc:0, dl:0}; | ||
for(i = 0; i < 2 * D_CODES + 1; i++) dynDTree[i] = {fc:0, dl:0}; | ||
for(i = 0; i < L_CODES + 2; i++) staticLTree[i] = {fc:0, dl:0}; | ||
for(i = 0; i < D_CODES; i++) staticDTree[i] = {fc:0, dl:0}; | ||
for(i = 0; i < 2 * BL_CODES + 1; i++) blTree[i] = {fc:0, dl:0}; | ||
lDesc = deflateTreeDesc(); | ||
dDesc = deflateTreeDesc(); | ||
blDesc = deflateTreeDesc(); | ||
blCount = new Buffer(MAX_BITS + 1); | ||
zip_heap = new Array(2 * L_CODES + 1); | ||
depth = new Buffer(2 * L_CODES + 1); | ||
lengthCode = new Buffer(MAX_MATCH - MIN_MATCH + 1); | ||
distCode = new Buffer(0x200); | ||
baseLength = new Buffer(0x1D); | ||
baseDist = new Buffer(D_CODES); | ||
flagBuf = new Buffer(parseInt(LIT_BUFSIZE / 8)); | ||
} | ||
function cleanup() { | ||
freeQueue = qHead = qTail = null; | ||
outbuf = null; | ||
window = null; | ||
dBuf = null; | ||
lBuf = null; | ||
prev = null; | ||
dynLTree = null; | ||
dynDTree = null; | ||
staticLTree = null; | ||
staticDTree = null; | ||
blTree = null; | ||
lDesc = null; | ||
dDesc = null; | ||
blDesc = null; | ||
blCount = null; | ||
zip_heap = null; | ||
depth = null; | ||
lengthCode = null; | ||
distCode = null; | ||
baseLength = null; | ||
baseDist = null; | ||
flagBuf = null; | ||
} | ||
function writeByte(c) { | ||
outbuf[outoff + outcnt++] = c; | ||
if(outoff + outcnt == LIT_BUFSIZE) { | ||
if(outcnt != 0) { | ||
var q, i; | ||
if (freeQueue != null) { | ||
q = freeQueue; | ||
freeQueue = freeQueue.next; | ||
} else { | ||
q = { | ||
"next" : null, | ||
"len" : 0, | ||
"ptr" : new Buffer(LIT_BUFSIZE), | ||
"off" : 0 | ||
} | ||
} | ||
q.next = null; | ||
q.len = q.off = 0; | ||
if(qHead == null) | ||
qHead = qTail = q; | ||
else | ||
qTail = qTail.next = q; | ||
q.len = outcnt - outoff; | ||
for(i = 0; i < q.len; i++) | ||
q.ptr[i] = outbuf[outoff + i]; | ||
outcnt = outoff = 0; | ||
} | ||
} | ||
} | ||
function writeShort(w) { | ||
w &= 0xffff; | ||
if(outoff + outcnt < LIT_BUFSIZE - 2) { | ||
outbuf[outoff + outcnt++] = (w & 0xff); | ||
outbuf[outoff + outcnt++] = (w >>> 8); | ||
} else { | ||
writeByte(w & 0xff); | ||
writeByte(w >>> 8); | ||
} | ||
return true; | ||
} | ||
function insertString() { | ||
zip_ins_h = ((zip_ins_h << H_SHIFT) ^ (window[dataStart + MIN_MATCH - 1] & 0xff)) & 0x1FFF; | ||
hashHead = prev[WSIZE + zip_ins_h]; | ||
prev[dataStart & 0x7FFF] = hashHead; | ||
prev[WSIZE + zip_ins_h] = dataStart; | ||
} | ||
function sendCode(c, tree) { | ||
sendBits(tree[c].fc, tree[c].dl); | ||
} | ||
function zip_D_CODE(dist) { | ||
return (dist < 256 ? distCode[dist] | ||
: distCode[256 + (dist>>7)]) & 0xff; | ||
} | ||
function smaller(tree, n, m) { | ||
return tree[n].fc < tree[m].fc || | ||
(tree[n].fc == tree[m].fc && depth[n] <= depth[m]); | ||
} | ||
function readBuff(buff, offset, n) { | ||
var i, len = deflateData.length; | ||
for(i = 0; i < n && deflatePos < len; i++) { | ||
buff[offset + i] = deflateData[deflatePos++]; | ||
} | ||
return i; | ||
} | ||
function lmInit() { | ||
var j; | ||
for(j = 0; j < 0x2000; j++) prev[WSIZE + j] = 0; | ||
goodMatch = [0x0, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x20, 0x20][compression_level]; | ||
maxLazyMatch = [0x0, 0x4, 0x5, 0x6, 0x4, 0x10, 0x10, 0x20, 0x80, 0x102][compression_level]; | ||
maxChainLength = [0x0, 0x4, 0x8, 0x20, 0x10, 0x20, 0x80, 0x100, 0x400, 0x1000][compression_level]; | ||
dataStart = 0; | ||
blockStart = 0; | ||
lookahead = readBuff(window, 0, 2 * WSIZE); | ||
if(lookahead <= 0) { | ||
eofile = true; | ||
lookahead = 0; | ||
return; | ||
} | ||
eofile = false; | ||
while(lookahead < 0x106 && !eofile) | ||
fillWindow(); | ||
zip_ins_h = 0; | ||
for(j = 0; j < MIN_MATCH - 1; j++) { | ||
zip_ins_h = ((zip_ins_h << H_SHIFT) ^ (window[j] & 0xFF)) & 0x1FFF; | ||
} | ||
} | ||
function longestMatch(cur_match) { | ||
var chain_length = maxChainLength, // max hash chain length | ||
scanp = dataStart, // current string | ||
matchp, // matched string | ||
len, // length of current match | ||
best_len = prevLength, // best match length so far | ||
limit = (dataStart > MAX_DIST ? dataStart - MAX_DIST : 0), | ||
strendp = dataStart + MAX_MATCH, | ||
scan_end1 = window[scanp + best_len - 1], | ||
scan_end = window[scanp + best_len]; | ||
prevLength >= goodMatch && (chain_length >>= 2); | ||
do { | ||
matchp = cur_match; | ||
if(window[matchp + best_len] != scan_end || | ||
window[matchp + best_len - 1] != scan_end1 || | ||
window[matchp] != window[scanp] || | ||
window[++matchp] != window[scanp + 1]) { | ||
continue; | ||
} | ||
scanp += 2; | ||
matchp++; | ||
do {} while(window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
window[++scanp] == window[++matchp] && | ||
scanp < strendp); | ||
len = MAX_MATCH - (strendp - scanp); | ||
scanp = strendp - MAX_MATCH; | ||
if(len > best_len) { | ||
matchStart = cur_match; | ||
best_len = len; | ||
if(len >= MAX_MATCH) break; | ||
scan_end1 = window[scanp + best_len-1]; | ||
scan_end = window[scanp + best_len]; | ||
} | ||
} while((cur_match = prev[cur_match & 0x7FFF]) > limit && --chain_length != 0); | ||
return best_len; | ||
} | ||
function fillWindow() { | ||
var n, m, | ||
more = WINDOW_SIZE - lookahead - dataStart; | ||
if(more == -1) { | ||
more--; | ||
} else if(dataStart >= WSIZE + MAX_DIST) { | ||
for(n = 0; n < WSIZE; n++) | ||
window[n] = window[n + WSIZE]; | ||
matchStart -= WSIZE; | ||
dataStart -= WSIZE; | ||
blockStart -= WSIZE; | ||
for(n = 0; n < 0x2000; n++) { | ||
m = prev[WSIZE + n]; | ||
prev[WSIZE + n] = m >= WSIZE ? m - WSIZE : 0; | ||
} | ||
for(n = 0; n < WSIZE; n++) { | ||
m = prev[n]; | ||
prev[n] = (m >= WSIZE ? m - WSIZE : 0); | ||
} | ||
more += WSIZE; | ||
} | ||
if(!eofile) { | ||
n = readBuff(window, dataStart + lookahead, more); | ||
n <= 0 && (eofile = true) || (lookahead += n); | ||
} | ||
} | ||
function deflateFast() { | ||
while(lookahead != 0 && qHead == null) { | ||
var flush; // set if current block must be flushed | ||
insertString(); | ||
if(hashHead != 0 && dataStart - hashHead <= MAX_DIST) { | ||
matchLength = longestMatch(hashHead); | ||
matchLength > lookahead && (matchLength = lookahead); | ||
} | ||
if(matchLength >= MIN_MATCH) { | ||
flush = ctTally(dataStart - matchStart, matchLength - MIN_MATCH); | ||
lookahead -= matchLength; | ||
if(matchLength <= maxLazyMatch) { | ||
matchLength--; | ||
do { | ||
dataStart++; | ||
insertString(); | ||
} while(--matchLength != 0); | ||
dataStart++; | ||
} else { | ||
dataStart += matchLength; | ||
matchLength = 0; | ||
zip_ins_h = (((window[dataStart] & 0xFF) << H_SHIFT) ^ (window[dataStart + 1] & 0xFF)) & 0x1FFF; | ||
} | ||
} else { | ||
flush = ctTally(0, window[dataStart] & 0xFF); | ||
lookahead--; | ||
dataStart++; | ||
} | ||
if(flush) { | ||
flushBlock(0); | ||
blockStart = dataStart; | ||
} | ||
while(lookahead < 0x106 && !eofile) | ||
fillWindow(); | ||
} | ||
} | ||
function deflateBetter() { | ||
while(lookahead != 0 && qHead == null) { | ||
insertString(); | ||
prevLength = matchLength; | ||
prevMatch = matchStart; | ||
matchLength = MIN_MATCH - 1; | ||
if(hashHead != 0 && prevLength < maxLazyMatch && dataStart - hashHead <= MAX_DIST) { | ||
matchLength = longestMatch(hashHead); | ||
matchLength > lookahead && (matchLength = lookahead); | ||
(matchLength == MIN_MATCH && dataStart - matchStart > 0x1000) && matchLength--; | ||
} | ||
if(prevLength >= MIN_MATCH && matchLength <= prevLength) { | ||
var flush; // set if current block must be flushed | ||
flush = ctTally(dataStart - 1 - prevMatch, prevLength - MIN_MATCH); | ||
lookahead -= prevLength - 1; | ||
prevLength -= 2; | ||
do { | ||
dataStart++; | ||
insertString(); | ||
} while(--prevLength != 0); | ||
matchAvailable = 0; | ||
matchLength = MIN_MATCH - 1; | ||
dataStart++; | ||
if(flush) { | ||
flushBlock(0); | ||
blockStart = dataStart; | ||
} | ||
} else if( matchAvailable != 0) { | ||
if(ctTally(0, window[dataStart - 1] & 0xff)) { | ||
flushBlock(0); | ||
blockStart = dataStart; | ||
} | ||
dataStart++; | ||
lookahead--; | ||
} else { | ||
matchAvailable = 1; | ||
dataStart++; | ||
lookahead--; | ||
} | ||
while(lookahead < 0x106 && !eofile) | ||
fillWindow(); | ||
} | ||
} | ||
function initDeflate() { | ||
if(eofile) return; | ||
biBuf = 0; | ||
biValid = 0; | ||
ctInit(); | ||
lmInit(); | ||
qHead = null; | ||
outcnt = 0; | ||
outoff = 0; | ||
if(compression_level <= 3) { | ||
prevLength = MIN_MATCH - 1; | ||
matchLength = 0; | ||
} else { | ||
matchLength = MIN_MATCH - 1; | ||
matchAvailable = 0; | ||
} | ||
complete = false; | ||
} | ||
function internalDeflate(buff, off, buff_size) { | ||
var n; | ||
if(!initFlag) { | ||
initDeflate(); | ||
initFlag = true; | ||
if(lookahead == 0) { // empty | ||
complete = true; | ||
return 0; | ||
} | ||
} | ||
if((n = qCopy(buff, off, buff_size)) == buff_size) return buff_size; | ||
if(complete) return n; | ||
if(compression_level <= 3) // optimized for speed | ||
deflateFast(); | ||
else | ||
deflateBetter(); | ||
if(lookahead == 0) { | ||
matchAvailable != 0 && ctTally(0, window[dataStart - 1] & 0xff); | ||
flushBlock(1); | ||
complete = true; | ||
} | ||
return n + qCopy(buff, n + off, buff_size - n); | ||
} | ||
function qCopy(buff, off, buff_size) { | ||
var n = 0, i, j; | ||
while(qHead != null && n < buff_size) { | ||
i = buff_size - n; | ||
i > qHead.len && (i = qHead.len); | ||
for(j = 0; j < i; j++) buff[off + n + j] = qHead.ptr[qHead.off + j]; | ||
qHead.off += i; | ||
qHead.len -= i; | ||
n += i; | ||
if(qHead.len == 0) { | ||
var p; | ||
p = qHead; | ||
qHead = qHead.next; | ||
p.next = freeQueue; | ||
freeQueue = p; | ||
} | ||
} | ||
if(n == buff_size) return n; | ||
if(outoff < outcnt) { | ||
i = buff_size - n; | ||
if(i > outcnt - outoff) | ||
i = outcnt - outoff; | ||
for(j = 0; j < i; j++) | ||
buff[off + n + j] = outbuf[outoff + j]; | ||
outoff += i; | ||
n += i; | ||
if(outcnt == outoff) | ||
outcnt = outoff = 0; | ||
} | ||
return n; | ||
} | ||
function ctInit() { | ||
var n, // iterates over tree elements | ||
bits, // bit counter | ||
length, // length value | ||
code, // code value | ||
dist; // distance index | ||
if(staticDTree[0].dl != 0) return; // ct_init already called | ||
lDesc.dyn_tree = dynLTree; | ||
lDesc.static_tree = staticLTree; | ||
lDesc.extra_bits = elbits; | ||
lDesc.extra_base = 0x101; | ||
lDesc.elems = L_CODES; | ||
lDesc.max_length = MAX_BITS; | ||
lDesc.max_code = 0; | ||
dDesc.dyn_tree = dynDTree; | ||
dDesc.static_tree = staticDTree; | ||
dDesc.extra_bits = edbits; | ||
dDesc.extra_base = 0; | ||
dDesc.elems = D_CODES; | ||
dDesc.max_length = MAX_BITS; | ||
dDesc.max_code = 0; | ||
blDesc.dyn_tree = blTree; | ||
blDesc.static_tree = null; | ||
blDesc.extra_bits = eblbits; | ||
blDesc.extra_base = 0; | ||
blDesc.elems = BL_CODES; | ||
blDesc.max_length = MAX_BL_BITS; | ||
blDesc.max_code = 0; | ||
// Initialize the mapping length (0..255) -> length code (0..28) | ||
length = 0; | ||
for(code = 0; code < 0x1E; code++) { | ||
baseLength[code] = length; | ||
for(n = 0; n < (1 << elbits[code]); n++) | ||
lengthCode[length++] = code; | ||
} | ||
lengthCode[length - 1] = code; | ||
dist = 0; | ||
for(code = 0 ; code < 16; code++) { | ||
baseDist[code] = dist; | ||
for(n = 0; n < (1 << edbits[code]); n++) | ||
distCode[dist++] = code; | ||
} | ||
dist >>= 7; // from now on, all distances are divided by 128 | ||
for( ; code < D_CODES; code++) { | ||
baseDist[code] = dist << 7; | ||
for(n = 0; n < (1<<(edbits[code]-7)); n++) | ||
distCode[256 + dist++] = code; | ||
} | ||
for(bits = 0; bits <= MAX_BITS; bits++) blCount[bits] = 0; | ||
n = 0; | ||
while(n <= 143) { staticLTree[n++].dl = 8; blCount[8]++; } | ||
while(n <= 255) { staticLTree[n++].dl = 9; blCount[9]++; } | ||
while(n <= 279) { staticLTree[n++].dl = 7; blCount[7]++; } | ||
while(n <= 287) { staticLTree[n++].dl = 8; blCount[8]++; } | ||
genCodes(staticLTree, L_CODES + 1); | ||
for(n = 0; n < D_CODES; n++) { | ||
staticDTree[n].dl = 5; | ||
staticDTree[n].fc = reverse(n, 5); | ||
} | ||
initBlock(); | ||
} | ||
function initBlock() { | ||
var n; | ||
for(n = 0; n < L_CODES; n++) dynLTree[n].fc = 0; | ||
for(n = 0; n < D_CODES; n++) dynDTree[n].fc = 0; | ||
for(n = 0; n < BL_CODES; n++) blTree[n].fc = 0; | ||
dynLTree[0x100].fc = flagBit = 1; // end block | ||
flags = optLen = staticLen = lastLit = lastDist = lastFlags = 0; | ||
} | ||
function pqDownHeap(tree, k) { | ||
var v = zip_heap[k], | ||
j = k << 1; | ||
while(j <= heapLen) { | ||
(j < heapLen && smaller(tree, zip_heap[j + 1], zip_heap[j])) && j++; | ||
if(smaller(tree, v, zip_heap[j])) break; | ||
zip_heap[k] = zip_heap[j]; | ||
k = j; | ||
j <<= 1; | ||
} | ||
zip_heap[k] = v; | ||
} | ||
function genBitLen(desc) { | ||
var tree = desc.dyn_tree, | ||
extra = desc.extra_bits, | ||
base = desc.extra_base, | ||
max_code = desc.max_code, | ||
max_length = desc.max_length, | ||
stree = desc.static_tree, | ||
h, // heap index | ||
n, m, // iterate over the tree elements | ||
bits, // bit length | ||
xbits, // extra bits | ||
f, // frequency | ||
overflow = 0; // number of elements with bit length too large | ||
for(bits = 0; bits <= MAX_BITS; bits++) | ||
blCount[bits] = 0; | ||
tree[zip_heap[heapMax]].dl = 0; // root of the heap | ||
for(h = heapMax + 1; h < HEAP_SIZE; h++) { | ||
n = zip_heap[h]; | ||
bits = tree[tree[n].dl].dl + 1; | ||
if(bits > max_length) { | ||
bits = max_length; | ||
overflow++; | ||
} | ||
tree[n].dl = bits; | ||
if(n > max_code) continue; // not a leaf node | ||
blCount[bits]++; | ||
xbits = 0; | ||
n >= base && (xbits = extra[n - base]); | ||
f = tree[n].fc; | ||
optLen += f * (bits + xbits); | ||
stree != null && (staticLen += f * (stree[n].dl + xbits)); | ||
} | ||
if (!overflow) return; | ||
do { | ||
bits = max_length - 1; | ||
while(blCount[bits] == 0) bits--; | ||
blCount[bits]--; // move one leaf down the tree | ||
blCount[bits + 1] += 2; // move one overflow item as its brother | ||
blCount[max_length]--; | ||
overflow -= 2; | ||
} while(overflow > 0); | ||
for(bits = max_length; bits != 0; bits--) { | ||
n = blCount[bits]; | ||
while(n != 0) { | ||
m = zip_heap[--h]; | ||
if(m > max_code) continue; | ||
if(tree[m].dl != bits) { | ||
optLen += (bits - tree[m].dl) * tree[m].fc; | ||
tree[m].fc = bits; | ||
} | ||
n--; | ||
} | ||
} | ||
} | ||
function genCodes(tree, max_code) { | ||
var next_code = new Array(MAX_BITS + 1), // next code value for each bit length | ||
code = 0, // running code value | ||
bits, // bit index | ||
n; // code index | ||
for(bits = 1; bits <= MAX_BITS; bits++) { | ||
code = ((code + blCount[bits-1]) << 1); | ||
next_code[bits] = code; | ||
} | ||
for(n = 0; n <= max_code; n++) { | ||
var len = tree[n].dl; | ||
if (len == 0) | ||
continue; | ||
tree[n].fc = reverse(next_code[len]++, len); | ||
} | ||
} | ||
function buildTree(desc) { // the tree descriptor | ||
var tree = desc.dyn_tree, | ||
stree = desc.static_tree, | ||
elems = desc.elems, | ||
n, m, // iterate over heap elements | ||
max_code = -1, // largest code with non zero frequency | ||
node = elems; // next internal node of the tree | ||
heapLen = 0; | ||
heapMax = HEAP_SIZE; | ||
for(n = 0; n < elems; n++) { | ||
if(tree[n].fc != 0) { | ||
zip_heap[++heapLen] = max_code = n; | ||
depth[n] = 0; | ||
} else | ||
tree[n].dl = 0; | ||
} | ||
while(heapLen < 2) { | ||
var xnew = zip_heap[++heapLen] = (max_code < 2 ? ++max_code : 0); | ||
tree[xnew].fc = 1; | ||
depth[xnew] = 0; | ||
optLen--; | ||
stree != null && (staticLen -= stree[xnew].dl); | ||
} | ||
desc.max_code = max_code; | ||
for(n = heapLen >> 1; n >= 1; n--) pqDownHeap(tree, n); | ||
do { | ||
n = zip_heap[1]; | ||
zip_heap[1] = zip_heap[heapLen--]; | ||
pqDownHeap(tree, 1); | ||
m = zip_heap[1]; // m = node of next least frequency | ||
// keep the nodes sorted by frequency | ||
zip_heap[--heapMax] = n; | ||
zip_heap[--heapMax] = m; | ||
// Create a new node father of n and m | ||
tree[node].fc = tree[n].fc + tree[m].fc; | ||
if(depth[n] > depth[m] + 1) | ||
depth[node] = depth[n]; | ||
else | ||
depth[node] = depth[m] + 1; | ||
tree[n].dl = tree[m].dl = node; | ||
// and insert the new node in the heap | ||
zip_heap[1] = node++; | ||
pqDownHeap(tree, 1); | ||
} while(heapLen >= 2); | ||
zip_heap[--heapMax] = zip_heap[1]; | ||
genBitLen(desc); | ||
genCodes(tree, max_code); | ||
} | ||
function scanTree(tree, max_code) { | ||
var n, // iterates over all tree elements | ||
prevlen = -1, // last emitted length | ||
curlen, // length of current code | ||
nextlen = tree[0].dl, // length of next code | ||
count = 0, // repeat count of the current code | ||
max_count = 7, // max repeat count | ||
min_count = 4; // min repeat count | ||
if(nextlen == 0) { | ||
max_count = 138; | ||
min_count = 3; | ||
} | ||
tree[max_code + 1].dl = 0xffff; // guard | ||
for(n = 0; n <= max_code; n++) { | ||
curlen = nextlen; | ||
nextlen = tree[n + 1].dl; | ||
if(++count < max_count && curlen == nextlen) | ||
continue; | ||
else if(count < min_count) | ||
blTree[curlen].fc += count; | ||
else if(curlen != 0) { | ||
if(curlen != prevlen) | ||
blTree[curlen].fc++; | ||
blTree[REP_3_6].fc++; | ||
} else if(count <= 10) | ||
blTree[REPZ_3_10].fc++; | ||
else | ||
blTree[REPZ_11_138].fc++; | ||
count = 0; prevlen = curlen; | ||
if(nextlen == 0) { | ||
max_count = 138; | ||
min_count = 3; | ||
} else if(curlen == nextlen) { | ||
max_count = 6; | ||
min_count = 3; | ||
} else { | ||
max_count = 7; | ||
min_count = 4; | ||
} | ||
} | ||
} | ||
function sendTree(tree, max_code) { | ||
var n, // iterates over all tree elements | ||
prevlen = -1, // last emitted length | ||
curlen, // length of current code | ||
nextlen = tree[0].dl, // length of next code | ||
count = 0, // repeat count of the current code | ||
max_count = 7, // max repeat count | ||
min_count = 4; // min repeat count | ||
if(nextlen == 0) { | ||
max_count = 138; | ||
min_count = 3; | ||
} | ||
for(n = 0; n <= max_code; n++) { | ||
curlen = nextlen; | ||
nextlen = tree[n+1].dl; | ||
if(++count < max_count && curlen == nextlen) { | ||
continue; | ||
} else if(count < min_count) { | ||
do { sendCode(curlen, blTree); } while(--count != 0); | ||
} else if(curlen != 0) { | ||
if(curlen != prevlen) { | ||
sendCode(curlen, blTree); | ||
count--; | ||
} | ||
sendCode(REP_3_6, blTree); | ||
sendBits(count - 3, 2); | ||
} else if(count <= 10) { | ||
sendCode(REPZ_3_10, blTree); | ||
sendBits(count-3, 3); | ||
} else { | ||
sendCode(REPZ_11_138, blTree); | ||
sendBits(count-11, 7); | ||
} | ||
count = 0; | ||
prevlen = curlen; | ||
if(nextlen == 0) { | ||
max_count = 138; | ||
min_count = 3; | ||
} else if(curlen == nextlen) { | ||
max_count = 6; | ||
min_count = 3; | ||
} else { | ||
max_count = 7; | ||
min_count = 4; | ||
} | ||
} | ||
} | ||
function buildBLTree() { | ||
var max_blindex; // index of last bit length code of non zero freq | ||
scanTree(dynLTree, lDesc.max_code); | ||
scanTree(dynDTree, dDesc.max_code); | ||
buildTree(blDesc); | ||
for(max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { | ||
if(blTree[blorder[max_blindex]].dl != 0) break; | ||
} | ||
/* Update opt_len to include the bit length tree and counts */ | ||
optLen += 3 * (max_blindex + 1) + 0xE; | ||
return max_blindex; | ||
} | ||
function sendTrees(lcodes, dcodes, blcodes) { | ||
var rank; // index in bl_order | ||
sendBits(lcodes - 0x101, 5); | ||
sendBits(dcodes - 1, 5); | ||
sendBits(blcodes - 4, 4); | ||
for(rank = 0; rank < blcodes; rank++) | ||
sendBits(blTree[blorder[rank]].dl, 3); | ||
sendTree(dynLTree, lcodes - 1); | ||
sendTree(dynDTree, dcodes - 1); | ||
} | ||
function flushBlock(eof) { // true if this is the last block for a file | ||
var opt_lenb, static_lenb, // opt_len and static_len in bytes | ||
max_blindex, // index of last bit length code of non zero freq | ||
stored_len = dataStart - blockStart; // length of input block | ||
flagBuf[lastFlags] = flags; // Save the flags for the last 8 items | ||
buildTree(lDesc); | ||
buildTree(dDesc); | ||
max_blindex = buildBLTree(); | ||
// Determine the best encoding. Compute first the block length in bytes | ||
opt_lenb = (optLen + 3 + 7) >> 3; | ||
static_lenb = (staticLen + 3 + 7) >> 3; | ||
static_lenb <= opt_lenb && (opt_lenb = static_lenb); | ||
if(stored_len + 4 <= opt_lenb && blockStart >= 0) { | ||
var i; | ||
sendBits(eof, 3); /* send block type */ | ||
biValid && writeShort(biBuf) && (biBuf = biValid = 0); /* align on byte boundary */ | ||
writeShort(stored_len); | ||
writeShort(~stored_len); | ||
for(i = 0; i < stored_len; i++) writeByte(window[blockStart + i]); | ||
} else if(static_lenb == opt_lenb) { | ||
sendBits(eof + 2, 3); | ||
compress(staticLTree, staticDTree); | ||
} else { | ||
sendBits(eof + 4, 3); | ||
sendTrees(lDesc.max_code + 1, dDesc.max_code + 1, max_blindex + 1); | ||
compress(dynLTree, dynDTree); | ||
} | ||
initBlock(); | ||
(eof != 0) && (biValid && writeShort(biBuf) && (biBuf = biValid = 0)); | ||
} | ||
function ctTally(dist, lc) { | ||
lBuf[lastLit++] = lc; | ||
if(dist == 0) { | ||
dynLTree[lc].fc++; | ||
} else { | ||
dist--; | ||
dynLTree[lengthCode[lc] + 0x101].fc++; | ||
dynDTree[zip_D_CODE(dist)].fc++; | ||
dBuf[lastDist++] = dist; | ||
flags |= flagBit; | ||
} | ||
flagBit <<= 1; | ||
if((lastLit & 7) == 0) { | ||
flagBuf[lastFlags++] = flags; | ||
flags = 0; | ||
flagBit = 1; | ||
} | ||
if(compression_level > 2 && (lastLit & 0xfff) == 0) { | ||
var out_length = lastLit * 8, | ||
in_length = dataStart - blockStart, | ||
dcode; | ||
for(dcode = 0; dcode < D_CODES; dcode++) { | ||
out_length += dynDTree[dcode].fc * (5 + edbits[dcode]); | ||
} | ||
out_length >>= 3; | ||
if(lastDist < parseInt(lastLit / 2) && out_length < parseInt(in_length / 2)) | ||
return true; | ||
} | ||
return (lastLit == LIT_BUFSIZE - 1 || lastDist == LIT_BUFSIZE); | ||
} | ||
function compress(ltree, dtree) { | ||
var dist, // distance of matched string | ||
lc, // match length or unmatched char (if dist == 0) | ||
lx = 0, // running index in l_buf | ||
dx = 0, // running index in d_buf | ||
fx = 0, // running index in flag_buf | ||
flag = 0, // current flags | ||
code, // the code to send | ||
extra; // number of extra bits to send | ||
if (lastLit != 0) do { | ||
(lx & 7) == 0 && (flag = flagBuf[fx++]); | ||
lc = lBuf[lx++] & 0xff; | ||
if ((flag & 1) == 0) { | ||
sendCode(lc, ltree); /* send a literal byte */ | ||
} else { | ||
code = lengthCode[lc]; | ||
sendCode(code + 0x101, ltree); // send the length code | ||
extra = elbits[code]; | ||
if(extra != 0) { | ||
lc -= baseLength[code]; | ||
sendBits(lc, extra); // send the extra length bits | ||
} | ||
dist = dBuf[dx++]; | ||
code = zip_D_CODE(dist); | ||
sendCode(code, dtree); // send the distance code | ||
extra = edbits[code]; | ||
if(extra != 0) { | ||
dist -= baseDist[code]; | ||
sendBits(dist, extra); // send the extra distance bits | ||
} | ||
} // literal or match pair ? | ||
flag >>= 1; | ||
} while(lx < lastLit); | ||
sendCode(0x100, ltree); // end block | ||
} | ||
function sendBits(value, length) { | ||
if(biValid > 0x10 - length) { | ||
biBuf |= (value << biValid); | ||
writeShort(biBuf); | ||
biBuf = (value >> (0x10 - biValid)); | ||
biValid += length - 0x10; | ||
} else { | ||
biBuf |= value << biValid; | ||
biValid += length; | ||
} | ||
} | ||
function reverse(code, len) { | ||
var res = 0; | ||
do { | ||
res |= code & 1; | ||
code >>= 1; | ||
res <<= 1; | ||
} while(--len > 0); | ||
return res >> 1; | ||
} | ||
function deflate(buffData, level) { | ||
deflateData = buffData; | ||
deflatePos = 0; | ||
deflateStart(level); | ||
var buff = new Array(1), | ||
pages = [], | ||
totalSize = 0, | ||
i; | ||
while((i = internalDeflate(buff, 0, buff.length)) > 0) { | ||
var buf = new Buffer(buff); | ||
pages.push(buf); | ||
totalSize += buff.length; | ||
} | ||
var result = new Buffer(totalSize), | ||
index = 0; | ||
for (i = 0; i < pages.length; i++) { | ||
pages[i].copy(result, index); | ||
index = index + pages[i].length | ||
} | ||
cleanup(); | ||
return result; | ||
} | ||
return { | ||
deflate : function() { | ||
return deflate(inbuf, 9); | ||
} | ||
} | ||
} | ||
module.exports = function(/*Buffer*/inbuf) { | ||
var zlib = require("zlib"); | ||
return { | ||
deflate : function(/*Buffer*/outputBuffer) { | ||
// pff...does nothing (YET), just moves stuff around | ||
inbuf.copy(outputBuffer, 0, index, index + ZipConstants.CENHDR); | ||
deflate : function() { | ||
return new JSDeflater(inbuf).deflate(); | ||
}, | ||
deflateAsync : function(/*Function*/callback) { | ||
var tmp = zlib.createDeflateRaw(); | ||
tmp.on('data', function(data) { | ||
callback(data); | ||
}); | ||
tmp.end(inbuf) | ||
} | ||
} | ||
}; |
@@ -1,146 +0,365 @@ | ||
module.exports = function(/*Buffer*/inbuf) { | ||
var Buffer = require("buffer").Buffer; | ||
var Errors = require("../util").Errors; | ||
function JSInflater(/*Buffer*/input) { | ||
var MAXBITS = 15, MAXLCODES = 286, MAXDCODES = 30, MAXCODES = 316, FIXLCODES = 288, | ||
LENS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258], | ||
LEXT = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], | ||
var WSIZE = 0x8000, | ||
slide = new Buffer(0x10000), | ||
windowPos = 0, | ||
fixedTableList = null, | ||
fixedTableDist, | ||
fixedLookup, | ||
bitBuf = 0, | ||
bitLen = 0, | ||
method = -1, | ||
eof = false, | ||
copyLen = 0, | ||
copyDist = 0, | ||
tblList, tblDist, bitList, bitdist, | ||
inputPosition = 0, | ||
MASK_BITS = [0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff], | ||
LENS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0], | ||
LEXT = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99], | ||
DISTS = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577], | ||
DEXT = [ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13], | ||
inbufpos = 0, | ||
incnt = 0, // bytes read so far | ||
bitbuf = 0, // bit buffer | ||
bitcnt = 0, // number of bits in bit buffer | ||
lencode = undefined, | ||
distcode = undefined; | ||
DEXT = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13], | ||
BITORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; | ||
function bits(need) { | ||
var val = bitbuf; | ||
while(bitcnt < need) { | ||
if (incnt == inbuf.length) throw Errors.AVAIL_DATA; | ||
val |= inbuf[incnt++] << bitcnt; | ||
bitcnt += 8; | ||
function HuffTable(clen, cnum, cval, blist, elist, lookupm) { | ||
this.status = 0; | ||
this.root = null; | ||
this.maxbit = 0; | ||
var el, f, tail, | ||
offsets = [], | ||
countTbl = [], | ||
sTbl = [], | ||
values = [], | ||
tentry = {extra: 0, bitcnt: 0, lbase: 0, next: null}; | ||
tail = this.root = null; | ||
for(var i = 0; i < 0x11; i++) { countTbl[i] = 0; sTbl[i] = 0; offsets[i] = 0; } | ||
for(i = 0; i < 0x120; i++) values[i] = 0; | ||
el = cnum > 256 ? clen[256] : 16; | ||
var pidx = -1; | ||
while (++pidx < cnum) countTbl[clen[pidx]]++; | ||
if(countTbl[0] == cnum) return; | ||
for(var j = 1; j <= 16; j++) if(countTbl[j] != 0) break; | ||
var bitLen = j; | ||
for(i = 16; i != 0; i--) if(countTbl[i] != 0) break; | ||
var maxLen = i; | ||
lookupm < j && (lookupm = j); | ||
var dCodes = 1 << j; | ||
for(; j < i; j++, dCodes <<= 1) | ||
if((dCodes -= countTbl[j]) < 0) { | ||
this.status = 2; | ||
this.maxbit = lookupm; | ||
return; | ||
} | ||
if((dCodes -= countTbl[i]) < 0) { | ||
this.status = 2; | ||
this.maxbit = lookupm; | ||
return; | ||
} | ||
bitbuf = val >> need; | ||
bitcnt -= need; | ||
return val & ((1 << need) - 1); | ||
countTbl[i] += dCodes; | ||
offsets[1] = j = 0; | ||
pidx = 1; | ||
var xp = 2; | ||
while(--i > 0) offsets[xp++] = (j += countTbl[pidx++]); | ||
pidx = 0; | ||
i = 0; | ||
do { | ||
(j = clen[pidx++]) && (values[offsets[j]++] = i); | ||
} while(++i < cnum); | ||
cnum = offsets[maxLen]; | ||
offsets[0] = i = 0; | ||
pidx = 0; | ||
var level = -1, | ||
w = sTbl[0] = 0, | ||
cnode = null, | ||
tblCnt = 0, | ||
tblStack = []; | ||
for(; bitLen <= maxLen; bitLen++) { | ||
var kccnt = countTbl[bitLen]; | ||
while(kccnt-- > 0) { | ||
while(bitLen > w + sTbl[1 + level]) { | ||
w += sTbl[1 + level]; | ||
level++; | ||
tblCnt = (tblCnt = maxLen - w) > lookupm ? lookupm : tblCnt; | ||
if((f = 1 << (j = bitLen - w)) > kccnt + 1) { | ||
f -= kccnt + 1; | ||
xp = bitLen; | ||
while(++j < tblCnt) { | ||
if((f <<= 1) <= countTbl[++xp]) break; | ||
f -= countTbl[xp]; | ||
} | ||
} | ||
if(w + j > el && w < el) j = el - w; | ||
tblCnt = 1 << j; | ||
sTbl[1 + level] = j; | ||
cnode = []; | ||
while (cnode.length < tblCnt) cnode.push({extra: 0, bitcnt: 0, lbase: 0, next: null}); | ||
if (tail == null) { | ||
tail = this.root = {next:null, list:null}; | ||
} else { | ||
tail = tail.next = {next:null, list:null} | ||
} | ||
tail.next = null; | ||
tail.list = cnode; | ||
tblStack[level] = cnode; | ||
if(level > 0) { | ||
offsets[level] = i; | ||
tentry.bitcnt = sTbl[level]; | ||
tentry.extra = 16 + j; | ||
tentry.next = cnode; | ||
j = (i & ((1 << w) - 1)) >> (w - sTbl[level]); | ||
tblStack[level-1][j].extra = tentry.extra; | ||
tblStack[level-1][j].bitcnt = tentry.bitcnt; | ||
tblStack[level-1][j].lbase = tentry.lbase; | ||
tblStack[level-1][j].next = tentry.next; | ||
} | ||
} | ||
tentry.bitcnt = bitLen - w; | ||
if(pidx >= cnum) | ||
tentry.extra = 99; | ||
else if(values[pidx] < cval) { | ||
tentry.extra = (values[pidx] < 256 ? 16 : 15); | ||
tentry.lbase = values[pidx++]; | ||
} else { | ||
tentry.extra = elist[values[pidx] - cval]; | ||
tentry.lbase = blist[values[pidx++] - cval]; | ||
} | ||
f = 1 << (bitLen - w); | ||
for(j = i >> w; j < tblCnt; j += f) { | ||
cnode[j].extra = tentry.extra; | ||
cnode[j].bitcnt = tentry.bitcnt; | ||
cnode[j].lbase = tentry.lbase; | ||
cnode[j].next = tentry.next; | ||
} | ||
for(j = 1 << (bitLen - 1); (i & j) != 0; j >>= 1) | ||
i ^= j; | ||
i ^= j; | ||
while((i & ((1 << w) - 1)) != offsets[level]) { | ||
w -= sTbl[level]; | ||
level--; | ||
} | ||
} | ||
} | ||
this.maxbit = sTbl[1]; | ||
this.status = ((dCodes != 0 && maxLen != 1) ? 1 : 0); | ||
} | ||
function construct(h, length, n) { | ||
var offs = new Array(); | ||
for (var len = 0; len <= MAXBITS; len++) h.count[len] = 0; | ||
for (var symbol = 0; symbol < n; symbol++) h.count[length[symbol]]++; | ||
if(h.count[0] == n) return 0; | ||
var left = 1; | ||
for(len = 1; len <= MAXBITS; len++) { | ||
left <<= 1; | ||
left -= h.count[len]; | ||
if(left < 0) return left; | ||
function addBits(n) { | ||
while(bitLen < n) { | ||
bitBuf |= input[inputPosition++] << bitLen; | ||
bitLen += 8; | ||
} | ||
offs[1] = 0; | ||
for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h.count[len]; | ||
for(symbol = 0; symbol < n; symbol++) | ||
if(length[symbol] !== 0) h.symbol[offs[length[symbol]]++] = symbol; | ||
return left; | ||
return bitBuf; | ||
} | ||
function decode(h) { | ||
var code = 0, first = 0, index = 0; | ||
for(var len = 1; len <= MAXBITS; len++) { | ||
code |= bits(1); | ||
var count = h.count[len]; | ||
if(code < first + count) return h.symbol[index + (code - first)]; | ||
index += count; | ||
first += count; | ||
first <<= 1; | ||
code <<= 1; | ||
function cutBits(n) { | ||
bitLen -= n; | ||
return bitBuf >>= n; | ||
} | ||
function maskBits(n) { | ||
while(bitLen < n) { | ||
bitBuf |= input[inputPosition++] << bitLen; | ||
bitLen += 8; | ||
} | ||
return -9; // ran out of codes | ||
var res = bitBuf & MASK_BITS[n]; | ||
bitBuf >>= n; | ||
bitLen -= n; | ||
return res; | ||
} | ||
function codes(buf) { | ||
var i = 0; | ||
do { | ||
var symbol = decode(lencode); | ||
if(symbol < 0) return symbol; | ||
if(symbol < 256) { | ||
buf[i++] = symbol; | ||
function codes(buff, off, size) { | ||
var e, t; | ||
if(size == 0) return 0; | ||
var n = 0; | ||
for(;;) { | ||
t = tblList.list[addBits(bitList) & MASK_BITS[bitList]]; | ||
e = t.extra; | ||
while(e > 16) { | ||
if(e == 99) return -1; | ||
cutBits(t.bitcnt); | ||
e -= 16; | ||
t = t.next[addBits(e) & MASK_BITS[e]]; | ||
e = t.extra; | ||
} | ||
else if(symbol > 256) { | ||
symbol -= 257; | ||
if(symbol >= 29) | ||
throw Errors.INVALID_DISTANCE; | ||
var len = LENS[symbol] + bits(LEXT[symbol]); | ||
symbol = decode(distcode); | ||
if(symbol < 0) return symbol; | ||
var dist = DISTS[symbol] + bits(DEXT[symbol]); | ||
/*if(dist > i) | ||
throw "distance is too far back in fixed or dynamic block";*/ | ||
while(len--) | ||
buf[i++] = buf[i - dist - 1]; | ||
cutBits(t.bitcnt); | ||
if(e == 16) { | ||
windowPos &= WSIZE - 1; | ||
buff[off + n++] = slide[windowPos++] = t.lbase; | ||
if(n == size) return size; | ||
continue; | ||
} | ||
} while (symbol != 256); | ||
return 0; | ||
if(e == 15) break; | ||
copyLen = t.lbase + maskBits(e); | ||
t = tblDist.list[addBits(bitdist) & MASK_BITS[bitdist]]; | ||
e = t.extra; | ||
while(e > 16) { | ||
if(e == 99) return -1; | ||
cutBits(t.bitcnt); | ||
e -= 16; | ||
t = t.next[addBits(e) & MASK_BITS[e]]; | ||
e = t.extra | ||
} | ||
cutBits(t.bitcnt); | ||
copyDist = windowPos - t.lbase - maskBits(e); | ||
while(copyLen > 0 && n < size) { | ||
copyLen--; | ||
copyDist &= WSIZE - 1; | ||
windowPos &= WSIZE - 1; | ||
buff[off + n++] = slide[windowPos++] = slide[copyDist++]; | ||
} | ||
if(n == size) return size; | ||
} | ||
method = -1; // done | ||
return n; | ||
} | ||
function stored(buf) { | ||
bitbuf = 0; | ||
bitcnt = 0; | ||
if(incnt + 4 > inbuf.length) throw Errors.AVAIL_DATA; | ||
var len = inbuf[incnt++]; | ||
len |= inbuf[incnt++] << 8; | ||
if(inbuf[incnt++] != (~len & 0xff) || inbuf[incnt++] != ((~len >> 8) & 0xff)) | ||
throw Errors.INVALID_STORE_BLOCK; | ||
if(incnt + len > inbuf.length) throw Errors.AVAIL_DATA; | ||
var i = 0; | ||
while(len--) buf[i++] += inbuf[incnt++]; | ||
function stored(buff, off, size) { | ||
cutBits(bitLen & 7); | ||
var n = maskBits(0x10); | ||
if(n != ((~maskBits(0x10)) & 0xffff)) return -1; | ||
copyLen = n; | ||
n = 0; | ||
while(copyLen > 0 && n < size) { | ||
copyLen--; | ||
windowPos &= WSIZE - 1; | ||
buff[off + n++] = slide[windowPos++] = maskBits(8); | ||
} | ||
if(copyLen == 0) method = -1; | ||
return n; | ||
} | ||
function constructFixedTables() { | ||
var lengths = new Array(); | ||
for(var symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8; | ||
for(; symbol < 256; symbol++) lengths[symbol] = 9; | ||
for(; symbol < 280; symbol++) lengths[symbol] = 7; | ||
for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8; | ||
construct(lencode, lengths, FIXLCODES); | ||
for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5; | ||
construct(distcode, lengths, MAXDCODES); | ||
function fixed(buff, off, size) { | ||
var fixed_bd = 0; | ||
if(fixedTableList == null) { | ||
var lengths = []; | ||
for(var symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8; | ||
for(; symbol < 256; symbol++) lengths[symbol] = 9; | ||
for(; symbol < 280; symbol++) lengths[symbol] = 7; | ||
for(; symbol < 288; symbol++) lengths[symbol] = 8; | ||
fixedLookup = 7; | ||
var htbl = new HuffTable(lengths, 288, 257, LENS, LEXT, fixedLookup); | ||
if(htbl.status != 0) return -1; | ||
fixedTableList = htbl.root; | ||
fixedLookup = htbl.maxbit; | ||
for(symbol = 0; symbol < 30; symbol++) lengths[symbol] = 5; | ||
fixed_bd = 5; | ||
htbl = new HuffTable(lengths, 30, 0, DISTS, DEXT, fixed_bd); | ||
if(htbl.status > 1) { | ||
fixedTableList = null; | ||
return -1; | ||
} | ||
fixedTableDist = htbl.root; | ||
fixed_bd = htbl.maxbit; | ||
} | ||
tblList = fixedTableList; | ||
tblDist = fixedTableDist; | ||
bitList = fixedLookup; | ||
bitdist = fixed_bd; | ||
return codes(buff, off, size); | ||
} | ||
function constructDynamicTables() { | ||
var lengths = new Array(), | ||
order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], | ||
nlen = bits(5) + 257, | ||
ndist = bits(5) + 1, | ||
ncode = bits(4) + 4; | ||
if(nlen > MAXLCODES || ndist > MAXDCODES) | ||
throw Errors.TO_MANY_CODES; | ||
for(var index = 0; index < ncode; index++) lengths[order[index]] = bits(3); | ||
for(; index < 19; index++) lengths[order[index]] = 0; | ||
var err = construct(lencode, lengths, 19); | ||
if(err !== 0) throw Errors.INCOMPLETE_CODES; | ||
index = 0; | ||
while(index < nlen + ndist) { | ||
var symbol = decode(lencode), len; | ||
if(symbol < 16) lengths[index++] = symbol; | ||
else { | ||
len = 0; | ||
if(symbol == 16) { | ||
if(index === 0) throw Errors.INVALID_REPEAT_FIRST; | ||
len = lengths[index - 1]; | ||
symbol = 3 + bits(2); | ||
} | ||
else if(symbol == 17) symbol = 3 + bits(3); | ||
else symbol = 11 + bits(7); | ||
if(index + symbol > nlen + ndist) | ||
throw Errors.INVALID_REPEAT_LEN; | ||
while(symbol--) lengths[index++] = len; | ||
function dynamic(buff, off, size) { | ||
var ll = new Array(0x023C); | ||
for (var m = 0; m < 0x023C; m++) ll[m] = 0; | ||
var llencnt = 257 + maskBits(5), | ||
dcodescnt = 1 + maskBits(5), | ||
bitlencnt = 4 + maskBits(4); | ||
if(llencnt > 286 || dcodescnt > 30) return -1; | ||
for(var j = 0; j < bitlencnt; j++) ll[BITORDER[j]] = maskBits(3); | ||
for(; j < 19; j++) ll[BITORDER[j]] = 0; | ||
// build decoding table for trees--single level, 7 bit lookup | ||
bitList = 7; | ||
var hufTable = new HuffTable(ll, 19, 19, null, null, bitList); | ||
if(hufTable.status != 0) | ||
return -1; // incomplete code set | ||
tblList = hufTable.root; | ||
bitList = hufTable.maxbit; | ||
var lencnt = llencnt + dcodescnt, | ||
i = 0, | ||
lastLen = 0; | ||
while(i < lencnt) { | ||
var hufLcode = tblList.list[addBits(bitList) & MASK_BITS[bitList]]; | ||
j = hufLcode.bitcnt; | ||
cutBits(j); | ||
j = hufLcode.lbase; | ||
if(j < 16) | ||
ll[i++] = lastLen = j; | ||
else if(j == 16) { | ||
j = 3 + maskBits(2); | ||
if(i + j > lencnt) return -1; | ||
while(j-- > 0) ll[i++] = lastLen; | ||
} else if(j == 17) { | ||
j = 3 + maskBits(3); | ||
if(i + j > lencnt) return -1; | ||
while(j-- > 0) ll[i++] = 0; | ||
lastLen = 0; | ||
} else { | ||
j = 11 + maskBits(7); | ||
if(i + j > lencnt) return -1; | ||
while(j-- > 0) ll[i++] = 0; | ||
lastLen = 0; | ||
} | ||
} | ||
bitList = 9; | ||
hufTable = new HuffTable(ll, llencnt, 257, LENS, LEXT, bitList); | ||
bitList == 0 && (hufTable.status = 1); | ||
err = construct(lencode, lengths, nlen); | ||
if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) throw Errors.INVALID_CODES_LEN; | ||
err = construct(distcode, lengths.slice(nlen), ndist); | ||
if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) throw Errors.INVALID_DYN_DISTANCE; | ||
return err; | ||
if (hufTable.status != 0) return -1; | ||
tblList = hufTable.root; | ||
bitList = hufTable.maxbit; | ||
for(i = 0; i < dcodescnt; i++) ll[i] = ll[i + llencnt]; | ||
bitdist = 6; | ||
hufTable = new HuffTable(ll, dcodescnt, 0, DISTS, DEXT, bitdist); | ||
tblDist = hufTable.root; | ||
bitdist = hufTable.maxbit; | ||
if((bitdist == 0 && llencnt > 257) || hufTable.status != 0) return -1; | ||
return codes(buff, off, size); | ||
} | ||
@@ -150,22 +369,79 @@ | ||
inflate : function(/*Buffer*/outputBuffer) { | ||
incnt = bitbuf = bitcnt = 0; | ||
var err = 0; | ||
do { | ||
var last = bits(1); | ||
var type = bits(2); | ||
if(type === 0) stored(outputBuffer); // uncompressed block | ||
else if(type == 3) throw Errors.INVALID_BLOCK_TYPE; | ||
else { // compressed block | ||
lencode = {count:[], symbol:[]}; | ||
distcode = {count:[], symbol:[]}; | ||
if(type == 1) constructFixedTables(); | ||
else if(type == 2) err = constructDynamicTables(); | ||
if(err !== 0) return err; | ||
err = codes(outputBuffer); | ||
tblList = null; | ||
var size = outputBuffer.length, | ||
offset = 0, i; | ||
while(offset < size) { | ||
if(eof && method == -1) return; | ||
if(copyLen > 0) { | ||
if(method != 0) { | ||
while(copyLen > 0 && offset < size) { | ||
copyLen--; | ||
copyDist &= WSIZE - 1; | ||
windowPos &= WSIZE - 1; | ||
outputBuffer[offset++] = slide[windowPos++] = slide[copyDist++]; | ||
} | ||
} else { | ||
while(copyLen > 0 && offset < size) { | ||
copyLen--; | ||
windowPos &= WSIZE - 1; | ||
outputBuffer[offset++] = slide[windowPos++] = maskBits(8); | ||
} | ||
copyLen == 0 && (method = -1); // done | ||
} | ||
if (offset == size) return; | ||
} | ||
if(err !== 0) break; | ||
} while (!last); | ||
return err; | ||
if(method == -1) { | ||
if(eof) break; | ||
eof = maskBits(1) != 0; | ||
method = maskBits(2); | ||
tblList = null; | ||
copyLen = 0; | ||
} | ||
switch(method) { | ||
case 0: i = stored(outputBuffer, offset, size - offset); break; | ||
case 1: i = tblList != null ? codes(outputBuffer, offset, size - offset) : fixed(outputBuffer, offset, size - offset); break; | ||
case 2: i = tblList != null ? codes(outputBuffer, offset, size - offset) : dynamic(outputBuffer, offset, size - offset); break; | ||
default: i = -1; break; | ||
} | ||
if(i == -1) return; | ||
offset += i; | ||
} | ||
} | ||
}; | ||
} | ||
module.exports = function(/*Buffer*/inbuf) { | ||
var zlib = require("zlib"); | ||
return { | ||
inflateAsync : function(/*Function*/callback) { | ||
var tmp = zlib.createInflateRaw(), | ||
parts = [], total = 0; | ||
tmp.on('data', function(data) { | ||
parts.push(data); | ||
total += data.length; | ||
}); | ||
tmp.on('end', function() { | ||
var buf = new Buffer(total), written = 0; | ||
buf.fill(0); | ||
for (var i = 0; i < parts.length; i++) { | ||
var part = parts[i]; | ||
part.copy(buf, written); | ||
written += part.length; | ||
} | ||
callback && callback(buf); | ||
}); | ||
tmp.end(inbuf) | ||
}, | ||
inflate : function(/*Buffer*/outputBuffer) { | ||
var x = new JSInflater(inbuf); | ||
x.inflate(outputBuffer); | ||
delete(x); | ||
} | ||
} | ||
}; |
{ | ||
"name": "adm-zip", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "A Javascript implementation of zip for nodejs. Allows user to create or extract zip files both in memory or to/from disk", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -23,3 +23,3 @@ # ADM-ZIP for NodeJS | ||
## Basic decompression | ||
## Basic usage | ||
```javascript | ||
@@ -26,0 +26,0 @@ |
@@ -10,20 +10,40 @@ var fs = require("fs"), | ||
function mkdirSync(path) { | ||
var curesolvedPath = path.split('\\')[0]; | ||
function mkdirSync(/*String*/path) { | ||
var resolvedPath = path.split('\\')[0]; | ||
path.split('\\').forEach(function(name) { | ||
if (!name || name.substr(-1,1) == ":") return; | ||
curesolvedPath += '\\' + name; | ||
resolvedPath += '\\' + name; | ||
var stat; | ||
try { | ||
stat = fs.statSync(curesolvedPath); | ||
stat = fs.statSync(resolvedPath); | ||
} catch (e) { | ||
fs.mkdirSync(curesolvedPath); | ||
fs.mkdirSync(resolvedPath); | ||
} | ||
if (stat && stat.isFile()) | ||
throw Errors.FILE_IN_THE_WAY.replace("%s", curesolvedPath); | ||
throw Errors.FILE_IN_THE_WAY.replace("%s", resolvedPath); | ||
}); | ||
} | ||
function findSync(/*String*/root, /*RegExp*/pattern, /*Boolean*/recoursive) { | ||
if (typeof pattern === 'boolean') { | ||
recoursive = pattern; | ||
pattern = undefined; | ||
} | ||
var files = []; | ||
fs.readdirSync(root).forEach(function(file) { | ||
var path = pth.join(root, file); | ||
if (fs.statSync(path).isDirectory() && recoursive) | ||
files = files.concat(findSync(path, pattern, recoursive)); | ||
if (!pattern || pattern.test(path)) { | ||
files.push(path.replace(/\\/g, "/") + (fs.statSync(path).isDirectory() ? "/" : "")); | ||
} | ||
}); | ||
return files; | ||
} | ||
return { | ||
makeDir : function(path) { | ||
makeDir : function(/*String*/path) { | ||
mkdirSync(path); | ||
@@ -35,3 +55,2 @@ }, | ||
if (!crcTable.length) { | ||
var tmp = []; | ||
for (var n = 0; n < 256; n++) { | ||
@@ -79,3 +98,3 @@ var c = n; | ||
if (!pth.existsSync(folder)) { | ||
exports.Utils.makeDir(folder); | ||
mkdirSync(folder); | ||
} | ||
@@ -97,6 +116,10 @@ | ||
}, | ||
findFiles : function(/*String*/path) { | ||
return findSync(path, true); | ||
}, | ||
Constants : Constants, | ||
Errors : Errors | ||
} | ||
})(); |
126
zipEntry.js
@@ -15,7 +15,15 @@ var Utils = require("./util"), | ||
_data = null, | ||
_comment = ""; | ||
_comment = "", | ||
_needDeflate = false; | ||
function decompress() { | ||
if (_data == null) { | ||
function decompress(/*Boolean*/async, /*Function*/callback) { | ||
// if (_data == null) { | ||
if (true) { | ||
if (_compressedData == null) { | ||
if (_isDirectory) { | ||
if (async && callback) { | ||
callback(new Buffer()); | ||
} | ||
return; | ||
} | ||
throw 'Noting to decompress'; | ||
@@ -32,6 +40,20 @@ } | ||
case Utils.Constants.DEFLATED: | ||
_data = new Buffer(_entryHeader.size); | ||
new Methods.Inflater(_compressedData.slice(_dataHeader.fileHeaderSize)).inflate(_data); | ||
if (Utils.crc32(_data) != _dataHeader.crc) { | ||
throw Utils.Errors.BAD_CRC | ||
var inflater = new Methods.Inflater(_compressedData.slice(_dataHeader.fileHeaderSize)); | ||
if (!async) { | ||
_data = new Buffer(_entryHeader.size); | ||
_data.fill(0); | ||
inflater.inflate(_data); | ||
if (Utils.crc32(_data) != _dataHeader.crc) { | ||
throw Utils.Errors.BAD_CRC + " " + _entryName | ||
} | ||
} else { | ||
inflater.inflateAsync(function(data) { | ||
_data = new Buffer(_entryHeader.size); | ||
_data.fill(0); | ||
data.copy(_data, 0); | ||
if (Utils.crc32(_data) != _dataHeader.crc) { | ||
throw Utils.Errors.BAD_CRC | ||
} | ||
callback(_data); | ||
}) | ||
} | ||
@@ -42,11 +64,15 @@ break; | ||
} | ||
} else { | ||
if (async && callback) { | ||
callback(_data); | ||
} | ||
} | ||
} | ||
function compress() { | ||
function compress(/*Boolean*/async, /*Function*/callback) { | ||
if ( _needDeflate) { | ||
_compressedData = null; | ||
} | ||
if (_compressedData == null) { | ||
if (_data == null && !_isDirectory) { | ||
throw Utils.Errors.NO_DATA | ||
} | ||
if (_isDirectory) { | ||
if (_isDirectory || !_data) { | ||
_data = new Buffer(0); | ||
@@ -57,11 +83,45 @@ } | ||
_dataHeader.flags = 0; | ||
_dataHeader.method = Utils.Constants.STORED; | ||
_dataHeader.time = _entryHeader.time; | ||
_dataHeader.compressedSize = _data.length; | ||
_dataHeader.fileNameLength = _entryName.length; | ||
_dataHeader.extraLength = _extra && _extra.length || 0; | ||
_dataHeader.method = 8; | ||
switch (_dataHeader.method) { | ||
case Utils.Constants.STORED: | ||
_dataHeader.method = Utils.Constants.STORED; | ||
_compressedData = new Buffer(Utils.Constants.LOCHDR + _entryName.length + _data.length); | ||
_dataHeader.toBinary().copy(_compressedData); | ||
_compressedData.write(_entryName, Utils.Constants.LOCHDR); | ||
_data.copy(_compressedData, Utils.Constants.LOCHDR + _entryName.length); | ||
break; | ||
default: | ||
case Utils.Constants.DEFLATED: | ||
_dataHeader.method = Utils.Constants.DEFLATED; | ||
_entryHeader.method = Utils.Constants.DEFLATED; | ||
_compressedData = new Buffer(Utils.Constants.LOCHDR + _entryName.length + _data.length); | ||
_dataHeader.toBinary().copy(_compressedData); | ||
_compressedData.write(_entryName, Utils.Constants.LOCHDR); | ||
_data.copy(_compressedData, Utils.Constants.LOCHDR + _entryName.length); | ||
var deflater = new Methods.Deflater(_data); | ||
if (!async) { | ||
var deflated = deflater.deflate(); | ||
_compressedData = new Buffer(deflated.length + Utils.Constants.LOCHDR + _entryName.length); | ||
_dataHeader.toBinary().copy(_compressedData); | ||
_compressedData.write(_entryName, Utils.Constants.LOCHDR); | ||
deflated.copy(_compressedData, Utils.Constants.LOCHDR + _entryName.length); | ||
deflated = null; | ||
} else { | ||
deflater.deflateAsync(function(data) { | ||
_compressedData = new Buffer(data.length + Utils.Constants.LOCHDR + _entryName.length); | ||
_dataHeader.toBinary().copy(_compressedData); | ||
_compressedData.write(_entryName, Utils.Constants.LOCHDR); | ||
data.copy(_compressedData, Utils.Constants.LOCHDR + _entryName.length); | ||
callback(_compressedData); | ||
}) | ||
} | ||
deflater = null; | ||
break; | ||
} | ||
_needDeflate = false; | ||
} else { | ||
if (async && callback) { | ||
callback(_compressedData); | ||
} | ||
} | ||
@@ -73,3 +133,3 @@ } | ||
set entryName (val) { | ||
_compressedData = null; | ||
_compressedData && (_needDeflate = true); | ||
_entryName = val; | ||
@@ -83,8 +143,6 @@ _isDirectory = val.charAt(_entryName.length - 1) == "/"; | ||
set extra (val) { | ||
_compressedData = null; | ||
_extra = val; | ||
_extra = val; | ||
_entryHeader.extraLength = val.length; | ||
_dataHeader.extraLength = val.length; | ||
}, | ||
get comment () { return _comment; }, | ||
@@ -95,7 +153,7 @@ set comment (val) { | ||
}, | ||
get name () { return _entryName.split("/").pop(); }, | ||
get isDirectory () { return _isDirectory }, | ||
set compressedData (value) { | ||
setCompressedData : function(value) { | ||
_compressedData = value; | ||
@@ -106,11 +164,15 @@ _dataHeader.loadFromBinary(_compressedData.slice(0, Utils.Constants.LOCHDR)); | ||
get compressedData () { | ||
compress(); | ||
getCompressedData : function() { | ||
compress(false, null); | ||
return _compressedData | ||
}, | ||
getCompressedDataAsync : function(/*Function*/callback) { | ||
compress(true, callback) | ||
}, | ||
set data (value) { | ||
setData : function(value) { | ||
if (typeof value == "string") { | ||
value = new Buffer(value); | ||
} | ||
_needDeflate = true; | ||
_compressedData = null; | ||
@@ -133,7 +195,11 @@ _dataHeader.time = +new Date(); | ||
get data() { | ||
decompress(); | ||
getData : function() { | ||
decompress(false, null); | ||
return _data | ||
}, | ||
getDataAsync : function(/*Function*/callback) { | ||
decompress(true, callback) | ||
}, | ||
set header(/*Buffer*/data) { | ||
@@ -140,0 +206,0 @@ _entryHeader.loadFromBinary(data); |
@@ -37,3 +37,3 @@ var ZipEntry = require("./zipEntry"), | ||
// read data | ||
entry.compressedData = buf.slice(entry.header.offset, entry.header.offset + Utils.Constants.LOCHDR + entry.header.compressedSize + entry.entryName.length); | ||
entry.setCompressedData(buf.slice(entry.header.offset, entry.header.offset + Utils.Constants.LOCHDR + entry.header.compressedSize + entry.entryName.length)); | ||
} | ||
@@ -175,3 +175,3 @@ | ||
entry.header.offset = dindex; | ||
var compressedData = entry.compressedData; | ||
var compressedData = entry.getCompressedData(); | ||
dindex += compressedData.length; | ||
@@ -208,6 +208,2 @@ data.push(compressedData); | ||
delete(data); | ||
delete(header); | ||
delete(mainHeader); | ||
return outBuffer | ||
@@ -214,0 +210,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
132748
25
2554
0