support multiple archives
This commit is contained in:
parent
26d2f339fe
commit
686e3ac121
@ -15,7 +15,7 @@ import java.io.InputStreamReader;
|
||||
*/
|
||||
public class MainApp {
|
||||
|
||||
public static final String APP_VERSION = "1.0.0";
|
||||
public static final String APP_VERSION = "1.0.1";
|
||||
|
||||
public enum OS {
|
||||
WINDOWS, LINUX, MACOS, UNKNOWN
|
||||
|
||||
@ -790,9 +790,14 @@ public class FileOperations {
|
||||
throw new IOException("Entry not found in archive: " + entryPath);
|
||||
}
|
||||
|
||||
private static boolean isArchiveFile(File f) {
|
||||
public static boolean isArchiveFile(File f) {
|
||||
if (f == null) return false;
|
||||
String n = f.getName().toLowerCase();
|
||||
return isArchiveFile(f.getName());
|
||||
}
|
||||
|
||||
public static boolean isArchiveFile(String filename) {
|
||||
if (filename == null) return false;
|
||||
String n = filename.toLowerCase();
|
||||
return n.endsWith(".war") || n.endsWith(".zip") || n.endsWith(".jar") || n.endsWith(".tar") || n.endsWith(".tar.gz") || n.endsWith(".tgz") || n.endsWith(".7z") || n.endsWith(".rar");
|
||||
}
|
||||
|
||||
@ -989,6 +994,110 @@ public class FileOperations {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an archive into a target directory
|
||||
*/
|
||||
public static void extractArchive(File archiveFile, File targetDirectory, ProgressCallback callback) throws Exception {
|
||||
if (!targetDirectory.exists()) {
|
||||
Files.createDirectories(targetDirectory.toPath());
|
||||
}
|
||||
|
||||
String name = archiveFile.getName().toLowerCase();
|
||||
if (name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith(".war")) {
|
||||
unzip(archiveFile, targetDirectory, callback);
|
||||
} else if (name.endsWith(".tar.gz") || name.endsWith(".tgz")) {
|
||||
extractTarGz(archiveFile, targetDirectory, callback);
|
||||
} else if (name.endsWith(".tar")) {
|
||||
extractTar(archiveFile, targetDirectory, callback);
|
||||
} else if (name.endsWith(".7z")) {
|
||||
extractSevenZ(archiveFile, targetDirectory, callback);
|
||||
} else if (name.endsWith(".rar")) {
|
||||
extractRar(archiveFile, targetDirectory, callback);
|
||||
} else {
|
||||
throw new IOException("Unsupported archive format: " + archiveFile.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractTarGz(File archive, File targetDir, ProgressCallback callback) throws IOException {
|
||||
try (InputStream fis = Files.newInputStream(archive.toPath());
|
||||
InputStream gzis = new org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream(fis);
|
||||
org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais = new org.apache.commons.compress.archivers.tar.TarArchiveInputStream(gzis)) {
|
||||
extractTarInternal(tais, targetDir, callback);
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractTar(File archive, File targetDir, ProgressCallback callback) throws IOException {
|
||||
try (InputStream fis = Files.newInputStream(archive.toPath());
|
||||
org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais = new org.apache.commons.compress.archivers.tar.TarArchiveInputStream(fis)) {
|
||||
extractTarInternal(tais, targetDir, callback);
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractTarInternal(org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais, File targetDir, ProgressCallback callback) throws IOException {
|
||||
org.apache.commons.compress.archivers.tar.TarArchiveEntry entry;
|
||||
long current = 0;
|
||||
while ((entry = tais.getNextTarEntry()) != null) {
|
||||
current++;
|
||||
if (callback != null) callback.onProgress(current, -1, entry.getName());
|
||||
|
||||
File newFile = new File(targetDir, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
newFile.mkdirs();
|
||||
} else {
|
||||
newFile.getParentFile().mkdirs();
|
||||
Files.copy(tais, newFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractSevenZ(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)) {
|
||||
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
|
||||
long current = 0;
|
||||
while ((entry = sevenZFile.getNextEntry()) != null) {
|
||||
current++;
|
||||
if (callback != null) callback.onProgress(current, -1, entry.getName());
|
||||
|
||||
File newFile = new File(targetDir, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
newFile.mkdirs();
|
||||
} else {
|
||||
newFile.getParentFile().mkdirs();
|
||||
try (OutputStream os = Files.newOutputStream(newFile.toPath())) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = sevenZFile.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractRar(File archiveFile, File targetDir, ProgressCallback callback) throws Exception {
|
||||
try (com.github.junrar.Archive archive = new com.github.junrar.Archive(archiveFile)) {
|
||||
com.github.junrar.rarfile.FileHeader fh = archive.nextFileHeader();
|
||||
long current = 0;
|
||||
while (fh != null) {
|
||||
current++;
|
||||
String entryName = fh.getFileName().replace('\\', '/');
|
||||
if (callback != null) callback.onProgress(current, -1, entryName);
|
||||
|
||||
File newFile = new File(targetDir, entryName);
|
||||
if (fh.isDirectory()) {
|
||||
newFile.mkdirs();
|
||||
} else {
|
||||
newFile.getParentFile().mkdirs();
|
||||
try (OutputStream os = Files.newOutputStream(newFile.toPath())) {
|
||||
archive.extractFile(fh, os);
|
||||
}
|
||||
}
|
||||
fh = archive.nextFileHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip a zip file into a target directory
|
||||
*/
|
||||
|
||||
@ -26,20 +26,8 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||
import com.github.junrar.Archive;
|
||||
import com.github.junrar.rarfile.FileHeader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.PosixFileAttributes;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
@ -755,7 +743,7 @@ public class FilePanelTab extends JPanel {
|
||||
int row = fileTable.getSelectedRow();
|
||||
if (row >= 0) {
|
||||
FileItem item = (viewMode == ViewMode.BRIEF) ? tableModel.getItemFromBriefLayout(row, briefCurrentColumn) : tableModel.getItem(row);
|
||||
if (item != null && (item.isDirectory() || isArchiveFile(item.getFile()))) {
|
||||
if (item != null && (item.isDirectory() || FileOperations.isArchiveFile(item.getFile()))) {
|
||||
openSelectedItem();
|
||||
}
|
||||
}
|
||||
@ -1241,30 +1229,11 @@ public class FilePanelTab extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isArchiveFile(File f) {
|
||||
if (f == null) return false;
|
||||
String n = f.getName().toLowerCase();
|
||||
return n.endsWith(".war") || n.endsWith(".zip") || n.endsWith(".jar") || n.endsWith(".tar") || n.endsWith(".tar.gz") || n.endsWith(".tgz") || n.endsWith(".7z") || n.endsWith(".rar");
|
||||
}
|
||||
|
||||
private Path extractArchiveToTemp(File archive) {
|
||||
if (archive == null || !archive.isFile()) return null;
|
||||
String name = archive.getName().toLowerCase();
|
||||
try {
|
||||
Path tempDir = Files.createTempDirectory("kfmanager-archive-");
|
||||
|
||||
if (name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith(".war")) {
|
||||
extractZip(archive, tempDir);
|
||||
} else if (name.endsWith(".tar.gz") || name.endsWith(".tgz")) {
|
||||
extractTarGz(archive, tempDir);
|
||||
} else if (name.endsWith(".tar")) {
|
||||
extractTar(archive, tempDir);
|
||||
} else if (name.endsWith(".7z")) {
|
||||
extractSevenZ(archive, tempDir);
|
||||
} else if (name.endsWith(".rar")) {
|
||||
extractRar(archive, tempDir);
|
||||
}
|
||||
|
||||
FileOperations.extractArchive(archive, tempDir.toFile(), null);
|
||||
return tempDir;
|
||||
} catch (Exception ex) {
|
||||
// extraction failed; attempt best-effort cleanup
|
||||
@ -1275,116 +1244,6 @@ public class FilePanelTab extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void extractZip(File archive, Path tempDir) throws IOException {
|
||||
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(archive.toPath()))) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
String entryName = entry.getName();
|
||||
Path resolved = tempDir.resolve(entryName).normalize();
|
||||
if (!resolved.startsWith(tempDir)) {
|
||||
zis.closeEntry();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isDirectory() || entryName.endsWith("/")) {
|
||||
Files.createDirectories(resolved);
|
||||
} else {
|
||||
Path parent = resolved.getParent();
|
||||
if (parent != null) Files.createDirectories(parent);
|
||||
Files.copy(zis, resolved, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
zis.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSevenZ(File archive, Path tempDir) throws IOException {
|
||||
try (SevenZFile sevenZFile = new SevenZFile(archive)) {
|
||||
SevenZArchiveEntry entry;
|
||||
while ((entry = sevenZFile.getNextEntry()) != null) {
|
||||
String entryName = entry.getName();
|
||||
Path resolved = tempDir.resolve(entryName).normalize();
|
||||
if (!resolved.startsWith(tempDir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(resolved);
|
||||
} else {
|
||||
Path parent = resolved.getParent();
|
||||
if (parent != null) Files.createDirectories(parent);
|
||||
|
||||
try (OutputStream os = Files.newOutputStream(resolved)) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = sevenZFile.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractRar(File archiveFile, Path tempDir) throws Exception {
|
||||
try (Archive archive = new Archive(archiveFile)) {
|
||||
FileHeader fh = archive.nextFileHeader();
|
||||
while (fh != null) {
|
||||
String entryName = fh.getFileName().replace('\\', '/');
|
||||
Path resolved = tempDir.resolve(entryName).normalize();
|
||||
if (!resolved.startsWith(tempDir)) {
|
||||
fh = archive.nextFileHeader();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fh.isDirectory()) {
|
||||
Files.createDirectories(resolved);
|
||||
} else {
|
||||
Path parent = resolved.getParent();
|
||||
if (parent != null) Files.createDirectories(parent);
|
||||
try (OutputStream os = Files.newOutputStream(resolved)) {
|
||||
archive.extractFile(fh, os);
|
||||
}
|
||||
}
|
||||
fh = archive.nextFileHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractTarGz(File archive, Path tempDir) throws IOException {
|
||||
try (InputStream fis = Files.newInputStream(archive.toPath());
|
||||
InputStream gzis = new GzipCompressorInputStream(fis);
|
||||
TarArchiveInputStream tais = new TarArchiveInputStream(gzis)) {
|
||||
extractTarInternal(tais, tempDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractTar(File archive, Path tempDir) throws IOException {
|
||||
try (InputStream fis = Files.newInputStream(archive.toPath());
|
||||
TarArchiveInputStream tais = new TarArchiveInputStream(fis)) {
|
||||
extractTarInternal(tais, tempDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractTarInternal(TarArchiveInputStream tais, Path tempDir) throws IOException {
|
||||
TarArchiveEntry entry;
|
||||
while ((entry = tais.getNextTarEntry()) != null) {
|
||||
String entryName = entry.getName();
|
||||
Path resolved = tempDir.resolve(entryName).normalize();
|
||||
if (!resolved.startsWith(tempDir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(resolved);
|
||||
} else {
|
||||
Path parent = resolved.getParent();
|
||||
if (parent != null) Files.createDirectories(parent);
|
||||
Files.copy(tais, resolved, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteTempDirRecursively(Path dir) {
|
||||
if (dir == null) return;
|
||||
try {
|
||||
@ -1412,7 +1271,7 @@ public class FilePanelTab extends JPanel {
|
||||
|
||||
if (item.getName().equals("..")) {
|
||||
navigateUp();
|
||||
} else if (isArchiveFile(item.getFile())) {
|
||||
} else if (FileOperations.isArchiveFile(item.getFile())) {
|
||||
Path temp = extractArchiveToTemp(item.getFile());
|
||||
if (temp != null) {
|
||||
// Delete any previous temp dir if different
|
||||
@ -1551,7 +1410,7 @@ public class FilePanelTab extends JPanel {
|
||||
|
||||
if (item.getName().equals("..")) {
|
||||
navigateUp();
|
||||
} else if (isArchiveFile(item.getFile())) {
|
||||
} else if (FileOperations.isArchiveFile(item.getFile())) {
|
||||
Path temp = extractArchiveToTemp(item.getFile());
|
||||
if (temp != null) {
|
||||
try {
|
||||
|
||||
@ -1837,24 +1837,24 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip selected zip file
|
||||
* Extract selected archive
|
||||
*/
|
||||
private void unzipFiles() {
|
||||
List<FileItem> selectedItems = activePanel.getSelectedItems();
|
||||
if (selectedItems.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"No files selected",
|
||||
"Unzip",
|
||||
"Extract",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
requestFocusInActivePanel();
|
||||
return;
|
||||
}
|
||||
|
||||
File zipFile = selectedItems.get(0).getFile();
|
||||
if (!zipFile.getName().toLowerCase().endsWith(".zip")) {
|
||||
File archiveFile = selectedItems.get(0).getFile();
|
||||
if (!FileOperations.isArchiveFile(archiveFile)) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Selected file is not a ZIP archive",
|
||||
"Unzip",
|
||||
"Selected file is not a supported archive",
|
||||
"Extract",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
requestFocusInActivePanel();
|
||||
return;
|
||||
@ -1865,18 +1865,18 @@ public class MainWindow extends JFrame {
|
||||
final FilePanel sourcePanel = activePanel;
|
||||
|
||||
int result = showConfirmWithBackground(
|
||||
String.format("Unzip %s to:\n%s", zipFile.getName(), targetDir.getAbsolutePath()),
|
||||
"Unzip");
|
||||
String.format("Extract %s to:\n%s", archiveFile.getName(), targetDir.getAbsolutePath()),
|
||||
"Extract archive");
|
||||
|
||||
if (result == 0 || result == 1) {
|
||||
boolean background = (result == 1);
|
||||
if (background) {
|
||||
addOperationToQueue("Unzip", String.format("Unzip %s to %s", zipFile.getName(), targetDir.getName()),
|
||||
(cb) -> FileOperations.unzip(zipFile, targetDir, cb), () -> sourcePanel.unselectAll(), targetPanel);
|
||||
addOperationToQueue("Extract", String.format("Extract %s to %s", archiveFile.getName(), targetDir.getName()),
|
||||
(cb) -> FileOperations.extractArchive(archiveFile, targetDir, cb), () -> sourcePanel.unselectAll(), targetPanel);
|
||||
} else {
|
||||
performFileOperation((callback) -> {
|
||||
FileOperations.unzip(zipFile, targetDir, callback);
|
||||
}, "Unzipped into " + targetDir.getName(), false, true, () -> sourcePanel.unselectAll(), targetPanel);
|
||||
FileOperations.extractArchive(archiveFile, targetDir, callback);
|
||||
}, "Extracted into " + targetDir.getName(), false, true, () -> sourcePanel.unselectAll(), targetPanel);
|
||||
}
|
||||
} else {
|
||||
if (activePanel != null && activePanel.getFileTable() != null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user