mirror of
https://github.com/FossifyOrg/File-Manager.git
synced 2026-07-30 09:58:13 -04:00
fix: preserve timestamps when decompressing folders (#422)
Refs: https://github.com/FossifyOrg/File-Manager/issues/190
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user