fix: preserve timestamps when decompressing folders (#422)

Refs: https://github.com/FossifyOrg/File-Manager/issues/190
This commit is contained in:
jbaali
2026-06-01 11:21:51 +02:00
committed by GitHub
parent 878fa50963
commit 5e316369df
3 changed files with 27 additions and 9 deletions

View File

@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- Fixed the modification of the original timestamp when decompressing folders ([#190])
## [1.6.1] - 2026-02-14
### Changed

View File

@@ -155,6 +155,7 @@ class DecompressActivity : SimpleActivity() {
zipInputStream.setPassword(password?.toCharArray())
}
val buffer = ByteArray(1024)
val foldersTimestamp = mutableListOf<Pair<File, LocalFileHeader>>()
zipInputStream.use {
while (true) {
@@ -163,16 +164,13 @@ class DecompressActivity : SimpleActivity() {
val parent = "$destination/$filename"
val newPath = "$parent/${entry.fileName.trimEnd('/')}"
if (!getDoesFilePathExist(parent)) {
if (!createDirectorySync(parent)) {
continue
}
}
if (entry.isDirectory) {
continue
}
val outputFile = File(newPath)
val isVulnerableForZipPathTraversal = !outputFile.canonicalPath.startsWith(parent)
@@ -180,6 +178,14 @@ class DecompressActivity : SimpleActivity() {
continue
}
if (entry.isDirectory) {
if (!outputFile.exists()) {
outputFile.mkdirs()
}
foldersTimestamp.add(Pair(outputFile, entry))
continue
}
val fos = getFileOutputStreamSync(newPath, newPath.getMimeType())
var count: Int
while (true) {
@@ -193,7 +199,9 @@ class DecompressActivity : SimpleActivity() {
fos!!.close()
outputFile.setLastModified(entry)
}
for ((outputFile, entry) in foldersTimestamp.asReversed()) {
outputFile.setLastModified(entry)
}
toast(R.string.decompression_successful)
finish()
}

View File

@@ -720,6 +720,8 @@ class ItemsAdapter(
paths.forEach { path ->
val zipInputStream =
ZipInputStream(BufferedInputStream(activity.getFileInputStreamSync(path)))
val foldersTimestamp = mutableListOf<Pair<File, LocalFileHeader>>()
zipInputStream.use {
try {
var entry = zipInputStream.nextEntry
@@ -740,7 +742,7 @@ class ItemsAdapter(
if (activity.getIsPathDirectory(path)) {
activity.deleteFolderBg(fileDirItem, false) {
if (it) {
extractEntry(newPath, entry, zipInputStream)
extractEntry(newPath, entry, zipInputStream, foldersTimestamp)
} else {
callback(false)
}
@@ -748,18 +750,21 @@ class ItemsAdapter(
} else {
activity.deleteFileBg(fileDirItem, false, false) {
if (it) {
extractEntry(newPath, entry, zipInputStream)
extractEntry(newPath, entry, zipInputStream, foldersTimestamp)
} else {
callback(false)
}
}
}
} else if (!doesPathExist) {
extractEntry(newPath, entry, zipInputStream)
extractEntry(newPath, entry, zipInputStream, foldersTimestamp)
}
entry = zipInputStream.nextEntry
}
for ((dir, header) in foldersTimestamp.asReversed()) {
dir.setLastModified(header)
}
callback(true)
} catch (e: Exception) {
activity.showErrorToast(e)
@@ -772,13 +777,16 @@ class ItemsAdapter(
private fun extractEntry(
newPath: String,
entry: LocalFileHeader,
zipInputStream: ZipInputStream
zipInputStream: ZipInputStream,
foldersTimestamp: MutableList<Pair<File, LocalFileHeader>>
) {
if (entry.isDirectory) {
if (!activity.createDirectorySync(newPath) && !activity.getDoesFilePathExist(newPath)) {
val error =
String.format(activity.getString(R.string.could_not_create_file), newPath)
activity.showErrorToast(error)
} else {
foldersTimestamp.add(Pair(File(newPath), entry))
}
} else {
val fos = activity.getFileOutputStreamSync(newPath, newPath.getMimeType())