From 75e0d2d7e1929a617ea21e235d96e0448eea091b Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 00:29:07 +0100 Subject: [PATCH] Verify database version before import --- .../ImportExportPreferencesFragment.java | 4 +-- .../core/storage/DatabaseExporter.java | 32 +++++++++---------- .../antennapod/core/storage/PodDBAdapter.java | 12 +++---- core/src/main/res/values/strings.xml | 3 +- 4 files changed, 22 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java index 9a09d55b0..8036a7506 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java @@ -216,8 +216,8 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat { private void showExportErrorDialog(final Throwable error) { progressDialog.dismiss(); - final AlertDialog.Builder alert = new AlertDialog.Builder(getContext()) - .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); + final AlertDialog.Builder alert = new AlertDialog.Builder(getContext()); + alert.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); alert.setTitle(R.string.export_error_label); alert.setMessage(error.getMessage()); alert.show(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java index af3d1206c..234c01b20 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -14,21 +16,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.channels.FileChannel; -import java.util.Arrays; public class DatabaseExporter { private static final String TAG = "DatabaseExporter"; - private static final byte[] SQLITE3_MAGIC = "SQLite format 3\0".getBytes(); - - public static boolean validateDB(Uri inputUri, Context context) throws IOException { - try (InputStream inputStream = context.getContentResolver().openInputStream(inputUri)) { - byte[] magicBuf = new byte[SQLITE3_MAGIC.length]; - if (inputStream.read(magicBuf) == magicBuf.length) { - return Arrays.equals(SQLITE3_MAGIC, magicBuf); - } - } - return false; - } + private static final String TEMP_DB_NAME = PodDBAdapter.DATABASE_NAME + "_tmp"; public static void exportToDocument(Uri uri, Context context) throws IOException { ParcelFileDescriptor pfd = null; @@ -78,14 +69,21 @@ public class DatabaseExporter { public static void importBackup(Uri inputUri, Context context) throws IOException { InputStream inputStream = null; try { - if (!validateDB(inputUri, context)) { - throw new IOException(context.getString(R.string.import_bad_file)); + File tempDB = context.getDatabasePath(TEMP_DB_NAME); + inputStream = context.getContentResolver().openInputStream(inputUri); + FileUtils.copyInputStreamToFile(inputStream, tempDB); + + SQLiteDatabase db = SQLiteDatabase.openDatabase(tempDB.getAbsolutePath(), + null, SQLiteDatabase.OPEN_READONLY); + if (db.getVersion() > PodDBAdapter.VERSION) { + throw new IOException(context.getString(R.string.import_no_downgrade)); } + db.close(); File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME); - inputStream = context.getContentResolver().openInputStream(inputUri); - FileUtils.copyInputStreamToFile(inputStream, currentDB); - } catch (IOException e) { + currentDB.delete(); + FileUtils.moveFile(tempDB, currentDB); + } catch (IOException | SQLiteException e) { Log.e(TAG, Log.getStackTraceString(e)); throw e; } finally { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 17b79a3da..ce55591ae 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -48,6 +48,7 @@ public class PodDBAdapter { private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; + public static final int VERSION = 1090000; /** * Maximum number of arguments for IN-operator. @@ -1336,8 +1337,6 @@ public class PodDBAdapter { * Helper class for opening the Antennapod database. */ private static class PodDBHelper extends SQLiteOpenHelper { - private static final int VERSION = 1090000; - /** * Constructor. * @@ -1345,8 +1344,7 @@ public class PodDBAdapter { * @param name Name of the database * @param factory to use for creating cursor objects */ - public PodDBHelper(final Context context, final String name, - final CursorFactory factory) { + public PodDBHelper(final Context context, final String name, final CursorFactory factory) { super(context, name, factory, VERSION, new PodDbErrorHandler()); } @@ -1369,10 +1367,8 @@ public class PodDBAdapter { } @Override - public void onUpgrade(final SQLiteDatabase db, final int oldVersion, - final int newVersion) { - Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " - + newVersion + "."); + public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + "."); DBUpgrader.upgrade(db, oldVersion, newVersion); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index d87afcd09..0b9100075 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -572,6 +572,7 @@ Access to external storage is required to read the OPML file Select file to import Import successful.\n\nPlease press OK to restart AntennaPod + This database was exported with a newer version of AntennaPod. Your current installation does not yet know how to handle this file. Set sleep timer @@ -768,7 +769,6 @@ Failed to start the playback of media Failed to stop the playback of media Failed to pause the playback of media - Failed to set the volume No connection to the cast device is present Connection to the cast device has been lost. Application is trying to re-establish the connection, if possible. Please wait for a few seconds and try again. @@ -786,7 +786,6 @@ Allows to control playback. This is the main notification you see while playing a podcast. Errors Shown if something went wrong, for example if download or gpodder sync fails. - Invalid/corrupt file Widget settings