/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
*/
package zip4cj.tasks
public abstract class AbstractModifyFileTask<T> <: AsyncZipTask<T> {
init(asyncTaskParameters: AsyncTaskParameters) {
super(asyncTaskParameters)
}
protected func getTemporaryFile(zipPathWithName: String): Path {
var random: SecureRandom = SecureRandom()
var tmpFile: Path = Path(zipPathWithName + "${random.nextInt32(10000)}")
while (exists(tmpFile)) {
tmpFile = Path(zipPathWithName + "${random.nextInt32(10000)}")
}
return tmpFile
}
func updateOffsetsForAllSubsequentFileHeaders(
sortedFileHeaders: Array<FileHeader>,
zipModel: ZipModel,
fileHeaderModified: FileHeader,
offsetToAdd: Int64
) {
var indexOfFileHeader: Int32 = getIndexOfFileHeader(sortedFileHeaders, fileHeaderModified)
if (indexOfFileHeader == -1) {
throw ZipException("Could not locate modified file header in zipModel")
}
for (i in Int64(indexOfFileHeader + 1)..sortedFileHeaders.size) {
var fileHeaderToUpdate: FileHeader = sortedFileHeaders.get(i).getOrThrow()
fileHeaderToUpdate.setOffsetLocalHeader(fileHeaderToUpdate.getOffsetLocalHeader() + offsetToAdd)
if (zipModel.isZip64Format() && fileHeaderToUpdate.getZip64ExtendedInfo().isSome() &&
fileHeaderToUpdate.getZip64ExtendedInfo().getOrThrow().getOffsetLocalHeader() != -1) {
fileHeaderToUpdate.getZip64ExtendedInfo().getOrThrow().setOffsetLocalHeader(
fileHeaderToUpdate.getZip64ExtendedInfo().getOrThrow().getOffsetLocalHeader() + offsetToAdd)
}
}
}
func cleanupFile(successFlag: Bool, zipFile: Path, temporaryZipFile: Path) {
if (successFlag) {
restoreFileName(zipFile, temporaryZipFile)
()
} else {
try {
remove(temporaryZipFile, recursive: true)
} catch (e: Exception) {
throw ZipException("Could not delete temporary file")
}
}
}
func copyFile(
randomAccessFile: RandomAccessFile,
outputStream: OutputStream,
start: Int64,
length: Int64,
progressMonitor: ProgressMonitor,
bufferSize: Int64
): Int64 {
FileUtils.copyFile(randomAccessFile, outputStream, start, start + length, progressMonitor, Int64(bufferSize))
return length
}
func cloneAndSortFileHeadersByOffset(allFileHeaders: ArrayList<FileHeader>): Array<FileHeader> {
let clonedFileHeaders: Array<FileHeader> = allFileHeaders.toArray()
stableSort<FileHeader>(clonedFileHeaders, {a,b =>
if (a.getFileName() == b.getFileName()) {
return Ordering.EQ
} else if (a.getOffsetLocalHeader() < b.getOffsetLocalHeader()) {
return Ordering.LT
} else if (a.getOffsetLocalHeader() > b.getOffsetLocalHeader()) {
return Ordering.GT
} else {
return Ordering.EQ
}
})
return clonedFileHeaders
}
func getOffsetOfNextEntry(sortedFileHeaders: Array<FileHeader>, fileHeader: FileHeader, zipModel: ZipModel): Int64 {
var indexOfFileHeader: Int32 = getIndexOfFileHeader(sortedFileHeaders, fileHeader)
if (Int64(indexOfFileHeader) == sortedFileHeaders.size - 1) {
return HeaderUtil.getOffsetStartOfCentralDirectory(zipModel)
} else {
return sortedFileHeaders.get(Int64(indexOfFileHeader + 1)).getOrThrow().getOffsetLocalHeader()
}
}
// TODO restore FileName
private func restoreFileName(zipFile: Path, temporaryZipFile: Path) {
try {
remove(zipFile, recursive: true)
try {
rename(temporaryZipFile, to: zipFile, overwrite: true)
} catch (e: Exception) {
throw ZipException("cannot rename modified zip file")
}
} catch (e: Exception) {
throw ZipException("cannot delete old zip file")
}
}
private func getIndexOfFileHeader(allFileHeaders: Array<FileHeader>, fileHeaderForIndex: FileHeader): Int32 {
for (i in 0..allFileHeaders.size) {
var fileHeader: FileHeader = allFileHeaders.get(i).getOrThrow()
if (fileHeader.equals(fileHeaderForIndex)) {
return Int32(i)
}
}
throw ZipException("Could not find file header in list of central directory file headers")
}
}