package com.yausername.youtubedl_common.utils; import android.system.ErrnoException; import android.system.Os; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.io.IOUtils; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.Enumeration; public class ZipUtils { private ZipUtils() { } public static void unzip(File sourceFile, File targetDirectory) throws IOException, ErrnoException, IllegalAccessException { try (ZipFile zipFile = new ZipFile(sourceFile)) { Enumeration<ZipArchiveEntry> entries = zipFile.getEntries(); while (entries.hasMoreElements()) { ZipArchiveEntry entry = entries.nextElement(); File entryDestination = new File(targetDirectory, entry.getName()); // prevent zipSlip if (!entryDestination.getCanonicalPath().startsWith(targetDirectory.getCanonicalPath() + File.separator)) { throw new IllegalAccessException("Entry is outside of the target dir: " + entry.getName()); } if (entry.isDirectory()) { entryDestination.mkdirs(); } else if (entry.isUnixSymlink()) { try (InputStream in = zipFile.getInputStream(entry)) { String symlink = IOUtils.toString(in, StandardCharsets.UTF_8); Os.symlink(symlink, entryDestination.getAbsolutePath()); } } else { entryDestination.getParentFile().mkdirs(); try (InputStream in = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination)) { IOUtils.copy(in, out); } } } } } public static void unzip(InputStream inputStream, File targetDirectory) throws IOException, IllegalAccessException { try (ZipArchiveInputStream zis = new ZipArchiveInputStream(new BufferedInputStream(inputStream))) { ZipArchiveEntry entry = null; while ((entry = zis.getNextZipEntry()) != null) { File entryDestination = new File(targetDirectory, entry.getName()); // prevent zipSlip if (!entryDestination.getCanonicalPath().startsWith(targetDirectory.getCanonicalPath() + File.separator)) { throw new IllegalAccessException("Entry is outside of the target dir: " + entry.getName()); } if (entry.isDirectory()) { entryDestination.mkdirs(); } else { entryDestination.getParentFile().mkdirs(); try (OutputStream out = new FileOutputStream(entryDestination)) { IOUtils.copy(zis, out); } } } } } }