aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider
diff options
context:
space:
mode:
authorAdithya Abraham Philip <adithyaphilip@gmail.com>2015-07-27 14:10:26 +0530
committerAdithya Abraham Philip <adithyaphilip@gmail.com>2015-08-20 21:02:29 +0530
commit1ef6f883e34a08dc916ad7dfabd7f892964aff54 (patch)
tree93abe6f44f6266f8c57e9b1cb1311d7e1af0068a /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider
parente643e098e2ad1a762e40f4ecbe6f97f729b11e3c (diff)
downloadopen-keychain-1ef6f883e34a08dc916ad7dfabd7f892964aff54.tar.gz
open-keychain-1ef6f883e34a08dc916ad7dfabd7f892964aff54.tar.bz2
open-keychain-1ef6f883e34a08dc916ad7dfabd7f892964aff54.zip
introduced keyserver sync adapter
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java37
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java71
4 files changed, 141 insertions, 2 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index 0d9a4ac16..73a687efe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -51,6 +51,11 @@ public class KeychainContract {
String EXPIRY = "expiry";
}
+ interface UpdatedKeysColumns {
+ String MASTER_KEY_ID = "master_key_id"; // not a database id
+ String LAST_UPDATED = "last_updated"; // time since epoch in seconds
+ }
+
interface UserPacketsColumns {
String MASTER_KEY_ID = "master_key_id"; // foreign key to key_rings._ID
String TYPE = "type"; // not a database id
@@ -97,6 +102,8 @@ public class KeychainContract {
public static final String BASE_KEY_RINGS = "key_rings";
+ public static final String BASE_UPDATED_KEYS = "updated_keys";
+
public static final String PATH_UNIFIED = "unified";
public static final String PATH_FIND = "find";
@@ -234,6 +241,16 @@ public class KeychainContract {
}
+ public static class UpdatedKeys implements UpdatedKeysColumns, BaseColumns {
+ public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+ .appendPath(BASE_UPDATED_KEYS).build();
+
+ public static final String CONTENT_TYPE
+ = "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.updated_keys";
+ public static final String CONTENT_ITEM_TYPE
+ = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.updated_keys";
+ }
+
public static class UserPackets implements UserPacketsColumns, BaseColumns {
public static final String VERIFIED = "verified";
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 4d16d44c5..d7fb738fc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -34,6 +34,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns;
import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity;
import org.sufficientlysecure.keychain.util.Log;
@@ -53,7 +54,7 @@ import java.io.IOException;
*/
public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "openkeychain.db";
- private static final int DATABASE_VERSION = 11;
+ private static final int DATABASE_VERSION = 12;
static Boolean apgHack = false;
private Context mContext;
@@ -61,6 +62,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
String KEY_RINGS_PUBLIC = "keyrings_public";
String KEY_RINGS_SECRET = "keyrings_secret";
String KEYS = "keys";
+ String UPDATED_KEYS = "updated_keys";
String USER_PACKETS = "user_packets";
String CERTS = "certs";
String API_APPS = "api_apps";
@@ -144,6 +146,14 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ Tables.USER_PACKETS + "(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + ") ON DELETE CASCADE"
+ ")";
+ private static final String CREATE_UPDATE_KEYS =
+ "CREATE TABLE IF NOT EXISTS " + Tables.UPDATED_KEYS + " ("
+ + UpdatedKeysColumns.MASTER_KEY_ID + " INTEGER PRIMARY KEY, "
+ + UpdatedKeysColumns.LAST_UPDATED + " INTEGER, "
+ + "FOREIGN KEY(" + UpdatedKeysColumns.MASTER_KEY_ID + ") REFERENCES "
+ + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE"
+ + ")";
+
private static final String CREATE_API_APPS =
"CREATE TABLE IF NOT EXISTS " + Tables.API_APPS + " ("
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -206,6 +216,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
db.execSQL(CREATE_KEYS);
db.execSQL(CREATE_USER_PACKETS);
db.execSQL(CREATE_CERTS);
+ db.execSQL(CREATE_UPDATE_KEYS);
db.execSQL(CREATE_API_APPS);
db.execSQL(CREATE_API_APPS_ACCOUNTS);
db.execSQL(CREATE_API_APPS_ALLOWED_KEYS);
@@ -278,8 +289,11 @@ public class KeychainDatabase extends SQLiteOpenHelper {
// fix problems in database, see #1402 for details
// https://github.com/open-keychain/open-keychain/issues/1402
db.execSQL("DELETE FROM api_accounts WHERE key_id BETWEEN 0 AND 3");
+ case 12:
+ db.execSQL(CREATE_UPDATE_KEYS);
if (oldVersion == 10) {
- // no consolidate if we are updating from 10, we're just here for the api_accounts fix
+ // no consolidate if we are updating from 10, we're just here for
+ // the api_accounts fix and the new update keys table
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index 3ed9b1da9..178199805 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
@@ -72,6 +73,9 @@ public class KeychainProvider extends ContentProvider {
private static final int KEY_RINGS_FIND_BY_EMAIL = 400;
private static final int KEY_RINGS_FIND_BY_SUBKEY = 401;
+ private static final int UPDATED_KEYS = 500;
+ private static final int UPDATED_KEYS_SPECIFIC = 501;
+
protected UriMatcher mUriMatcher;
/**
@@ -179,6 +183,12 @@ public class KeychainProvider extends ContentProvider {
matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ KeychainContract.PATH_ALLOWED_KEYS, API_ALLOWED_KEYS);
+ /**
+ * to access table containing last updated dates of keys
+ */
+ matcher.addURI(authority, KeychainContract.BASE_UPDATED_KEYS, UPDATED_KEYS);
+ matcher.addURI(authority, KeychainContract.BASE_UPDATED_KEYS + "/*", UPDATED_KEYS_SPECIFIC);
+
return matcher;
}
@@ -218,6 +228,11 @@ public class KeychainProvider extends ContentProvider {
case KEY_RING_SECRET:
return KeyRings.CONTENT_ITEM_TYPE;
+ case UPDATED_KEYS:
+ return UpdatedKeys.CONTENT_TYPE;
+ case UPDATED_KEYS_SPECIFIC:
+ return UpdatedKeys.CONTENT_ITEM_TYPE;
+
case API_APPS:
return ApiApps.CONTENT_TYPE;
@@ -606,6 +621,22 @@ public class KeychainProvider extends ContentProvider {
break;
}
+ case UPDATED_KEYS:
+ case UPDATED_KEYS_SPECIFIC: {
+ HashMap<String, String> projectionMap = new HashMap<>();
+ qb.setTables(Tables.UPDATED_KEYS);
+ projectionMap.put(UpdatedKeys.MASTER_KEY_ID, Tables.UPDATED_KEYS + "."
+ + UpdatedKeys.MASTER_KEY_ID);
+ projectionMap.put(UpdatedKeys.LAST_UPDATED, Tables.UPDATED_KEYS + "."
+ + UpdatedKeys.LAST_UPDATED);
+ qb.setProjectionMap(projectionMap);
+ if (match == UPDATED_KEYS_SPECIFIC) {
+ qb.appendWhere(UpdatedKeys.MASTER_KEY_ID + " = ");
+ qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+ }
+ break;
+ }
+
case API_APPS: {
qb.setTables(Tables.API_APPS);
@@ -726,6 +757,12 @@ public class KeychainProvider extends ContentProvider {
keyId = values.getAsLong(Certs.MASTER_KEY_ID);
break;
}
+ case UPDATED_KEYS: {
+ long updatedKeyId = db.replace(Tables.UPDATED_KEYS, null, values);
+ rowUri = UpdatedKeys.CONTENT_URI.buildUpon().appendPath("" + updatedKeyId)
+ .build();
+ break;
+ }
case API_APPS: {
db.insertOrThrow(Tables.API_APPS, null, values);
break;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 0c37bfc2a..e8eea6831 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -59,6 +59,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
@@ -82,6 +83,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
/**
* This class contains high level methods for database access. Despite its
@@ -685,6 +687,41 @@ public class ProviderHelper {
mIndent -= 1;
}
+ // before deleting key, retrieve it's last updated time
+ final int INDEX_MASTER_KEY_ID = 0;
+ final int INDEX_LAST_UPDATED = 1;
+ Cursor lastUpdatedCursor = mContentResolver.query(
+ UpdatedKeys.CONTENT_URI,
+ new String[]{
+ UpdatedKeys.MASTER_KEY_ID,
+ UpdatedKeys.LAST_UPDATED
+ },
+ UpdatedKeys.MASTER_KEY_ID + " = ?",
+ new String[]{"" + masterKeyId},
+ null
+ );
+ ContentValues lastUpdatedEntry = null;
+ if (lastUpdatedCursor.moveToNext()) {
+ lastUpdatedEntry = new ContentValues(2);
+ lastUpdatedEntry.put(UpdatedKeys.MASTER_KEY_ID,
+ lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID));
+ lastUpdatedEntry.put(UpdatedKeys.LAST_UPDATED,
+ lastUpdatedCursor.getLong(INDEX_LAST_UPDATED));
+ Log.e("PHILIP", "cv: " + lastUpdatedEntry + " actual: " + masterKeyId);
+ }
+ lastUpdatedCursor.close();
+
+ if (lastUpdatedEntry != null) {
+ // there was an entry to re-insert
+ // this operation must happen after the new key is inserted
+ operations.add(
+ ContentProviderOperation
+ .newInsert(UpdatedKeys.CONTENT_URI)
+ .withValues(lastUpdatedEntry)
+ .build()
+ );
+ }
+
try {
// delete old version of this keyRing, which also deletes all keys and userIds on cascade
int deleted = mContentResolver.delete(
@@ -1239,6 +1276,28 @@ public class ProviderHelper {
}
// 2. wipe database (IT'S DANGEROUS)
+
+ // first, backup our list of updated key times
+ ArrayList<ContentValues> updatedKeysValues = new ArrayList<>();
+ final int INDEX_MASTER_KEY_ID = 0;
+ final int INDEX_LAST_UPDATED = 1;
+ Cursor lastUpdatedCursor = mContentResolver.query(
+ UpdatedKeys.CONTENT_URI,
+ new String[]{
+ UpdatedKeys.MASTER_KEY_ID,
+ UpdatedKeys.LAST_UPDATED
+ },
+ null, null, null);
+ while (lastUpdatedCursor.moveToNext()) {
+ ContentValues values = new ContentValues();
+ values.put(UpdatedKeys.MASTER_KEY_ID,
+ lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID));
+ values.put(UpdatedKeys.LAST_UPDATED,
+ lastUpdatedCursor.getLong(INDEX_LAST_UPDATED));
+ updatedKeysValues.add(values);
+ }
+ lastUpdatedCursor.close();
+
log.add(LogType.MSG_CON_DB_CLEAR, indent);
mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null);
@@ -1288,6 +1347,10 @@ public class ProviderHelper {
new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport))
.serialKeyRingImport(itPublics, numPublics, null, null);
log.add(result, indent);
+ // re-insert our backed up list of updated key times
+ // TODO: can this cause issues in case a public key re-import failed?
+ mContentResolver.bulkInsert(UpdatedKeys.CONTENT_URI,
+ updatedKeysValues.toArray(new ContentValues[updatedKeysValues.size()]));
} else {
log.add(LogType.MSG_CON_REIMPORT_PUBLIC_SKIP, indent);
}
@@ -1397,6 +1460,14 @@ public class ProviderHelper {
return getKeyRingAsArmoredString(data);
}
+ public Uri renewKeyLastUpdatedTime(long masterKeyId, long time, TimeUnit timeUnit) {
+ ContentValues values = new ContentValues();
+ values.put(UpdatedKeys.MASTER_KEY_ID, masterKeyId);
+ values.put(UpdatedKeys.LAST_UPDATED, timeUnit.toSeconds(time));
+
+ return mContentResolver.insert(UpdatedKeys.CONTENT_URI, values);
+ }
+
public ArrayList<String> getRegisteredApiApps() {
Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null);