From 1c4ba0706a460a6ba7eabe459ea08babef187bd0 Mon Sep 17 00:00:00 2001 From: Ziggy Jonsson Date: Sat, 11 May 2024 14:38:51 -0400 Subject: [PATCH] Retry stream if not big enough --- lib/Open/unzip.js | 17 ++++++++++++++--- test/office-files.js | 26 ++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/Open/unzip.js b/lib/Open/unzip.js index 5cb0ef1..079ca7d 100644 --- a/lib/Open/unzip.js +++ b/lib/Open/unzip.js @@ -6,9 +6,9 @@ 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(); +module.exports = function unzip(source, offset, _password, directoryVars, length, _entry) { + var file = PullStream(), + entry = _entry || Stream.PassThrough(); const req = source.stream(offset, length); req.pipe(file).on('error', function(e) { @@ -34,6 +34,17 @@ module.exports = function unzip(source, offset, _password, directoryVars, length ['extraFieldLength', 2], ]); + var localSize = 30 + + 100 // add extra padding + + (vars.extraFieldLength || 0) + + (vars.fileNameLength || 0) + + vars.compressedSize; + + if (localSize > length) { + entry.emit('streamRetry', localSize); + return unzip(source, offset, _password, directoryVars, localSize, entry); + } + vars.lastModifiedDateTime = parseDateTime(vars.lastModifiedDate, vars.lastModifiedTime); const fileName = await file.pull(vars.fileNameLength); diff --git a/test/office-files.js b/test/office-files.js index b7baabe..00068e2 100644 --- a/test/office-files.js +++ b/test/office-files.js @@ -2,8 +2,16 @@ const test = require('tap').test; const path = require('path'); const unzip = require('../'); -test("get content a docx file without errors", async function () { - const archive = path.join(__dirname, '../testData/office/testfile.docx'); +var test = require('tap').test; +var fs = require('fs'); +var path = require('path'); +var unzip = require('../'); +var il = require('iconv-lite'); +var Promise = require('bluebird'); +var NoopStream = require('../lib/NoopStream'); + +test("get content a docx file without errors", async function (t) { + var archive = path.join(__dirname, '../testData/office/testfile.docx'); const directory = await unzip.Open.file(archive); await Promise.all(directory.files.map(file => file.buffer())); @@ -14,4 +22,18 @@ test("get content a xlsx file without errors", async function () { const directory = await unzip.Open.file(archive); await Promise.all(directory.files.map(file => file.buffer())); +}); + +test("stream retries when the local file header indicates bigger size than central directory", async function (t) { + var archive = path.join(__dirname, '../testData/office/testfile.xlsx'); + let retries = 0, size; + const directory = await unzip.Open.file(archive, {padding: 10}); + const stream = directory.files[0].stream(); + stream.on('streamRetry', _size => { + retries += 1; + size = _size; + }); + await new Promise(resolve => stream.pipe(NoopStream()).on('finish', resolve)); + t.ok(retries === 1, 'retries once'); + t.ok(size > 0, 'size is set'); }); \ No newline at end of file