diff --git a/k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSettings.java b/k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSettings.java
index 9ebeee4f9..19a718bf0 100644
--- a/k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSettings.java
+++ b/k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSettings.java
@@ -45,7 +45,7 @@ import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.StorageManager;
import com.fsck.k9.service.MailService;
-import org.openintents.openpgp.util.OpenPgpListPreference;
+import org.openintents.openpgp.util.OpenPgpAppPreference;
import org.openintents.openpgp.util.OpenPgpUtils;
@@ -174,7 +174,7 @@ public class AccountSettings extends K9PreferenceActivity {
private ListPreference mIdleRefreshPeriod;
private ListPreference mMaxPushFolders;
private boolean mHasCrypto = false;
- private OpenPgpListPreference mCryptoApp;
+ private OpenPgpAppPreference mCryptoApp;
private PreferenceScreen mSearchScreen;
private CheckBoxPreference mCloudSearchEnabled;
@@ -687,7 +687,7 @@ public class AccountSettings extends K9PreferenceActivity {
mHasCrypto = OpenPgpUtils.isAvailable(this);
if (mHasCrypto) {
- mCryptoApp = (OpenPgpListPreference) findPreference(PREFERENCE_CRYPTO_APP);
+ mCryptoApp = (OpenPgpAppPreference) findPreference(PREFERENCE_CRYPTO_APP);
mCryptoApp.setValue(String.valueOf(mAccount.getCryptoApp()));
mCryptoApp.setSummary(mCryptoApp.getEntry());
diff --git a/k9mail/src/main/java/com/fsck/k9/ui/messageview/OpenPgpHeaderView.java b/k9mail/src/main/java/com/fsck/k9/ui/messageview/OpenPgpHeaderView.java
index a13bf1d93..d65c75d15 100644
--- a/k9mail/src/main/java/com/fsck/k9/ui/messageview/OpenPgpHeaderView.java
+++ b/k9mail/src/main/java/com/fsck/k9/ui/messageview/OpenPgpHeaderView.java
@@ -285,7 +285,7 @@ public class OpenPgpHeaderView extends LinearLayout {
}
private void setUserId(OpenPgpSignatureResult signatureResult) {
- final OpenPgpUtils.UserInfo userInfo = OpenPgpUtils.splitUserId(signatureResult.getPrimaryUserId());
+ final OpenPgpUtils.UserId userInfo = OpenPgpUtils.splitUserId(signatureResult.getPrimaryUserId());
if (userInfo.name != null) {
resultSignatureName.setText(userInfo.name);
} else {
diff --git a/k9mail/src/main/res/xml/account_settings_preferences.xml b/k9mail/src/main/res/xml/account_settings_preferences.xml
index a0c5f4a28..d55c87ec1 100644
--- a/k9mail/src/main/res/xml/account_settings_preferences.xml
+++ b/k9mail/src/main/res/xml/account_settings_preferences.xml
@@ -466,7 +466,7 @@
android:title="@string/account_settings_crypto"
android:key="crypto">
-
diff --git a/plugins/openpgp-api-library/src/main/AndroidManifest.xml b/plugins/openpgp-api-library/src/main/AndroidManifest.xml
index 98cb89faa..f1f29cf3c 100644
--- a/plugins/openpgp-api-library/src/main/AndroidManifest.xml
+++ b/plugins/openpgp-api-library/src/main/AndroidManifest.xml
@@ -1,12 +1,6 @@
-
-
+ package="org.openintents.openpgp">
diff --git a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java
index dbfb7971f..7a714050d 100644
--- a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java
+++ b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpApi.java
@@ -57,8 +57,15 @@ public class OpenPgpApi {
* - New extra for ACTION_DETACHED_SIGN: EXTRA_DETACHED_SIGNATURE
* - New result for ACTION_DECRYPT_VERIFY: RESULT_DETACHED_SIGNATURE
* - New result for ACTION_DECRYPT_VERIFY: RESULT_CHARSET
+ * 7:
+ * - Deprecation of ACCOUNT_NAME, please use ACTION_GET_SIGN_KEY_ID to get key id
+ * - Introduce EXTRA_SIGN_KEY_ID
+ * - New extra for ACTION_ENCRYPT and ACTION_SIGN_AND_ENCRYPT: EXTRA_ENABLE_COMPRESSION (default to true)
+ * - Return PendingIntent to view key for signatures
+ * - New result for ACTION_DECRYPT_VERIFY: RESULT_TYPE
+ * - New ACTION_GET_SIGN_KEY_ID
*/
- public static final int API_VERSION = 6;
+ public static final int API_VERSION = 7;
/**
* General extras
@@ -90,6 +97,9 @@ public class OpenPgpApi {
* - end cleartext with newline
* - remove whitespaces on line endings
*
+ * required extras:
+ * long EXTRA_SIGN_KEY_ID (key id of signing key)
+ *
* optional extras:
* String EXTRA_PASSPHRASE (key passphrase)
*/
@@ -100,6 +110,9 @@ public class OpenPgpApi {
* No OutputStream necessary for ACTION_DETACHED_SIGN (No magic pre-processing like in ACTION_CLEARTEXT_SIGN)!
* The detached signature is returned separately in RESULT_DETACHED_SIGNATURE.
*
+ * required extras:
+ * long EXTRA_SIGN_KEY_ID (key id of signing key)
+ *
* optional extras:
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for detached signature)
* String EXTRA_PASSPHRASE (key passphrase)
@@ -121,6 +134,7 @@ public class OpenPgpApi {
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
* String EXTRA_PASSPHRASE (key passphrase)
* String EXTRA_ORIGINAL_FILENAME (original filename to be encrypted as metadata)
+ * boolean EXTRA_ENABLE_COMPRESSION (enable ZLIB compression, default ist true)
*/
public static final String ACTION_ENCRYPT = "org.openintents.openpgp.action.ENCRYPT";
@@ -133,9 +147,11 @@ public class OpenPgpApi {
* long[] EXTRA_KEY_IDS
*
* optional extras:
+ * long EXTRA_SIGN_KEY_ID (key id of signing key)
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
* String EXTRA_PASSPHRASE (key passphrase)
* String EXTRA_ORIGINAL_FILENAME (original filename to be encrypted as metadata)
+ * boolean EXTRA_ENABLE_COMPRESSION (enable ZLIB compression, default ist true)
*/
public static final String ACTION_SIGN_AND_ENCRYPT = "org.openintents.openpgp.action.SIGN_AND_ENCRYPT";
@@ -146,6 +162,8 @@ public class OpenPgpApi {
*
* If OpenPgpSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING
* in addition a PendingIntent is returned via RESULT_INTENT to download missing keys.
+ * On all other status, in addition a PendingIntent is returned via RESULT_INTENT to open
+ * the key view in OpenKeychain.
*
* optional extras:
* byte[] EXTRA_DETACHED_SIGNATURE (detached signature)
@@ -154,6 +172,7 @@ public class OpenPgpApi {
* OpenPgpSignatureResult RESULT_SIGNATURE
* OpenPgpDecryptMetadata RESULT_METADATA
* String RESULT_CHARSET (charset which was specified in the headers of ascii armored input, if any)
+ * int RESULT_TYPE
*/
public static final String ACTION_DECRYPT_VERIFY = "org.openintents.openpgp.action.DECRYPT_VERIFY";
@@ -168,6 +187,17 @@ public class OpenPgpApi {
*/
public static final String ACTION_DECRYPT_METADATA = "org.openintents.openpgp.action.DECRYPT_METADATA";
+ /**
+ * Select key id for signing
+ *
+ * optional extras:
+ * String EXTRA_USER_ID
+ *
+ * returned extras:
+ * long EXTRA_SIGN_KEY_ID
+ */
+ public static final String ACTION_GET_SIGN_KEY_ID = "org.openintents.openpgp.action.GET_SIGN_KEY_ID";
+
/**
* Get key ids based on given user ids (=emails)
*
@@ -191,9 +221,11 @@ public class OpenPgpApi {
*/
public static final String ACTION_GET_KEY = "org.openintents.openpgp.action.GET_KEY";
+
/* Intent extras */
public static final String EXTRA_API_VERSION = "api_version";
+ // DEPRECATED!!!
public static final String EXTRA_ACCOUNT_NAME = "account_name";
// ACTION_DETACHED_SIGN, ENCRYPT, SIGN_AND_ENCRYPT, DECRYPT_VERIFY
@@ -207,15 +239,20 @@ public class OpenPgpApi {
// ENCRYPT, SIGN_AND_ENCRYPT
public static final String EXTRA_USER_IDS = "user_ids";
public static final String EXTRA_KEY_IDS = "key_ids";
+ public static final String EXTRA_SIGN_KEY_ID = "sign_key_id";
// optional extras:
public static final String EXTRA_PASSPHRASE = "passphrase";
public static final String EXTRA_ORIGINAL_FILENAME = "original_filename";
+ public static final String EXTRA_ENABLE_COMPRESSION = "enable_compression";
// internal NFC states
public static final String EXTRA_NFC_SIGNED_HASH = "nfc_signed_hash";
public static final String EXTRA_NFC_SIG_CREATION_TIMESTAMP = "nfc_sig_creation_timestamp";
public static final String EXTRA_NFC_DECRYPTED_SESSION_KEY = "nfc_decrypted_session_key";
+ // GET_SIGN_KEY_ID
+ public static final String EXTRA_USER_ID = "user_id";
+
// GET_KEY
public static final String EXTRA_KEY_ID = "key_id";
public static final String RESULT_KEY_IDS = "key_ids";
@@ -236,12 +273,16 @@ public class OpenPgpApi {
// DECRYPT_VERIFY
public static final String EXTRA_DETACHED_SIGNATURE = "detached_signature";
-
public static final String RESULT_SIGNATURE = "signature";
public static final String RESULT_METADATA = "metadata";
// This will be the charset which was specified in the headers of ascii armored input, if any
public static final String RESULT_CHARSET = "charset";
+ public static final String RESULT_TYPE = "type";
+ public static final int RESULT_TYPE_UNENCRYPTED_UNSIGNED = 0;
+ public static final int RESULT_TYPE_ENCRYPTED = 1;
+ public static final int RESULT_TYPE_SIGNED = 2;
+
IOpenPgpService mService;
Context mContext;
diff --git a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpAppPreference.java
similarity index 81%
rename from plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java
rename to plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpAppPreference.java
index 31ba97c33..6e8ddad84 100644
--- a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpListPreference.java
+++ b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpAppPreference.java
@@ -25,12 +25,15 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.preference.DialogPreference;
+import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
+
import org.openintents.openpgp.R;
import java.util.ArrayList;
@@ -40,7 +43,7 @@ import java.util.List;
* Does not extend ListPreference, but is very similar to it!
* http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/preference/ListPreference.java/?v=source
*/
-public class OpenPgpListPreference extends DialogPreference {
+public class OpenPgpAppPreference extends DialogPreference {
private static final String OPENKEYCHAIN_PACKAGE = "org.sufficientlysecure.keychain";
private static final String MARKET_INTENT_URI_BASE = "market://details?id=%s";
private static final Intent MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse(
@@ -53,16 +56,17 @@ public class OpenPgpListPreference extends DialogPreference {
PROVIDER_BLACKLIST.add("org.thialfihar.android.apg");
}
- private ArrayList mLegacyList = new ArrayList();
- private ArrayList mList = new ArrayList();
+ private ArrayList mLegacyList = new ArrayList<>();
+ private ArrayList mList = new ArrayList<>();
private String mSelectedPackage;
- public OpenPgpListPreference(Context context, AttributeSet attrs) {
+ public OpenPgpAppPreference(Context context, AttributeSet attrs) {
super(context, attrs);
+ populateAppList();
}
- public OpenPgpListPreference(Context context) {
+ public OpenPgpAppPreference(Context context) {
this(context, null);
}
@@ -79,18 +83,177 @@ public class OpenPgpListPreference extends DialogPreference {
@Override
protected void onPrepareDialogBuilder(Builder builder) {
+
+ // do again, maybe an app has now been installed
+ populateAppList();
+
+ // Init ArrayAdapter with OpenPGP Providers
+ ListAdapter adapter = new ArrayAdapter(getContext(),
+ android.R.layout.select_dialog_singlechoice, android.R.id.text1, mList) {
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // User super class to create the View
+ View v = super.getView(position, convertView, parent);
+ TextView tv = (TextView) v.findViewById(android.R.id.text1);
+
+ // Put the image on the TextView
+ tv.setCompoundDrawablesWithIntrinsicBounds(mList.get(position).icon, null,
+ null, null);
+
+ // Add margin between image and text (support various screen densities)
+ int dp10 = (int) (10 * getContext().getResources().getDisplayMetrics().density + 0.5f);
+ tv.setCompoundDrawablePadding(dp10);
+
+ return v;
+ }
+ };
+
+ builder.setSingleChoiceItems(adapter, getIndexOfProviderList(mSelectedPackage),
+ new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ OpenPgpProviderEntry entry = mList.get(which);
+
+ if (entry.intent != null) {
+ /*
+ * Intents are called as activity
+ *
+ * Current approach is to assume the user installed the app.
+ * If he does not, the selected package is not valid.
+ *
+ * However applications should always consider this could happen,
+ * as the user might remove the currently used OpenPGP app.
+ */
+ getContext().startActivity(entry.intent);
+ return;
+ }
+
+ mSelectedPackage = entry.packageName;
+
+ /*
+ * Clicking on an item simulates the positive button click, and dismisses
+ * the dialog.
+ */
+ OpenPgpAppPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
+ dialog.dismiss();
+ }
+ });
+
+ /*
+ * The typical interaction for list-based dialogs is to have click-on-an-item dismiss the
+ * dialog instead of the user having to press 'Ok'.
+ */
+ builder.setPositiveButton(null, null);
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult && (mSelectedPackage != null)) {
+ save();
+ }
+ }
+
+ private void save() {
+ // Give the client a chance to ignore this change if they deem it
+ // invalid
+ if (!callChangeListener(mSelectedPackage)) {
+ // They don't want the value to be set
+ return;
+ }
+
+ setAndPersist(mSelectedPackage);
+ }
+
+ private void setAndPersist(String packageName) {
+ mSelectedPackage = packageName;
+
+ // Save to persistent storage (this method will make sure this
+ // preference should be persistent, along with other useful checks)
+ persistString(mSelectedPackage);
+
+ // Data has changed, notify so UI can be refreshed!
+ notifyChanged();
+
+ // also update summary with selected provider
+ updateSummary(mSelectedPackage);
+ }
+
+ private void updateSummary(String packageName) {
+ String summary = getEntryByValue(packageName);
+ setSummary(summary);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return getEntryByValue(mSelectedPackage);
+ }
+
+ private int getIndexOfProviderList(String packageName) {
+ for (OpenPgpProviderEntry app : mList) {
+ if (app.packageName.equals(packageName)) {
+ return mList.indexOf(app);
+ }
+ }
+
+ // default is "none"
+ return 0;
+ }
+
+ public String getEntry() {
+ return getEntryByValue(mSelectedPackage);
+ }
+
+ public String getValue() {
+ return mSelectedPackage;
+ }
+
+ public void setValue(String packageName) {
+ setAndPersist(packageName);
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getString(index);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ if (restoreValue) {
+ // Restore state
+ mSelectedPackage = getPersistedString(mSelectedPackage);
+ updateSummary(mSelectedPackage);
+ } else {
+ String value = (String) defaultValue;
+ setAndPersist(value);
+ updateSummary(value);
+ }
+ }
+
+ public String getEntryByValue(String packageName) {
+ for (OpenPgpProviderEntry app : mList) {
+ if (app.packageName.equals(packageName) && app.intent == null) {
+ return app.simpleName;
+ }
+ }
+
+ return getContext().getString(R.string.openpgp_list_preference_none);
+ }
+
+ private void populateAppList() {
mList.clear();
-
+
// add "none"-entry
mList.add(0, new OpenPgpProviderEntry("",
getContext().getString(R.string.openpgp_list_preference_none),
getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
-
+
// add all additional (legacy) providers
mList.addAll(mLegacyList);
-
+
// search for OpenPGP providers...
- ArrayList providerList = new ArrayList();
+ ArrayList providerList = new ArrayList<>();
Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT);
List resInfo = getContext().getPackageManager().queryIntentServices(intent, 0);
if (!resInfo.isEmpty()) {
@@ -128,117 +291,6 @@ public class OpenPgpListPreference extends DialogPreference {
// add provider
mList.addAll(providerList);
}
-
- // Init ArrayAdapter with OpenPGP Providers
- ListAdapter adapter = new ArrayAdapter(getContext(),
- android.R.layout.select_dialog_singlechoice, android.R.id.text1, mList) {
- public View getView(int position, View convertView, ViewGroup parent) {
- // User super class to create the View
- View v = super.getView(position, convertView, parent);
- TextView tv = (TextView) v.findViewById(android.R.id.text1);
-
- // Put the image on the TextView
- tv.setCompoundDrawablesWithIntrinsicBounds(mList.get(position).icon, null,
- null, null);
-
- // Add margin between image and text (support various screen densities)
- int dp10 = (int) (10 * getContext().getResources().getDisplayMetrics().density + 0.5f);
- tv.setCompoundDrawablePadding(dp10);
-
- return v;
- }
- };
-
- builder.setSingleChoiceItems(adapter, getIndexOfProviderList(getValue()),
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- OpenPgpProviderEntry entry = mList.get(which);
-
- if (entry.intent != null) {
- /*
- * Intents are called as activity
- *
- * Current approach is to assume the user installed the app.
- * If he does not, the selected package is not valid.
- *
- * However applications should always consider this could happen,
- * as the user might remove the currently used OpenPGP app.
- */
- getContext().startActivity(entry.intent);
- }
-
- mSelectedPackage = entry.packageName;
-
- /*
- * Clicking on an item simulates the positive button click, and dismisses
- * the dialog.
- */
- OpenPgpListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
- dialog.dismiss();
- }
- });
-
- /*
- * The typical interaction for list-based dialogs is to have click-on-an-item dismiss the
- * dialog instead of the user having to press 'Ok'.
- */
- builder.setPositiveButton(null, null);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (positiveResult && (mSelectedPackage != null)) {
- if (callChangeListener(mSelectedPackage)) {
- setValue(mSelectedPackage);
- }
- }
- }
-
- private int getIndexOfProviderList(String packageName) {
- for (OpenPgpProviderEntry app : mList) {
- if (app.packageName.equals(packageName)) {
- return mList.indexOf(app);
- }
- }
-
- return -1;
- }
-
- public void setValue(String packageName) {
- mSelectedPackage = packageName;
- persistString(packageName);
- }
-
- public String getValue() {
- return mSelectedPackage;
- }
-
- public String getEntry() {
- return getEntryByValue(mSelectedPackage);
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getString(index);
- }
-
- @Override
- protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
- setValue(restoreValue ? getPersistedString(mSelectedPackage) : (String) defaultValue);
- }
-
- public String getEntryByValue(String packageName) {
- for (OpenPgpProviderEntry app : mList) {
- if (app.packageName.equals(packageName)) {
- return app.simpleName;
- }
- }
-
- return null;
}
private static class OpenPgpProviderEntry {
diff --git a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpKeyPreference.java b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpKeyPreference.java
new file mode 100644
index 000000000..e5bd8ea03
--- /dev/null
+++ b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpKeyPreference.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openintents.openpgp.util;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.Preference;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import org.openintents.openpgp.IOpenPgpService;
+import org.openintents.openpgp.OpenPgpError;
+import org.openintents.openpgp.R;
+
+public class OpenPgpKeyPreference extends Preference {
+ private long mKeyId;
+ private String mOpenPgpProvider;
+ private OpenPgpServiceConnection mServiceConnection;
+ private String mDefaultUserId;
+
+ public static final int REQUEST_CODE_KEY_PREFERENCE = 9999;
+
+ public OpenPgpKeyPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return (mKeyId == 0) ? getContext().getString(R.string.openpgp_no_key_selected)
+ : getContext().getString(R.string.openpgp_key_selected);
+ }
+
+ private void updateEnabled() {
+ if (TextUtils.isEmpty(mOpenPgpProvider)) {
+ setEnabled(false);
+ } else {
+ setEnabled(true);
+ }
+ }
+
+ public void setOpenPgpProvider(String packageName) {
+ mOpenPgpProvider = packageName;
+ updateEnabled();
+ }
+
+ public void setDefaultUserId(String userId) {
+ mDefaultUserId = userId;
+ }
+
+ @Override
+ protected void onClick() {
+ // bind to service
+ mServiceConnection = new OpenPgpServiceConnection(
+ getContext().getApplicationContext(),
+ mOpenPgpProvider,
+ new OpenPgpServiceConnection.OnBound() {
+ @Override
+ public void onBound(IOpenPgpService service) {
+ Log.d(OpenPgpApi.TAG, "onBound!");
+
+ Intent data = new Intent();
+ data.setAction(OpenPgpApi.ACTION_GET_SIGN_KEY_ID);
+ data.putExtra(OpenPgpApi.EXTRA_USER_ID, mDefaultUserId);
+
+ OpenPgpApi api = new OpenPgpApi(getContext(), mServiceConnection.getService());
+ api.executeApiAsync(data, null, null, new MyCallback(REQUEST_CODE_KEY_PREFERENCE));
+ }
+
+ @Override
+ public void onError(Exception e) {
+ Log.e(OpenPgpApi.TAG, "exception when binding!", e);
+ }
+ }
+ );
+ mServiceConnection.bindToService();
+ }
+
+ private class MyCallback implements OpenPgpApi.IOpenPgpCallback {
+ int requestCode;
+
+ private MyCallback(int requestCode) {
+ this.requestCode = requestCode;
+ }
+
+ @Override
+ public void onReturn(Intent result) {
+ switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
+ case OpenPgpApi.RESULT_CODE_SUCCESS: {
+ Log.e(OpenPgpApi.TAG, "RESULT_CODE_SUCCESS: Should not happen!");
+
+ break;
+ }
+ case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: {
+
+ PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
+ try {
+ Activity act = (Activity) getContext();
+ act.startIntentSenderFromChild(
+ act, pi.getIntentSender(),
+ requestCode, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(OpenPgpApi.TAG, "SendIntentException", e);
+ }
+ break;
+ }
+ case OpenPgpApi.RESULT_CODE_ERROR: {
+ OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
+ Log.e(OpenPgpApi.TAG, "RESULT_CODE_ERROR: " + error.getMessage());
+
+ break;
+ }
+ }
+ }
+ }
+
+ private void save(long newValue) {
+ // Give the client a chance to ignore this change if they deem it
+ // invalid
+ if (!callChangeListener(newValue)) {
+ // They don't want the value to be set
+ return;
+ }
+
+ setAndPersist(newValue);
+ }
+
+ private void setAndPersist(long newValue) {
+ mKeyId = newValue;
+
+ // Save to persistent storage (this method will make sure this
+ // preference should be persistent, along with other useful checks)
+ persistLong(mKeyId);
+
+ // Data has changed, notify so UI can be refreshed!
+ notifyChanged();
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ // This preference type's value type is Long, so we read the default
+ // value from the attributes as an Integer.
+ return (long) a.getInteger(index, 0);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ if (restoreValue) {
+ // Restore state
+ mKeyId = getPersistedLong(mKeyId);
+ } else {
+ // Set state
+ long value = (Long) defaultValue;
+ setAndPersist(value);
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ /*
+ * Suppose a client uses this preference type without persisting. We
+ * must save the instance state so it is able to, for example, survive
+ * orientation changes.
+ */
+
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) {
+ // No need to save instance state since it's persistent
+ return superState;
+ }
+
+ // Save the instance state
+ final SavedState myState = new SavedState(superState);
+ myState.keyId = mKeyId;
+ myState.openPgpProvider = mOpenPgpProvider;
+ myState.defaultUserId = mDefaultUserId;
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (!state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ // Restore the instance state
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ mKeyId = myState.keyId;
+ mOpenPgpProvider = myState.openPgpProvider;
+ mDefaultUserId = myState.defaultUserId;
+ notifyChanged();
+ }
+
+ /**
+ * SavedState, a subclass of {@link BaseSavedState}, will store the state
+ * of MyPreference, a subclass of Preference.
+ *
+ * It is important to always call through to super methods.
+ */
+ private static class SavedState extends BaseSavedState {
+ long keyId;
+ String openPgpProvider;
+ String defaultUserId;
+
+ public SavedState(Parcel source) {
+ super(source);
+
+ keyId = source.readInt();
+ openPgpProvider = source.readString();
+ defaultUserId = source.readString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+
+ dest.writeLong(keyId);
+ dest.writeString(openPgpProvider);
+ dest.writeString(defaultUserId);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public static final Parcelable.Creator CREATOR =
+ new Parcelable.Creator() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ public boolean handleOnActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_KEY_PREFERENCE && resultCode == Activity.RESULT_OK) {
+ long keyId = data.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, 0);
+ save(keyId);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java
index ef0a88ce1..ad5f47b9a 100644
--- a/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java
+++ b/plugins/openpgp-api-library/src/main/java/org/openintents/openpgp/util/OpenPgpUtils.java
@@ -71,7 +71,8 @@ public class OpenPgpUtils {
return hexString;
}
- private static final Pattern USER_ID_PATTERN = Pattern.compile("^(.*?)(?: (\\[.*\\]))?(?: \\((.*)\\))?(?: <(.*)>)?$");
+
+ private static final Pattern USER_ID_PATTERN = Pattern.compile("^(.*?)(?: \\((.*)\\))?(?: <(.*)>)?$");
/**
* Splits userId string into naming part, email part, and comment part
@@ -82,22 +83,42 @@ public class OpenPgpUtils {
* @param userId
* @return theParsedUserInfo
*/
- public static UserInfo splitUserId(final String userId) {
+ public static UserId splitUserId(final String userId) {
if (!TextUtils.isEmpty(userId)) {
final Matcher matcher = USER_ID_PATTERN.matcher(userId);
if (matcher.matches()) {
- return new UserInfo(matcher.group(1), matcher.group(4), matcher.group(3));
+ return new UserId(matcher.group(1), matcher.group(3), matcher.group(2));
}
}
- return new UserInfo(null, null, null);
+ return new UserId(null, null, null);
}
- public static class UserInfo {
+ /**
+ * Returns a composed user id. Returns null if name is null!
+ *
+ * @param name
+ * @param email
+ * @param comment
+ * @return
+ */
+ public static String createUserId(UserId userId) {
+ String userIdString = userId.name; // consider name a required value
+ if (userIdString != null && !TextUtils.isEmpty(userId.comment)) {
+ userIdString += " (" + userId.comment + ")";
+ }
+ if (userIdString != null && !TextUtils.isEmpty(userId.email)) {
+ userIdString += " <" + userId.email + ">";
+ }
+
+ return userIdString;
+ }
+
+ public static class UserId {
public final String name;
public final String email;
public final String comment;
- public UserInfo(String name, String email, String comment) {
+ public UserId(String name, String email, String comment) {
this.name = name;
this.email = email;
this.comment = comment;
diff --git a/plugins/openpgp-api-library/src/main/res/values/strings.xml b/plugins/openpgp-api-library/src/main/res/values/strings.xml
index 0119831cc..a45524f41 100644
--- a/plugins/openpgp-api-library/src/main/res/values/strings.xml
+++ b/plugins/openpgp-api-library/src/main/res/values/strings.xml
@@ -3,5 +3,7 @@
None
Install OpenKeychain via %s
+ No key selected
+ Key has been selected
\ No newline at end of file