package com.raizlabs.android.dbflow.sqlcipher; import android.content.Context; import com.raizlabs.android.dbflow.config.DatabaseConfig; import com.raizlabs.android.dbflow.config.DatabaseDefinition; import com.raizlabs.android.dbflow.config.FlowManager; import com.raizlabs.android.dbflow.structure.database.BaseDatabaseHelper; import com.raizlabs.android.dbflow.structure.database.DatabaseHelperDelegate; import com.raizlabs.android.dbflow.structure.database.DatabaseHelperListener; import com.raizlabs.android.dbflow.structure.database.DatabaseWrapper; import com.raizlabs.android.dbflow.structure.database.OpenHelper; import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteOpenHelper; /** * Description: The replacement {@link OpenHelper} for SQLCipher. Specify a subclass of this is {@link DatabaseConfig#databaseClass()} * of your database to get it to work with specifying the secret you use for the database. */ public abstract class SQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper { private DatabaseHelperDelegate databaseHelperDelegate; private SQLCipherDatabase cipherDatabase; public SQLCipherOpenHelper(DatabaseDefinition databaseDefinition, DatabaseHelperListener listener) { super(FlowManager.getContext(), databaseDefinition.isInMemory() ? null : databaseDefinition.getDatabaseFileName(), null, databaseDefinition.getDatabaseVersion()); SQLiteDatabase.loadLibs(FlowManager.getContext()); OpenHelper backupHelper = null; if (databaseDefinition.backupEnabled()) { // Temp database mirrors existing backupHelper = new BackupHelper(FlowManager.getContext(), DatabaseHelperDelegate.getTempDbFileName(databaseDefinition), databaseDefinition.getDatabaseVersion(), databaseDefinition); } databaseHelperDelegate = new DatabaseHelperDelegate(listener, databaseDefinition, backupHelper); } @Override public void performRestoreFromBackup() { databaseHelperDelegate.performRestoreFromBackup(); } @Override public DatabaseHelperDelegate getDelegate() { return databaseHelperDelegate; } @Override public boolean isDatabaseIntegrityOk() { return databaseHelperDelegate.isDatabaseIntegrityOk(); } @Override public void backupDB() { databaseHelperDelegate.backupDB(); } @Override public DatabaseWrapper getDatabase() { if (cipherDatabase == null || !cipherDatabase.getDatabase().isOpen()) { cipherDatabase = SQLCipherDatabase.from(getWritableDatabase(getCipherSecret())); } return cipherDatabase; } /** * Set a listener to listen for specific DB events and perform an action before we execute this classes * specific methods. * * @param listener */ public void setDatabaseListener(DatabaseHelperListener listener) { databaseHelperDelegate.setDatabaseHelperListener(listener); } @Override public void onCreate(SQLiteDatabase db) { databaseHelperDelegate.onCreate(SQLCipherDatabase.from(db)); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { databaseHelperDelegate.onUpgrade(SQLCipherDatabase.from(db), oldVersion, newVersion); } @Override public void onOpen(SQLiteDatabase db) { databaseHelperDelegate.onOpen(SQLCipherDatabase.from(db)); } @Override public void closeDB() { getDatabase(); cipherDatabase.getDatabase().close(); } /** * @return The SQLCipher secret for opening this database. */ protected abstract String getCipherSecret(); /** * Simple helper to manage backup. */ private class BackupHelper extends SQLiteOpenHelper implements OpenHelper { private SQLCipherDatabase sqlCipherDatabase; private final BaseDatabaseHelper baseDatabaseHelper; public BackupHelper(Context context, String name, int version, DatabaseDefinition databaseDefinition) { super(context, name, null, version); this.baseDatabaseHelper = new BaseDatabaseHelper(databaseDefinition); } @Override public DatabaseWrapper getDatabase() { if (sqlCipherDatabase == null) { sqlCipherDatabase = SQLCipherDatabase.from(getWritableDatabase(getCipherSecret())); } return sqlCipherDatabase; } @Override public void performRestoreFromBackup() { } @Override public DatabaseHelperDelegate getDelegate() { return null; } @Override public boolean isDatabaseIntegrityOk() { return false; } @Override public void backupDB() { } @Override public void closeDB() { } @Override public void setDatabaseListener(DatabaseHelperListener helperListener) { } @Override public void onCreate(SQLiteDatabase db) { baseDatabaseHelper.onCreate(SQLCipherDatabase.from(db)); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { baseDatabaseHelper.onUpgrade(SQLCipherDatabase.from(db), oldVersion, newVersion); } @Override public void onOpen(SQLiteDatabase db) { baseDatabaseHelper.onOpen(SQLCipherDatabase.from(db)); } } }