Fix zip closing

This commit is contained in:
Koitharu
2024-10-11 10:55:47 +03:00
parent 557b69d73f
commit 144e66bedb
6 changed files with 53 additions and 47 deletions

View File

@@ -1,14 +1,11 @@
package org.koitharu.kotatsu.core.backup
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runInterruptible
import okhttp3.internal.closeQuietly
import okio.Closeable
import org.json.JSONArray
import org.koitharu.kotatsu.core.exceptions.BadBackupFormatException
import org.koitharu.kotatsu.core.util.ext.processLifecycleScope
import java.io.File
import java.util.EnumSet
import java.util.zip.ZipException
@@ -36,13 +33,9 @@ class BackupZipInput private constructor(val file: File) : Closeable {
zipFile.close()
}
fun cleanupAsync() {
processLifecycleScope.launch(Dispatchers.IO, CoroutineStart.ATOMIC) {
runCatching {
closeQuietly()
file.delete()
}
}
fun closeAndDelete() {
closeQuietly()
file.delete()
}
companion object {
@@ -55,7 +48,7 @@ class BackupZipInput private constructor(val file: File) : Closeable {
throw BadBackupFormatException(null)
}
res
} catch (exception: Exception) {
} catch (exception: Throwable) {
res?.closeQuietly()
throw if (exception is ZipException) {
BadBackupFormatException(exception)

View File

@@ -39,14 +39,6 @@ fun ZipFile.readText(entry: ZipEntry) = getInputStream(entry).bufferedReader().u
it.readText()
}
@Blocking
fun ZipFile.getInputStreamOrClose(entry: ZipEntry): InputStream = try {
getInputStream(entry)
} catch (e: Throwable) {
closeQuietly()
throw e
}
fun File.getStorageName(context: Context): String = runCatching {
val manager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

View File

@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.util.ext
import android.net.Uri
import androidx.core.net.toFile
import okhttp3.internal.closeQuietly
import okio.Source
import okio.source
import okio.use
@@ -40,8 +41,13 @@ fun Uri.source(): Source = when (scheme) {
URI_SCHEME_FILE -> toFile().source()
URI_SCHEME_ZIP -> {
val zip = ZipFile(schemeSpecificPart)
val entry = zip.getEntry(fragment)
zip.getInputStreamOrClose(entry).source().withExtraCloseable(zip)
try {
val entry = zip.getEntry(fragment)
zip.getInputStream(entry).source().withExtraCloseable(zip)
} catch (e: Throwable) {
zip.closeQuietly()
throw e
}
}
else -> unsupportedUri(this)

View File

@@ -16,13 +16,13 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import okhttp3.OkHttpClient
import okhttp3.internal.closeQuietly
import okio.Path.Companion.toOkioPath
import okio.buffer
import okio.source
import org.koitharu.kotatsu.core.network.MangaHttpClient
import org.koitharu.kotatsu.core.network.imageproxy.ImageProxyInterceptor
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.util.ext.getInputStreamOrClose
import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.local.data.isFileUri
import org.koitharu.kotatsu.local.data.isZipUri
@@ -67,17 +67,22 @@ class MangaPageFetcher(
return when {
uri.isZipUri() -> runInterruptible(Dispatchers.IO) {
val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment)
SourceResult(
source = ImageSource(
source = zip.getInputStreamOrClose(entry).source().withExtraCloseable(zip).buffer(),
context = context,
metadata = MangaPageMetadata(page),
),
mimeType = MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(entry.name.substringAfterLast('.', "")),
dataSource = DataSource.DISK,
)
try {
val entry = zip.getEntry(uri.fragment)
SourceResult(
source = ImageSource(
source = zip.getInputStream(entry).source().withExtraCloseable(zip).buffer(),
context = context,
metadata = MangaPageMetadata(page),
),
mimeType = MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(entry.name.substringAfterLast('.', "")),
dataSource = DataSource.DISK,
)
} catch (e: Throwable) {
zip.closeQuietly()
throw e
}
}
uri.isFileUri() -> runInterruptible(Dispatchers.IO) {

View File

@@ -10,9 +10,9 @@ import coil.fetch.SourceResult
import coil.request.Options
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import okhttp3.internal.closeQuietly
import okio.buffer
import okio.source
import org.koitharu.kotatsu.core.util.ext.getInputStreamOrClose
import org.koitharu.kotatsu.local.data.util.withExtraCloseable
import java.util.zip.ZipFile
@@ -23,18 +23,23 @@ class CbzFetcher(
override suspend fun fetch() = runInterruptible(Dispatchers.IO) {
val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment)
val ext = MimeTypeMap.getFileExtensionFromUrl(entry.name)
val bufferedSource = zip.getInputStreamOrClose(entry).source().withExtraCloseable(zip).buffer()
SourceResult(
source = ImageSource(
source = bufferedSource,
context = options.context,
metadata = CbzMetadata(uri),
),
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext),
dataSource = DataSource.DISK,
)
try {
val entry = zip.getEntry(uri.fragment)
val ext = MimeTypeMap.getFileExtensionFromUrl(entry.name)
val bufferedSource = zip.getInputStream(entry).source().withExtraCloseable(zip).buffer()
SourceResult(
source = ImageSource(
source = bufferedSource,
context = options.context,
metadata = CbzMetadata(uri),
),
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext),
dataSource = DataSource.DISK,
)
} catch (e: Throwable) {
zip.closeQuietly()
throw e
}
}
class Factory : Fetcher.Factory<Uri> {

View File

@@ -14,6 +14,7 @@ import org.koitharu.kotatsu.core.backup.CompositeResult
import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.toUriOrNull
import org.koitharu.kotatsu.parsers.util.SuspendLazy
import java.io.File
@@ -71,7 +72,11 @@ class RestoreViewModel @Inject constructor(
override fun onCleared() {
super.onCleared()
backupInput.peek()?.cleanupAsync()
runCatching {
backupInput.peek()?.closeAndDelete()
}.onFailure {
it.printStackTraceDebug()
}
}
fun onItemClick(item: BackupEntryModel) {