diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 282b293241..6620b74541 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -210,6 +210,7 @@ dependencies { // Disk implementation(libs.disklrucache) implementation(libs.unifile) + implementation(libs.compress) implementation(libs.junrar) // Preferences diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt index a9a4e91ff5..c10552b4ee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt @@ -1,12 +1,13 @@ package eu.kanade.tachiyomi.ui.reader.loader import android.app.Application -import android.os.Build import eu.kanade.tachiyomi.ui.reader.model.ReaderPage +import org.apache.commons.compress.archivers.zip.ZipFile +import org.apache.commons.compress.utils.SeekableInMemoryByteChannel import uy.kohesive.injekt.injectLazy +import java.io.ByteArrayOutputStream import java.io.File import java.io.FileInputStream -import java.util.zip.ZipInputStream /** * Loader used to load a chapter from a .zip or .cbz file. @@ -20,29 +21,21 @@ internal class ZipPageLoader(file: File) : PageLoader() { } init { - ZipInputStream(FileInputStream(file)).use { zipInputStream -> - generateSequence { zipInputStream.nextEntry } - .filterNot { it.isDirectory } - .forEach { entry -> - File(tmpDir, entry.name.substringAfterLast("/")) - .also { it.createNewFile() } - .outputStream().use { pageOutputStream -> - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - pageOutputStream.write(zipInputStream.readNBytes(entry.size.toInt())) - } else { - val buffer = ByteArray(2048) - var len: Int - while ( - zipInputStream.read(buffer, 0, buffer.size) - .also { len = it } >= 0 - ) { - pageOutputStream.write(buffer, 0, len) - } + ByteArrayOutputStream().use { byteArrayOutputStream -> + FileInputStream(file).use { it.copyTo(byteArrayOutputStream) } + + ZipFile(SeekableInMemoryByteChannel(byteArrayOutputStream.toByteArray())).use { zip -> + zip.entries.asSequence() + .filterNot { it.isDirectory } + .forEach { entry -> + File(tmpDir, entry.name.substringAfterLast("/")) + .also { it.createNewFile() } + .outputStream().use { pageOutputStream -> + zip.getInputStream(entry).copyTo(pageOutputStream) + pageOutputStream.flush() } - pageOutputStream.flush() - } - zipInputStream.closeEntry() - } + } + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7437447465..c3196e0b5b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,6 +32,7 @@ jsoup = "org.jsoup:jsoup:1.15.4" disklrucache = "com.jakewharton:disklrucache:2.0.2" unifile = "com.github.tachiyomiorg:unifile:17bec43" +compress = "org.apache.commons:commons-compress:1.23.0" junrar = "com.github.junrar:junrar:7.5.4" sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqlite" }