From a7eff41ced8b5622f6ed96a5b834677314ae7ca8 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 3 Apr 2014 01:34:35 +0200 Subject: [PATCH] Break a lot of stuff. Also, database redesign. Change entire database design. This introduces a lot of changes, notably all URIs and almost all projections. Some features (like key deletion) have been simply commented out for now since they need serious reconsideration. There are a couple of new TODOs marking places where more work is needed. The migration path works fine from what I tested. The old database is not deleted for now, ie, it is reimported at every start of the application making all intermediate changes transient. Tested and working (for me): - All activities in the main drawer - Multiselect and Search - ViewKeyActivity, with and without secret key available - CertifyKeyActivity - SelectSecretKeyActivity (from CertifyKeyActivity) - SelectPublicKeyActivity (from encrypt activity) What doesn't work: - Actually certifying keys (pending a TODO in ProviderHelper) - Importing keys doesn't preserve secret keys - "Encrypt to this contact" doesn't pass key - Editing keys. All controls are disabled, I'm not sure why... (is this even my fault?) - Deleting keys What I didn't test: - Key export - API stuff - Creating keys (since editing doesn't even work) --- .../keychain/pgp/PgpDecryptVerify.java | 8 +- .../keychain/pgp/PgpHelper.java | 2 +- .../keychain/pgp/PgpImportExport.java | 4 +- .../keychain/pgp/PgpKeyHelper.java | 25 +- .../keychain/pgp/PgpSignEncrypt.java | 4 +- .../keychain/provider/KeychainContract.java | 173 ++-- .../keychain/provider/KeychainDatabase.java | 223 +++-- .../keychain/provider/KeychainProvider.java | 850 ++++-------------- .../provider/KeychainServiceBlobDatabase.java | 2 +- .../keychain/provider/ProviderHelper.java | 417 ++------- .../keychain/remote/OpenPgpService.java | 2 +- .../service/KeychainIntentService.java | 15 +- .../service/PassphraseCacheService.java | 5 +- .../keychain/ui/CertifyKeyActivity.java | 33 +- .../keychain/ui/EditKeyActivity.java | 4 +- .../ui/EncryptAsymmetricFragment.java | 6 +- .../keychain/ui/KeyListFragment.java | 31 +- .../keychain/ui/SelectPublicKeyFragment.java | 34 +- .../keychain/ui/SelectSecretKeyFragment.java | 52 +- .../ui/SelectSecretKeyLayoutFragment.java | 15 +- .../keychain/ui/ViewKeyActivity.java | 11 +- .../keychain/ui/ViewKeyMainFragment.java | 44 +- .../ui/adapter/ViewKeyKeysAdapter.java | 6 +- .../ui/dialog/DeleteKeyDialogFragment.java | 2 + .../ui/dialog/PassphraseDialogFragment.java | 7 +- 25 files changed, 603 insertions(+), 1372 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 29255fbbe..43a1d9aab 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 @@ -239,7 +239,7 @@ public class PgpDecryptVerify { if (mEnforcedKeyId != 0) { // TODO: improve this code! get master key directly! PGPSecretKeyRing secretKeyRing = - ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, encData.getKeyID()); + ProviderHelper.getPGPSecretKeyRingWithKeyId(mContext, encData.getKeyID()); long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID(); Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID()); Log.d(Constants.TAG, "enforcedKeyId: " + mEnforcedKeyId); @@ -371,7 +371,7 @@ public class PgpDecryptVerify { signatureIndex = i; signatureKeyId = signature.getKeyID(); String userId = null; - PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId( + PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId( mContext, signatureKeyId); if (signKeyRing != null) { userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing)); @@ -555,7 +555,7 @@ public class PgpDecryptVerify { } else { signatureKeyId = signature.getKeyID(); String userId = null; - PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(mContext, + PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(mContext, signatureKeyId); if (signKeyRing != null) { userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing)); @@ -619,7 +619,7 @@ public class PgpDecryptVerify { long signatureKeyId = signature.getKeyID(); boolean validKeyBinding = false; - PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context, + PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(context, signatureKeyId); PGPPublicKey mKey = null; if (signKeyRing != null) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index cc40afbac..60967a0d1 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -97,7 +97,7 @@ public class PgpHelper { if (obj instanceof PGPPublicKeyEncryptedData) { gotAsymmetricEncryption = true; PGPPublicKeyEncryptedData pbe = (PGPPublicKeyEncryptedData) obj; - secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, pbe.getKeyID()); + secretKey = ProviderHelper.getPGPSecretKeyRing(context, pbe.getKeyID()).getSecretKey(); if (secretKey != null) { break; } 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 0e0fdec83..e2ea91470 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 @@ -184,7 +184,7 @@ public class PgpImportExport { updateProgress(progress * 100 / masterKeyIdsSize, 100); PGPPublicKeyRing publicKeyRing = - ProviderHelper.getPGPPublicKeyRingByMasterKeyId(mContext, pubKeyMasterId); + ProviderHelper.getPGPPublicKeyRing(mContext, pubKeyMasterId); if (publicKeyRing != null) { publicKeyRing.encode(arOutStream); @@ -207,7 +207,7 @@ public class PgpImportExport { updateProgress(progress * 100 / masterKeyIdsSize, 100); PGPSecretKeyRing secretKeyRing = - ProviderHelper.getPGPSecretKeyRingByMasterKeyId(mContext, secretKeyMasterId); + ProviderHelper.getPGPSecretKeyRing(mContext, secretKeyMasterId); if (secretKeyRing != null) { secretKeyRing.encode(arOutStream); 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 b4bf0747f..658b9460b 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 @@ -219,8 +219,7 @@ public class PgpKeyHelper { } public static PGPPublicKey getEncryptPublicKey(Context context, long masterKeyId) { - PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context, - masterKeyId); + PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRing(context, masterKeyId); if (keyRing == null) { Log.e(Constants.TAG, "keyRing is null!"); return null; @@ -234,8 +233,7 @@ public class PgpKeyHelper { } public static PGPSecretKey getCertificationKey(Context context, long masterKeyId) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context, - masterKeyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId); if (keyRing == null) { return null; } @@ -247,8 +245,7 @@ public class PgpKeyHelper { } public static PGPSecretKey getSigningKey(Context context, long masterKeyId) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context, - masterKeyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId); if (keyRing == null) { return null; } @@ -491,21 +488,6 @@ public class PgpKeyHelper { return algorithmStr + ", " + keySize + " bit"; } - public static String getFingerPrint(Context context, long keyId) { - PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId); - // if it is no public key get it from your own keys... - if (key == null) { - PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId); - if (secretKey == null) { - Log.e(Constants.TAG, "Key could not be found!"); - return null; - } - key = secretKey.getPublicKey(); - } - - return convertFingerprintToHex(key.getFingerprint()); - } - /** * Converts fingerprint to hex (optional: with whitespaces after 4 characters) *

@@ -513,7 +495,6 @@ public class PgpKeyHelper { * better differentiate between numbers and letters when letters are lowercase. * * @param fingerprint - * @param split split into 4 character chunks * @return */ public static String convertFingerprintToHex(byte[] fingerprint) { 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 6d80c154b..a16ebdab8 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 @@ -214,7 +214,7 @@ public class PgpSignEncrypt { PGPSecretKeyRing signingKeyRing = null; PGPPrivateKey signaturePrivateKey = null; if (enableSignature) { - signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, mSignatureKeyId); + signingKeyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(mContext, mSignatureKeyId); signingKey = PgpKeyHelper.getSigningKey(mContext, mSignatureKeyId); if (signingKey == null) { throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed)); @@ -444,7 +444,7 @@ public class PgpSignEncrypt { } PGPSecretKeyRing signingKeyRing = - ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, mSignatureKeyId); + ProviderHelper.getPGPSecretKeyRingWithKeyId(mContext, mSignatureKeyId); PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(mContext, mSignatureKeyId); if (signingKey == null) { throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed)); 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 e7b31bf65..fcf8f7962 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 @@ -26,32 +26,32 @@ public class KeychainContract { interface KeyRingsColumns { String MASTER_KEY_ID = "master_key_id"; // not a database id - String TYPE = "type"; // see KeyTypes String KEY_RING_DATA = "key_ring_data"; // PGPPublicKeyRing / PGPSecretKeyRing blob } interface KeysColumns { + String MASTER_KEY_ID = "master_key_id"; // not a database id + String RANK = "rank"; + String KEY_ID = "key_id"; // not a database id - String TYPE = "type"; // see KeyTypes - String IS_MASTER_KEY = "is_master_key"; String ALGORITHM = "algorithm"; + String FINGERPRINT = "fingerprint"; + String KEY_SIZE = "key_size"; - String CAN_CERTIFY = "can_certify"; String CAN_SIGN = "can_sign"; String CAN_ENCRYPT = "can_encrypt"; + String CAN_CERTIFY = "can_certify"; String IS_REVOKED = "is_revoked"; + String CREATION = "creation"; String EXPIRY = "expiry"; - String KEY_RING_ROW_ID = "key_ring_row_id"; // foreign key to key_rings._ID - String KEY_DATA = "key_data"; // PGPPublicKey/PGPSecretKey blob - String RANK = "rank"; - String FINGERPRINT = "fingerprint"; } interface UserIdsColumns { - String KEY_RING_ROW_ID = "key_ring_row_id"; // foreign key to key_rings._ID + String MASTER_KEY_ID = "master_key_id"; // foreign key to key_rings._ID String USER_ID = "user_id"; // not a database id - String RANK = "rank"; + String RANK = "rank"; // ONLY used for sorting! no key, no nothing! + String IS_PRIMARY = "is_primary"; } interface ApiAppsColumns { @@ -81,14 +81,15 @@ public class KeychainContract { public static final String BASE_KEY_RINGS = "key_rings"; public static final String BASE_DATA = "data"; - public static final String PATH_PUBLIC = "public"; - public static final String PATH_SECRET = "secret"; + 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_PUBLIC = "public"; + public static final String PATH_SECRET = "secret"; public static final String PATH_USER_IDS = "user_ids"; public static final String PATH_KEYS = "keys"; @@ -102,72 +103,43 @@ public class KeychainContract { /** * Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.key_ring"; + 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.thialfihar.apg.key_ring"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.key_ring"; public static Uri buildUnifiedKeyRingsUri() { - return CONTENT_URI; + 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 buildPublicKeyRingsUri() { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).build(); + public static Uri buildGenericKeyRingUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).build(); } - public static Uri buildPublicKeyRingsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId).build(); + public static Uri buildPublicKeyRingUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_PUBLIC).build(); + } + public static Uri buildPublicKeyRingUri(Uri uri) { + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_PUBLIC).build(); } - public static Uri buildPublicKeyRingsByMasterKeyIdUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC) - .appendPath(PATH_BY_MASTER_KEY_ID).appendPath(masterKeyId).build(); + public static Uri buildSecretKeyRingUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_SECRET).build(); + } + public static Uri buildSecretKeyRingUri(Uri uri) { + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_SECRET).build(); } - public static Uri buildPublicKeyRingsByKeyIdUri(String keyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(PATH_BY_KEY_ID) - .appendPath(keyId).build(); + public static Uri buildUnifiedKeyRingUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_UNIFIED).build(); } - - public static Uri buildPublicKeyRingsByEmailsUri(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(PATH_BY_EMAILS) - .appendPath(emails).build(); - } - - public static Uri buildPublicKeyRingsByLikeEmailUri(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(PATH_BY_LIKE_EMAIL) - .appendPath(emails).build(); - } - - public static Uri buildSecretKeyRingsUri() { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).build(); - } - - public static Uri buildSecretKeyRingsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId).build(); - } - - public static Uri buildSecretKeyRingsByMasterKeyIdUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET) - .appendPath(PATH_BY_MASTER_KEY_ID).appendPath(masterKeyId).build(); - } - - public static Uri buildSecretKeyRingsByKeyIdUri(String keyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_KEY_ID) - .appendPath(keyId).build(); - } - - public static Uri buildSecretKeyRingsByEmailsUri(String emails) { - // TODO: encoded? - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_EMAILS) - .appendPath(emails).build(); - } - - public static Uri buildSecretKeyRingsByLikeEmails(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_LIKE_EMAIL) - .appendPath(emails).build(); + public static Uri buildUnifiedKeyRingUri(Uri uri) { + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_UNIFIED).build(); } } @@ -178,40 +150,20 @@ public class KeychainContract { /** * Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.key"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.key"; /** * Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.key"; - public static Uri buildPublicKeysUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).build(); + public static Uri buildKeysUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_KEYS).build(); + } + public static Uri buildKeysUri(Uri uri) { + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_KEYS).build(); } - public static Uri buildPublicKeysUri(String keyRingRowId, String keyRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).appendPath(keyRowId).build(); - } - - public static Uri buildSecretKeysUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).build(); - } - - public static Uri buildSecretKeysUri(String keyRingRowId, String keyRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).appendPath(keyRowId).build(); - } - - public static Uri buildKeysUri(Uri keyRingUri) { - return keyRingUri.buildUpon().appendPath(PATH_KEYS).build(); - } - - public static Uri buildKeysUri(Uri keyRingUri, String keyRowId) { - return keyRingUri.buildUpon().appendPath(PATH_KEYS).appendPath(keyRowId).build(); - } } public static class UserIds implements UserIdsColumns, BaseColumns { @@ -221,39 +173,18 @@ public class KeychainContract { /** * Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.user_id"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.user_id"; /** * Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.user_id"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.user_id"; - public static Uri buildPublicUserIdsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).build(); + public static Uri buildUserIdsUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_USER_IDS).build(); } - - public static Uri buildPublicUserIdsUri(String keyRingRowId, String userIdRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).appendPath(userIdRowId).build(); - } - - public static Uri buildSecretUserIdsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).build(); - } - - public static Uri buildSecretUserIdsUri(String keyRingRowId, String userIdRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).appendPath(userIdRowId).build(); - } - - public static Uri buildUserIdsUri(Uri keyRingUri) { - return keyRingUri.buildUpon().appendPath(PATH_USER_IDS).build(); - } - - public static Uri buildUserIdsUri(Uri keyRingUri, String userIdRowId) { - return keyRingUri.buildUpon().appendPath(PATH_USER_IDS).appendPath(userIdRowId).build(); + public static Uri buildUserIdsUri(Uri uri) { + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_USER_IDS).build(); } } @@ -264,12 +195,12 @@ public class KeychainContract { /** * Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_apps"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.api_apps"; /** * Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_app"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.api_app"; public static Uri buildByPackageNameUri(String packageName) { return CONTENT_URI.buildUpon().appendEncodedPath(packageName).build(); @@ -283,12 +214,12 @@ public class KeychainContract { /** * Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_app.accounts"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.api_app.accounts"; /** * Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_app.account"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.api_app.account"; public static Uri buildBaseUri(String packageName) { return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendPath(PATH_ACCOUNTS) 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 8c33844b2..055957eda 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 @@ -18,11 +18,16 @@ package org.sufficientlysecure.keychain.provider; import android.content.Context; +import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.provider.BaseColumns; +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.spongycastle.openpgp.PGPSecretKeyRing; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; @@ -30,51 +35,72 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; import org.sufficientlysecure.keychain.util.Log; +import java.io.IOException; +import java.util.Arrays; + public class KeychainDatabase extends SQLiteOpenHelper { - private static final String DATABASE_NAME = "apg.db"; - private static final int DATABASE_VERSION = 8; + private static final String DATABASE_NAME = "openkeychain.db"; + private static final int DATABASE_VERSION = 1; + static Boolean apg_hack = false; public interface Tables { - String KEY_RINGS = "key_rings"; + String KEY_RINGS_PUBLIC = "keyrings_public"; + String KEY_RINGS_SECRET = "keyrings_secret"; String KEYS = "keys"; String USER_IDS = "user_ids"; String API_APPS = "api_apps"; String API_ACCOUNTS = "api_accounts"; } - private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS - + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + KeyRingsColumns.MASTER_KEY_ID + " INT64, " - + KeyRingsColumns.TYPE + " INTEGER, " - + KeyRingsColumns.KEY_RING_DATA + " BLOB)"; + private static final String CREATE_KEYRINGS_PUBLIC = + "CREATE TABLE IF NOT EXISTS keyrings_public (" + + KeyRingsColumns.MASTER_KEY_ID + " INTEGER PRIMARY KEY," + + KeyRingsColumns.KEY_RING_DATA + " BLOB" + + ")"; - private static final String CREATE_KEYS = "CREATE TABLE IF NOT EXISTS " + Tables.KEYS + " (" - + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + KeysColumns.KEY_ID + " INT64, " - + KeysColumns.TYPE + " INTEGER, " - + KeysColumns.IS_MASTER_KEY + " INTEGER, " - + KeysColumns.ALGORITHM + " INTEGER, " - + KeysColumns.KEY_SIZE + " INTEGER, " - + KeysColumns.CAN_CERTIFY + " INTEGER, " - + KeysColumns.CAN_SIGN + " INTEGER, " - + KeysColumns.CAN_ENCRYPT + " INTEGER, " - + KeysColumns.IS_REVOKED + " INTEGER, " - + KeysColumns.CREATION + " INTEGER, " - + KeysColumns.EXPIRY + " INTEGER, " - + KeysColumns.KEY_DATA + " BLOB," - + KeysColumns.RANK + " INTEGER, " - + KeysColumns.FINGERPRINT + " BLOB, " - + KeysColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, " - + "FOREIGN KEY(" + KeysColumns.KEY_RING_ROW_ID + ") REFERENCES " - + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)"; + private static final String CREATE_KEYRINGS_SECRET = + "CREATE TABLE IF NOT EXISTS keyrings_secret (" + + KeyRingsColumns.MASTER_KEY_ID + " INTEGER PRIMARY KEY," + + KeyRingsColumns.KEY_RING_DATA + " BLOB," + + "FOREIGN KEY(" + KeyRingsColumns.MASTER_KEY_ID + ") " + + "REFERENCES keyrings_public(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + + ")"; - private static final String CREATE_USER_IDS = "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS - + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + UserIdsColumns.USER_ID + " TEXT, " - + UserIdsColumns.RANK + " INTEGER, " - + UserIdsColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, " - + "FOREIGN KEY(" + UserIdsColumns.KEY_RING_ROW_ID + ") REFERENCES " - + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)"; + private static final String CREATE_KEYS = + "CREATE TABLE IF NOT EXISTS " + Tables.KEYS + " (" + + KeysColumns.MASTER_KEY_ID + " INTEGER, " + + KeysColumns.RANK + " INTEGER, " + + + KeysColumns.KEY_ID + " INTEGER, " + + KeysColumns.KEY_SIZE + " INTEGER, " + + KeysColumns.ALGORITHM + " INTEGER, " + + KeysColumns.FINGERPRINT + " BLOB, " + + + KeysColumns.CAN_CERTIFY + " BOOLEAN, " + + KeysColumns.CAN_SIGN + " BOOLEAN, " + + KeysColumns.CAN_ENCRYPT + " BOOLEAN, " + + KeysColumns.IS_REVOKED + " BOOLEAN, " + + + KeysColumns.CREATION + " INTEGER, " + + KeysColumns.EXPIRY + " INTEGER, " + + + "PRIMARY KEY(" + KeysColumns.MASTER_KEY_ID + ", " + KeysColumns.RANK + ")," + + "FOREIGN KEY(" + KeysColumns.MASTER_KEY_ID + ") REFERENCES " + + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + + ")"; + + private static final String CREATE_USER_IDS = + "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS + "(" + + UserIdsColumns.MASTER_KEY_ID + " INTEGER, " + + UserIdsColumns.USER_ID + " CHARMANDER, " + + + UserIdsColumns.IS_PRIMARY + " BOOLEAN, " + + UserIdsColumns.RANK+ " INTEGER, " + + + "PRIMARY KEY(" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.USER_ID + ")," + + "FOREIGN KEY(" + UserIdsColumns.MASTER_KEY_ID + ") REFERENCES " + + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + + ")"; private static final String CREATE_API_APPS = "CREATE TABLE IF NOT EXISTS " + Tables.API_APPS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -96,13 +122,27 @@ 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) { + if(!apg_hack) { + iAmIt = true; + apg_hack = true; + } + } + // if it's us, do the import + if(iAmIt) + checkAndImportApg(context); } @Override public void onCreate(SQLiteDatabase db) { Log.w(Constants.TAG, "Creating database..."); - db.execSQL(CREATE_KEY_RINGS); + db.execSQL(CREATE_KEYRINGS_PUBLIC); + db.execSQL(CREATE_KEYRINGS_SECRET); db.execSQL(CREATE_KEYS); db.execSQL(CREATE_USER_IDS); db.execSQL(CREATE_API_APPS); @@ -119,44 +159,91 @@ public class KeychainDatabase extends SQLiteOpenHelper { } @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(Constants.TAG, "Upgrading database from version " + oldVersion + " to " + newVersion); + public void onUpgrade(SQLiteDatabase db, int old, int nu) { + // don't care (this is version 1) + } - // Upgrade from oldVersion through all cases to newest one - for (int version = oldVersion; version < newVersion; ++version) { - Log.w(Constants.TAG, "Upgrading database to version " + version); + /** This method tries to import data from a provided database. + * + * The sole assumptions made on this db are that there is a key_rings table + * with a key_ring_data and a type column, the latter of which should be bigger + * for secret keys. + */ + public void checkAndImportApg(Context context) { - switch (version) { - case 3: - db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.CAN_CERTIFY - + " INTEGER DEFAULT 0;"); - db.execSQL("UPDATE " + Tables.KEYS + " SET " + KeysColumns.CAN_CERTIFY - + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;"); + boolean hasApgDb = false; { + // It's the Java way =( + String[] dbs = context.databaseList(); + for(String db : dbs) { + if(db.equals("apg.db")) { + hasApgDb = true; break; - case 4: - db.execSQL(CREATE_API_APPS); - break; - case 5: - // new column: package_signature - db.execSQL("DROP TABLE IF EXISTS " + Tables.API_APPS); - db.execSQL(CREATE_API_APPS); - break; - case 6: - // new column: fingerprint - db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.FINGERPRINT - + " BLOB;"); - break; - case 7: - // new db layout for api apps - db.execSQL("DROP TABLE IF EXISTS " + Tables.API_APPS); - db.execSQL(CREATE_API_APPS); - db.execSQL(CREATE_API_APPS_ACCOUNTS); - break; - default: - break; - + } } } + + if(!hasApgDb) + return; + + Log.d(Constants.TAG, "apg.db exists! Importing..."); + + SQLiteDatabase db = new SQLiteOpenHelper(context, "apg.db", null, 1) { + @Override + public void onCreate(SQLiteDatabase db) { + // should never happen + assert false; + } + @Override + public void onDowngrade(SQLiteDatabase db, int old, int nu) { + // don't care + } + @Override + public void onUpgrade(SQLiteDatabase db, int old, int nu) { + // don't care either + } + }.getReadableDatabase(); + + // kill current! + { // TODO don't kill current. + Log.d(Constants.TAG, "Truncating db..."); + SQLiteDatabase d = getWritableDatabase(); + d.execSQL("DELETE FROM keyrings_public"); + d.close(); + Log.d(Constants.TAG, "Ok."); + } + + Cursor c = db.rawQuery("SELECT key_ring_data FROM key_rings ORDER BY type ASC", null); + try { + // import from old database + Log.d(Constants.TAG, "Importing " + c.getCount() + " keyrings from apg.db..."); + for(int i = 0; i < c.getCount(); i++) { + c.moveToPosition(i); + byte[] data = c.getBlob(0); + PGPKeyRing ring = PgpConversionHelper.BytesToPGPKeyRing(data); + if(ring instanceof PGPPublicKeyRing) + ProviderHelper.saveKeyRing(context, (PGPPublicKeyRing) ring); + else if(ring instanceof PGPSecretKeyRing) + ProviderHelper.saveKeyRing(context, (PGPSecretKeyRing) ring); + else { + Log.e(Constants.TAG, "Unknown blob data type!"); + } + } + + } catch(IOException e) { + Log.e(Constants.TAG, "Error importing apg db!", e); + return; + } finally { + if(c != null) + c.close(); + if(db != null) + db.close(); + } + + // TODO delete old db, if we are sure this works + // context.deleteDatabase("apg.db"); + Log.d(Constants.TAG, "All done, (not) deleting apg.db"); + + } } 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 1c5e3ab36..39ea083fa 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 @@ -52,40 +52,19 @@ public class KeychainProvider extends ContentProvider { // public static final String EXTRA_BROADCAST_KEY_TYPE = "key_type"; // public static final String EXTRA_BROADCAST_CONTENT_ITEM_TYPE = "contentItemType"; - private static final int PUBLIC_KEY_RING = 101; - private static final int PUBLIC_KEY_RING_BY_ROW_ID = 102; - private static final int PUBLIC_KEY_RING_BY_MASTER_KEY_ID = 103; - private static final int PUBLIC_KEY_RING_BY_KEY_ID = 104; - private static final int PUBLIC_KEY_RING_BY_EMAILS = 105; - private static final int PUBLIC_KEY_RING_BY_LIKE_EMAIL = 106; + private static final int KEY_RINGS_UNIFIED = 101; - private static final int PUBLIC_KEY_RING_KEY = 111; - private static final int PUBLIC_KEY_RING_KEY_BY_ROW_ID = 112; - - private static final int PUBLIC_KEY_RING_USER_ID = 121; - private static final int PUBLIC_KEY_RING_USER_ID_BY_ROW_ID = 122; - private static final int PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID = 123; - - private static final int SECRET_KEY_RING = 201; - private static final int SECRET_KEY_RING_BY_ROW_ID = 202; - private static final int SECRET_KEY_RING_BY_MASTER_KEY_ID = 203; - private static final int SECRET_KEY_RING_BY_KEY_ID = 204; - private static final int SECRET_KEY_RING_BY_EMAILS = 205; - private static final int SECRET_KEY_RING_BY_LIKE_EMAIL = 206; - - private static final int SECRET_KEY_RING_KEY = 211; - private static final int SECRET_KEY_RING_KEY_BY_ROW_ID = 212; - - private static final int SECRET_KEY_RING_USER_ID = 221; - private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222; + private static final int KEY_RING_UNIFIED = 200; + private static final int KEY_RING_KEYS = 201; + private static final int KEY_RING_USER_IDS = 202; + private static final int KEY_RING_PUBLIC = 203; + private static final int KEY_RING_SECRET = 204; private static final int API_APPS = 301; private static final int API_APPS_BY_PACKAGE_NAME = 303; private static final int API_ACCOUNTS = 304; private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 306; - private static final int UNIFIED_KEY_RING = 401; - // private static final int DATA_STREAM = 401; protected UriMatcher mUriMatcher; @@ -100,142 +79,42 @@ public class KeychainProvider extends ContentProvider { String authority = KeychainContract.CONTENT_AUTHORITY; /** - * unified key rings + * select from key_ring * *

-         * key_rings
+         * key_rings/unified
          * 
*/ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS, UNIFIED_KEY_RING); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + + "/" + KeychainContract.PATH_UNIFIED, + KEY_RINGS_UNIFIED); /** - * public key rings + * select from key_ring * *
-         * key_rings/public
-         * key_rings/public/#
-         * key_rings/public/master_key_id/_
-         * key_rings/public/key_id/_
-         * key_rings/public/emails/_
-         * key_rings/public/like_email/_
+         * key_rings/_/unified
+         * key_rings/_/keys
+         * key_rings/_/user_ids
+         * key_rings/_/public
+         * key_rings/_/secret
          * 
*/ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC, PUBLIC_KEY_RING); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#", PUBLIC_KEY_RING_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_MASTER_KEY_ID - + "/*", PUBLIC_KEY_RING_BY_MASTER_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_KEY_ID + "/*", - PUBLIC_KEY_RING_BY_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_EMAILS + "/*", - PUBLIC_KEY_RING_BY_EMAILS); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_EMAILS, - PUBLIC_KEY_RING_BY_EMAILS); // without emails specified - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_LIKE_EMAIL + "/*", - PUBLIC_KEY_RING_BY_LIKE_EMAIL); - - /** - * public keys - * - *
-         * key_rings/public/#/keys
-         * key_rings/public/#/keys/#
-         * 
- */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_KEYS, - PUBLIC_KEY_RING_KEY); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_KEYS + "/#", - PUBLIC_KEY_RING_KEY_BY_ROW_ID); - - /** - * public user ids - * - *
-         * key_rings/public/#/user_ids
-         * key_rings/public/#/user_ids/#
-         * key_rings/public/master_key_id/#/user_ids
-         * 
- */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_USER_IDS, - PUBLIC_KEY_RING_USER_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_USER_IDS + "/#", - PUBLIC_KEY_RING_USER_ID_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" - + KeychainContract.PATH_BY_MASTER_KEY_ID + "/*/" + KeychainContract.PATH_USER_IDS, - PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID); - - /** - * secret key rings - * - *
-         * key_rings/secret
-         * key_rings/secret/#
-         * key_rings/secret/master_key_id/_
-         * key_rings/secret/key_id/_
-         * key_rings/secret/emails/_
-         * key_rings/secret/like_email/_
-         * 
- */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET, SECRET_KEY_RING); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#", SECRET_KEY_RING_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_MASTER_KEY_ID - + "/*", SECRET_KEY_RING_BY_MASTER_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_KEY_ID + "/*", - SECRET_KEY_RING_BY_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_EMAILS + "/*", - SECRET_KEY_RING_BY_EMAILS); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_EMAILS, - SECRET_KEY_RING_BY_EMAILS); // without emails specified - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_LIKE_EMAIL + "/*", - SECRET_KEY_RING_BY_LIKE_EMAIL); - - /** - * secret keys - * - *
-         * key_rings/secret/#/keys
-         * key_rings/secret/#/keys/#
-         * 
- */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_KEYS, - SECRET_KEY_RING_KEY); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_KEYS + "/#", - SECRET_KEY_RING_KEY_BY_ROW_ID); - - /** - * secret user ids - * - *
-         * key_rings/secret/#/user_ids
-         * key_rings/secret/#/user_ids/#
-         * 
- */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_USER_IDS, - SECRET_KEY_RING_USER_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_USER_IDS + "/#", - SECRET_KEY_RING_USER_ID_BY_ROW_ID); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + + KeychainContract.PATH_UNIFIED, + KEY_RING_UNIFIED); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + + KeychainContract.PATH_KEYS, + KEY_RING_KEYS); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + + KeychainContract.PATH_USER_IDS, + KEY_RING_USER_IDS); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + + KeychainContract.PATH_PUBLIC, + KEY_RING_PUBLIC); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + + KeychainContract.PATH_SECRET, + KEY_RING_SECRET); /** * API apps @@ -287,38 +166,17 @@ public class KeychainProvider extends ContentProvider { public String getType(Uri uri) { final int match = mUriMatcher.match(uri); switch (match) { - case PUBLIC_KEY_RING: - case PUBLIC_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - case SECRET_KEY_RING: - case SECRET_KEY_RING_BY_EMAILS: - case SECRET_KEY_RING_BY_LIKE_EMAIL: - return KeyRings.CONTENT_TYPE; - - case PUBLIC_KEY_RING_BY_ROW_ID: - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - case SECRET_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_KEY_ID: + case KEY_RING_PUBLIC: return KeyRings.CONTENT_ITEM_TYPE; - case PUBLIC_KEY_RING_KEY: - case SECRET_KEY_RING_KEY: + case KEY_RING_KEYS: return Keys.CONTENT_TYPE; - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - return Keys.CONTENT_ITEM_TYPE; - - case PUBLIC_KEY_RING_USER_ID: - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID: - case SECRET_KEY_RING_USER_ID: + case KEY_RING_USER_IDS: return UserIds.CONTENT_TYPE; - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - return UserIds.CONTENT_ITEM_TYPE; + case KEY_RING_SECRET: + return KeyRings.CONTENT_ITEM_TYPE; case API_APPS: return ApiApps.CONTENT_TYPE; @@ -337,175 +195,9 @@ public class KeychainProvider extends ContentProvider { } } - /** - * Returns type of the query (secret/public) - * - * @param match - * @return - */ - private int getKeyType(int match) { - int type; - switch (match) { - case PUBLIC_KEY_RING: - case PUBLIC_KEY_RING_BY_ROW_ID: - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - case PUBLIC_KEY_RING_KEY: - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case PUBLIC_KEY_RING_USER_ID: - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID: - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - type = KeyTypes.PUBLIC; - break; - - case SECRET_KEY_RING: - case SECRET_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_KEY_ID: - case SECRET_KEY_RING_BY_EMAILS: - case SECRET_KEY_RING_BY_LIKE_EMAIL: - case SECRET_KEY_RING_KEY: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - type = KeyTypes.SECRET; - break; - - default: - Log.e(Constants.TAG, "Unknown match " + match); - type = -1; - break; - } - - return type; - } - - /** - * Set result of query to specific columns, don't show blob column - * - * @return - */ - private HashMap getProjectionMapForKeyRings() { - HashMap projectionMap = new HashMap(); - - projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); - projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "." - + KeyRingsColumns.KEY_RING_DATA); - projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." - + KeyRingsColumns.MASTER_KEY_ID); - // TODO: deprecated master key id - //projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.KEY_ID); - - projectionMap.put(KeysColumns.ALGORITHM, Tables.KEYS + "." + KeysColumns.ALGORITHM); - projectionMap.put(KeysColumns.KEY_SIZE, Tables.KEYS + "." + KeysColumns.KEY_SIZE); - projectionMap.put(KeysColumns.CREATION, Tables.KEYS + "." + KeysColumns.CREATION); - projectionMap.put(KeysColumns.EXPIRY, Tables.KEYS + "." + KeysColumns.EXPIRY); - projectionMap.put(KeysColumns.KEY_RING_ROW_ID, Tables.KEYS + "." + KeysColumns.KEY_RING_ROW_ID); - projectionMap.put(KeysColumns.FINGERPRINT, Tables.KEYS + "." + KeysColumns.FINGERPRINT); - projectionMap.put(KeysColumns.IS_REVOKED, Tables.KEYS + "." + KeysColumns.IS_REVOKED); - - projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID); - - // type attribute is special: if there is any grouping, choose secret over public type - projectionMap.put(KeyRingsColumns.TYPE, - "MAX(" + Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + ") AS " + KeyRingsColumns.TYPE); - - return projectionMap; - } - - /** - * Set result of query to specific columns, don't show blob column - * - * @return - */ - private HashMap getProjectionMapForKeys() { - HashMap projectionMap = new HashMap(); - - projectionMap.put(BaseColumns._ID, BaseColumns._ID); - projectionMap.put(KeysColumns.KEY_ID, KeysColumns.KEY_ID); - projectionMap.put(KeysColumns.IS_MASTER_KEY, KeysColumns.IS_MASTER_KEY); - projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM); - projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE); - projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY); - projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN); - projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT); - projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED); - projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION); - projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY); - projectionMap.put(KeysColumns.KEY_RING_ROW_ID, KeysColumns.KEY_RING_ROW_ID); - projectionMap.put(KeysColumns.KEY_DATA, KeysColumns.KEY_DATA); - projectionMap.put(KeysColumns.RANK, KeysColumns.RANK); - projectionMap.put(KeysColumns.FINGERPRINT, KeysColumns.FINGERPRINT); - - return projectionMap; - } - - private HashMap getProjectionMapForUserIds() { - HashMap projectionMap = new HashMap(); - - projectionMap.put(BaseColumns._ID, Tables.USER_IDS + "." + BaseColumns._ID); - projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID); - projectionMap.put(UserIdsColumns.RANK, Tables.USER_IDS + "." + UserIdsColumns.RANK); - projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." - + KeyRingsColumns.MASTER_KEY_ID); - - return projectionMap; - } - - /** - * Builds default query for keyRings: KeyRings table is joined with UserIds and Keys - */ - private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match) { - if (match != UNIFIED_KEY_RING) { - // public or secret keyring - qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - } - - // join keyrings with keys and userIds - // Only get user id and key with rank 0 (main user id and main key) - qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" - + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." - + KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "." - + KeysColumns.RANK + " = '0') " + " INNER JOIN " + Tables.USER_IDS + " ON " - + "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "." - + UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "." - + UserIdsColumns.RANK + " = '0')"); - - qb.setProjectionMap(getProjectionMapForKeyRings()); - - return qb; - } - - /** - * Builds default query for keyRings: KeyRings table is joined with UserIds and Keys - *

- * Here only one key should be selected in the query to return a single keyring! - */ - private SQLiteQueryBuilder buildKeyRingQueryWithSpecificKey(SQLiteQueryBuilder qb, int match) { - // public or secret keyring - qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - - // join keyrings with keys and userIds to every keyring - qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" - + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." - + KeysColumns.KEY_RING_ROW_ID + ") " + " INNER JOIN " + Tables.USER_IDS + " ON " - + "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "." - + UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "." - + UserIdsColumns.RANK + " = '0')"); - - qb.setProjectionMap(getProjectionMapForKeyRings()); - - return qb; - } - /** * {@inheritDoc} */ - @SuppressWarnings("deprecation") @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { @@ -520,64 +212,53 @@ public class KeychainProvider extends ContentProvider { String groupBy = null, having = null; switch (match) { - case UNIFIED_KEY_RING: - qb = buildKeyRingQuery(qb, match); + case KEY_RING_UNIFIED: + case KEY_RINGS_UNIFIED: { + HashMap projectionMap = new HashMap(); + 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); + qb.setProjectionMap(projectionMap); - // GROUP BY so we don't get duplicates - groupBy = Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID; + qb.setTables( + Tables.KEYS + + " INNER JOIN " + Tables.USER_IDS + " ON (" + + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID + + " = " + + Tables.USER_IDS + "." + UserIdsColumns.MASTER_KEY_ID + + " AND " + Tables.USER_IDS + "." + UserIdsColumns.RANK + " = 0" + + ") LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON (" + + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID + + " = " + + Tables.KEY_RINGS_SECRET + "." + KeyRingsColumns.MASTER_KEY_ID + + ")" + ); + qb.appendWhere(Tables.KEYS + "." + KeysColumns.RANK + " = 0"); - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = KeyRings.TYPE + " DESC, " + - Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; + 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)) { + sortOrder = + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL DESC" + + Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; } break; - case PUBLIC_KEY_RING: - case SECRET_KEY_RING: - qb = buildKeyRingQuery(qb, match); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - case PUBLIC_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_ROW_ID: - qb = buildKeyRingQuery(qb, match); - - qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - qb = buildKeyRingQuery(qb, match); - - qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - case SECRET_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - qb = buildKeyRingQueryWithSpecificKey(qb, match); - - qb.appendWhere(" AND " + Tables.KEYS + "." + KeysColumns.KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - case SECRET_KEY_RING_BY_EMAILS: + } + /*case SECRET_KEY_RING_BY_EMAILS: case PUBLIC_KEY_RING_BY_EMAILS: qb = buildKeyRingQuery(qb, match); @@ -603,78 +284,77 @@ public class KeychainProvider extends ContentProvider { + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + emailWhere + "))"); - } + }*/ - break; - case SECRET_KEY_RING_BY_LIKE_EMAIL: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - qb = buildKeyRingQuery(qb, match); + case KEY_RING_KEYS: { + HashMap projectionMap = new HashMap(); + 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); + qb.setProjectionMap(projectionMap); - String likeEmail = uri.getLastPathSegment(); - - String likeEmailWhere = "tmp." + UserIdsColumns.USER_ID + " LIKE " - + DatabaseUtils.sqlEscapeString("%<%" + likeEmail + "%>"); - - 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 (" + likeEmailWhere - + "))"); - - break; - case PUBLIC_KEY_RING_KEY: - case SECRET_KEY_RING_KEY: qb.setTables(Tables.KEYS); - qb.appendWhere(KeysColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - - qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - - qb.setProjectionMap(getProjectionMapForKeys()); + qb.appendWhere(KeysColumns.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(1)); break; - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - qb.setTables(Tables.KEYS); - qb.appendWhere(KeysColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); + } - qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + case KEY_RING_USER_IDS: { + HashMap projectionMap = new HashMap(); + projectionMap.put(BaseColumns._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); + projectionMap.put(UserIds.IS_PRIMARY, UserIds.IS_PRIMARY); + qb.setProjectionMap(projectionMap); - qb.appendWhere(" AND " + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - qb.setProjectionMap(getProjectionMapForKeys()); - - break; - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID: - qb.setTables(Tables.USER_IDS + " INNER JOIN " + Tables.KEY_RINGS + " ON " + "(" - + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "." - + KeysColumns.KEY_RING_ROW_ID + " )"); - qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(3)); - - qb.setProjectionMap(getProjectionMapForUserIds()); - - break; - case PUBLIC_KEY_RING_USER_ID: - case SECRET_KEY_RING_USER_ID: qb.setTables(Tables.USER_IDS); - qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + qb.appendWhere(UserIdsColumns.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(1)); break; - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - qb.setTables(Tables.USER_IDS); - qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - qb.appendWhere(" AND " + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + } + + case KEY_RING_PUBLIC: { + HashMap projectionMap = new HashMap(); + 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); + qb.setProjectionMap(projectionMap); + + qb.setTables(Tables.KEY_RINGS_PUBLIC); + qb.appendWhere(KeyRingsColumns.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(1)); break; + } + + case KEY_RING_SECRET: { + HashMap projectionMap = new HashMap(); + 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); + qb.setProjectionMap(projectionMap); + + qb.setTables(Tables.KEY_RINGS_SECRET); + qb.appendWhere(KeyRingsColumns.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(1)); + + break; + } + case API_APPS: qb.setTables(Tables.API_APPS); @@ -739,63 +419,36 @@ public class KeychainProvider extends ContentProvider { final SQLiteDatabase db = mKeychainDatabase.getWritableDatabase(); Uri rowUri = null; - long rowId = -1; + Long keyId = null; try { final int match = mUriMatcher.match(uri); switch (match) { - case PUBLIC_KEY_RING: - values.put(KeyRings.TYPE, KeyTypes.PUBLIC); - - rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); - rowUri = KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - + case KEY_RING_PUBLIC: + db.insertOrThrow(Tables.KEY_RINGS_PUBLIC, null, values); + keyId = values.getAsLong(KeyRingsColumns.MASTER_KEY_ID); break; - case PUBLIC_KEY_RING_KEY: - values.put(Keys.TYPE, KeyTypes.PUBLIC); - - rowId = db.insertOrThrow(Tables.KEYS, null, values); - // TODO: this is wrong: - rowUri = Keys.buildPublicKeysUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + case KEY_RING_SECRET: + db.insertOrThrow(Tables.KEY_RINGS_SECRET, null, values); + keyId = values.getAsLong(KeyRingsColumns.MASTER_KEY_ID); break; - case PUBLIC_KEY_RING_USER_ID: - rowId = db.insertOrThrow(Tables.USER_IDS, null, values); - // TODO: this is wrong: - rowUri = UserIds.buildPublicUserIdsUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + case KEY_RING_KEYS: + Log.d(Constants.TAG, "keys"); + db.insertOrThrow(Tables.KEYS, null, values); + keyId = values.getAsLong(KeysColumns.MASTER_KEY_ID); break; - case SECRET_KEY_RING: - values.put(KeyRings.TYPE, KeyTypes.SECRET); - - rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); - rowUri = KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + case KEY_RING_USER_IDS: + db.insertOrThrow(Tables.USER_IDS, null, values); + keyId = values.getAsLong(UserIdsColumns.MASTER_KEY_ID); break; - case SECRET_KEY_RING_KEY: - values.put(Keys.TYPE, KeyTypes.SECRET); - rowId = db.insertOrThrow(Tables.KEYS, null, values); - // TODO: this is wrong: - rowUri = Keys.buildSecretKeysUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case SECRET_KEY_RING_USER_ID: - rowId = db.insertOrThrow(Tables.USER_IDS, null, values); - // TODO: this is wrong: - rowUri = UserIds.buildSecretUserIdsUri(Long.toString(rowId)); - - break; case API_APPS: - rowId = db.insertOrThrow(Tables.API_APPS, null, values); -// rowUri = ApiApps.buildIdUri(Long.toString(rowId)); - + db.insertOrThrow(Tables.API_APPS, null, values); break; + case API_ACCOUNTS: // set foreign key automatically based on given uri // e.g., api_apps/com.example.app/accounts/ @@ -804,20 +457,26 @@ public class KeychainProvider extends ContentProvider { Log.d(Constants.TAG, "provider packageName: " + packageName); - rowId = db.insertOrThrow(Tables.API_ACCOUNTS, null, values); + db.insertOrThrow(Tables.API_ACCOUNTS, null, values); // TODO: this is wrong: // rowUri = ApiAccounts.buildIdUri(Long.toString(rowId)); break; + default: throw new UnsupportedOperationException("Unknown uri: " + uri); } + if(keyId != null) { + uri = KeyRings.buildGenericKeyRingUri(keyId.toString()); + rowUri = uri; + } + // notify of changes in db getContext().getContentResolver().notifyChange(uri, null); } catch (SQLiteConstraintException e) { - Log.e(Constants.TAG, "Constraint exception on insert! Entry already existing?"); + Log.e(Constants.TAG, "Constraint exception on insert! Entry already existing?", e); } return rowUri; @@ -827,7 +486,7 @@ public class KeychainProvider extends ContentProvider { * {@inheritDoc} */ @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { + public int delete(Uri uri, String additionalSelection, String[] selectionArgs) { Log.v(Constants.TAG, "delete(uri=" + uri + ")"); final SQLiteDatabase db = mKeychainDatabase.getWritableDatabase(); @@ -835,43 +494,33 @@ public class KeychainProvider extends ContentProvider { int count; final int match = mUriMatcher.match(uri); - String defaultSelection = null; switch (match) { - case PUBLIC_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_ROW_ID: - defaultSelection = BaseColumns._ID + "=" + uri.getLastPathSegment(); + case KEY_RING_PUBLIC: { + @SuppressWarnings("ConstantConditions") // ensured by uriMatcher above + String selection = KeyRings.MASTER_KEY_ID + " = " + uri.getPathSegments().get(1); + if (!TextUtils.isEmpty(additionalSelection)) { + selection += " AND (" + additionalSelection + ")"; + } // corresponding keys and userIds are deleted by ON DELETE CASCADE - count = db.delete(Tables.KEY_RINGS, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), - selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + count = db.delete(Tables.KEY_RINGS_PUBLIC, selection, selectionArgs); break; - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - defaultSelection = KeyRings.MASTER_KEY_ID + "=" + uri.getLastPathSegment(); - // corresponding keys and userIds are deleted by ON DELETE CASCADE - count = db.delete(Tables.KEY_RINGS, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), - selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - count = db.delete(Tables.KEYS, - buildDefaultKeysSelection(uri, getKeyType(match), selection), selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - count = db.delete(Tables.KEYS, buildDefaultUserIdsSelection(uri, selection), - selectionArgs); + } + case KEY_RING_SECRET: { + @SuppressWarnings("ConstantConditions") // ensured by uriMatcher above + String selection = KeyRings.MASTER_KEY_ID + " = " + uri.getPathSegments().get(1); + if (!TextUtils.isEmpty(additionalSelection)) { + selection += " AND (" + additionalSelection + ")"; + } + count = db.delete(Tables.KEY_RINGS_SECRET, selection, selectionArgs); break; + } + case API_APPS_BY_PACKAGE_NAME: - count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, selection), + count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, additionalSelection), selectionArgs); break; case API_ACCOUNTS_BY_ACCOUNT_NAME: - count = db.delete(Tables.API_ACCOUNTS, buildDefaultApiAccountsSelection(uri, selection), + count = db.delete(Tables.API_ACCOUNTS, buildDefaultApiAccountsSelection(uri, additionalSelection), selectionArgs); break; default: @@ -898,44 +547,6 @@ public class KeychainProvider extends ContentProvider { try { final int match = mUriMatcher.match(uri); switch (match) { - case PUBLIC_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_ROW_ID: - defaultSelection = BaseColumns._ID + "=" + uri.getLastPathSegment(); - - count = db.update( - Tables.KEY_RINGS, - values, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), - selection), selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - defaultSelection = KeyRings.MASTER_KEY_ID + "=" + uri.getLastPathSegment(); - - count = db.update( - Tables.KEY_RINGS, - values, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), - selection), selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - count = db - .update(Tables.KEYS, values, - buildDefaultKeysSelection(uri, getKeyType(match), selection), - selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - count = db.update(Tables.USER_IDS, values, - buildDefaultUserIdsSelection(uri, selection), selectionArgs); - break; case API_APPS_BY_PACKAGE_NAME: count = db.update(Tables.API_APPS, values, buildDefaultApiAppsSelection(uri, selection), selectionArgs); @@ -958,81 +569,6 @@ public class KeychainProvider extends ContentProvider { return count; } - /** - * Build default selection statement for KeyRings. If no extra selection is specified only build - * where clause with rowId - * - * @param defaultSelection - * @param keyType - * @param selection - * @return - */ - private String buildDefaultKeyRingsSelection(String defaultSelection, Integer keyType, - String selection) { - String andType = ""; - if (keyType != null) { - andType = " AND " + KeyRingsColumns.TYPE + "=" + keyType; - } - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - return defaultSelection + andType + andSelection; - } - - /** - * Build default selection statement for Keys. If no extra selection is specified only build - * where clause with rowId - * - * @param uri - * @param selection - * @return - */ - private String buildDefaultKeysSelection(Uri uri, Integer keyType, String selection) { - String rowId = uri.getLastPathSegment(); - - String foreignKeyRingRowId = uri.getPathSegments().get(2); - String andForeignKeyRing = " AND " + KeysColumns.KEY_RING_ROW_ID + " = " - + foreignKeyRingRowId; - - String andType = ""; - if (keyType != null) { - andType = " AND " + KeysColumns.TYPE + "=" + keyType; - } - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - return BaseColumns._ID + "=" + rowId + andForeignKeyRing + andType + andSelection; - } - - /** - * Build default selection statement for UserIds. If no extra selection is specified only build - * where clause with rowId - * - * @param uri - * @param selection - * @return - */ - private String buildDefaultUserIdsSelection(Uri uri, String selection) { - String rowId = uri.getLastPathSegment(); - - String foreignKeyRingRowId = uri.getPathSegments().get(2); - String andForeignKeyRing = " AND " + KeysColumns.KEY_RING_ROW_ID + " = " - + foreignKeyRingRowId; - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - return BaseColumns._ID + "=" + rowId + andForeignKeyRing + andSelection; - } - /** * Build default selection statement for API apps. If no extra selection is specified only build * where clause with rowId @@ -1066,28 +602,4 @@ public class KeychainProvider extends ContentProvider { + andSelection; } - // @Override - // public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - // int match = mUriMatcher.match(uri); - // if (match != DATA_STREAM) { - // throw new FileNotFoundException(); - // } - // String fileName = uri.getLastPathSegment(); - // File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName); - // return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); - // } - - /** - * This broadcast is send system wide to inform other application that a keyring was inserted, - * updated, or deleted - */ - private void sendBroadcastDatabaseChange(int keyType, String contentItemType) { - // TODO: Disabled, old API - // Intent intent = new Intent(); - // intent.setAction(ACTION_BROADCAST_DATABASE_CHANGE); - // intent.putExtra(EXTRA_BROADCAST_KEY_TYPE, keyType); - // intent.putExtra(EXTRA_BROADCAST_CONTENT_ITEM_TYPE, contentItemType); - // - // getContext().sendBroadcast(intent, Constants.PERMISSION_ACCESS_API); - } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java index da1bcb2d9..bc7de0b37 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java @@ -25,7 +25,7 @@ import android.provider.BaseColumns; import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns; public class KeychainServiceBlobDatabase extends SQLiteOpenHelper { - private static final String DATABASE_NAME = "apg_blob.db"; + private static final String DATABASE_NAME = "openkeychain_blob.db"; private static final int DATABASE_VERSION = 2; public static final String TABLE = "data"; 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 b971143ae..040923c33 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 @@ -75,78 +75,40 @@ public class ProviderHelper { return keyRing; } - /** - * Retrieves the actual PGPPublicKeyRing object from the database blob based on the rowId - */ - public static PGPPublicKeyRing getPGPPublicKeyRingByRowId(Context context, long rowId) { - Uri queryUri = KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); - return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri); + public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) { + return getPGPPublicKeyRingWithKeyId(context, keyId).getPublicKey(keyId); + } + public static PGPPublicKeyRing getPGPPublicKeyRingWithKeyId(Context context, long keyId) { + // todo do + 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 + return null; } /** * Retrieves the actual PGPPublicKeyRing object from the database blob based on the masterKeyId */ - public static PGPPublicKeyRing getPGPPublicKeyRingByMasterKeyId(Context context, + public static PGPPublicKeyRing getPGPPublicKeyRing(Context context, long masterKeyId) { - Uri queryUri = KeyRings.buildPublicKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); + Uri queryUri = KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)); return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri); } - /** - * Retrieves the actual PGPPublicKeyRing object from the database blob associated with a key - * with this keyId - */ - public static PGPPublicKeyRing getPGPPublicKeyRingByKeyId(Context context, long keyId) { - Uri queryUri = KeyRings.buildPublicKeyRingsByKeyIdUri(Long.toString(keyId)); - return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * Retrieves the actual PGPPublicKey object from the database blob associated with a key with - * this keyId - */ - public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) { - PGPPublicKeyRing keyRing = getPGPPublicKeyRingByKeyId(context, keyId); - - return (keyRing == null) ? null : keyRing.getPublicKey(keyId); - } - - /** - * Retrieves the actual PGPSecretKeyRing object from the database blob based on the rowId - */ - public static PGPSecretKeyRing getPGPSecretKeyRingByRowId(Context context, long rowId) { - Uri queryUri = KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); - return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri); - } - /** * Retrieves the actual PGPSecretKeyRing object from the database blob based on the maserKeyId */ - public static PGPSecretKeyRing getPGPSecretKeyRingByMasterKeyId(Context context, + public static PGPSecretKeyRing getPGPSecretKeyRing(Context context, long masterKeyId) { - Uri queryUri = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); + Uri queryUri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId)); return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri); } - /** - * Retrieves the actual PGPSecretKeyRing object from the database blob associated with a key - * with this keyId - */ - public static PGPSecretKeyRing getPGPSecretKeyRingByKeyId(Context context, long keyId) { - Uri queryUri = KeyRings.buildSecretKeyRingsByKeyIdUri(Long.toString(keyId)); - return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * Retrieves the actual PGPSecretKey object from the database blob associated with a key with - * this keyId - */ - public static PGPSecretKey getPGPSecretKeyByKeyId(Context context, long keyId) { - PGPSecretKeyRing keyRing = getPGPSecretKeyRingByKeyId(context, keyId); - - return (keyRing == null) ? null : keyRing.getSecretKey(keyId); - } - /** * Saves PGPPublicKeyRing with its keys and userIds in DB */ @@ -155,21 +117,13 @@ public class ProviderHelper { PGPPublicKey masterKey = keyRing.getPublicKey(); long masterKeyId = masterKey.getKeyID(); - Uri deleteUri = KeyRings.buildPublicKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); - - // get current _ID of key - long currentRowId = -1; - Cursor oldQuery = context.getContentResolver() - .query(deleteUri, new String[]{KeyRings._ID}, null, null, null); - if (oldQuery != null && oldQuery.moveToFirst()) { - currentRowId = oldQuery.getLong(0); - } else { - Log.e(Constants.TAG, "Key could not be found! Something wrong is happening!"); - } + // IF there is a secret key, preserve it! + // TODO This even necessary? + // 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(deleteUri, null, null); + context.getContentResolver().delete(KeyRings.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); } @@ -179,29 +133,25 @@ 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 - if (currentRowId != -1) { - values.put(KeyRings._ID, currentRowId); - } values.put(KeyRings.MASTER_KEY_ID, masterKeyId); values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); // insert new version of this keyRing - Uri uri = KeyRings.buildPublicKeyRingsUri(); + Uri uri = KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)); Uri insertedUri = context.getContentResolver().insert(uri, values); - long keyRingRowId = Long.valueOf(insertedUri.getLastPathSegment()); // save all keys and userIds included in keyRing object in database ArrayList operations = new ArrayList(); int rank = 0; for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { - operations.add(buildPublicKeyOperations(context, keyRingRowId, key, rank)); + operations.add(buildPublicKeyOperations(context, masterKeyId, key, rank)); ++rank; } int userIdRank = 0; for (String userId : new IterableIterator(masterKey.getUserIDs())) { - operations.add(buildPublicUserIdOperations(context, keyRingRowId, userId, userIdRank)); + operations.add(buildUserIdOperations(context, masterKeyId, userId, userIdRank)); ++userIdRank; } @@ -214,7 +164,6 @@ public class ProviderHelper { // operations.add(buildPublicKeyOperations(context, keyRingRowId, key, rank)); } - try { context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY, operations); } catch (RemoteException e) { @@ -222,6 +171,12 @@ public class ProviderHelper { } catch (OperationApplicationException e) { Log.e(Constants.TAG, "applyBatch failed!", e); } + + // Save the saved keyring (if any) + // TODO this even necessary? see above... + // if(secretRing != null) + // saveKeyRing(context, secretRing); + } /** @@ -232,104 +187,46 @@ public class ProviderHelper { PGPSecretKey masterKey = keyRing.getSecretKey(); long masterKeyId = masterKey.getKeyID(); - Uri deleteUri = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); + // TODO Make sure there is a public key for this secret key in the db (create one maybe) - // get current _ID of key - long currentRowId = -1; - Cursor oldQuery = context.getContentResolver() - .query(deleteUri, new String[]{KeyRings._ID}, null, null, null); - if (oldQuery != null && oldQuery.moveToFirst()) { - currentRowId = oldQuery.getLong(0); - } else { - Log.e(Constants.TAG, "Key could not be found! Something wrong is happening!"); + { + 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); } - // delete old version of this keyRing, which also deletes all keys and userIds on cascade - try { - context.getContentResolver().delete(deleteUri, null, null); - } catch (UnsupportedOperationException e) { - Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e); - } - - ContentValues values = new ContentValues(); - // use exactly the same _ID again to replace key in-place. - // 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 - if (currentRowId != -1) { - values.put(KeyRings._ID, currentRowId); - } - values.put(KeyRings.MASTER_KEY_ID, masterKeyId); - values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); - - // insert new version of this keyRing - Uri uri = KeyRings.buildSecretKeyRingsUri(); - Uri insertedUri = context.getContentResolver().insert(uri, values); - long keyRingRowId = Long.valueOf(insertedUri.getLastPathSegment()); - - // save all keys and userIds included in keyRing object in database - ArrayList operations = new ArrayList(); - - int rank = 0; - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - operations.add(buildSecretKeyOperations(context, keyRingRowId, key, rank)); - ++rank; - } - - int userIdRank = 0; - for (String userId : new IterableIterator(masterKey.getUserIDs())) { - operations.add(buildSecretUserIdOperations(context, keyRingRowId, userId, userIdRank)); - ++userIdRank; - } - - try { - context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY, operations); - } catch (RemoteException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); - } catch (OperationApplicationException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); - } } /** * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing */ private static ContentProviderOperation buildPublicKeyOperations(Context context, - long keyRingRowId, PGPPublicKey key, int rank) throws IOException { + long masterKeyId, PGPPublicKey key, int rank) throws IOException { + ContentValues values = new ContentValues(); + values.put(Keys.MASTER_KEY_ID, masterKeyId); + values.put(Keys.RANK, rank); + values.put(Keys.KEY_ID, key.getKeyID()); - values.put(Keys.IS_MASTER_KEY, key.isMasterKey()); - values.put(Keys.ALGORITHM, key.getAlgorithm()); values.put(Keys.KEY_SIZE, key.getBitStrength()); - values.put(Keys.CAN_SIGN, PgpKeyHelper.isSigningKey(key)); + values.put(Keys.ALGORITHM, key.getAlgorithm()); + values.put(Keys.FINGERPRINT, key.getFingerprint()); + + values.put(Keys.CAN_CERTIFY, (PgpKeyHelper.isCertificationKey(key))); + values.put(Keys.CAN_SIGN, (PgpKeyHelper.isSigningKey(key))); values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key)); values.put(Keys.IS_REVOKED, key.isRevoked()); + values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000); Date expiryDate = PgpKeyHelper.getExpiryDate(key); if (expiryDate != null) { values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); } - values.put(Keys.KEY_RING_ROW_ID, keyRingRowId); - values.put(Keys.KEY_DATA, key.getEncoded()); - values.put(Keys.RANK, rank); - values.put(Keys.FINGERPRINT, key.getFingerprint()); - Uri uri = Keys.buildPublicKeysUri(Long.toString(keyRingRowId)); - - return ContentProviderOperation.newInsert(uri).withValues(values).build(); - } - - /** - * Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing - */ - private static ContentProviderOperation buildPublicUserIdOperations(Context context, - long keyRingRowId, String userId, int rank) { - ContentValues values = new ContentValues(); - values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId); - values.put(UserIds.USER_ID, userId); - values.put(UserIds.RANK, rank); - - Uri uri = UserIds.buildPublicUserIdsUri(Long.toString(keyRingRowId)); + Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId)); return ContentProviderOperation.newInsert(uri).withValues(values).build(); } @@ -338,50 +235,21 @@ public class ProviderHelper { * Build ContentProviderOperation to add PGPSecretKey to database corresponding to a keyRing */ private static ContentProviderOperation buildSecretKeyOperations(Context context, - long keyRingRowId, PGPSecretKey key, int rank) throws IOException { - ContentValues values = new ContentValues(); - - boolean hasPrivate = true; - if (key.isMasterKey()) { - if (key.isPrivateKeyEmpty()) { - hasPrivate = false; - } - } - - values.put(Keys.KEY_ID, key.getKeyID()); - values.put(Keys.IS_MASTER_KEY, key.isMasterKey()); - values.put(Keys.ALGORITHM, key.getPublicKey().getAlgorithm()); - values.put(Keys.KEY_SIZE, key.getPublicKey().getBitStrength()); - values.put(Keys.CAN_CERTIFY, (PgpKeyHelper.isCertificationKey(key) && hasPrivate)); - values.put(Keys.CAN_SIGN, (PgpKeyHelper.isSigningKey(key) && hasPrivate)); - values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key)); - values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked()); - values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000); - Date expiryDate = PgpKeyHelper.getExpiryDate(key); - if (expiryDate != null) { - values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); - } - values.put(Keys.KEY_RING_ROW_ID, keyRingRowId); - values.put(Keys.KEY_DATA, key.getEncoded()); - values.put(Keys.RANK, rank); - values.put(Keys.FINGERPRINT, key.getPublicKey().getFingerprint()); - - Uri uri = Keys.buildSecretKeysUri(Long.toString(keyRingRowId)); - - return ContentProviderOperation.newInsert(uri).withValues(values).build(); + long masterKeyId, PGPSecretKey key, int rank) throws IOException { + return buildPublicKeyOperations(context, masterKeyId, key.getPublicKey(), rank); } /** - * Build ContentProviderOperation to add SecretUserIds to database corresponding to a keyRing + * Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing */ - private static ContentProviderOperation buildSecretUserIdOperations(Context context, - long keyRingRowId, String userId, int rank) { + private static ContentProviderOperation buildUserIdOperations(Context context, + long masterKeyId, String userId, int rank) { ContentValues values = new ContentValues(); - values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId); + values.put(UserIds.MASTER_KEY_ID, masterKeyId); values.put(UserIds.USER_ID, userId); values.put(UserIds.RANK, rank); - Uri uri = UserIds.buildSecretUserIdsUri(Long.toString(keyRingRowId)); + Uri uri = UserIds.buildUserIdsUri(Long.toString(masterKeyId)); return ContentProviderOperation.newInsert(uri).withValues(values).build(); } @@ -410,141 +278,54 @@ public class ProviderHelper { return masterKeyIds; } - /** - * Private helper method - */ - private static ArrayList getKeyRingsRowIds(Context context, Uri queryUri) { - Cursor cursor = context.getContentResolver().query(queryUri, - new String[]{KeyRings._ID}, null, null, null); - - ArrayList rowIds = new ArrayList(); - if (cursor != null) { - int idCol = cursor.getColumnIndex(KeyRings._ID); - if (cursor.moveToFirst()) { - do { - rowIds.add(cursor.getLong(idCol)); - } while (cursor.moveToNext()); - } - } - - if (cursor != null) { - cursor.close(); - } - - return rowIds; - } - - /** - * Retrieves ids of all SecretKeyRings - */ - public static ArrayList getSecretKeyRingsMasterKeyIds(Context context) { - Uri queryUri = KeyRings.buildSecretKeyRingsUri(); - return getKeyRingsMasterKeyIds(context, queryUri); - } - - /** - * Retrieves ids of all PublicKeyRings - */ - public static ArrayList getPublicKeyRingsMasterKeyIds(Context context) { - Uri queryUri = KeyRings.buildPublicKeyRingsUri(); - return getKeyRingsMasterKeyIds(context, queryUri); - } - - /** - * Retrieves ids of all SecretKeyRings - */ - public static ArrayList getSecretKeyRingsRowIds(Context context) { - Uri queryUri = KeyRings.buildSecretKeyRingsUri(); - return getKeyRingsRowIds(context, queryUri); - } - - /** - * Retrieves ids of all PublicKeyRings - */ - public static ArrayList getPublicKeyRingsRowIds(Context context) { - Uri queryUri = KeyRings.buildPublicKeyRingsUri(); - return getKeyRingsRowIds(context, queryUri); - } - - public static void deletePublicKeyRing(Context context, long rowId) { + public static void deletePublicKeyRing(Context context, long masterKeyId) { ContentResolver cr = context.getContentResolver(); - cr.delete(KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)), null, null); + cr.delete(KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null); } - public static void deleteSecretKeyRing(Context context, long rowId) { + public static void deleteSecretKeyRing(Context context, long masterKeyId) { ContentResolver cr = context.getContentResolver(); - cr.delete(KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)), null, null); + cr.delete(KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null); } - public static void deleteUnifiedKeyRing(Context context, String masterKeyId, boolean isSecretKey) { - ContentResolver cr = context.getContentResolver(); - cr.delete(KeyRings.buildPublicKeyRingsByMasterKeyIdUri(masterKeyId), null, null); - if (isSecretKey) { - cr.delete(KeyRings.buildSecretKeyRingsByMasterKeyIdUri(masterKeyId), null, null); - } - - } - - /** - * Get master key id of keyring by its row id - */ - public static long getPublicMasterKeyId(Context context, long keyRingRowId) { - Uri queryUri = KeyRings.buildPublicKeyRingsUri(String.valueOf(keyRingRowId)); - return getMasterKeyId(context, queryUri); - } - - /** - * Get empty status of master key of keyring by its row id - */ - public static boolean getSecretMasterKeyCanCertify(Context context, long keyRingRowId) { - Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId)); - return getMasterKeyCanCertify(context, queryUri); - } - - /** - * Private helper method to get master key private empty status of keyring by its row id - */ - public static boolean getMasterKeyCanCertify(Context context, Uri queryUri) { - 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",}; + // TODO redo - ContentResolver cr = context.getContentResolver(); - Cursor cursor = cr.query(queryUri, projection, null, null, null); + return false; - long masterKeyId = -1; - if (cursor != null && cursor.moveToFirst()) { - int masterKeyIdCol = cursor.getColumnIndex("sign"); + /* + 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",}; - masterKeyId = cursor.getLong(masterKeyIdCol); - } + ContentResolver cr = context.getContentResolver(); + Cursor cursor = cr.query(queryUri, projection, null, null, null); - if (cursor != null) { - cursor.close(); - } + long masterKeyId = -1; + if (cursor != null && cursor.moveToFirst()) { + int masterKeyIdCol = cursor.getColumnIndex("sign"); - return (masterKeyId > 0); + masterKeyId = cursor.getLong(masterKeyIdCol); + } + + if (cursor != null) { + cursor.close(); + } + + return (masterKeyId > 0); + */ } public static boolean hasSecretKeyByMasterKeyId(Context context, long masterKeyId) { - Uri queryUri = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); + Uri queryUri = KeyRings.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 keyring by its row id - */ - public static long getSecretMasterKeyId(Context context, long keyRingRowId) { - Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId)); - return getMasterKeyId(context, queryUri); - } - /** * Get master key id of key */ @@ -629,10 +410,10 @@ public class ProviderHelper { } } - PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, masterKeyId); + 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.getPGPSecretKeyByKeyId(context, masterKeyId); + PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId).getSecretKey(); if (secretKey == null) { Log.e(Constants.TAG, "Key could not be found!"); return null; @@ -646,26 +427,6 @@ public class ProviderHelper { return fingerprint; } - public static String getUserId(Context context, Uri queryUri) { - String[] projection = new String[]{UserIds.USER_ID}; - Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null); - - String userId = null; - try { - if (cursor != null && cursor.moveToFirst()) { - int col = cursor.getColumnIndexOrThrow(UserIds.USER_ID); - - userId = cursor.getString(col); - } - } finally { - if (cursor != null) { - cursor.close(); - } - } - - return userId; - } - public static ArrayList getKeyRingsAsArmoredString(Context context, Uri uri, long[] masterKeyIds) { ArrayList output = new ArrayList(); 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 1cd5862e7..614fc2c00 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 @@ -64,7 +64,7 @@ public class OpenPgpService extends RemoteService { ArrayList dublicateUserIds = new ArrayList(); for (String email : encryptionUserIds) { - Uri uri = KeychainContract.KeyRings.buildPublicKeyRingsByEmailsUri(email); + Uri uri = KeychainContract.KeyRings.buildUnifiedKeyRingsByEmailUri(email); Cursor cur = getContentResolver().query(uri, null, null, null, null); if (cur.moveToFirst()) { long id = cur.getLong(cur.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID)); 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 f82e5e619..6997a8f3e 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 @@ -478,8 +478,7 @@ public class KeychainIntentService extends IntentService /* Operation */ if (!canSign) { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 50, 100)); - PGPSecretKeyRing keyRing = ProviderHelper - .getPGPSecretKeyRingByKeyId(this, masterKeyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); keyRing = keyOperations.changeSecretKeyPassphrase(keyRing, oldPassPhrase, newPassPhrase); setProgress(R.string.progress_saving_key_ring, 50, 100); @@ -487,8 +486,8 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); } else { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); - PGPSecretKeyRing privkey = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, masterKeyId); - PGPPublicKeyRing pubkey = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, masterKeyId); + PGPSecretKeyRing privkey = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); + PGPPublicKeyRing pubkey = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId); PgpKeyOperation.Pair pair = keyOperations.buildSecretKey(privkey, pubkey, saveParams); setProgress(R.string.progress_saving_key_ring, 90, 100); @@ -639,8 +638,9 @@ public class KeychainIntentService extends IntentService ArrayList publicMasterKeyIds = new ArrayList(); ArrayList secretMasterKeyIds = new ArrayList(); - ArrayList allPublicMasterKeyIds = ProviderHelper.getPublicKeyRingsMasterKeyIds(this); - ArrayList allSecretMasterKeyIds = ProviderHelper.getSecretKeyRingsMasterKeyIds(this); + // TODO redo + ArrayList allPublicMasterKeyIds = null; // ProviderHelper.getPublicKeyRingsMasterKeyIds(this); + ArrayList allSecretMasterKeyIds = null; // ProviderHelper.getSecretKeyRingsMasterKeyIds(this); if (exportAll) { // get all public key ring MasterKey ids @@ -790,8 +790,7 @@ public class KeychainIntentService extends IntentService } PgpKeyOperation keyOperation = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - PGPPublicKeyRing publicRing = ProviderHelper - .getPGPPublicKeyRingByKeyId(this, pubKeyId); + PGPPublicKeyRing publicRing = ProviderHelper.getPGPPublicKeyRing(this, pubKeyId); PGPPublicKey publicKey = publicRing.getPublicKey(pubKeyId); PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(this, masterKeyId); 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 5825db01b..f2ab049c3 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 @@ -161,7 +161,7 @@ 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.getPGPSecretKeyRingByKeyId(this, keyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(this, keyId); if (keyRing == null) { return null; } @@ -202,8 +202,7 @@ public class PassphraseCacheService extends Service { public static boolean hasPassphrase(Context context, long secretKeyId) { // check if the key has no passphrase try { - PGPSecretKeyRing secRing = ProviderHelper - .getPGPSecretKeyRingByKeyId(context, secretKeyId); + PGPSecretKeyRing secRing = ProviderHelper.getPGPSecretKeyRing(context, secretKeyId); PGPSecretKey secretKey = null; boolean foundValidKey = false; for (Iterator keys = secRing.getSecretKeys(); keys.hasNext(); ) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 5dc06c16d..fd6f2186c 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -139,8 +139,6 @@ public class CertifyKeyActivity extends ActionBarActivity implements } Log.e(Constants.TAG, "uri: " + mDataUri); - PGPPublicKeyRing signKey = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, mDataUri); - mUserIds = (ListView) findViewById(R.id.user_ids); mUserIdsAdapter = new ViewKeyUserIdsAdapter(this, null, 0, true); @@ -149,20 +147,12 @@ public class CertifyKeyActivity extends ActionBarActivity implements getSupportLoaderManager().initLoader(LOADER_ID_KEYRING, null, this); getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); - if (signKey != null) { - mPubKeyId = PgpKeyHelper.getMasterKey(signKey).getKeyID(); - } - if (mPubKeyId == 0) { - Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!"); - finish(); - return; - } } static final String[] KEYRING_PROJECTION = new String[] { KeychainContract.KeyRings._ID, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.Keys.FINGERPRINT, KeychainContract.UserIds.USER_ID }; @@ -182,11 +172,13 @@ public class CertifyKeyActivity extends ActionBarActivity implements @Override public Loader onCreateLoader(int id, Bundle args) { switch(id) { - case LOADER_ID_KEYRING: - return new CursorLoader(this, mDataUri, KEYRING_PROJECTION, null, null, null); + case LOADER_ID_KEYRING: { + Uri uri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); + return new CursorLoader(this, uri, KEYRING_PROJECTION, null, null, null); + } case LOADER_ID_USER_IDS: { - Uri baseUri = KeychainContract.UserIds.buildUserIdsUri(mDataUri); - return new CursorLoader(this, baseUri, USER_IDS_PROJECTION, null, null, USER_IDS_SORT_ORDER); + Uri uri = KeychainContract.UserIds.buildUserIdsUri(mDataUri); + return new CursorLoader(this, uri, USER_IDS_PROJECTION, null, null, USER_IDS_SORT_ORDER); } } return null; @@ -199,19 +191,14 @@ public class CertifyKeyActivity extends ActionBarActivity implements // the first key here is our master key if (data.moveToFirst()) { // TODO: put findViewById in onCreate! - - long keyId = data.getLong(INDEX_MASTER_KEY_ID); - String keyIdStr = PgpKeyHelper.convertKeyIdToHexShort(keyId); + mPubKeyId = data.getLong(INDEX_MASTER_KEY_ID); + String keyIdStr = PgpKeyHelper.convertKeyIdToHexShort(mPubKeyId); ((TextView) findViewById(R.id.key_id)).setText(keyIdStr); String mainUserId = data.getString(INDEX_USER_ID); ((TextView) findViewById(R.id.main_user_id)).setText(mainUserId); byte[] fingerprintBlob = data.getBlob(INDEX_FINGERPRINT); - if (fingerprintBlob == null) { - // FALLBACK for old database entries - fingerprintBlob = ProviderHelper.getFingerprint(this, mDataUri); - } String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); ((TextView) findViewById(R.id.fingerprint)).setText(PgpKeyHelper.colorizeFingerprint(fingerprint)); } @@ -261,7 +248,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements * handles the UI bits of the signing process on the UI thread */ private void initiateSigning() { - PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, mPubKeyId); + PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRing(this, mPubKeyId); if (pubring != null) { // if we have already signed this key, dont bother doing it again boolean alreadySigned = false; 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 9df84065f..0d0b7222e 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 @@ -356,7 +356,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.buildSecretKeyRingsUri(Long.toString(rowId)); + Uri convertUri = KeychainContract.KeyRings.buildSecretKeyRingUri(Long.toString(rowId)); // Message is received after key is deleted Handler returnHandler = new Handler() { @Override @@ -380,7 +380,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener private void finallyEdit(final long masterKeyId) { if (masterKeyId != 0) { PGPSecretKey masterKey = null; - mKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, masterKeyId); + mKeyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); if (mKeyRing != null) { masterKey = PgpKeyHelper.getMasterKey(mKeyRing); for (PGPSecretKey key : new IterableIterator(mKeyRing.getSecretKeys())) { 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 5b7f9e4cc..10508317d 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 @@ -141,7 +141,7 @@ public class EncryptAsymmetricFragment extends Fragment { private void preselectKeys(long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds) { if (preselectedSignatureKeyId != 0) { // TODO: don't use bouncy castle objects! - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(getActivity(), + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(getActivity(), preselectedSignatureKeyId); PGPSecretKey masterKey; if (keyRing != null) { @@ -160,7 +160,7 @@ public class EncryptAsymmetricFragment extends Fragment { for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { // TODO: don't use bouncy castle objects! - PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(getActivity(), + PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(getActivity(), preselectedEncryptionKeyIds[i]); PGPPublicKey masterKey; if (keyRing == null) { @@ -203,7 +203,7 @@ public class EncryptAsymmetricFragment extends Fragment { String uid = getResources().getString(R.string.user_id_no_name); String uidExtra = ""; // TODO: don't use bouncy castle objects! - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(getActivity(), + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(getActivity(), mSecretKeyId); if (keyRing != null) { PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing); 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 957c822d2..573ddd1a7 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 @@ -186,6 +186,7 @@ public class KeyListFragment extends Fragment case R.id.menu_key_list_multi_export: { ids = mStickyList.getWrappedList().getCheckedItemIds(); long[] masterKeyIds = new long[2*ids.length]; + /* TODO! redo ArrayList allPubRowIds = ProviderHelper.getPublicKeyRingsRowIds(getActivity()); for (int i = 0; i < ids.length; i++) { @@ -194,7 +195,7 @@ public class KeyListFragment extends Fragment } else { masterKeyIds[i] = ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]); } - } + }*/ ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity()); mExportHelper .showExportKeysDialog(masterKeyIds, Id.type.public_key, @@ -254,22 +255,22 @@ public class KeyListFragment extends Fragment // These are the rows that we will retrieve. static final String[] PROJECTION = new String[]{ KeychainContract.KeyRings._ID, - KeychainContract.KeyRings.TYPE, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.UserIds.USER_ID, - KeychainContract.Keys.IS_REVOKED + KeychainContract.Keys.IS_REVOKED, + KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID }; - static final int INDEX_TYPE = 1; - static final int INDEX_MASTER_KEY_ID = 2; - static final int INDEX_USER_ID = 3; - static final int INDEX_IS_REVOKED = 4; + static final int INDEX_MASTER_KEY_ID = 1; + static final int INDEX_USER_ID = 2; + 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 + "." + KeyRings.TYPE + " DESC, " + KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID + " IS NULL ASC, " + // sort by user id otherwise - + UserIds.USER_ID + " ASC"; + UserIds.USER_ID + " ASC"; @Override public Loader onCreateLoader(int id, Bundle args) { @@ -326,7 +327,7 @@ public class KeyListFragment extends Fragment } viewIntent.setData( KeychainContract - .KeyRings.buildPublicKeyRingsByMasterKeyIdUri( + .KeyRings.buildPublicKeyRingUri( Long.toString(mAdapter.getMasterKeyId(position)))); startActivity(viewIntent); } @@ -503,7 +504,7 @@ public class KeyListFragment extends Fragment Button button = (Button) view.findViewById(R.id.edit); TextView revoked = (TextView) view.findViewById(R.id.revoked); - if (cursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) { + if (!cursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) { // this is a secret key - show the edit button statusDivider.setVisibility(View.VISIBLE); statusLayout.setVisibility(View.VISIBLE); @@ -516,7 +517,7 @@ public class KeyListFragment extends Fragment Intent editIntent = new Intent(getActivity(), EditKeyActivity.class); editIntent.setData( KeychainContract.KeyRings - .buildSecretKeyRingsByMasterKeyIdUri(Long.toString(id))); + .buildSecretKeyRingUri(Long.toString(id))); editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); startActivityForResult(editIntent, 0); } @@ -577,7 +578,7 @@ public class KeyListFragment extends Fragment throw new IllegalStateException("couldn't move cursor to position " + position); } - if (mCursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) { + if (!mCursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) { { // set contact count int num = mCursor.getCount(); String contactsTotal = getResources().getQuantityString(R.plurals.n_contacts, num, num); @@ -617,7 +618,7 @@ public class KeyListFragment extends Fragment } // early breakout: all secret keys are assigned id 0 - if (mCursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) { + if (!mCursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) { return 1L; } // otherwise, return the first character of the name as ID diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java index 6ab9f1c6e..fcce39ee9 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java @@ -248,9 +248,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T @Override public Loader onCreateLoader(int id, Bundle args) { - // This is called when a new Loader needs to be created. This - // sample only has one Loader, so we don't care about the ID. - Uri baseUri = KeyRings.buildPublicKeyRingsUri(); + Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); // These are the rows that we will retrieve. long now = new Date().getTime() / 1000; @@ -258,24 +256,24 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T KeyRings._ID, KeyRings.MASTER_KEY_ID, UserIds.USER_ID, - "(SELECT COUNT(available_keys." + Keys._ID + ") FROM " + Tables.KEYS - + " AS available_keys WHERE available_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID - + " AND available_keys." + Keys.IS_REVOKED + " = '0' AND available_keys." - + Keys.CAN_ENCRYPT + " = '1') AS " - + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, - "(SELECT COUNT(valid_keys." + Keys._ID + ") FROM " + Tables.KEYS - + " AS valid_keys WHERE valid_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID - + " AND valid_keys." + Keys.IS_REVOKED + " = '0' AND valid_keys." - + Keys.CAN_ENCRYPT + " = '1' AND valid_keys." + Keys.CREATION + " <= '" - + now + "' AND " + "(valid_keys." + Keys.EXPIRY + " IS NULL OR valid_keys." - + Keys.EXPIRY + " >= '" + now + "')) AS " - + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; + "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + +" WHERE k." + Keys.MASTER_KEY_ID + " = " + + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND k." + Keys.IS_REVOKED + " = '0'" + + " AND k." + Keys.CAN_ENCRYPT + " = '1'" + + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, + "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + + " WHERE k." + Keys.MASTER_KEY_ID + " = " + + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND k." + Keys.IS_REVOKED + " = '0'" + + " AND k." + Keys.CAN_ENCRYPT + " = '1'" + + " AND k." + Keys.CREATION + " <= '" + now + "'" + + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + " >= '" + now + "' )" + + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; String inMasterKeyList = null; if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) { - inMasterKeyList = KeyRings.MASTER_KEY_ID + " IN ("; + inMasterKeyList = Tables.KEYS + "." + KeyRings.MASTER_KEY_ID + " IN ("; for (int i = 0; i < mSelectedMasterKeyIds.length; ++i) { if (i != 0) { inMasterKeyList += ", "; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java index 2efa7d33a..9987facbc 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java @@ -85,7 +85,7 @@ public class SelectSecretKeyFragment extends ListFragment implements @Override public void onItemClick(AdapterView adapterView, View view, int position, long id) { long masterKeyId = mAdapter.getMasterKeyId(position); - Uri result = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(String.valueOf(masterKeyId)); + Uri result = KeyRings.buildGenericKeyRingUri(String.valueOf(masterKeyId)); // return data to activity, which results in finishing it mActivity.afterListSelection(result); @@ -112,12 +112,7 @@ public class SelectSecretKeyFragment extends ListFragment implements public Loader onCreateLoader(int id, Bundle args) { // This is called when a new Loader needs to be created. This // sample only has one Loader, so we don't care about the ID. - Uri baseUri = KeyRings.buildSecretKeyRingsUri(); - - String capFilter = null; - if (mFilterCertify) { - capFilter = "(cert > 0)"; - } + Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); // These are the rows that we will retrieve. long now = new Date().getTime() / 1000; @@ -125,29 +120,36 @@ public class SelectSecretKeyFragment extends ListFragment implements KeyRings._ID, KeyRings.MASTER_KEY_ID, UserIds.USER_ID, - "(SELECT COUNT(cert_keys." + Keys._ID + ") FROM " + Tables.KEYS - + " AS cert_keys WHERE cert_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + " AND cert_keys." - + Keys.CAN_CERTIFY + " = '1') AS cert", - "(SELECT COUNT(available_keys." + Keys._ID + ") FROM " + Tables.KEYS - + " AS available_keys WHERE available_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID - + " AND available_keys." + Keys.IS_REVOKED + " = '0' AND available_keys." - + Keys.CAN_SIGN + " = '1') AS " - + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, - "(SELECT COUNT(valid_keys." + Keys._ID + ") FROM " + Tables.KEYS - + " AS valid_keys WHERE valid_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + " AND valid_keys." - + Keys.IS_REVOKED + " = '0' AND valid_keys." + Keys.CAN_SIGN - + " = '1' AND valid_keys." + Keys.CREATION + " <= '" + now + "' AND " - + "(valid_keys." + Keys.EXPIRY + " IS NULL OR valid_keys." + Keys.EXPIRY - + " >= '" + now + "')) AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID,}; + "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + + " WHERE k." + Keys.MASTER_KEY_ID + " = " + + KeychainDatabase.Tables.KEYS + "." + KeyRings.MASTER_KEY_ID + + " AND k." + Keys.CAN_CERTIFY + " = '1'" + + ") AS cert", + "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + +" WHERE k." + Keys.MASTER_KEY_ID + " = " + + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND k." + Keys.IS_REVOKED + " = '0'" + + " AND k." + Keys.CAN_SIGN + " = '1'" + + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, + "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + + " WHERE k." + Keys.MASTER_KEY_ID + " = " + + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND k." + Keys.IS_REVOKED + " = '0'" + + " AND k." + Keys.CAN_SIGN + " = '1'" + + " AND k." + Keys.CREATION + " <= '" + now + "'" + + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + " >= '" + now + "' )" + + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; String orderBy = UserIds.USER_ID + " ASC"; + String where = Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL"; + if (mFilterCertify) { + where += " AND (cert > 0)"; + } + // 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, capFilter, null, orderBy); + return new CursorLoader(getActivity(), baseUri, projection, where, null, orderBy); } @Override diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java index cbc0f4c5c..95eb4df94 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java @@ -57,10 +57,12 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan //The Projection we will retrieve, Master Key ID is for convenience sake, //to avoid having to pass the Key Around - final String[] PROJECTION = new String[]{KeychainContract.UserIds.USER_ID - , KeychainContract.KeyRings.MASTER_KEY_ID}; - final int INDEX_USER_ID = 0; - final int INDEX_MASTER_KEY_ID = 1; + final String[] PROJECTION = new String[] { + KeychainContract.Keys.MASTER_KEY_ID, + KeychainContract.UserIds.USER_ID + }; + final int INDEX_MASTER_KEY_ID = 0; + final int INDEX_USER_ID = 1; public interface SelectSecretKeyCallback { void onKeySelected(long secretKeyId); @@ -126,7 +128,7 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan //For AppSettingsFragment public void selectKey(long masterKeyId) { - Uri buildUri = KeychainContract.KeyRings.buildSecretKeyRingsByMasterKeyIdUri(String.valueOf(masterKeyId)); + Uri buildUri = KeychainContract.KeyRings.buildGenericKeyRingUri(String.valueOf(masterKeyId)); mReceivedUri = buildUri; getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this); } @@ -139,8 +141,9 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan @Override public Loader onCreateLoader(int id, Bundle args) { + Uri uri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mReceivedUri); //We don't care about the Loader id - return new CursorLoader(getActivity(), mReceivedUri, PROJECTION, null, null, null); + return new CursorLoader(getActivity(), uri, PROJECTION, null, null, null); } @Override 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 3e7e6d7ce..c212bea1f 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 @@ -83,13 +83,7 @@ public class ViewKeyActivity extends ActionBarActivity { selectedTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB); } - { - // normalize mDataUri to a "by row id" query, to ensure it works with any - // given valid /public/ query - long rowId = ProviderHelper.getRowId(this, getIntent().getData()); - // TODO: handle (rowId == 0) with something else than a crash - mDataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); - } + mDataUri = getIntent().getData(); Bundle mainBundle = new Bundle(); mainBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, mDataUri); @@ -124,8 +118,7 @@ public class ViewKeyActivity extends ActionBarActivity { uploadToKeyserver(mDataUri); return true; case R.id.menu_key_view_export_file: - long masterKeyId = - ProviderHelper.getPublicMasterKeyId(this, Long.valueOf(mDataUri.getLastPathSegment())); + long masterKeyId = Long.valueOf(mDataUri.getLastPathSegment()); long[] ids = new long[]{masterKeyId}; mExportHelper.showExportKeysDialog(ids, Id.type.public_key, Constants.Path.APP_DIR_FILE_PUB, 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 691be5fa9..397cfafa7 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 @@ -69,7 +69,6 @@ public class ViewKeyMainFragment extends Fragment implements private ListView mUserIds; private ListView mKeys; - private static final int LOADER_ID_KEYRING = 0; private static final int LOADER_ID_USER_IDS = 1; private static final int LOADER_ID_KEYS = 2; @@ -144,7 +143,7 @@ public class ViewKeyMainFragment extends Fragment implements Intent editIntent = new Intent(getActivity(), EditKeyActivity.class); editIntent.setData( KeychainContract - .KeyRings.buildSecretKeyRingsByMasterKeyIdUri( + .KeyRings.buildSecretKeyRingUri( Long.toString(masterKeyId))); editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); startActivityForResult(editIntent, 0); @@ -163,7 +162,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.buildPublicKeyRingsByMasterKeyIdUri( + certifyKey(KeychainContract.KeyRings.buildGenericKeyRingUri( Long.toString(masterKeyId) )); } @@ -187,39 +186,31 @@ public class ViewKeyMainFragment extends Fragment implements // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. - getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYRING, null, this); getActivity().getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this); } - static final String[] KEYRING_PROJECTION = - new String[]{KeychainContract.KeyRings._ID, KeychainContract.KeyRings.MASTER_KEY_ID, - KeychainContract.UserIds.USER_ID}; - static final int KEYRING_INDEX_ID = 0; - static final int KEYRING_INDEX_MASTER_KEY_ID = 1; - static final int KEYRING_INDEX_USER_ID = 2; - static final String[] USER_IDS_PROJECTION = new String[]{ KeychainContract.UserIds._ID, KeychainContract.UserIds.USER_ID, KeychainContract.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.IS_MASTER_KEY, KeychainContract.Keys.ALGORITHM, + 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 int KEYS_INDEX_ID = 0; static final int KEYS_INDEX_KEY_ID = 1; - static final int KEYS_INDEX_IS_MASTER_KEY = 2; - static final int KEYS_INDEX_ALGORITHM = 3; + static final int KEYS_INDEX_ALGORITHM = 2; + static final int KEYS_INDEX_RANK = 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; @@ -231,13 +222,6 @@ public class ViewKeyMainFragment extends Fragment implements public Loader onCreateLoader(int id, Bundle args) { switch (id) { - case LOADER_ID_KEYRING: { - Uri baseUri = 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, KEYRING_PROJECTION, null, null, null); - } case LOADER_ID_USER_IDS: { Uri baseUri = KeychainContract.UserIds.buildUserIdsUri(mDataUri); @@ -263,11 +247,11 @@ public class ViewKeyMainFragment extends Fragment implements // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) switch (loader.getId()) { - case LOADER_ID_KEYRING: + case LOADER_ID_USER_IDS: if (data.moveToFirst()) { // get name, email, and comment from USER_ID String[] mainUserId = PgpKeyHelper.splitUserId(data - .getString(KEYRING_INDEX_USER_ID)); + .getString(INDEX_UID_UID)); if (mainUserId[0] != null) { getActivity().setTitle(mainUserId[0]); mName.setText(mainUserId[0]); @@ -278,9 +262,6 @@ public class ViewKeyMainFragment extends Fragment implements mEmail.setText(mainUserId[1]); mComment.setText(mainUserId[2]); } - - break; - case LOADER_ID_USER_IDS: mUserIdsAdapter.swapCursor(data); break; case LOADER_ID_KEYS: @@ -354,9 +335,6 @@ public class ViewKeyMainFragment extends Fragment implements */ public void onLoaderReset(Loader loader) { switch (loader.getId()) { - case LOADER_ID_KEYRING: - // No resources need to be freed for this ID - break; case LOADER_ID_USER_IDS: mUserIdsAdapter.swapCursor(null); break; @@ -368,11 +346,11 @@ public class ViewKeyMainFragment extends Fragment implements } } - private void encryptToContact(Uri dataUri) { - long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); + // TODO preselect from uri? should be feasible without trivial query + long keyId = Long.parseLong(dataUri.getPathSegments().get(1)); - long[] encryptionKeyIds = new long[]{keyId}; + long[] encryptionKeyIds = new long[]{ keyId }; Intent intent = new Intent(getActivity(), EncryptActivity.class); intent.setAction(EncryptActivity.ACTION_ENCRYPT); intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java index 9d60c1530..adcb5619d 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java @@ -41,7 +41,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter { private int mIndexKeyId; private int mIndexAlgorithm; private int mIndexKeySize; - private int mIndexIsMasterKey; + private int mIndexRank; private int mIndexCanCertify; private int mIndexCanEncrypt; private int mIndexCanSign; @@ -76,7 +76,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter { mIndexKeyId = cursor.getColumnIndexOrThrow(Keys.KEY_ID); mIndexAlgorithm = cursor.getColumnIndexOrThrow(Keys.ALGORITHM); mIndexKeySize = cursor.getColumnIndexOrThrow(Keys.KEY_SIZE); - mIndexIsMasterKey = cursor.getColumnIndexOrThrow(Keys.IS_MASTER_KEY); + mIndexRank = cursor.getColumnIndexOrThrow(Keys.RANK); mIndexCanCertify = cursor.getColumnIndexOrThrow(Keys.CAN_CERTIFY); mIndexCanEncrypt = cursor.getColumnIndexOrThrow(Keys.CAN_ENCRYPT); mIndexCanSign = cursor.getColumnIndexOrThrow(Keys.CAN_SIGN); @@ -103,7 +103,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter { keyId.setText(keyIdStr); keyDetails.setText("(" + algorithmStr + ")"); - if (cursor.getInt(mIndexIsMasterKey) != 1) { + if (cursor.getInt(mIndexRank) == 0) { masterKeyIcon.setVisibility(View.INVISIBLE); } else { masterKeyIcon.setVisibility(View.VISIBLE); 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 3ff88aa2b..cd15c4d2d 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 @@ -98,6 +98,7 @@ public class DeleteKeyDialogFragment extends DialogFragment { checkDeleteSecret = (CheckBox) inflateView.findViewById(R.id.checkDeleteSecret); builder.setTitle(R.string.warning); + /* TODO! redo //If only a single key has been selected if (keyRingRowIds.length == 1) { @@ -210,6 +211,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 3c8b872b0..b8db470b4 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,10 +116,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor secretKey = null; alert.setMessage(R.string.passphrase_for_symmetric_encryption); } else { - // TODO: by master key id??? - secretKey = PgpKeyHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, - secretKeyId)); - // secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId)); + secretKey = ProviderHelper.getPGPSecretKeyByKeyId(activity, secretKeyId); if (secretKey == null) { alert.setTitle(R.string.title_key_not_found); @@ -175,7 +172,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor return; } else { clickSecretKey = PgpKeyHelper.getKeyNum(ProviderHelper - .getPGPSecretKeyRingByKeyId(activity, secretKeyId), + .getPGPSecretKeyRingWithKeyId(activity, secretKeyId), curKeyIndex); curKeyIndex++; // does post-increment work like C? continue;