2021-11-30 17:23:27 +01:00
|
|
|
package eu.openaire.urls_controller.util;
|
|
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2022-01-30 21:14:52 +01:00
|
|
|
import org.springframework.stereotype.Component;
|
2021-11-30 17:23:27 +01:00
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.nio.file.Files;
|
|
|
|
import java.nio.file.Path;
|
|
|
|
import java.nio.file.StandardCopyOption;
|
|
|
|
import java.util.zip.ZipEntry;
|
|
|
|
import java.util.zip.ZipInputStream;
|
|
|
|
|
2022-01-30 21:14:52 +01:00
|
|
|
@Component
|
2021-11-30 17:23:27 +01:00
|
|
|
public class FileUnZipper {
|
|
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(FileUnZipper.class);
|
|
|
|
|
2022-01-30 21:14:52 +01:00
|
|
|
public void unzipFolder(Path source, Path target) throws Exception {
|
|
|
|
try ( ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile())) ) {
|
2021-11-30 17:23:27 +01:00
|
|
|
// Iterate over the files in zip and un-zip them.
|
|
|
|
ZipEntry zipEntry = zis.getNextEntry();
|
2022-01-30 21:14:52 +01:00
|
|
|
while ( zipEntry != null ) {
|
2021-11-30 17:23:27 +01:00
|
|
|
Path targetPath = zipSlipProtect(zipEntry, target);
|
|
|
|
|
|
|
|
if ( zipEntry.getName().endsWith(File.separator) ) // If we have a directory.
|
|
|
|
Files.createDirectories(targetPath);
|
|
|
|
else {
|
2021-12-21 14:55:27 +01:00
|
|
|
// Some zip -files store only the file-paths and not separate directories. We need to create parent directories, e.g data/folder/file.txt
|
|
|
|
Path parentPath = targetPath.getParent();
|
|
|
|
if ( (parentPath != null) && Files.notExists(parentPath) ) {
|
|
|
|
Files.createDirectories(parentPath);
|
2021-11-30 17:23:27 +01:00
|
|
|
}
|
2021-12-21 14:55:27 +01:00
|
|
|
Files.copy(zis, targetPath, StandardCopyOption.REPLACE_EXISTING); // Copy an individual entry.
|
2021-11-30 17:23:27 +01:00
|
|
|
}
|
|
|
|
zipEntry = zis.getNextEntry();
|
|
|
|
}
|
|
|
|
zis.closeEntry();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Protect from a Zip Slip attack: https://snyk.io/research/zip-slip-vulnerability
|
2022-01-30 21:14:52 +01:00
|
|
|
public Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException {
|
2021-11-30 17:23:27 +01:00
|
|
|
Path targetDirResolved = targetDir.resolve(zipEntry.getName());
|
|
|
|
// Make sure normalized file still has targetDir as its prefix, else throw an exception.
|
|
|
|
Path normalizePath = targetDirResolved.normalize();
|
|
|
|
if ( !normalizePath.startsWith(targetDir) ) {
|
|
|
|
throw new IOException("Bad zip entry: " + zipEntry.getName());
|
|
|
|
}
|
|
|
|
return normalizePath;
|
|
|
|
}
|
2022-01-30 21:14:52 +01:00
|
|
|
}
|