adm-zip = function (input) { var _zip = undefined, _filename = ""; if (input && typeof input === "string") { // load zip file if (fs.existsSync(input)) { _filename = input; _zip = new ZipFile(input, Utils.Constants.FILE); } else { throw Utils.Errors.INVALID_FILENAME; } } else if(input && Buffer.isBuffer(input)) { // load buffer _zip = new ZipFile(input, Utils.Constants.BUFFER); } else { // create new zip file _zip = new ZipFile(null, Utils.Constants.NONE); } function getEntry(/*Object*/entry) { if (entry && _zip) { var item; // If entry was given as a file name if (typeof entry === "string") item = _zip.getEntry(entry); // if entry was given as a ZipEntry object if (typeof entry === "object" && entry.entryName != undefined && entry.header != undefined) item = _zip.getEntry(entry.entryName); if (item) { return item; } } return null; } return { /** * Extracts the given entry from the archive and returns the content as a Buffer object * @param entry ZipEntry object or String with the full path of the entry * * @return Buffer or Null in case of error */ readFile : function(/*Object*/entry) { var item = getEntry(entry); 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.getDataAsync(callback); } else { callback(null,"getEntry failed for:" + entry) } }, /** * 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 Optional. If no encoding is specified utf8 is used * * @return String */ readAsText : function(/*Object*/entry, /*String - Optional*/encoding) { var item = getEntry(entry); if (item) { var data = item.getData(); if (data && data.length) { return data.toString(encoding || "utf8"); } } return ""; }, /** * 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.getDataAsync(function(data) { if (data && data.length) { callback(data.toString(encoding || "utf8")); } else { callback(""); } }) } else { callback(""); } }, /** * 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) { // @TODO: test deleteFile var item = getEntry(entry); if (item) { _zip.deleteEntry(item.entryName); } }, /** ...
n/a
EntryHeader = function () { var _verMade = 0x0A, _version = 0x0A, _flags = 0, _method = 0, _time = 0, _crc = 0, _compressedSize = 0, _size = 0, _fnameLen = 0, _extraLen = 0, _comLen = 0, _diskStart = 0, _inattr = 0, _attr = 0, _offset = 0; var _dataHeader = {}; function setTime(val) { var val = new Date(val); _time = (val.getFullYear() - 1980 & 0x7f) << 25 // b09-16 years from 1980 | (val.getMonth() + 1) << 21 // b05-08 month | val.getDay() << 16 // b00-04 hour // 2 bytes time | val.getHours() << 11 // b11-15 hour | val.getMinutes() << 5 // b05-10 minute | val.getSeconds() >> 1; // b00-04 seconds divided by 2 } setTime(+new Date()); return { get made () { return _verMade; }, set made (val) { _verMade = val; }, get version () { return _version; }, set version (val) { _version = val }, get flags () { return _flags }, set flags (val) { _flags = val; }, get method () { return _method; }, set method (val) { _method = val; }, get time () { return new Date( ((_time >> 25) & 0x7f) + 1980, ((_time >> 21) & 0x0f) - 1, (_time >> 16) & 0x1f, (_time >> 11) & 0x1f, (_time >> 5) & 0x3f, (_time & 0x1f) << 1 ); }, set time (val) { setTime(val); }, get crc () { return _crc; }, set crc (val) { _crc = val; }, get compressedSize () { return _compressedSize; }, set compressedSize (val) { _compressedSize = val; }, get size () { return _size; }, set size (val) { _size = val; }, get fileNameLength () { return _fnameLen; }, set fileNameLength (val) { _fnameLen = val; }, get extraLength () { return _extraLen }, set extraLength (val) { _extraLen = val; }, get commentLength () { return _comLen }, set commentLength (val) { _comLen = val }, get diskNumStart () { return _diskStart }, set diskNumStart (val) { _diskStart = val }, get inAttr () { return _inattr }, set inAttr (val) { _inattr = val }, get attr () { return _attr }, set attr (val) { _attr = val }, get offset () { return _offset }, set offset (val) { _offset = val }, get encripted () { return (_flags & 1) == 1 }, get entryHeaderSize () { return Constants.CENHDR + _fnameLen + _extraLen + _comLen; }, get realDataOffset () { return _offset + Constants.LOCHDR + _dataHeader.fnameLen + _dataHeader.extraLen; }, get dataHeader () { return _dataHeader; }, loadDataHeaderFromBinary : function(/*Buffer*/input) { var data = input.slice(_offset, _offset + Constants.LOCHDR); // 30 bytes and should start with "PK\003\004" if (data.readUInt32LE(0) != Constants.LOCSIG) { throw Utils.Errors.INVALID_LOC; } _dataHeader = { // version needed to extract version : data.readUInt16LE(Constants.LOCVER), // general purpose bit flag flags : data.readUInt16LE(Constants.LOCFLG), // compression method method : data.readUInt16LE(Constants.LOCHOW), // modification time (2 bytes time, 2 bytes date) time : data.readUInt32LE(Constants.LOCTIM), // uncompressed file crc-32 value crc : data.readUInt32LE(Constants.LOCCRC), // compressed size compressedSize : data.readUInt32LE(Constants.LOCSIZ), // uncompressed size ...
...
var Utils = require("./util"),
Headers = require("./headers"),
Constants = Utils.Constants,
Methods = require("./methods");
module.exports = function (/*Buffer*/input) {
var _entryHeader = new Headers.EntryHeader(),
_entryName = new Buffer(0),
_comment = new Buffer(0),
_isDirectory = false,
uncompressedData = null,
_extra = new Buffer(0);
function getCompressedDataFromZip() {
...
MainHeader = function () { var _volumeEntries = 0, _totalEntries = 0, _size = 0, _offset = 0, _commentLength = 0; return { get diskEntries () { return _volumeEntries }, set diskEntries (/*Number*/val) { _volumeEntries = _totalEntries = val; }, get totalEntries () { return _totalEntries }, set totalEntries (/*Number*/val) { _totalEntries = _volumeEntries = val; }, get size () { return _size }, set size (/*Number*/val) { _size = val; }, get offset () { return _offset }, set offset (/*Number*/val) { _offset = val; }, get commentLength () { return _commentLength }, set commentLength (/*Number*/val) { _commentLength = val; }, get mainHeaderSize () { return Constants.ENDHDR + _commentLength; }, loadFromBinary : function(/*Buffer*/data) { // data should be 22 bytes and start with "PK 05 06" if (data.length != Constants.ENDHDR || data.readUInt32LE(0) != Constants.ENDSIG) throw Utils.Errors.INVALID_END; // number of entries on this volume _volumeEntries = data.readUInt16LE(Constants.ENDSUB); // total number of entries _totalEntries = data.readUInt16LE(Constants.ENDTOT); // central directory size in bytes _size = data.readUInt32LE(Constants.ENDSIZ); // offset of first CEN header _offset = data.readUInt32LE(Constants.ENDOFF); // zip file comment length _commentLength = data.readUInt16LE(Constants.ENDCOM); }, toBinary : function() { var b = new Buffer(Constants.ENDHDR + _commentLength); // "PK 05 06" signature b.writeUInt32LE(Constants.ENDSIG, 0); b.writeUInt32LE(0, 4); // number of entries on this volume b.writeUInt16LE(_volumeEntries, Constants.ENDSUB); // total number of entries b.writeUInt16LE(_totalEntries, Constants.ENDTOT); // central directory size in bytes b.writeUInt32LE(_size, Constants.ENDSIZ); // offset of first CEN header b.writeUInt32LE(_offset, Constants.ENDOFF); // zip file comment length b.writeUInt16LE(_commentLength, Constants.ENDCOM); // fill comment memory with spaces so no garbage is left there b.fill(" ", Constants.ENDHDR); return b; }, toString : function() { return '{\n' + '\t"diskEntries" : ' + _volumeEntries + ",\n" + '\t"totalEntries" : ' + _totalEntries + ",\n" + '\t"size" : ' + _size + " bytes,\n" + '\t"offset" : 0x' + _offset.toString(16).toUpperCase() + ",\n" + '\t"commentLength" : 0x' + _commentLength + "\n" + '}'; } } }
...
module.exports = function(/*String|Buffer*/input, /*Number*/inputType) {
var entryList = [],
entryTable = {},
_comment = new Buffer(0),
filename = "",
fs = require("fs"),
inBuffer = null,
mainHeader = new Headers.MainHeader();
if (inputType == Utils.Constants.FILE) {
// is a filename
filename = input;
inBuffer = fs.readFileSync(filename);
readMainHeader();
} else if (inputType == Utils.Constants.BUFFER) {
...
FileAttr = function (path) { var _path = path || "", _permissions = 0, _obj = newAttr(), _stat = null; function newAttr() { return { directory : false, readonly : false, hidden : false, executable : false, mtime : 0, atime : 0 } } if (_path && fs.existsSync(_path)) { _stat = fs.statSync(_path); _obj.directory = _stat.isDirectory(); _obj.mtime = _stat.mtime; _obj.atime = _stat.atime; _obj.executable = !!(1 & parseInt ((_stat.mode & parseInt ("777", 8)).toString (8)[0])); _obj.readonly = !!(2 & parseInt ((_stat.mode & parseInt ("777", 8)).toString (8)[0])); _obj.hidden = pth.basename(_path)[0] === "."; } else { console.warn("Invalid path: " + _path) } return { get directory () { return _obj.directory; }, get readOnly () { return _obj.readonly; }, get hidden () { return _obj.hidden; }, get mtime () { return _obj.mtime; }, get atime () { return _obj.atime; }, get executable () { return _obj.executable; }, decodeAttributes : function(val) { }, encodeAttributes : function (val) { }, toString : function() { return '{\n' + '\t"path" : "' + _path + ",\n" + '\t"isDirectory" : ' + _obj.directory + ",\n" + '\t"isReadOnly" : ' + _obj.readonly + ",\n" + '\t"isHidden" : ' + _obj.hidden + ",\n" + '\t"isExecutable" : ' + _obj.executable + ",\n" + '\t"mTime" : ' + _obj.mtime + "\n" + '\t"aTime" : ' + _obj.atime + "\n" + '}'; } } }
n/a
crc32 = function (buf) { var b = new Buffer(4); if (!crcTable.length) { for (var n = 0; n < 256; n++) { var c = n; for (var k = 8; --k >= 0;) // if ((c & 1) != 0) { c = 0xedb88320 ^ (c >>> 1); } else { c = c >>> 1; } if (c < 0) { b.writeInt32LE(c, 0); c = b.readUInt32LE(0); } crcTable[n] = c; } } var crc = 0, off = 0, len = buf.length, c1 = ~crc; while(--len >= 0) c1 = crcTable[(c1 ^ buf[off++]) & 0xff] ^ (c1 >>> 8); crc = ~c1; b.writeInt32LE(crc & 0xffffffff, 0); return b.readUInt32LE(0); }
...
_entryHeader.loadDataHeaderFromBinary(input);
return input.slice(_entryHeader.realDataOffset, _entryHeader.realDataOffset + _entryHeader.compressedSize)
}
function crc32OK(data) {
// if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is
written
if (_entryHeader.flags & 0x8 != 0x8) {
if (Utils.crc32(data) != _entryHeader.crc) {
return false;
}
} else {
// @TODO: load and check data descriptor header
// The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure
// (optionally preceded by a 4-byte signature) immediately after the compressed data:
}
...
findFiles = function (path) { return findSync(path, true); }
...
localPath = localPath.split("\\").join("/"); //windows fix
localPath = pth.normalize(localPath);
if (localPath.charAt(localPath.length - 1) != "/")
localPath += "/";
if (fs.existsSync(localPath)) {
var items = Utils.findFiles(localPath),
self = this;
if (items.length) {
items.forEach(function(path) {
var p = path.split("\\").join("/").replace( new RegExp(localPath, 'i'), ""); //windows
fix
if (filter(p)) {
if (p.charAt(p.length - 1) !== "/") {
...
getAttributes = function (path) { }
n/a
makeDir = function (path) { mkdirSync(path); }
...
overwrite = overwrite || false;
if (!_zip) {
throw Utils.Errors.NO_ZIP;
}
_zip.entries.forEach(function(entry) {
if (entry.isDirectory) {
Utils.makeDir(pth.resolve(targetPath, entry.entryName.toString()));
return;
}
var content = entry.getData();
if (!content) {
throw Utils.Errors.CANT_EXTRACT_FILE + "2";
}
Utils.writeFileTo(pth.resolve(targetPath, entry.entryName.toString()), content, overwrite);
...
methodToString = function (method) { switch (method) { case Constants.STORED: return 'STORED (' + method + ')'; case Constants.DEFLATED: return 'DEFLATED (' + method + ')'; default: return 'UNSUPPORTED (' + method + ')'; } }
...
},
toString : function() {
return '{\n' +
'\t"made" : ' + _verMade + ",\n" +
'\t"version" : ' + _version + ",\n" +
'\t"flags" : ' + _flags + ",\n" +
'\t"method" : ' + Utils.methodToString(_method) + ",\n" +
'\t"time" : ' + _time + ",\n" +
'\t"crc" : 0x' + _crc.toString(16).toUpperCase() + ",\n" +
'\t"compressedSize" : ' + _compressedSize + " bytes,\n" +
'\t"size" : ' + _size + " bytes,\n" +
'\t"fileNameLength" : ' + _fnameLen + ",\n" +
'\t"extraLength" : ' + _extraLen + " bytes,\n" +
'\t"commentLength" : ' + _comLen + " bytes,\n" +
...
setAttributes = function (path) { }
n/a
toBuffer = function (input) { if (Buffer.isBuffer(input)) { return input; } else { if (input.length == 0) { return new Buffer(0) } return new Buffer(input, 'utf8'); } }
...
var zip = new AdmZip();
// add file directly
zip.addFile("test.txt", new Buffer("inner content of the file"), "entry comment goes here");
// add local file
zip.addLocalFile("/home/me/some_picture.png");
// get everything as a buffer
var willSendthis = zip.toBuffer();
// or write everything to disk
zip.writeZip(/*target file name*/"/home/me/files.zip");
// ... more examples in the wiki
```
...
writeFileTo = function (path, content, overwrite, attr) { if (fs.existsSync(path)) { if (!overwrite) return false; // cannot overwite var stat = fs.statSync(path); if (stat.isDirectory()) { return false; } } var folder = pth.dirname(path); if (!fs.existsSync(folder)) { mkdirSync(folder); } var fd; try { fd = fs.openSync(path, 'w', 438); // 0666 } catch(e) { fs.chmodSync(path, 438); fd = fs.openSync(path, 'w', 438); } if (fd) { fs.writeSync(fd, content, 0, content.length, 0); fs.closeSync(fd); } fs.chmodSync(path, attr || 438); return true; }
...
var children = _zip.getEntryChildren(item);
children.forEach(function(child) {
if (child.isDirectory) return;
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.getData();
if (!content) throw Utils.Errors.CANT_EXTRACT_FILE;
...
writeFileToAsync = function (path, content, overwrite, attr, callback) { if(typeof attr === 'function') { callback = attr; attr = undefined; } fs.exists(path, function(exists) { if(exists && !overwrite) return callback(false); fs.stat(path, function(err, stat) { if(exists &&stat.isDirectory()) { return callback(false); } var folder = pth.dirname(path); fs.exists(folder, function(exists) { if(!exists) mkdirSync(folder); fs.open(path, 'w', 438, function(err, fd) { if(err) { fs.chmod(path, 438, function(err) { fs.open(path, 'w', 438, function(err, fd) { fs.write(fd, content, 0, content.length, 0, function(err, written, buffer) { fs.close(fd, function(err) { fs.chmod(path, attr || 438, function() { callback(true); }) }); }); }); }) } else { if(fd) { fs.write(fd, content, 0, content.length, 0, function(err, written, buffer) { fs.close(fd, function(err) { fs.chmod(path, attr || 438, function() { callback(true); }) }); }); } else { fs.chmod(path, attr || 438, function() { callback(true); }) } } }); }) }) }) }
...
entry.getDataAsync(function(content) {
if(i <= 0) return;
if (!content) {
i = 0;
callback(new Error(Utils.Errors.CANT_EXTRACT_FILE + "2"));
return;
}
Utils.writeFileToAsync(pth.resolve(targetPath, entry.entryName.toString
()), content, overwrite, function(succ) {
if(i <= 0) return;
if(!succ) {
i = 0;
callback(new Error('Unable to write'));
return;
}
...