AbstractModifyFileTask.java
package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderUtil;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.util.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.security.SecureRandom;
abstract class AbstractModifyFileTask<T> extends AsyncZipTask<T> {
AbstractModifyFileTask(AsyncTaskParameters asyncTaskParameters) {
super(asyncTaskParameters);
}
File getTemporaryFile(String zipPathWithName) {
SecureRandom random = new SecureRandom();
File tmpFile = new File(zipPathWithName + random.nextInt(10000));
while (tmpFile.exists()) {
tmpFile = new File(zipPathWithName + random.nextInt(10000));
}
return tmpFile;
}
void updateOffsetsForAllSubsequentFileHeaders(List<FileHeader> sortedFileHeaders, ZipModel zipModel,
FileHeader fileHeaderModified, long offsetToAdd) throws ZipException {
int indexOfFileHeader = getIndexOfFileHeader(sortedFileHeaders, fileHeaderModified);
if (indexOfFileHeader == -1) {
throw new ZipException("Could not locate modified file header in zipModel");
}
for (int i = indexOfFileHeader + 1; i < sortedFileHeaders.size(); i++) {
FileHeader fileHeaderToUpdate = sortedFileHeaders.get(i);
fileHeaderToUpdate.setOffsetLocalHeader(fileHeaderToUpdate.getOffsetLocalHeader() + offsetToAdd);
if (zipModel.isZip64Format()
&& fileHeaderToUpdate.getZip64ExtendedInfo() != null
&& fileHeaderToUpdate.getZip64ExtendedInfo().getOffsetLocalHeader() != -1) {
fileHeaderToUpdate.getZip64ExtendedInfo().setOffsetLocalHeader(
fileHeaderToUpdate.getZip64ExtendedInfo().getOffsetLocalHeader() + offsetToAdd
);
}
}
}
void cleanupFile(boolean successFlag, File zipFile, File temporaryZipFile) throws ZipException {
if (successFlag) {
restoreFileName(zipFile, temporaryZipFile);
} else {
if (!temporaryZipFile.delete()) {
throw new ZipException("Could not delete temporary file");
}
}
}
long copyFile(RandomAccessFile randomAccessFile, OutputStream outputStream, long start, long length,
ProgressMonitor progressMonitor, int bufferSize) throws IOException {
FileUtils.copyFile(randomAccessFile, outputStream, start, start + length, progressMonitor, bufferSize);
return length;
}
List<FileHeader> cloneAndSortFileHeadersByOffset(List<FileHeader> allFileHeaders) {
List<FileHeader> clonedFileHeaders = new ArrayList<>(allFileHeaders);
//noinspection Java8ListSort
Collections.sort(clonedFileHeaders, new Comparator<FileHeader>() {
@Override
public int compare(FileHeader o1, FileHeader o2) {
if (o1.getFileName().equals(o2.getFileName())) {
return 0;
}
return o1.getOffsetLocalHeader() < o2.getOffsetLocalHeader() ? -1 : 1;
}
});
return clonedFileHeaders;
}
long getOffsetOfNextEntry(List<FileHeader> sortedFileHeaders, FileHeader fileHeader,
ZipModel zipModel) throws ZipException {
int indexOfFileHeader = getIndexOfFileHeader(sortedFileHeaders, fileHeader);
if (indexOfFileHeader == sortedFileHeaders.size() - 1) {
return HeaderUtil.getOffsetStartOfCentralDirectory(zipModel);
} else {
return sortedFileHeaders.get(indexOfFileHeader + 1).getOffsetLocalHeader();
}
}
private void restoreFileName(File zipFile, File temporaryZipFile) throws ZipException {
if (zipFile.delete()) {
if (!temporaryZipFile.renameTo(zipFile)) {
throw new ZipException("cannot rename modified zip file");
}
} else {
throw new ZipException("cannot delete old zip file");
}
}
private int getIndexOfFileHeader(List<FileHeader> allFileHeaders, FileHeader fileHeaderForIndex) throws ZipException {
for (int i = 0; i < allFileHeaders.size(); i++) {
FileHeader fileHeader = allFileHeaders.get(i);
if (fileHeader.equals(fileHeaderForIndex)) {
return i;
}
}
throw new ZipException("Could not find file header in list of central directory file headers");
}
}