Verify database version before import
This commit is contained in:
parent
7e2fd0b1d7
commit
75e0d2d7e1
|
@ -216,8 +216,8 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
private void showExportErrorDialog(final Throwable error) {
|
private void showExportErrorDialog(final Throwable error) {
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
final AlertDialog.Builder alert = new AlertDialog.Builder(getContext())
|
final AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
.setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
|
alert.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
|
||||||
alert.setTitle(R.string.export_error_label);
|
alert.setTitle(R.string.export_error_label);
|
||||||
alert.setMessage(error.getMessage());
|
alert.setMessage(error.getMessage());
|
||||||
alert.show();
|
alert.show();
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package de.danoeh.antennapod.core.storage;
|
package de.danoeh.antennapod.core.storage;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -14,21 +16,10 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class DatabaseExporter {
|
public class DatabaseExporter {
|
||||||
private static final String TAG = "DatabaseExporter";
|
private static final String TAG = "DatabaseExporter";
|
||||||
private static final byte[] SQLITE3_MAGIC = "SQLite format 3\0".getBytes();
|
private static final String TEMP_DB_NAME = PodDBAdapter.DATABASE_NAME + "_tmp";
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void exportToDocument(Uri uri, Context context) throws IOException {
|
public static void exportToDocument(Uri uri, Context context) throws IOException {
|
||||||
ParcelFileDescriptor pfd = null;
|
ParcelFileDescriptor pfd = null;
|
||||||
|
@ -78,14 +69,21 @@ public class DatabaseExporter {
|
||||||
public static void importBackup(Uri inputUri, Context context) throws IOException {
|
public static void importBackup(Uri inputUri, Context context) throws IOException {
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
try {
|
try {
|
||||||
if (!validateDB(inputUri, context)) {
|
File tempDB = context.getDatabasePath(TEMP_DB_NAME);
|
||||||
throw new IOException(context.getString(R.string.import_bad_file));
|
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);
|
File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME);
|
||||||
inputStream = context.getContentResolver().openInputStream(inputUri);
|
currentDB.delete();
|
||||||
FileUtils.copyInputStreamToFile(inputStream, currentDB);
|
FileUtils.moveFile(tempDB, currentDB);
|
||||||
} catch (IOException e) {
|
} catch (IOException | SQLiteException e) {
|
||||||
Log.e(TAG, Log.getStackTraceString(e));
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class PodDBAdapter {
|
||||||
|
|
||||||
private static final String TAG = "PodDBAdapter";
|
private static final String TAG = "PodDBAdapter";
|
||||||
public static final String DATABASE_NAME = "Antennapod.db";
|
public static final String DATABASE_NAME = "Antennapod.db";
|
||||||
|
public static final int VERSION = 1090000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of arguments for IN-operator.
|
* Maximum number of arguments for IN-operator.
|
||||||
|
@ -1336,8 +1337,6 @@ public class PodDBAdapter {
|
||||||
* Helper class for opening the Antennapod database.
|
* Helper class for opening the Antennapod database.
|
||||||
*/
|
*/
|
||||||
private static class PodDBHelper extends SQLiteOpenHelper {
|
private static class PodDBHelper extends SQLiteOpenHelper {
|
||||||
private static final int VERSION = 1090000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
|
@ -1345,8 +1344,7 @@ public class PodDBAdapter {
|
||||||
* @param name Name of the database
|
* @param name Name of the database
|
||||||
* @param factory to use for creating cursor objects
|
* @param factory to use for creating cursor objects
|
||||||
*/
|
*/
|
||||||
public PodDBHelper(final Context context, final String name,
|
public PodDBHelper(final Context context, final String name, final CursorFactory factory) {
|
||||||
final CursorFactory factory) {
|
|
||||||
super(context, name, factory, VERSION, new PodDbErrorHandler());
|
super(context, name, factory, VERSION, new PodDbErrorHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1369,10 +1367,8 @@ public class PodDBAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
|
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||||
final int newVersion) {
|
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + ".");
|
||||||
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
|
|
||||||
+ newVersion + ".");
|
|
||||||
DBUpgrader.upgrade(db, oldVersion, newVersion);
|
DBUpgrader.upgrade(db, oldVersion, newVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -572,6 +572,7 @@
|
||||||
<string name="opml_import_ask_read_permission">Access to external storage is required to read the OPML file</string>
|
<string name="opml_import_ask_read_permission">Access to external storage is required to read the OPML file</string>
|
||||||
<string name="import_select_file">Select file to import</string>
|
<string name="import_select_file">Select file to import</string>
|
||||||
<string name="import_ok">Import successful.\n\nPlease press OK to restart AntennaPod</string>
|
<string name="import_ok">Import successful.\n\nPlease press OK to restart AntennaPod</string>
|
||||||
|
<string name="import_no_downgrade">This database was exported with a newer version of AntennaPod. Your current installation does not yet know how to handle this file.</string>
|
||||||
|
|
||||||
<!-- Sleep timer -->
|
<!-- Sleep timer -->
|
||||||
<string name="set_sleeptimer_label">Set sleep timer</string>
|
<string name="set_sleeptimer_label">Set sleep timer</string>
|
||||||
|
@ -768,7 +769,6 @@
|
||||||
<string name="cast_failed_to_play">Failed to start the playback of media</string>
|
<string name="cast_failed_to_play">Failed to start the playback of media</string>
|
||||||
<string name="cast_failed_to_stop">Failed to stop the playback of media</string>
|
<string name="cast_failed_to_stop">Failed to stop the playback of media</string>
|
||||||
<string name="cast_failed_to_pause">Failed to pause the playback of media</string>
|
<string name="cast_failed_to_pause">Failed to pause the playback of media</string>
|
||||||
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
|
|
||||||
<string name="cast_failed_setting_volume">Failed to set the volume</string>
|
<string name="cast_failed_setting_volume">Failed to set the volume</string>
|
||||||
<string name="cast_failed_no_connection">No connection to the cast device is present</string>
|
<string name="cast_failed_no_connection">No connection to the cast device is present</string>
|
||||||
<string name="cast_failed_no_connection_trans">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.</string>
|
<string name="cast_failed_no_connection_trans">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.</string>
|
||||||
|
@ -786,7 +786,6 @@
|
||||||
<string name="notification_channel_playing_description">Allows to control playback. This is the main notification you see while playing a podcast.</string>
|
<string name="notification_channel_playing_description">Allows to control playback. This is the main notification you see while playing a podcast.</string>
|
||||||
<string name="notification_channel_error">Errors</string>
|
<string name="notification_channel_error">Errors</string>
|
||||||
<string name="notification_channel_error_description">Shown if something went wrong, for example if download or gpodder sync fails.</string>
|
<string name="notification_channel_error_description">Shown if something went wrong, for example if download or gpodder sync fails.</string>
|
||||||
<string name="import_bad_file">Invalid/corrupt file</string>
|
|
||||||
|
|
||||||
<!-- Widget settings -->
|
<!-- Widget settings -->
|
||||||
<string name="widget_settings">Widget settings</string>
|
<string name="widget_settings">Widget settings</string>
|
||||||
|
|
Loading…
Reference in New Issue