Files
Foundry-VTT-Docker/resources/app/node_modules/unzipper/lib/Open/unzip.js
2025-01-04 00:34:03 +01:00

121 lines
3.5 KiB
JavaScript

const Decrypt = require('../Decrypt');
const PullStream = require('../PullStream');
const Stream = require('stream');
const zlib = require('zlib');
const parseExtraField = require('../parseExtraField');
const parseDateTime = require('../parseDateTime');
const parseBuffer = require('../parseBuffer');
module.exports = function unzip(source, offset, _password, directoryVars, length) {
const file = PullStream(),
entry = Stream.PassThrough();
const req = source.stream(offset, length);
req.pipe(file).on('error', function(e) {
entry.emit('error', e);
});
entry.vars = file.pull(30)
.then(function(data) {
let vars = parseBuffer.parse(data, [
['signature', 4],
['versionsNeededToExtract', 2],
['flags', 2],
['compressionMethod', 2],
['lastModifiedTime', 2],
['lastModifiedDate', 2],
['crc32', 4],
['compressedSize', 4],
['uncompressedSize', 4],
['fileNameLength', 2],
['extraFieldLength', 2],
]);
vars.lastModifiedDateTime = parseDateTime(vars.lastModifiedDate, vars.lastModifiedTime);
return file.pull(vars.fileNameLength)
.then(function(fileName) {
vars.fileName = fileName.toString('utf8');
return file.pull(vars.extraFieldLength);
})
.then(function(extraField) {
let checkEncryption;
vars.extra = parseExtraField(extraField, vars);
// Ignore logal file header vars if the directory vars are available
if (directoryVars && directoryVars.compressedSize) vars = directoryVars;
if (vars.flags & 0x01) checkEncryption = file.pull(12)
.then(function(header) {
if (!_password)
throw new Error('MISSING_PASSWORD');
const decrypt = Decrypt();
String(_password).split('').forEach(function(d) {
decrypt.update(d);
});
for (let i=0; i < header.length; i++)
header[i] = decrypt.decryptByte(header[i]);
vars.decrypt = decrypt;
vars.compressedSize -= 12;
const check = (vars.flags & 0x8) ? (vars.lastModifiedTime >> 8) & 0xff : (vars.crc32 >> 24) & 0xff;
if (header[11] !== check)
throw new Error('BAD_PASSWORD');
return vars;
});
return Promise.resolve(checkEncryption)
.then(function() {
entry.emit('vars', vars);
return vars;
});
});
});
entry.vars.then(function(vars) {
const fileSizeKnown = !(vars.flags & 0x08) || vars.compressedSize > 0;
let eof;
const inflater = vars.compressionMethod ? zlib.createInflateRaw() : Stream.PassThrough();
if (fileSizeKnown) {
entry.size = vars.uncompressedSize;
eof = vars.compressedSize;
} else {
eof = Buffer.alloc(4);
eof.writeUInt32LE(0x08074b50, 0);
}
let stream = file.stream(eof);
if (vars.decrypt)
stream = stream.pipe(vars.decrypt.stream());
stream
.pipe(inflater)
.on('error', function(err) { entry.emit('error', err);})
.pipe(entry)
.on('finish', function() {
if(req.destroy)
req.destroy();
else if (req.abort)
req.abort();
else if (req.close)
req.close();
else if (req.push)
req.push();
else
console.log('warning - unable to close stream');
});
})
.catch(function(e) {
entry.emit('error', e);
});
return entry;
};