package com.skcraft.playblock.installer.tasks;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import com.sk89q.task.Task;
import com.skcraft.playblock.util.IOUtils;
/**
* Extracts a .zip file's contents to a directory.
*
* <p>
* Zip files may traverse outside their target directory.
* </p>
*/
public class ZipExtract extends Task {
private final File file;
private final File targetDir;
/**
* Extract a given file to a given directory.
*
* @param file
* the file
* @param targetDir
* the target directory
*/
public ZipExtract(File file, File targetDir) {
this.file = file;
this.targetDir = targetDir;
}
@SuppressWarnings("resource")
@Override
protected void execute() throws InterruptedException, ZipException, IOException {
fireProgressChange(0);
fireStatusChange("Prepare to extract " + file.getAbsolutePath() + "...");
targetDir.mkdirs();
ZipFile zip = null;
try {
// Open ZIP file and get a list of entries
zip = new ZipFile(file);
Enumeration<? extends ZipEntry> entries = zip.entries();
int index = 0;
int numEntries = zip.size();
while (entries.hasMoreElements()) {
if (Thread.interrupted()) {
throw new InterruptedException();
}
index++;
ZipEntry entry = entries.nextElement();
String entryName = entry.getName();
File destFile = new File(targetDir, entryName);
File destFolder = destFile.getParentFile();
destFolder.mkdirs();
// Fire events
fireProgressChange(index / (double) numEntries);
fireStatusChange("Extracting " + entryName + "...");
if (entry.isDirectory()) {
destFile.mkdir();
} else {
BufferedInputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(zip.getInputStream(entry));
out = new BufferedOutputStream(new FileOutputStream(destFile));
StreamCopy copy = new StreamCopy(in, out);
copy.execute();
} finally {
IOUtils.close(in);
IOUtils.close(out);
}
}
}
} finally {
IOUtils.close(zip);
}
}
}