UNPKG

unzipper-esm

Version:
65 lines (51 loc) 1.9 kB
import fs from 'fs'; // 'node:fs' import path from 'path'; // 'node:path' import { Writable } from 'stream'; // 'node:stream' import DuplexStream from './DuplexStream.js'; import Parse from './parse.js'; import ensureDir from './ensureDir.js'; export default function Extract (opts) { // make sure path is normalized before using it opts.path = path.resolve(path.normalize(opts.path)); const parser = Parse(opts); const outStream = new Writable({ objectMode: true, write: async function(entry, encoding, cb) { // 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. // NOTE: Need to normalize to forward slashes for UNIX OS's to properly // ignore the zip slipped file entirely const extractPath = path.join(opts.path, entry.path.replace(/\\/g, '/')); if (extractPath.indexOf(opts.path) != 0) { return cb(); } if (entry.type == 'Directory') { await ensureDir(extractPath); return cb(); } await ensureDir(path.dirname(extractPath)); const writer = opts.getWriter ? opts.getWriter({path: extractPath}) : fs.createWriteStream(extractPath); entry.pipe(writer) .on('error', cb) .on('close', cb); } }); // Create a combined stream const extract = new DuplexStream(parser, outStream); parser.once('crx-header', function(crxHeader) { extract.crxHeader = crxHeader; }); parser .pipe(outStream) .on('finish', function() { extract.emit('close'); }); extract.promise = function() { return new Promise(function(resolve, reject) { extract.on('close', resolve); extract.on('error', reject); }); }; return extract; }