diff options
Diffstat (limited to 'OpenKeychain/src')
8 files changed, 119 insertions, 11 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 9a2011205..31c809334 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! --> <application @@ -91,6 +92,11 @@ <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ui.KeyListActivity" /> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key" /> + </intent-filter> </activity> <activity android:name=".ui.ViewCertActivity" diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 0fd109484..c769da421 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -46,6 +46,8 @@ public final class Constants { public static final String INTENT_PREFIX = PACKAGE_NAME + ".action."; + public static final String CUSTOM_CONTACT_DATA_MIME_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key"; + public static final class Path { public static final String APP_DIR = Environment.getExternalStorageDirectory() + "/OpenKeychain"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 3ac3a9dee..5d6a62f9c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable; import android.os.Environment; import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PRNGFixes; @@ -79,14 +80,14 @@ public class KeychainApplication extends Application { brandGlowEffect(getApplicationContext(), getApplicationContext().getResources().getColor(R.color.emphasis)); - setupAccountAsNeeded(); + setupAccountAsNeeded(this); } - private void setupAccountAsNeeded() { - AccountManager manager = AccountManager.get(this); - Account[] accounts = manager.getAccountsByType(getPackageName()); + public static void setupAccountAsNeeded(Context context) { + AccountManager manager = AccountManager.get(context); + Account[] accounts = manager.getAccountsByType(Constants.PACKAGE_NAME); if (accounts == null || accounts.length == 0) { - Account dummy = new Account(getString(R.string.app_name), getPackageName()); + Account dummy = new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME); manager.addAccountExplicitly(dummy, null, null); } } 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 583543c4a..4b85d7e80 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -19,11 +19,17 @@ package org.sufficientlysecure.keychain.helper; import android.accounts.Account; import android.accounts.AccountManager; -import android.content.ContentResolver; -import android.content.Context; +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; +import org.sufficientlysecure.keychain.R; +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; @@ -32,6 +38,15 @@ import java.util.Set; public class ContactHelper { + public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{ + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.FINGERPRINT, + KeychainContract.KeyRings.KEY_ID, + KeychainContract.KeyRings.MASTER_KEY_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) { final Account[] accounts = AccountManager.get(context).getAccounts(); final Set<String> emailSet = new HashSet<String>(); @@ -60,4 +75,74 @@ public class ContactHelper { mailCursor.close(); return new ArrayList<String>(mails); } + + public static Uri dataUriFromContactUri(Context context, Uri contactUri) { + Cursor contactMasterKey = context.getContentResolver().query(contactUri, new String[]{ContactsContract.Data.DATA2}, null, null, null, null); + if (contactMasterKey != null) { + if (contactMasterKey.moveToNext()) { + return KeychainContract.KeyRings.buildGenericKeyRingUri(contactMasterKey.getLong(0)); + } + contactMasterKey.close(); + } + return null; + } + + 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 = PgpKeyHelper.splitUserId(cursor.getString(0)); + String fingerprint = PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1)); + String keyIdShort = PgpKeyHelper.convertKeyIdToHexShort(cursor.getLong(2)); + long masterKeyId = cursor.getLong(3); + 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); + if (raw != null) { + if (raw.moveToNext()) { + rawContactId = raw.getInt(0); + } + 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 (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()); + } + 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(); + } + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 4d0397196..a52dbfa27 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -24,6 +24,8 @@ import android.content.ContentProviderClient; import android.content.Intent; import android.content.SyncResult; import android.os.*; +import org.sufficientlysecure.keychain.KeychainApplication; +import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.helper.EmailKeyHelper; import org.sufficientlysecure.keychain.util.Log; @@ -60,6 +62,8 @@ public class ContactSyncAdapterService extends Service { } } }))); + KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); + ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index bed116f5f..010144851 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -32,6 +33,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.provider.ContactsContract; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -47,6 +49,7 @@ import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.helper.ExportHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; @@ -125,7 +128,7 @@ public class ViewKeyActivity extends ActionBarActivity implements switchToTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB); } - Uri dataUri = getIntent().getData(); + Uri dataUri = getDataUri(); if (dataUri == null) { Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); finish(); @@ -163,6 +166,14 @@ public class ViewKeyActivity extends ActionBarActivity implements mViewPager.setCurrentItem(switchToTab); } + private Uri getDataUri() { + Uri dataUri = getIntent().getData(); + if (dataUri != null && dataUri.getHost().equals(ContactsContract.AUTHORITY)) { + dataUri = ContactHelper.dataUriFromContactUri(this, dataUri); + } + return dataUri; + } + private void loadData(Uri dataUri) { mDataUri = dataUri; diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 09f76c675..ec6b389ed 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -521,5 +521,6 @@ <string name="error_no_encrypt_subkey">No encryption subkey available!</string> <string name="info_no_manual_account_creation">Do not create OpenKeychain-Accounts manually. For more information, see Help.</string> + <string name="contact_show_key">Show key (%s)</string> </resources> diff --git a/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml b/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml index 3318f3b45..5f5f2be80 100644 --- a/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml +++ b/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml @@ -1,7 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <ContactsSource xmlns:android="http://schemas.android.com/apk/res/android"> <ContactsDataKind android:mimeType="vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key" - android:icon="@drawable/key_small" - android:summaryColumn="data1" - android:detailColumn="data2"/> + android:detailColumn="data1"/> </ContactsSource>
\ No newline at end of file |