Skip to content

Commit

Permalink
Greater archive support
Browse files Browse the repository at this point in the history
Now supports TAR, 7Z, and modern ZIP
  • Loading branch information
barnabwhy committed May 26, 2023
1 parent 7ccf5af commit cbbc733
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 41 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.palette:palette:1.0.0'

implementation 'org.tukaani:xz:1.9'
implementation 'org.apache.commons:commons-compress:1.23.0'

implementation 'commons-net:commons-net:3.9.0'
implementation 'com.hierynomus:smbj:0.11.5'

Expand Down
150 changes: 109 additions & 41 deletions app/src/main/java/com/barnabwhy/picozen/SideloadAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
import com.barnabwhy.picozen.Sideload.SideloadItem;
import com.barnabwhy.picozen.Sideload.SideloadItemType;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
Expand Down Expand Up @@ -264,8 +270,9 @@ class CompleteData {
currentDownload = null;
};

if (getFileExtension(outFile).equals(".zip")) {
((TextView) dialog.get().findViewById(R.id.progress_text)).setText(R.string.extracting_zip);
if (getFileExtension(outFile).equals(".zip") || getFileExtension(outFile).equals(".7z")
|| getFileExtension(outFile).equals(".tar")) {
((TextView) dialog.get().findViewById(R.id.progress_text)).setText(R.string.extracting_archive);

Thread zipThread = new Thread(() -> {
Exception error = null;
Expand All @@ -290,18 +297,11 @@ class CompleteData {
});
});

long uncompressedSize = 0;
ZipFile f = new ZipFile(outFile);
Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) f.entries();
while(entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
uncompressedSize += entry.getSize();
}
long uncompressedSize = getUncompressedArchiveSize(outFile);

long finalUncompressedSize = uncompressedSize;
unzip(outFile, dir, processedBytes -> {
extractArchive(outFile, dir, processedBytes -> {
mainActivityContext.runOnUiThread(() -> {
((TextView) dialog.get().findViewById(R.id.progress_text)).setText(String.format(mainActivityContext.getResources().getString(R.string.extracting_zip_progress), bytesReadable(processedBytes) + "/" + bytesReadable(finalUncompressedSize)));
((TextView) dialog.get().findViewById(R.id.progress_text)).setText(String.format(mainActivityContext.getResources().getString(R.string.extracting_archive_progress), bytesReadable(processedBytes) + "/" + bytesReadable(uncompressedSize)));
});
});

Expand Down Expand Up @@ -430,43 +430,111 @@ private static String bytesReadable(long bytes) {
return String.format("%01.2f %s", size, currentByteType);
}

public static void unzip(File zipFile, File targetDirectory, Consumer<Long> progressCallback) throws IOException {
try (ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(Files.newInputStream(zipFile.toPath())))) {
ZipEntry ze;
int count;
byte[] buffer = new byte[8192];
long processedBytes = 0;
while ((ze = zis.getNextEntry()) != null) {
if(!zipFile.exists()) {
throw new IOException();
public static long getUncompressedArchiveSize(File archiveFile) throws Exception {
if(getFileExtension(archiveFile).equals(".7z")) {
try (SevenZFile is = new SevenZFile(archiveFile)) {
SevenZArchiveEntry ze;
long totalBytes = 0;
while ((ze = is.getNextEntry()) != null) {
if(!archiveFile.exists()) {
throw new IOException();
}

if (ze.isDirectory())
continue;

long size = ze.getSize();
if(size > 0)
totalBytes += size;
}
return totalBytes;
}
} else {
try (ArchiveInputStream is = new ArchiveStreamFactory()
.createArchiveInputStream(new BufferedInputStream(Files.newInputStream(archiveFile.toPath())))) {
ArchiveEntry ze;
long totalBytes = 0;
while ((ze = is.getNextEntry()) != null) {
if (!archiveFile.exists()) {
throw new IOException();
}

if (ze.isDirectory())
continue;

long size = ze.getSize();
if (size > 0)
totalBytes += size;
}
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
try (FileOutputStream fout = new FileOutputStream(file)) {
while ((count = zis.read(buffer)) != -1) {
fout.write(buffer, 0, count);
processedBytes += count;
progressCallback.accept(processedBytes);
if(!zipFile.exists()) {
throw new IOException();
return totalBytes;
}
}
}

public static void extractArchive(File archiveFile, File targetDirectory, Consumer<Long> progressCallback) throws Exception {
if(getFileExtension(archiveFile).equals(".7z")) {
try (SevenZFile is = new SevenZFile(archiveFile)) {
SevenZArchiveEntry ze;
int count;
byte[] buffer = new byte[8192];
long processedBytes = 0;
while ((ze = is.getNextEntry()) != null) {
if (!archiveFile.exists()) {
throw new IOException();
}
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
try (FileOutputStream fout = new FileOutputStream(file)) {
while ((count = is.read(buffer)) != -1) {
fout.write(buffer, 0, count);
processedBytes += count;
progressCallback.accept(processedBytes);
if (!archiveFile.exists()) {
throw new IOException();
}
}
}
}
}
} else {
try (ArchiveInputStream is = new ArchiveStreamFactory()
.createArchiveInputStream(new BufferedInputStream(Files.newInputStream(archiveFile.toPath())))) {
ArchiveEntry ze;
int count;
byte[] buffer = new byte[8192];
long processedBytes = 0;
while ((ze = is.getNextEntry()) != null) {
if (!archiveFile.exists()) {
throw new IOException();
}
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
try (FileOutputStream fout = new FileOutputStream(file)) {
while ((count = is.read(buffer)) != -1) {
fout.write(buffer, 0, count);
processedBytes += count;
progressCallback.accept(processedBytes);
if (!archiveFile.exists()) {
throw new IOException();
}
}
}
}
/* if time should be restored as well
long time = ze.getTime();
if (time > 0)
file.setLastModified(time);
*/
}
}
}


private static String getFileExtension(File file) {
String name = file.getName();
int lastIndexOf = name.lastIndexOf(".");
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
<string name="download_cancelled">Download cancelled</string>
<string name="extracting_zip">Extracting ZIP</string>
<string name="extracting_zip_progress">Extracting ZIP (%1$s)</string>
<string name="extracting_archive">Extracting archive</string>
<string name="extracting_archive_progress">Extracting archive (%1$s)</string>
<string name="download_complete">Download complete</string>
<string name="fetch_files_error">Couldn\'t fetch files</string>
<string name="no_files">No files found</string>
Expand Down

0 comments on commit cbbc733

Please sign in to comment.