UrlsController/src/main/java/eu/openaire/urls_controller/util/FileUnZipper.java

52 lines
2.3 KiB
Java

package eu.openaire.urls_controller.util;
import org.springframework.stereotype.Component;
import java.io.File;
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;
@Component
public class FileUnZipper {
public void unzipFolder(Path source, Path target) throws Exception {
try ( ZipInputStream zis = new ZipInputStream(Files.newInputStream(source.toFile().toPath())) ) {
// Iterate over the files in zip and unzip them.
ZipEntry zipEntry = zis.getNextEntry();
while ( zipEntry != null ) {
String zipEntryName = zipEntry.getName();
Path targetPath = zipSlipProtect(zipEntryName, target);
if ( zipEntryName.endsWith(File.separator) ) // If we have a directory.
Files.createDirectories(targetPath);
else {
// 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);
}
Files.copy(zis, targetPath, StandardCopyOption.REPLACE_EXISTING); // Copy an individual entry.
}
zis.closeEntry();
zipEntry = zis.getNextEntry();
}
// Here the "zipEntry" will always be "null", so no "current ZIP entry" will be open, (so the "closeEntry()" is not needed).
}
}
// Protect from a Zip Slip attack: https://snyk.io/research/zip-slip-vulnerability
public Path zipSlipProtect(String zipEntryName, Path targetDir) throws IOException {
Path targetDirResolved = targetDir.resolve(zipEntryName);
// 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: " + zipEntryName);
}
return normalizePath;
}
}