react-native-sqlite-storage
react-native-sqlite-storage copied to clipboard
Encryption support
Is there a plan for encryption support anytime soon?
I've used this patch
diff --git a/node_modules/react-native-sqlite-storage/platforms/android/build.gradle b/node_modules/react-native-sqlite-storage/platforms/android/build.gradle
index 084752e..7fbd196 100644
--- a/node_modules/react-native-sqlite-storage/platforms/android/build.gradle
+++ b/node_modules/react-native-sqlite-storage/platforms/android/build.gradle
@@ -36,4 +36,6 @@ repositories {
dependencies {
implementation 'com.facebook.react:react-native:+'
+
+ implementation 'net.zetetic:android-database-sqlcipher:4.2.0'
}
diff --git a/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePlugin.java b/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePlugin.java
index 4f2391b..b0d12f0 100644
--- a/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePlugin.java
+++ b/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePlugin.java
@@ -8,10 +8,15 @@
package org.pgsqlite;
import android.annotation.SuppressLint;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.database.sqlite.SQLiteStatement;
+//import android.database.Cursor;
+//import android.database.sqlite.SQLiteDatabase;
+//import android.database.sqlite.SQLiteException;
+//import android.database.sqlite.SQLiteStatement;
+import net.sqlcipher.Cursor;
+import net.sqlcipher.database.SQLiteCursor;
+import net.sqlcipher.database.SQLiteDatabase;
+import net.sqlcipher.database.SQLiteException;
+import net.sqlcipher.database.SQLiteStatement;
import android.content.Context;
import android.util.Base64;
@@ -335,7 +340,7 @@ public class SQLitePlugin extends ReactContextBaseJavaModule {
* @return instance of SQLite database
* @throws Exception
*/
- private SQLiteDatabase openDatabase(String dbname, String assetFilePath, int openFlags, CallbackContext cbc) throws Exception {
+ private SQLiteDatabase openDatabase(String dbname, String key, String assetFilePath, int openFlags, CallbackContext cbc) throws Exception {
InputStream in = null;
File dbfile = null;
try {
@@ -411,7 +416,7 @@ public class SQLitePlugin extends ReactContextBaseJavaModule {
FLog.v(TAG, "DB file is ready, proceeding to OPEN SQLite DB: " + dbfile.getAbsolutePath());
- SQLiteDatabase mydb = SQLiteDatabase.openDatabase(dbfile.getAbsolutePath(), null, openFlags);
+ SQLiteDatabase mydb = SQLiteDatabase.openDatabase(dbfile.getAbsolutePath(), key, null, openFlags);
if (cbc != null)
cbc.success("Database opened");
@@ -868,7 +873,16 @@ public class SQLitePlugin extends ReactContextBaseJavaModule {
}
}
+ private void closeQuietly(SQLiteCursor closeable) {
+ closeable.close();
+ }
+
+ private void closeQuietly(SQLiteStatement closeable) {
+ closeable.close();
+ }
+
private class DBRunner implements Runnable {
+ final String key;
final String dbname;
final int openFlags;
private String assetFilename;
@@ -880,6 +894,7 @@ public class SQLitePlugin extends ReactContextBaseJavaModule {
DBRunner(final String dbname, ReadableMap options, CallbackContext cbc) {
this.dbname = dbname;
+ this.key = options.getString("key");
int openFlags = SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.CREATE_IF_NECESSARY;
try {
this.assetFilename = SQLitePluginConverter.getString(options,"assetFilename",null);
@@ -901,7 +916,7 @@ public class SQLitePlugin extends ReactContextBaseJavaModule {
public void run() {
try {
- this.mydb = openDatabase(dbname, this.assetFilename, this.openFlags, this.openCbc);
+ this.mydb = openDatabase(dbname, key, this.assetFilename, this.openFlags, this.openCbc);
} catch (SQLiteException ex) {
FLog.e(TAG, "SQLite error opening database, stopping db thread", ex);
if (this.openCbc != null) {
@@ -930,7 +945,7 @@ public class SQLitePlugin extends ReactContextBaseJavaModule {
if (androidLockWorkaround && dbq.queries.length == 1 && dbq.queries[0].equals("COMMIT")) {
// FLog.v(TAG, "close and reopen db");
closeDatabaseNow(dbname);
- this.mydb = openDatabase(dbname, "", this.openFlags, null);
+ this.mydb = openDatabase(dbname, key, "", this.openFlags, null);
// FLog.v(TAG, "close and reopen db finished");
}
diff --git a/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePluginPackage.java b/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePluginPackage.java
index be25027..ddec9cc 100644
--- a/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePluginPackage.java
+++ b/node_modules/react-native-sqlite-storage/platforms/android/src/main/java/org/pgsqlite/SQLitePluginPackage.java
@@ -13,6 +13,8 @@ import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
+import net.sqlcipher.database.SQLiteDatabase;
+
import java.util.ArrayList;
import java.util.Collections;
@@ -34,6 +36,8 @@ public class SQLitePluginPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
+ SQLiteDatabase.loadLibs(reactContext);
+
List<NativeModule> modules = new ArrayList<>();
modules.add(new SQLitePlugin(reactContext));
diff --git a/node_modules/react-native-sqlite-storage/platforms/ios/SQLite.m b/node_modules/react-native-sqlite-storage/platforms/ios/SQLite.m
index 6ba5355..1ce1b5f 100644
--- a/node_modules/react-native-sqlite-storage/platforms/ios/SQLite.m
+++ b/node_modules/react-native-sqlite-storage/platforms/ios/SQLite.m
@@ -32,7 +32,12 @@
* See http://opensource.org/licenses/alphabetical for full text.
*/
+#ifdef SQLCIPHER
+#define SQLITE_HAS_CODEC
+#import <SQLCipher/sqlite3.h>
+#else
#import "sqlite3.h"
+#endif
#include <regex.h>
@@ -75,7 +80,7 @@ @implementation SQLite
- (id) init
{
- RCTLog(@"Initializing SQLitePlugin");
+// RCTLog(@"Initializing SQLitePlugin");
self = [super init];
if (self) {
openDBs = [NSMutableDictionary dictionaryWithCapacity:0];
@@ -86,18 +91,18 @@ - (id) init
#endif
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
- RCTLog(@"Detected docs path: %@", docs);
+// RCTLog(@"Detected docs path: %@", docs);
[appDBPaths setObject: docs forKey:@"docs"];
NSString *libs = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
- RCTLog(@"Detected Library path: %@", libs);
+// RCTLog(@"Detected Library path: %@", libs);
[appDBPaths setObject: libs forKey:@"libs"];
NSString *nosync = [libs stringByAppendingPathComponent:@"LocalDatabase"];
NSError *err;
if ([[NSFileManager defaultManager] fileExistsAtPath: nosync])
{
- RCTLog(@"no cloud sync at path: %@", nosync);
+// RCTLog(@"no cloud sync at path: %@", nosync);
[appDBPaths setObject: nosync forKey:@"nosync"];
}
else
@@ -109,7 +114,7 @@ - (id) init
{
RCTLog(@"IGNORED: error setting nobackup flag in LocalDatabase directory: %@", err);
}
- RCTLog(@"no cloud sync at path: %@", nosync);
+// RCTLog(@"no cloud sync at path: %@", nosync);
[appDBPaths setObject: nosync forKey:@"nosync"];
}
else
@@ -161,7 +166,7 @@ -(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
} else {
NSDictionary *dbInfo = openDBs[dbfilename];
if (dbInfo != NULL && dbInfo[@"dbPointer"] != NULL) {
- RCTLog(@"Reusing existing database connection for db name %@", dbfilename);
+// RCTLog(@"Reusing existing database connection for db name %@", dbfilename);
pluginResult = [SQLiteResult resultWithStatus:SQLiteStatus_OK messageAsString:@"Database opened"];
} else {
NSString *assetFilePath = options[@"assetFilename"];
@@ -171,17 +176,17 @@ -(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
NSString *targetBundleDirPath = [[NSBundle mainBundle] resourcePath];
targetBundleDirPath = [targetBundleDirPath stringByAppendingPathComponent: @"www"];
assetFilePath = [targetBundleDirPath stringByAppendingPathComponent: dbfilename];
- RCTLog(@"Built path to pre-populated DB asset from app bundle www subdirectory: %@",assetFilePath);
+// RCTLog(@"Built path to pre-populated DB asset from app bundle www subdirectory: %@",assetFilePath);
} else if ([assetFilePath hasPrefix:@"~"]) {
assetFilePath = [assetFilePath substringFromIndex:1];
NSString *targetBundleDirPath = [[NSBundle mainBundle] resourcePath];
assetFilePath = [targetBundleDirPath stringByAppendingPathComponent: assetFilePath];
- RCTLog(@"Built path to pre-populated DB asset from app bundle subdirectory: %@",assetFilePath);
+// RCTLog(@"Built path to pre-populated DB asset from app bundle subdirectory: %@",assetFilePath);
} else {
NSURL * documentsDirUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
assetFilePath = [documentsDirUrl.path stringByAppendingPathComponent:assetFilePath];
- RCTLog(@"Built path to pre-populated DB asset from app sandbox documents directory: %@",assetFilePath);
+// RCTLog(@"Built path to pre-populated DB asset from app sandbox documents directory: %@",assetFilePath);
}
} @catch(NSException *ex){
RCTLog(@"Error building path for pre-populated DB asset %@",ex.reason);
@@ -194,18 +199,18 @@ -(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
} else {
NSString *dblocation = options[@"dblocation"];
if (dblocation == NULL) dblocation = @"nosync";
- RCTLog(@"target database location: %@", dblocation);
+// RCTLog(@"target database location: %@", dblocation);
dbname = [self getDBPath:dbfilename at:dblocation];
/* Option to create from resource (pre-populated) if db does not exist: */
if (![[NSFileManager defaultManager] fileExistsAtPath:dbname] && assetFilePath != NULL) {
- RCTLog(@"Copying pre-populated asset to the destination directory");
+// RCTLog(@"Copying pre-populated asset to the destination directory");
[self createFromResource:assetFilePath withDbname:dbname];
}
}
- RCTLog(@"Opening db in mode %@, full path: %@", (sqlOpenFlags == SQLITE_OPEN_READONLY) ? @"READ ONLY" : @"READ_WRITE",dbname);
+// RCTLog(@"Opening db in mode %@, full path: %@", (sqlOpenFlags == SQLITE_OPEN_READONLY) ? @"READ ONLY" : @"READ_WRITE",dbname);
const char *name = [dbname UTF8String];
sqlite3 *db;
@@ -222,7 +227,7 @@ -(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
if (dbkey != NULL) {
key = [dbkey UTF8String];
if (key != NULL) {
- sqlite3_key(db, key, strlen(key));
+ sqlite3_key(db, key, (int)strlen(key));
}
}
#endif
@@ -232,7 +237,7 @@ -(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
openDBs[dbfilename] = @{ @"dbPointer": dbPointer, @"dbPath" : dbname};
NSString *msg = (key != NULL) ? @"Secure database opened" : @"Database opened";
pluginResult = [SQLiteResult resultWithStatus:SQLiteStatus_OK messageAsString: msg];
- RCTLog(@"%@", msg);
+// RCTLog(@"%@", msg);
} else {
NSString *msg = [NSString stringWithFormat:@"Unable to open %@", (key != NULL) ? @"secure database with key" : @"database"];
pluginResult = [SQLiteResult resultWithStatus:SQLiteStatus_ERROR messageAsString:msg];
@@ -246,25 +251,25 @@ -(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
}
if (sqlite3_threadsafe()) {
- RCTLog(@"Good news: SQLite is thread safe!");
+// RCTLog(@"Good news: SQLite is thread safe!");
} else {
RCTLog(@"Warning: SQLite is not thread safe.");
}
[pluginResult.status intValue] == SQLiteStatus_OK ? success(@[pluginResult.message]) : error(@[pluginResult.message]);
- RCTLog(@"open cb finished ok");
+// RCTLog(@"open cb finished ok");
}
-(void)createFromResource:(NSString *)prepopulatedDb withDbname:(NSString *)dbname {
- RCTLog(@"Looking for prepopulated DB at: %@", prepopulatedDb);
+// RCTLog(@"Looking for prepopulated DB at: %@", prepopulatedDb);
if ([[NSFileManager defaultManager] fileExistsAtPath:prepopulatedDb]) {
- RCTLog(@"Found prepopulated DB: %@", prepopulatedDb);
+// RCTLog(@"Found prepopulated DB: %@", prepopulatedDb);
NSError *error;
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:prepopulatedDb toPath:dbname error:&error];
if(success) {
- RCTLog(@"Copied prepopulated DB content to: %@", dbname);
+// RCTLog(@"Copied prepopulated DB content to: %@", dbname);
} else {
RCTLog(@"Unable to copy DB file: %@", [error localizedDescription]);
}
@@ -299,16 +304,16 @@ -(void)createFromResource:(NSString *)prepopulatedDb withDbname:(NSString *)dbna
RCTLog(@"close: db name was not open: %@", dbFileName);
pluginResult = [SQLiteResult resultWithStatus:SQLiteStatus_ERROR messageAsString:@"Specified db was not open"];
} else {
- RCTLog(@"close: closing db: %@", dbFileName);
+// RCTLog(@"close: closing db: %@", dbFileName);
sqlite3_close (db);
[openDBs removeObjectForKey:dbFileName];
pluginResult = [SQLiteResult resultWithStatus:SQLiteStatus_OK messageAsString:@"DB closed"];
}
if ([[NSFileManager defaultManager]fileExistsAtPath:dbPath]) {
- RCTLog(@"database file still exists after close");
+// RCTLog(@"database file still exists after close");
} else {
- RCTLog(@"database file doesn't exists after close");
+// RCTLog(@"database file doesn't exists after close");
}
}
}
diff --git a/node_modules/react-native-sqlite-storage/react-native-sqlite-storage.podspec b/node_modules/react-native-sqlite-storage/react-native-sqlite-storage.podspec
index afc3e92..630228c 100644
--- a/node_modules/react-native-sqlite-storage/react-native-sqlite-storage.podspec
+++ b/node_modules/react-native-sqlite-storage/react-native-sqlite-storage.podspec
@@ -18,5 +18,8 @@ Pod::Spec.new do |s|
s.source_files = "platforms/ios/*.{h,m}"
s.dependency 'React'
- s.library = 'sqlite3'
+# s.library = 'sqlite3'
+
+ s.dependency 'SQLCipher'
+ s.compiler_flags = ['-DSQLCIPHER=1']
end