Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Change Log
==========

Version 1.0.5 *(2019-02-18)*
----------------------------

* Reduce size by taking out encrypted database library as a separate module
* New: Add support for database delete
* Changed compile to implementation
* Fix: Minor bug fixes


Version 1.0.4 *(2018-06-23)*
----------------------------

Expand Down Expand Up @@ -48,7 +57,7 @@ Version 0.5.0 *(2017-01-21)*

* New: Export DB
* New: Method to get DB version
* Fix: Fix prouard issue and other minor issues
* Fix: Fix proguard issue and other minor issues


Version 0.4.0 *(2016-11-29)*
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ Add this to your app's build.gradle
debugImplementation 'com.amitshekhar.android:debug-db:1.0.5'
```

Using the Android Debug Database with encrypted database

```groovy
debugImplementation 'com.amitshekhar.android:debug-db-encrypt:1.0.5'
```

Use `debugImplementation` so that it will only compile in your debug build and not in your release build.

That’s all, just start the application, you will see in the logcat an entry like follows :
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.android.tools.build:gradle:3.3.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}
Expand Down
1 change: 1 addition & 0 deletions debug-db-base/debug-db-base-upload.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ task sourcesJar(type: Jar) {

task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
failOnError false
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
Expand Down
1 change: 1 addition & 0 deletions debug-db-encrypt/debug-db-encrypt-upload.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ task sourcesJar(type: Jar) {

task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
failOnError false
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
Expand Down
1 change: 1 addition & 0 deletions debug-db/debug-db-upload.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ task sourcesJar(type: Jar) {

task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
failOnError false
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
Expand Down
19 changes: 9 additions & 10 deletions sample-app-encrypt/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,33 @@ apply plugin: 'com.android.application'

android {
compileSdkVersion 28



defaultConfig {
applicationId "com.sample.encrypt"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
debug {
resValue("string", "PORT_NUMBER", "8080")
resValue("string", "DB_PASSWORD_PERSON", "a_password")
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

debugImplementation project(':debug-db-encrypt')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'net.zetetic:android-database-sqlcipher:3.5.9'
implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
Expand Down
136 changes: 135 additions & 1 deletion sample-app-encrypt/src/main/java/com/sample/encrypt/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,147 @@
/*
*
* * Copyright (C) 2019 Amit Shekhar
* * Copyright (C) 2011 Android Open Source Project
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/

package com.sample.encrypt;

import android.support.v7.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.sample.encrypt.database.CarDBHelper;
import com.sample.encrypt.database.ContactDBHelper;
import com.sample.encrypt.database.ExtTestDBHelper;
import com.sample.encrypt.database.PersonDBHelper;
import com.sample.encrypt.database.room.User;
import com.sample.encrypt.database.room.UserDBHelper;
import com.sample.encrypt.utils.Utils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MainActivity extends AppCompatActivity {

@SuppressLint("CommitPrefEdits")
@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Set<String> stringSet = new HashSet<>();
stringSet.add("SetOne");
stringSet.add("SetTwo");
stringSet.add("SetThree");

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

SharedPreferences prefsOne = getSharedPreferences("countPrefOne", Context.MODE_PRIVATE);
SharedPreferences prefsTwo = getSharedPreferences("countPrefTwo", Context.MODE_PRIVATE);

sharedPreferences.edit().putString("testOne", "one").commit();
sharedPreferences.edit().putInt("testTwo", 2).commit();
sharedPreferences.edit().putLong("testThree", 100000L).commit();
sharedPreferences.edit().putFloat("testFour", 3.01F).commit();
sharedPreferences.edit().putBoolean("testFive", true).commit();
sharedPreferences.edit().putStringSet("testSix", stringSet).commit();

prefsOne.edit().putString("testOneNew", "one").commit();

prefsTwo.edit().putString("testTwoNew", "two").commit();

ContactDBHelper contactDBHelper = new ContactDBHelper(getApplicationContext());
if (contactDBHelper.count() == 0) {
for (int i = 0; i < 100; i++) {
String name = "name_" + i;
String phone = "phone_" + i;
String email = "email_" + i;
String street = "street_" + i;
String place = "place_" + i;
contactDBHelper.insertContact(name, phone, email, street, place);
}
}

CarDBHelper carDBHelper = new CarDBHelper(getApplicationContext());
if (carDBHelper.count() == 0) {
for (int i = 0; i < 50; i++) {
String name = "name_" + i;
String color = "RED";
float mileage = i + 10.45f;
carDBHelper.insertCar(name, color, mileage);
}
}

ExtTestDBHelper extTestDBHelper = new ExtTestDBHelper(getApplicationContext());
if (extTestDBHelper.count() == 0) {
for (int i = 0; i < 20; i++) {
String value = "value_" + i;
extTestDBHelper.insertTest(value);
}
}

// Create Person encrypted database
PersonDBHelper personDBHelper = new PersonDBHelper(getApplicationContext());
if (personDBHelper.count() == 0) {
for (int i = 0; i < 100; i++) {
String firstName = PersonDBHelper.PERSON_COLUMN_FIRST_NAME + "_" + i;
String lastName = PersonDBHelper.PERSON_COLUMN_LAST_NAME + "_" + i;
String address = PersonDBHelper.PERSON_COLUMN_ADDRESS + "_" + i;
personDBHelper.insertPerson(firstName, lastName, address);
}
}

// Room database
UserDBHelper userDBHelper = new UserDBHelper(getApplicationContext());
if (userDBHelper.count() == 0) {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
User user = new User();
user.id = (long) (i + 1);
user.name = "user_" + i;
userList.add(user);
}
userDBHelper.insertUser(userList);
}

// Room inMemory database
if (userDBHelper.countInMemory() == 0) {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
User user = new User();
user.id = (long) (i + 1);
user.name = "in_memory_user_" + i;
userList.add(user);
}
userDBHelper.insertUserInMemory(userList);
}

Utils.setCustomDatabaseFiles(getApplicationContext());
Utils.setInMemoryRoomDatabases(userDBHelper.getInMemoryDatabase());
}

public void showDebugDbAddress(View view) {
Utils.showDebugDBAddressLogToast(getApplicationContext());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
*
* * Copyright (C) 2019 Amit Shekhar
* * Copyright (C) 2011 Android Open Source Project
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/

package com.sample.encrypt.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;

/**
* Created by amitshekhar on 06/02/17.
*/

public class CarDBHelper extends SQLiteOpenHelper {

public static final String DATABASE_NAME = "Car.db";
public static final String CARS_TABLE_NAME = "cars";
public static final String CARS_COLUMN_ID = "id";
public static final String CARS_COLUMN_NAME = "name";
public static final String CARS_COLUMN_COLOR = "color";
public static final String CCARS_COLUMN_MILEAGE = "mileage";

public CarDBHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(
"create table cars " +
"(id integer primary key, name text, color text, mileage real)"
);

db.execSQL("create table [transaction] (id integer primary key, name text)");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Correctness Issue

Using SQL Reserved Keyword as Table Name.

Using 'transaction' as a table name is problematic as it's a SQL reserved keyword, which could cause unexpected behavior or errors.

Current Code (Diff):

-         db.execSQL("create table [transaction] (id integer primary key, name text)");
+         db.execSQL("create table transactions (id integer primary key, name text)");
📝 Committable suggestion

‼️ IMPORTANT
Trust, but verify! 🕵️ Please review this suggestion with the care of a code archaeologist - check that it perfectly replaces the highlighted code, preserves all lines, maintains proper indentation, and won't break anything in production. Your future self will thank you! 🚀

Suggested change
db.execSQL("create table [transaction] (id integer primary key, name text)");
db.execSQL("create table transactions (id integer primary key, name text)");

🔄 Dependencies Affected

src/main/java/com/sample/encrypt/database/CarDBHelper.java

Function: CarDBHelper.onCreate

Issue: The insert statements also need to be updated to match the new table name

Suggestion: Update insert statements to use the new table name

Current Code (Diff):

-             db.execSQL("insert into [transaction] (name) values ('hello');");
+             db.execSQL("insert into transactions (name) values ('hello');");


for (int i = 0; i < 10; i++) {
db.execSQL("insert into [transaction] (name) values ('hello');");
}
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS cars");
onCreate(db);
}

public boolean insertCar(String name, String color, float mileage) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("color", color);
contentValues.put("mileage", mileage);
db.insert("cars", null, contentValues);
return true;
}

public Cursor getData(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from cars where id=" + id + "", null);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security Issue

SQL Injection Vulnerability.

Direct concatenation of user input into SQL query creates a critical security vulnerability allowing attackers to execute arbitrary SQL commands.

Current Code (Diff):

-         Cursor res = db.rawQuery("select * from cars where id=" + id + "", null);
+         Cursor res = db.rawQuery("select * from cars where id=?", new String[]{String.valueOf(id)});
📝 Committable suggestion

‼️ IMPORTANT
Trust, but verify! 🕵️ Please review this suggestion with the care of a code archaeologist - check that it perfectly replaces the highlighted code, preserves all lines, maintains proper indentation, and won't break anything in production. Your future self will thank you! 🚀

Suggested change
Cursor res = db.rawQuery("select * from cars where id=" + id + "", null);
Cursor res = db.rawQuery("select * from cars where id=?", new String[]{String.valueOf(id)});

return res;
}

public int numberOfRows() {
SQLiteDatabase db = this.getReadableDatabase();
int numRows = (int) DatabaseUtils.queryNumEntries(db, CARS_TABLE_NAME);
return numRows;
}

public boolean updateCar(Integer id, String name, String color, float mileage) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("color", color);
contentValues.put("mileage", mileage);
db.update("cars", contentValues, "id = ? ", new String[]{Integer.toString(id)});
return true;
}

public Integer deleteCar(Integer id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete("cars",
"id = ? ",
new String[]{Integer.toString(id)});
}

public ArrayList<String> getAllCars() {
ArrayList<String> arrayList = new ArrayList<>();

//hp = new HashMap();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from cars", null);
res.moveToFirst();

while (!res.isAfterLast()) {
arrayList.add(res.getString(res.getColumnIndex(CARS_COLUMN_NAME)));
res.moveToNext();
}
return arrayList;
Comment on lines +114 to +121
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Correctness Issue

Resource Leak - Unclosed Cursor.

The Cursor object in getAllCars() is never closed, which will cause memory leaks and potentially crash the application.

Current Code (Diff):

-         Cursor res = db.rawQuery("select * from cars", null);
-         res.moveToFirst();
-
-         while (!res.isAfterLast()) {
-             arrayList.add(res.getString(res.getColumnIndex(CARS_COLUMN_NAME)));
-             res.moveToNext();
-         }
-         return arrayList;
+         Cursor res = db.rawQuery("select * from cars", null);
+         res.moveToFirst();
+
+         while (!res.isAfterLast()) {
+             arrayList.add(res.getString(res.getColumnIndex(CARS_COLUMN_NAME)));
+             res.moveToNext();
+         }
+         res.close();
+         return arrayList;
📝 Committable suggestion

‼️ IMPORTANT
Trust, but verify! 🕵️ Please review this suggestion with the care of a code archaeologist - check that it perfectly replaces the highlighted code, preserves all lines, maintains proper indentation, and won't break anything in production. Your future self will thank you! 🚀

Suggested change
Cursor res = db.rawQuery("select * from cars", null);
res.moveToFirst();
while (!res.isAfterLast()) {
arrayList.add(res.getString(res.getColumnIndex(CARS_COLUMN_NAME)));
res.moveToNext();
}
return arrayList;
Cursor res = db.rawQuery("select * from cars", null);
res.moveToFirst();
while (!res.isAfterLast()) {
arrayList.add(res.getString(res.getColumnIndex(CARS_COLUMN_NAME)));
res.moveToNext();
}
res.close();
return arrayList;

}

public int count() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("select * from cars", null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
return cursor.getInt(0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Correctness Issue

Logic Error in count() Method.

The count() method incorrectly returns the first column value (id) instead of the actual count of rows, causing incorrect data to be returned.

Current Code (Diff):

-             return cursor.getInt(0);
+             return cursor.getCount();
📝 Committable suggestion

‼️ IMPORTANT
Trust, but verify! 🕵️ Please review this suggestion with the care of a code archaeologist - check that it perfectly replaces the highlighted code, preserves all lines, maintains proper indentation, and won't break anything in production. Your future self will thank you! 🚀

Suggested change
return cursor.getInt(0);
return cursor.getCount();

} else {
return 0;
}
Comment on lines +126 to +132
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Correctness Issue

Resource Leak - Unclosed Cursor.

The Cursor object in count() is never closed, which will cause memory leaks and potentially crash the application.

Current Code (Diff):

-         Cursor cursor = db.rawQuery("select * from cars", null);
-         if (cursor != null && cursor.getCount() > 0) {
-             cursor.moveToFirst();
-             return cursor.getInt(0);
-         } else {
-             return 0;
-         }
+         Cursor cursor = db.rawQuery("select * from cars", null);
+         try {
+             if (cursor != null && cursor.getCount() > 0) {
+                 cursor.moveToFirst();
+                 return cursor.getInt(0);
+             } else {
+                 return 0;
+             }
+         } finally {
+             if (cursor != null) cursor.close();
+         }
📝 Committable suggestion

‼️ IMPORTANT
Trust, but verify! 🕵️ Please review this suggestion with the care of a code archaeologist - check that it perfectly replaces the highlighted code, preserves all lines, maintains proper indentation, and won't break anything in production. Your future self will thank you! 🚀

Suggested change
Cursor cursor = db.rawQuery("select * from cars", null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
return cursor.getInt(0);
} else {
return 0;
}
Cursor cursor = db.rawQuery("select * from cars", null);
try {
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
return cursor.getInt(0);
} else {
return 0;
}
} finally {
if (cursor != null) cursor.close();
}

}
}
Loading