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