fixed posix

This commit is contained in:
Radek Davidek 2026-05-19 14:46:32 +02:00
parent aeef004664
commit c9d802d10c

View File

@ -1292,6 +1292,8 @@ public class FileOperations {
long total = countZipEntries(zipBytes); long total = countZipEntries(zipBytes);
long current = 0; long current = 0;
byte[] buffer = new byte[65536]; byte[] buffer = new byte[65536];
java.util.Map<String, Integer> zipEntryModes = readZipEntryModes(archive);
java.util.Map<File, Integer> directoryModes = new java.util.LinkedHashMap<>();
try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes))) { try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes))) {
ZipEntry entry; ZipEntry entry;
@ -1301,8 +1303,12 @@ public class FileOperations {
} }
File targetFile = secureZipTarget(targetDir, entry.getName()); File targetFile = secureZipTarget(targetDir, entry.getName());
Integer mode = zipEntryModes.get(entry.getName());
if (entry.isDirectory()) { if (entry.isDirectory()) {
targetFile.mkdirs(); targetFile.mkdirs();
if (mode != null && mode > 0) {
directoryModes.put(targetFile, mode);
}
} else { } else {
File parent = targetFile.getParentFile(); File parent = targetFile.getParentFile();
if (parent != null) { if (parent != null) {
@ -1317,6 +1323,9 @@ public class FileOperations {
out.write(buffer, 0, len); out.write(buffer, 0, len);
} }
} }
if (mode != null && mode > 0) {
applyPosixPermissions(targetFile, mode);
}
} }
current++; current++;
@ -1324,8 +1333,32 @@ public class FileOperations {
callback.onProgress(current, total, entry.getName()); callback.onProgress(current, total, entry.getName());
} }
} }
for (java.util.Map.Entry<File, Integer> directoryMode : directoryModes.entrySet()) {
applyPosixPermissions(directoryMode.getKey(), directoryMode.getValue());
} }
} }
}
private static java.util.Map<String, Integer> readZipEntryModes(File archive) {
java.util.Map<String, Integer> 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 { private static void extractZip(File archive, File targetDir, ProgressCallback callback) throws IOException {
String password = null; String password = null;
@ -1347,7 +1380,7 @@ public class FileOperations {
byte[] externalAttributes = header.getExternalFileAttributes(); byte[] externalAttributes = header.getExternalFileAttributes();
if (externalAttributes != null && externalAttributes.length >= 4) { if (externalAttributes != null && externalAttributes.length >= 4) {
// Unix mode is stored in the upper 16 bits of the external file attributes // 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) { if (mode > 0) {
File extractedFile = new File(targetDir, header.getFileName()); File extractedFile = new File(targetDir, header.getFileName());
applyPosixPermissions(extractedFile, mode); applyPosixPermissions(extractedFile, mode);