pax_global_header00006660000000000000000000000064124201267130014510gustar00rootroot0000000000000052 comment=00456a617df26b97ea58def96d2c720db23eaeb4 node-yazl-2.0.2/000077500000000000000000000000001242012671300134135ustar00rootroot00000000000000node-yazl-2.0.2/.gitignore000066400000000000000000000000161242012671300154000ustar00rootroot00000000000000node_modules/ node-yazl-2.0.2/.npmignore000066400000000000000000000000061242012671300154060ustar00rootroot00000000000000test/ node-yazl-2.0.2/LICENSE000066400000000000000000000020651242012671300144230ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Josh Wolfe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-yazl-2.0.2/README.md000066400000000000000000000202061242012671300146720ustar00rootroot00000000000000# yazl yet another zip library for node Design principles: * Don't block the JavaScript thread. Use and provide async APIs. * Keep memory usage under control. Don't attempt to buffer entire files in RAM at once. * Prefer to open input files one at a time than all at once. This is slightly suboptimal for time performance, but avoids OS-imposed limits on the number of simultaneously open file handles. ## Usage ```js var yazl = require("yazl"); var zipfile = new yazl.ZipFile(); zipfile.addFile("file1.txt", "file1.txt"); // (add only files, not directories) zipfile.addFile("path/to/file.txt", "path/in/zipfile.txt"); // pipe() can be called any time after the constructor zipfile.outputStream.pipe(fs.createWriteStream("output.zip")).on("close", function() { console.log("done"); }); // alternate apis for adding files: zipfile.addReadStream(process.stdin, "stdin.txt", { mtime: new Date(), mode: 0100664, // -rw-rw-r-- }); zipfile.addBuffer(new Buffer("hello"), "hello.txt", { mtime: new Date(), mode: 0100664, // -rw-rw-r-- }); // call end() after all the files have been added zipfile.end(); ``` ## API ### Class: ZipFile #### new ZipFile() No parameters. Nothing can go wrong. #### addFile(realPath, metadataPath, [options]) Adds a file from the file system at `realPath` into the zipfile as `metadataPath`. Typically `metadataPath` would be calculated as `path.relative(root, realPath)`. Unzip programs would extract the file from the zipfile as `metadataPath`. `realPath` is not stored in the zipfile. This function throws an error if `metadataPath` starts with `"/"` or `/[A-Za-z]:\//` or if it contains `".."` path segments or `"\\"`. These would be illegal file names according to the spec. `options` may be omitted or null has the following structure and default values: ```js { mtime: stats.mtime, // optional mode: stats.mode, // optional compress: true, // optional } ``` Use `options.mtime` and/or `options.mode` to override the values that would normally be obtained by the `fs.Stats` for the `realPath`. The mtime and mode (unix permission bits and file type) are stored in the zip file in the fields "last mod file time", "last mod file date", and "external file attributes". yazl does not store group and user ids in the zip file. Internally, `fs.stat()` is called immediately in the `addFile` function, and `fs.createReadStream()` is used later when the file data is actually required. Throughout adding and encoding `n` files with `addFile()`, the number of simultaneous open files is `O(1)`, probably just 1 at a time. #### addReadStream(readStream, metadataPath, options) Adds a file to the zip file whose content is read from `readStream`. See `addFile()` for info about the `metadataPath` parameter. `options` is an `Object` and has the following structure: ```js { mtime: new Date(), // required mode: 0100664, // required compress: true, // optional (default true) size: 12345, // optional } ``` See `addFile()` for the meaning of `mtime` and `mode`. If `size` is given, it will be checked against the actual number of bytes in the `readStream`, and an error will be emitted if there is a mismatch. #### addBuffer(buffer, metadataPath, options) Adds a file to the zip file whose content is `buffer`. See `addFile()` for info about the `metadataPath` parameter. `options` is an `Object` and has the following structure: ```js { mtime: new Date(), // required mode: 0100664, // required compress: true, // optional (default true) } ``` See `addFile()` for the meaning of `mtime` and `mode`. #### end([finalSizeCallback]) Indicates that no more files will be added via `addFile()`, `addReadStream()`, or `addBuffer()`. Some time after calling this function, `outputStream` will be ended. If specified and non-null, `finalSizeCallback` is given the parameters `(finalSize)` sometime during or after the call to `end()`. `finalSize` is of type `Number` and can either be `-1` or the guaranteed eventual size in bytes of the output data that can be read from `outputStream`. If `finalSize` is `-1`, it means means the final size is too hard to guess before processing the input file data. This will happen if and only if the `compress` option is `true` on any call to `addFile()`, `addReadStream()`, or `addBuffer()`, or if `addReadStream()` is called and the optional `size` option is not given. In other words, clients should know whether they're going to get a `-1` or a real value by looking at how they are calling this function. The call to `finalSizeCallback` might be delayed if yazl is still waiting for `fs.Stats` for an `addFile()` entry. If `addFile()` was never called, `finalSizeCallback` will be called during the call to `end()`. It is not required to start piping data from `outputStream` before `finalSizeCallback` is called. `finalSizeCallback` will be called only once, and only if this is the first call to `end()`. #### outputStream A readable stream that will produce the contents of the zip file. It is typical to pipe this stream to a writable stream created from `fs.createWriteStream()`. Internally, large amounts of file data are piped to `outputStream` using `pipe()`, which means throttling happens appropriately when this stream is piped to a slow destination. Data becomes available in this stream soon after calling one of `addFile()`, `addReadStream()`, or `addBuffer()`. Clients can call `pipe()` on this stream at any time, such as immediately after getting a new `ZipFile` instance, or long after calling `end()`. ### dateToDosDateTime(jsDate) `jsDate` is a `Date` instance. Returns `{date: date, time: time}`, where `date` and `time` are unsigned 16-bit integers. ## Output Structure The Zip File Spec leaves a lot of flexibility up to the zip file creator. This section explains and justifies yazl's interpretation and decisions regarding this flexibility. This section is probably not useful to yazl clients, but may be interesting to unzip implementors and zip file enthusiasts. ### Disk Numbers All values related to disk numbers are `0`, because yazl has no multi-disk archive support. ### Version Made By Always `0x031e`. This is the value reported by a Linux build of Info-Zip. Instead of experimenting with different values of this field to see how different unzip clients would behave, yazl mimics Info-Zip, which should work everywhere. Note that the top byte means "UNIX" and has implications in the External File Attributes. ### Version Needed to Extract Always `0x0014`. Without this value, Info-Zip, and possibly other unzip implementations, refuse to acknowledge General Purpose Bit `8`, which enables utf8 filename encoding. ### General Purpose Bit Flag Bit `8` is always set. Filenames are always encoded in utf8, even if the result is indistinguishable from ascii. Bit `3` is set in the Local File Header. To support both a streaming input and streaming output api, it is impossible to know the crc32 before processing the file data. File Descriptors are given after each file data with this information, as per the spec. But remember a complete metadata listing is still always available in the central directory record, so if unzip implementations are relying on that, like they should, none of this paragraph will matter anyway. Even so, Mac's Archive Utility requires File Descriptors to include the optional signature, so yazl includes the optional file descriptor signature. All other bits are unset. ### Internal File Attributes Always `0`. The "apparently an ASCII or text file" bit is always unset meaning "apparently binary". This kind of determination is outside the scope of yazl, and is probably not significant in any modern unzip implementation. ### External File Attributes Always `stats.mode << 16`. This is apparently the convention for "version made by" = `0x03xx` (UNIX). ### Directory Entries yazl does not record directories themselves as separate entries in the zipfile metadata. Instead, file entries with paths (such as "directory/file.txt") imply the need for their parent directories. Unzip clients seems to respect this style of pathing, and the zip file spec does not specify what is standard in this regard. Directory entries would be required to archive empty directories (see issue #4). node-yazl-2.0.2/index.js000066400000000000000000000377001242012671300150670ustar00rootroot00000000000000var 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; } ZipFile.prototype.addFile = function(realPath, metadataPath, options) { var self = this; validateMetadataPath(metadataPath); if (options == null) options = {}; var entry = new Entry(metadataPath, 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 (entry.lastModFileTime == null || entry.lastModFileDate == null) entry.setLastModDate(stats.mtime); if (entry.externalFileAttributes == 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; validateMetadataPath(metadataPath); if (options == null) options = {}; var entry = new Entry(metadataPath, options); validateFilelessEntryProperties(entry); self.entries.push(entry); entry.setFileDataPumpFunction(function() { entry.state = Entry.FILE_DATA_IN_PROGRESS; pumpFileDataReadStream(self, entry, readStream); pumpEntries(self); }); pumpEntries(self); }; ZipFile.prototype.addBuffer = function(buffer, metadataPath, options) { var self = this; validateMetadataPath(metadataPath); if (options == null) options = {}; var entry = new Entry(metadataPath, options); validateFilelessEntryProperties(entry, buffer.length); entry.uncompressedSize = buffer.length; entry.crc32 = crc32.unsigned(buffer); 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.getFileDescriptor()); entry.state = Entry.FILE_DATA_DONE; pumpEntries(self); }); pumpEntries(self); } }; ZipFile.prototype.end = function(finalSizeCallback) { if (this.ended) return; this.ended = true; this.finalSizeCallback = finalSizeCallback; 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.getFileDescriptor()); entry.state = Entry.FILE_DATA_DONE; pumpEntries(self); }); } function pumpEntries(self) { // 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(); } } } function calculateFinalSize(self) { var result = 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; } result += LOCAL_FILE_HEADER_FIXED_SIZE + entry.utf8FileName.length + entry.uncompressedSize + FILE_DESCRIPTOR_SIZE + CENTRAL_DIRECTORY_RECORD_FIXED_SIZE + entry.utf8FileName.length; } result += END_OF_CENTRAL_DIRECTORY_RECORD_SIZE; return result; } var END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 22; function getEndOfCentralDirectoryRecord(self) { var buffer = new Buffer(END_OF_CENTRAL_DIRECTORY_RECORD_SIZE); buffer.writeUInt32LE(0x06054b50, 0); // end of central dir signature 4 bytes (0x06054b50) buffer.writeUInt16LE(0, 4); // number of this disk 2 bytes buffer.writeUInt16LE(0, 6); // number of the disk with the start of the central directory 2 bytes buffer.writeUInt16LE(self.entries.length, 8); // total number of entries in the central directory on this disk 2 bytes buffer.writeUInt16LE(self.entries.length, 10); // total number of entries in the central directory 2 bytes buffer.writeUInt32LE(self.outputStreamCursor - self.offsetOfStartOfCentralDirectory, 12); // size of the central directory 4 bytes buffer.writeUInt32LE(self.offsetOfStartOfCentralDirectory, 16); // offset of start of central directory with respect to the starting disk number 4 bytes buffer.writeUInt16LE(0, 20); // .ZIP file comment length 2 bytes /* no comment */ // .ZIP file comment (variable size) return buffer; } function validateMetadataPath(metadataPath) { if (metadataPath.indexOf("\\") !== -1) throw new Error("invalid characters in path: " + metadataPath); 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); } function validateFilelessEntryProperties(entry, length) { if (entry.lastModFileTime == null || entry.lastModFileDate == null) throw new Error("missing options.mtime"); if (entry.externalFileAttributes == null) throw new Error("missing options.mode"); if (entry.uncompressedSize != null && length != null && entry.uncompressedSize !== length) throw new Error("invalid options.size"); } // this class is not part of the public API function Entry(metadataPath, options) { this.utf8FileName = new Buffer(metadataPath); if (this.utf8FileName.length > 0xffff) throw new Error("utf8 file name too long. " + utf8FileName.length + " > " + 0xffff); this.state = Entry.WAITING_FOR_METADATA; if (options.mtime != null) this.setLastModDate(options.mtime); if (options.mode != null) this.setFileAttributesMode(options.mode); this.uncompressedSize = null; // unknown if (options.size != null) this.uncompressedSize = options.size; this.compress = true; // default if (options.compress != null) this.compress = !!options.compress; } 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; }; Entry.prototype.setFileDataPumpFunction = function(doFileDataPump) { this.doFileDataPump = doFileDataPump; this.state = Entry.READY_TO_PUMP_FILE_DATA; }; var LOCAL_FILE_HEADER_FIXED_SIZE = 30; // this version enables utf8 filename encoding var VERSION_NEEDED_TO_EXTRACT = 0x0014; // this is the "version made by" reported by linux info-zip. var VERSION_MADE_BY_INFO_ZIP = 0x031e; var FILE_NAME_IS_UTF8 = 1 << 11; var UNKNOWN_CRC32_AND_FILE_SIZES = 1 << 3; Entry.prototype.getLocalFileHeader = function() { var fixedSizeStuff = new Buffer(LOCAL_FILE_HEADER_FIXED_SIZE); var generalPurposeBitFlag = UNKNOWN_CRC32_AND_FILE_SIZES | FILE_NAME_IS_UTF8; fixedSizeStuff.writeUInt32LE(0x04034b50, 0); // local file header signature 4 bytes (0x04034b50) fixedSizeStuff.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT, 4); // version needed to extract 2 bytes fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 6); // general purpose bit flag 2 bytes fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 8); // compression method 2 bytes fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 10); // last mod file time 2 bytes fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 12); // last mod file date 2 bytes fixedSizeStuff.writeUInt32LE(0, 14); // crc-32 4 bytes fixedSizeStuff.writeUInt32LE(0, 18); // compressed size 4 bytes fixedSizeStuff.writeUInt32LE(0, 22); // uncompressed size 4 bytes fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 26); // file name length 2 bytes fixedSizeStuff.writeUInt16LE(0, 28); // extra field length 2 bytes return Buffer.concat([ fixedSizeStuff, this.utf8FileName, // file name (variable size) /* no extra fields */ // extra field (variable size) ]); }; var FILE_DESCRIPTOR_SIZE = 16 Entry.prototype.getFileDescriptor = function() { var buffer = new Buffer(FILE_DESCRIPTOR_SIZE); buffer.writeUInt32LE(0x08074b50, 0); // optional signature (required according to Archive Utility) buffer.writeUInt32LE(this.crc32, 4); // crc-32 4 bytes buffer.writeUInt32LE(this.compressedSize, 8); // compressed size 4 bytes buffer.writeUInt32LE(this.uncompressedSize, 12); // uncompressed size 4 bytes return buffer; }; var CENTRAL_DIRECTORY_RECORD_FIXED_SIZE = 46; Entry.prototype.getCentralDirectoryRecord = function() { var fixedSizeStuff = new Buffer(CENTRAL_DIRECTORY_RECORD_FIXED_SIZE); fixedSizeStuff.writeUInt32LE(0x02014b50, 0); // central file header signature 4 bytes (0x02014b50) fixedSizeStuff.writeUInt16LE(VERSION_MADE_BY_INFO_ZIP, 4); // version made by 2 bytes fixedSizeStuff.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT, 6); // version needed to extract 2 bytes fixedSizeStuff.writeUInt16LE(FILE_NAME_IS_UTF8, 8); // general purpose bit flag 2 bytes fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 10); // compression method 2 bytes fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 12); // last mod file time 2 bytes fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 14); // last mod file date 2 bytes fixedSizeStuff.writeUInt32LE(this.crc32, 16); // crc-32 4 bytes fixedSizeStuff.writeUInt32LE(this.compressedSize, 20); // compressed size 4 bytes fixedSizeStuff.writeUInt32LE(this.uncompressedSize, 24); // uncompressed size 4 bytes fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 28); // file name length 2 bytes fixedSizeStuff.writeUInt16LE(0, 30); // extra field length 2 bytes fixedSizeStuff.writeUInt16LE(0, 32); // file comment length 2 bytes fixedSizeStuff.writeUInt16LE(0, 34); // disk number start 2 bytes fixedSizeStuff.writeUInt16LE(0, 36); // internal file attributes 2 bytes fixedSizeStuff.writeUInt32LE(this.externalFileAttributes, 38); // external file attributes 4 bytes fixedSizeStuff.writeUInt32LE(this.relativeOffsetOfLocalHeader, 42); // relative offset of local header 4 bytes return Buffer.concat([ fixedSizeStuff, this.utf8FileName, // file name (variable size) /* no extra fields */ // extra field (variable size) /* empty comment */ // file comment (variable size) ]); }; 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 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); }; node-yazl-2.0.2/package.json000066400000000000000000000011541242012671300157020ustar00rootroot00000000000000{ "name": "yazl", "version": "2.0.2", "description": "yet another zip library for node", "main": "index.js", "scripts": { "test": "node test/test.js" }, "repository": { "type": "git", "url": "https://github.com/thejoshwolfe/yazl.git" }, "keywords": [ "zip" ], "author": "Josh Wolfe ", "license": "MIT", "bugs": { "url": "https://github.com/thejoshwolfe/yazl/issues" }, "homepage": "https://github.com/thejoshwolfe/yazl", "dependencies": { "buffer-crc32": "~0.2.3" }, "devDependencies": { "bl": "~0.9.3", "yauzl": "~2.0.0" } } node-yazl-2.0.2/test/000077500000000000000000000000001242012671300143725ustar00rootroot00000000000000node-yazl-2.0.2/test/test.js000066400000000000000000000042361242012671300157140ustar00rootroot00000000000000var fs = require("fs"); var yazl = require("../"); var yauzl = require("yauzl"); var BufferList = require("bl"); (function() { var fileMetadata = { mtime: new Date(), mode: 0100664, }; var zipfile = new yazl.ZipFile(); zipfile.addFile(__filename, "unicōde.txt"); zipfile.addFile(__filename, "without-compression.txt", {compress: false}); zipfile.addReadStream(fs.createReadStream(__filename), "readStream.txt", fileMetadata); var expectedContents = fs.readFileSync(__filename); zipfile.addBuffer(expectedContents, "with/directories.txt", fileMetadata); zipfile.end(function(finalSize) { if (finalSize !== -1) throw new Error("finalSize is impossible to know before compression"); zipfile.outputStream.pipe(new BufferList(function(err, data) { if (err) throw err; yauzl.fromBuffer(data, function(err, zipfile) { if (err) throw err; zipfile.on("entry", function(entry) { zipfile.openReadStream(entry, function(err, readStream) { if (err) throw err; readStream.pipe(new BufferList(function(err, data) { if (err) throw err; if (expectedContents.toString("binary") !== data.toString("binary")) throw new Error("unexpected contents"); console.log(entry.fileName + ": pass"); })); }); }); }); })); }); })(); (function() { var fileMetadata = { mtime: new Date(), mode: 0100664, compress: false, }; var zipfile = new yazl.ZipFile(); zipfile.addFile(__filename, "asdf.txt", {compress: false}); zipfile.addFile(__filename, "fdsa.txt", {compress: false}); zipfile.addBuffer(new Buffer("buffer"), "buffer.txt", fileMetadata); fileMetadata.size = "stream".length; zipfile.addReadStream(new BufferList().append("stream"), "stream.txt", fileMetadata); zipfile.end(function(finalSize) { if (finalSize === -1) throw new Error("finalSize should be known"); zipfile.outputStream.pipe(new BufferList(function(err, data) { if (data.length !== finalSize) throw new Error("finalSize prediction is wrong. " + finalSize + " !== " + data.length); console.log("finalSize: pass"); })); }); })(); node-yazl-2.0.2/test/zip.js000066400000000000000000000015021242012671300155300ustar00rootroot00000000000000var usage = "node " + __filename.replace(/.*[\/\\]/, "") + " " + "[FILE | --compress | --no-compress]... -o OUTPUT.zip"; var yazl = require("../"); var fs = require("fs"); var zipfile = new yazl.ZipFile(); var options = {compress: false}; var args = process.argv.slice(2); if (Math.max(args.indexOf("-h"), args.indexOf("--help")) !== -1) throw new Error("usage: " + usage); var outputFileIndex = args.indexOf("-o"); if (outputFileIndex === -1) throw new Error("missing -o"); zipfile.outputStream.pipe(fs.createWriteStream(args[outputFileIndex + 1])); args.splice(outputFileIndex, 2); args.forEach(function(arg) { if (/--compress/.test(arg)) { options.compress = true; } else if (/--no-compress/.test(arg)) { options.compress = false; } else { zipfile.addFile(arg, arg, options); } }); zipfile.end();