From c9d802d10c983221b642bb9e89502e3d748dddc5 Mon Sep 17 00:00:00 2001 From: Radek Davidek Date: Tue, 19 May 2026 14:46:32 +0200 Subject: [PATCH] fixed posix --- .../kfmanager/service/FileOperations.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java index 7efe33e..c28151a 100644 --- a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java +++ b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java @@ -1292,6 +1292,8 @@ public class FileOperations { long total = countZipEntries(zipBytes); long current = 0; byte[] buffer = new byte[65536]; + java.util.Map zipEntryModes = readZipEntryModes(archive); + java.util.Map directoryModes = new java.util.LinkedHashMap<>(); try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes))) { ZipEntry entry; @@ -1301,8 +1303,12 @@ public class FileOperations { } File targetFile = secureZipTarget(targetDir, entry.getName()); + Integer mode = zipEntryModes.get(entry.getName()); if (entry.isDirectory()) { targetFile.mkdirs(); + if (mode != null && mode > 0) { + directoryModes.put(targetFile, mode); + } } else { File parent = targetFile.getParentFile(); if (parent != null) { @@ -1317,6 +1323,9 @@ public class FileOperations { out.write(buffer, 0, len); } } + if (mode != null && mode > 0) { + applyPosixPermissions(targetFile, mode); + } } current++; @@ -1324,9 +1333,33 @@ public class FileOperations { callback.onProgress(current, total, entry.getName()); } } + for (java.util.Map.Entry directoryMode : directoryModes.entrySet()) { + applyPosixPermissions(directoryMode.getKey(), directoryMode.getValue()); + } } } + private static java.util.Map readZipEntryModes(File archive) { + java.util.Map modes = new java.util.HashMap<>(); + try (ZipFile zipFile = new ZipFile(archive)) { + for (net.lingala.zip4j.model.FileHeader header : zipFile.getFileHeaders()) { + int mode = zipHeaderMode(header); + if (mode > 0) { + modes.put(header.getFileName(), mode); + } + } + } catch (Exception ignore) { + // Best effort; extraction still works without permission metadata. + } + return modes; + } + + private static int zipHeaderMode(net.lingala.zip4j.model.FileHeader header) { + byte[] externalAttributes = header.getExternalFileAttributes(); + if (externalAttributes == null || externalAttributes.length < 4) return 0; + return ((externalAttributes[3] & 0xFF) << 8) | (externalAttributes[2] & 0xFF); + } + private static void extractZip(File archive, File targetDir, ProgressCallback callback) throws IOException { String password = null; try (ZipFile zipFile = new ZipFile(archive)) { @@ -1347,7 +1380,7 @@ public class FileOperations { byte[] externalAttributes = header.getExternalFileAttributes(); if (externalAttributes != null && externalAttributes.length >= 4) { // Unix mode is stored in the upper 16 bits of the external file attributes - int mode = ((externalAttributes[3] & 0xFF) << 8) | (externalAttributes[2] & 0xFF); + int mode = zipHeaderMode(header); if (mode > 0) { File extractedFile = new File(targetDir, header.getFileName()); applyPosixPermissions(extractedFile, mode);