7z encryption support

This commit is contained in:
Radek Davidek 2026-04-21 19:26:23 +02:00
parent 898416bea7
commit 65a996bc29
2 changed files with 98 additions and 34 deletions

View File

@ -15,7 +15,7 @@ import java.io.InputStreamReader;
*/
public class MainApp {
public static final String APP_VERSION = "1.4.0";
public static final String APP_VERSION = "1.4.1";
public enum OS {
WINDOWS, LINUX, MACOS, UNKNOWN

View File

@ -18,6 +18,10 @@ import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.apache.commons.compress.PasswordRequiredException;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import cz.kamma.kfmanager.model.FileItem;
import cz.kamma.kfmanager.model.FtpProfile;
import net.lingala.zip4j.ZipFile;
@ -751,8 +755,14 @@ public class FileOperations {
}
}
} else if (name.endsWith(".7z")) {
try (org.apache.commons.compress.archivers.sevenz.SevenZFile sevenZFile = new org.apache.commons.compress.archivers.sevenz.SevenZFile(archive)) {
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
SevenZFile szf;
try {
szf = new SevenZFile(archive);
} catch (PasswordRequiredException e) {
return null;
}
try (SevenZFile sevenZFile = szf) {
SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null) {
if (entry.getName().equals(entryPath) || (archive.getAbsolutePath() + File.separator + entry.getName()).equals(entryPath)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -764,6 +774,8 @@ public class FileOperations {
return baos.toByteArray();
}
}
} catch (PasswordRequiredException e) {
return null;
}
} else if (name.endsWith(".rar")) {
try (com.github.junrar.Archive rar = new com.github.junrar.Archive(archive)) {
@ -842,8 +854,15 @@ public class FileOperations {
}
}
} else if (name.endsWith(".7z")) {
try (org.apache.commons.compress.archivers.sevenz.SevenZFile sevenZFile = new org.apache.commons.compress.archivers.sevenz.SevenZFile(archive)) {
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
SevenZFile szf;
try {
szf = new SevenZFile(archive);
} catch (PasswordRequiredException e) {
szf = null;
}
if (szf != null) {
try (SevenZFile sevenZFile = szf) {
SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null) {
if (callback.isCancelled()) return;
if (!entry.isDirectory()) {
@ -853,22 +872,36 @@ public class FileOperations {
}
boolean contentMatched = true;
if (nameMatched && contentPattern != null) {
contentMatched = searchInStream(new InputStream() {
final SevenZFile szfFinal = sevenZFile;
InputStream is = new InputStream() {
@Override
public int read() throws IOException {
return sevenZFile.read();
try {
return szfFinal.read();
} catch (PasswordRequiredException e) {
throw new IOException("Password required", e);
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return sevenZFile.read(b, off, len);
try {
return szfFinal.read(b, off, len);
} catch (PasswordRequiredException e) {
throw new IOException("Password required", e);
}
}, contentPattern);
}
};
contentMatched = searchInStream(is, contentPattern);
}
if (nameMatched && contentMatched) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
}
} catch (PasswordRequiredException e) {
// Handle cases where data is encrypted but headers were not
}
}
} else if (name.endsWith(".rar")) {
try (com.github.junrar.Archive rar = new com.github.junrar.Archive(archive)) {
@ -1041,17 +1074,44 @@ public class FileOperations {
}
private static void extract7z(File archive, File targetDir, ProgressCallback callback) throws IOException {
try (org.apache.commons.compress.archivers.sevenz.SevenZFile sevenZFile = new org.apache.commons.compress.archivers.sevenz.SevenZFile(archive)) {
Iterable<org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry> entries = sevenZFile.getEntries();
List<org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry> entryList = new ArrayList<>();
for (org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry : entries) {
String password = null;
SevenZFile szf = null;
try {
szf = new SevenZFile(archive);
} catch (PasswordRequiredException e) {
password = callback.requestPassword(archive.getName());
if (password == null) return;
szf = new SevenZFile(archive, password.toCharArray());
}
try {
Iterable<SevenZArchiveEntry> entries = szf.getEntries();
List<SevenZArchiveEntry> entryList = new ArrayList<>();
for (SevenZArchiveEntry entry : entries) {
entryList.add(entry);
}
long total = entryList.size();
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
SevenZArchiveEntry entry;
int count = 0;
while ((entry = sevenZFile.getNextEntry()) != null) {
while (true) {
try {
entry = szf.getNextEntry();
} catch (PasswordRequiredException e) {
if (password == null) {
password = callback.requestPassword(archive.getName());
if (password == null) {
szf.close();
return;
}
}
szf.close();
szf = new SevenZFile(archive, password.toCharArray());
count = 0;
entry = szf.getNextEntry();
}
if (entry == null) break;
if (callback != null && callback.isCancelled()) break;
File targetFile = new File(targetDir, entry.getName());
if (entry.isDirectory()) {
@ -1061,7 +1121,7 @@ public class FileOperations {
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(targetFile), 65536)) {
byte[] buffer = new byte[65536];
int len;
while ((len = sevenZFile.read(buffer)) > 0) {
while ((len = szf.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
}
@ -1071,6 +1131,10 @@ public class FileOperations {
callback.onProgress(count, total, entry.getName());
}
}
} finally {
if (szf != null) {
szf.close();
}
}
}