Skip to content

Commit f83d22d

Browse files
Add support for password and database hook on SQLiteOpenHelper
1 parent 07aae6c commit f83d22d

File tree

1 file changed

+85
-5
lines changed

1 file changed

+85
-5
lines changed

sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteOpenHelper.java

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import net.zetetic.database.sqlcipher.SQLiteDatabase.CursorFactory;
2727
import android.util.Log;
2828
import java.io.File;
29+
import java.nio.ByteBuffer;
30+
import java.nio.CharBuffer;
31+
import java.nio.charset.Charset;
2932

3033
/**
3134
* A helper class to manage database creation and version management.
@@ -63,9 +66,11 @@ public abstract class SQLiteOpenHelper {
6366
private final int mMinimumSupportedVersion;
6467

6568
private SQLiteDatabase mDatabase;
69+
private byte[] mPassword;
6670
private boolean mIsInitializing;
6771
private boolean mEnableWriteAheadLogging;
6872
private final DatabaseErrorHandler mErrorHandler;
73+
private final SQLiteDatabaseHook mDatabaseHook;
6974

7075
/**
7176
* Create a helper object to create, open, and/or manage a database.
@@ -131,13 +136,79 @@ public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int
131136
*/
132137
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
133138
int minimumSupportedVersion, DatabaseErrorHandler errorHandler) {
139+
this(context, name, new byte[0], factory, version, minimumSupportedVersion,
140+
errorHandler, null);
141+
}
142+
143+
/**
144+
* Same as {@link #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)}
145+
* but also accepts an integer minimumSupportedVersion as a convenience for upgrading very old
146+
* versions of this database that are no longer supported. If a database with older version that
147+
* minimumSupportedVersion is found, it is simply deleted and a new database is created with the
148+
* given name and version
149+
*
150+
* @param context to use to open or create the database
151+
* @param name the name of the database file, null for a temporary in-memory database
152+
* @param password for use with SQLCipher
153+
* @param factory to use for creating cursor objects, null for default
154+
* @param version the required version of the database
155+
* @param minimumSupportedVersion the minimum version that is supported to be upgraded to
156+
* {@code version} via {@link #onUpgrade}. If the current database version is lower
157+
* than this, database is simply deleted and recreated with the version passed in
158+
* {@code version}. {@link #onBeforeDelete} is called before deleting the database
159+
* when this happens. This is 0 by default.
160+
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
161+
* corruption, or null to use the default error handler.
162+
* @param databaseHook for preKey and postKey events with SQLCipher.
163+
* @see #onBeforeDelete(SQLiteDatabase)
164+
* @see #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)
165+
* @see #onUpgrade(SQLiteDatabase, int, int)
166+
* @hide
167+
*/
168+
public SQLiteOpenHelper(Context context, String name, String password, CursorFactory factory,
169+
int version, int minimumSupportedVersion,
170+
DatabaseErrorHandler errorHandler, SQLiteDatabaseHook databaseHook){
171+
this(context, name, getBytes(password), factory, version, minimumSupportedVersion,
172+
errorHandler, databaseHook);
173+
}
174+
175+
/**
176+
* Same as {@link #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)}
177+
* but also accepts an integer minimumSupportedVersion as a convenience for upgrading very old
178+
* versions of this database that are no longer supported. If a database with older version that
179+
* minimumSupportedVersion is found, it is simply deleted and a new database is created with the
180+
* given name and version
181+
*
182+
* @param context to use to open or create the database
183+
* @param name the name of the database file, null for a temporary in-memory database
184+
* @param password for use with SQLCipher
185+
* @param factory to use for creating cursor objects, null for default
186+
* @param version the required version of the database
187+
* @param minimumSupportedVersion the minimum version that is supported to be upgraded to
188+
* {@code version} via {@link #onUpgrade}. If the current database version is lower
189+
* than this, database is simply deleted and recreated with the version passed in
190+
* {@code version}. {@link #onBeforeDelete} is called before deleting the database
191+
* when this happens. This is 0 by default.
192+
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
193+
* corruption, or null to use the default error handler.
194+
* @param databaseHook for preKey and postKey events with SQLCipher.
195+
* @see #onBeforeDelete(SQLiteDatabase)
196+
* @see #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)
197+
* @see #onUpgrade(SQLiteDatabase, int, int)
198+
* @hide
199+
*/
200+
public SQLiteOpenHelper(Context context, String name, byte[] password, CursorFactory factory,
201+
int version, int minimumSupportedVersion,
202+
DatabaseErrorHandler errorHandler, SQLiteDatabaseHook databaseHook) {
134203
if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
135204

136205
mContext = context;
137206
mName = name;
207+
mPassword = password;
138208
mFactory = factory;
139209
mNewVersion = version;
140210
mErrorHandler = errorHandler;
211+
mDatabaseHook = databaseHook;
141212
mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
142213
}
143214

@@ -253,11 +324,11 @@ private SQLiteDatabase getDatabaseLocked(boolean writable) {
253324
try {
254325
if (DEBUG_STRICT_READONLY && !writable) {
255326
final String path = mContext.getDatabasePath(mName).getPath();
256-
db = SQLiteDatabase.openDatabase(path, mFactory,
257-
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
327+
db = SQLiteDatabase.openDatabase(path, mPassword, mFactory,
328+
SQLiteDatabase.OPEN_READONLY, mErrorHandler, mDatabaseHook);
258329
} else {
259330
db = SQLiteDatabase.openOrCreateDatabase(
260-
mName, mFactory, mErrorHandler
331+
mName, mPassword, mFactory, mErrorHandler, mDatabaseHook
261332
);
262333
}
263334
} catch (SQLiteException ex) {
@@ -267,8 +338,8 @@ private SQLiteDatabase getDatabaseLocked(boolean writable) {
267338
Log.e(TAG, "Couldn't open " + mName
268339
+ " for writing (will try read-only):", ex);
269340
final String path = mContext.getDatabasePath(mName).getPath();
270-
db = SQLiteDatabase.openDatabase(path, mFactory,
271-
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
341+
db = SQLiteDatabase.openDatabase(path, mPassword, mFactory,
342+
SQLiteDatabase.OPEN_READONLY, mErrorHandler, mDatabaseHook);
272343
}
273344
}
274345

@@ -438,4 +509,13 @@ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
438509
* @param db The database.
439510
*/
440511
public void onOpen(SQLiteDatabase db) {}
512+
513+
private static byte[] getBytes(String data) {
514+
if(data == null || data.length() == 0) return new byte[0];
515+
CharBuffer charBuffer = CharBuffer.wrap(data);
516+
ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
517+
byte[] result = new byte[byteBuffer.limit()];
518+
byteBuffer.get(result);
519+
return result;
520+
}
441521
}

0 commit comments

Comments
 (0)