From 140ab34a76f7fb8d467c9ada000a1bbab6ea3a13 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 22:03:16 -0400 Subject: [PATCH] Verify database version before importing --- .../org/isoron/uhabits/HabitsApplication.java | 13 +++++- .../org/isoron/uhabits/io/LoopDBImporter.java | 41 +++++++++++++------ .../InvalidDatabaseVersionException.java | 24 +++++++++++ .../isoron/uhabits/utils/DatabaseUtils.java | 12 +++++- 4 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java diff --git a/app/src/main/java/org/isoron/uhabits/HabitsApplication.java b/app/src/main/java/org/isoron/uhabits/HabitsApplication.java index bad1c4ee5..8e2e1e8ad 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitsApplication.java +++ b/app/src/main/java/org/isoron/uhabits/HabitsApplication.java @@ -21,10 +21,10 @@ package org.isoron.uhabits; import android.app.*; import android.content.*; -import android.support.annotation.*; import com.activeandroid.*; +import org.isoron.uhabits.models.sqlite.*; import org.isoron.uhabits.notifications.*; import org.isoron.uhabits.preferences.*; import org.isoron.uhabits.tasks.*; @@ -88,7 +88,16 @@ public class HabitsApplication extends Application if (db.exists()) db.delete(); } - DatabaseUtils.initializeActiveAndroid(context); + try + { + DatabaseUtils.initializeActiveAndroid(context); + } + catch (InvalidDatabaseVersionException e) + { + File db = DatabaseUtils.getDatabaseFile(context); + db.renameTo(new File(db.getAbsolutePath() + ".invalid")); + DatabaseUtils.initializeActiveAndroid(context); + } widgetUpdater = component.getWidgetUpdater(); widgetUpdater.startListening(); diff --git a/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java b/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java index a3ebcf882..bfcf5886f 100644 --- a/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java @@ -19,20 +19,20 @@ package org.isoron.uhabits.io; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.support.annotation.NonNull; +import android.content.*; +import android.database.*; +import android.database.sqlite.*; +import android.support.annotation.*; +import android.util.*; -import com.activeandroid.ActiveAndroid; +import com.activeandroid.*; -import org.isoron.uhabits.AppContext; +import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.utils.DatabaseUtils; -import org.isoron.uhabits.utils.FileUtils; +import org.isoron.uhabits.utils.*; -import java.io.File; -import java.io.IOException; +import java.io.*; import javax.inject.*; @@ -45,7 +45,8 @@ public class LoopDBImporter extends AbstractImporter private Context context; @Inject - public LoopDBImporter(@NonNull @AppContext Context context, @NonNull HabitList habits) + public LoopDBImporter(@NonNull @AppContext Context context, + @NonNull HabitList habits) { super(habits); this.context = context; @@ -59,15 +60,29 @@ public class LoopDBImporter extends AbstractImporter SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getPath(), null, SQLiteDatabase.OPEN_READONLY); + boolean canHandle = true; + Cursor c = db.rawQuery( "select count(*) from SQLITE_MASTER where name=? or name=?", - new String[]{"Checkmarks", "Repetitions"}); + new String[]{ "Checkmarks", "Repetitions" }); + + if (!c.moveToFirst() || c.getInt(0) != 2) + { + Log.w("LoopDBImporter", "Cannot handle file: tables not found"); + canHandle = false; + } - boolean result = (c.moveToFirst() && c.getInt(0) == 2); + if (db.getVersion() > BuildConfig.databaseVersion) + { + Log.w("LoopDBImporter", String.format( + "Cannot handle file: incompatible version: %d > %d", + db.getVersion(), BuildConfig.databaseVersion)); + canHandle = false; + } c.close(); db.close(); - return result; + return canHandle; } @Override diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java new file mode 100644 index 000000000..6fb417cc4 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.models.sqlite; + +public class InvalidDatabaseVersionException extends RuntimeException +{ +} diff --git a/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java b/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java index 5e6d9e97a..4db87a8db 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java @@ -25,6 +25,7 @@ import android.support.annotation.*; import com.activeandroid.*; import org.isoron.uhabits.*; +import org.isoron.uhabits.models.sqlite.*; import org.isoron.uhabits.models.sqlite.records.*; import java.io.*; @@ -76,7 +77,16 @@ public abstract class DatabaseUtils RepetitionRecord.class, ScoreRecord.class, StreakRecord.class) .create(); - ActiveAndroid.initialize(dbConfig); + try + { + ActiveAndroid.initialize(dbConfig); + } + catch (RuntimeException e) + { + if(e.getMessage().contains("downgrade")) + throw new InvalidDatabaseVersionException(); + else throw e; + } } @SuppressWarnings("ResultOfMethodCallIgnored")