pax_global_header00006660000000000000000000000064124201276270014515gustar00rootroot0000000000000052 comment=7c2c9619ce12370a4496965465c650c582bf6fab node-yauzl-2.1.0/000077500000000000000000000000001242012762700136045ustar00rootroot00000000000000node-yauzl-2.1.0/.gitignore000066400000000000000000000000161242012762700155710ustar00rootroot00000000000000node_modules/ node-yauzl-2.1.0/.npmignore000066400000000000000000000000061242012762700155770ustar00rootroot00000000000000test/ node-yauzl-2.1.0/LICENSE000066400000000000000000000020651242012762700146140ustar00rootroot00000000000000The 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-yauzl-2.1.0/README.md000066400000000000000000000215721242012762700150720ustar00rootroot00000000000000# yauzl yet another unzip library for node. For zipping, see [yazl](https://github.com/thejoshwolfe/yazl). Design principles: * Follow the spec. Don't scan for local file headers. Read the central directory for file metadata. * 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. * Never crash (if used properly). Don't let malformed zip files bring down client applications who are trying to catch errors. * Catch unsafe filenames entries. A zip file entry throws an error if its file name starts with `"/"` or `/[A-Za-z]:\//` or if it contains `".."` path segments or `"\\"` (per the spec). ## Usage ```js var yauzl = require("yauzl"); var fs = require("fs"); yauzl.open("path/to/file.zip", function(err, zipfile) { if (err) throw err; zipfile.on("entry", function(entry) { if (/\/$/.test(entry.fileName)) { // directory file names end with '/' return; } zipfile.openReadStream(entry, function(err, readStream) { if (err) throw err; // ensure parent directory exists, and then: readStream.pipe(fs.createWriteStream(entry.fileName)); }); }); }); ``` ## API The default for every `callback` parameter is: ```js function defaultCallback(err) { if (err) throw err; } ``` ### open(path, [options], [callback]) Calls `fs.open(path, "r")` and gives the `fd`, `options`, and `callback` to `fromFd()` below. `options` may be omitted or `null` and defaults to `{autoClose: true}`. ### fromFd(fd, [options], [callback]) Reads from the fd, which is presumed to be an open .zip file. Note that random access is required by the zip file specification, so the fd cannot be an open socket or any other fd that does not support random access. The `callback` is given the arguments `(err, zipfile)`. An `err` is provided if the End of Central Directory Record Signature cannot be found in the file, which indicates that the fd is not a zip file. `zipfile` is an instance of `ZipFile`. `options` may be omitted or `null` and defaults to `{autoClose: false}`. `autoClose` is effectively equivalent to: ```js zipfile.once("end", function() { zipfile.close(); }); ``` ### fromBuffer(buffer, [callback]) Like `fromFd()`, but reads from a RAM buffer instead of an open file. `buffer` is a `Buffer`. `callback` is effectively passed directly to `fromFd()`. If a `ZipFile` is acquired from this method, it will never emit the `close` event, and calling `close()` is not necessary. ### dosDateTimeToDate(date, time) Converts MS-DOS `date` and `time` data into a JavaScript `Date` object. Each parameter is a `Number` treated as an unsigned 16-bit integer. Note that this format does not support timezones, so the returned object will use the local timezone. ### Class: ZipFile The constructor for the class is not part of the public API. Use `open()`, `fromFd()`, or `fromBuffer()` instead. #### Event: "entry" Callback gets `(entry)`, which is an `Entry`. #### Event: "end" Emitted after the last `entry` event has been emitted. #### Event: "close" Emitted after the fd is actually closed. This is after calling `close()` (or after the `end` event when `autoClose` is `true`), and after all streams created from `openReadStream()` have emitted their `end` events. This event is never emitted if this `ZipFile` was acquired from `fromBuffer()`. #### Event: "error" Emitted in the case of errors with reading the zip file. (Note that other errors can be emitted from the streams created from `openReadStream()` as well.) After this event has been emitted, no further `entry`, `end`, or `error` events will be emitted, but the `close` event may still be emitted. #### openReadStream(entry, [callback]) `entry` must be an `Entry` object from this `ZipFile`. `callback` gets `(err, readStream)`, where `readStream` is a `Readable Stream`. If the entry is compressed (with a supported compression method), the read stream provides the decompressed data. If this zipfile is already closed (see `close()`), the `callback` will receive an `err`. #### close() Causes all future calls to `openReadStream()` to fail, and closes the fd after all streams created by `openReadStream()` have emitted their `end` events. If this object's `end` event has not been emitted yet, this function causes undefined behavior. If `autoClose` is `true` in the original `open()` or `fromFd()` call, this function will be called automatically effectively in response to this object's `end` event. #### isOpen `Boolean`. `true` until `close()` is called; then it's `false`. #### entryCount `Number`. Total number of central directory records. #### comment `String`. Always decoded with `CP437` per the spec. ### Class: Entry Objects of this class represent Central Directory Records. Refer to the zipfile specification for more details about these fields. These fields are of type `Number`: * `versionMadeBy` * `versionNeededToExtract` * `generalPurposeBitFlag` * `compressionMethod` * `lastModFileTime` (MS-DOS format, see `getLastModDateTime`) * `lastModFileDate` (MS-DOS format, see `getLastModDateTime`) * `crc32` * `compressedSize` * `uncompressedSize` * `fileNameLength` (bytes) * `extraFieldLength` (bytes) * `fileCommentLength` (bytes) * `internalFileAttributes` * `externalFileAttributes` * `relativeOffsetOfLocalHeader` #### fileName `String`. Following the spec, the bytes for the file name are decoded with `UTF-8` if `generalPurposeBitFlag & 0x800`, otherwise with `CP437`. If `fileName` would contain unsafe characters, such as an absolute path or a relative directory, yauzl emits an error instead of an entry. #### extraFields `Array` with each entry in the form `{id: id, data: data}`, where `id` is a `Number` and `data` is a `Buffer`. None of the extra fields are considered significant by this library. #### comment `String` decoded with the same charset as used for `fileName`. #### getLastModDate() Effectively implemented as: ```js return dosDateTimeToDate(this.lastModFileDate, this.lastModFileTime); ``` ## How to Avoid Crashing When a malformed zipfile is encountered, the default behavior is to crash (throw an exception). If you want to handle errors more gracefully than this, be sure to do the following: * Provide `callback` parameters where they are allowed, and check the `err` parameter. * Attach a listener for the `error` event on any `ZipFile` object you get from `open()`, `fromFd()`, or `fromBuffer()`. * Attach a listener for the `error` event on any stream you get from `openReadStream()`. ## Limitations ### No Multi-Disk Archive Support This library does not support multi-disk zip files. The multi-disk fields in the zipfile spec were intended for a zip file to span multiple floppy disks, which probably never happens now. If the "number of this disk" field in the End of Central Directory Record is not `0`, the `open()`, `fromFd()`, or `fromBuffer()` `callback` will receive an `err`. By extension the following zip file fields are ignored by this library and not provided to clients: * Disk where central directory starts * Number of central directory records on this disk * Disk number where file starts ### No Encryption Support Currently, the presence of encryption is not even checked, and encrypted zip files will cause undefined behavior. ### Local File Headers Are Ignored Many unzip libraries mistakenly read the Local File Header data in zip files. This data is officially defined to be redundant with the Central Directory information, and is not to be trusted. There may be conflicts between the Central Directory information and the Local File Header, but the Local File Header is always ignored. ### No CRC-32 Checking This library provides the `crc32` field of `Entry` objects read from the Central Directory. However, this field is not used for anything in this library. ### versionNeededToExtract Is Ignored The field `versionNeededToExtract` is ignored, because this library doesn't support the complete zip file spec at any version, ### No Support For Obscure Compression Methods Regarding the `compressionMethod` field of `Entry` objects, only method `0` (stored with no compression) and method `8` (deflated) are supported. Any of the other 15 official methods will cause the `openReadStream()` `callback` to receive an `err`. ### No ZIP64 Support A ZIP64 file will probably cause undefined behavior. ### Data Descriptors Are Ignored There may or may not be Data Descriptor sections in a zip file. This library provides no support for finding or interpreting them. ### Archive Extra Data Record Is Ignored There may or may not be an Archive Extra Data Record section in a zip file. This library provides no support for finding or interpreting it. ### No Language Encoding Flag Support Zip files officially support charset encodings other than CP437 and UTF-8, but the zip file spec does not specify how it works. This library makes no attempt to interpret the Language Encoding Flag. node-yauzl-2.1.0/index.js000066400000000000000000000351601242012762700152560ustar00rootroot00000000000000var fs = require("fs"); var zlib = require("zlib"); var FdSlicer = require("fd-slicer"); var util = require("util"); var EventEmitter = require("events").EventEmitter; var PassThrough = require("stream").PassThrough; exports.open = open; exports.fromFd = fromFd; exports.fromBuffer = fromBuffer; exports.ZipFile = ZipFile; exports.Entry = Entry; exports.dosDateTimeToDate = dosDateTimeToDate; // cd - Central Directory // cdr - Central Directory Record // eocdr - End of Central Directory Record function open(path, options, callback) { if (typeof options === "function") { callback = options; options = null; } if (options == null) options = {autoClose: true}; if (callback == null) callback = defaultCallback; fs.open(path, "r", function(err, fd) { if (err) return callback(err); fromFd(fd, options, function(err, zipfile) { if (err) fs.close(fd, defaultCallback); callback(err, zipfile); }); }); } function fromFd(fd, options, callback) { if (typeof options === "function") { callback = options; options = null; } if (options == null) options = {autoClose: false}; if (callback == null) callback = defaultCallback; fs.fstat(fd, function(err, stats) { if (err) return callback(err); var fdSlicer = new FdSlicer(fd, {autoClose: true}); // this ref is unreffed in zipfile.close() fdSlicer.ref(); fromFdSlicer(fdSlicer, stats.size, options, callback); }); } function fromBuffer(buffer, callback) { if (callback == null) callback = defaultCallback; // i got your open file right here. var fdSlicer = new FakeFdSlicer(buffer); fromFdSlicer(fdSlicer, buffer.length, {}, callback); } function fromFdSlicer(fdSlicer, totalSize, options, callback) { // search backwards for the eocdr signature. // the last field of the eocdr is a variable-length comment. // the comment size is encoded in a 2-byte field in the eocdr, which we can't find without trudging backwards through the comment to find it. // as a consequence of this design decision, it's possible to have ambiguous zip file metadata if a coherent eocdr was in the comment. // we search backwards for a eocdr signature, and hope that whoever made the zip file was smart enough to forbid the eocdr signature in the comment. var eocdrWithoutCommentSize = 22; var maxCommentSize = 0x10000; // 2-byte size var bufferSize = Math.min(eocdrWithoutCommentSize + maxCommentSize, totalSize); var buffer = new Buffer(bufferSize); var bufferReadStart = totalSize - buffer.length; readFdSlicerNoEof(fdSlicer, buffer, 0, bufferSize, bufferReadStart, function(err) { if (err) return callback(err); for (var i = bufferSize - eocdrWithoutCommentSize; i >= 0; i -= 1) { if (buffer.readUInt32LE(i) !== 0x06054b50) continue; // found eocdr var eocdrBuffer = buffer.slice(i); // 0 - End of central directory signature = 0x06054b50 // 4 - Number of this disk var diskNumber = eocdrBuffer.readUInt16LE(4); if (diskNumber !== 0) return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber)); // 6 - Disk where central directory starts // 8 - Number of central directory records on this disk // 10 - Total number of central directory records var entryCount = eocdrBuffer.readUInt16LE(10); // 12 - Size of central directory (bytes) // 16 - Offset of start of central directory, relative to start of archive var cdOffset = eocdrBuffer.readUInt32LE(16); // 20 - Comment length var commentLength = eocdrBuffer.readUInt16LE(20); var expectedCommentLength = eocdrBuffer.length - eocdrWithoutCommentSize; if (commentLength !== expectedCommentLength) { return callback(new Error("invalid comment length. expected: " + expectedCommentLength + ". found: " + commentLength)); } // 22 - Comment // the encoding is always cp437. var comment = bufferToString(eocdrBuffer, 22, eocdrBuffer.length, false); return callback(null, new ZipFile(fdSlicer, cdOffset, totalSize, entryCount, comment, options.autoClose)); } callback(new Error("end of central directory record signature not found")); }); } util.inherits(ZipFile, EventEmitter); function ZipFile(fdSlicer, cdOffset, fileSize, entryCount, comment, autoClose) { var self = this; EventEmitter.call(self); self.fdSlicer = fdSlicer; // forward close events self.fdSlicer.on("error", function(err) { // error closing the fd emitError(self, err); }); self.fdSlicer.once("close", function() { self.emit("close"); }); self.readEntryCursor = cdOffset; self.fileSize = fileSize; self.entryCount = entryCount; self.comment = comment; self.entriesRead = 0; self.autoClose = !!autoClose; self.isOpen = true; self.emittedError = false; // make sure events don't fire outta here until the client has a chance to attach listeners setImmediate(function() { readEntries(self); }); } ZipFile.prototype.close = function() { if (!this.isOpen) return; this.isOpen = false; this.fdSlicer.unref(); }; function emitErrorAndAutoClose(self, err) { if (self.autoClose) self.close(); emitError(self, err); } function emitError(self, err) { if (self.emittedError) return; self.emittedError = true; self.emit("error", err); } function readEntries(self) { if (self.entryCount === self.entriesRead) { // done with metadata if (self.autoClose) self.close(); if (self.emittedError) return; return self.emit("end"); } if (self.emittedError) return; var buffer = new Buffer(46); readFdSlicerNoEof(self.fdSlicer, buffer, 0, buffer.length, self.readEntryCursor, function(err) { if (err) return emitErrorAndAutoClose(self, err); if (self.emittedError) return; var entry = new Entry(); // 0 - Central directory file header signature var signature = buffer.readUInt32LE(0); if (signature !== 0x02014b50) return emitErrorAndAutoClose(self, new Error("invalid central directory file header signature: 0x" + signature.toString(16))); // 4 - Version made by entry.versionMadeBy = buffer.readUInt16LE(4); // 6 - Version needed to extract (minimum) entry.versionNeededToExtract = buffer.readUInt16LE(6); // 8 - General purpose bit flag entry.generalPurposeBitFlag = buffer.readUInt16LE(8); // 10 - Compression method entry.compressionMethod = buffer.readUInt16LE(10); // 12 - File last modification time entry.lastModFileTime = buffer.readUInt16LE(12); // 14 - File last modification date entry.lastModFileDate = buffer.readUInt16LE(14); // 16 - CRC-32 entry.crc32 = buffer.readUInt32LE(16); // 20 - Compressed size entry.compressedSize = buffer.readUInt32LE(20); // 24 - Uncompressed size entry.uncompressedSize = buffer.readUInt32LE(24); // 28 - File name length (n) entry.fileNameLength = buffer.readUInt16LE(28); // 30 - Extra field length (m) entry.extraFieldLength = buffer.readUInt16LE(30); // 32 - File comment length (k) entry.fileCommentLength = buffer.readUInt16LE(32); // 34 - Disk number where file starts // 36 - Internal file attributes entry.internalFileAttributes = buffer.readUInt16LE(36); // 38 - External file attributes entry.externalFileAttributes = buffer.readUInt32LE(38); // 42 - Relative offset of local file header entry.relativeOffsetOfLocalHeader = buffer.readUInt32LE(42); self.readEntryCursor += 46; buffer = new Buffer(entry.fileNameLength + entry.extraFieldLength + entry.fileCommentLength); readFdSlicerNoEof(self.fdSlicer, buffer, 0, buffer.length, self.readEntryCursor, function(err) { if (err) return emitErrorAndAutoClose(self, err); if (self.emittedError) return; // 46 - File name var isUtf8 = entry.generalPurposeBitFlag & 0x800 try { entry.fileName = bufferToString(buffer, 0, entry.fileNameLength, isUtf8); } catch (e) { return emitErrorAndAutoClose(self, e); } // 46+n - Extra field var fileCommentStart = entry.fileNameLength + entry.extraFieldLength; var extraFieldBuffer = buffer.slice(entry.fileNameLength, fileCommentStart); entry.extraFields = []; var i = 0; while (i < extraFieldBuffer.length) { var headerId = extraFieldBuffer.readUInt16LE(i + 0); var dataSize = extraFieldBuffer.readUInt16LE(i + 2); var dataStart = i + 4; var dataEnd = dataStart + dataSize; var dataBuffer = new Buffer(dataSize); extraFieldBuffer.copy(dataBuffer, 0, dataStart, dataEnd); entry.extraFields.push({ id: headerId, data: dataBuffer, }); i = dataEnd; } // 46+n+m - File comment try { entry.fileComment = bufferToString(buffer, fileCommentStart, fileCommentStart + entry.fileCommentLength, isUtf8); } catch (e) { return emitErrorAndAutoClose(self, e); } self.readEntryCursor += buffer.length; self.entriesRead += 1; // validate file name if (entry.fileName.indexOf("\\") !== -1) return emitErrorAndAutoClose(self, new Error("invalid characters in fileName: " + entry.fileName)); if (/^[a-zA-Z]:/.test(entry.fileName) || /^\//.test(entry.fileName)) return emitErrorAndAutoClose(self, new Error("absolute path: " + entry.fileName)); if (entry.fileName.split("/").indexOf("..") !== -1) return emitErrorAndAutoClose(self, new Error("invalid relative path: " + entry.fileName)); self.emit("entry", entry); readEntries(self); }); }); } ZipFile.prototype.openReadStream = function(entry, callback) { var self = this; if (!self.isOpen) return callback(new Error("closed")); // make sure we don't lose the fd before we open the actual read stream self.fdSlicer.ref(); var buffer = new Buffer(30); readFdSlicerNoEof(self.fdSlicer, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader, function(err) { try { if (err) return callback(err); // 0 - Local file header signature = 0x04034b50 var signature = buffer.readUInt32LE(0); if (signature !== 0x04034b50) return callback(new Error("invalid local file header signature: 0x" + signature.toString(16))); // all this should be redundant // 4 - Version needed to extract (minimum) // 6 - General purpose bit flag // 8 - Compression method // 10 - File last modification time // 12 - File last modification date // 14 - CRC-32 // 18 - Compressed size // 22 - Uncompressed size // 26 - File name length (n) var fileNameLength = buffer.readUInt16LE(26); // 28 - Extra field length (m) var extraFieldLength = buffer.readUInt16LE(28); // 30 - File name // 30+n - Extra field var localFileHeaderEnd = entry.relativeOffsetOfLocalHeader + buffer.length + fileNameLength + extraFieldLength; var filterStream = null; if (entry.compressionMethod === 0) { // 0 - The file is stored (no compression) } else if (entry.compressionMethod === 8) { // 8 - The file is Deflated filterStream = zlib.createInflateRaw(); } else { return callback(new Error("unsupported compression method: " + entry.compressionMethod)); } var fileDataStart = localFileHeaderEnd; var fileDataEnd = fileDataStart + entry.compressedSize; if (entry.compressedSize !== 0) { // bounds check now, because the read streams will probably not complain loud enough. // since we're dealing with an unsigned offset plus an unsigned size, // we only have 1 thing to check for. if (fileDataEnd > self.fileSize) { return callback(new Error("file data overflows file bounds: " + fileDataStart + " + " + entry.compressedSize + " > " + self.fileSize)); } } var stream = self.fdSlicer.createReadStream({start: fileDataStart, end: fileDataEnd}); if (filterStream != null) { stream = stream.pipe(filterStream); } callback(null, stream); } finally { self.fdSlicer.unref(); } }); }; function Entry() { } Entry.prototype.getLastModDate = function() { return dosDateTimeToDate(this.lastModFileDate, this.lastModFileTime); }; function dosDateTimeToDate(date, time) { var day = date & 0x1f; // 1-31 var month = (date >> 5 & 0xf) - 1; // 1-12, 0-11 var year = (date >> 9 & 0x7f) + 1980; // 0-128, 1980-2108 var millisecond = 0; var second = (time & 0x1f) * 2; // 0-29, 0-58 (even numbers) var minute = time >> 5 & 0x3f; // 0-59 var hour = time >> 11 & 0x1f; // 0-23 return new Date(year, month, day, hour, minute, second, millisecond); } function readFdSlicerNoEof(fdSlicer, buffer, offset, length, position, callback) { if (length === 0) { // fs.read will throw an out-of-bounds error if you try to read 0 bytes from a 0 byte file return setImmediate(function() { callback(null, new Buffer(0)); }); } fdSlicer.read(buffer, offset, length, position, function(err, bytesRead) { if (err) return callback(err); if (bytesRead < length) return callback(new Error("unexpected EOF")); callback(); }); } var cp437 = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ '; function bufferToString(buffer, start, end, isUtf8) { if (isUtf8) { return buffer.toString("utf8", start, end); } else { var result = ""; for (var i = start; i < end; i++) { result += cp437[buffer[i]]; } return result; } } function FakeFdSlicer(buffer) { // pretend that a buffer is an FdSlicer this.buffer = buffer; } FakeFdSlicer.prototype.read = function(buffer, offset, length, position, callback) { this.buffer.copy(buffer, offset, position, position + length); setImmediate(function() { callback(null, length); }); }; FakeFdSlicer.prototype.createReadStream = function(options) { var start = options.start; var end = options.end; var buffer = new Buffer(end - start); this.buffer.copy(buffer, 0, start, end); var stream = new PassThrough(); stream.write(buffer); stream.end(); return stream; }; // i promise these functions are working properly :| FakeFdSlicer.prototype.ref = function() {}; FakeFdSlicer.prototype.unref = function() {}; FakeFdSlicer.prototype.on = function() {}; FakeFdSlicer.prototype.once = function() {}; function defaultCallback(err) { if (err) throw err; } node-yauzl-2.1.0/package.json000066400000000000000000000011651242012762700160750ustar00rootroot00000000000000{ "name": "yauzl", "version": "2.1.0", "description": "yet another unzip library for node", "main": "index.js", "scripts": { "test": "node test/test.js" }, "repository": { "type": "git", "url": "https://github.com/thejoshwolfe/yauzl.git" }, "keywords": [ "unzip", "zip", "stream", "archive", "file" ], "author": "Josh Wolfe ", "license": "MIT", "bugs": { "url": "https://github.com/thejoshwolfe/yauzl/issues" }, "homepage": "https://github.com/thejoshwolfe/yauzl", "dependencies": { "fd-slicer": "~0.2.1", "pend": "~1.1.3" } } node-yauzl-2.1.0/test/000077500000000000000000000000001242012762700145635ustar00rootroot00000000000000node-yauzl-2.1.0/test/dump.js000066400000000000000000000013041242012762700160640ustar00rootroot00000000000000 var yauzl = require("../"); var paths = []; var dumpContents = true; process.argv.slice(2).forEach(function(arg) { if (arg === "--no-contents") { dumpContents = false; } else { paths.push(arg); } }); paths.forEach(function(path) { yauzl.open(path, function(err, zipfile) { if (err) throw err; zipfile.on("error", function(err) { throw err; }); zipfile.on("entry", function(entry) { console.log(entry); console.log(entry.getLastModDate()); if (!dumpContents || /\/$/.exec(entry)) return; zipfile.openReadStream(entry, function(err, readStream) { if (err) throw err; readStream.pipe(process.stdout); }); }); }); }); node-yauzl-2.1.0/test/failure/000077500000000000000000000000001242012762700162125ustar00rootroot00000000000000node-yauzl-2.1.0/test/failure/absolute path C xt.zip000066400000000000000000000004641242012762700222540ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVC:/xtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/absolute path atxt.zip000066400000000000000000000004641242012762700224360ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQV/atxtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/end of central directory record signature not found.zip000066400000000000000000000004641242012762700305710ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/file data overflows file bounds 63 2147483647 308.zip000066400000000000000000000004641242012762700265170ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/invalid central directory file header signature 0x1014b50.zip000066400000000000000000000004641242012762700312060ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/invalid characters in fileName a txt.zip000066400000000000000000000004641242012762700255610ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa\txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/invalid code lengths set.zip000066400000000000000000000056611242012762700234700ustar00rootroot00000000000000PK E )index.jsUT WSWSux [o~C#ۺUov\IZ" $Ų69s 9dj 9sΙ܇z 5+p>%,MJ..H YU A%򑆼rIsEg4`˶}4HH<Z"K ۪.ء t;Cd MzE@LQOK%Q¬72I%֎ir: ҲU(d~ ,Q=漨J5#~ ?ڍI$&4OoI2"8V=&RAq8 ,64CyX>aK*63ْf~SXlC*< {4(8 A}PD%\ RFJCj/$\M"11 =+I@ ͱ`IBmIS@=SEG4",PQc߱pG ^ A{ zsDV\ncF 4PVDY xaӫ,YJtö5Kt^CRZQP`>iб"Aۃxu6TpPi$bVUN8{4eDe"qda^ J OhX U< ~xHentaS1-;HӔ;o P11Eu)0螼 ABV<-wa~y,SlldfƱ'i0^0D]hg5(srC헬Z.وqv9q +DIŲ6ɤ{qx&0ϰ9aC{km"@(Zkkno_uA&Y([5ZYg@]?؍HcCtpBgbqHuŅFD*2[bȲ]ziƇ\9twg, tq2J>J5}Ê aei ^%]6f" [V*)^ pjUcd(y8l߉-7Iyb"V,{$x#$ +}U?(zJsˮx;Y.l pe&{ J [rNeaf*{X5sFK1fK8 op(㥅xR~i+ܞe-?ZP9$cHN,h *H1&GK HP߿>U,Y^IN  B?Y6(%LEڿ뗸ZR Y]*_y~\W(nvة,< ױL'(sW+U|5 0e݇k$O\ŕ7u3KBt8LZ脅<{*MHl 37WXXXԷ/rY_;8ݼ-3@6CFQDVe嵳I ߾*޼mVp77ṑإ} mMmI)(ıV6 &]`sdvmi۬=Y:3m&)וV}Dͭu'Gӝٗt= }sgscFN=Z2@ޝW8ނ .:|G?YySvmX͖-w\a (: Фfz=ݜCN+fУ5࣫_(w\<ֈrx lGp.w{[Qp( CFV]w{+iU\mj:}؊X%b#uflG~mc;,w]wh%ζH9%6{ ; ;9f^ o}C] 0k[]@[*]̕~5V}/^p/ӹIRė2gukC%@<5ԝQ7G ]2-*loOk]6EPK E )index.jsUTWSux PKNM node-yauzl-2.1.0/test/failure/invalid comment length expected 1 found 0.zip000066400000000000000000000004651242012762700263750ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/invalid local file header signature 0x3034b50.zip000066400000000000000000000004641242012762700266670ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/invalid relative path xt.zip000066400000000000000000000004641242012762700235150ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQV../xtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/multi-disk zip files are not supported found disk number 1.zip000066400000000000000000000004641242012762700316120ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/failure/too many length or distance symbols.zip000066400000000000000000000056611242012762700255630ustar00rootroot00000000000000PK E )index.jsUT WSWSux Z[o~C#ۺUov\IZ" $Ų69s 9dj 9sΙ܇z 5+p>%,MJ..H YU A%򑆼rIsEg4`˶}4HH<Z"K ۪.ء t;Cd MzE@LQOK%Q¬72I%֎ir: ҲU(d~ ,Q=漨J5#~ ?ڍI$&4OoI2"8V=&RAq8 ,64CyX>aK*63ْf~SXlC*< {4(8 A}PD%\ RFJCj/$\M"11 =+I@ ͱ`IBmIS@=SEG4",PQc߱pG ^ A{ zsDV\ncF 4PVDY xaӫ,YJtö5Kt^CRZQP`>iб"Aۃxu6TpPi$bVUN8{4eDe"qda^ J OhX U< ~xHentaS1-;HӔ;o P11Eu)0螼 ABV<-wa~y,SlldfƱ'i0^0D]hg5(srC헬Z.وqv9q +DIŲ6ɤ{qx&0ϰ9aC{km"@(Zkkno_uA&Y([5ZYg@]?؍HcCtpBgbqHuŅFD*2[bȲ]ziƇ\9twg, tq2J>J5}Ê aei ^%]6f" [V*)^ pjUcd(y8l߉-7Iyb"V,{$x#$ +}U?(zJsˮx;Y.l pe&{ J [rNeaf*{X5sFK1fK8 op(㥅xR~i+ܞe-?ZP9$cHN,h *H1&GK HP߿>U,Y^IN  B?Y6(%LEڿ뗸ZR Y]*_y~\W(nvة,< ױL'(sW+U|5 0e݇k$O\ŕ7u3KBt8LZ脅<{*MHl 37WXXXԷ/rY_;8ݼ-3@6CFQDVe嵳I ߾*޼mVp77ṑإ} mMmI)(ıV6 &]`sdvmi۬=Y:3m&)וV}Dͭu'Gӝٗt= }sgscFN=Z2@ޝW8ނ .:|G?YySvmX͖-w\a (: Фfz=ݜCN+fУ5࣫_(w\<ֈrx lGp.w{[Qp( CFV]w{+iU\mj:}؊X%b#uflG~mc;,w]wh%ζH9%6{ ; ;9f^ o}C] 0k[]@[*]̕~5V}/^p/ӹIRė2gukC%@<5ԝQ7G ]2-*loOk]6EPK E )index.jsUTWSux PKNM node-yauzl-2.1.0/test/failure/unsupported compression method 1.zip000066400000000000000000000004641242012762700252360ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/success/000077500000000000000000000000001242012762700162335ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/cygwin-info-zip.zip000066400000000000000000000004641242012762700220140ustar00rootroot00000000000000PK KEQVa.txtUT =*S=*Sux +z+asdf PK KEb.txtUT =*S=*Sux +z+bsdf PK KEQVa.txtUT=*Sux +z+PK KEDb.txtUT=*Sux +z+PKnode-yauzl-2.1.0/test/success/cygwin-info-zip/000077500000000000000000000000001242012762700212645ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/cygwin-info-zip/a.txt000066400000000000000000000000051242012762700222400ustar00rootroot00000000000000asdf node-yauzl-2.1.0/test/success/cygwin-info-zip/b.txt000066400000000000000000000000051242012762700222410ustar00rootroot00000000000000bsdf node-yauzl-2.1.0/test/success/deflate.zip000066400000000000000000000056611242012762700203730ustar00rootroot00000000000000PK E )index.jsUT WSWSux Z[o~C#ۺUov\IZ" $Ų69s 9dj 9sΙ܇z 5+p>%,MJ..H YU A%򑆼rIsEg4`˶}4HH<Z"K ۪.ء t;Cd MzE@LQOK%Q¬72I%֎ir: ҲU(d~ ,Q=漨J5#~ ?ڍI$&4OoI2"8V=&RAq8 ,64CyX>aK*63ْf~SXlC*< {4(8 A}PD%\ RFJCj/$\M"11 =+I@ ͱ`IBmIS@=SEG4",PQc߱pG ^ A{ zsDV\ncF 4PVDY xaӫ,YJtö5Kt^CRZQP`>iб"Aۃxu6TpPi$bVUN8{4eDe"qda^ J OhX U< ~xHentaS1-;HӔ;o P11Eu)0螼 ABV<-wa~y,SlldfƱ'i0^0D]hg5(srC헬Z.وqv9q +DIŲ6ɤ{qx&0ϰ9aC{km"@(Zkkno_uA&Y([5ZYg@]?؍HcCtpBgbqHuŅFD*2[bȲ]ziƇ\9twg, tq2J>J5}Ê aei ^%]6f" [V*)^ pjUcd(y8l߉-7Iyb"V,{$x#$ +}U?(zJsˮx;Y.l pe&{ J [rNeaf*{X5sFK1fK8 op(㥅xR~i+ܞe-?ZP9$cHN,h *H1&GK HP߿>U,Y^IN  B?Y6(%LEڿ뗸ZR Y]*_y~\W(nvة,< ױL'(sW+U|5 0e݇k$O\ŕ7u3KBt8LZ脅<{*MHl 37WXXXԷ/rY_;8ݼ-3@6CFQDVe嵳I ߾*޼mVp77ṑإ} mMmI)(ıV6 &]`sdvmi۬=Y:3m&)וV}Dͭu'Gӝٗt= }sgscFN=Z2@ޝW8ނ .:|G?YySvmX͖-w\a (: Фfz=ݜCN+fУ5࣫_(w\<ֈrx lGp.w{[Qp( CFV]w{+iU\mj:}؊X%b#uflG~mc;,w]wh%ζH9%6{ ; ;9f^ o}C] 0k[]@[*]̕~5V}/^p/ӹIRė2gukC%@<5ԝQ7G ]2-*loOk]6EPK E )index.jsUTWSux PKNM node-yauzl-2.1.0/test/success/deflate/000077500000000000000000000000001242012762700176375ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/deflate/index.js000066400000000000000000000247011242012762700213100ustar00rootroot00000000000000var fs = require("fs"); var FdSlicer = require("fd-slicer"); // cd - Central Directory // cdr - Central Directory Record // eocdr - End of Central Directory Record open("test/cygwin-info-zip.zip", function(err, zipfile) { if (err) throw err; console.log("entries:", zipfile.entriesRemaining()); keepReading(); function keepReading() { if (zipfile.entriesRemaining() === 0) return; zipfile.readEntry(function(err, entry) { if (err) throw err; console.log(entry); zipfile.openReadStream(entry, function(err, readStream) { if (err) throw err; readStream.pipe(process.stdout); }); keepReading(); }); } }); module.exports.open = open; function open(path, callback) { if (callback == null) callback = defaultCallback; fs.open(path, "r", function(err, fd) { if (err) return callback(err); fopen(fd, function(err, zipfile) { if (err) fs.close(fd, defaultCallback); callback(err, zipfile); }); }); } module.exports.fopen = fopen; function fopen(fd, callback) { if (callback == null) callback = defaultCallback; fs.fstat(fd, function(err, stats) { if (err) return callback(err); verbose("searching backwards for the eocdr signature"); // the last field of the eocdr is a variable-length comment. // the comment size is encoded in a 2-byte field in the eocdr, which we can't find without trudging backwards through the comment to find it. // as a consequence of this design decision, it's possible to have ambiguous zip file metadata if, for example, a coherent eocdr was in the comment. // we search backwards for the first eocdr signature, and hope that whoever made the zip file was smart enough to forbid the eocdr signature in the comment. var eocdrWithoutCommentSize = 22; var maxCommentSize = 0x10000; // 2-byte size var bufferSize = Math.min(eocdrWithoutCommentSize + maxCommentSize, stats.size); var buffer = new Buffer(bufferSize); var bufferReadStart = stats.size - buffer.length; readNoEof(fd, buffer, 0, bufferSize, bufferReadStart, function(err) { if (err) return callback(err); for (var i = bufferSize - eocdrWithoutCommentSize; i >= 0; i -= 1) { if (buffer.readUInt32LE(i) !== 0x06054b50) continue; verbose("found eocdr at offset: " + (bufferReadStart + i)); var eocdrBuffer = buffer.slice(i); // 0 - End of central directory signature = 0x06054b50 // 4 - Number of this disk var diskNumber = eocdrBuffer.readUInt16LE(4); if (diskNumber !== 0) return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber)); // 6 - Disk where central directory starts // 8 - Number of central directory records on this disk // 10 - Total number of central directory records var entryCount = eocdrBuffer.readUInt16LE(10); // 12 - Size of central directory (bytes) // 16 - Offset of start of central directory, relative to start of archive var cdOffset = eocdrBuffer.readUInt32LE(16); // 20 - Comment length var commentLength = eocdrBuffer.readUInt16LE(20); var expectedCommentLength = eocdrBuffer.length - eocdrWithoutCommentSize; if (commentLength !== expectedCommentLength) { return callback(new Error("invalid comment length. expected: " + expectedCommentLength + ". found: " + commentLength)); } // 22 - Comment var comment = new Buffer(commentLength); // the comment length is typcially 0. // copy from the original buffer to make sure we're not pinning it from being GC'ed. eocdrBuffer.copy(comment, 0, 22, eocdrBuffer.length); return callback(null, new ZipFile(fd, cdOffset, entryCount, comment)); } callback(new Error("end of central directory record signature not found")); }); }); } function ZipFile(fd, cdOffset, entryCount, comment) { this.fdSlicer = new FdSlicer(fd); this.readEntryCursor = cdOffset; this.entryCount = entryCount; this.comment = comment; this.entriesRead = 0; this.isReadingEntry = false; } ZipFile.prototype.close = function(callback) { if (callback == null) callback = defaultCallback; fs.close(this.fdSlicer.fd, callback); }; ZipFile.prototype.readEntries = function(callback) { var self = this; if (callback == null) callback = defaultCallback; var entries = []; keepReading(); function keepReading() { self.readEntry(function(err, entry) { if (err) return callback(err); entries.push(entry); if (self.entriesRemaining() > 0) { keepReading(); } else { callback(null, entries); } }); } }; ZipFile.prototype.entriesRemaining = function() { return this.entryCount - this.entriesRead; }; ZipFile.prototype.readEntry = function(callback) { var self = this; if (self.isReadingEntry) throw new Error("readEntry already in progress"); self.isReadingEntry = true; if (callback == null) callback = defaultCallback; var buffer = new Buffer(46); readFdSlicerNoEof(this.fdSlicer, buffer, 0, buffer.length, this.readEntryCursor, function(err) { if (err) return callback(err); var entry = {}; // 0 - Central directory file header signature var signature = buffer.readUInt32LE(0); if (signature !== 0x02014b50) return callback(new Error("invalid central directory file header signature: 0x" + signature.toString(16))); // 4 - Version made by entry.versionMadeBy = buffer.readUInt16LE(4); // 6 - Version needed to extract (minimum) entry.versionNeededToExtract = buffer.readUInt16LE(6); // 8 - General purpose bit flag entry.generalPurposeBitFlag = buffer.readUInt16LE(8); // 10 - Compression method entry.compressionMethod = buffer.readUInt16LE(10); // 12 - File last modification time entry.lastModFileTime = buffer.readUInt16LE(12); // 14 - File last modification date entry.lastModFileDate = buffer.readUInt16LE(14); // 16 - CRC-32 entry.crc32 = buffer.readUInt32LE(16); // 20 - Compressed size entry.compressedSize = buffer.readUInt32LE(20); // 24 - Uncompressed size entry.uncompressedSize = buffer.readUInt32LE(24); // 28 - File name length (n) entry.fileNameLength = buffer.readUInt16LE(28); // 30 - Extra field length (m) entry.extraFieldLength = buffer.readUInt16LE(30); // 32 - File comment length (k) entry.fileCommentLength = buffer.readUInt16LE(32); // 34 - Disk number where file starts // 36 - Internal file attributes entry.internalFileAttributes = buffer.readUInt16LE(36); // 38 - External file attributes entry.externalFileAttributes = buffer.readUInt32LE(38); // 42 - Relative offset of local file header entry.relativeOffsetOfLocalHeader = buffer.readUInt32LE(42); self.readEntryCursor += 46; buffer = new Buffer(entry.fileNameLength + entry.extraFieldLength + entry.fileCommentLength); readFdSlicerNoEof(self.fdSlicer, buffer, 0, buffer.length, self.readEntryCursor, function(err) { if (err) return callback(err); // 46 - File name var encoding = entry.generalPurposeBitFlag & 0x800 ? "utf8" : "ascii"; // TODO: replace ascii with CP437 using https://github.com/bnoordhuis/node-iconv entry.fileName = buffer.toString(encoding, 0, entry.fileNameLength); // 46+n - Extra field var fileCommentStart = entry.fileNameLength + entry.extraFieldLength; var extraFieldBuffer = buffer.slice(entry.fileNameLength, fileCommentStart); entry.extraFields = []; var i = 0; while (i < extraFieldBuffer.length) { var headerId = extraFieldBuffer.readUInt16LE(i + 0); var dataSize = extraFieldBuffer.readUInt16LE(i + 2); var dataStart = i + 4; var dataEnd = dataStart + dataSize; var dataBuffer = new Buffer(dataSize); extraFieldBuffer.copy(dataBuffer, 0, dataStart, dataEnd); entry.extraFields.push({ id: headerId, data: dataBuffer, }); i = dataEnd; } // 46+n+m - File comment entry.fileComment = buffer.toString(encoding, fileCommentStart, fileCommentStart + entry.fileCommentLength); self.readEntryCursor += buffer.length; self.entriesRead += 1; self.isReadingEntry = false; callback(null, entry); }); }); }; ZipFile.prototype.openReadStream = function(entry, callback) { var self = this; var buffer = new Buffer(30); readFdSlicerNoEof(self.fdSlicer, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader, function(err) { if (err) return callback(err); // 0 - Local file header signature = 0x04034b50 var signature = buffer.readUInt32LE(0); if (signature !== 0x04034b50) callback(new Error("invalid local file header signature: 0x" + signature.toString(16))); // all this should be redundant // 4 - Version needed to extract (minimum) // 6 - General purpose bit flag // 8 - Compression method // 10 - File last modification time // 12 - File last modification date // 14 - CRC-32 // 18 - Compressed size // 22 - Uncompressed size // 26 - File name length (n) var fileNameLength = buffer.readUInt16LE(26); // 28 - Extra field length (m) var extraFieldLength = buffer.readUInt16LE(28); // 30 - File name // 30+n - Extra field var localFileHeaderEnd = entry.relativeOffsetOfLocalHeader + buffer.length + fileNameLength + extraFieldLength; if (entry.compressionMethod === 0) { // 0 - The file is stored (no compression) } else { return callback(new Error("unsupported compression method: " + entry.compressionMethod)); } var fileDataStart = localFileHeaderEnd; var fileDataEnd = fileDataStart + entry.compressedSize; var readStream = self.fdSlicer.createReadStream({start: fileDataStart, end: fileDataEnd}); callback(null, readStream); }); }; function verbose(message) { console.log(message); } function readNoEof(fd, buffer, offset, length, position, callback) { fs.read(fd, buffer, offset, length, position, function(err, bytesRead) { if (err) return callback(err); if (bytesRead < length) return callback(new Error("unexpected EOF")); callback(null, buffer); }); } function readFdSlicerNoEof(fdSlicer, buffer, offset, length, position, callback) { fdSlicer.read(buffer, offset, length, position, function(err, bytesRead) { if (err) return callback(err); if (bytesRead < length) return callback(new Error("unexpected EOF")); callback(null, buffer); }); } function defaultCallback(err) { if (err) throw err; } node-yauzl-2.1.0/test/success/directories.zip000066400000000000000000000006541242012762700213000ustar00rootroot00000000000000PK Ea/UT SSux PK Ea/a.txtUT SSux PK Eb/UT 3S3Sux PK EAa/UTSux PK E<a/a.txtUTSux PK EA}b/UT3Sux PKnode-yauzl-2.1.0/test/success/directories/000077500000000000000000000000001242012762700205475ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/directories/a/000077500000000000000000000000001242012762700207675ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/directories/a/a.txt000066400000000000000000000000001242012762700217360ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/directories/b/000077500000000000000000000000001242012762700207705ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/directories/b/.git_please_make_this_directory000066400000000000000000000000001242012762700272030ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/empty.zip000066400000000000000000000000261242012762700201130ustar00rootroot00000000000000PKnode-yauzl-2.1.0/test/success/empty/000077500000000000000000000000001242012762700173715ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/empty/.git_please_make_this_directory000066400000000000000000000000001242012762700256040ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/linux-info-zip.zip000066400000000000000000000004641242012762700216530ustar00rootroot00000000000000PK KEQVa.txtUT >*S>*Sux asdf PK KEb.txtUT >*S>*Sux bsdf PK KEQVa.txtUT>*Sux PK KEDb.txtUT>*Sux PKnode-yauzl-2.1.0/test/success/linux-info-zip/000077500000000000000000000000001242012762700211235ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/linux-info-zip/a.txt000066400000000000000000000000051242012762700220770ustar00rootroot00000000000000asdf node-yauzl-2.1.0/test/success/linux-info-zip/b.txt000066400000000000000000000000051242012762700221000ustar00rootroot00000000000000bsdf node-yauzl-2.1.0/test/success/unicode.zip000066400000000000000000000017641242012762700204150ustar00rootroot00000000000000PK z ETurmion Kätilöt/UT SSux PK E ETurmion Kätilöt/Hoitovirhe/UT SSux PK  E+Turmion Kätilöt/Hoitovirhe/Rautaketju.mp3UT S8FSux PK  ETurmion Kätilöt/Pirun nyrkki/UT 0S1Sux PK  E6Turmion Kätilöt/Pirun nyrkki/Mistä veri pakenee.mp3UT S:FSux PK z EATurmion Kätilöt/UTSux PK E EALTurmion Kätilöt/Hoitovirhe/UTSux PK  E+Turmion Kätilöt/Hoitovirhe/Rautaketju.mp3UTSux PK  EATurmion Kätilöt/Pirun nyrkki/UT0Sux PK  E6aTurmion Kätilöt/Pirun nyrkki/Mistä veri pakenee.mp3UTSux PK node-yauzl-2.1.0/test/success/unicode/000077500000000000000000000000001242012762700176615ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/unicode/Turmion Kätilöt/000077500000000000000000000000001242012762700237265ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/unicode/Turmion Kätilöt/Hoitovirhe/000077500000000000000000000000001242012762700260465ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/unicode/Turmion Kätilöt/Hoitovirhe/Rautaketju.mp3000066400000000000000000000000001242012762700305740ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/unicode/Turmion Kätilöt/Pirun nyrkki/000077500000000000000000000000001242012762700263135ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/unicode/Turmion Kätilöt/Pirun nyrkki/Mistä veri pakenee.mp3000066400000000000000000000000001242012762700327240ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/windows-7-zip.zip000077500000000000000000000004241242012762700214200ustar00rootroot00000000000000PK KEQVa.txtasdf PK KEb.txtbsdf PK? KEQV$ a.txt >l>l>lPK? KE$ (b.txt mmmPKPnode-yauzl-2.1.0/test/success/windows-7-zip/000077500000000000000000000000001242012762700206715ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/windows-7-zip/a.txt000066400000000000000000000000051242012762700216450ustar00rootroot00000000000000asdf node-yauzl-2.1.0/test/success/windows-7-zip/b.txt000066400000000000000000000000051242012762700216460ustar00rootroot00000000000000bsdf node-yauzl-2.1.0/test/success/windows-compressed-folder.zip000077500000000000000000000003141242012762700240650ustar00rootroot00000000000000PKKEQVa.txtasdf PKKEb.txtbsdf PKKEQV a.txtPKKE (b.txtPKfPnode-yauzl-2.1.0/test/success/windows-compressed-folder/000077500000000000000000000000001242012762700233405ustar00rootroot00000000000000node-yauzl-2.1.0/test/success/windows-compressed-folder/a.txt000066400000000000000000000000051242012762700243140ustar00rootroot00000000000000asdf node-yauzl-2.1.0/test/success/windows-compressed-folder/b.txt000066400000000000000000000000051242012762700243150ustar00rootroot00000000000000bsdf node-yauzl-2.1.0/test/test.js000066400000000000000000000145101242012762700161010ustar00rootroot00000000000000var yauzl = require("../"); var fs = require("fs"); var path = require("path"); var Pend = require("pend"); // this is the date i made the example zip files and their content files, // so this timestamp will be earlier than all the ones stored in these test zip files // (and probably all future zip files). // no timezone awareness, because that's how MS-DOS rolls. var earliestTimestamp = new Date(2014, 7, 18, 0, 0, 0, 0); var pend = new Pend(); // 1 thing at a time for better determinism/reproducibility pend.max = 1; // success tests listZipFiles(path.join(__dirname, "success")).forEach(function(zipfilePath) { var openFunctions = [ function(callback) { yauzl.open(zipfilePath, callback); }, function(callback) { yauzl.fromBuffer(fs.readFileSync(zipfilePath), callback); }, ]; openFunctions.forEach(function(openFunction, i) { var testId = zipfilePath + "(" + ["fd", "buffer"][i] + "): "; var expectedPathPrefix = zipfilePath.replace(/\.zip$/, ""); var expectedArchiveContents = {}; var DIRECTORY = 1; // not a string recursiveRead("."); function recursiveRead(name) { var realPath = path.join(expectedPathPrefix, name); if (fs.statSync(realPath).isFile()) { if (path.basename(name) !== ".git_please_make_this_directory") { expectedArchiveContents[name] = fs.readFileSync(realPath); } } else { if (name !== ".") expectedArchiveContents[name] = DIRECTORY; fs.readdirSync(realPath).forEach(function(child) { recursiveRead(path.join(name, child)); }); } } pend.go(function(zipfileCallback) { openFunction(function(err, zipfile) { if (err) throw err; var entryProcessing = new Pend(); entryProcessing.max = 1; zipfile.on("entry", function(entry) { var messagePrefix = testId + entry.fileName + ": "; var timestamp = entry.getLastModDate(); if (timestamp < earliestTimestamp) throw new Error(messagePrefix + "timestamp too early: " + timestamp); if (timestamp > new Date()) throw new Error(messagePrefix + "timestamp in the future: " + timestamp); entryProcessing.go(function(entryCallback) { var fileNameKey = entry.fileName.replace(/\/$/, ""); var expectedContents = expectedArchiveContents[fileNameKey]; if (expectedContents == null) { throw new Error(messagePrefix + "not supposed to exist"); } delete expectedArchiveContents[fileNameKey]; if (entry.fileName !== fileNameKey) { // directory console.log(messagePrefix + "pass"); entryCallback(); } else { zipfile.openReadStream(entry, function(err, readStream) { if (err) throw err; var buffers = []; readStream.on("data", function(data) { buffers.push(data); }); readStream.on("end", function() { var actualContents = Buffer.concat(buffers); // uh. there's no buffer equality check? var equal = actualContents.toString("binary") === expectedContents.toString("binary"); if (!equal) { throw new Error(messagePrefix + "wrong contents"); } console.log(messagePrefix + "pass"); entryCallback(); }); readStream.on("error", function(err) { throw err; }); }); } }); }); zipfile.on("end", function() { entryProcessing.wait(function() { for (var fileName in expectedArchiveContents) { throw new Error(testId + fileName + ": missing file"); } console.log(testId + "pass"); zipfileCallback(); }); }); zipfile.on("close", function() { console.log(testId + "closed"); }); }); }); }); }); // failure tests listZipFiles(path.join(__dirname, "failure")).forEach(function(zipfilePath) { var expectedErrorMessage = path.basename(zipfilePath).replace(/\.zip$/, ""); var failedYet = false; var emittedError = false; pend.go(function(cb) { var operationsInProgress = 0; yauzl.open(zipfilePath, function(err, zipfile) { if (err) return checkErrorMessage(err); zipfile.on("error", function(err) { noEventsAllowedAfterError(); emittedError = true; checkErrorMessage(err); }); zipfile.on("entry", function(entry) { noEventsAllowedAfterError(); // let's also try to read directories, cuz whatever. operationsInProgress += 1; zipfile.openReadStream(entry, function(err, stream) { if (err) return checkErrorMessage(err); stream.on("error", function(err) { checkErrorMessage(err); }); stream.on("data", function(data) { // ignore }); stream.on("end", function() { doneWithSomething(); }); }); }); operationsInProgress += 1; zipfile.on("end", function() { noEventsAllowedAfterError(); doneWithSomething(); }); function doneWithSomething() { operationsInProgress -= 1; if (operationsInProgress !== 0) return; if (!failedYet) { throw new Error(zipfilePath + ": expected failure"); } } }); function checkErrorMessage(err) { var actualMessage = err.message.replace(/[^0-9A-Za-z-]+/g, " "); if (actualMessage !== expectedErrorMessage) { throw new Error(zipfilePath + ": wrong error message: " + actualMessage); } console.log(zipfilePath + ": pass"); failedYet = true; operationsInProgress = -Infinity; cb(); } function noEventsAllowedAfterError() { if (emittedError) throw new Error("events emitted after error event"); } }); }); pend.wait(function() { // if you don't see this, something never happened. console.log("done"); }); function listZipFiles(dir) { var zipfilePaths = fs.readdirSync(dir).filter(function(filepath) { return /\.zip$/.exec(filepath); }).map(function(name) { return path.relative(".", path.join(dir, name)); }); zipfilePaths.sort(); return zipfilePaths; }