Skip to content

Commit

Permalink
Fix: 7zip extract only the exact intended archive entry (#772)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmercm authored Oct 21, 2023
1 parent 6ebe652 commit f3195da
Showing 1 changed file with 14 additions and 19 deletions.
33 changes: 14 additions & 19 deletions src/types/files/archives/sevenZip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,19 @@ export default class SevenZip extends Archive {
): Promise<void> {
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<void>((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 {
Expand All @@ -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);
Expand Down

0 comments on commit f3195da

Please sign in to comment.