11package nl .sense_os .service .storage ;
22
3- import nl .sense_os .service .constants .SensorData .DataPoint ;
4- import nl .sense_os .service .constants .SensePrefs ;
5- import nl .sense_os .service .constants .SensePrefs .Main .Advanced ;
63import android .content .Context ;
74import android .content .SharedPreferences ;
8- import net .sqlcipher .database .SQLiteDatabase ;
9- import net .sqlcipher .database .SQLiteOpenHelper ;
10- import net .sqlcipher .database .SQLiteException ;
115import android .provider .BaseColumns ;
12- import android .util .Log ;
136import android .telephony .TelephonyManager ;
7+ import android .util .Log ;
8+
9+ import net .sqlcipher .database .SQLiteDatabase ;
10+ import net .sqlcipher .database .SQLiteException ;
11+ import net .sqlcipher .database .SQLiteOpenHelper ;
12+
1413import java .io .File ;
1514import java .security .MessageDigest ;
1615import java .security .NoSuchAlgorithmException ;
1716
17+ import nl .sense_os .service .constants .SensePrefs ;
18+ import nl .sense_os .service .constants .SensePrefs .Main .Advanced ;
19+ import nl .sense_os .service .constants .SensorData .DataPoint ;
20+
1821/**
1922 * Helper class that assist in creating, opening and managing the SQLite3 database for data points.
2023 */
@@ -41,8 +44,12 @@ public class DbHelper extends SQLiteOpenHelper {
4144
4245 private static String passphrase = "" ;
4346
47+ private static boolean libsLoaded = false ;
48+
4449 private static final String TAG = "DbHelper" ;
4550
51+ private Context mContext ;
52+
4653 /**
4754 * Constructor. The database is not actually created or opened until one of
4855 * {@link #getWritableDatabase()} or {@link #getReadableDatabase()} is called.
@@ -55,45 +62,44 @@ public class DbHelper extends SQLiteOpenHelper {
5562 public DbHelper (Context context , boolean persistent ) {
5663 // if the database name is null, it will be created in-memory
5764 super (context , persistent ? DATABASE_NAME : null , null , DATABASE_VERSION );
65+ this .mContext = context ;
5866
5967 if (null == sMainPrefs ) {
60- sMainPrefs = context .getSharedPreferences (SensePrefs .MAIN_PREFS ,
61- Context .MODE_PRIVATE );
68+ sMainPrefs = mContext .getSharedPreferences (SensePrefs .MAIN_PREFS ,
69+ Context .MODE_PRIVATE );
6270 }
71+ loadLibs (context );
72+ updateEncryption ();
73+ // add a listener to update the encryption settings when it changes
74+ sMainPrefs .registerOnSharedPreferenceChangeListener (encryptionChanged );
75+ }
6376
77+ public void updateEncryption ()
78+ {
6479 boolean encrypt = sMainPrefs .getBoolean (Advanced .ENCRYPT_DATABASE , false );
65-
6680 if (encrypt ) {
67- TelephonyManager telephonyManager = (TelephonyManager ) context .getSystemService (Context .TELEPHONY_SERVICE );
81+ TelephonyManager telephonyManager = (TelephonyManager ) mContext .getSystemService (Context .TELEPHONY_SERVICE );
6882 String imei = telephonyManager .getDeviceId ();
69-
7083 setPassphrase (imei );
7184 }
85+ }
7286
73- SQLiteDatabase .loadLibs (context );
74-
75- // check for old plain database
76- if (persistent && encrypt ) {
77- // try to open the database with the password from the user.
78- // The only possible error now must be a wrong password or using plain database.
79- try {
80- getWritableDatabase (passphrase );
81- } catch (SQLiteException e ) {
82- Log .v (TAG , "Trying to encrypte old plain database" );
83- File plain = context .getDatabasePath (DATABASE_NAME );
84- File encrypted = context .getDatabasePath ("tmp.db" );
85-
86- // try to open the database without password
87- SQLiteDatabase migrate_db = SQLiteDatabase .openOrCreateDatabase (plain , "" , null );
88- migrate_db .rawExecSQL (String .format ("ATTACH DATABASE '%s' AS encrypted KEY '%s'" ,
89- encrypted .getAbsolutePath (), passphrase ));
90- migrate_db .rawExecSQL ("SELECT sqlcipher_export('encrypted');" );
91- migrate_db .execSQL ("DETACH DATABASE encrypted;" );
92- migrate_db .close ();
93-
94- // rename the encrypted file name back
95- encrypted .renameTo (new File (plain .getAbsolutePath ()));
96- }
87+ /**
88+ * Monitor changes in the database encryption settings
89+ */
90+ SharedPreferences .OnSharedPreferenceChangeListener encryptionChanged = new SharedPreferences .OnSharedPreferenceChangeListener () {
91+ @ Override
92+ public void onSharedPreferenceChanged (SharedPreferences sharedPreferences , String key )
93+ {
94+ if (key .equals (Advanced .ENCRYPT_DATABASE ) || key .equals (Advanced .ENCRYPT_DATABASE_SALT ))
95+ updateEncryption ();
96+ }
97+ };
98+
99+ public static synchronized void loadLibs (Context context ) {
100+ if (!libsLoaded ) {
101+ SQLiteDatabase .loadLibs (context );
102+ libsLoaded = true ;
97103 }
98104 }
99105
@@ -127,11 +133,36 @@ public void onUpgrade(SQLiteDatabase db, int oldVers, int newVers) {
127133 }
128134
129135 public SQLiteDatabase getWritableDatabase (){
130- return getWritableDatabase (passphrase );
136+ try {
137+ return getWritableDatabase (passphrase );
138+ } catch (SQLiteException e ) {
139+ migrateDatabase ();
140+ return getWritableDatabase (passphrase );
141+ }
131142 }
132143
133144 public SQLiteDatabase getReadableDatabase (){
134- return getReadableDatabase (passphrase );
145+ try {
146+ return getWritableDatabase (passphrase );
147+ } catch (SQLiteException e ) {
148+ migrateDatabase ();
149+ return getWritableDatabase (passphrase );
150+ }
151+ }
152+
153+ private void migrateDatabase () {
154+ File plain = mContext .getDatabasePath (DATABASE_NAME );
155+ File encrypted = mContext .getDatabasePath ("tmp.db" );
156+
157+ // try to open the database without password
158+ SQLiteDatabase migrate_db = SQLiteDatabase .openOrCreateDatabase (plain , "" , null );
159+ migrate_db .rawExecSQL (String .format ("ATTACH DATABASE '%s' AS encrypted KEY '%s'" , encrypted .getAbsolutePath (), passphrase ));
160+ migrate_db .rawExecSQL ("SELECT sqlcipher_export('encrypted');" );
161+ migrate_db .execSQL ("DETACH DATABASE encrypted;" );
162+ migrate_db .close ();
163+
164+ // rename the encrypted file name back
165+ encrypted .renameTo (new File (plain .getAbsolutePath ()));
135166 }
136167
137168 private void setPassphrase (String imei ) {
0 commit comments