fix: Allow for zip files with '/' path in central directory
This commit is contained in:
@@ -2,7 +2,7 @@ import path from "path";
|
|||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
import tmp from "tmp";
|
import tmp from "tmp";
|
||||||
import yauzl from "yauzl";
|
import yauzl, { Entry, validateFileName } from "yauzl";
|
||||||
import { bytesToHumanReadable } from "@shared/utils/files";
|
import { bytesToHumanReadable } from "@shared/utils/files";
|
||||||
import Logger from "@server/logging/Logger";
|
import Logger from "@server/logging/Logger";
|
||||||
import { trace } from "@server/logging/tracing";
|
import { trace } from "@server/logging/tracing";
|
||||||
@@ -103,19 +103,32 @@ export default class ZipHelper {
|
|||||||
|
|
||||||
yauzl.open(
|
yauzl.open(
|
||||||
filePath,
|
filePath,
|
||||||
{ lazyEntries: true, autoClose: true },
|
{
|
||||||
|
lazyEntries: true,
|
||||||
|
autoClose: true,
|
||||||
|
// Filenames are validated inside on("entry") handler instead of within yauzl as some
|
||||||
|
// otherwise valid zip files (including those in our test suite) include / path. We can
|
||||||
|
// safely read but skip writing these.
|
||||||
|
// see: https://github.com/thejoshwolfe/yauzl/issues/135
|
||||||
|
decodeStrings: false,
|
||||||
|
},
|
||||||
function (err, zipfile) {
|
function (err, zipfile) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
zipfile.readEntry();
|
zipfile.readEntry();
|
||||||
zipfile.on("entry", function (entry) {
|
zipfile.on("entry", function (entry: Entry) {
|
||||||
Logger.debug("utils", "Extracting zip entry", entry);
|
const fileName = Buffer.from(entry.fileName).toString("utf8");
|
||||||
if (/\/$/.test(entry.fileName)) {
|
Logger.debug("utils", "Extracting zip entry", { fileName });
|
||||||
|
|
||||||
|
if (validateFileName(fileName)) {
|
||||||
|
Logger.warn("Invalid zip entry", { fileName });
|
||||||
|
zipfile.readEntry();
|
||||||
|
} else if (/\/$/.test(fileName)) {
|
||||||
// directory file names end with '/'
|
// directory file names end with '/'
|
||||||
fs.mkdirp(
|
fs.mkdirp(
|
||||||
path.join(outputDir, entry.fileName),
|
path.join(outputDir, fileName),
|
||||||
function (err: Error) {
|
function (err: Error) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
@@ -131,15 +144,13 @@ export default class ZipHelper {
|
|||||||
}
|
}
|
||||||
// ensure parent directory exists
|
// ensure parent directory exists
|
||||||
fs.mkdirp(
|
fs.mkdirp(
|
||||||
path.join(outputDir, path.dirname(entry.fileName)),
|
path.join(outputDir, path.dirname(fileName)),
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
readStream.pipe(
|
readStream.pipe(
|
||||||
fs.createWriteStream(
|
fs.createWriteStream(path.join(outputDir, fileName))
|
||||||
path.join(outputDir, entry.fileName)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
readStream.on("end", function () {
|
readStream.on("end", function () {
|
||||||
zipfile.readEntry();
|
zipfile.readEntry();
|
||||||
|
|||||||
Reference in New Issue
Block a user