Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

unzipper

Package Overview
Dependencies
Maintainers
1
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

unzipper - npm Package Compare versions

Comparing version 0.9.0-rc9 to 0.9.0

lib/Open/unzip.js

4

lib/BufferStream.js

@@ -5,4 +5,4 @@ var Promise = require('bluebird');

// Backwards compatibility for node 0.8
if (!Stream.Writable)
// Backwards compatibility for node versions < 8
if (!Stream.Writable || !Stream.Writable.prototype.destroy)
Stream = require('readable-stream');

@@ -9,0 +9,0 @@

var bigInt = require('big-integer');
var Stream = require('stream');
// Backwards compatibility for node 0.8
if (!Stream.Writable)
// Backwards compatibility for node versions < 8
if (!Stream.Writable || !Stream.Writable.prototype.destroy)
Stream = require('readable-stream');

@@ -7,0 +7,0 @@

@@ -15,3 +15,18 @@ module.exports = Extract;

var self = this;
var finishCb;
var pending = 0;
var _final = typeof this._final === 'function' ? this._final : undefined;
function checkFinished() {
if (pending === 0 && finishCb) {
_final ? _final(finishCb) : finishCb();
}
}
this._final = function(cb) {
finishCb = cb;
checkFinished();
};
Parse.call(self,opts);

@@ -21,9 +36,25 @@

if (entry.type == 'Directory') return;
entry.pipe(Writer({
path: path.join(opts.path,entry.path)
}))
// to avoid zip slip (writing outside of the destination), we resolve
// the target path, and make sure it's nested in the intended
// destination, or not extract it otherwise.
var extractPath = path.join(opts.path, entry.path);
if (extractPath.indexOf(opts.path) != 0) {
return;
}
const writer = opts.getWriter ? opts.getWriter({path: extractPath}) : Writer({ path: extractPath });
pending += 1;
entry.pipe(writer)
.on('error',function(e) {
self.emit('error',e);
pending -= 1;
checkFinished();
})
.on('close', function() {
pending -= 1;
checkFinished();
});
});
}
var Stream = require('stream');
var util = require('util');
// Backwards compatibility for node 0.8
if (!Stream.Writable)
// Backwards compatibility for node versions < 8
if (!Stream.Writable || !Stream.Writable.prototype.destroy)
Stream = require('readable-stream');

@@ -7,0 +7,0 @@

@@ -0,5 +1,6 @@

var binary = require('binary');
var PullStream = require('../PullStream');
var unzip = require('./unzip');
var Promise = require('bluebird');
var BufferStream = require('../BufferStream');
var read = require('../read');

@@ -11,3 +12,5 @@ var signature = Buffer(4);

var endDir = PullStream(),
records = PullStream();
records = PullStream(),
self = this,
vars;

@@ -20,33 +23,62 @@ return source.size()

.then(function() {
return read.endOfDirectory(endDir);
return endDir.pull(22);
})
.then(function(vars) {
Object.defineProperty(vars,'source',{value: source});
.then(function(data) {
vars = binary.parse(data)
.word32lu('signature')
.word16lu('diskNumber')
.word16lu('diskStart')
.word16lu('numberOfRecordsOnDisk')
.word16lu('numberOfRecords')
.word32lu('sizeOfCentralDirectory')
.word32lu('offsetToStartOfCentralDirectory')
.word16lu('commentLength')
.vars;
source.stream(vars.offsetToStartOfCentralDirectory).pipe(records);
vars.files = Promise.mapSeries(Array(vars.numberOfRecords),function() {
return read.directoryFileHeader(records)
.then(function(file) {
file.stream = function(_password, _raw) {
var input = source.stream(file.offsetToLocalFileHeader);
var output = read.fileStream(input.pipe(PullStream()),{password:_password, raw: _raw});
return records.pull(46).then(function(data) {
var vars = binary.parse(data)
.word32lu('signature')
.word16lu('versionMadeBy')
.word16lu('versionsNeededToExtract')
.word16lu('flags')
.word16lu('compressionMethod')
.word16lu('lastModifiedTime')
.word16lu('lastModifiedDate')
.word32lu('crc32')
.word32lu('compressedSize')
.word32lu('uncompressedSize')
.word16lu('fileNameLength')
.word16lu('extraFieldLength')
.word16lu('fileCommentLength')
.word16lu('diskNumber')
.word16lu('internalFileAttributes')
.word32lu('externalFileAttributes')
.word32lu('offsetToLocalFileHeader')
.vars;
input.on('error',function(err) {
output.emit('error',err);
});
return output;
};
file.buffer = function(_password) {
return BufferStream(file.stream(_password));
};
return file;
});
return records.pull(vars.fileNameLength).then(function(fileName) {
vars.path = fileName.toString('utf8');
return records.pull(vars.extraFieldLength);
})
.then(function(extraField) {
return records.pull(vars.fileCommentLength);
})
.then(function(comment) {
vars.comment = comment;
vars.stream = function(_password) {
return unzip(source, vars.offsetToLocalFileHeader,_password);
};
vars.buffer = function(_password) {
return BufferStream(vars.stream(_password));
};
return vars;
});
});
return Promise.props(vars);
});
return Promise.props(vars);
});
};
var util = require('util');
var zlib = require('zlib');
var Stream = require('stream');
var binary = require('binary');
var Promise = require('bluebird');
var PullStream = require('./PullStream');
var read = require('./read');
var NoopStream = require('./NoopStream');
var BufferStream = require('./BufferStream');
// Backwards compatibility for node 0.8
if (!Stream.Writable)
// Backwards compatibility for node versions < 8
if (!Stream.Writable || !Stream.Writable.prototype.destroy)
Stream = require('readable-stream');

@@ -36,26 +39,21 @@

// Read signature and put back on buffer
var signature = data.readUInt32LE(0);
self.buffer = Buffer.concat([data,self.buffer]);
if (signature === 0x04034b50)
if (signature === 0x04034b50) {
return self._readFile();
}
else if (signature === 0x02014b50) {
self.__ended = true;
return read.directoryFileHeader(self)
.then(function(vars) {
return self._readRecord();
});
return self._readCentralDirectoryFileHeader();
}
else if (signature === 0x06054b50 || self.__ended) {
else if (signature === 0x06054b50) {
return self._readEndOfCentralDirectoryRecord();
}
else if (self.__ended) {
return self.pull(endDirectorySignature).then(function() {
return read.endOfDirectory(self);
})
.then(function() {
self.end();
self.push(null);
return self._readEndOfCentralDirectoryRecord();
});
}
else
self.emit('error', Error('invalid signature: 0x' + signature.toString(16)));
self.emit('error', new Error('invalid signature: 0x' + signature.toString(16)));
});

@@ -66,38 +64,179 @@ };

var self = this;
var entry = read.fileStream(self,self._opts);
self.pull(26).then(function(data) {
var vars = binary.parse(data)
.word16lu('versionsNeededToExtract')
.word16lu('flags')
.word16lu('compressionMethod')
.word16lu('lastModifiedTime')
.word16lu('lastModifiedDate')
.word32lu('crc32')
.word32lu('compressedSize')
.word32lu('uncompressedSize')
.word16lu('fileNameLength')
.word16lu('extraFieldLength')
.vars;
entry.header.then(function(vars) {
var fileSizeKnown = !(vars.flags & 0x08);
entry.path = vars.path;
entry.props = {};
entry.props.path = vars.fileName;
entry.type = (vars.compressedSize === 0 && /[\/\\]$/.test(vars.path)) ? 'Directory' : 'File';
return self.pull(vars.fileNameLength).then(function(fileName) {
fileName = fileName.toString('utf8');
var entry = Stream.PassThrough();
entry.autodrain = function() {
return new Promise(function(resolve,reject) {
entry.pipe(NoopStream());
entry.on('finish',resolve);
entry.on('error',reject);
});
};
entry.autodrain = function() {
entry.autodraining = true;
return new Promise(function(resolve,reject) {
entry.on('finish',resolve);
entry.on('error',reject);
});
};
entry.buffer = function() {
return BufferStream(entry);
};
self.emit('entry',entry);
entry.path = fileName;
entry.props = {};
entry.props.path = fileName;
entry.type = (vars.uncompressedSize === 0 && /[\/\\]$/.test(fileName)) ? 'Directory' : 'File';
if (self._readableState.pipesCount)
self.push(entry);
if (self._opts.verbose) {
if (entry.type === 'Directory') {
console.log(' creating:', fileName);
} else if (entry.type === 'File') {
if (vars.compressionMethod === 0) {
console.log(' extracting:', fileName);
} else {
console.log(' inflating:', fileName);
}
}
}
self.pull(vars.extraFieldLength).then(function(extraField) {
var extra = binary.parse(extraField)
.word16lu('signature')
.word16lu('partsize')
.word64lu('uncompressedSize')
.word64lu('compressedSize')
.word64lu('offset')
.word64lu('disknum')
.vars;
if (vars.compressedSize === 0xffffffff)
vars.compressedSize = extra.compressedSize;
if (vars.uncompressedSize === 0xffffffff)
vars.uncompressedSize= extra.uncompressedSize;
entry
.on('finish', function() {
Promise.resolve(!fileSizeKnown && read.dataDescriptor(self))
.then(function() {
return self._readRecord();
});
entry.vars = vars;
entry.extra = extra;
self.emit('entry', entry);
if (self._readableState.pipesCount)
self.push(entry);
if (self._opts.verbose)
console.log({
filename:fileName,
vars: vars,
extra: extra
});
var fileSizeKnown = !(vars.flags & 0x08),
eof;
var inflater = vars.compressionMethod ? zlib.createInflateRaw() : Stream.PassThrough();
if (fileSizeKnown) {
entry.size = vars.uncompressedSize;
eof = vars.compressedSize;
} else {
eof = new Buffer(4);
eof.writeUInt32LE(0x08074b50, 0);
}
self.stream(eof)
.pipe(inflater)
.on('error',function(err) { self.emit('error',err);})
.pipe(entry)
.on('finish', function() {
return fileSizeKnown ? self._readRecord() : self._processDataDescriptor(entry);
});
});
});
});
};
Parse.prototype._processDataDescriptor = function (entry) {
var self = this;
self.pull(16).then(function(data) {
var vars = binary.parse(data)
.word32lu('dataDescriptorSignature')
.word32lu('crc32')
.word32lu('compressedSize')
.word32lu('uncompressedSize')
.vars;
entry.size = vars.uncompressedSize;
self._readRecord();
});
};
Parse.prototype._readCentralDirectoryFileHeader = function () {
var self = this;
self.pull(42).then(function(data) {
var vars = binary.parse(data)
.word16lu('versionMadeBy')
.word16lu('versionsNeededToExtract')
.word16lu('flags')
.word16lu('compressionMethod')
.word16lu('lastModifiedTime')
.word16lu('lastModifiedDate')
.word32lu('crc32')
.word32lu('compressedSize')
.word32lu('uncompressedSize')
.word16lu('fileNameLength')
.word16lu('extraFieldLength')
.word16lu('fileCommentLength')
.word16lu('diskNumber')
.word16lu('internalFileAttributes')
.word32lu('externalFileAttributes')
.word32lu('offsetToLocalFileHeader')
.vars;
return self.pull(vars.fileNameLength).then(function(fileName) {
vars.fileName = fileName.toString('utf8');
return self.pull(vars.extraFieldLength);
})
.then(function(extraField) {
return self.pull(vars.fileCommentLength);
})
.then(function(fileComment) {
return self._readRecord();
});
});
};
Parse.prototype._readEndOfCentralDirectoryRecord = function() {
var self = this;
self.pull(18).then(function(data) {
var vars = binary.parse(data)
.word16lu('diskNumber')
.word16lu('diskStart')
.word16lu('numberOfRecordsOnDisk')
.word16lu('numberOfRecords')
.word32lu('sizeOfCentralDirectory')
.word32lu('offsetToStartOfCentralDirectory')
.word16lu('commentLength')
.vars;
self.pull(vars.commentLength).then(function(comment) {
comment = comment.toString('utf8');
self.end();
self.push(null);
});
});
};
Parse.prototype.promise = function() {

@@ -104,0 +243,0 @@ var self = this;

@@ -6,16 +6,14 @@ var Stream = require('stream');

// Backwards compatibility for node 0.8
if (!Stream.Writable)
// Backwards compatibility for node versions < 8
if (!Stream.Writable || !Stream.Writable.prototype.destroy)
Stream = require('readable-stream');
function parseOne(match,opts) {
opts = opts || {};
var inStream = Stream.PassThrough({objectMode:true});
var outStream = Stream.PassThrough();
var transform = Stream.Transform({objectMode:true});
var re = match && new RegExp(match);
var re = match instanceof RegExp ? match : (match && new RegExp(match));
var found;
transform._transform = function(entry,e,cb) {
entry.password = opts.password;
if (found || (re && !re.exec(entry.path))) {

@@ -61,3 +59,2 @@ entry.autodrain();

module.exports = parseOne;
module.exports = parseOne;

@@ -6,4 +6,4 @@ var Stream = require('stream');

// Backwards compatibility for node 0.8
if (!Stream.Writable)
// Backwards compatibility for node versions < 8
if (!Stream.Writable || !Stream.Writable.prototype.destroy)
Stream = require('readable-stream');

@@ -37,3 +37,3 @@

var p = Stream.PassThrough();
var done,packet,self= this;
var count = 0,done,packet,self= this;

@@ -66,8 +66,9 @@ function pull() {

if (!done) {
if (self.finished && !self.__ended) {
if (self.finished && !this.__ended) {
self.removeListener('chunk',pull);
self.emit('error',new Error('FILE_ENDED'));
self.emit('error', new Error('FILE_ENDED'));
this.__ended = true;
return;
}
} else {

@@ -74,0 +75,0 @@ self.removeListener('chunk',pull);

{
"name": "unzipper",
"version": "0.9.0-rc9",
"version": "0.9.0",
"description": "Unzip cross-platform streaming API ",

@@ -33,3 +33,3 @@ "author": "Evan Oxfeld <eoxfeld@gmail.com>",

"listenercount": "~1.0.1",
"readable-stream": "~2.1.5",
"readable-stream": "~2.3.6",
"setimmediate": "~1.0.4"

@@ -39,4 +39,4 @@ },

"aws-sdk": "^2.77.0",
"request": "^2.79.0",
"tap": "^10.3.2",
"request": "2.79.0",
"tap": ">= 0.3.0 < 1",
"temp": ">= 0.4.0 < 1",

@@ -43,0 +43,0 @@ "dirdiff": ">= 0.0.1 < 1",

# unzipper [![Build Status](https://api.travis-ci.org/ZJONSSON/node-unzipper.png)](https://api.travis-ci.org/ZJONSSON/node-unzipper)
This is a fork of [node-unzip](https://github.com/EvanOxfeld/node-pullstream) which has not been maintained in a while. This fork addresses the following issues:
This is a fork of [node-unzip](https://github.com/EvanOxfeld/node-unzip) which has not been maintained in a while. This fork addresses the following issues:
* finish/close events are not always triggered, particular when the input stream is slower than the receivers

@@ -157,3 +157,3 @@ * Any files are buffered into memory before passing on to entry

.pipe(fs.createWriteStream('firstFile'))
.on('error',reject);
.on('error',reject)
.on('finish',resolve)

@@ -164,4 +164,4 @@ });

### Open.url([requestLibrary], [url])
This function will return a Promise to the central directory information from a URL point to a zipfile. Range-headers are used to avoid reading the whole file. Unzipper does not ship with a request library so you will have to provide it as the first option. The url parameter can either be a string or an object that will be passed to each request (containing the url, but also any optional properties such as cookies, proxy etc)
### Open.url([requestLibrary], [url | options])
This function will return a Promise to the central directory information from a URL point to a zipfile. Range-headers are used to avoid reading the whole file. Unzipper does not ship with a request library so you will have to provide it as the first option.

@@ -186,2 +186,24 @@ Live Example: (extracts a tiny xml file from the middle of a 500MB zipfile)

This function takes a second parameter which can either be a string containing the `url` to request, or an `options` object to invoke the supplied `request` library with. This can be used when other request options are required, such as custom heders or authentication to a third party service.
```js
const request = require('google-oauth-jwt').requestWithJWT();
const googleStorageOptions = {
url: `https://www.googleapis.com/storage/v1/b/m-bucket-name/o/my-object-name`,
qs: { alt: 'media' },
jwt: {
email: google.storage.credentials.client_email,
key: google.storage.credentials.private_key,
scopes: ['https://www.googleapis.com/auth/devstorage.read_only']
}
});
return unzipper.Open.url(request, googleStorageOptions).then((zip) => {
const file = zip.files.find((file) => file.path === 'my-filename');
return file.stream().pipe(res);
});
```
### Open.s3([aws-sdk], [params])

@@ -203,3 +225,3 @@ This function will return a Promise to the central directory information from a zipfile on S3. Range-headers are used to avoid reading the whole file. Unzipper does not ship with with the aws-sdk so you have to provide an instanciated client as first arguments. The params object requires `Bucket` and `Key` to fetch the correct file.

.pipe(fs.createWriteStream('firstFile'))
.on('error',reject);
.on('error',reject)
.on('finish',resolve)

@@ -206,0 +228,0 @@ });

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc