Try Apache implementation of ZipFile instead

Docs: https://commons.apache.org/proper/commons-compress/
Related StackOverflow post: https://stackoverflow.com/a/54236244/4421500

Related to #9438

(cherry picked from commit c623258e8c289ecebb2a673fd118686ab56bd0bd)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt
This commit is contained in:
arkon
2023-05-03 14:00:33 -04:00
committed by Jobobby04
parent fe0f9f053b
commit 782b6dec02
6 changed files with 33 additions and 55 deletions
@@ -101,13 +101,7 @@ class ChapterLoader(
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
when (format) {
is Format.Directory -> DirectoryPageLoader(format.file)
// SY -->
is Format.Zip -> try {
ZipPageLoader(format.file, context)
} catch (e: Throwable) {
error(context.getString(R.string.wrong_cbz_archive_password))
}
// SY <--
is Format.Zip -> ZipPageLoader(format.file)
is Format.Rar -> try {
RarPageLoader(format.file)
} catch (e: UnsupportedRarV5Exception) {
@@ -124,13 +118,7 @@ class ChapterLoader(
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
when (format) {
is Format.Directory -> DirectoryPageLoader(format.file)
// SY -->
is Format.Zip -> try {
ZipPageLoader(format.file, context)
} catch (e: Throwable) {
error(context.getString(R.string.wrong_cbz_archive_password))
}
// SY <--
is Format.Zip -> ZipPageLoader(format.file)
is Format.Rar -> try {
RarPageLoader(format.file)
} catch (e: UnsupportedRarV5Exception) {
@@ -47,9 +47,7 @@ internal class DownloadPageLoader(
}
private suspend fun getPagesFromArchive(chapterPath: UniFile): List<ReaderPage> {
// SY -->
val loader = ZipPageLoader(File(chapterPath.filePath!!), context).also { zipPageLoader = it }
// SY <--
val loader = ZipPageLoader(File(chapterPath.filePath!!)).also { zipPageLoader = it }
return loader.getPages()
}
@@ -1,27 +1,23 @@
package eu.kanade.tachiyomi.ui.reader.loader
import android.app.Application
import android.content.Context
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 net.lingala.zip4j.ZipFile
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.nio.charset.StandardCharsets
import java.util.zip.ZipInputStream
import net.lingala.zip4j.ZipFile as Zip4JFile
/**
* Loader used to load a chapter from a .zip or .cbz file.
*/
internal class ZipPageLoader(
file: File,
// SY -->
context: Context,
// SY <--
) : PageLoader() {
internal class ZipPageLoader(file: File) : PageLoader() {
private val context: Application by injectLazy()
private val tmpDir = File(context.externalCacheDir, "reader_${file.hashCode()}").also {
@@ -31,11 +27,11 @@ internal class ZipPageLoader(
// SY -->
init {
val zip = ZipFile(file)
val zip = Zip4JFile(file)
if (zip.isEncrypted) {
if (!CbzCrypto.checkCbzPassword(zip, CbzCrypto.getDecryptedPasswordCbz())) {
this.recycle()
throw Exception(context.getString(R.string.wrong_cbz_archive_password))
throw IllegalStateException(context.getString(R.string.wrong_cbz_archive_password))
}
unzipEncrypted(zip)
} else {
@@ -44,34 +40,26 @@ internal class ZipPageLoader(
}
private fun unzip(file: File) {
// SY <--
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()
}
}
}
}
}
// SY -->
private fun unzipEncrypted(zip: ZipFile) {
private fun unzipEncrypted(zip: Zip4JFile) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
zip.charset = StandardCharsets.ISO_8859_1
}