mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-23 09:52:16 -05:00
Update openpgp-api-library for APIv7
This commit is contained in:
parent
bf344dee5d
commit
e4cfd3c886
@ -45,7 +45,7 @@ import com.fsck.k9.mailstore.LocalFolder;
|
|||||||
import com.fsck.k9.mailstore.StorageManager;
|
import com.fsck.k9.mailstore.StorageManager;
|
||||||
import com.fsck.k9.service.MailService;
|
import com.fsck.k9.service.MailService;
|
||||||
|
|
||||||
import org.openintents.openpgp.util.OpenPgpListPreference;
|
import org.openintents.openpgp.util.OpenPgpAppPreference;
|
||||||
import org.openintents.openpgp.util.OpenPgpUtils;
|
import org.openintents.openpgp.util.OpenPgpUtils;
|
||||||
|
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
private ListPreference mIdleRefreshPeriod;
|
private ListPreference mIdleRefreshPeriod;
|
||||||
private ListPreference mMaxPushFolders;
|
private ListPreference mMaxPushFolders;
|
||||||
private boolean mHasCrypto = false;
|
private boolean mHasCrypto = false;
|
||||||
private OpenPgpListPreference mCryptoApp;
|
private OpenPgpAppPreference mCryptoApp;
|
||||||
|
|
||||||
private PreferenceScreen mSearchScreen;
|
private PreferenceScreen mSearchScreen;
|
||||||
private CheckBoxPreference mCloudSearchEnabled;
|
private CheckBoxPreference mCloudSearchEnabled;
|
||||||
@ -687,7 +687,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
|
|
||||||
mHasCrypto = OpenPgpUtils.isAvailable(this);
|
mHasCrypto = OpenPgpUtils.isAvailable(this);
|
||||||
if (mHasCrypto) {
|
if (mHasCrypto) {
|
||||||
mCryptoApp = (OpenPgpListPreference) findPreference(PREFERENCE_CRYPTO_APP);
|
mCryptoApp = (OpenPgpAppPreference) findPreference(PREFERENCE_CRYPTO_APP);
|
||||||
|
|
||||||
mCryptoApp.setValue(String.valueOf(mAccount.getCryptoApp()));
|
mCryptoApp.setValue(String.valueOf(mAccount.getCryptoApp()));
|
||||||
mCryptoApp.setSummary(mCryptoApp.getEntry());
|
mCryptoApp.setSummary(mCryptoApp.getEntry());
|
||||||
|
@ -285,7 +285,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setUserId(OpenPgpSignatureResult signatureResult) {
|
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) {
|
if (userInfo.name != null) {
|
||||||
resultSignatureName.setText(userInfo.name);
|
resultSignatureName.setText(userInfo.name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -466,7 +466,7 @@
|
|||||||
android:title="@string/account_settings_crypto"
|
android:title="@string/account_settings_crypto"
|
||||||
android:key="crypto">
|
android:key="crypto">
|
||||||
|
|
||||||
<org.openintents.openpgp.util.OpenPgpListPreference
|
<org.openintents.openpgp.util.OpenPgpAppPreference
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:key="crypto_app"
|
android:key="crypto_app"
|
||||||
android:title="@string/account_settings_crypto_app" />
|
android:title="@string/account_settings_crypto_app" />
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.openintents.openpgp"
|
package="org.openintents.openpgp">
|
||||||
android:versionCode="1"
|
|
||||||
android:versionName="1.0" >
|
|
||||||
|
|
||||||
<uses-sdk
|
|
||||||
android:minSdkVersion="9"
|
|
||||||
android:targetSdkVersion="19" />
|
|
||||||
|
|
||||||
<application/>
|
<application/>
|
||||||
|
|
||||||
|
@ -57,8 +57,15 @@ public class OpenPgpApi {
|
|||||||
* - New extra for ACTION_DETACHED_SIGN: EXTRA_DETACHED_SIGNATURE
|
* - 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_DETACHED_SIGNATURE
|
||||||
* - New result for ACTION_DECRYPT_VERIFY: RESULT_CHARSET
|
* - 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
|
* General extras
|
||||||
@ -90,6 +97,9 @@ public class OpenPgpApi {
|
|||||||
* - end cleartext with newline
|
* - end cleartext with newline
|
||||||
* - remove whitespaces on line endings
|
* - remove whitespaces on line endings
|
||||||
* <p/>
|
* <p/>
|
||||||
|
* required extras:
|
||||||
|
* long EXTRA_SIGN_KEY_ID (key id of signing key)
|
||||||
|
* <p/>
|
||||||
* optional extras:
|
* optional extras:
|
||||||
* String EXTRA_PASSPHRASE (key passphrase)
|
* 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)!
|
* 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.
|
* The detached signature is returned separately in RESULT_DETACHED_SIGNATURE.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
* required extras:
|
||||||
|
* long EXTRA_SIGN_KEY_ID (key id of signing key)
|
||||||
|
* <p/>
|
||||||
* optional extras:
|
* optional extras:
|
||||||
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for detached signature)
|
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for detached signature)
|
||||||
* String EXTRA_PASSPHRASE (key passphrase)
|
* String EXTRA_PASSPHRASE (key passphrase)
|
||||||
@ -121,6 +134,7 @@ public class OpenPgpApi {
|
|||||||
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
|
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
|
||||||
* String EXTRA_PASSPHRASE (key passphrase)
|
* String EXTRA_PASSPHRASE (key passphrase)
|
||||||
* String EXTRA_ORIGINAL_FILENAME (original filename to be encrypted as metadata)
|
* 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";
|
public static final String ACTION_ENCRYPT = "org.openintents.openpgp.action.ENCRYPT";
|
||||||
|
|
||||||
@ -133,9 +147,11 @@ public class OpenPgpApi {
|
|||||||
* long[] EXTRA_KEY_IDS
|
* long[] EXTRA_KEY_IDS
|
||||||
* <p/>
|
* <p/>
|
||||||
* optional extras:
|
* optional extras:
|
||||||
|
* long EXTRA_SIGN_KEY_ID (key id of signing key)
|
||||||
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
|
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
|
||||||
* String EXTRA_PASSPHRASE (key passphrase)
|
* String EXTRA_PASSPHRASE (key passphrase)
|
||||||
* String EXTRA_ORIGINAL_FILENAME (original filename to be encrypted as metadata)
|
* 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";
|
public static final String ACTION_SIGN_AND_ENCRYPT = "org.openintents.openpgp.action.SIGN_AND_ENCRYPT";
|
||||||
|
|
||||||
@ -146,6 +162,8 @@ public class OpenPgpApi {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* If OpenPgpSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING
|
* If OpenPgpSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING
|
||||||
* in addition a PendingIntent is returned via RESULT_INTENT to download missing keys.
|
* 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.
|
||||||
* <p/>
|
* <p/>
|
||||||
* optional extras:
|
* optional extras:
|
||||||
* byte[] EXTRA_DETACHED_SIGNATURE (detached signature)
|
* byte[] EXTRA_DETACHED_SIGNATURE (detached signature)
|
||||||
@ -154,6 +172,7 @@ public class OpenPgpApi {
|
|||||||
* OpenPgpSignatureResult RESULT_SIGNATURE
|
* OpenPgpSignatureResult RESULT_SIGNATURE
|
||||||
* OpenPgpDecryptMetadata RESULT_METADATA
|
* OpenPgpDecryptMetadata RESULT_METADATA
|
||||||
* String RESULT_CHARSET (charset which was specified in the headers of ascii armored input, if any)
|
* 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";
|
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";
|
public static final String ACTION_DECRYPT_METADATA = "org.openintents.openpgp.action.DECRYPT_METADATA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select key id for signing
|
||||||
|
* <p/>
|
||||||
|
* optional extras:
|
||||||
|
* String EXTRA_USER_ID
|
||||||
|
* <p/>
|
||||||
|
* 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)
|
* Get key ids based on given user ids (=emails)
|
||||||
* <p/>
|
* <p/>
|
||||||
@ -191,9 +221,11 @@ public class OpenPgpApi {
|
|||||||
*/
|
*/
|
||||||
public static final String ACTION_GET_KEY = "org.openintents.openpgp.action.GET_KEY";
|
public static final String ACTION_GET_KEY = "org.openintents.openpgp.action.GET_KEY";
|
||||||
|
|
||||||
|
|
||||||
/* Intent extras */
|
/* Intent extras */
|
||||||
public static final String EXTRA_API_VERSION = "api_version";
|
public static final String EXTRA_API_VERSION = "api_version";
|
||||||
|
|
||||||
|
// DEPRECATED!!!
|
||||||
public static final String EXTRA_ACCOUNT_NAME = "account_name";
|
public static final String EXTRA_ACCOUNT_NAME = "account_name";
|
||||||
|
|
||||||
// ACTION_DETACHED_SIGN, ENCRYPT, SIGN_AND_ENCRYPT, DECRYPT_VERIFY
|
// ACTION_DETACHED_SIGN, ENCRYPT, SIGN_AND_ENCRYPT, DECRYPT_VERIFY
|
||||||
@ -207,15 +239,20 @@ public class OpenPgpApi {
|
|||||||
// ENCRYPT, SIGN_AND_ENCRYPT
|
// ENCRYPT, SIGN_AND_ENCRYPT
|
||||||
public static final String EXTRA_USER_IDS = "user_ids";
|
public static final String EXTRA_USER_IDS = "user_ids";
|
||||||
public static final String EXTRA_KEY_IDS = "key_ids";
|
public static final String EXTRA_KEY_IDS = "key_ids";
|
||||||
|
public static final String EXTRA_SIGN_KEY_ID = "sign_key_id";
|
||||||
// optional extras:
|
// optional extras:
|
||||||
public static final String EXTRA_PASSPHRASE = "passphrase";
|
public static final String EXTRA_PASSPHRASE = "passphrase";
|
||||||
public static final String EXTRA_ORIGINAL_FILENAME = "original_filename";
|
public static final String EXTRA_ORIGINAL_FILENAME = "original_filename";
|
||||||
|
public static final String EXTRA_ENABLE_COMPRESSION = "enable_compression";
|
||||||
|
|
||||||
// internal NFC states
|
// internal NFC states
|
||||||
public static final String EXTRA_NFC_SIGNED_HASH = "nfc_signed_hash";
|
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_SIG_CREATION_TIMESTAMP = "nfc_sig_creation_timestamp";
|
||||||
public static final String EXTRA_NFC_DECRYPTED_SESSION_KEY = "nfc_decrypted_session_key";
|
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
|
// GET_KEY
|
||||||
public static final String EXTRA_KEY_ID = "key_id";
|
public static final String EXTRA_KEY_ID = "key_id";
|
||||||
public static final String RESULT_KEY_IDS = "key_ids";
|
public static final String RESULT_KEY_IDS = "key_ids";
|
||||||
@ -236,12 +273,16 @@ public class OpenPgpApi {
|
|||||||
|
|
||||||
// DECRYPT_VERIFY
|
// DECRYPT_VERIFY
|
||||||
public static final String EXTRA_DETACHED_SIGNATURE = "detached_signature";
|
public static final String EXTRA_DETACHED_SIGNATURE = "detached_signature";
|
||||||
|
|
||||||
public static final String RESULT_SIGNATURE = "signature";
|
public static final String RESULT_SIGNATURE = "signature";
|
||||||
public static final String RESULT_METADATA = "metadata";
|
public static final String RESULT_METADATA = "metadata";
|
||||||
// This will be the charset which was specified in the headers of ascii armored input, if any
|
// 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_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;
|
IOpenPgpService mService;
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
|
@ -25,12 +25,15 @@ import android.content.res.TypedArray;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.preference.DialogPreference;
|
import android.preference.DialogPreference;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.ListAdapter;
|
import android.widget.ListAdapter;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.openintents.openpgp.R;
|
import org.openintents.openpgp.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -40,7 +43,7 @@ import java.util.List;
|
|||||||
* Does not extend ListPreference, but is very similar to it!
|
* 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
|
* 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 OPENKEYCHAIN_PACKAGE = "org.sufficientlysecure.keychain";
|
||||||
private static final String MARKET_INTENT_URI_BASE = "market://details?id=%s";
|
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(
|
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");
|
PROVIDER_BLACKLIST.add("org.thialfihar.android.apg");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<OpenPgpProviderEntry> mLegacyList = new ArrayList<OpenPgpProviderEntry>();
|
private ArrayList<OpenPgpProviderEntry> mLegacyList = new ArrayList<>();
|
||||||
private ArrayList<OpenPgpProviderEntry> mList = new ArrayList<OpenPgpProviderEntry>();
|
private ArrayList<OpenPgpProviderEntry> mList = new ArrayList<>();
|
||||||
|
|
||||||
private String mSelectedPackage;
|
private String mSelectedPackage;
|
||||||
|
|
||||||
public OpenPgpListPreference(Context context, AttributeSet attrs) {
|
public OpenPgpAppPreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
populateAppList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenPgpListPreference(Context context) {
|
public OpenPgpAppPreference(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,18 +83,177 @@ public class OpenPgpListPreference extends DialogPreference {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPrepareDialogBuilder(Builder builder) {
|
protected void onPrepareDialogBuilder(Builder builder) {
|
||||||
|
|
||||||
|
// do again, maybe an app has now been installed
|
||||||
|
populateAppList();
|
||||||
|
|
||||||
|
// Init ArrayAdapter with OpenPGP Providers
|
||||||
|
ListAdapter adapter = new ArrayAdapter<OpenPgpProviderEntry>(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();
|
mList.clear();
|
||||||
|
|
||||||
// add "none"-entry
|
// add "none"-entry
|
||||||
mList.add(0, new OpenPgpProviderEntry("",
|
mList.add(0, new OpenPgpProviderEntry("",
|
||||||
getContext().getString(R.string.openpgp_list_preference_none),
|
getContext().getString(R.string.openpgp_list_preference_none),
|
||||||
getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
|
getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
|
||||||
|
|
||||||
// add all additional (legacy) providers
|
// add all additional (legacy) providers
|
||||||
mList.addAll(mLegacyList);
|
mList.addAll(mLegacyList);
|
||||||
|
|
||||||
// search for OpenPGP providers...
|
// search for OpenPGP providers...
|
||||||
ArrayList<OpenPgpProviderEntry> providerList = new ArrayList<OpenPgpProviderEntry>();
|
ArrayList<OpenPgpProviderEntry> providerList = new ArrayList<>();
|
||||||
Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT);
|
Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT);
|
||||||
List<ResolveInfo> resInfo = getContext().getPackageManager().queryIntentServices(intent, 0);
|
List<ResolveInfo> resInfo = getContext().getPackageManager().queryIntentServices(intent, 0);
|
||||||
if (!resInfo.isEmpty()) {
|
if (!resInfo.isEmpty()) {
|
||||||
@ -128,117 +291,6 @@ public class OpenPgpListPreference extends DialogPreference {
|
|||||||
// add provider
|
// add provider
|
||||||
mList.addAll(providerList);
|
mList.addAll(providerList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init ArrayAdapter with OpenPGP Providers
|
|
||||||
ListAdapter adapter = new ArrayAdapter<OpenPgpProviderEntry>(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 {
|
private static class OpenPgpProviderEntry {
|
@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* <p/>
|
||||||
|
* 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<SavedState> CREATOR =
|
||||||
|
new Parcelable.Creator<SavedState>() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -71,7 +71,8 @@ public class OpenPgpUtils {
|
|||||||
return hexString;
|
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
|
* Splits userId string into naming part, email part, and comment part
|
||||||
@ -82,22 +83,42 @@ public class OpenPgpUtils {
|
|||||||
* @param userId
|
* @param userId
|
||||||
* @return theParsedUserInfo
|
* @return theParsedUserInfo
|
||||||
*/
|
*/
|
||||||
public static UserInfo splitUserId(final String userId) {
|
public static UserId splitUserId(final String userId) {
|
||||||
if (!TextUtils.isEmpty(userId)) {
|
if (!TextUtils.isEmpty(userId)) {
|
||||||
final Matcher matcher = USER_ID_PATTERN.matcher(userId);
|
final Matcher matcher = USER_ID_PATTERN.matcher(userId);
|
||||||
if (matcher.matches()) {
|
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 name;
|
||||||
public final String email;
|
public final String email;
|
||||||
public final String comment;
|
public final String comment;
|
||||||
|
|
||||||
public UserInfo(String name, String email, String comment) {
|
public UserId(String name, String email, String comment) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
|
@ -3,5 +3,7 @@
|
|||||||
|
|
||||||
<string name="openpgp_list_preference_none">None</string>
|
<string name="openpgp_list_preference_none">None</string>
|
||||||
<string name="openpgp_install_openkeychain_via">Install OpenKeychain via %s</string>
|
<string name="openpgp_install_openkeychain_via">Install OpenKeychain via %s</string>
|
||||||
|
<string name="openpgp_no_key_selected">No key selected</string>
|
||||||
|
<string name="openpgp_key_selected">Key has been selected</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user