diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3e159bff2..3ba29b4c6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -210,7 +210,6 @@ dependencies { // Disk implementation(libs.disklrucache) implementation(libs.unifile) - implementation(libs.compress) implementation(libs.junrar) // SY --> implementation(libs.zip4j) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index dd3809769..5e481c974 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -265,7 +265,6 @@ -keep,allowoptimization class kotlin.coroutines.Continuation -keep,allowoptimization class * extends uy.kohesive.injekt.api.TypeReference -keep,allowoptimization public class io.requery.android.database.sqlite.SQLiteConnection { *; } - -keep,allowoptimization class org.apache.commons.compress.archivers.zip.** # Suggested rules -dontwarn com.oracle.svm.core.annotate.AutomaticFeature diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt index 7231a45a0..056319d4e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt @@ -1,10 +1,11 @@ package eu.kanade.tachiyomi.ui.reader.loader -import android.app.Application import com.github.junrar.Archive import com.github.junrar.rarfile.FileHeader +import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage -import uy.kohesive.injekt.injectLazy +import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder +import tachiyomi.core.util.system.ImageUtil import java.io.File import java.io.InputStream import java.io.PipedInputStream @@ -15,36 +16,30 @@ import java.io.PipedOutputStream */ internal class RarPageLoader(file: File) : PageLoader() { - private val context: Application by injectLazy() - private val tmpDir = File(context.externalCacheDir, "reader_${file.hashCode()}").also { - it.deleteRecursively() - it.mkdirs() - } - - init { - Archive(file).use { rar -> - rar.fileHeaders.asSequence() - .filterNot { it.isDirectory } - .forEach { header -> - val pageOutputStream = File(tmpDir, header.fileName.substringAfterLast("/")) - .also { it.createNewFile() } - .outputStream() - getStream(rar, header).use { - it.copyTo(pageOutputStream) - } - } - } - } + private val rar = Archive(file) override var isLocal: Boolean = true override suspend fun getPages(): List { - return DirectoryPageLoader(tmpDir).getPages() + return rar.fileHeaders.asSequence() + .filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { rar.getInputStream(it) } } + .sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) } + .mapIndexed { i, header -> + ReaderPage(i).apply { + stream = { getStream(rar, header) } + status = Page.State.READY + } + } + .toList() + } + + override suspend fun loadPage(page: ReaderPage) { + check(!isRecycled) } override fun recycle() { super.recycle() - tmpDir.deleteRecursively() + rar.close() } /** 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 7f486410a..e942d384d 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 @@ -5,68 +5,48 @@ import android.os.Build import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.storage.CbzCrypto -import org.apache.commons.compress.archivers.zip.ZipFile -import org.apache.commons.compress.utils.SeekableInMemoryByteChannel +import net.lingala.zip4j.ZipFile +import tachiyomi.core.util.system.ImageUtil import uy.kohesive.injekt.injectLazy -import java.io.ByteArrayOutputStream import java.io.File -import java.io.FileInputStream import java.nio.charset.StandardCharsets -import net.lingala.zip4j.ZipFile as Zip4JFile /** * Loader used to load a chapter from a .zip or .cbz file. */ internal class ZipPageLoader(file: File) : PageLoader() { + // SY --> private val context: Application by injectLazy() private val tmpDir = File(context.externalCacheDir, "reader_${file.hashCode()}").also { it.deleteRecursively() it.mkdirs() } - // SY --> init { - val zip = Zip4JFile(file) - if (zip.isEncrypted) { - if (!CbzCrypto.checkCbzPassword(zip, CbzCrypto.getDecryptedPasswordCbz())) { - this.recycle() - throw IllegalStateException(context.getString(R.string.wrong_cbz_archive_password)) - } - unzipEncrypted(zip) - } else { - unzip(file) - } - } - private fun unzip(file: File) { - // SY <-- - 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() - } - } + ZipFile(file).use { zip -> + if (zip.isEncrypted) { + if (!CbzCrypto.checkCbzPassword(zip, CbzCrypto.getDecryptedPasswordCbz())) { + this.recycle() + throw IllegalStateException(context.getString(R.string.wrong_cbz_archive_password)) + } + unzip(zip, CbzCrypto.getDecryptedPasswordCbz()) + } else { + unzip(zip) } } } - - // SY --> - private fun unzipEncrypted(zip: Zip4JFile) { + private fun unzip(zip: ZipFile, password: CharArray? = null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { zip.charset = StandardCharsets.ISO_8859_1 } - zip.setPassword(CbzCrypto.getDecryptedPasswordCbz()) + + if (password != null) { + zip.setPassword(password) + } zip.fileHeaders.asSequence() - .filterNot { it.isDirectory } + .filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { zip.getInputStream(it) } } .forEach { entry -> zip.extractFile(entry, tmpDir.absolutePath) } @@ -78,9 +58,4 @@ internal class ZipPageLoader(file: File) : PageLoader() { override suspend fun getPages(): List { return DirectoryPageLoader(tmpDir).getPages() } - - override fun recycle() { - super.recycle() - tmpDir.deleteRecursively() - } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6f832d7bf..3aa9f5482 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,6 @@ jsoup = "org.jsoup:jsoup:1.16.1" 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" zip4j = "net.lingala.zip4j:zip4j:2.11.5"