added sup[port for more archivers
This commit is contained in:
parent
ae7cf32132
commit
0a95ad9f53
30
pom.xml
30
pom.xml
@ -21,6 +21,23 @@
|
|||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>3.9.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||||
|
<includeScope>runtime</includeScope>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
@ -68,4 +85,17 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
<version>1.21</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.junrar</groupId>
|
||||||
|
<artifactId>junrar</artifactId>
|
||||||
|
<version>7.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -16,9 +16,17 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
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.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
@ -871,22 +879,44 @@ public class FilePanelTab extends JPanel {
|
|||||||
private boolean isArchiveFile(File f) {
|
private boolean isArchiveFile(File f) {
|
||||||
if (f == null) return false;
|
if (f == null) return false;
|
||||||
String n = f.getName().toLowerCase();
|
String n = f.getName().toLowerCase();
|
||||||
return n.endsWith(".zip") || n.endsWith(".jar");
|
return 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) {
|
private Path extractArchiveToTemp(File archive) {
|
||||||
if (archive == null || !archive.isFile()) return null;
|
if (archive == null || !archive.isFile()) return null;
|
||||||
|
String name = archive.getName().toLowerCase();
|
||||||
try {
|
try {
|
||||||
Path tempDir = Files.createTempDirectory("kfmanager-archive-");
|
Path tempDir = Files.createTempDirectory("kfmanager-archive-");
|
||||||
|
|
||||||
|
if (name.endsWith(".zip") || name.endsWith(".jar")) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempDir;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// extraction failed; attempt best-effort cleanup
|
||||||
|
try {
|
||||||
|
if (currentArchiveTempDir != null) deleteTempDirRecursively(currentArchiveTempDir);
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractZip(File archive, Path tempDir) throws IOException {
|
||||||
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(archive.toPath()))) {
|
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(archive.toPath()))) {
|
||||||
ZipEntry entry;
|
ZipEntry entry;
|
||||||
while ((entry = zis.getNextEntry()) != null) {
|
while ((entry = zis.getNextEntry()) != null) {
|
||||||
String entryName = entry.getName();
|
String entryName = entry.getName();
|
||||||
// Normalize entry name and prevent zip-slip
|
|
||||||
Path resolved = tempDir.resolve(entryName).normalize();
|
Path resolved = tempDir.resolve(entryName).normalize();
|
||||||
if (!resolved.startsWith(tempDir)) {
|
if (!resolved.startsWith(tempDir)) {
|
||||||
// suspicious entry, skip
|
|
||||||
zis.closeEntry();
|
zis.closeEntry();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -896,20 +926,97 @@ public class FilePanelTab extends JPanel {
|
|||||||
} else {
|
} else {
|
||||||
Path parent = resolved.getParent();
|
Path parent = resolved.getParent();
|
||||||
if (parent != null) Files.createDirectories(parent);
|
if (parent != null) Files.createDirectories(parent);
|
||||||
// Copy entry contents
|
|
||||||
Files.copy(zis, resolved, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(zis, resolved, StandardCopyOption.REPLACE_EXISTING);
|
||||||
}
|
}
|
||||||
zis.closeEntry();
|
zis.closeEntry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tempDir;
|
private void extractSevenZ(File archive, Path tempDir) throws IOException {
|
||||||
} catch (IOException ex) {
|
try (SevenZFile sevenZFile = new SevenZFile(archive)) {
|
||||||
// extraction failed; attempt best-effort cleanup
|
SevenZArchiveEntry entry;
|
||||||
try {
|
while ((entry = sevenZFile.getNextEntry()) != null) {
|
||||||
if (currentArchiveTempDir != null) deleteTempDirRecursively(currentArchiveTempDir);
|
String entryName = entry.getName();
|
||||||
} catch (Exception ignore) {}
|
Path resolved = tempDir.resolve(entryName).normalize();
|
||||||
return null;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user