diff options
Diffstat (limited to 'node_modules/yazl/index.js')
-rw-r--r-- | node_modules/yazl/index.js | 641 |
1 files changed, 0 insertions, 641 deletions
diff --git a/node_modules/yazl/index.js b/node_modules/yazl/index.js deleted file mode 100644 index 3328732f6..000000000 --- a/node_modules/yazl/index.js +++ /dev/null @@ -1,641 +0,0 @@ -var fs = require("fs"); -var Transform = require("stream").Transform; -var PassThrough = require("stream").PassThrough; -var zlib = require("zlib"); -var util = require("util"); -var EventEmitter = require("events").EventEmitter; -var crc32 = require("buffer-crc32"); - -exports.ZipFile = ZipFile; -exports.dateToDosDateTime = dateToDosDateTime; - -util.inherits(ZipFile, EventEmitter); -function ZipFile() { - this.outputStream = new PassThrough(); - this.entries = []; - this.outputStreamCursor = 0; - this.ended = false; // .end() sets this - this.allDone = false; // set when we've written the last bytes - this.forceZip64Eocd = false; // configurable in .end() -} - -ZipFile.prototype.addFile = function(realPath, metadataPath, options) { - var self = this; - metadataPath = validateMetadataPath(metadataPath, false); - if (options == null) options = {}; - - var entry = new Entry(metadataPath, false, options); - self.entries.push(entry); - fs.stat(realPath, function(err, stats) { - if (err) return self.emit("error", err); - if (!stats.isFile()) return self.emit("error", new Error("not a file: " + realPath)); - entry.uncompressedSize = stats.size; - if (options.mtime == null) entry.setLastModDate(stats.mtime); - if (options.mode == null) entry.setFileAttributesMode(stats.mode); - entry.setFileDataPumpFunction(function() { - var readStream = fs.createReadStream(realPath); - entry.state = Entry.FILE_DATA_IN_PROGRESS; - readStream.on("error", function(err) { - self.emit("error", err); - }); - pumpFileDataReadStream(self, entry, readStream); - }); - pumpEntries(self); - }); -}; - -ZipFile.prototype.addReadStream = function(readStream, metadataPath, options) { - var self = this; - metadataPath = validateMetadataPath(metadataPath, false); - if (options == null) options = {}; - var entry = new Entry(metadataPath, false, options); - self.entries.push(entry); - entry.setFileDataPumpFunction(function() { - entry.state = Entry.FILE_DATA_IN_PROGRESS; - pumpFileDataReadStream(self, entry, readStream); - }); - pumpEntries(self); -}; - -ZipFile.prototype.addBuffer = function(buffer, metadataPath, options) { - var self = this; - metadataPath = validateMetadataPath(metadataPath, false); - if (buffer.length > 0x3fffffff) throw new Error("buffer too large: " + buffer.length + " > " + 0x3fffffff); - if (options == null) options = {}; - if (options.size != null) throw new Error("options.size not allowed"); - var entry = new Entry(metadataPath, false, options); - entry.uncompressedSize = buffer.length; - entry.crc32 = crc32.unsigned(buffer); - entry.crcAndFileSizeKnown = true; - self.entries.push(entry); - if (!entry.compress) { - setCompressedBuffer(buffer); - } else { - zlib.deflateRaw(buffer, function(err, compressedBuffer) { - setCompressedBuffer(compressedBuffer); - }); - } - function setCompressedBuffer(compressedBuffer) { - entry.compressedSize = compressedBuffer.length; - entry.setFileDataPumpFunction(function() { - writeToOutputStream(self, compressedBuffer); - writeToOutputStream(self, entry.getDataDescriptor()); - entry.state = Entry.FILE_DATA_DONE; - - // don't call pumpEntries() recursively. - // (also, don't call process.nextTick recursively.) - setImmediate(function() { - pumpEntries(self); - }); - }); - pumpEntries(self); - } -}; - -ZipFile.prototype.addEmptyDirectory = function(metadataPath, options) { - var self = this; - metadataPath = validateMetadataPath(metadataPath, true); - if (options == null) options = {}; - if (options.size != null) throw new Error("options.size not allowed"); - if (options.compress != null) throw new Error("options.compress not allowed"); - var entry = new Entry(metadataPath, true, options); - self.entries.push(entry); - entry.setFileDataPumpFunction(function() { - writeToOutputStream(self, entry.getDataDescriptor()); - entry.state = Entry.FILE_DATA_DONE; - pumpEntries(self); - }); - pumpEntries(self); -}; - -ZipFile.prototype.end = function(options, finalSizeCallback) { - if (typeof options === "function") { - finalSizeCallback = options; - options = null; - } - if (options == null) options = {}; - if (this.ended) return; - this.ended = true; - this.finalSizeCallback = finalSizeCallback; - this.forceZip64Eocd = !!options.forceZip64Format; - pumpEntries(this); -}; - -function writeToOutputStream(self, buffer) { - self.outputStream.write(buffer); - self.outputStreamCursor += buffer.length; -} - -function pumpFileDataReadStream(self, entry, readStream) { - var crc32Watcher = new Crc32Watcher(); - var uncompressedSizeCounter = new ByteCounter(); - var compressor = entry.compress ? new zlib.DeflateRaw() : new PassThrough(); - var compressedSizeCounter = new ByteCounter(); - readStream.pipe(crc32Watcher) - .pipe(uncompressedSizeCounter) - .pipe(compressor) - .pipe(compressedSizeCounter) - .pipe(self.outputStream, {end: false}); - compressedSizeCounter.on("end", function() { - entry.crc32 = crc32Watcher.crc32; - if (entry.uncompressedSize == null) { - entry.uncompressedSize = uncompressedSizeCounter.byteCount; - } else { - if (entry.uncompressedSize !== uncompressedSizeCounter.byteCount) return self.emit("error", new Error("file data stream has unexpected number of bytes")); - } - entry.compressedSize = compressedSizeCounter.byteCount; - self.outputStreamCursor += entry.compressedSize; - writeToOutputStream(self, entry.getDataDescriptor()); - entry.state = Entry.FILE_DATA_DONE; - pumpEntries(self); - }); -} - -function pumpEntries(self) { - if (self.allDone) return; - // first check if finalSize is finally known - if (self.ended && self.finalSizeCallback != null) { - var finalSize = calculateFinalSize(self); - if (finalSize != null) { - // we have an answer - self.finalSizeCallback(finalSize); - self.finalSizeCallback = null; - } - } - - // pump entries - var entry = getFirstNotDoneEntry(); - function getFirstNotDoneEntry() { - for (var i = 0; i < self.entries.length; i++) { - var entry = self.entries[i]; - if (entry.state < Entry.FILE_DATA_DONE) return entry; - } - return null; - } - if (entry != null) { - // this entry is not done yet - if (entry.state < Entry.READY_TO_PUMP_FILE_DATA) return; // input file not open yet - if (entry.state === Entry.FILE_DATA_IN_PROGRESS) return; // we'll get there - // start with local file header - entry.relativeOffsetOfLocalHeader = self.outputStreamCursor; - var localFileHeader = entry.getLocalFileHeader(); - writeToOutputStream(self, localFileHeader); - entry.doFileDataPump(); - } else { - // all cought up on writing entries - if (self.ended) { - // head for the exit - self.offsetOfStartOfCentralDirectory = self.outputStreamCursor; - self.entries.forEach(function(entry) { - var centralDirectoryRecord = entry.getCentralDirectoryRecord(); - writeToOutputStream(self, centralDirectoryRecord); - }); - writeToOutputStream(self, getEndOfCentralDirectoryRecord(self)); - self.outputStream.end(); - self.allDone = true; - } - } -} - -function calculateFinalSize(self) { - var pretendOutputCursor = 0; - var centralDirectorySize = 0; - for (var i = 0; i < self.entries.length; i++) { - var entry = self.entries[i]; - // compression is too hard to predict - if (entry.compress) return -1; - if (entry.state >= Entry.READY_TO_PUMP_FILE_DATA) { - // if addReadStream was called without providing the size, we can't predict the final size - if (entry.uncompressedSize == null) return -1; - } else { - // if we're still waiting for fs.stat, we might learn the size someday - if (entry.uncompressedSize == null) return null; - } - // we know this for sure, and this is important to know if we need ZIP64 format. - entry.relativeOffsetOfLocalHeader = pretendOutputCursor; - var useZip64Format = entry.useZip64Format(); - - pretendOutputCursor += LOCAL_FILE_HEADER_FIXED_SIZE + entry.utf8FileName.length; - pretendOutputCursor += entry.uncompressedSize; - if (!entry.crcAndFileSizeKnown) { - // use a data descriptor - if (useZip64Format) { - pretendOutputCursor += ZIP64_DATA_DESCRIPTOR_SIZE; - } else { - pretendOutputCursor += DATA_DESCRIPTOR_SIZE; - } - } - - centralDirectorySize += CENTRAL_DIRECTORY_RECORD_FIXED_SIZE + entry.utf8FileName.length; - if (useZip64Format) { - centralDirectorySize += ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE; - } - } - - var endOfCentralDirectorySize = 0; - if (self.forceZip64Eocd || - self.entries.length >= 0xffff || - centralDirectorySize >= 0xffff || - pretendOutputCursor >= 0xffffffff) { - // use zip64 end of central directory stuff - endOfCentralDirectorySize += ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE; - } - endOfCentralDirectorySize += END_OF_CENTRAL_DIRECTORY_RECORD_SIZE; - return pretendOutputCursor + centralDirectorySize + endOfCentralDirectorySize; -} - -var ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 56; -var ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE = 20; -var END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 22; -function getEndOfCentralDirectoryRecord(self, actuallyJustTellMeHowLongItWouldBe) { - var needZip64Format = false; - var normalEntriesLength = self.entries.length; - if (self.forceZip64Eocd || self.entries.length >= 0xffff) { - normalEntriesLength = 0xffff; - needZip64Format = true; - } - var sizeOfCentralDirectory = self.outputStreamCursor - self.offsetOfStartOfCentralDirectory; - var normalSizeOfCentralDirectory = sizeOfCentralDirectory; - if (self.forceZip64Eocd || sizeOfCentralDirectory >= 0xffffffff) { - normalSizeOfCentralDirectory = 0xffffffff; - needZip64Format = true; - } - var normalOffsetOfStartOfCentralDirectory = self.offsetOfStartOfCentralDirectory; - if (self.forceZip64Eocd || self.offsetOfStartOfCentralDirectory >= 0xffffffff) { - normalOffsetOfStartOfCentralDirectory = 0xffffffff; - needZip64Format = true; - } - if (actuallyJustTellMeHowLongItWouldBe) { - if (needZip64Format) { - return ( - ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + - ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE + - END_OF_CENTRAL_DIRECTORY_RECORD_SIZE - ); - } else { - return END_OF_CENTRAL_DIRECTORY_RECORD_SIZE; - } - } - - var eocdrBuffer = new Buffer(END_OF_CENTRAL_DIRECTORY_RECORD_SIZE); - // end of central dir signature 4 bytes (0x06054b50) - eocdrBuffer.writeUInt32LE(0x06054b50, 0); - // number of this disk 2 bytes - eocdrBuffer.writeUInt16LE(0, 4); - // number of the disk with the start of the central directory 2 bytes - eocdrBuffer.writeUInt16LE(0, 6); - // total number of entries in the central directory on this disk 2 bytes - eocdrBuffer.writeUInt16LE(normalEntriesLength, 8); - // total number of entries in the central directory 2 bytes - eocdrBuffer.writeUInt16LE(normalEntriesLength, 10); - // size of the central directory 4 bytes - eocdrBuffer.writeUInt32LE(normalSizeOfCentralDirectory, 12); - // offset of start of central directory with respect to the starting disk number 4 bytes - eocdrBuffer.writeUInt32LE(normalOffsetOfStartOfCentralDirectory, 16); - // .ZIP file comment length 2 bytes - eocdrBuffer.writeUInt16LE(0, 20); - // .ZIP file comment (variable size) - // no comment - - if (!needZip64Format) return eocdrBuffer; - - // ZIP64 format - // ZIP64 End of Central Directory Record - var zip64EocdrBuffer = new Buffer(ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE); - // zip64 end of central dir signature 4 bytes (0x06064b50) - zip64EocdrBuffer.writeUInt32LE(0x06064b50, 0); - // size of zip64 end of central directory record 8 bytes - writeUInt64LE(zip64EocdrBuffer, ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE - 12, 4); - // version made by 2 bytes - zip64EocdrBuffer.writeUInt16LE(VERSION_MADE_BY, 12); - // version needed to extract 2 bytes - zip64EocdrBuffer.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT_ZIP64, 14); - // number of this disk 4 bytes - zip64EocdrBuffer.writeUInt32LE(0, 16); - // number of the disk with the start of the central directory 4 bytes - zip64EocdrBuffer.writeUInt32LE(0, 20); - // total number of entries in the central directory on this disk 8 bytes - writeUInt64LE(zip64EocdrBuffer, self.entries.length, 24); - // total number of entries in the central directory 8 bytes - writeUInt64LE(zip64EocdrBuffer, self.entries.length, 32); - // size of the central directory 8 bytes - writeUInt64LE(zip64EocdrBuffer, sizeOfCentralDirectory, 40); - // offset of start of central directory with respect to the starting disk number 8 bytes - writeUInt64LE(zip64EocdrBuffer, self.offsetOfStartOfCentralDirectory, 48); - // zip64 extensible data sector (variable size) - // nothing in the zip64 extensible data sector - - - // ZIP64 End of Central Directory Locator - var zip64EocdlBuffer = new Buffer(ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE); - // zip64 end of central dir locator signature 4 bytes (0x07064b50) - zip64EocdlBuffer.writeUInt32LE(0x07064b50, 0); - // number of the disk with the start of the zip64 end of central directory 4 bytes - zip64EocdlBuffer.writeUInt32LE(0, 4); - // relative offset of the zip64 end of central directory record 8 bytes - writeUInt64LE(zip64EocdlBuffer, self.outputStreamCursor, 8); - // total number of disks 4 bytes - zip64EocdlBuffer.writeUInt32LE(1, 16); - - - return Buffer.concat([ - zip64EocdrBuffer, - zip64EocdlBuffer, - eocdrBuffer, - ]); -} - -function validateMetadataPath(metadataPath, isDirectory) { - if (metadataPath === "") throw new Error("empty metadataPath"); - metadataPath = metadataPath.replace(/\\/g, "/"); - if (/^[a-zA-Z]:/.test(metadataPath) || /^\//.test(metadataPath)) throw new Error("absolute path: " + metadataPath); - if (metadataPath.split("/").indexOf("..") !== -1) throw new Error("invalid relative path: " + metadataPath); - var looksLikeDirectory = /\/$/.test(metadataPath); - if (isDirectory) { - // append a trailing '/' if necessary. - if (!looksLikeDirectory) metadataPath += "/"; - } else { - if (looksLikeDirectory) throw new Error("file path cannot end with '/': " + metadataPath); - } - return metadataPath; -} - -var defaultFileMode = parseInt("0100664", 8); -var defaultDirectoryMode = parseInt("040775", 8); - -// this class is not part of the public API -function Entry(metadataPath, isDirectory, options) { - this.utf8FileName = new Buffer(metadataPath); - if (this.utf8FileName.length > 0xffff) throw new Error("utf8 file name too long. " + utf8FileName.length + " > " + 0xffff); - this.isDirectory = isDirectory; - this.state = Entry.WAITING_FOR_METADATA; - this.setLastModDate(options.mtime != null ? options.mtime : new Date()); - if (options.mode != null) { - this.setFileAttributesMode(options.mode); - } else { - this.setFileAttributesMode(isDirectory ? defaultDirectoryMode : defaultFileMode); - } - if (isDirectory) { - this.crcAndFileSizeKnown = true; - this.crc32 = 0; - this.uncompressedSize = 0; - this.compressedSize = 0; - } else { - // unknown so far - this.crcAndFileSizeKnown = false; - this.crc32 = null; - this.uncompressedSize = null; - this.compressedSize = null; - if (options.size != null) this.uncompressedSize = options.size; - } - if (isDirectory) { - this.compress = false; - } else { - this.compress = true; // default - if (options.compress != null) this.compress = !!options.compress; - } - this.forceZip64Format = !!options.forceZip64Format; -} -Entry.WAITING_FOR_METADATA = 0; -Entry.READY_TO_PUMP_FILE_DATA = 1; -Entry.FILE_DATA_IN_PROGRESS = 2; -Entry.FILE_DATA_DONE = 3; -Entry.prototype.setLastModDate = function(date) { - var dosDateTime = dateToDosDateTime(date); - this.lastModFileTime = dosDateTime.time; - this.lastModFileDate = dosDateTime.date; -}; -Entry.prototype.setFileAttributesMode = function(mode) { - if ((mode & 0xffff) !== mode) throw new Error("invalid mode. expected: 0 <= " + mode + " <= " + 0xffff); - // http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute/14727#14727 - this.externalFileAttributes = (mode << 16) >>> 0; -}; -// doFileDataPump() should not call pumpEntries() directly. see issue #9. -Entry.prototype.setFileDataPumpFunction = function(doFileDataPump) { - this.doFileDataPump = doFileDataPump; - this.state = Entry.READY_TO_PUMP_FILE_DATA; -}; -Entry.prototype.useZip64Format = function() { - return ( - (this.forceZip64Format) || - (this.uncompressedSize != null && this.uncompressedSize > 0xfffffffe) || - (this.compressedSize != null && this.compressedSize > 0xfffffffe) || - (this.relativeOffsetOfLocalHeader != null && this.relativeOffsetOfLocalHeader > 0xfffffffe) - ); -} -var LOCAL_FILE_HEADER_FIXED_SIZE = 30; -var VERSION_NEEDED_TO_EXTRACT_UTF8 = 20; -var VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45; -// 3 = unix. 63 = spec version 6.3 -var VERSION_MADE_BY = (3 << 8) | 63; -var FILE_NAME_IS_UTF8 = 1 << 11; -var UNKNOWN_CRC32_AND_FILE_SIZES = 1 << 3; -Entry.prototype.getLocalFileHeader = function() { - var crc32 = 0; - var compressedSize = 0; - var uncompressedSize = 0; - if (this.crcAndFileSizeKnown) { - crc32 = this.crc32; - compressedSize = this.compressedSize; - uncompressedSize = this.uncompressedSize; - } - - var fixedSizeStuff = new Buffer(LOCAL_FILE_HEADER_FIXED_SIZE); - var generalPurposeBitFlag = FILE_NAME_IS_UTF8; - if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES; - - // local file header signature 4 bytes (0x04034b50) - fixedSizeStuff.writeUInt32LE(0x04034b50, 0); - // version needed to extract 2 bytes - fixedSizeStuff.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT_UTF8, 4); - // general purpose bit flag 2 bytes - fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 6); - // compression method 2 bytes - fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 8); - // last mod file time 2 bytes - fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 10); - // last mod file date 2 bytes - fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 12); - // crc-32 4 bytes - fixedSizeStuff.writeUInt32LE(crc32, 14); - // compressed size 4 bytes - fixedSizeStuff.writeUInt32LE(compressedSize, 18); - // uncompressed size 4 bytes - fixedSizeStuff.writeUInt32LE(uncompressedSize, 22); - // file name length 2 bytes - fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 26); - // extra field length 2 bytes - fixedSizeStuff.writeUInt16LE(0, 28); - return Buffer.concat([ - fixedSizeStuff, - // file name (variable size) - this.utf8FileName, - // extra field (variable size) - // no extra fields - ]); -}; -var DATA_DESCRIPTOR_SIZE = 16; -var ZIP64_DATA_DESCRIPTOR_SIZE = 24; -Entry.prototype.getDataDescriptor = function() { - if (this.crcAndFileSizeKnown) { - // the Mac Archive Utility requires this not be present unless we set general purpose bit 3 - return new Buffer(0); - } - if (!this.useZip64Format()) { - var buffer = new Buffer(DATA_DESCRIPTOR_SIZE); - // optional signature (required according to Archive Utility) - buffer.writeUInt32LE(0x08074b50, 0); - // crc-32 4 bytes - buffer.writeUInt32LE(this.crc32, 4); - // compressed size 4 bytes - buffer.writeUInt32LE(this.compressedSize, 8); - // uncompressed size 4 bytes - buffer.writeUInt32LE(this.uncompressedSize, 12); - return buffer; - } else { - // ZIP64 format - var buffer = new Buffer(ZIP64_DATA_DESCRIPTOR_SIZE); - // optional signature (unknown if anyone cares about this) - buffer.writeUInt32LE(0x08074b50, 0); - // crc-32 4 bytes - buffer.writeUInt32LE(this.crc32, 4); - // compressed size 8 bytes - writeUInt64LE(buffer, this.compressedSize, 8); - // uncompressed size 8 bytes - writeUInt64LE(buffer, this.uncompressedSize, 16); - return buffer; - } -}; -var CENTRAL_DIRECTORY_RECORD_FIXED_SIZE = 46; -var ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE = 28; -Entry.prototype.getCentralDirectoryRecord = function() { - var fixedSizeStuff = new Buffer(CENTRAL_DIRECTORY_RECORD_FIXED_SIZE); - var generalPurposeBitFlag = FILE_NAME_IS_UTF8; - if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES; - - var normalCompressedSize = this.compressedSize; - var normalUncompressedSize = this.uncompressedSize; - var normalRelativeOffsetOfLocalHeader = this.relativeOffsetOfLocalHeader; - var versionNeededToExtract; - var zeiefBuffer; - if (this.useZip64Format()) { - normalCompressedSize = 0xffffffff; - normalUncompressedSize = 0xffffffff; - normalRelativeOffsetOfLocalHeader = 0xffffffff; - versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_ZIP64; - - // ZIP64 extended information extra field - zeiefBuffer = new Buffer(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE); - // 0x0001 2 bytes Tag for this "extra" block type - zeiefBuffer.writeUInt16LE(0x0001, 0); - // Size 2 bytes Size of this "extra" block - zeiefBuffer.writeUInt16LE(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE - 4, 2); - // Original Size 8 bytes Original uncompressed file size - writeUInt64LE(zeiefBuffer, this.uncompressedSize, 4); - // Compressed Size 8 bytes Size of compressed data - writeUInt64LE(zeiefBuffer, this.compressedSize, 12); - // Relative Header Offset 8 bytes Offset of local header record - writeUInt64LE(zeiefBuffer, this.relativeOffsetOfLocalHeader, 20); - // Disk Start Number 4 bytes Number of the disk on which this file starts - // (omit) - } else { - versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_UTF8; - zeiefBuffer = new Buffer(0); - } - - // central file header signature 4 bytes (0x02014b50) - fixedSizeStuff.writeUInt32LE(0x02014b50, 0); - // version made by 2 bytes - fixedSizeStuff.writeUInt16LE(VERSION_MADE_BY, 4); - // version needed to extract 2 bytes - fixedSizeStuff.writeUInt16LE(versionNeededToExtract, 6); - // general purpose bit flag 2 bytes - fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 8); - // compression method 2 bytes - fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 10); - // last mod file time 2 bytes - fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 12); - // last mod file date 2 bytes - fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 14); - // crc-32 4 bytes - fixedSizeStuff.writeUInt32LE(this.crc32, 16); - // compressed size 4 bytes - fixedSizeStuff.writeUInt32LE(normalCompressedSize, 20); - // uncompressed size 4 bytes - fixedSizeStuff.writeUInt32LE(normalUncompressedSize, 24); - // file name length 2 bytes - fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 28); - // extra field length 2 bytes - fixedSizeStuff.writeUInt16LE(zeiefBuffer.length, 30); - // file comment length 2 bytes - fixedSizeStuff.writeUInt16LE(0, 32); - // disk number start 2 bytes - fixedSizeStuff.writeUInt16LE(0, 34); - // internal file attributes 2 bytes - fixedSizeStuff.writeUInt16LE(0, 36); - // external file attributes 4 bytes - fixedSizeStuff.writeUInt32LE(this.externalFileAttributes, 38); - // relative offset of local header 4 bytes - fixedSizeStuff.writeUInt32LE(normalRelativeOffsetOfLocalHeader, 42); - - return Buffer.concat([ - fixedSizeStuff, - // file name (variable size) - this.utf8FileName, - // extra field (variable size) - zeiefBuffer, - // file comment (variable size) - // empty comment - ]); -}; -Entry.prototype.getCompressionMethod = function() { - var NO_COMPRESSION = 0; - var DEFLATE_COMPRESSION = 8; - return this.compress ? DEFLATE_COMPRESSION : NO_COMPRESSION; -}; - -function dateToDosDateTime(jsDate) { - var date = 0; - date |= jsDate.getDate() & 0x1f; // 1-31 - date |= ((jsDate.getMonth() + 1) & 0xf) << 5; // 0-11, 1-12 - date |= ((jsDate.getFullYear() - 1980) & 0x7f) << 9; // 0-128, 1980-2108 - - var time = 0; - time |= Math.floor(jsDate.getSeconds() / 2); // 0-59, 0-29 (lose odd numbers) - time |= (jsDate.getMinutes() & 0x3f) << 5; // 0-59 - time |= (jsDate.getHours() & 0x1f) << 11; // 0-23 - - return {date: date, time: time}; -} - -function writeUInt64LE(buffer, n, offset) { - // can't use bitshift here, because JavaScript only allows bitshiting on 32-bit integers. - var high = Math.floor(n / 0x100000000); - var low = n % 0x100000000; - buffer.writeUInt32LE(low, offset); - buffer.writeUInt32LE(high, offset + 4); -} - -function defaultCallback(err) { - if (err) throw err; -} - -util.inherits(ByteCounter, Transform); -function ByteCounter(options) { - Transform.call(this, options); - this.byteCount = 0; -} -ByteCounter.prototype._transform = function(chunk, encoding, cb) { - this.byteCount += chunk.length; - cb(null, chunk); -}; - -util.inherits(Crc32Watcher, Transform); -function Crc32Watcher(options) { - Transform.call(this, options); - this.crc32 = 0; -} -Crc32Watcher.prototype._transform = function(chunk, encoding, cb) { - this.crc32 = crc32.unsigned(chunk, this.crc32); - cb(null, chunk); -}; |