Remove storage permissions

Requires adjusting some file reading to first copy to a temporary file
in cache that we have permissions to read from. This is only applicable for things
like ZIP files where we need an actual File rather than just some Android content
URI shenanigans.

(cherry picked from commit 4fcdde4913df28bbd678ae1be4a2971ed77179d3)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt
#	source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt
This commit is contained in:
arkon
2023-11-28 08:59:45 -05:00
committed by Jobobby04
parent 7e6d1196ac
commit ab63f6036c
17 changed files with 97 additions and 151 deletions
@@ -30,7 +30,7 @@ import tachiyomi.core.metadata.comicinfo.getComicInfo
import tachiyomi.core.metadata.tachiyomi.MangaDetails
import tachiyomi.core.storage.extension
import tachiyomi.core.storage.nameWithoutExtension
import tachiyomi.core.storage.toFile
import tachiyomi.core.storage.toTempFile
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.ImageUtil
import tachiyomi.core.util.system.logcat
@@ -154,12 +154,12 @@ actual class LocalSource(
// SY -->
fun updateMangaInfo(manga: SManga) {
val directory = fileSystem.getFilesInBaseDirectory().map { File(it.toFile(), manga.url) }.find {
it.exists()
val directory = fileSystem.getFilesInBaseDirectory().map { it.createDirectory(manga.url) }.find {
it?.exists() == true
} ?: return
val existingFileName = directory.listFiles()?.find { it.extension == "json" }?.name
val file = File(directory, existingFileName ?: "info.json")
file.outputStream().use {
val existingFile = directory.listFiles()?.find { it.extension == "json" }
val file = existingFile ?: directory.createFile("info.json") ?: return
file.openOutputStream().use {
json.encodeToStream(manga.toJson(), it)
}
}
@@ -199,7 +199,7 @@ actual class LocalSource(
}
// SY -->
comicInfoArchiveFile != null -> {
val comicInfoArchive = ZipFile(comicInfoArchiveFile.toFile())
val comicInfoArchive = ZipFile(comicInfoArchiveFile.toTempFile(context))
noXmlFile?.delete()
if (CbzCrypto.checkCbzPassword(comicInfoArchive, CbzCrypto.getDecryptedPasswordCbz())) {
@@ -269,7 +269,7 @@ actual class LocalSource(
for (chapter in chapterArchives) {
when (Format.valueOf(chapter)) {
is Format.Zip -> {
ZipFile(chapter.toFile()).use { zip: ZipFile ->
ZipFile(chapter.toTempFile(context)).use { zip: ZipFile ->
// SY -->
if (zip.isEncrypted && !CbzCrypto.checkCbzPassword(zip, CbzCrypto.getDecryptedPasswordCbz())
) {
@@ -288,7 +288,7 @@ actual class LocalSource(
}
}
is Format.Rar -> {
JunrarArchive(chapter.toFile()).use { rar ->
JunrarArchive(chapter.toTempFile(context)).use { rar ->
rar.fileHeaders.firstOrNull { it.fileName == COMIC_INFO_FILE }?.let { comicInfoFile ->
rar.getInputStream(comicInfoFile).buffered().use { stream ->
return copyComicInfoFile(stream, folderPath)
@@ -354,7 +354,7 @@ actual class LocalSource(
val format = Format.valueOf(chapterFile)
if (format is Format.Epub) {
EpubFile(format.file).use { epub ->
EpubFile(format.file.toTempFile(context)).use { epub ->
epub.fillMetadata(manga, this)
}
}
@@ -413,7 +413,7 @@ actual class LocalSource(
entry?.let { coverManager.update(manga, it.openInputStream()) }
}
is Format.Zip -> {
ZipFile(format.file.toFile()).use { zip ->
ZipFile(format.file.toTempFile(context)).use { zip ->
// SY -->
var encrypted = false
if (zip.isEncrypted) {
@@ -428,7 +428,7 @@ actual class LocalSource(
}
}
is Format.Rar -> {
JunrarArchive(format.file.toFile()).use { archive ->
JunrarArchive(format.file.toTempFile(context)).use { archive ->
val entry = archive.fileHeaders
.sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
.find { !it.isDirectory && ImageUtil.isImage(it.fileName) { archive.getInputStream(it) } }
@@ -437,7 +437,7 @@ actual class LocalSource(
}
}
is Format.Epub -> {
EpubFile(format.file).use { epub ->
EpubFile(format.file.toTempFile(context)).use { epub ->
val entry = epub.getImagesFromPages()
.firstOrNull()
?.let { epub.getEntry(it) }
@@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
import net.lingala.zip4j.ZipFile
import net.lingala.zip4j.model.ZipParameters
import tachiyomi.core.storage.nameWithoutExtension
import tachiyomi.core.storage.toFile
import tachiyomi.core.util.system.ImageUtil
import tachiyomi.source.local.io.LocalSourceFileSystem
import java.io.File
@@ -61,12 +60,22 @@ actual class LocalCoverManager(
inputStream.use { input ->
// SY -->
if (encrypted) {
val zip4j = ZipFile(targetFile.toFile())
val tempFile = File.createTempFile(
targetFile.nameWithoutExtension.orEmpty(),
null,
)
val zip4j = ZipFile(tempFile)
val zipParameters = ZipParameters()
zip4j.setPassword(CbzCrypto.getDecryptedPasswordCbz())
CbzCrypto.setZipParametersEncrypted(zipParameters)
zipParameters.fileNameInZip = DEFAULT_COVER_NAME
zip4j.addStream(input, zipParameters)
zip4j.close()
targetFile.openOutputStream().use { output ->
tempFile.inputStream().use { input ->
input.copyTo(output)
}
}
DiskUtil.createNoMediaFile(directory, context)