diff options
| author | mar-v-in <github@rvin.mooo.com> | 2014-06-18 16:05:01 +0200 | 
|---|---|---|
| committer | mar-v-in <github@rvin.mooo.com> | 2014-06-18 16:14:11 +0200 | 
| commit | 0bcf7a39bf44994dfcc8e4f8cc52084976b597b0 (patch) | |
| tree | 6733feac224cdd7cf4e4e9f9dd939ecc56503561 | |
| parent | 90f9646f2554c48b1d346e68374dbe943ab8aa9f (diff) | |
| download | open-keychain-0bcf7a39bf44994dfcc8e4f8cc52084976b597b0.tar.gz open-keychain-0bcf7a39bf44994dfcc8e4f8cc52084976b597b0.tar.bz2 open-keychain-0bcf7a39bf44994dfcc8e4f8cc52084976b597b0.zip | |
Continue contact db sync
- Only add keyrings to contact db that are not expired nor revoked
- Merge all user ids of a key into one contact (#659)
- Update contacts: Changes in keyrings (user id add, user id revoke, change of primary id) will be updated into contact db
TODO:
- delete contact once keyring is removed from OK
- sync: wait for key downloads to complete before changing contact db
| -rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java | 128 | 
1 files changed, 89 insertions, 39 deletions
| diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index f50ccf6f8..8e4505004 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -22,7 +22,6 @@ import android.accounts.AccountManager;  import android.content.*;  import android.database.Cursor;  import android.net.Uri; -import android.os.RemoteException;  import android.provider.ContactsContract;  import android.util.Patterns;  import org.sufficientlysecure.keychain.Constants; @@ -32,10 +31,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;  import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.util.Log; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*;  public class ContactHelper { @@ -43,12 +39,17 @@ public class ContactHelper {              KeychainContract.KeyRings.USER_ID,              KeychainContract.KeyRings.FINGERPRINT,              KeychainContract.KeyRings.KEY_ID, -            KeychainContract.KeyRings.MASTER_KEY_ID}; +            KeychainContract.KeyRings.MASTER_KEY_ID, +            KeychainContract.KeyRings.EXPIRY, +            KeychainContract.KeyRings.IS_REVOKED}; +    public static final String[] USER_IDS_PROJECTION = new String[]{ +            KeychainContract.UserIds.USER_ID +    };      public static final String[] RAW_CONTACT_ID_PROJECTION = new String[]{ContactsContract.RawContacts._ID};      public static final String FIND_RAW_CONTACT_SELECTION =              ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?"; -    public static final List<String> getMailAccounts(Context context) { +    public static List<String> getMailAccounts(Context context) {          final Account[] accounts = AccountManager.get(context).getAccounts();          final Set<String> emailSet = new HashSet<String>();          for (Account account : accounts) { @@ -88,16 +89,24 @@ public class ContactHelper {          return null;      } +    private static ContentProviderOperation.Builder referenceRawContact(ContentProviderOperation.Builder builder, int rawContactId) { +        return rawContactId == -1 ? +                builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) : +                builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); +    } +      public static void writeKeysToContacts(Context context) {          ContentResolver resolver = context.getContentResolver();          Cursor cursor = resolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), KEYS_TO_CONTACT_PROJECTION,                  null, null, null);          if (cursor != null) {              while (cursor.moveToNext()) { -                String[] userId = KeyRing.splitUserId(cursor.getString(0)); +                String[] primaryUserId = KeyRing.splitUserId(cursor.getString(0));                  String fingerprint = PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1));                  String keyIdShort = PgpKeyHelper.convertKeyIdToHexShort(cursor.getLong(2));                  long masterKeyId = cursor.getLong(3); +                boolean isExpired = !cursor.isNull(4) && new Date(cursor.getLong(4) * 1000).before(new Date()); +                boolean isRevoked = cursor.getInt(5) > 0;                  int rawContactId = -1;                  Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI, RAW_CONTACT_ID_PROJECTION,                          FIND_RAW_CONTACT_SELECTION, new String[]{Constants.PACKAGE_NAME, fingerprint}, null, null); @@ -108,42 +117,83 @@ public class ContactHelper {                      raw.close();                  }                  ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); -                if (rawContactId == -1) { -                    ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) -                            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, context.getString(R.string.app_name)) -                            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.PACKAGE_NAME) -                            .withValue(ContactsContract.RawContacts.SOURCE_ID, fingerprint) -                            .build()); -                    if (userId[0] != null) { -                        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) -                                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) -                                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) -                                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, userId[0]) -                                .build()); +                if (isExpired || isRevoked) { +                    if (rawContactId != -1) { +                        resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.RawContacts._ID + "=?", new String[]{Integer.toString(rawContactId)});                      } -                    if (userId[1] != null) { -                        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) -                                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) -                                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) -                                .withValue(ContactsContract.CommonDataKinds.Email.DATA, userId[1]) -                                .build()); +                } else { +                    if (rawContactId == -1) { +                        insertContact(ops, context, fingerprint); +                        writeContactKey(ops, context, rawContactId, masterKeyId, keyIdShort); +                    } +                    writeContactDisplayName(ops, rawContactId, primaryUserId[0]); +                    writeContactEmail(ops, resolver, rawContactId, masterKeyId); +                    try { +                        resolver.applyBatch(ContactsContract.AUTHORITY, ops); +                    } catch (Exception e) { +                        Log.w(Constants.TAG, e);                      } -                    ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) -                            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) -                            .withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE) -                            .withValue(ContactsContract.Data.DATA1, String.format(context.getString(R.string.contact_show_key), keyIdShort)) -                            .withValue(ContactsContract.Data.DATA2, masterKeyId) -                            .build()); -                } -                try { -                    resolver.applyBatch(ContactsContract.AUTHORITY, ops); -                } catch (RemoteException e) { -                    e.printStackTrace(); -                } catch (OperationApplicationException e) { -                    e.printStackTrace();                  }              }              cursor.close();          }      } + +    private static void insertContact(ArrayList<ContentProviderOperation> ops, Context context, String fingerprint) { +        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) +                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, context.getString(R.string.app_name)) +                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.PACKAGE_NAME) +                .withValue(ContactsContract.RawContacts.SOURCE_ID, fingerprint) +                .build()); +    } + +    private static void writeContactKey(ArrayList<ContentProviderOperation> ops, Context context, int rawContactId, long masterKeyId, String keyIdShort) { +        ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId) +                .withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE) +                .withValue(ContactsContract.Data.DATA1, context.getString(R.string.contact_show_key, keyIdShort)) +                .withValue(ContactsContract.Data.DATA2, masterKeyId) +                .build()); +    } + +    private static void writeContactEmail(ArrayList<ContentProviderOperation> ops, ContentResolver resolver, int rawContactId, long masterKeyId) { +        ops.add(selectByRawContactAndItemType(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI), +                rawContactId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE).build()); +        Cursor ids = resolver.query(KeychainContract.UserIds.buildUserIdsUri(Long.toString(masterKeyId)), USER_IDS_PROJECTION, KeychainContract.UserIds.IS_REVOKED + "=0", null, null); +        if (ids != null) { +            while (ids.moveToNext()) { +                String[] userId = KeyRing.splitUserId(ids.getString(0)); +                if (userId[1] != null) { +                    ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId) +                            .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) +                            .withValue(ContactsContract.CommonDataKinds.Email.DATA, userId[1]) +                            .build()); +                } +            } +            ids.close(); +        } +    } + +    private static void writeContactDisplayName(ArrayList<ContentProviderOperation> ops, int rawContactId, String displayName) { +        if (displayName != null) { +            ops.add(insertOrUpdateForRawContact(ContactsContract.Data.CONTENT_URI, rawContactId, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) +                    .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName) +                    .build()); +        } +    } + +    private static ContentProviderOperation.Builder insertOrUpdateForRawContact(Uri uri, int rawContactId, String itemType) { +        if (rawContactId == -1) { +            return referenceRawContact(ContentProviderOperation.newInsert(uri), rawContactId).withValue(ContactsContract.Data.MIMETYPE, itemType); +        } else { +            return ContentProviderOperation.newUpdate(uri).withSelection( +                    ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", +                    new String[]{Integer.toString(rawContactId), itemType}); +        } +    } + +    private static ContentProviderOperation.Builder selectByRawContactAndItemType(ContentProviderOperation.Builder builder, int rawContactId, String itemType) { +        return builder.withSelection( +                ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", +                new String[]{Integer.toString(rawContactId), itemType}); +    }  } | 
