package org.bitseal.database;
import info.guardianproject.cacheword.CacheWordHandler;
import info.guardianproject.cacheword.ICacheWordSubscriber;
import info.guardianproject.cacheword.PassphraseSecrets;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.HashSet;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteQueryBuilder;
import android.annotation.SuppressLint;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
public class DatabaseContentProvider extends ContentProvider implements ICacheWordSubscriber
{
private static DatabaseHelper sDatabaseHelper;
private static Context sContext;
private static CacheWordHandler sCacheWordHandler;
private static SQLiteDatabase sDatabase;
/** The key for a boolean variable that records whether or not a user-defined database encryption passphrase has been saved */
private static final String KEY_DATABASE_PASSPHRASE_SAVED = "databasePassphraseSaved";
/** The default passphrase for the database. This is NOT intended to have any security value, but rather to make the
* code simpler by always having the database encrypted and therefore not forcing us to switch between encrypted and unencrypted
* databases. */
public static final String DEFAULT_DATABASE_PASSPHRASE = "myDefaultDatabasePassphrase";
// Used by the URI Matcher
private static final int ADDRESSES = 10;
private static final int ADDRESS_ID = 20;
private static final int ADDRESS_BOOK_RECORDS = 30;
private static final int ADDRESS_BOOK_RECORD_ID = 40;
private static final int MESSAGES = 50;
private static final int MESSAGE_ID = 60;
private static final int QUEUE_RECORDS = 70;
private static final int QUEUE_RECORD_ID = 80;
private static final int PAYLOADS = 90;
private static final int PAYLOAD_ID = 100;
private static final int PUBKEYS = 110;
private static final int PUBKEY_ID = 120;
private static final int SERVER_RECORDS = 130;
private static final int SERVER_RECORD_ID = 140;
private static final String AUTHORITY = "org.bitseal.database";
// The path strings for each table in the database
private static final String PATH_ADDRESSES = "addresses";
private static final String PATH_ADDRESS_BOOK_RECORDS = "address_book_records";
private static final String PATH_MESSAGES = "messages";
private static final String PATH_QUEUE_RECORDS = "queue_records";
private static final String PATH_PAYLOADS = "payloads";
private static final String PATH_PUBKEYS = "pubkeys";
private static final String PATH_SERVER_RECORDS = "server_records";
// The URIs for each table in the database
public static final Uri CONTENT_URI_ADDRESSES = Uri.parse("content://" + AUTHORITY + "/" + PATH_ADDRESSES);
public static final Uri CONTENT_URI_ADDRESS_BOOK_RECORDS = Uri.parse("content://" + AUTHORITY + "/" + PATH_ADDRESS_BOOK_RECORDS);
public static final Uri CONTENT_URI_MESSAGES = Uri.parse("content://" + AUTHORITY + "/" + PATH_MESSAGES);
public static final Uri CONTENT_URI_QUEUE_RECORDS = Uri.parse("content://" + AUTHORITY + "/" + PATH_QUEUE_RECORDS);
public static final Uri CONTENT_URI_PAYLOADS = Uri.parse("content://" + AUTHORITY + "/" + PATH_PAYLOADS);
public static final Uri CONTENT_URI_PUBKEYS = Uri.parse("content://" + AUTHORITY + "/" + PATH_PUBKEYS);
public static final Uri CONTENT_URI_SERVER_RECORDS = Uri.parse("content://" + AUTHORITY + "/" + PATH_SERVER_RECORDS);
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final String TAG = "DATABASE_CONTENT_PROVIDER";
static
{
sURIMatcher.addURI(AUTHORITY, PATH_ADDRESSES, ADDRESSES);
sURIMatcher.addURI(AUTHORITY, PATH_ADDRESSES + "/#", ADDRESS_ID);
sURIMatcher.addURI(AUTHORITY, PATH_ADDRESS_BOOK_RECORDS, ADDRESS_BOOK_RECORDS);
sURIMatcher.addURI(AUTHORITY, PATH_ADDRESS_BOOK_RECORDS + "/#", ADDRESS_BOOK_RECORD_ID);
sURIMatcher.addURI(AUTHORITY, PATH_MESSAGES, MESSAGES);
sURIMatcher.addURI(AUTHORITY, PATH_MESSAGES + "/#", MESSAGE_ID);
sURIMatcher.addURI(AUTHORITY, PATH_QUEUE_RECORDS, QUEUE_RECORDS);
sURIMatcher.addURI(AUTHORITY, PATH_QUEUE_RECORDS + "/#", QUEUE_RECORD_ID);
sURIMatcher.addURI(AUTHORITY, PATH_PAYLOADS, PAYLOADS);
sURIMatcher.addURI(AUTHORITY, PATH_PAYLOADS + "/#", PAYLOAD_ID);
sURIMatcher.addURI(AUTHORITY, PATH_PUBKEYS, PUBKEYS);
sURIMatcher.addURI(AUTHORITY, PATH_PUBKEYS + "/#", PUBKEY_ID);
sURIMatcher.addURI(AUTHORITY, PATH_SERVER_RECORDS, SERVER_RECORDS);
sURIMatcher.addURI(AUTHORITY, PATH_SERVER_RECORDS + "/#", SERVER_RECORD_ID);
}
@SuppressLint("InlinedApi")
@Override
public boolean onCreate()
{
Log.i(TAG, "Database content provider onCreate() called");
sContext = getContext();
sCacheWordHandler = new CacheWordHandler(sContext, this);
sCacheWordHandler.connectToService();
sDatabaseHelper = new DatabaseHelper(sContext, sCacheWordHandler);
return false;
}
/**
* Gets a writable SQLiteDatabase object
*
* @return The SQLiteDatabase object
*/
public static SQLiteDatabase openDatabase()
{
Log.i(TAG, "DatabaseContentProvider.openDatabase() called");
try
{
SQLiteDatabase.loadLibs(sContext);
sDatabase = sDatabaseHelper.getWritableDatabase();
}
catch (Exception e)
{
Log.e(TAG, "Exception occurred while running DatabaseContentProvider.openDatabase(). The exception message was:\n"
+ e.getMessage());
}
return sDatabase;
}
/**
* Changes the database passphrase
*
* @param newPassphrase - The new passphrase
*
* @return A boolean indicating whether or not the database passphrase was
* changed successfully
*/
public static boolean changeDatabasePassphrase(String newPassphrase)
{
Log.i(TAG, "DatabaseContentProvider.changeDatabasePassphrase() called");
try
{
// Get the old encryption key
String oldEncryptionKey = DatabaseHelper.encodeRawKeyToStr(sCacheWordHandler.getEncryptionKey());
// Set CacheWord to use the new passphrase
sCacheWordHandler.changePassphrase((PassphraseSecrets) sCacheWordHandler.getCachedSecrets(), newPassphrase.toCharArray());
// Get the new encryption key
String newEncryptionKey = DatabaseHelper.encodeRawKeyToStr(sCacheWordHandler.getEncryptionKey());
sDatabase.execSQL("PRAGMA key = \"" + oldEncryptionKey + "\";");
sDatabase.execSQL("PRAGMA rekey = \"" + newEncryptionKey + "\";");
openDatabase();
return true;
}
catch (Exception e)
{
Log.e(TAG, "Exception occurred while running DatabaseContentProvider.changeDatabasePassphrase(). The exception message was:\n" +
e.getMessage());
return false;
}
}
/**
* Closes the SQLiteDatabase object that we use to interact with the
* app's database. This method is intended to be used when the user locks
* the app.
*/
public static void closeDatabase()
{
Log.i(TAG, "DatabaseContentProvider.closeDatabase() called.");
if (sDatabase != null)
{
Log.d(TAG, "About to close database");
sDatabase.close();
sDatabase = null;
System.gc();
}
}
@Override
public String getType(Uri uri)
{
return null; // This method will not be called unless the application changes to specifically invoke it. Thus it can be safely left to return null.
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
// Using SQLiteQueryBuilder instead of query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
// Check if the caller has requested a column which does not exists
checkColumns(projection, uriType);
switch (uriType)
{
case ADDRESS_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(AddressesTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case ADDRESSES:
queryBuilder.setTables(AddressesTable.TABLE_ADDRESSES);
break;
case ADDRESS_BOOK_RECORD_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(AddressBookRecordsTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case ADDRESS_BOOK_RECORDS:
queryBuilder.setTables(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS);
break;
case MESSAGE_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(MessagesTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case MESSAGES:
queryBuilder.setTables(MessagesTable.TABLE_MESSAGES);
break;
case QUEUE_RECORD_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(QueueRecordsTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case QUEUE_RECORDS:
queryBuilder.setTables(QueueRecordsTable.TABLE_QUEUE_RECORDS);
break;
case PAYLOAD_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(PayloadsTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case PAYLOADS:
queryBuilder.setTables(PayloadsTable.TABLE_PAYLOADS);
break;
case PUBKEY_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(PubkeysTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case PUBKEYS:
queryBuilder.setTables(PubkeysTable.TABLE_PUBKEYS);
break;
case SERVER_RECORD_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(ServerRecordsTable.COLUMN_ID + "=" + uri.getLastPathSegment());
case SERVER_RECORDS:
queryBuilder.setTables(ServerRecordsTable.TABLE_SERVER_RECORDS);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri + " Exception occurred in DatabaseContentProvider.query()");
}
Cursor cursor = queryBuilder.query(sDatabase, projection, selection, selectionArgs, null, null, sortOrder);
// make sure that potential listeners are getting notified
cursor.setNotificationUri(sContext.getContentResolver(), uri);
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues values)
{
int uriType = sURIMatcher.match(uri);
long id = 0;
String path;
switch (uriType)
{
case ADDRESSES:
id = sDatabase.insert(AddressesTable.TABLE_ADDRESSES, null, values);
path = PATH_ADDRESSES;
break;
case ADDRESS_BOOK_RECORDS:
id = sDatabase.insert(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, null, values);
path = PATH_ADDRESS_BOOK_RECORDS;
break;
case MESSAGES:
id = sDatabase.insert(MessagesTable.TABLE_MESSAGES, null, values);
path = PATH_MESSAGES;
break;
case QUEUE_RECORDS:
id = sDatabase.insert(QueueRecordsTable.TABLE_QUEUE_RECORDS, null, values);
path = PATH_QUEUE_RECORDS;
break;
case PAYLOADS:
id = sDatabase.insert(PayloadsTable.TABLE_PAYLOADS, null, values);
path = PATH_PAYLOADS;
break;
case PUBKEYS:
id = sDatabase.insert(PubkeysTable.TABLE_PUBKEYS, null, values);
path = PATH_PUBKEYS;
break;
case SERVER_RECORDS:
id = sDatabase.insert(ServerRecordsTable.TABLE_SERVER_RECORDS, null, values);
path = PATH_SERVER_RECORDS;
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri + " Exception occurred in DatabaseContentProvider.insert()");
}
sContext.getContentResolver().notifyChange(uri, null);
return Uri.parse(path + "/" + id);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{
int uriType = sURIMatcher.match(uri);
int rowsDeleted = 0;
String id;
switch (uriType)
{
case ADDRESSES:
rowsDeleted = sDatabase.delete(AddressesTable.TABLE_ADDRESSES, selection, selectionArgs);
break;
case ADDRESS_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(AddressesTable.TABLE_ADDRESSES, AddressesTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(AddressesTable.TABLE_ADDRESSES, AddressesTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case ADDRESS_BOOK_RECORDS:
rowsDeleted = sDatabase.delete(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, selection, selectionArgs);
break;
case ADDRESS_BOOK_RECORD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, AddressBookRecordsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, AddressBookRecordsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case MESSAGES:
rowsDeleted = sDatabase.delete(MessagesTable.TABLE_MESSAGES, selection, selectionArgs);
break;
case MESSAGE_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(MessagesTable.TABLE_MESSAGES, MessagesTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(MessagesTable.TABLE_MESSAGES, MessagesTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case QUEUE_RECORDS:
rowsDeleted = sDatabase.delete(QueueRecordsTable.TABLE_QUEUE_RECORDS, selection, selectionArgs);
break;
case QUEUE_RECORD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(QueueRecordsTable.TABLE_QUEUE_RECORDS, QueueRecordsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(QueueRecordsTable.TABLE_QUEUE_RECORDS, QueueRecordsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case PAYLOADS:
rowsDeleted = sDatabase.delete(PayloadsTable.TABLE_PAYLOADS, selection, selectionArgs);
break;
case PAYLOAD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(PayloadsTable.TABLE_PAYLOADS, PayloadsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(PayloadsTable.TABLE_PAYLOADS, PayloadsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case PUBKEYS:
rowsDeleted = sDatabase.delete(PubkeysTable.TABLE_PUBKEYS, selection, selectionArgs);
break;
case PUBKEY_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(PubkeysTable.TABLE_PUBKEYS, PubkeysTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(PubkeysTable.TABLE_PUBKEYS, PubkeysTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case SERVER_RECORDS:
rowsDeleted = sDatabase.delete(ServerRecordsTable.TABLE_SERVER_RECORDS, selection, selectionArgs);
break;
case SERVER_RECORD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsDeleted = sDatabase.delete(ServerRecordsTable.TABLE_SERVER_RECORDS, ServerRecordsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsDeleted = sDatabase.delete(ServerRecordsTable.TABLE_SERVER_RECORDS, ServerRecordsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri + " Exception occurred in DatabaseContentProvider.delete()");
}
sContext.getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
{
int uriType = sURIMatcher.match(uri);
int rowsUpdated = 0;
String id;
switch (uriType)
{
case ADDRESSES:
rowsUpdated = sDatabase.update(AddressesTable.TABLE_ADDRESSES, values, selection, selectionArgs);
break;
case ADDRESS_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(AddressesTable.TABLE_ADDRESSES, values, AddressesTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(AddressesTable.TABLE_ADDRESSES, values, AddressesTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case ADDRESS_BOOK_RECORDS:
rowsUpdated = sDatabase.update(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, values, selection, selectionArgs);
break;
case ADDRESS_BOOK_RECORD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, values, AddressBookRecordsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(AddressBookRecordsTable.TABLE_ADDRESS_BOOK_RECORDS, values, AddressBookRecordsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case MESSAGES:
rowsUpdated = sDatabase.update(MessagesTable.TABLE_MESSAGES, values, selection, selectionArgs);
break;
case MESSAGE_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(MessagesTable.TABLE_MESSAGES, values, MessagesTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(MessagesTable.TABLE_MESSAGES, values, MessagesTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case QUEUE_RECORDS:
rowsUpdated = sDatabase.update(QueueRecordsTable.TABLE_QUEUE_RECORDS, values, selection, selectionArgs);
break;
case QUEUE_RECORD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(QueueRecordsTable.TABLE_QUEUE_RECORDS, values, QueueRecordsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(QueueRecordsTable.TABLE_QUEUE_RECORDS, values, QueueRecordsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case PAYLOADS:
rowsUpdated = sDatabase.update(PayloadsTable.TABLE_PAYLOADS, values, selection, selectionArgs);
break;
case PAYLOAD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(PayloadsTable.TABLE_PAYLOADS, values, PayloadsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(PayloadsTable.TABLE_PAYLOADS, values, PayloadsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case PUBKEYS:
rowsUpdated = sDatabase.update(PubkeysTable.TABLE_PUBKEYS, values, selection, selectionArgs);
break;
case PUBKEY_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(PubkeysTable.TABLE_PUBKEYS, values, PubkeysTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(PubkeysTable.TABLE_PUBKEYS, values, PubkeysTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
case SERVER_RECORDS:
rowsUpdated = sDatabase.update(ServerRecordsTable.TABLE_SERVER_RECORDS, values, selection, selectionArgs);
break;
case SERVER_RECORD_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection))
{
rowsUpdated = sDatabase.update(ServerRecordsTable.TABLE_SERVER_RECORDS, values, ServerRecordsTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sDatabase.update(ServerRecordsTable.TABLE_SERVER_RECORDS, values, ServerRecordsTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri + " Exception occurred in DatabaseContentProvider.update()");
}
sContext.getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
private void checkColumns(String[] projection, int uriType)
{
String[] available = getAvailable(uriType);
if (projection != null)
{
HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
// check if all columns which are requested are available
if (!availableColumns.containsAll(requestedColumns))
{
throw new IllegalArgumentException("Unknown columns in projection. Exception occurred in DatabaseContentProvider.checkColumns()");
}
}
}
private String[] getAvailable(int uriType)
{
if (uriType == ADDRESSES || uriType == ADDRESS_ID)
{
String[] available = {AddressesTable.COLUMN_ID, AddressesTable.COLUMN_CORRESPONDING_PUBKEY_ID, AddressesTable.COLUMN_LABEL,
AddressesTable.COLUMN_ADDRESS, AddressesTable.COLUMN_PRIVATE_SIGNING_KEY, AddressesTable.COLUMN_PRIVATE_ENCRYPTION_KEY,
AddressesTable.COLUMN_RIPE_HASH, AddressesTable.COLUMN_TAG};
return available;
}
else if (uriType == ADDRESS_BOOK_RECORDS || uriType == ADDRESS_BOOK_RECORD_ID)
{
String[] available = {AddressBookRecordsTable.COLUMN_ID, AddressBookRecordsTable.COLUMN_COLOUR_R, AddressBookRecordsTable.COLUMN_COLOUR_G,
AddressBookRecordsTable.COLUMN_COLOUR_B, AddressBookRecordsTable.COLUMN_LABEL, AddressBookRecordsTable.COLUMN_ADDRESS};
return available;
}
else if (uriType == MESSAGES || uriType == MESSAGE_ID)
{
String[] available = {MessagesTable.COLUMN_ID, MessagesTable.COLUMN_MSG_PAYLOAD_ID, MessagesTable.COLUMN_ACK_PAYLOAD_ID, MessagesTable.COLUMN_BELONGS_TO_ME,
MessagesTable.COLUMN_READ, MessagesTable.COLUMN_STATUS, MessagesTable.COLUMN_TIME, MessagesTable.COLUMN_TO_ADDRESS,
MessagesTable.COLUMN_FROM_ADDRESS, MessagesTable.COLUMN_SUBJECT, MessagesTable.COLUMN_BODY};
return available;
}
else if (uriType == QUEUE_RECORDS || uriType == QUEUE_RECORD_ID)
{
String[] available = {QueueRecordsTable.COLUMN_ID, QueueRecordsTable.COLUMN_TASK, QueueRecordsTable.COLUMN_TRIGGER_TIME,
QueueRecordsTable.COLUMN_RECORD_COUNT, QueueRecordsTable.COLUMN_LAST_ATTEMPT_TIME, QueueRecordsTable.COLUMN_ATTEMPTS,
QueueRecordsTable.COLUMN_OBJECT_0_ID, QueueRecordsTable.COLUMN_OBJECT_0_TYPE, QueueRecordsTable.COLUMN_OBJECT_1_ID,
QueueRecordsTable.COLUMN_OBJECT_1_TYPE, QueueRecordsTable.COLUMN_OBJECT_2_ID, QueueRecordsTable.COLUMN_OBJECT_2_TYPE};
return available;
}
else if (uriType == PAYLOADS || uriType == PAYLOAD_ID)
{
String[] available = {PayloadsTable.COLUMN_ID, PayloadsTable.COLUMN_RELATED_ADDRESS_ID, PayloadsTable.COLUMN_BELONGS_TO_ME,
PayloadsTable.COLUMN_PROCESSING_COMPLETE, PayloadsTable.COLUMN_TIME, PayloadsTable.COLUMN_TYPE, PayloadsTable.COLUMN_ACK,
PayloadsTable.COLUMN_POW_DONE, PayloadsTable.COLUMN_PAYLOAD};
return available;
}
else if (uriType == PUBKEYS || uriType == PUBKEY_ID)
{
String[] available = {PubkeysTable.COLUMN_ID, PubkeysTable.COLUMN_BELONGS_TO_ME, PubkeysTable.COLUMN_POW_NONCE, PubkeysTable.COLUMN_EXPIRATION_TIME,
PubkeysTable.COLUMN_OBJECT_TYPE, PubkeysTable.COLUMN_OBJECT_VERSION, PubkeysTable.COLUMN_STREAM_NUMBER, PubkeysTable.COLUMN_CORRESPONDING_ADDRESS_ID,
PubkeysTable.COLUMN_RIPE_HASH, PubkeysTable.COLUMN_BEHAVIOUR_BITFIELD, PubkeysTable.COLUMN_PUBLIC_SIGNING_KEY, PubkeysTable.COLUMN_PUBLIC_ENCRYPTION_KEY,
PubkeysTable.COLUMN_NONCE_TRIALS_PER_BYTE, PubkeysTable.COLUMN_EXTRA_BYTES, PubkeysTable.COLUMN_SIGNATURE_LENGTH, PubkeysTable.COLUMN_SIGNATURE};
return available;
}
else if (uriType == SERVER_RECORDS || uriType == SERVER_RECORD_ID)
{
String[] available = {ServerRecordsTable.COLUMN_ID, ServerRecordsTable.COLUMN_URL, ServerRecordsTable.COLUMN_USERNAME, ServerRecordsTable.COLUMN_PASSWORD};
return available;
}
else
{
throw new IllegalArgumentException("Unknown URI Type: " + uriType + " Exception occurred in DatabaseContentProvider.getAvailable()");
}
}
/**
* If the database encryption passphrase is currently set to its default value,
* this method retrieves the corresponding encryption key and stores it using
* CacheWord.
*/
public static void attemptGetDefaultEncryptionKey()
{
// Check whether the user has set a database encryption passphrase
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(sContext);
if (prefs.getBoolean(KEY_DATABASE_PASSPHRASE_SAVED, false) == false)
{
try
{
sCacheWordHandler.setPassphrase(DEFAULT_DATABASE_PASSPHRASE.toCharArray());
}
catch (GeneralSecurityException e)
{
Log.e(TAG, "GeneralSecurityException occurred in DatabaseContentProvider.onCreate(). The exception message was:\n"
+ e.getMessage());
}
}
}
@SuppressLint("InlinedApi")
@Override
public void onCacheWordLocked()
{
Log.d(TAG, "DatabaseContenProvider.onCacheWordLocked() called.");
attemptGetDefaultEncryptionKey();
}
@Override
public void onCacheWordOpened()
{
Log.d(TAG, "DatabaseContenProvider.onCacheWordOpened() called.");
openDatabase();
}
@Override
public void onCacheWordUninitialized()
{
Log.d(TAG, "DatabaseContenProvider.onCacheWordUninitialized() called.");
// Nothing to do here
}
}