aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src/main/java')
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java14
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java28
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java53
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java1
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java260
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java364
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java23
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java6
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java4
-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/EditKeyActivity.java10
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java47
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java74
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java25
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java29
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java71
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java130
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java17
21 files changed, 498 insertions, 679 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
index 11b87fc97..4b0a07d9b 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
@@ -232,7 +232,7 @@ public class PgpDecryptVerify {
updateProgress(R.string.progress_finding_key, currentProgress, 100);
PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
- secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID());
+ secretKey = ProviderHelper.getPGPSecretKeyRing(mContext, encData.getKeyID()).getSecretKey();
if (secretKey != null) {
// secret key exists in database
@@ -241,7 +241,7 @@ public class PgpDecryptVerify {
// TODO: improve this code! get master key directly!
PGPSecretKeyRing secretKeyRing =
ProviderHelper.getPGPSecretKeyRingWithKeyId(mContext, encData.getKeyID());
- long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID();
+ long masterKeyId = secretKeyRing.getSecretKey().getKeyID();
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID());
Log.d(Constants.TAG, "allowedKeyIds: " + mAllowedKeyIds);
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
@@ -362,7 +362,7 @@ public class PgpDecryptVerify {
for (int i = 0; i < sigList.size(); ++i) {
signature = sigList.get(i);
signatureKey = ProviderHelper
- .getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
+ .getPGPPublicKeyRing(mContext, signature.getKeyID()).getPublicKey();
if (signatureKeyId == 0) {
signatureKeyId = signature.getKeyID();
}
@@ -375,7 +375,7 @@ public class PgpDecryptVerify {
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(
mContext, signatureKeyId);
if (signKeyRing != null) {
- userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
+ userId = PgpKeyHelper.getMainUserId(signKeyRing.getPublicKey());
}
signatureResult.setUserId(userId);
break;
@@ -546,7 +546,7 @@ public class PgpDecryptVerify {
PGPPublicKey signatureKey = null;
for (int i = 0; i < sigList.size(); ++i) {
signature = sigList.get(i);
- signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
+ signatureKey = ProviderHelper.getPGPPublicKeyRing(mContext, signature.getKeyID()).getPublicKey();
if (signatureKeyId == 0) {
signatureKeyId = signature.getKeyID();
}
@@ -559,7 +559,7 @@ public class PgpDecryptVerify {
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(mContext,
signatureKeyId);
if (signKeyRing != null) {
- userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
+ userId = PgpKeyHelper.getMainUserId(signKeyRing.getPublicKey());
}
signatureResult.setUserId(userId);
break;
@@ -624,7 +624,7 @@ public class PgpDecryptVerify {
signatureKeyId);
PGPPublicKey mKey = null;
if (signKeyRing != null) {
- mKey = PgpKeyHelper.getMasterKey(signKeyRing);
+ mKey = signKeyRing.getPublicKey();
}
if (signature.getKeyID() != mKey.getKeyID()) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
index 49ce8d3bb..d03f3ccc2 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
@@ -260,7 +260,6 @@ public class PgpImportExport {
}
if (save) {
- ProviderHelper.saveKeyRing(mContext, secretKeyRing);
// TODO: preserve certifications
// (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?)
PGPPublicKeyRing newPubRing = null;
@@ -275,6 +274,7 @@ public class PgpImportExport {
if (newPubRing != null) {
ProviderHelper.saveKeyRing(mContext, newPubRing);
}
+ ProviderHelper.saveKeyRing(mContext, secretKeyRing);
// TODO: remove status returns, use exceptions!
status = Id.return_value.ok;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
index 290c8870b..9a97bc717 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
@@ -61,34 +61,6 @@ public class PgpKeyHelper {
}
@SuppressWarnings("unchecked")
- public static PGPPublicKey getMasterKey(PGPPublicKeyRing keyRing) {
- if (keyRing == null) {
- return null;
- }
- for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
- if (key.isMasterKey()) {
- return key;
- }
- }
-
- return null;
- }
-
- @SuppressWarnings("unchecked")
- public static PGPSecretKey getMasterKey(PGPSecretKeyRing keyRing) {
- if (keyRing == null) {
- return null;
- }
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
- if (key.isMasterKey()) {
- return key;
- }
- }
-
- return null;
- }
-
- @SuppressWarnings("unchecked")
public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
long cnt = 0;
if (keyRing == null) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
index c1baed402..a864a165d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
@@ -306,7 +306,7 @@ public class PgpSignEncrypt {
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
signatureGenerator.init(signatureType, signaturePrivateKey);
- String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signingKeyRing));
+ String userId = PgpKeyHelper.getMainUserId(signingKeyRing.getSecretKey());
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, userId);
signatureGenerator.setHashedSubpackets(spGen.generate());
@@ -505,7 +505,7 @@ public class PgpSignEncrypt {
signatureGenerator.init(type, signaturePrivateKey);
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signingKeyRing));
+ String userId = PgpKeyHelper.getMainUserId(signingKeyRing.getSecretKey());
spGen.setSignerUserID(false, userId);
signatureGenerator.setHashedSubpackets(spGen.generate());
}
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 fcf8f7962..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";
@@ -96,31 +95,49 @@ public class KeychainContract {
public static final String BASE_API_APPS = "api_apps";
public static final String PATH_ACCOUNTS = "accounts";
- public static class KeyRings implements KeyRingsColumns, BaseColumns {
+ public static class KeyRings implements BaseColumns, KeysColumns, UserIdsColumns {
+ public static final String MASTER_KEY_ID = "master_key_id";
+ public static final String HAS_SECRET = "has_secret";
+
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
.appendPath(BASE_KEY_RINGS).build();
- /**
- * Use if multiple items get returned
- */
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.key_ring";
-
- /**
- * Use if a single item is returned
- */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.key_ring";
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 {
+ public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+ .appendPath(BASE_KEY_RINGS).build();
+
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.key_ring_data";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.key_ring_data";
+
+ public static Uri buildPublicKeyRingUri() {
+ return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).build();
+ }
public static Uri buildPublicKeyRingUri(String masterKeyId) {
return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_PUBLIC).build();
}
@@ -135,12 +152,6 @@ public class KeychainContract {
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_SECRET).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 class Keys implements KeysColumns, BaseColumns {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index e0cf6b6c5..36e2a7962 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -124,7 +124,6 @@ public class KeychainDatabase extends SQLiteOpenHelper {
KeychainDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
-
// make sure this is only done once, on the first instance!
boolean iAmIt = false;
synchronized(apg_hack) {
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 39ea083fa..1dd6ab08f 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
@@ -26,19 +26,15 @@ import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
-import android.provider.BaseColumns;
import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.util.Log;
@@ -46,13 +42,9 @@ import java.util.Arrays;
import java.util.HashMap;
public class KeychainProvider extends ContentProvider {
- // public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME
- // + ".action.DATABASE_CHANGE";
- //
- // public static final String EXTRA_BROADCAST_KEY_TYPE = "key_type";
- // public static final String EXTRA_BROADCAST_CONTENT_ITEM_TYPE = "contentItemType";
private static final int KEY_RINGS_UNIFIED = 101;
+ private static final int KEY_RINGS_PUBLIC = 102;
private static final int KEY_RING_UNIFIED = 200;
private static final int KEY_RING_KEYS = 201;
@@ -65,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;
@@ -79,18 +74,36 @@ public class KeychainProvider extends ContentProvider {
String authority = KeychainContract.CONTENT_AUTHORITY;
/**
- * select from key_ring
+ * list key_rings
*
* <pre>
* key_rings/unified
+ * key_rings/public
* </pre>
*/
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS
+ "/" + KeychainContract.PATH_UNIFIED,
KEY_RINGS_UNIFIED);
+ matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS
+ + "/" + KeychainContract.PATH_PUBLIC,
+ 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);
/**
- * select from key_ring
+ * list key_ring specifics
*
* <pre>
* key_rings/_/unified
@@ -155,10 +168,15 @@ public class KeychainProvider extends ContentProvider {
@Override
public boolean onCreate() {
mUriMatcher = buildUriMatcher();
- mKeychainDatabase = new KeychainDatabase(getContext());
return true;
}
+ public KeychainDatabase getDb() {
+ if(mKeychainDatabase == null)
+ mKeychainDatabase = new KeychainDatabase(getContext());
+ return mKeychainDatabase;
+ }
+
/**
* {@inheritDoc}
*/
@@ -204,7 +222,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);
@@ -213,98 +230,126 @@ 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(BaseColumns._ID, Tables.KEYS + ".oid AS _id");
- projectionMap.put(KeysColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID);
- projectionMap.put(KeysColumns.RANK, Tables.KEYS + "." + KeysColumns.RANK);
- projectionMap.put(KeysColumns.KEY_ID, KeysColumns.KEY_ID);
- projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE);
- projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
- projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY);
- projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
- projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN);
- projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION);
- projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY);
- projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
- projectionMap.put(KeysColumns.FINGERPRINT, KeysColumns.FINGERPRINT);
- projectionMap.put(UserIdsColumns.USER_ID, UserIdsColumns.USER_ID);
- projectionMap.put(Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID, Tables.KEY_RINGS_SECRET + "." + KeyRingsColumns.MASTER_KEY_ID);
+ projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id");
+ projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
+ projectionMap.put(KeyRings.KEY_ID, Keys.KEY_ID);
+ projectionMap.put(KeyRings.KEY_SIZE, Keys.KEY_SIZE);
+ projectionMap.put(KeyRings.IS_REVOKED, Keys.IS_REVOKED);
+ projectionMap.put(KeyRings.CAN_CERTIFY, Keys.CAN_CERTIFY);
+ projectionMap.put(KeyRings.CAN_ENCRYPT, Keys.CAN_ENCRYPT);
+ projectionMap.put(KeyRings.CAN_SIGN, Keys.CAN_SIGN);
+ projectionMap.put(KeyRings.CREATION, Keys.CREATION);
+ projectionMap.put(KeyRings.EXPIRY, Keys.EXPIRY);
+ projectionMap.put(KeyRings.ALGORITHM, Keys.ALGORITHM);
+ projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT);
+ projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID);
+ projectionMap.put(KeyRings.HAS_SECRET, "(" + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL) AS " + KeyRings.HAS_SECRET);
qb.setProjectionMap(projectionMap);
qb.setTables(
Tables.KEYS
+ " INNER JOIN " + Tables.USER_IDS + " ON ("
- + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID
+ + Tables.KEYS + "." + Keys.MASTER_KEY_ID
+ " = "
- + Tables.USER_IDS + "." + UserIdsColumns.MASTER_KEY_ID
- + " AND " + Tables.USER_IDS + "." + UserIdsColumns.RANK + " = 0"
+ + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID
+ + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0"
+ ") LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON ("
- + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID
+ + Tables.KEYS + "." + Keys.MASTER_KEY_ID
+ " = "
- + Tables.KEY_RINGS_SECRET + "." + KeyRingsColumns.MASTER_KEY_ID
+ + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID
+ ")"
);
- qb.appendWhere(Tables.KEYS + "." + KeysColumns.RANK + " = 0");
+ qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0");
- if(match == KEY_RING_UNIFIED) {
- qb.appendWhere(" AND " + Tables.KEYS + "." + KeysColumns.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 + "." + UserIdsColumns.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/
+ uri = KeyRings.CONTENT_URI;
+
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." + UserIdsColumns.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." + BaseColumns._ID + " FROM "
- + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID
- + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + emailWhere
- + "))");
- }*/
case KEY_RING_KEYS: {
HashMap<String, String> projectionMap = new HashMap<String, String>();
- projectionMap.put(BaseColumns._ID, Tables.KEYS + ".oid AS _id");
- projectionMap.put(KeysColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID);
- projectionMap.put(KeysColumns.RANK, Tables.KEYS + "." + KeysColumns.RANK);
- projectionMap.put(KeysColumns.KEY_ID, KeysColumns.KEY_ID);
- projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE);
- projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
- projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY);
- projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
- projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN);
- projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION);
- projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY);
- projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
- projectionMap.put(KeysColumns.FINGERPRINT, KeysColumns.FINGERPRINT);
+ projectionMap.put(Keys._ID, Tables.KEYS + ".oid AS _id");
+ projectionMap.put(Keys.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
+ projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK);
+ projectionMap.put(Keys.KEY_ID, Keys.KEY_ID);
+ projectionMap.put(Keys.KEY_SIZE, Keys.KEY_SIZE);
+ projectionMap.put(Keys.IS_REVOKED, Keys.IS_REVOKED);
+ projectionMap.put(Keys.CAN_CERTIFY, Keys.CAN_CERTIFY);
+ projectionMap.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT);
+ projectionMap.put(Keys.CAN_SIGN, Keys.CAN_SIGN);
+ projectionMap.put(Keys.CREATION, Keys.CREATION);
+ projectionMap.put(Keys.EXPIRY, Keys.EXPIRY);
+ projectionMap.put(Keys.ALGORITHM, Keys.ALGORITHM);
+ projectionMap.put(Keys.FINGERPRINT, Keys.FINGERPRINT);
qb.setProjectionMap(projectionMap);
qb.setTables(Tables.KEYS);
- qb.appendWhere(KeysColumns.MASTER_KEY_ID + " = ");
+ qb.appendWhere(Keys.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
break;
@@ -312,7 +357,7 @@ public class KeychainProvider extends ContentProvider {
case KEY_RING_USER_IDS: {
HashMap<String, String> projectionMap = new HashMap<String, String>();
- projectionMap.put(BaseColumns._ID, Tables.USER_IDS + ".oid AS _id");
+ projectionMap.put(UserIds._ID, Tables.USER_IDS + ".oid AS _id");
projectionMap.put(UserIds.MASTER_KEY_ID, UserIds.MASTER_KEY_ID);
projectionMap.put(UserIds.USER_ID, UserIds.USER_ID);
projectionMap.put(UserIds.RANK, UserIds.RANK);
@@ -320,36 +365,44 @@ public class KeychainProvider extends ContentProvider {
qb.setProjectionMap(projectionMap);
qb.setTables(Tables.USER_IDS);
- qb.appendWhere(UserIdsColumns.MASTER_KEY_ID + " = ");
+ qb.appendWhere(UserIds.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+ if (TextUtils.isEmpty(sortOrder)) {
+ sortOrder = UserIds.RANK + " ASC";
+ }
+
break;
}
+ case KEY_RINGS_PUBLIC:
case KEY_RING_PUBLIC: {
HashMap<String, String> projectionMap = new HashMap<String, String>();
- projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id");
- projectionMap.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID);
- projectionMap.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA);
+ projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id");
+ projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID);
+ projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA);
qb.setProjectionMap(projectionMap);
qb.setTables(Tables.KEY_RINGS_PUBLIC);
- qb.appendWhere(KeyRingsColumns.MASTER_KEY_ID + " = ");
- qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+
+ if(match == KEY_RING_PUBLIC) {
+ qb.appendWhere(KeyRings.MASTER_KEY_ID + " = ");
+ qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+ }
break;
}
case KEY_RING_SECRET: {
HashMap<String, String> projectionMap = new HashMap<String, String>();
- projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id");
- projectionMap.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID);
- projectionMap.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA);
+ projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id");
+ projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID);
+ projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA);
qb.setProjectionMap(projectionMap);
qb.setTables(Tables.KEY_RINGS_SECRET);
- qb.appendWhere(KeyRingsColumns.MASTER_KEY_ID + " = ");
+ qb.appendWhere(KeyRings.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
break;
@@ -381,7 +434,7 @@ public class KeychainProvider extends ContentProvider {
break;
default:
- throw new IllegalArgumentException("Unknown URI " + uri);
+ throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")");
}
@@ -393,6 +446,7 @@ public class KeychainProvider extends ContentProvider {
orderBy = sortOrder;
}
+ SQLiteDatabase db = getDb().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
@@ -416,7 +470,7 @@ public class KeychainProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) {
Log.d(Constants.TAG, "insert(uri=" + uri + ", values=" + values.toString() + ")");
- final SQLiteDatabase db = mKeychainDatabase.getWritableDatabase();
+ final SQLiteDatabase db = getDb().getWritableDatabase();
Uri rowUri = null;
Long keyId = null;
@@ -426,23 +480,23 @@ public class KeychainProvider extends ContentProvider {
switch (match) {
case KEY_RING_PUBLIC:
db.insertOrThrow(Tables.KEY_RINGS_PUBLIC, null, values);
- keyId = values.getAsLong(KeyRingsColumns.MASTER_KEY_ID);
+ keyId = values.getAsLong(KeyRings.MASTER_KEY_ID);
break;
case KEY_RING_SECRET:
db.insertOrThrow(Tables.KEY_RINGS_SECRET, null, values);
- keyId = values.getAsLong(KeyRingsColumns.MASTER_KEY_ID);
+ keyId = values.getAsLong(KeyRings.MASTER_KEY_ID);
break;
case KEY_RING_KEYS:
Log.d(Constants.TAG, "keys");
db.insertOrThrow(Tables.KEYS, null, values);
- keyId = values.getAsLong(KeysColumns.MASTER_KEY_ID);
+ keyId = values.getAsLong(Keys.MASTER_KEY_ID);
break;
case KEY_RING_USER_IDS:
db.insertOrThrow(Tables.USER_IDS, null, values);
- keyId = values.getAsLong(UserIdsColumns.MASTER_KEY_ID);
+ keyId = values.getAsLong(UserIds.MASTER_KEY_ID);
break;
case API_APPS:
@@ -489,7 +543,7 @@ public class KeychainProvider extends ContentProvider {
public int delete(Uri uri, String additionalSelection, String[] selectionArgs) {
Log.v(Constants.TAG, "delete(uri=" + uri + ")");
- final SQLiteDatabase db = mKeychainDatabase.getWritableDatabase();
+ final SQLiteDatabase db = getDb().getWritableDatabase();
int count;
final int match = mUriMatcher.match(uri);
@@ -503,6 +557,7 @@ public class KeychainProvider extends ContentProvider {
}
// corresponding keys and userIds are deleted by ON DELETE CASCADE
count = db.delete(Tables.KEY_RINGS_PUBLIC, selection, selectionArgs);
+ uri = KeyRings.buildGenericKeyRingUri(uri.getPathSegments().get(1));
break;
}
case KEY_RING_SECRET: {
@@ -512,6 +567,7 @@ public class KeychainProvider extends ContentProvider {
selection += " AND (" + additionalSelection + ")";
}
count = db.delete(Tables.KEY_RINGS_SECRET, selection, selectionArgs);
+ uri = KeyRings.buildGenericKeyRingUri(uri.getPathSegments().get(1));
break;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 3f96a51ef..6a12184fe 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -23,7 +23,10 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
+import android.database.CursorWindow;
+import android.database.CursorWrapper;
import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteCursor;
import android.net.Uri;
import android.os.RemoteException;
@@ -40,9 +43,9 @@ import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.util.IterableIterator;
@@ -52,21 +55,73 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class ProviderHelper {
- /**
- * Private helper method to get PGPKeyRing from database
+ public static Object getGenericData(Context context, Uri uri, String column) {
+ return getGenericData(context, uri, new String[] { column }).get(column);
+ }
+ public static HashMap<String,Object> getGenericData(Context context, Uri uri, String[] proj) {
+ Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
+
+ HashMap<String, Object> result = new HashMap<String, Object>(proj.length);
+ if (cursor != null && cursor.moveToFirst()) {
+ int pos = 0;
+ for(String p : proj) {
+ switch(cursor.getType(pos)) {
+ case Cursor.FIELD_TYPE_NULL: result.put(p, cursor.isNull(pos)); break;
+ case Cursor.FIELD_TYPE_INTEGER: result.put(p, cursor.getLong(pos)); break;
+ case Cursor.FIELD_TYPE_FLOAT: result.put(p, cursor.getFloat(pos)); break;
+ case Cursor.FIELD_TYPE_STRING: result.put(p, cursor.getString(pos)); break;
+ case Cursor.FIELD_TYPE_BLOB: result.put(p, cursor.getBlob(pos)); break;
+ }
+ pos += 1;
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ return result;
+ }
+
+ public static Object getUnifiedData(Context context, long masterKeyId, String column) {
+ return getUnifiedData(context, masterKeyId, new String[] { column }).get(column);
+ }
+ public static HashMap<String,Object> getUnifiedData(Context context, long masterKeyId, String[] proj) {
+ return getGenericData(context, KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), proj);
+ }
+
+ /** Find the master key id related to a given query. The id will either be extracted from the
+ * query, which should work for all specific /key_rings/ queries, or will be queried if it can't.
*/
+ public static long getMasterKeyId(Context context, Uri queryUri) {
+ // try extracting from the uri first
+ String firstSegment = queryUri.getPathSegments().get(1);
+ if(!firstSegment.equals("find")) try {
+ return Long.parseLong(firstSegment);
+ } catch(NumberFormatException e) {
+ // didn't work? oh well.
+ Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying...");
+ }
+ Object data = getGenericData(context, queryUri, KeyRings.MASTER_KEY_ID);
+ if(data instanceof Long)
+ return (Long) data;
+ // TODO better error handling?
+ return 0L;
+ }
+
public static PGPKeyRing getPGPKeyRing(Context context, Uri queryUri) {
Cursor cursor = context.getContentResolver().query(queryUri,
- new String[]{KeyRings._ID, KeyRings.KEY_RING_DATA}, null, null, null);
+ new String[]{KeyRings._ID, KeyRingData.KEY_RING_DATA}, null, null, null);
PGPKeyRing keyRing = null;
if (cursor != null && cursor.moveToFirst()) {
- int keyRingDataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
+ int keyRingDataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA);
byte[] data = cursor.getBlob(keyRingDataCol);
if (data != null) {
@@ -81,19 +136,18 @@ public class ProviderHelper {
return keyRing;
}
- public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) {
- return getPGPPublicKeyRingWithKeyId(context, keyId).getPublicKey(keyId);
- }
public static PGPPublicKeyRing getPGPPublicKeyRingWithKeyId(Context context, long keyId) {
- // todo do
+ Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId));
+ long masterKeyId = getMasterKeyId(context, uri);
+ if(masterKeyId != 0)
+ return getPGPPublicKeyRing(context, masterKeyId);
return null;
}
-
- public static PGPSecretKey getPGPSecretKeyByKeyId(Context context, long keyId) {
- return getPGPSecretKeyRingWithKeyId(context, keyId).getSecretKey(keyId);
- }
public static PGPSecretKeyRing getPGPSecretKeyRingWithKeyId(Context context, long keyId) {
- // todo do
+ Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId));
+ long masterKeyId = getMasterKeyId(context, uri);
+ if(masterKeyId != 0)
+ return getPGPSecretKeyRing(context, masterKeyId);
return null;
}
@@ -102,7 +156,7 @@ public class ProviderHelper {
*/
public static PGPPublicKeyRing getPGPPublicKeyRing(Context context,
long masterKeyId) {
- Uri queryUri = KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId));
+ Uri queryUri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId));
return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri);
}
@@ -111,7 +165,7 @@ public class ProviderHelper {
*/
public static PGPSecretKeyRing getPGPSecretKeyRing(Context context,
long masterKeyId) {
- Uri queryUri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId));
+ Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri);
}
@@ -124,12 +178,11 @@ public class ProviderHelper {
long masterKeyId = masterKey.getKeyID();
// IF there is a secret key, preserve it!
- // TODO This even necessary?
- // PGPSecretKeyRing secretRing = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId);
+ PGPSecretKeyRing secretRing = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId);
// delete old version of this keyRing, which also deletes all keys and userIds on cascade
try {
- context.getContentResolver().delete(KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null);
+ context.getContentResolver().delete(KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null);
} catch (UnsupportedOperationException e) {
Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e);
}
@@ -139,11 +192,11 @@ public class ProviderHelper {
// NOTE: If we would not use the same _ID again,
// getting back to the ViewKeyActivity would result in Nullpointer,
// because the currently loaded key would be gone from the database
- values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
- values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
+ values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
+ values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
// insert new version of this keyRing
- Uri uri = KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId));
+ Uri uri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId));
Uri insertedUri = context.getContentResolver().insert(uri, values);
// save all keys and userIds included in keyRing object in database
@@ -179,31 +232,43 @@ public class ProviderHelper {
}
// Save the saved keyring (if any)
- // TODO this even necessary? see above...
- // if(secretRing != null)
- // saveKeyRing(context, secretRing);
+ if(secretRing != null) {
+ saveKeyRing(context, secretRing);
+ }
}
/**
- * Saves PGPSecretKeyRing with its keys and userIds in DB
+ * Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring
+ * is already in the database!
*/
@SuppressWarnings("unchecked")
public static void saveKeyRing(Context context, PGPSecretKeyRing keyRing) throws IOException {
- PGPSecretKey masterKey = keyRing.getSecretKey();
- long masterKeyId = masterKey.getKeyID();
+ long masterKeyId = keyRing.getPublicKey().getKeyID();
- // TODO Make sure there is a public key for this secret key in the db (create one maybe)
+ // save secret keyring
+ ContentValues values = new ContentValues();
+ values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
+ values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
+ // insert new version of this keyRing
+ Uri uri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
+ context.getContentResolver().insert(uri, values);
- {
- ContentValues values = new ContentValues();
- values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
- values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
- // insert new version of this keyRing
- Uri uri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId));
- context.getContentResolver().insert(uri, values);
- }
+ }
+
+ /**
+ * Saves (or updates) a pair of public and secret KeyRings in the database
+ */
+ @SuppressWarnings("unchecked")
+ public static void saveKeyRing(Context context, PGPPublicKeyRing pubRing, PGPSecretKeyRing privRing) throws IOException {
+ long masterKeyId = pubRing.getPublicKey().getKeyID();
+ // delete secret keyring (so it isn't unnecessarily saved by public-saveKeyRing below)
+ context.getContentResolver().delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null);
+
+ // save public keyring
+ saveKeyRing(context, pubRing);
+ saveKeyRing(context, privRing);
}
/**
@@ -260,190 +325,22 @@ public class ProviderHelper {
return ContentProviderOperation.newInsert(uri).withValues(values).build();
}
- /**
- * Private helper method
- */
- private static ArrayList<Long> getKeyRingsMasterKeyIds(Context context, Uri queryUri) {
- Cursor cursor = context.getContentResolver().query(queryUri,
- new String[]{KeyRings.MASTER_KEY_ID}, null, null, null);
-
- ArrayList<Long> masterKeyIds = new ArrayList<Long>();
- if (cursor != null) {
- int masterKeyIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
- if (cursor.moveToFirst()) {
- do {
- masterKeyIds.add(cursor.getLong(masterKeyIdCol));
- } while (cursor.moveToNext());
- }
- }
-
- if (cursor != null) {
- cursor.close();
- }
-
- return masterKeyIds;
- }
-
- public static void deletePublicKeyRing(Context context, long masterKeyId) {
- ContentResolver cr = context.getContentResolver();
- cr.delete(KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null);
- }
-
- public static void deleteSecretKeyRing(Context context, long masterKeyId) {
- ContentResolver cr = context.getContentResolver();
- cr.delete(KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null);
- }
-
- public static boolean getMasterKeyCanCertify(Context context, Uri queryUri) {
- // TODO redo
-
- return false;
-
- /*
- String[] projection = new String[]{
- KeyRings.MASTER_KEY_ID,
- "(SELECT COUNT(sign_keys." + Keys._ID + ") FROM " + Tables.KEYS
- + " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
- + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID
- + " AND sign_keys." + Keys.CAN_CERTIFY + " = '1' AND " + Keys.IS_MASTER_KEY
- + " = 1) AS sign",};
-
- ContentResolver cr = context.getContentResolver();
- Cursor cursor = cr.query(queryUri, projection, null, null, null);
-
- long masterKeyId = -1;
- if (cursor != null && cursor.moveToFirst()) {
- int masterKeyIdCol = cursor.getColumnIndex("sign");
-
- masterKeyId = cursor.getLong(masterKeyIdCol);
- }
-
- if (cursor != null) {
- cursor.close();
- }
-
- return (masterKeyId > 0);
- */
- }
-
public static boolean hasSecretKeyByMasterKeyId(Context context, long masterKeyId) {
- Uri queryUri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId));
+ Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
// see if we can get our master key id back from the uri
return getMasterKeyId(context, queryUri) == masterKeyId;
}
- /**
- * Get master key id of key
- */
- public static long getMasterKeyId(Context context, Uri queryUri) {
- String[] projection = new String[]{KeyRings.MASTER_KEY_ID};
- Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
-
- long masterKeyId = 0;
- try {
- if (cursor != null && cursor.moveToFirst()) {
- int masterKeyIdCol = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
-
- masterKeyId = cursor.getLong(masterKeyIdCol);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- return masterKeyId;
- }
-
- public static long getRowId(Context context, Uri queryUri) {
- String[] projection = new String[]{KeyRings._ID};
- Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
-
- long rowId = 0;
- try {
- if (cursor != null && cursor.moveToFirst()) {
- int idCol = cursor.getColumnIndexOrThrow(KeyRings._ID);
-
- rowId = cursor.getLong(idCol);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- return rowId;
- }
-
- /**
- * Get fingerprint of key
- */
- public static byte[] getFingerprint(Context context, Uri queryUri) {
- String[] projection = new String[]{Keys.FINGERPRINT};
- Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
-
- byte[] fingerprint = null;
- try {
- if (cursor != null && cursor.moveToFirst()) {
- int col = cursor.getColumnIndexOrThrow(Keys.FINGERPRINT);
-
- fingerprint = cursor.getBlob(col);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- // FALLBACK: If fingerprint is not in database, get it from key blob!
- // this could happen if the key was saved by a previous version of Keychain!
- if (fingerprint == null) {
- Log.d(Constants.TAG, "FALLBACK: fingerprint is not in database, get it from key blob!");
-
- // get master key id
- projection = new String[]{KeyRings.MASTER_KEY_ID};
- cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
- long masterKeyId = 0;
- try {
- if (cursor != null && cursor.moveToFirst()) {
- int col = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
-
- masterKeyId = cursor.getLong(col);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- PGPPublicKey key = ProviderHelper.getPGPPublicKeyRing(context, masterKeyId).getPublicKey();
- // if it is no public key get it from your own keys...
- if (key == null) {
- PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId).getSecretKey();
- if (secretKey == null) {
- Log.e(Constants.TAG, "Key could not be found!");
- return null;
- }
- key = secretKey.getPublicKey();
- }
-
- fingerprint = key.getFingerprint();
- }
-
- return fingerprint;
- }
-
- public static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri,
- long[] masterKeyIds) {
+ public static ArrayList<String> getKeyRingsAsArmoredString(Context context, long[] masterKeyIds) {
ArrayList<String> output = new ArrayList<String>();
if (masterKeyIds != null && masterKeyIds.length > 0) {
- Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds);
+ Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, masterKeyIds);
if (cursor != null) {
- int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
- int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
+ int masterIdCol = cursor.getColumnIndex(KeyRingData.MASTER_KEY_ID);
+ int dataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA);
if (cursor.moveToFirst()) {
do {
Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
@@ -493,48 +390,11 @@ public class ProviderHelper {
return null;
}
}
-
- public static byte[] getKeyRingsAsByteArray(Context context, Uri uri, long[] masterKeyIds) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
- if (masterKeyIds != null && masterKeyIds.length > 0) {
-
- Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds);
-
- if (cursor != null) {
- int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
- int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
- if (cursor.moveToFirst()) {
- do {
- Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
-
- // get actual keyring data blob and write it to ByteArrayOutputStream
- try {
- bos.write(cursor.getBlob(dataCol));
- } catch (IOException e) {
- Log.e(Constants.TAG, "IOException", e);
- }
- } while (cursor.moveToNext());
- }
- }
-
- if (cursor != null) {
- cursor.close();
- }
-
- } else {
- Log.e(Constants.TAG, "No master keys given!");
- }
-
- return bos.toByteArray();
- }
-
- private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, Uri baseUri,
- long[] masterKeyIds) {
+ private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, long[] masterKeyIds) {
Cursor cursor = null;
if (masterKeyIds != null && masterKeyIds.length > 0) {
- String inMasterKeyList = KeyRings.MASTER_KEY_ID + " IN (";
+ String inMasterKeyList = KeyRingData.MASTER_KEY_ID + " IN (";
for (int i = 0; i < masterKeyIds.length; ++i) {
if (i != 0) {
inMasterKeyList += ", ";
@@ -543,9 +403,9 @@ public class ProviderHelper {
}
inMasterKeyList += ")";
- cursor = context.getContentResolver().query(baseUri,
- new String[]{KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.KEY_RING_DATA},
- inMasterKeyList, null, null);
+ cursor = context.getContentResolver().query(KeyRingData.buildPublicKeyRingUri(), new String[] {
+ KeyRingData._ID, KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA
+ }, inMasterKeyList, null, null);
}
return cursor;
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 e6e6ba31b..b38fea5a9 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
@@ -35,7 +35,8 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
@@ -61,15 +62,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 +78,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 +91,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,
@@ -351,7 +352,7 @@ public class OpenPgpService extends RemoteService {
try {
long keyId = data.getLongExtra(OpenPgpApi.EXTRA_KEY_ID, 0);
- if (ProviderHelper.getPGPPublicKeyByKeyId(this, keyId) == null) {
+ if (ProviderHelper.getPGPPublicKeyRing(this, keyId) == null) {
Intent result = new Intent();
// If keys are not in db we return an additional PendingIntent
@@ -462,7 +463,7 @@ public class OpenPgpService extends RemoteService {
String currentPkg = getCurrentCallingPackage();
Set<Long> allowedKeyIds =
ProviderHelper.getAllKeyIdsForApp(mContext,
- KeychainContract.ApiAccounts.buildBaseUri(currentPkg));
+ ApiAccounts.buildBaseUri(currentPkg));
return decryptAndVerifyImpl(data, input, output, allowedKeyIds);
} else if (OpenPgpApi.ACTION_GET_KEY.equals(action)) {
return getKeyImpl(data);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
index dee0dae95..992aa7c95 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
@@ -34,6 +34,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.ui.EditKeyActivity;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
@@ -176,9 +177,8 @@ public class AccountSettingsFragment extends Fragment implements
case REQUEST_CODE_CREATE_KEY: {
if (resultCode == Activity.RESULT_OK) {
// select newly created key
- Uri newKeyUri = data.getData();
- // TODO helper method for this?
- mSelectKeyFragment.selectKey(Long.parseLong(newKeyUri.getPathSegments().get(1)));
+ long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), data.getData());
+ mSelectKeyFragment.selectKey(masterKeyId);
}
break;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index aea562227..768237c7d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -508,8 +508,8 @@ public class KeychainIntentService extends IntentService
PgpKeyOperation.Pair<PGPSecretKeyRing,PGPPublicKeyRing> pair =
keyOperations.buildSecretKey(privkey, pubkey, saveParams);
setProgress(R.string.progress_saving_key_ring, 90, 100);
- ProviderHelper.saveKeyRing(this, pair.first);
- ProviderHelper.saveKeyRing(this, pair.second);
+ // save the pair
+ ProviderHelper.saveKeyRing(this, pair.second, pair.first);
setProgress(R.string.progress_done, 100, 100);
}
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase);
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 63703a02b..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 = PgpKeyHelper.getMasterKey(keyRing);
- 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/EditKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index d7ff8c207..e6fd59d55 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
@@ -276,8 +277,6 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
// get master key id using row id
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
-
- mMasterCanSign = ProviderHelper.getMasterKeyCanCertify(this, mDataUri);
finallyEdit(masterKeyId);
}
}
@@ -347,8 +346,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
}
return true;
case R.id.menu_key_edit_delete:
- long rowId= ProviderHelper.getRowId(this,mDataUri);
- Uri convertUri = KeychainContract.KeyRings.buildSecretKeyRingUri(Long.toString(rowId));
+ Uri convertUri = KeyRingData.buildSecretKeyRingUri(mDataUri);
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@Override
@@ -374,7 +372,8 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
PGPSecretKey masterKey = null;
mKeyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId);
if (mKeyRing != null) {
- masterKey = PgpKeyHelper.getMasterKey(mKeyRing);
+ masterKey = mKeyRing.getSecretKey();
+ mMasterCanSign = PgpKeyHelper.isCertificationKey(mKeyRing.getSecretKey());
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(mKeyRing.getSecretKeys())) {
mKeys.add(key);
mKeysUsages.add(-1); // get usage when view is created
@@ -382,6 +381,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
} else {
Log.e(Constants.TAG, "Keyring not found with masterKeyId: " + masterKeyId);
Toast.makeText(this, R.string.error_no_secret_key_found, Toast.LENGTH_LONG).show();
+ // TODO
}
if (masterKey != null) {
boolean isSet = false;
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 7ae48f9be..67d59ab7d 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
@@ -37,8 +37,10 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import java.util.HashMap;
import java.util.Vector;
public class EncryptAsymmetricFragment extends Fragment {
@@ -145,7 +147,7 @@ public class EncryptAsymmetricFragment extends Fragment {
preselectedSignatureKeyId);
PGPSecretKey masterKey;
if (keyRing != null) {
- masterKey = PgpKeyHelper.getMasterKey(keyRing);
+ masterKey = keyRing.getSecretKey();
if (masterKey != null) {
Vector<PGPSecretKey> signKeys = PgpKeyHelper.getUsableSigningKeys(keyRing);
if (signKeys.size() > 0) {
@@ -158,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 = PgpKeyHelper.getMasterKey(keyRing);
- 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()];
@@ -202,20 +192,17 @@ public class EncryptAsymmetricFragment extends Fragment {
} else {
String uid = getResources().getString(R.string.user_id_no_name);
String uidExtra = "";
- // TODO: don't use bouncy castle objects!
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(getActivity(),
- mSecretKeyId);
- if (keyRing != null) {
- PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing);
- if (key != null) {
- String userId = PgpKeyHelper.getMainUserIdSafe(getActivity(), key);
- String chunks[] = userId.split(" <", 2);
- uid = chunks[0];
- if (chunks.length > 1) {
- uidExtra = "<" + chunks[1];
- }
+ // See if we can get a user_id from a unified query
+ Object data = ProviderHelper.getUnifiedData(
+ getActivity(), mSecretKeyId, KeyRings.USER_ID);
+ if(data instanceof String) {
+ String chunks[] = ((String) data).split(" <", 2);
+ uid = chunks[0];
+ if (chunks.length > 1) {
+ uidExtra = "<" + chunks[1];
}
}
+
mMainUserId.setText(uid);
mMainUserIdRest.setText(uidExtra);
mSign.setChecked(true);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index 6dec5e56e..33ccd3a23 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -58,12 +58,9 @@ import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ExportHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.HighlightQueryCursorAdapter;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
@@ -157,9 +154,6 @@ public class KeyListFragment extends Fragment
} catch (ApiLevelTooLowException e) {
}
- // this view is made visible if no data is available
- mStickyList.setEmptyView(getActivity().findViewById(R.id.key_list_empty));
-
/*
* ActionBarSherlock does not support MultiChoiceModeListener. Thus multi-selection is only
* available for Android >= 3.0
@@ -193,28 +187,15 @@ public class KeyListFragment extends Fragment
break;
}
case R.id.menu_key_list_multi_delete: {
- ids = mStickyList.getWrappedList().getCheckedItemIds();
+ ids = mAdapter.getCurrentSelectedMasterKeyIds();
showDeleteKeyDialog(mode, ids);
break;
}
case R.id.menu_key_list_multi_export: {
- ids = mStickyList.getWrappedList().getCheckedItemIds();
- long[] masterKeyIds = new long[2*ids.length];
- /* TODO! redo
- ArrayList<Long> allPubRowIds =
- ProviderHelper.getPublicKeyRingsRowIds(getActivity());
- for (int i = 0; i < ids.length; i++) {
- if (allPubRowIds.contains(ids[i])) {
- masterKeyIds[i] =
- ProviderHelper.getPublicMasterKeyId(getActivity(), ids[i]);
- } else {
- masterKeyIds[i] =
- ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]);
- }
- }*/
+ ids = mAdapter.getCurrentSelectedMasterKeyIds();
ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());
mExportHelper
- .showExportKeysDialog(masterKeyIds, Id.type.public_key,
+ .showExportKeysDialog(ids, Id.type.public_key,
Constants.Path.APP_DIR_FILE_PUB,
getString(R.string.also_export_secret_keys));
break;
@@ -270,11 +251,11 @@ public class KeyListFragment extends Fragment
// These are the rows that we will retrieve.
static final String[] PROJECTION = new String[]{
- KeychainContract.KeyRings._ID,
- KeychainContract.Keys.MASTER_KEY_ID,
- KeychainContract.UserIds.USER_ID,
- KeychainContract.Keys.IS_REVOKED,
- KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID
+ KeyRings._ID,
+ KeyRings.MASTER_KEY_ID,
+ KeyRings.USER_ID,
+ KeyRings.IS_REVOKED,
+ KeyRings.HAS_SECRET
};
static final int INDEX_MASTER_KEY_ID = 1;
@@ -282,12 +263,6 @@ public class KeyListFragment extends Fragment
static final int INDEX_IS_REVOKED = 3;
static final int INDEX_HAS_SECRET = 4;
- static final String SORT_ORDER =
- // show secret before public key
- KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID + " IS NULL ASC, " +
- // sort by user id otherwise
- UserIds.USER_ID + " ASC";
-
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
@@ -296,12 +271,12 @@ public class KeyListFragment extends Fragment
String where = null;
String whereArgs[] = null;
if (mCurQuery != null) {
- where = KeychainContract.UserIds.USER_ID + " LIKE ?";
+ where = KeyRings.USER_ID + " LIKE ?";
whereArgs = new String[]{"%" + mCurQuery + "%"};
}
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, PROJECTION, where, whereArgs, SORT_ORDER);
+ return new CursorLoader(getActivity(), baseUri, PROJECTION, where, whereArgs, null);
}
@Override
@@ -313,6 +288,9 @@ public class KeyListFragment extends Fragment
mStickyList.setAdapter(mAdapter);
+ // this view is made visible if no data is available
+ mStickyList.setEmptyView(getActivity().findViewById(R.id.key_list_empty));
+
// NOTE: Not supported by StickyListHeader, but reimplemented here
// The list should now be shown.
if (isResumed()) {
@@ -342,17 +320,15 @@ public class KeyListFragment extends Fragment
viewIntent = new Intent(getActivity(), ViewKeyActivityJB.class);
}
viewIntent.setData(
- KeychainContract
- .KeyRings.buildPublicKeyRingUri(
- Long.toString(mAdapter.getMasterKeyId(position))));
+ KeyRings.buildGenericKeyRingUri(Long.toString(mAdapter.getMasterKeyId(position))));
startActivity(viewIntent);
}
@TargetApi(11)
- protected void encrypt(ActionMode mode, long[] keyRingMasterKeyIds) {
+ protected void encrypt(ActionMode mode, long[] masterKeyIds) {
Intent intent = new Intent(getActivity(), EncryptActivity.class);
intent.setAction(EncryptActivity.ACTION_ENCRYPT);
- intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, keyRingMasterKeyIds);
+ intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, masterKeyIds);
// used instead of startActivity set actionbar based on callingPackage
startActivityForResult(intent, 0);
@@ -362,11 +338,11 @@ public class KeyListFragment extends Fragment
/**
* Show dialog to delete key
*
- * @param keyRingRowIds
+ * @param masterKeyIds
*/
@TargetApi(11)
// TODO: this method needs an overhaul to handle both public and secret keys gracefully!
- public void showDeleteKeyDialog(final ActionMode mode, long[] keyRingRowIds) {
+ public void showDeleteKeyDialog(final ActionMode mode, long[] masterKeyIds) {
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@Override
@@ -381,7 +357,7 @@ public class KeyListFragment extends Fragment
Messenger messenger = new Messenger(returnHandler);
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
- keyRingRowIds);
+ masterKeyIds);
deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog");
}
@@ -520,7 +496,7 @@ public class KeyListFragment extends Fragment
Button button = (Button) view.findViewById(R.id.edit);
TextView revoked = (TextView) view.findViewById(R.id.revoked);
- if (!cursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) {
+ if (cursor.getInt(KeyListFragment.INDEX_HAS_SECRET) != 0) {
// this is a secret key - show the edit button
statusDivider.setVisibility(View.VISIBLE);
statusLayout.setVisibility(View.VISIBLE);
@@ -531,9 +507,7 @@ public class KeyListFragment extends Fragment
button.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
- editIntent.setData(
- KeychainContract.KeyRings
- .buildSecretKeyRingUri(Long.toString(id)));
+ editIntent.setData(KeyRingData.buildSecretKeyRingUri(Long.toString(id)));
editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
startActivityForResult(editIntent, 0);
}
@@ -594,7 +568,7 @@ public class KeyListFragment extends Fragment
throw new IllegalStateException("couldn't move cursor to position " + position);
}
- if (!mCursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) {
+ if (mCursor.getInt(KeyListFragment.INDEX_HAS_SECRET) != 0) {
{ // set contact count
int num = mCursor.getCount();
String contactsTotal = getResources().getQuantityString(R.plurals.n_contacts, num, num);
@@ -634,7 +608,7 @@ public class KeyListFragment extends Fragment
}
// early breakout: all secret keys are assigned id 0
- if (!mCursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) {
+ if (mCursor.getInt(KeyListFragment.INDEX_HAS_SECRET) != 0) {
return 1L;
}
// otherwise, return the first character of the name as ID
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 26aeeaa22..d09f85c47 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -29,6 +29,7 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.Window;
import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
@@ -60,6 +61,7 @@ public class ViewKeyActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceState);
mExportHelper = new ExportHelper(this);
@@ -169,15 +171,22 @@ public class ViewKeyActivity extends ActionBarActivity {
private void shareKey(Uri dataUri, boolean fingerprintOnly) {
String content;
if (fingerprintOnly) {
- byte[] fingerprintBlob = ProviderHelper.getFingerprint(this, dataUri);
- String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
-
- content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
+ Object blob = ProviderHelper.getGenericData(
+ this, KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
+ KeychainContract.Keys.FINGERPRINT);
+ if(blob instanceof byte[]) {
+ String fingerprint = PgpKeyHelper.convertFingerprintToHex((byte[]) blob);
+ content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
+ } else {
+ Toast.makeText(getApplicationContext(), "Bad key selected!",
+ Toast.LENGTH_LONG).show();
+ return;
+ }
} else {
// get public keyring as ascii armored string
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
- ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this,
- dataUri, new long[]{masterKeyId});
+ ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
+ this, new long[]{ masterKeyId });
content = keyringArmored.get(0);
@@ -207,8 +216,8 @@ public class ViewKeyActivity extends ActionBarActivity {
private void copyToClipboard(Uri dataUri) {
// get public keyring as ascii armored string
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
- ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri,
- new long[]{masterKeyId});
+ ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
+ this, new long[]{ masterKeyId });
ClipboardReflection.copyToClipboard(this, keyringArmored.get(0));
Toast.makeText(getApplicationContext(), R.string.key_copied_to_clipboard, Toast.LENGTH_LONG)
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java
index 997ff9c7a..6ce7d9aa8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java
@@ -34,6 +34,9 @@ import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.IOException;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback,
@@ -47,26 +50,18 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- initNfc(mDataUri);
}
/**
* NFC: Initialize NFC sharing if OS and device supports it
*/
- private void initNfc(Uri dataUri) {
+ private void initNfc() {
// check if NFC Beam is supported (>= Android 4.1)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// Check for available NFC Adapter
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
// init nfc
-
- // get public keyring as byte array
- long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
- mSharedKeyringBytes = ProviderHelper.getKeyRingsAsByteArray(this, dataUri,
- new long[]{masterKeyId});
-
// Register callback to set NDEF message
mNfcAdapter.setNdefPushMessageCallback(this, this);
// Register callback to listen for message-sent success
@@ -86,9 +81,19 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
* guarantee that this activity starts when receiving a beamed message. For now, this code
* uses the tag dispatch system.
*/
- NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
- mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
- return msg;
+ // get public keyring as byte array
+ long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
+ try {
+ mSharedKeyringBytes = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId).getEncoded();
+
+ NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
+ mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
+ return msg;
+ } catch(IOException e) {
+ // not much trouble, but leave a note
+ Log.e(Constants.TAG, "Error parsing keyring: ", e);
+ return null;
+ }
}
/**
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
index 703f7e861..ae8b6d595 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
@@ -30,6 +30,7 @@ import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
@@ -38,7 +39,10 @@ import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter;
@@ -52,6 +56,7 @@ public class ViewKeyMainFragment extends Fragment implements
public static final String ARG_DATA_URI = "uri";
+ private LinearLayout mContainer;
private TextView mName;
private TextView mEmail;
private TextView mComment;
@@ -80,6 +85,7 @@ public class ViewKeyMainFragment extends Fragment implements
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_key_main_fragment, container, false);
+ mContainer = (LinearLayout) view.findViewById(R.id.container);
mName = (TextView) view.findViewById(R.id.name);
mEmail = (TextView) view.findViewById(R.id.email);
mComment = (TextView) view.findViewById(R.id.comment);
@@ -118,12 +124,16 @@ public class ViewKeyMainFragment extends Fragment implements
return;
}
+ getActivity().setProgressBarIndeterminateVisibility(Boolean.TRUE);
+ mContainer.setVisibility(View.GONE);
+
mDataUri = dataUri;
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
{ // label whether secret key is available, and edit button if it is
final long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), mDataUri);
+ // TODO do this some other way...
if (ProviderHelper.hasSecretKeyByMasterKeyId(getActivity(), masterKeyId)) {
// set this attribute. this is a LITTLE unclean, but we have the info available
// right here, so why not.
@@ -141,8 +151,7 @@ public class ViewKeyMainFragment extends Fragment implements
public void onClick(View view) {
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
editIntent.setData(
- KeychainContract
- .KeyRings.buildSecretKeyRingUri(
+ KeyRingData.buildSecretKeyRingUri(
Long.toString(masterKeyId)));
editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
startActivityForResult(editIntent, 0);
@@ -161,7 +170,7 @@ public class ViewKeyMainFragment extends Fragment implements
// TODO see todo note above, doing this here for now
mActionCertify.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
- certifyKey(KeychainContract.KeyRings.buildGenericKeyRingUri(
+ certifyKey(KeyRings.buildGenericKeyRingUri(
Long.toString(masterKeyId)
));
}
@@ -190,31 +199,26 @@ public class ViewKeyMainFragment extends Fragment implements
}
static final String[] USER_IDS_PROJECTION =
- new String[]{
- KeychainContract.UserIds._ID,
- KeychainContract.UserIds.USER_ID,
- KeychainContract.UserIds.RANK,
+ new String[] {
+ UserIds._ID,
+ UserIds.USER_ID,
+ UserIds.RANK,
};
static final int INDEX_UID_UID = 1;
- static final String USER_IDS_SORT_ORDER =
- KeychainContract.UserIds.RANK + " COLLATE LOCALIZED ASC";
-
- static final String[] KEYS_PROJECTION =
- new String[]{KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
- KeychainContract.Keys.ALGORITHM, KeychainContract.Keys.RANK,
- KeychainContract.Keys.KEY_SIZE, KeychainContract.Keys.CAN_CERTIFY,
- KeychainContract.Keys.CAN_SIGN, KeychainContract.Keys.CAN_ENCRYPT,
- KeychainContract.Keys.IS_REVOKED, KeychainContract.Keys.CREATION,
- KeychainContract.Keys.EXPIRY, KeychainContract.Keys.FINGERPRINT};
- static final String KEYS_SORT_ORDER = KeychainContract.Keys.RANK + " ASC";
+
+ static final String[] KEYS_PROJECTION = new String[] {
+ Keys._ID,
+ Keys.KEY_ID, Keys.RANK,
+ Keys.ALGORITHM, Keys.KEY_SIZE,
+ Keys.CAN_CERTIFY, Keys.CAN_ENCRYPT,
+ Keys.CAN_SIGN, Keys.IS_REVOKED,
+ Keys.CREATION, Keys.EXPIRY,
+ Keys.FINGERPRINT
+ };
static final int KEYS_INDEX_KEY_ID = 1;
- static final int KEYS_INDEX_ALGORITHM = 2;
- static final int KEYS_INDEX_RANK = 3;
+ static final int KEYS_INDEX_ALGORITHM = 3;
static final int KEYS_INDEX_KEY_SIZE = 4;
- static final int KEYS_INDEX_CAN_CERTIFY = 5;
- static final int KEYS_INDEX_CAN_SIGN = 6;
- static final int KEYS_INDEX_CAN_ENCRYPT = 7;
- static final int KEYS_INDEX_IS_REVOKED = 8;
+ static final int KEYS_INDEX_CAN_ENCRYPT = 6;
static final int KEYS_INDEX_CREATION = 9;
static final int KEYS_INDEX_EXPIRY = 10;
static final int KEYS_INDEX_FINGERPRINT = 11;
@@ -222,19 +226,18 @@ public class ViewKeyMainFragment extends Fragment implements
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_USER_IDS: {
- Uri baseUri = KeychainContract.UserIds.buildUserIdsUri(mDataUri);
+ Uri baseUri = UserIds.buildUserIdsUri(mDataUri);
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, USER_IDS_PROJECTION, null, null,
- USER_IDS_SORT_ORDER);
+ return new CursorLoader(getActivity(), baseUri, USER_IDS_PROJECTION, null, null, null);
}
case LOADER_ID_KEYS: {
- Uri baseUri = KeychainContract.Keys.buildKeysUri(mDataUri);
+ Uri baseUri = Keys.buildKeysUri(mDataUri);
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, KEYS_PROJECTION, null, null, KEYS_SORT_ORDER);
+ return new CursorLoader(getActivity(), baseUri, KEYS_PROJECTION, null, null, null);
}
default:
@@ -298,10 +301,6 @@ public class ViewKeyMainFragment extends Fragment implements
mAlgorithm.setText(algorithmStr);
byte[] fingerprintBlob = data.getBlob(KEYS_INDEX_FINGERPRINT);
- if (fingerprintBlob == null) {
- // FALLBACK for old database entries
- fingerprintBlob = ProviderHelper.getFingerprint(getActivity(), mDataUri);
- }
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
@@ -326,6 +325,8 @@ public class ViewKeyMainFragment extends Fragment implements
default:
break;
}
+ getActivity().setProgressBarIndeterminateVisibility(Boolean.FALSE);
+ mContainer.setVisibility(View.VISIBLE);
}
/**
@@ -347,7 +348,7 @@ public class ViewKeyMainFragment extends Fragment implements
private void encryptToContact(Uri dataUri) {
// TODO preselect from uri? should be feasible without trivial query
- long keyId = Long.parseLong(dataUri.getPathSegments().get(1));
+ long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
long[] encryptionKeyIds = new long[]{ keyId };
Intent intent = new Intent(getActivity(), EncryptActivity.class);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
index 9427ce0db..feaa0b4cd 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -20,8 +20,6 @@ package org.sufficientlysecure.keychain.ui.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
-import android.database.Cursor;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
@@ -35,18 +33,18 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
-import java.util.ArrayList;
+import java.util.HashMap;
public class DeleteKeyDialogFragment extends DialogFragment {
private static final String ARG_MESSENGER = "messenger";
- private static final String ARG_DELETE_KEY_RING_ROW_IDS = "delete_key_ring_row_ids";
+ private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids";
public static final int MESSAGE_OKAY = 1;
public static final int MESSAGE_ERROR = 0;
@@ -63,13 +61,13 @@ public class DeleteKeyDialogFragment extends DialogFragment {
/**
* Creates new instance of this delete file dialog fragment
*/
- public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] keyRingRowIds
- ) {
+ public static DeleteKeyDialogFragment newInstance(Messenger messenger,
+ long[] masterKeyIds) {
DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_MESSENGER, messenger);
- args.putLongArray(ARG_DELETE_KEY_RING_ROW_IDS, keyRingRowIds);
+ args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds);
//We don't need the key type
frag.setArguments(args);
@@ -84,7 +82,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
final FragmentActivity activity = getActivity();
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
- final long[] keyRingRowIds = getArguments().getLongArray(ARG_DELETE_KEY_RING_ROW_IDS);
+ final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@@ -98,35 +96,27 @@ public class DeleteKeyDialogFragment extends DialogFragment {
mCheckDeleteSecret = (CheckBox) mInflateView.findViewById(R.id.checkDeleteSecret);
builder.setTitle(R.string.warning);
- /* TODO! redo
- //If only a single key has been selected
- if (keyRingRowIds.length == 1) {
- Uri dataUri;
- ArrayList<Long> publicKeyRings; //Any one will do
+ // If only a single key has been selected
+ if (masterKeyIds.length == 1) {
mIsSingleSelection = true;
- long selectedRow = keyRingRowIds[0];
- long keyType;
- publicKeyRings = ProviderHelper.getPublicKeyRingsRowIds(activity);
-
- if (publicKeyRings.contains(selectedRow)) {
- //TODO Should be a better method to do this other than getting all the KeyRings
- dataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(String.valueOf(selectedRow));
- keyType = Id.type.public_key;
- } else {
- dataUri = KeychainContract.KeyRings.buildSecretKeyRingsUri(String.valueOf(selectedRow));
- keyType = Id.type.secret_key;
- }
+ long masterKeyId = masterKeyIds[0];
+
+ HashMap<String, Object> data = ProviderHelper.getUnifiedData(activity, masterKeyId, new String[]{
+ KeyRings.USER_ID,
+ KeyRings.HAS_SECRET
+ });
+ String userId = (String) data.get(KeyRings.USER_ID);
+ boolean hasSecret = ((Long) data.get(KeyRings.HAS_SECRET)) == 1;
- String userId = ProviderHelper.getUserId(activity, dataUri);
- // Hide the Checkbox and TextView since this is a single selection,
- // user will be notified thru message
+ // Hide the Checkbox and TextView since this is a single selection,user will be notified through message
mDeleteSecretKeyView.setVisibility(View.GONE);
// Set message depending on which key it is.
- mMainMessage.setText(getString(keyType == Id.type.secret_key ?
- R.string.secret_key_deletion_confirmation :
- R.string.public_key_deletetion_confirmation, userId));
+ mMainMessage.setText(getString(
+ hasSecret ? R.string.secret_key_deletion_confirmation
+ : R.string.public_key_deletetion_confirmation,
+ userId));
} else {
mDeleteSecretKeyView.setVisibility(View.VISIBLE);
mMainMessage.setText(R.string.key_deletion_confirmation_multi);
@@ -137,75 +127,27 @@ public class DeleteKeyDialogFragment extends DialogFragment {
builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- Uri queryUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri();
- String[] projection = new String[]{
- KeychainContract.KeyRings.MASTER_KEY_ID, // 0
- KeychainContract.KeyRings.TYPE// 1
- };
-
- // make selection with all entries where _ID is one of the given row ids
- String selection = KeychainDatabase.Tables.KEY_RINGS + "." +
- KeychainContract.KeyRings._ID + " IN(";
- String selectionIDs = "";
- for (int i = 0; i < keyRingRowIds.length; i++) {
- selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'";
- if (i + 1 < keyRingRowIds.length) {
- selectionIDs += ",";
- }
- }
- selection += selectionIDs + ")";
-
- Cursor cursor = activity.getContentResolver().query(queryUri, projection,
- selection, null, null);
-
-
- long masterKeyId;
- long keyType;
- boolean isSuccessfullyDeleted;
- try {
- isSuccessfullyDeleted = false;
- while (cursor != null && cursor.moveToNext()) {
- masterKeyId = cursor.getLong(0);
- keyType = cursor.getLong(1);
-
- Log.d(Constants.TAG, "masterKeyId: " + masterKeyId +
- ", keyType:" +
- (keyType == KeychainContract.KeyTypes.PUBLIC ?
- "Public" : "Private"));
-
- if (keyType == KeychainContract.KeyTypes.SECRET) {
- if (mCheckDeleteSecret.isChecked() || mIsSingleSelection) {
- ProviderHelper.deleteUnifiedKeyRing(activity,
- String.valueOf(masterKeyId), true);
- }
- } else {
- ProviderHelper.deleteUnifiedKeyRing(activity,
- String.valueOf(masterKeyId), false);
- }
- }
-
- //Check if the selected rows have actually been deleted
- cursor = activity.getContentResolver().query(
- queryUri, projection, selection, null, null);
- if (cursor == null || cursor.getCount() == 0 ||
- !mCheckDeleteSecret.isChecked()) {
- isSuccessfullyDeleted = true;
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
+
+ boolean success = false;
+ for(long masterKeyId : masterKeyIds) {
+ int count = activity.getContentResolver().delete(
+ KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null
+ );
+ if(count > 0)
+ success = true;
}
dismiss();
- if (isSuccessfullyDeleted) {
+ if (success) {
sendMessageToHandler(MESSAGE_OKAY, null);
} else {
sendMessageToHandler(MESSAGE_ERROR, null);
}
}
- });
+
+ }
+ );
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
@@ -213,7 +155,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
dismiss();
}
});
- */
+
return builder.create();
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
index b8db470b4..05b571362 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
@@ -116,7 +116,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
secretKey = null;
alert.setMessage(R.string.passphrase_for_symmetric_encryption);
} else {
- secretKey = ProviderHelper.getPGPSecretKeyByKeyId(activity, secretKeyId);
+ secretKey = ProviderHelper.getPGPSecretKeyRing(activity, secretKeyId).getSecretKey();
if (secretKey == null) {
alert.setTitle(R.string.title_key_not_found);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
index 18403837a..b55645732 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
@@ -31,6 +31,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.QrCodeUtils;
@@ -89,22 +90,26 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
if (mFingerprintOnly) {
alert.setPositiveButton(R.string.btn_okay, null);
- byte[] fingerprintBlob = ProviderHelper.getFingerprint(getActivity(), dataUri);
- String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
+ Object blob = ProviderHelper.getGenericData(
+ getActivity(), KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
+ KeychainContract.Keys.FINGERPRINT);
+ if(!(blob instanceof byte[])) {
+ // TODO error handling?!
+ return null;
+ }
+ String fingerprint = PgpKeyHelper.convertFingerprintToHex((byte[]) blob);
mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint);
-
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
setQrCode(content);
} else {
mText.setText(R.string.share_qr_code_dialog_start);
- // TODO
+ // TODO works, but
long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
-
// get public keyring as ascii armored string
ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
- getActivity(), dataUri, new long[]{masterKeyId});
+ getActivity(), new long[] { masterKeyId });
// TODO: binary?