diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 93c71f5d0..e2d809d9e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -72,52 +72,61 @@ public class OpenPgpService extends RemoteService { * @return */ private Intent getKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { - // find key ids to given emails in database - ArrayList keyIds = new ArrayList(); - + boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0); boolean missingUserIdsCheck = false; boolean duplicateUserIdsCheck = false; + + ArrayList keyIds = new ArrayList(); ArrayList missingUserIds = new ArrayList(); ArrayList duplicateUserIds = new ArrayList(); + if (!noUserIdsCheck) { + for (String email : encryptionUserIds) { + // try to find the key for this specific email + Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); + Cursor cursor = getContentResolver().query(uri, EMAIL_SEARCH_PROJECTION, EMAIL_SEARCH_WHERE, null, null); + try { + // result should be one entry containing the key id + if (cursor != null && cursor.moveToFirst()) { + long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); + keyIds.add(id); + } else { + missingUserIdsCheck = true; + missingUserIds.add(email); + Log.d(Constants.TAG, "user id missing"); + } + // another entry for this email -> too keys with the same email inside user id + if (cursor != null && cursor.moveToNext()) { + duplicateUserIdsCheck = true; + duplicateUserIds.add(email); - for (String email : encryptionUserIds) { - Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); - Cursor cursor = getContentResolver().query(uri, EMAIL_SEARCH_PROJECTION, EMAIL_SEARCH_WHERE, null, null); - try { - if (cursor != null && cursor.moveToFirst()) { - long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); - keyIds.add(id); - } else { - missingUserIdsCheck = true; - missingUserIds.add(email); - Log.d(Constants.TAG, "user id missing"); - } - if (cursor != null && cursor.moveToNext()) { - duplicateUserIdsCheck = true; - duplicateUserIds.add(email); - Log.d(Constants.TAG, "more than one user id with the same email"); - } - } finally { - if (cursor != null) { - cursor.close(); + // also pre-select + long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); + keyIds.add(id); + Log.d(Constants.TAG, "more than one user id with the same email"); + } + } finally { + if (cursor != null) { + cursor.close(); + } } } } - // convert to long[] + // convert ArrayList to long[] long[] keyIdsArray = new long[keyIds.size()]; for (int i = 0; i < keyIdsArray.length; i++) { keyIdsArray[i] = keyIds.get(i); } - // allow the user to verify pub key selection - if (missingUserIdsCheck || duplicateUserIdsCheck) { - // build PendingIntent + if (noUserIdsCheck || missingUserIdsCheck || duplicateUserIdsCheck) { + // allow the user to verify pub key selection + Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS); intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray); + intent.putExtra(RemoteServiceActivity.EXTRA_NO_USER_IDS_CHECK, noUserIdsCheck); intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds); - intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, duplicateUserIds); + intent.putExtra(RemoteServiceActivity.EXTRA_DUPLICATE_USER_IDS, duplicateUserIds); intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, @@ -129,16 +138,18 @@ public class OpenPgpService extends RemoteService { result.putExtra(OpenPgpApi.RESULT_INTENT, pi); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); return result; - } + } else { + // everything was easy, we have exactly one key for every email - if (keyIdsArray.length == 0) { - return null; - } + if (keyIdsArray.length == 0) { + Log.e(Constants.TAG, "keyIdsArray.length == 0, should never happen!"); + } - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_KEY_IDS, keyIdsArray); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); - return result; + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_KEY_IDS, keyIdsArray); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); + return result; + } } private Intent getPassphraseBundleIntent(Intent data, long keyId) { @@ -241,10 +252,9 @@ public class OpenPgpService extends RemoteService { originalFilename = ""; } - long[] keyIds; - if (data.hasExtra(OpenPgpApi.EXTRA_KEY_IDS)) { - keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); - } else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS)) { + // first try to get key ids from non-ambiguous key id extra + long[] keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); + if (keyIds == null) { // get key ids based on given user ids String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); // give params through to activity... @@ -256,14 +266,6 @@ public class OpenPgpService extends RemoteService { // if not success -> result contains a PendingIntent for user interaction return result; } - } else { - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_ERROR, - new OpenPgpError(OpenPgpError.GENERIC_ERROR, - "Missing parameter user_ids or key_ids!") - ); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); - return result; } // build InputData and write into OutputStream diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java index 48c76d561..4b27e115b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java @@ -18,11 +18,20 @@ package org.sufficientlysecure.keychain.remote.ui; import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBarActivity; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.SpannedString; +import android.text.TextUtils; +import android.text.style.BulletSpan; +import android.text.style.StyleSpan; import android.view.View; import android.widget.TextView; @@ -39,7 +48,6 @@ import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import java.security.Provider; import java.util.ArrayList; public class RemoteServiceActivity extends ActionBarActivity { @@ -68,7 +76,8 @@ public class RemoteServiceActivity extends ActionBarActivity { // select pub keys action public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids"; public static final String EXTRA_MISSING_USER_IDS = "missing_user_ids"; - public static final String EXTRA_DUBLICATE_USER_IDS = "dublicate_user_ids"; + public static final String EXTRA_DUPLICATE_USER_IDS = "dublicate_user_ids"; + public static final String EXTRA_NO_USER_IDS_CHECK = "no_user_ids"; // error message public static final String EXTRA_ERROR_MESSAGE = "error_message"; @@ -229,32 +238,41 @@ public class RemoteServiceActivity extends ActionBarActivity { } else if (ACTION_SELECT_PUB_KEYS.equals(action)) { long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS); + boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true); ArrayList missingUserIds = intent .getStringArrayListExtra(EXTRA_MISSING_USER_IDS); ArrayList dublicateUserIds = intent - .getStringArrayListExtra(EXTRA_DUBLICATE_USER_IDS); + .getStringArrayListExtra(EXTRA_DUPLICATE_USER_IDS); + + SpannableStringBuilder ssb = new SpannableStringBuilder(); + final SpannableString textIntro = new SpannableString( + noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids) + : getString(R.string.api_select_pub_keys_text) + ); + textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(textIntro); - // TODO: do this with spannable instead of HTML to prevent parsing failures with weird user ids - String text = "" + getString(R.string.api_select_pub_keys_text) + ""; - text += "

"; if (missingUserIds != null && missingUserIds.size() > 0) { - text += getString(R.string.api_select_pub_keys_missing_text); - text += "
"; - text += "
    "; + ssb.append("\n\n"); + ssb.append(getString(R.string.api_select_pub_keys_missing_text)); + ssb.append("\n"); for (String userId : missingUserIds) { - text += "
  • " + userId + "
  • "; + SpannableString ss = new SpannableString(userId + "\n"); + ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(ss); } - text += "
"; - text += "
"; } if (dublicateUserIds != null && dublicateUserIds.size() > 0) { - text += getString(R.string.api_select_pub_keys_dublicates_text); - text += "
"; - text += "
    "; + ssb.append("\n\n"); + ssb.append(getString(R.string.api_select_pub_keys_dublicates_text)); + ssb.append("\n"); for (String userId : dublicateUserIds) { - text += "
  • " + userId + "
  • "; + SpannableString ss = new SpannableString(userId + "\n"); + ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(ss); } - text += "
"; } // Inflate a "Done"/"Cancel" custom action bar view @@ -284,8 +302,8 @@ public class RemoteServiceActivity extends ActionBarActivity { setContentView(R.layout.api_remote_select_pub_keys); // set text on view - HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_select_pub_keys_text); - textView.setHtmlFromString(text, true); + TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text); + textView.setText(ssb, TextView.BufferType.SPANNABLE); /* Load select pub keys fragment */ // Check that the activity is using the layout version with diff --git a/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml b/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml index a10592607..bf4d0a70d 100644 --- a/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml +++ b/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml @@ -4,13 +4,13 @@ android:layout_height="fill_parent" android:orientation="vertical" > - Allow access
Disallow access Please select a key! - No public keys were found for these identities: - More than one public key exist for these identities: + No keys were found for these identities: + More than one key exist for these identities: Please review the list of recipients! + Please select the recipients! Signature check failed! Have you installed this app from a different source? If you are sure that this is not an attack, revoke this app\'s registration in OpenKeychain and then register the app again.