aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main/java/org
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2014-04-04 01:07:09 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2014-04-04 01:56:02 +0200
commitd921cca91312e5888f98b178252efa2f5db103cf (patch)
tree2df5180644b302bd5360f8963a73237d6ae12a14 /OpenPGP-Keychain/src/main/java/org
parent59f4b4e3e7cc27981e66f140030bef9a3fce3d25 (diff)
downloadopen-keychain-d921cca91312e5888f98b178252efa2f5db103cf.tar.gz
open-keychain-d921cca91312e5888f98b178252efa2f5db103cf.tar.bz2
open-keychain-d921cca91312e5888f98b178252efa2f5db103cf.zip
db-overhaul: reintroduce by-mail and by-subkey queries
the only thing left to fix after the db upgrade (that I can think of right now) are key exports
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org')
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java19
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java117
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java16
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java13
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java22
5 files changed, 109 insertions, 78 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index e6e106ba6..9eeb57222 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -83,10 +83,9 @@ public class KeychainContract {
public static final String PATH_UNIFIED = "unified";
- public static final String PATH_BY_MASTER_KEY_ID = "master_key_id";
- public static final String PATH_BY_KEY_ID = "key_id";
- public static final String PATH_BY_EMAILS = "emails";
- public static final String PATH_BY_LIKE_EMAIL = "like_email";
+ public static final String PATH_FIND = "find";
+ public static final String PATH_BY_EMAIL = "email";
+ public static final String PATH_BY_SUBKEY = "subkey";
public static final String PATH_PUBLIC = "public";
public static final String PATH_SECRET = "secret";
@@ -109,20 +108,24 @@ public class KeychainContract {
public static Uri buildUnifiedKeyRingsUri() {
return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build();
}
- public static Uri buildUnifiedKeyRingsByEmailUri(String email) {
- return CONTENT_URI.buildUpon().appendPath("email:" + email).build();
- }
public static Uri buildGenericKeyRingUri(String masterKeyId) {
return CONTENT_URI.buildUpon().appendPath(masterKeyId).build();
}
-
public static Uri buildUnifiedKeyRingUri(String masterKeyId) {
return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_UNIFIED).build();
}
public static Uri buildUnifiedKeyRingUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_UNIFIED).build();
}
+
+ public static Uri buildUnifiedKeyRingsFindByEmailUri(String email) {
+ return CONTENT_URI.buildUpon().appendPath(PATH_FIND).appendPath(PATH_BY_EMAIL).appendPath(email).build();
+ }
+ public static Uri buildUnifiedKeyRingsFindBySubkeyUri(String subkey) {
+ return CONTENT_URI.buildUpon().appendPath(PATH_FIND).appendPath(PATH_BY_SUBKEY).appendPath(subkey).build();
+ }
+
}
public static class KeyRingData implements KeyRingsColumns, BaseColumns {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index 8b1ee4886..a14b5b3de 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -57,7 +57,10 @@ public class KeychainProvider extends ContentProvider {
private static final int API_ACCOUNTS = 304;
private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 306;
- // private static final int DATA_STREAM = 401;
+ private static final int KEY_RINGS_FIND_BY_EMAIL = 400;
+ private static final int KEY_RINGS_FIND_BY_SUBKEY = 401;
+
+ // private static final int DATA_STREAM = 501;
protected UriMatcher mUriMatcher;
@@ -86,6 +89,20 @@ public class KeychainProvider extends ContentProvider {
KEY_RINGS_PUBLIC);
/**
+ * find by criteria other than master key id
+ *
+ * key_rings/find/email/_
+ * key_rings/find/subkey/_
+ *
+ */
+ matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ + KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_EMAIL + "/*",
+ KEY_RINGS_FIND_BY_EMAIL);
+ matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ + KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_SUBKEY + "/*",
+ KEY_RINGS_FIND_BY_SUBKEY);
+
+ /**
* list key_ring specifics
*
* <pre>
@@ -200,7 +217,6 @@ public class KeychainProvider extends ContentProvider {
Log.v(Constants.TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")");
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
- SQLiteDatabase db = mKeychainDatabase.getReadableDatabase();
int match = mUriMatcher.match(uri);
@@ -209,7 +225,9 @@ public class KeychainProvider extends ContentProvider {
switch (match) {
case KEY_RING_UNIFIED:
- case KEY_RINGS_UNIFIED: {
+ case KEY_RINGS_UNIFIED:
+ case KEY_RINGS_FIND_BY_EMAIL:
+ case KEY_RINGS_FIND_BY_SUBKEY: {
HashMap<String, String> projectionMap = new HashMap<String, String>();
projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id");
projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
@@ -242,13 +260,64 @@ public class KeychainProvider extends ContentProvider {
);
qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0");
- if(match == KEY_RING_UNIFIED) {
- qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = ");
- qb.appendWhereEscapeString(uri.getPathSegments().get(1));
- } else if (TextUtils.isEmpty(sortOrder)) {
+ switch(match) {
+ case KEY_RING_UNIFIED: {
+ qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = ");
+ qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+ break;
+ }
+ case KEY_RINGS_FIND_BY_SUBKEY: {
+ try {
+ String subkey = Long.valueOf(uri.getLastPathSegment()).toString();
+ qb.appendWhere(" AND EXISTS ("
+ + " SELECT 1 FROM " + Tables.KEYS + " AS tmp"
+ + " WHERE tmp." + UserIds.MASTER_KEY_ID
+ + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
+ + " AND tmp." + Keys.KEY_ID + " = " + subkey + ""
+ + ")");
+ } catch(NumberFormatException e) {
+ Log.e(Constants.TAG, "Malformed find by subkey query!", e);
+ qb.appendWhere(" AND 0");
+ }
+ break;
+ }
+ case KEY_RINGS_FIND_BY_EMAIL: {
+ String chunks[] = uri.getLastPathSegment().split(" *, *");
+ boolean gotCondition = false;
+ String emailWhere = "";
+ // JAVA ♥
+ for (int i = 0; i < chunks.length; ++i) {
+ if (chunks[i].length() == 0) {
+ continue;
+ }
+ if (i != 0) {
+ emailWhere += " OR ";
+ }
+ emailWhere += "tmp." + UserIds.USER_ID + " LIKE ";
+ // match '*<email>', so it has to be at the *end* of the user id
+ emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">");
+ gotCondition = true;
+ }
+ if(gotCondition) {
+ qb.appendWhere(" AND EXISTS ("
+ + " SELECT 1 FROM " + Tables.USER_IDS + " AS tmp"
+ + " WHERE tmp." + UserIds.MASTER_KEY_ID
+ + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
+ + " AND (" + emailWhere + ")"
+ + ")");
+ } else {
+ // TODO better way to do this?
+ Log.e(Constants.TAG, "Malformed find by email query!");
+ qb.appendWhere(" AND 0");
+ }
+ break;
+ }
+ }
+
+ if (TextUtils.isEmpty(sortOrder)) {
sortOrder =
- Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL DESC"
- + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC";
+ Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL ASC, "
+ + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC";
}
// uri to watch is all /key_rings/
@@ -256,33 +325,6 @@ public class KeychainProvider extends ContentProvider {
break;
}
- /*case SECRET_KEY_RING_BY_EMAILS:
- case PUBLIC_KEY_RING_BY_EMAILS:
- qb = buildKeyRingQuery(qb, match);
-
- String emails = uri.getLastPathSegment();
- String chunks[] = emails.split(" *, *");
- boolean gotCondition = false;
- String emailWhere = "";
- for (int i = 0; i < chunks.length; ++i) {
- if (chunks[i].length() == 0) {
- continue;
- }
- if (i != 0) {
- emailWhere += " OR ";
- }
- emailWhere += "tmp." + UserIds.USER_ID + " LIKE ";
- // match '*<email>', so it has to be at the *end* of the user id
- emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">");
- gotCondition = true;
- }
-
- if (gotCondition) {
- qb.appendWhere(" AND EXISTS (SELECT tmp." + Base._ID + " FROM "
- + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIds.KEY_RING_ROW_ID
- + " = " + Tables.KEY_RINGS + "." + Base._ID + " AND (" + emailWhere
- + "))");
- }*/
case KEY_RING_KEYS: {
HashMap<String, String> projectionMap = new HashMap<String, String>();
@@ -387,7 +429,7 @@ public class KeychainProvider extends ContentProvider {
break;
default:
- throw new IllegalArgumentException("Unknown URI " + uri);
+ throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")");
}
@@ -399,6 +441,7 @@ public class KeychainProvider extends ContentProvider {
orderBy = sortOrder;
}
+ SQLiteDatabase db = mKeychainDatabase.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, having, orderBy);
// Tell the cursor what uri to watch, so it knows when its source data changes
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index ccae6b2f2..c640bdb7c 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -61,15 +61,15 @@ public class OpenPgpService extends RemoteService {
ArrayList<Long> keyIds = new ArrayList<Long>();
boolean missingUserIdsCheck = false;
- boolean dublicateUserIdsCheck = false;
+ boolean duplicateUserIdsCheck = false;
ArrayList<String> missingUserIds = new ArrayList<String>();
- ArrayList<String> dublicateUserIds = new ArrayList<String>();
+ ArrayList<String> duplicateUserIds = new ArrayList<String>();
for (String email : encryptionUserIds) {
- Uri uri = KeychainContract.KeyRings.buildUnifiedKeyRingsByEmailUri(email);
+ Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email);
Cursor cur = getContentResolver().query(uri, null, null, null, null);
if (cur.moveToFirst()) {
- long id = cur.getLong(cur.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID));
+ long id = cur.getLong(cur.getColumnIndex(KeyRings.MASTER_KEY_ID));
keyIds.add(id);
} else {
missingUserIdsCheck = true;
@@ -77,8 +77,8 @@ public class OpenPgpService extends RemoteService {
Log.d(Constants.TAG, "user id missing");
}
if (cur.moveToNext()) {
- dublicateUserIdsCheck = true;
- dublicateUserIds.add(email);
+ duplicateUserIdsCheck = true;
+ duplicateUserIds.add(email);
Log.d(Constants.TAG, "more than one user id with the same email");
}
}
@@ -90,13 +90,13 @@ public class OpenPgpService extends RemoteService {
}
// allow the user to verify pub key selection
- if (missingUserIdsCheck || dublicateUserIdsCheck) {
+ if (missingUserIdsCheck || duplicateUserIdsCheck) {
// build PendingIntent
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS);
intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds);
- intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds);
+ intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, duplicateUserIds);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 0ec4c1239..962b304c7 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import java.util.Date;
@@ -170,15 +171,11 @@ public class PassphraseCacheService extends Service {
// try to get master key id which is used as an identifier for cached passphrases
long masterKeyId = keyId;
if (masterKeyId != Id.key.symmetric) {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(this, keyId);
- if (keyRing == null) {
+ masterKeyId = ProviderHelper.getMasterKeyId(this,
+ KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)));
+ // Failure
+ if(masterKeyId == 0)
return null;
- }
- PGPSecretKey masterKey = keyRing.getSecretKey();
- if (masterKey == null) {
- return null;
- }
- masterKeyId = masterKey.getKeyID();
}
Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
index f749a4c1c..11fe4a908 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
@@ -160,23 +160,11 @@ public class EncryptAsymmetricFragment extends Fragment {
if (preselectedEncryptionKeyIds != null) {
Vector<Long> goodIds = new Vector<Long>();
for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) {
- // TODO: don't use bouncy castle objects!
-
- PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(getActivity(),
- preselectedEncryptionKeyIds[i]);
- PGPPublicKey masterKey;
- if (keyRing == null) {
- continue;
- }
- masterKey = keyRing.getPublicKey();
- if (masterKey == null) {
- continue;
- }
- Vector<PGPPublicKey> encryptKeys = PgpKeyHelper.getUsableEncryptKeys(keyRing);
- if (encryptKeys.size() == 0) {
- continue;
- }
- goodIds.add(masterKey.getKeyID());
+ long id = ProviderHelper.getMasterKeyId(getActivity(),
+ KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(preselectedEncryptionKeyIds[i]))
+ );
+ // TODO check for available encrypt keys... is this even relevant?
+ goodIds.add(id);
}
if (goodIds.size() > 0) {
long[] keyIds = new long[goodIds.size()];