From dfd79953c5dea5f09724ba03dc89e4003d006831 Mon Sep 17 00:00:00 2001 From: Jalila BAALI Date: Fri, 3 Apr 2026 20:57:36 +0200 Subject: [PATCH 1/4] Fix: Decompress folder retain their original timestamps --- .../filemanager/activities/DecompressActivity.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt index 39d03354..a55fe7e6 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt @@ -155,6 +155,7 @@ class DecompressActivity : SimpleActivity() { zipInputStream.setPassword(password?.toCharArray()) } val buffer = ByteArray(1024) + val foldersTimestamp = mutableListOf>() zipInputStream.use { while (true) { @@ -162,6 +163,7 @@ class DecompressActivity : SimpleActivity() { val filename = filename.substringBeforeLast(".") val parent = "$destination/$filename" val newPath = "$parent/${entry.fileName.trimEnd('/')}" + val outputFile = File(newPath) if (!getDoesFilePathExist(parent)) { if (!createDirectorySync(parent)) { @@ -170,10 +172,14 @@ class DecompressActivity : SimpleActivity() { } if (entry.isDirectory) { + if (!getDoesFilePathExist(newPath)) { + createDirectorySync(newPath) + } + + foldersTimestamp.add(Pair(outputFile,entry)) continue - } - val outputFile = File(newPath) + } val isVulnerableForZipPathTraversal = !outputFile.canonicalPath.startsWith(parent) if (isVulnerableForZipPathTraversal) { @@ -193,7 +199,9 @@ class DecompressActivity : SimpleActivity() { fos!!.close() outputFile.setLastModified(entry) } - + for ((folder,header) in foldersTimestamp){ + folder.setLastModified((header)) + } toast(R.string.decompression_successful) finish() } From 4494f15a477a1fa87c8a1f39614c7d009b814ded Mon Sep 17 00:00:00 2001 From: Jalila BAALI Date: Thu, 16 Apr 2026 00:43:42 +0200 Subject: [PATCH 2/4] Fix: Preserve folder timestamps when decompressing --- .../filemanager/activities/DecompressActivity.kt | 16 ++++++++-------- .../fossify/filemanager/adapters/ItemsAdapter.kt | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt index a55fe7e6..dfb108ad 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt @@ -163,7 +163,7 @@ class DecompressActivity : SimpleActivity() { val filename = filename.substringBeforeLast(".") val parent = "$destination/$filename" val newPath = "$parent/${entry.fileName.trimEnd('/')}" - val outputFile = File(newPath) + if (!getDoesFilePathExist(parent)) { if (!createDirectorySync(parent)) { @@ -172,14 +172,14 @@ class DecompressActivity : SimpleActivity() { } if (entry.isDirectory) { - if (!getDoesFilePathExist(newPath)) { - createDirectorySync(newPath) + val dir = File(newPath) + if (!dir.exists()) { + dir.mkdirs() } - - foldersTimestamp.add(Pair(outputFile,entry)) + foldersTimestamp.add(Pair(dir, entry)) continue - } + val outputFile = File(newPath) val isVulnerableForZipPathTraversal = !outputFile.canonicalPath.startsWith(parent) if (isVulnerableForZipPathTraversal) { @@ -199,8 +199,8 @@ class DecompressActivity : SimpleActivity() { fos!!.close() outputFile.setLastModified(entry) } - for ((folder,header) in foldersTimestamp){ - folder.setLastModified((header)) + for ((dir, entry) in foldersTimestamp.asReversed()) { + dir.setLastModified(entry) } toast(R.string.decompression_successful) finish() diff --git a/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt b/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt index bea52946..90b471f4 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt @@ -720,6 +720,8 @@ class ItemsAdapter( paths.forEach { path -> val zipInputStream = ZipInputStream(BufferedInputStream(activity.getFileInputStreamSync(path))) + + val foldersTimestamp = mutableListOf>() 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> ) { 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()) From 0faeabca3bbeeb7a99eb548c4e02743a2821e2c9 Mon Sep 17 00:00:00 2001 From: Jalila BAALI Date: Sun, 31 May 2026 22:43:33 +0200 Subject: [PATCH 3/4] Fix: path validation placed before directory entries --- CHANGELOG.md | 4 ++++ .../activities/DecompressActivity.kt | 20 +++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79f79d89..a79ac5dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.6.2] - 2026-05-31 +### Fixed +- Fixed the modification of the original timestamp when decompressing folders ([#190]) + ## [1.6.1] - 2026-02-14 ### Changed - Updated translations diff --git a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt index dfb108ad..350c9c5b 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt @@ -171,14 +171,6 @@ class DecompressActivity : SimpleActivity() { } } - if (entry.isDirectory) { - val dir = File(newPath) - if (!dir.exists()) { - dir.mkdirs() - } - foldersTimestamp.add(Pair(dir, entry)) - continue - } val outputFile = File(newPath) val isVulnerableForZipPathTraversal = !outputFile.canonicalPath.startsWith(parent) @@ -186,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) { @@ -199,8 +199,8 @@ class DecompressActivity : SimpleActivity() { fos!!.close() outputFile.setLastModified(entry) } - for ((dir, entry) in foldersTimestamp.asReversed()) { - dir.setLastModified(entry) + for ((outputFile, entry) in foldersTimestamp.asReversed()) { + outputFile.setLastModified(entry) } toast(R.string.decompression_successful) finish() From 2b9eed02b907dfa2e978fc2dd529a7bb6ad42269 Mon Sep 17 00:00:00 2001 From: Naveen Singh <36371707+naveensingh@users.noreply.github.com> Date: Mon, 1 Jun 2026 14:49:41 +0530 Subject: [PATCH 4/4] docs(changelog): remove manually added release version It's updated by @fossifybot --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a79ac5dd..fd08943f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,6 @@ 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] - -## [1.6.2] - 2026-05-31 ### Fixed - Fixed the modification of the original timestamp when decompressing folders ([#190])