From f3195daa9a1c05b0cf5bbf7c40338e4128028b97 Mon Sep 17 00:00:00 2001 From: Christian Emmer <10749361+emmercm@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:33:59 -0700 Subject: [PATCH] Fix: 7zip extract only the exact intended archive entry (#772) --- src/types/files/archives/sevenZip.ts | 33 ++++++++++++---------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/types/files/archives/sevenZip.ts b/src/types/files/archives/sevenZip.ts index 71f9efc5d..83443404b 100644 --- a/src/types/files/archives/sevenZip.ts +++ b/src/types/files/archives/sevenZip.ts @@ -108,12 +108,19 @@ export default class SevenZip extends Archive { ): Promise { const tempDir = await fsPoly.mkdtemp(path.join(Constants.GLOBAL_TEMP_DIR, '7z')); try { - // https://github.com/onikienko/7zip-min/issues/71 - // Work around `7zip-min.unpack()` not being able to extract a single file at a time let tempFile = path.join(tempDir, entryPath); - await new Promise((resolve, reject) => { - _7z.unpack(this.getFilePath(), tempDir, (err) => { + _7z.cmd([ + // _7z.unpack() flags + 'x', + this.getFilePath(), + '-y', + `-o${tempDir}`, + // https://github.com/onikienko/7zip-min/issues/71 + // Extract only the single archive entry + entryPath, + '-r', + ], (err) => { if (err) { reject(err); } else { @@ -124,26 +131,14 @@ export default class SevenZip extends Archive { // https://github.com/onikienko/7zip-min/issues/86 // Fix `7zip-min.list()` returning unicode entry names as � on Windows - // This is really only an issue until https://github.com/onikienko/7zip-min/issues/71 (above) - // is addressed if (process.platform === 'win32' && !await fsPoly.exists(tempFile)) { const files = await fsPoly.walk(tempDir); if (files.length === 0) { throw new Error('failed to extract any files'); + } else if (files.length > 1) { + throw new Error('extracted too many files'); } - const actualTempFile = files.find((file) => { - const pattern = file - .replace(tempDir + path.sep, '') - // Convert all non-ASCII characters into single character matches - .replace(/\./g, '\\.') - .replace(/[^\x00-\x7F]/g, '.'); - const regex = new RegExp(`^${pattern}$`); - return entryPath.match(regex) !== null; - }); - if (!actualTempFile) { - throw new Error('failed to find the extracted file'); - } - tempFile = actualTempFile; + [tempFile] = files; } await fsPoly.mv(tempFile, extractedFilePath);