forked from lix-project/lix-website
62 lines
1.4 KiB
JavaScript
62 lines
1.4 KiB
JavaScript
|
module.exports = Extract;
|
||
|
|
||
|
var Parse = require('./parse');
|
||
|
var Writer = require('fstream').Writer;
|
||
|
var util = require('util');
|
||
|
var path = require('path');
|
||
|
|
||
|
util.inherits(Extract, Parse);
|
||
|
|
||
|
function Extract (opts) {
|
||
|
if (!(this instanceof Extract))
|
||
|
return new Extract(opts);
|
||
|
|
||
|
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();
|
||
|
};
|
||
|
|
||
|
// make sure path is normalized before using it
|
||
|
opts.path = path.normalize(opts.path);
|
||
|
|
||
|
Parse.call(self,opts);
|
||
|
|
||
|
self.on('entry', function(entry) {
|
||
|
if (entry.type == 'Directory') return;
|
||
|
|
||
|
// 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();
|
||
|
});
|
||
|
});
|
||
|
}
|