diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipInput.kt index 61da0c264..342f1640d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipInput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipInput.kt @@ -6,12 +6,14 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runInterruptible 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 import java.util.zip.ZipFile -class BackupZipInput(val file: File) : Closeable { +class BackupZipInput private constructor(val file: File) : Closeable { private val zipFile = ZipFile(file) @@ -41,4 +43,17 @@ class BackupZipInput(val file: File) : Closeable { } } } + + companion object { + + fun from(file: File): BackupZipInput = try { + val res = BackupZipInput(file) + if (res.zipFile.getEntry("index") == null) { + throw BadBackupFormatException(null) + } + res + } catch (e: ZipException) { + throw BadBackupFormatException(e) + } + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/BadBackupFormatException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/BadBackupFormatException.kt new file mode 100644 index 000000000..422d551d2 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/BadBackupFormatException.kt @@ -0,0 +1,5 @@ +package org.koitharu.kotatsu.core.exceptions + +import java.io.IOException + +class BadBackupFormatException(cause: Throwable?) : IOException(cause) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt index c19d76c6c..94726ef95 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt @@ -10,6 +10,7 @@ import okio.IOException import org.acra.ktx.sendWithAcra import org.jsoup.HttpStatusException import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.exceptions.BadBackupFormatException import org.koitharu.kotatsu.core.exceptions.CaughtException import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException @@ -43,6 +44,7 @@ fun Throwable.getDisplayMessage(resources: Resources): String = when (this) { is TooManyRequestExceptions -> resources.getString(R.string.too_many_requests_message) is UnsupportedFileException -> resources.getString(R.string.text_file_not_supported) + is BadBackupFormatException -> resources.getString(R.string.unsupported_backup_message) is FileNotFoundException -> resources.getString(R.string.file_not_found) is AccessDeniedException -> resources.getString(R.string.no_access_to_file) is EmptyHistoryException -> resources.getString(R.string.history_is_empty) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt index 2de76928c..919728c4d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt @@ -13,7 +13,9 @@ import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipInput import org.koitharu.kotatsu.core.backup.BackupZipOutput import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.exceptions.BadBackupFormatException import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import java.io.File import java.io.FileDescriptor import java.io.FileInputStream @@ -88,7 +90,12 @@ class AppBackupAgent : BackupAgent() { input.copyLimitedTo(output, size) } } - val backup = BackupZipInput(tempFile) + val backup = try { + BackupZipInput.from(tempFile) + } catch (e: BadBackupFormatException) { + tempFile.delete() + throw e + } try { runBlocking { backup.getEntry(BackupEntry.Name.HISTORY)?.let { repository.restoreHistory(it) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt index d1497f696..9acb88717 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt @@ -1,6 +1,8 @@ package org.koitharu.kotatsu.settings.backup +import android.content.ContentResolver import android.content.Context +import android.net.Uri import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext @@ -11,6 +13,8 @@ import org.koitharu.kotatsu.core.backup.BackupEntry import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipInput import org.koitharu.kotatsu.core.backup.CompositeResult +import org.koitharu.kotatsu.core.exceptions.BadBackupFormatException +import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call @@ -41,7 +45,7 @@ class RestoreViewModel @Inject constructor( input.copyTo(output) } } - BackupZipInput(tempFile) + BackupZipInput.from(tempFile) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6970d4c88..d914c5561 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -641,4 +641,5 @@ Show pages thumbnails Enable the \"Pages\" tab on the details screen No data was received from server + Please select a proper Kotatsu backup file