Index: sqlite3/src/androidTest/java/org/sqlite/database/SeeTest1.java ================================================================== --- sqlite3/src/androidTest/java/org/sqlite/database/SeeTest1.java +++ sqlite3/src/androidTest/java/org/sqlite/database/SeeTest1.java @@ -1,43 +1,40 @@ package org.sqlite.database; - import android.content.Context; import android.database.Cursor; import android.os.AsyncTask; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; +import android.util.Log; import junit.framework.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.sqlite.database.sqlite.SQLiteConnection; import org.sqlite.database.sqlite.SQLiteDatabase; import org.sqlite.database.sqlite.SQLiteOpenHelper; import java.io.File; +import java.io.FileInputStream; +import java.util.Arrays; import static org.junit.Assert.*; class MyHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "mydb.db"; public MyHelper(Context ctx){ - super(ctx, ctx.getDatabasePath(DATABASE_NAME).getAbsolutePath(), null, 1); + super(ctx, "file:" + ctx.getDatabasePath(DATABASE_NAME).getAbsolutePath() + "?key=secret", null, 1); } public void onConfigure(SQLiteDatabase db){ - db.execSQL("PRAGMA key = 'secret'"); - db.enableWriteAheadLogging(); - - final Cursor pragmaCursor = db.rawQuery("PRAGMA journal_mode = WAL", null); - pragmaCursor.moveToFirst(); - pragmaCursor.close(); } public void onCreate(SQLiteDatabase db){ db.execSQL("CREATE TABLE t1(x)"); } public void onUpgrade(SQLiteDatabase db, int iOld, int iNew){ @@ -48,11 +45,32 @@ /** * Created by dan on 5/3/17. */ @RunWith(AndroidJUnit4.class) public class SeeTest1 { - private Context mContext; + private Context mContext; + + /* + ** Test if the database at path is encrypted or not. The db + ** is assumed to be encrypted if the first 6 bytes are anything + ** other than "SQLite". + ** + ** If the test reveals that the db is encrypted, return the string + ** "encrypted". Otherwise, "unencrypted". + */ + public String db_is_encrypted(String path) throws Exception { + FileInputStream in = new FileInputStream(mContext.getDatabasePath(path)); + + byte[] buffer = new byte[6]; + in.read(buffer, 0, 6); + + String res = "encrypted"; + if( Arrays.equals(buffer, (new String("SQLite")).getBytes()) ){ + res = "unencrypted"; + } + return res; + } @Before public void setup() throws Exception { System.loadLibrary("sqliteX"); @@ -66,19 +84,19 @@ databaseFile.delete(); } } @Test - public void testAndroidDefaultWalMode() throws Exception { + public void testEncryptedWalMode() throws Exception { // create database final MyHelper helper = new MyHelper(mContext); helper.getWritableDatabase(); // verify that WAL journal mode is set final Cursor pragmaCursor = helper.getWritableDatabase().rawQuery("PRAGMA journal_mode", null); pragmaCursor.moveToFirst(); - Assert.assertEquals(pragmaCursor.getString(pragmaCursor.getColumnIndex("journal_mode")), "wal"); + Assert.assertEquals("wal", pragmaCursor.getString(pragmaCursor.getColumnIndex("journal_mode"))); pragmaCursor.close(); // start long running transaction AsyncTask.execute(new Runnable() { @Override @@ -107,7 +125,13 @@ //verify that the operation didn't wait until the 3000ms long operation finished if (System.currentTimeMillis() - startTime > 3000) { throw new Exception("WAL mode isn't working corectly - read operation was blocked"); } + + if( SQLiteConnection.hasCodec() ){ + Assert.assertEquals("encrypted", db_is_encrypted(MyHelper.DATABASE_NAME)); + } else { + Assert.assertEquals("unencrypted", db_is_encrypted(MyHelper.DATABASE_NAME)); + } } } Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java @@ -220,14 +220,12 @@ setPageSize(); setForeignKeyModeFromConfiguration(); setJournalSizeLimit(); setAutoCheckpointInterval(); - if( !nativeHasCodec() ){ - setWalModeFromConfiguration(); - setLocaleFromConfiguration(); - } + setWalModeFromConfiguration(); + setLocaleFromConfiguration(); // Register custom functions. final int functionCount = mConfiguration.customFunctions.size(); for (int i = 0; i < functionCount; i++) { SQLiteCustomFunction function = mConfiguration.customFunctions.get(i); Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java @@ -948,13 +948,11 @@ private static int getPriority(int connectionFlags) { return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0; } private void setMaxConnectionPoolSizeLocked() { - if( !SQLiteDatabase.hasCodec() - && (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0 - ) { + if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) { mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize(); } else { // TODO: We don't actually need to restrict the connection pool size to 1 // for non-WAL databases. There might be reasons to use connection pooling // with other journal modes. For now, enabling connection pooling and Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseConfiguration.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseConfiguration.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseConfiguration.java @@ -159,10 +159,16 @@ public boolean isInMemoryDb() { return path.equalsIgnoreCase(MEMORY_DB_PATH); } private static String stripPathForLogs(String path) { + /* Strip off all URI parameters. */ + int iIdx = path.indexOf('?'); + if( iIdx>=0 ){ + path = (String) path.subSequence(0, iIdx); + } + if (path.indexOf('@') == -1) { return path; } return EMAIL_IN_DB_PATTERN.matcher(path).replaceAll("XX@YY"); } Index: sqlite3/src/main/jni/sqlite/Android.mk ================================================================== --- sqlite3/src/main/jni/sqlite/Android.mk +++ sqlite3/src/main/jni/sqlite/Android.mk @@ -22,12 +22,13 @@ LOCAL_CFLAGS += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA LOCAL_CFLAGS += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL LOCAL_CFLAGS += -U__APPLE__ LOCAL_CFLAGS += -DHAVE_STRCHRNUL=0 +LOCAL_CFLAGS += -DSQLITE_USE_URI=1 LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast -LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses +LOCAL_CFLAGS += -Wno-uninitialized -Wno-parentheses LOCAL_CPPFLAGS += -Wno-conversion-null ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"