Remove archiver dependency

This commit is contained in:
advplyr 2022-07-06 20:12:14 -05:00
parent 415e0a7b5a
commit ab08d83c04
35 changed files with 4046 additions and 194 deletions

View file

@ -0,0 +1,16 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
var ArchiveEntry = module.exports = function() {};
ArchiveEntry.prototype.getName = function() {};
ArchiveEntry.prototype.getSize = function() {};
ArchiveEntry.prototype.getLastModifiedDate = function() {};
ArchiveEntry.prototype.isDirectory = function() {};

View file

@ -0,0 +1,117 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
var inherits = require('util').inherits;
var Transform = require('readable-stream').Transform;
var ArchiveEntry = require('./archive-entry');
var util = require('../util');
var ArchiveOutputStream = module.exports = function(options) {
if (!(this instanceof ArchiveOutputStream)) {
return new ArchiveOutputStream(options);
}
Transform.call(this, options);
this.offset = 0;
this._archive = {
finish: false,
finished: false,
processing: false
};
};
inherits(ArchiveOutputStream, Transform);
ArchiveOutputStream.prototype._appendBuffer = function(zae, source, callback) {
// scaffold only
};
ArchiveOutputStream.prototype._appendStream = function(zae, source, callback) {
// scaffold only
};
ArchiveOutputStream.prototype._emitErrorCallback = function(err) {
if (err) {
this.emit('error', err);
}
};
ArchiveOutputStream.prototype._finish = function(ae) {
// scaffold only
};
ArchiveOutputStream.prototype._normalizeEntry = function(ae) {
// scaffold only
};
ArchiveOutputStream.prototype._transform = function(chunk, encoding, callback) {
callback(null, chunk);
};
ArchiveOutputStream.prototype.entry = function(ae, source, callback) {
source = source || null;
if (typeof callback !== 'function') {
callback = this._emitErrorCallback.bind(this);
}
if (!(ae instanceof ArchiveEntry)) {
callback(new Error('not a valid instance of ArchiveEntry'));
return;
}
if (this._archive.finish || this._archive.finished) {
callback(new Error('unacceptable entry after finish'));
return;
}
if (this._archive.processing) {
callback(new Error('already processing an entry'));
return;
}
this._archive.processing = true;
this._normalizeEntry(ae);
this._entry = ae;
source = util.normalizeInputSource(source);
if (Buffer.isBuffer(source)) {
this._appendBuffer(ae, source, callback);
} else if (util.isStream(source)) {
this._appendStream(ae, source, callback);
} else {
this._archive.processing = false;
callback(new Error('input source must be valid Stream or Buffer instance'));
return;
}
return this;
};
ArchiveOutputStream.prototype.finish = function() {
if (this._archive.processing) {
this._archive.finish = true;
return;
}
this._finish();
};
ArchiveOutputStream.prototype.getBytesWritten = function() {
return this.offset;
};
ArchiveOutputStream.prototype.write = function(chunk, cb) {
if (chunk) {
this.offset += chunk.length;
}
return Transform.prototype.write.call(this, chunk, cb);
};

View file

@ -0,0 +1,71 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
module.exports = {
WORD: 4,
DWORD: 8,
EMPTY: Buffer.alloc(0),
SHORT: 2,
SHORT_MASK: 0xffff,
SHORT_SHIFT: 16,
SHORT_ZERO: Buffer.from(Array(2)),
LONG: 4,
LONG_ZERO: Buffer.from(Array(4)),
MIN_VERSION_INITIAL: 10,
MIN_VERSION_DATA_DESCRIPTOR: 20,
MIN_VERSION_ZIP64: 45,
VERSION_MADEBY: 45,
METHOD_STORED: 0,
METHOD_DEFLATED: 8,
PLATFORM_UNIX: 3,
PLATFORM_FAT: 0,
SIG_LFH: 0x04034b50,
SIG_DD: 0x08074b50,
SIG_CFH: 0x02014b50,
SIG_EOCD: 0x06054b50,
SIG_ZIP64_EOCD: 0x06064B50,
SIG_ZIP64_EOCD_LOC: 0x07064B50,
ZIP64_MAGIC_SHORT: 0xffff,
ZIP64_MAGIC: 0xffffffff,
ZIP64_EXTRA_ID: 0x0001,
ZLIB_NO_COMPRESSION: 0,
ZLIB_BEST_SPEED: 1,
ZLIB_BEST_COMPRESSION: 9,
ZLIB_DEFAULT_COMPRESSION: -1,
MODE_MASK: 0xFFF,
DEFAULT_FILE_MODE: 33188, // 010644 = -rw-r--r-- = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
DEFAULT_DIR_MODE: 16877, // 040755 = drwxr-xr-x = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
EXT_FILE_ATTR_DIR: 1106051088, // 010173200020 = drwxr-xr-x = (((S_IFDIR | 0755) << 16) | S_DOS_D)
EXT_FILE_ATTR_FILE: 2175008800, // 020151000040 = -rw-r--r-- = (((S_IFREG | 0644) << 16) | S_DOS_A) >>> 0
// Unix file types
S_IFMT: 61440, // 0170000 type of file mask
S_IFIFO: 4096, // 010000 named pipe (fifo)
S_IFCHR: 8192, // 020000 character special
S_IFDIR: 16384, // 040000 directory
S_IFBLK: 24576, // 060000 block special
S_IFREG: 32768, // 0100000 regular
S_IFLNK: 40960, // 0120000 symbolic link
S_IFSOCK: 49152, // 0140000 socket
// DOS file type flags
S_DOS_A: 32, // 040 Archive
S_DOS_D: 16, // 020 Directory
S_DOS_V: 8, // 010 Volume
S_DOS_S: 4, // 04 System
S_DOS_H: 2, // 02 Hidden
S_DOS_R: 1 // 01 Read Only
};

View file

@ -0,0 +1,101 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
var zipUtil = require('./util');
var DATA_DESCRIPTOR_FLAG = 1 << 3;
var ENCRYPTION_FLAG = 1 << 0;
var NUMBER_OF_SHANNON_FANO_TREES_FLAG = 1 << 2;
var SLIDING_DICTIONARY_SIZE_FLAG = 1 << 1;
var STRONG_ENCRYPTION_FLAG = 1 << 6;
var UFT8_NAMES_FLAG = 1 << 11;
var GeneralPurposeBit = module.exports = function() {
if (!(this instanceof GeneralPurposeBit)) {
return new GeneralPurposeBit();
}
this.descriptor = false;
this.encryption = false;
this.utf8 = false;
this.numberOfShannonFanoTrees = 0;
this.strongEncryption = false;
this.slidingDictionarySize = 0;
return this;
};
GeneralPurposeBit.prototype.encode = function() {
return zipUtil.getShortBytes(
(this.descriptor ? DATA_DESCRIPTOR_FLAG : 0) |
(this.utf8 ? UFT8_NAMES_FLAG : 0) |
(this.encryption ? ENCRYPTION_FLAG : 0) |
(this.strongEncryption ? STRONG_ENCRYPTION_FLAG : 0)
);
};
GeneralPurposeBit.prototype.parse = function(buf, offset) {
var flag = zipUtil.getShortBytesValue(buf, offset);
var gbp = new GeneralPurposeBit();
gbp.useDataDescriptor((flag & DATA_DESCRIPTOR_FLAG) !== 0);
gbp.useUTF8ForNames((flag & UFT8_NAMES_FLAG) !== 0);
gbp.useStrongEncryption((flag & STRONG_ENCRYPTION_FLAG) !== 0);
gbp.useEncryption((flag & ENCRYPTION_FLAG) !== 0);
gbp.setSlidingDictionarySize((flag & SLIDING_DICTIONARY_SIZE_FLAG) !== 0 ? 8192 : 4096);
gbp.setNumberOfShannonFanoTrees((flag & NUMBER_OF_SHANNON_FANO_TREES_FLAG) !== 0 ? 3 : 2);
return gbp;
};
GeneralPurposeBit.prototype.setNumberOfShannonFanoTrees = function(n) {
this.numberOfShannonFanoTrees = n;
};
GeneralPurposeBit.prototype.getNumberOfShannonFanoTrees = function() {
return this.numberOfShannonFanoTrees;
};
GeneralPurposeBit.prototype.setSlidingDictionarySize = function(n) {
this.slidingDictionarySize = n;
};
GeneralPurposeBit.prototype.getSlidingDictionarySize = function() {
return this.slidingDictionarySize;
};
GeneralPurposeBit.prototype.useDataDescriptor = function(b) {
this.descriptor = b;
};
GeneralPurposeBit.prototype.usesDataDescriptor = function() {
return this.descriptor;
};
GeneralPurposeBit.prototype.useEncryption = function(b) {
this.encryption = b;
};
GeneralPurposeBit.prototype.usesEncryption = function() {
return this.encryption;
};
GeneralPurposeBit.prototype.useStrongEncryption = function(b) {
this.strongEncryption = b;
};
GeneralPurposeBit.prototype.usesStrongEncryption = function() {
return this.strongEncryption;
};
GeneralPurposeBit.prototype.useUTF8ForNames = function(b) {
this.utf8 = b;
};
GeneralPurposeBit.prototype.usesUTF8ForNames = function() {
return this.utf8;
};

View file

@ -0,0 +1,53 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
module.exports = {
/**
* Bits used for permissions (and sticky bit)
*/
PERM_MASK: 4095, // 07777
/**
* Bits used to indicate the filesystem object type.
*/
FILE_TYPE_FLAG: 61440, // 0170000
/**
* Indicates symbolic links.
*/
LINK_FLAG: 40960, // 0120000
/**
* Indicates plain files.
*/
FILE_FLAG: 32768, // 0100000
/**
* Indicates directories.
*/
DIR_FLAG: 16384, // 040000
// ----------------------------------------------------------
// somewhat arbitrary choices that are quite common for shared
// installations
// -----------------------------------------------------------
/**
* Default permissions for symbolic links.
*/
DEFAULT_LINK_PERM: 511, // 0777
/**
* Default permissions for directories.
*/
DEFAULT_DIR_PERM: 493, // 0755
/**
* Default permissions for plain files.
*/
DEFAULT_FILE_PERM: 420 // 0644
};

View file

@ -0,0 +1,74 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
var util = module.exports = {};
util.dateToDos = function(d, forceLocalTime) {
forceLocalTime = forceLocalTime || false;
var year = forceLocalTime ? d.getFullYear() : d.getUTCFullYear();
if (year < 1980) {
return 2162688; // 1980-1-1 00:00:00
} else if (year >= 2044) {
return 2141175677; // 2043-12-31 23:59:58
}
var val = {
year: year,
month: forceLocalTime ? d.getMonth() : d.getUTCMonth(),
date: forceLocalTime ? d.getDate() : d.getUTCDate(),
hours: forceLocalTime ? d.getHours() : d.getUTCHours(),
minutes: forceLocalTime ? d.getMinutes() : d.getUTCMinutes(),
seconds: forceLocalTime ? d.getSeconds() : d.getUTCSeconds()
};
return ((val.year - 1980) << 25) | ((val.month + 1) << 21) | (val.date << 16) |
(val.hours << 11) | (val.minutes << 5) | (val.seconds / 2);
};
util.dosToDate = function(dos) {
return new Date(((dos >> 25) & 0x7f) + 1980, ((dos >> 21) & 0x0f) - 1, (dos >> 16) & 0x1f, (dos >> 11) & 0x1f, (dos >> 5) & 0x3f, (dos & 0x1f) << 1);
};
util.fromDosTime = function(buf) {
return util.dosToDate(buf.readUInt32LE(0));
};
util.getEightBytes = function(v) {
var buf = Buffer.alloc(8);
buf.writeUInt32LE(v % 0x0100000000, 0);
buf.writeUInt32LE((v / 0x0100000000) | 0, 4);
return buf;
};
util.getShortBytes = function(v) {
var buf = Buffer.alloc(2);
buf.writeUInt16LE((v & 0xFFFF) >>> 0, 0);
return buf;
};
util.getShortBytesValue = function(buf, offset) {
return buf.readUInt16LE(offset);
};
util.getLongBytes = function(v) {
var buf = Buffer.alloc(4);
buf.writeUInt32LE((v & 0xFFFFFFFF) >>> 0, 0);
return buf;
};
util.getLongBytesValue = function(buf, offset) {
return buf.readUInt32LE(offset);
};
util.toDosTime = function(d) {
return util.getLongBytes(util.dateToDos(d));
};

View file

@ -0,0 +1,413 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
var inherits = require('util').inherits;
var normalizePath = require('../../../normalize-path');
var ArchiveEntry = require('../archive-entry');
var GeneralPurposeBit = require('./general-purpose-bit');
var UnixStat = require('./unix-stat');
var constants = require('./constants');
var zipUtil = require('./util');
var ZipArchiveEntry = module.exports = function (name) {
if (!(this instanceof ZipArchiveEntry)) {
return new ZipArchiveEntry(name);
}
ArchiveEntry.call(this);
this.platform = constants.PLATFORM_FAT;
this.method = -1;
this.name = null;
this.size = 0;
this.csize = 0;
this.gpb = new GeneralPurposeBit();
this.crc = 0;
this.time = -1;
this.minver = constants.MIN_VERSION_INITIAL;
this.mode = -1;
this.extra = null;
this.exattr = 0;
this.inattr = 0;
this.comment = null;
if (name) {
this.setName(name);
}
};
inherits(ZipArchiveEntry, ArchiveEntry);
/**
* Returns the extra fields related to the entry.
*
* @returns {Buffer}
*/
ZipArchiveEntry.prototype.getCentralDirectoryExtra = function () {
return this.getExtra();
};
/**
* Returns the comment set for the entry.
*
* @returns {string}
*/
ZipArchiveEntry.prototype.getComment = function () {
return this.comment !== null ? this.comment : '';
};
/**
* Returns the compressed size of the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getCompressedSize = function () {
return this.csize;
};
/**
* Returns the CRC32 digest for the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getCrc = function () {
return this.crc;
};
/**
* Returns the external file attributes for the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getExternalAttributes = function () {
return this.exattr;
};
/**
* Returns the extra fields related to the entry.
*
* @returns {Buffer}
*/
ZipArchiveEntry.prototype.getExtra = function () {
return this.extra !== null ? this.extra : constants.EMPTY;
};
/**
* Returns the general purpose bits related to the entry.
*
* @returns {GeneralPurposeBit}
*/
ZipArchiveEntry.prototype.getGeneralPurposeBit = function () {
return this.gpb;
};
/**
* Returns the internal file attributes for the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getInternalAttributes = function () {
return this.inattr;
};
/**
* Returns the last modified date of the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getLastModifiedDate = function () {
return this.getTime();
};
/**
* Returns the extra fields related to the entry.
*
* @returns {Buffer}
*/
ZipArchiveEntry.prototype.getLocalFileDataExtra = function () {
return this.getExtra();
};
/**
* Returns the compression method used on the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getMethod = function () {
return this.method;
};
/**
* Returns the filename of the entry.
*
* @returns {string}
*/
ZipArchiveEntry.prototype.getName = function () {
return this.name;
};
/**
* Returns the platform on which the entry was made.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getPlatform = function () {
return this.platform;
};
/**
* Returns the size of the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getSize = function () {
return this.size;
};
/**
* Returns a date object representing the last modified date of the entry.
*
* @returns {number|Date}
*/
ZipArchiveEntry.prototype.getTime = function () {
return this.time !== -1 ? zipUtil.dosToDate(this.time) : -1;
};
/**
* Returns the DOS timestamp for the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getTimeDos = function () {
return this.time !== -1 ? this.time : 0;
};
/**
* Returns the UNIX file permissions for the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getUnixMode = function () {
return this.platform !== constants.PLATFORM_UNIX ? 0 : ((this.getExternalAttributes() >> constants.SHORT_SHIFT) & constants.SHORT_MASK);
};
/**
* Returns the version of ZIP needed to extract the entry.
*
* @returns {number}
*/
ZipArchiveEntry.prototype.getVersionNeededToExtract = function () {
return this.minver;
};
/**
* Sets the comment of the entry.
*
* @param comment
*/
ZipArchiveEntry.prototype.setComment = function (comment) {
if (Buffer.byteLength(comment) !== comment.length) {
this.getGeneralPurposeBit().useUTF8ForNames(true);
}
this.comment = comment;
};
/**
* Sets the compressed size of the entry.
*
* @param size
*/
ZipArchiveEntry.prototype.setCompressedSize = function (size) {
if (size < 0) {
throw new Error('invalid entry compressed size');
}
this.csize = size;
};
/**
* Sets the checksum of the entry.
*
* @param crc
*/
ZipArchiveEntry.prototype.setCrc = function (crc) {
if (crc < 0) {
throw new Error('invalid entry crc32');
}
this.crc = crc;
};
/**
* Sets the external file attributes of the entry.
*
* @param attr
*/
ZipArchiveEntry.prototype.setExternalAttributes = function (attr) {
this.exattr = attr >>> 0;
};
/**
* Sets the extra fields related to the entry.
*
* @param extra
*/
ZipArchiveEntry.prototype.setExtra = function (extra) {
this.extra = extra;
};
/**
* Sets the general purpose bits related to the entry.
*
* @param gpb
*/
ZipArchiveEntry.prototype.setGeneralPurposeBit = function (gpb) {
if (!(gpb instanceof GeneralPurposeBit)) {
throw new Error('invalid entry GeneralPurposeBit');
}
this.gpb = gpb;
};
/**
* Sets the internal file attributes of the entry.
*
* @param attr
*/
ZipArchiveEntry.prototype.setInternalAttributes = function (attr) {
this.inattr = attr;
};
/**
* Sets the compression method of the entry.
*
* @param method
*/
ZipArchiveEntry.prototype.setMethod = function (method) {
if (method < 0) {
throw new Error('invalid entry compression method');
}
this.method = method;
};
/**
* Sets the name of the entry.
*
* @param name
* @param prependSlash
*/
ZipArchiveEntry.prototype.setName = function (name, prependSlash = false) {
name = normalizePath(name, false)
.replace(/^\w+:/, '')
.replace(/^(\.\.\/|\/)+/, '');
if (prependSlash) {
name = `/${name}`;
}
if (Buffer.byteLength(name) !== name.length) {
this.getGeneralPurposeBit().useUTF8ForNames(true);
}
this.name = name;
};
/**
* Sets the platform on which the entry was made.
*
* @param platform
*/
ZipArchiveEntry.prototype.setPlatform = function (platform) {
this.platform = platform;
};
/**
* Sets the size of the entry.
*
* @param size
*/
ZipArchiveEntry.prototype.setSize = function (size) {
if (size < 0) {
throw new Error('invalid entry size');
}
this.size = size;
};
/**
* Sets the time of the entry.
*
* @param time
* @param forceLocalTime
*/
ZipArchiveEntry.prototype.setTime = function (time, forceLocalTime) {
if (!(time instanceof Date)) {
throw new Error('invalid entry time');
}
this.time = zipUtil.dateToDos(time, forceLocalTime);
};
/**
* Sets the UNIX file permissions for the entry.
*
* @param mode
*/
ZipArchiveEntry.prototype.setUnixMode = function (mode) {
mode |= this.isDirectory() ? constants.S_IFDIR : constants.S_IFREG;
var extattr = 0;
extattr |= (mode << constants.SHORT_SHIFT) | (this.isDirectory() ? constants.S_DOS_D : constants.S_DOS_A);
this.setExternalAttributes(extattr);
this.mode = mode & constants.MODE_MASK;
this.platform = constants.PLATFORM_UNIX;
};
/**
* Sets the version of ZIP needed to extract this entry.
*
* @param minver
*/
ZipArchiveEntry.prototype.setVersionNeededToExtract = function (minver) {
this.minver = minver;
};
/**
* Returns true if this entry represents a directory.
*
* @returns {boolean}
*/
ZipArchiveEntry.prototype.isDirectory = function () {
return this.getName().slice(-1) === '/';
};
/**
* Returns true if this entry represents a unix symlink,
* in which case the entry's content contains the target path
* for the symlink.
*
* @returns {boolean}
*/
ZipArchiveEntry.prototype.isUnixSymlink = function () {
return (this.getUnixMode() & UnixStat.FILE_TYPE_FLAG) === UnixStat.LINK_FLAG;
};
/**
* Returns true if this entry is using the ZIP64 extension of ZIP.
*
* @returns {boolean}
*/
ZipArchiveEntry.prototype.isZip64 = function () {
return this.csize > constants.ZIP64_MAGIC || this.size > constants.ZIP64_MAGIC;
};

View file

@ -0,0 +1,437 @@
/**
* node-compress-commons
*
* Copyright (c) 2014 Chris Talkington, contributors.
* Licensed under the MIT license.
* https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT
*/
var inherits = require('util').inherits;
var crc32 = require('../../../buffer-crc32');
var { CRC32Stream } = require('../../../crc32-stream');
var { DeflateCRC32Stream } = require('../../../crc32-stream');
var ArchiveOutputStream = require('../archive-output-stream');
var constants = require('./constants');
var zipUtil = require('./util');
var ZipArchiveOutputStream = module.exports = function (options) {
if (!(this instanceof ZipArchiveOutputStream)) {
return new ZipArchiveOutputStream(options);
}
options = this.options = this._defaults(options);
ArchiveOutputStream.call(this, options);
this._entry = null;
this._entries = [];
this._archive = {
centralLength: 0,
centralOffset: 0,
comment: '',
finish: false,
finished: false,
processing: false,
forceZip64: options.forceZip64,
forceLocalTime: options.forceLocalTime
};
};
inherits(ZipArchiveOutputStream, ArchiveOutputStream);
ZipArchiveOutputStream.prototype._afterAppend = function (ae) {
this._entries.push(ae);
if (ae.getGeneralPurposeBit().usesDataDescriptor()) {
this._writeDataDescriptor(ae);
}
this._archive.processing = false;
this._entry = null;
if (this._archive.finish && !this._archive.finished) {
this._finish();
}
};
ZipArchiveOutputStream.prototype._appendBuffer = function (ae, source, callback) {
if (source.length === 0) {
ae.setMethod(constants.METHOD_STORED);
}
var method = ae.getMethod();
if (method === constants.METHOD_STORED) {
ae.setSize(source.length);
ae.setCompressedSize(source.length);
ae.setCrc(crc32.unsigned(source));
}
this._writeLocalFileHeader(ae);
if (method === constants.METHOD_STORED) {
this.write(source);
this._afterAppend(ae);
callback(null, ae);
return;
} else if (method === constants.METHOD_DEFLATED) {
this._smartStream(ae, callback).end(source);
return;
} else {
callback(new Error('compression method ' + method + ' not implemented'));
return;
}
};
ZipArchiveOutputStream.prototype._appendStream = function (ae, source, callback) {
ae.getGeneralPurposeBit().useDataDescriptor(true);
ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR);
this._writeLocalFileHeader(ae);
var smart = this._smartStream(ae, callback);
source.once('error', function (err) {
smart.emit('error', err);
smart.end();
})
source.pipe(smart);
};
ZipArchiveOutputStream.prototype._defaults = function (o) {
if (typeof o !== 'object') {
o = {};
}
if (typeof o.zlib !== 'object') {
o.zlib = {};
}
if (typeof o.zlib.level !== 'number') {
o.zlib.level = constants.ZLIB_BEST_SPEED;
}
o.forceZip64 = !!o.forceZip64;
o.forceLocalTime = !!o.forceLocalTime;
return o;
};
ZipArchiveOutputStream.prototype._finish = function () {
this._archive.centralOffset = this.offset;
this._entries.forEach(function (ae) {
this._writeCentralFileHeader(ae);
}.bind(this));
this._archive.centralLength = this.offset - this._archive.centralOffset;
if (this.isZip64()) {
this._writeCentralDirectoryZip64();
}
this._writeCentralDirectoryEnd();
this._archive.processing = false;
this._archive.finish = true;
this._archive.finished = true;
this.end();
};
ZipArchiveOutputStream.prototype._normalizeEntry = function (ae) {
if (ae.getMethod() === -1) {
ae.setMethod(constants.METHOD_DEFLATED);
}
if (ae.getMethod() === constants.METHOD_DEFLATED) {
ae.getGeneralPurposeBit().useDataDescriptor(true);
ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR);
}
if (ae.getTime() === -1) {
ae.setTime(new Date(), this._archive.forceLocalTime);
}
ae._offsets = {
file: 0,
data: 0,
contents: 0,
};
};
ZipArchiveOutputStream.prototype._smartStream = function (ae, callback) {
var deflate = ae.getMethod() === constants.METHOD_DEFLATED;
var process = deflate ? new DeflateCRC32Stream(this.options.zlib) : new CRC32Stream();
var error = null;
function handleStuff() {
var digest = process.digest().readUInt32BE(0);
ae.setCrc(digest);
ae.setSize(process.size());
ae.setCompressedSize(process.size(true));
this._afterAppend(ae);
callback(error, ae);
}
process.once('end', handleStuff.bind(this));
process.once('error', function (err) {
error = err;
});
process.pipe(this, { end: false });
return process;
};
ZipArchiveOutputStream.prototype._writeCentralDirectoryEnd = function () {
var records = this._entries.length;
var size = this._archive.centralLength;
var offset = this._archive.centralOffset;
if (this.isZip64()) {
records = constants.ZIP64_MAGIC_SHORT;
size = constants.ZIP64_MAGIC;
offset = constants.ZIP64_MAGIC;
}
// signature
this.write(zipUtil.getLongBytes(constants.SIG_EOCD));
// disk numbers
this.write(constants.SHORT_ZERO);
this.write(constants.SHORT_ZERO);
// number of entries
this.write(zipUtil.getShortBytes(records));
this.write(zipUtil.getShortBytes(records));
// length and location of CD
this.write(zipUtil.getLongBytes(size));
this.write(zipUtil.getLongBytes(offset));
// archive comment
var comment = this.getComment();
var commentLength = Buffer.byteLength(comment);
this.write(zipUtil.getShortBytes(commentLength));
this.write(comment);
};
ZipArchiveOutputStream.prototype._writeCentralDirectoryZip64 = function () {
// signature
this.write(zipUtil.getLongBytes(constants.SIG_ZIP64_EOCD));
// size of the ZIP64 EOCD record
this.write(zipUtil.getEightBytes(44));
// version made by
this.write(zipUtil.getShortBytes(constants.MIN_VERSION_ZIP64));
// version to extract
this.write(zipUtil.getShortBytes(constants.MIN_VERSION_ZIP64));
// disk numbers
this.write(constants.LONG_ZERO);
this.write(constants.LONG_ZERO);
// number of entries
this.write(zipUtil.getEightBytes(this._entries.length));
this.write(zipUtil.getEightBytes(this._entries.length));
// length and location of CD
this.write(zipUtil.getEightBytes(this._archive.centralLength));
this.write(zipUtil.getEightBytes(this._archive.centralOffset));
// extensible data sector
// not implemented at this time
// end of central directory locator
this.write(zipUtil.getLongBytes(constants.SIG_ZIP64_EOCD_LOC));
// disk number holding the ZIP64 EOCD record
this.write(constants.LONG_ZERO);
// relative offset of the ZIP64 EOCD record
this.write(zipUtil.getEightBytes(this._archive.centralOffset + this._archive.centralLength));
// total number of disks
this.write(zipUtil.getLongBytes(1));
};
ZipArchiveOutputStream.prototype._writeCentralFileHeader = function (ae) {
var gpb = ae.getGeneralPurposeBit();
var method = ae.getMethod();
var offsets = ae._offsets;
var size = ae.getSize();
var compressedSize = ae.getCompressedSize();
if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) {
size = constants.ZIP64_MAGIC;
compressedSize = constants.ZIP64_MAGIC;
ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64);
var extraBuf = Buffer.concat([
zipUtil.getShortBytes(constants.ZIP64_EXTRA_ID),
zipUtil.getShortBytes(24),
zipUtil.getEightBytes(ae.getSize()),
zipUtil.getEightBytes(ae.getCompressedSize()),
zipUtil.getEightBytes(offsets.file)
], 28);
ae.setExtra(extraBuf);
}
// signature
this.write(zipUtil.getLongBytes(constants.SIG_CFH));
// version made by
this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));
// version to extract and general bit flag
this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
this.write(gpb.encode());
// compression method
this.write(zipUtil.getShortBytes(method));
// datetime
this.write(zipUtil.getLongBytes(ae.getTimeDos()));
// crc32 checksum
this.write(zipUtil.getLongBytes(ae.getCrc()));
// sizes
this.write(zipUtil.getLongBytes(compressedSize));
this.write(zipUtil.getLongBytes(size));
var name = ae.getName();
var comment = ae.getComment();
var extra = ae.getCentralDirectoryExtra();
if (gpb.usesUTF8ForNames()) {
name = Buffer.from(name);
comment = Buffer.from(comment);
}
// name length
this.write(zipUtil.getShortBytes(name.length));
// extra length
this.write(zipUtil.getShortBytes(extra.length));
// comments length
this.write(zipUtil.getShortBytes(comment.length));
// disk number start
this.write(constants.SHORT_ZERO);
// internal attributes
this.write(zipUtil.getShortBytes(ae.getInternalAttributes()));
// external attributes
this.write(zipUtil.getLongBytes(ae.getExternalAttributes()));
// relative offset of LFH
if (offsets.file > constants.ZIP64_MAGIC) {
this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC));
} else {
this.write(zipUtil.getLongBytes(offsets.file));
}
// name
this.write(name);
// extra
this.write(extra);
// comment
this.write(comment);
};
ZipArchiveOutputStream.prototype._writeDataDescriptor = function (ae) {
// signature
this.write(zipUtil.getLongBytes(constants.SIG_DD));
// crc32 checksum
this.write(zipUtil.getLongBytes(ae.getCrc()));
// sizes
if (ae.isZip64()) {
this.write(zipUtil.getEightBytes(ae.getCompressedSize()));
this.write(zipUtil.getEightBytes(ae.getSize()));
} else {
this.write(zipUtil.getLongBytes(ae.getCompressedSize()));
this.write(zipUtil.getLongBytes(ae.getSize()));
}
};
ZipArchiveOutputStream.prototype._writeLocalFileHeader = function (ae) {
var gpb = ae.getGeneralPurposeBit();
var method = ae.getMethod();
var name = ae.getName();
var extra = ae.getLocalFileDataExtra();
if (ae.isZip64()) {
gpb.useDataDescriptor(true);
ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64);
}
if (gpb.usesUTF8ForNames()) {
name = Buffer.from(name);
}
ae._offsets.file = this.offset;
// signature
this.write(zipUtil.getLongBytes(constants.SIG_LFH));
// version to extract and general bit flag
this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
this.write(gpb.encode());
// compression method
this.write(zipUtil.getShortBytes(method));
// datetime
this.write(zipUtil.getLongBytes(ae.getTimeDos()));
ae._offsets.data = this.offset;
// crc32 checksum and sizes
if (gpb.usesDataDescriptor()) {
this.write(constants.LONG_ZERO);
this.write(constants.LONG_ZERO);
this.write(constants.LONG_ZERO);
} else {
this.write(zipUtil.getLongBytes(ae.getCrc()));
this.write(zipUtil.getLongBytes(ae.getCompressedSize()));
this.write(zipUtil.getLongBytes(ae.getSize()));
}
// name length
this.write(zipUtil.getShortBytes(name.length));
// extra length
this.write(zipUtil.getShortBytes(extra.length));
// name
this.write(name);
// extra
this.write(extra);
ae._offsets.contents = this.offset;
};
ZipArchiveOutputStream.prototype.getComment = function (comment) {
return this._archive.comment !== null ? this._archive.comment : '';
};
ZipArchiveOutputStream.prototype.isZip64 = function () {
return this._archive.forceZip64 || this._entries.length > constants.ZIP64_MAGIC_SHORT || this._archive.centralLength > constants.ZIP64_MAGIC || this._archive.centralOffset > constants.ZIP64_MAGIC;
};
ZipArchiveOutputStream.prototype.setComment = function (comment) {
this._archive.comment = comment;
};