mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-27 03:32:16 -05:00
Remove legacy APG interface
This commit is contained in:
parent
99991e6651
commit
352fb8fd25
@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.fsck.k9.view.MessageCryptoView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout_decrypt"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/crypto_signature"
|
||||
android:orientation="horizontal"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="2"
|
||||
android:gravity="center_vertical">
|
||||
<RelativeLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/ic_crypto_signature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/signed_large"/>
|
||||
<ImageView
|
||||
android:id="@+id/ic_crypto_signature_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/overlay_error"/>
|
||||
</RelativeLayout>
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:paddingLeft="5dip">
|
||||
<TextView
|
||||
android:id="@+id/userId"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"/>
|
||||
<TextView
|
||||
android:id="@+id/userIdRest"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:text="@string/btn_decrypt"
|
||||
android:id="@+id/btn_decrypt"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</com.fsck.k9.view.MessageCryptoView>
|
@ -250,8 +250,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/message_view_crypto_layout" />
|
||||
|
||||
<include layout="@layout/message_view_openpgp_layout"/>
|
||||
|
||||
</com.fsck.k9.view.MessageHeader>
|
||||
|
@ -569,6 +569,7 @@ Please submit bug reports, contribute new features and ask questions at
|
||||
<string name="account_settings_crypto_auto_encrypt">Auto-encrypt</string>
|
||||
<string name="account_settings_crypto_auto_encrypt_summary">Automatically set encrypt if a public key matches a recipient.</string>
|
||||
<string name="account_settings_crypto_apg_not_installed">APG not installed</string>
|
||||
<string name="account_settings_no_openpgp_provider_installed">No OpenPGP Provider installed</string>
|
||||
|
||||
<string name="account_settings_mail_check_frequency_label">Folder poll frequency</string>
|
||||
|
||||
|
@ -24,8 +24,6 @@ import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection;
|
||||
import com.fsck.k9.crypto.Apg;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
@ -135,6 +133,7 @@ public class Account implements BaseAccount {
|
||||
|
||||
public static final SortType DEFAULT_SORT_TYPE = SortType.SORT_DATE;
|
||||
public static final boolean DEFAULT_SORT_ASCENDING = false;
|
||||
public static final String NO_OPENPGP_PROVIDER = "";
|
||||
|
||||
|
||||
/**
|
||||
@ -206,16 +205,12 @@ public class Account implements BaseAccount {
|
||||
private boolean mStripSignature;
|
||||
private boolean mSyncRemoteDeletions;
|
||||
private String mCryptoApp;
|
||||
private boolean mCryptoAutoSignature;
|
||||
private boolean mCryptoAutoEncrypt;
|
||||
private boolean mMarkMessageAsReadOnView;
|
||||
private boolean mAlwaysShowCcBcc;
|
||||
private boolean mAllowRemoteSearch;
|
||||
private boolean mRemoteSearchFullText;
|
||||
private int mRemoteSearchNumResults;
|
||||
|
||||
private CryptoProvider mCryptoProvider = null;
|
||||
|
||||
private ColorChip mUnreadColorChip;
|
||||
private ColorChip mReadColorChip;
|
||||
|
||||
@ -303,9 +298,7 @@ public class Account implements BaseAccount {
|
||||
mReplyAfterQuote = DEFAULT_REPLY_AFTER_QUOTE;
|
||||
mStripSignature = DEFAULT_STRIP_SIGNATURE;
|
||||
mSyncRemoteDeletions = true;
|
||||
mCryptoApp = Apg.NAME;
|
||||
mCryptoAutoSignature = false;
|
||||
mCryptoAutoEncrypt = false;
|
||||
mCryptoApp = NO_OPENPGP_PROVIDER;
|
||||
mAllowRemoteSearch = false;
|
||||
mRemoteSearchFullText = false;
|
||||
mRemoteSearchNumResults = DEFAULT_REMOTE_SEARCH_NUM_RESULTS;
|
||||
@ -492,9 +485,7 @@ public class Account implements BaseAccount {
|
||||
mIsSignatureBeforeQuotedText = prefs.getBoolean(mUuid + ".signatureBeforeQuotedText", false);
|
||||
identities = loadIdentities(prefs);
|
||||
|
||||
mCryptoApp = prefs.getString(mUuid + ".cryptoApp", Apg.NAME);
|
||||
mCryptoAutoSignature = prefs.getBoolean(mUuid + ".cryptoAutoSignature", false);
|
||||
mCryptoAutoEncrypt = prefs.getBoolean(mUuid + ".cryptoAutoEncrypt", false);
|
||||
mCryptoApp = prefs.getString(mUuid + ".cryptoApp", NO_OPENPGP_PROVIDER);
|
||||
mAllowRemoteSearch = prefs.getBoolean(mUuid + ".allowRemoteSearch", false);
|
||||
mRemoteSearchFullText = prefs.getBoolean(mUuid + ".remoteSearchFullText", false);
|
||||
mRemoteSearchNumResults = prefs.getInt(mUuid + ".remoteSearchNumResults", DEFAULT_REMOTE_SEARCH_NUM_RESULTS);
|
||||
@ -756,8 +747,6 @@ public class Account implements BaseAccount {
|
||||
editor.putBoolean(mUuid + ".replyAfterQuote", mReplyAfterQuote);
|
||||
editor.putBoolean(mUuid + ".stripSignature", mStripSignature);
|
||||
editor.putString(mUuid + ".cryptoApp", mCryptoApp);
|
||||
editor.putBoolean(mUuid + ".cryptoAutoSignature", mCryptoAutoSignature);
|
||||
editor.putBoolean(mUuid + ".cryptoAutoEncrypt", mCryptoAutoEncrypt);
|
||||
editor.putBoolean(mUuid + ".allowRemoteSearch", mAllowRemoteSearch);
|
||||
editor.putBoolean(mUuid + ".remoteSearchFullText", mRemoteSearchFullText);
|
||||
editor.putInt(mUuid + ".remoteSearchNumResults", mRemoteSearchNumResults);
|
||||
@ -1646,24 +1635,6 @@ public class Account implements BaseAccount {
|
||||
|
||||
public void setCryptoApp(String cryptoApp) {
|
||||
mCryptoApp = cryptoApp;
|
||||
// invalidate the provider
|
||||
mCryptoProvider = null;
|
||||
}
|
||||
|
||||
public boolean getCryptoAutoSignature() {
|
||||
return mCryptoAutoSignature;
|
||||
}
|
||||
|
||||
public void setCryptoAutoSignature(boolean cryptoAutoSignature) {
|
||||
mCryptoAutoSignature = cryptoAutoSignature;
|
||||
}
|
||||
|
||||
public boolean isCryptoAutoEncrypt() {
|
||||
return mCryptoAutoEncrypt;
|
||||
}
|
||||
|
||||
public void setCryptoAutoEncrypt(boolean cryptoAutoEncrypt) {
|
||||
mCryptoAutoEncrypt = cryptoAutoEncrypt;
|
||||
}
|
||||
|
||||
public boolean allowRemoteSearch() {
|
||||
@ -1706,13 +1677,6 @@ public class Account implements BaseAccount {
|
||||
lastSelectedFolderName = folderName;
|
||||
}
|
||||
|
||||
public synchronized CryptoProvider getCryptoProvider() {
|
||||
if (mCryptoProvider == null) {
|
||||
mCryptoProvider = CryptoProvider.createInstance(getCryptoApp());
|
||||
}
|
||||
return mCryptoProvider;
|
||||
}
|
||||
|
||||
public synchronized String getOpenPgpProvider() {
|
||||
// return null if set to "APG" or "None"
|
||||
if (getCryptoApp().equals("apg") || getCryptoApp().equals("")) {
|
||||
|
@ -82,7 +82,6 @@ import com.fsck.k9.activity.loader.AttachmentInfoLoader;
|
||||
import com.fsck.k9.activity.misc.Attachment;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.crypto.OpenPgpApiHelper;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.ProgressDialogFragment;
|
||||
@ -127,9 +126,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
|
||||
private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1;
|
||||
private static final int DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED = 2;
|
||||
private static final int DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY = 3;
|
||||
private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 4;
|
||||
private static final int DIALOG_CHOOSE_IDENTITY = 5;
|
||||
private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 3;
|
||||
private static final int DIALOG_CHOOSE_IDENTITY = 4;
|
||||
|
||||
private static final long INVALID_DRAFT_ID = MessagingController.INVALID_MESSAGE_ID;
|
||||
|
||||
@ -313,9 +311,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
private ImageButton mAddBccFromContacts;
|
||||
|
||||
private PgpData mPgpData = null;
|
||||
private boolean mAutoEncrypt = false;
|
||||
private boolean mContinueWithoutPublicKey = false;
|
||||
|
||||
private String mOpenPgpProvider;
|
||||
private OpenPgpServiceConnection mOpenPgpServiceConnection;
|
||||
|
||||
@ -506,7 +501,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
* Save will attempt to replace the message in the given folder with the updated version.
|
||||
* Discard will delete the message from the given folder.
|
||||
* @param context
|
||||
* @param message
|
||||
* @param messageReference
|
||||
*/
|
||||
public static void actionEditDraft(Context context, MessageReference messageReference) {
|
||||
Intent i = new Intent(context, MessageCompose.class);
|
||||
@ -656,17 +651,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(android.text.Editable s) {
|
||||
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||
if (mAutoEncrypt && crypto.isAvailable(getApplicationContext())) {
|
||||
for (Address address : getRecipientAddresses()) {
|
||||
if (crypto.hasPublicKeyForEmail(getApplicationContext(),
|
||||
address.getAddress())) {
|
||||
mEncryptCheckbox.setChecked(true);
|
||||
mContinueWithoutPublicKey = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do nothing */
|
||||
}
|
||||
};
|
||||
|
||||
@ -858,7 +843,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
|
||||
initializeCrypto();
|
||||
|
||||
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||
mOpenPgpProvider = mAccount.getOpenPgpProvider();
|
||||
if (mOpenPgpProvider != null) {
|
||||
// New OpenPGP Provider API
|
||||
@ -878,44 +862,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
}
|
||||
});
|
||||
|
||||
if (mAccount.getCryptoAutoSignature()) {
|
||||
// TODO: currently disabled for new openpgp providers (see AccountSettings)
|
||||
}
|
||||
updateMessageFormat();
|
||||
// TODO: currently disabled for new openpgp providers (see AccountSettings)
|
||||
mAutoEncrypt = false;
|
||||
//mAutoEncrypt = mAccount.isCryptoAutoEncrypt();
|
||||
} else if (crypto.isAvailable(this)) {
|
||||
mEncryptLayout.setVisibility(View.VISIBLE);
|
||||
mCryptoSignatureCheckbox.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
CheckBox checkBox = (CheckBox) v;
|
||||
if (checkBox.isChecked()) {
|
||||
mPreventDraftSaving = true;
|
||||
if (!crypto.selectSecretKey(MessageCompose.this, mPgpData)) {
|
||||
mPreventDraftSaving = false;
|
||||
}
|
||||
checkBox.setChecked(false);
|
||||
} else {
|
||||
mPgpData.setSignatureKeyId(0);
|
||||
updateEncryptLayout();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (mAccount.getCryptoAutoSignature()) {
|
||||
long ids[] = crypto.getSecretKeyIdsFromEmail(this, mIdentity.getEmail());
|
||||
if (ids != null && ids.length > 0) {
|
||||
mPgpData.setSignatureKeyId(ids[0]);
|
||||
mPgpData.setSignatureUserId(crypto.getUserId(this, ids[0]));
|
||||
} else {
|
||||
mPgpData.setSignatureKeyId(0);
|
||||
mPgpData.setSignatureUserId(null);
|
||||
}
|
||||
}
|
||||
updateEncryptLayout();
|
||||
mAutoEncrypt = mAccount.isCryptoAutoEncrypt();
|
||||
} else {
|
||||
mEncryptLayout.setVisibility(View.GONE);
|
||||
}
|
||||
@ -1108,11 +1055,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
mCryptoSignatureUserIdRest.setText("");
|
||||
|
||||
String userId = mPgpData.getSignatureUserId();
|
||||
if (userId == null) {
|
||||
userId = mAccount.getCryptoProvider().getUserId(this, mPgpData.getSignatureKeyId());
|
||||
mPgpData.setSignatureUserId(userId);
|
||||
}
|
||||
|
||||
if (userId != null) {
|
||||
String chunks[] = mPgpData.getSignatureUserId().split(" <", 2);
|
||||
mCryptoSignatureUserId.setText(chunks[0]);
|
||||
@ -1795,8 +1737,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
}
|
||||
|
||||
private void performSend() {
|
||||
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||
|
||||
if (mOpenPgpProvider != null) {
|
||||
// OpenPGP Provider API
|
||||
|
||||
@ -1831,44 +1771,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
// encryptedData set in pgpData!
|
||||
return;
|
||||
}
|
||||
} else if (crypto.isAvailable(this)) {
|
||||
// Legacy APG API
|
||||
|
||||
if (mEncryptCheckbox.isChecked() && !mPgpData.hasEncryptionKeys()) {
|
||||
// key selection before encryption
|
||||
StringBuilder emails = new StringBuilder();
|
||||
for (Address address : getRecipientAddresses()) {
|
||||
if (emails.length() != 0) {
|
||||
emails.append(',');
|
||||
}
|
||||
emails.append(address.getAddress());
|
||||
if (!mContinueWithoutPublicKey &&
|
||||
!crypto.hasPublicKeyForEmail(this, address.getAddress())) {
|
||||
showDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (emails.length() != 0) {
|
||||
emails.append(',');
|
||||
}
|
||||
emails.append(mIdentity.getEmail());
|
||||
|
||||
mPreventDraftSaving = true;
|
||||
if (!crypto.selectEncryptionKeys(MessageCompose.this, emails.toString(), mPgpData)) {
|
||||
mPreventDraftSaving = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPgpData.hasEncryptionKeys() || mPgpData.hasSignatureKey()) {
|
||||
if (mPgpData.getEncryptedData() == null) {
|
||||
String text = buildText(false).getText();
|
||||
mPreventDraftSaving = true;
|
||||
crypto.encrypt(this, text, mPgpData);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
sendMessage();
|
||||
|
||||
@ -2053,7 +1955,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
*/
|
||||
@SuppressLint("InlinedApi")
|
||||
private void onAddAttachment2(final String mime_type) {
|
||||
if (mAccount.getCryptoProvider().isAvailable(this) || mAccount.getOpenPgpProvider() != null) {
|
||||
if (mAccount.getOpenPgpProvider() != null) {
|
||||
Toast.makeText(this, R.string.attachment_encryption_unsupported, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
@ -2252,10 +2154,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAccount.getCryptoProvider().onActivityResult(this, requestCode, resultCode, data, mPgpData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
@ -2661,26 +2559,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
}
|
||||
})
|
||||
.create();
|
||||
case DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY:
|
||||
return new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.continue_without_public_key_dlg_title)
|
||||
.setMessage(R.string.continue_without_public_key_instructions_fmt)
|
||||
.setPositiveButton(R.string.continue_action, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||
mContinueWithoutPublicKey = true;
|
||||
onSend();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.back_action, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||
mContinueWithoutPublicKey = false;
|
||||
}
|
||||
})
|
||||
.create();
|
||||
case DIALOG_CONFIRM_DISCARD_ON_BACK:
|
||||
return new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.confirm_discard_draft_message_title)
|
||||
|
@ -697,7 +697,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
||||
} else {
|
||||
final Preference mCryptoMenu = findPreference(PREFERENCE_CRYPTO);
|
||||
mCryptoMenu.setEnabled(false);
|
||||
mCryptoMenu.setSummary(R.string.account_settings_crypto_apg_not_installed);
|
||||
mCryptoMenu.setSummary(R.string.account_settings_no_openpgp_provider_installed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,588 +0,0 @@
|
||||
package com.fsck.k9.crypto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.activity.MessageCompose;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
|
||||
/**
|
||||
* APG integration.
|
||||
*/
|
||||
public class Apg extends CryptoProvider {
|
||||
static final long serialVersionUID = 0x21071235;
|
||||
public static final String NAME = "apg";
|
||||
|
||||
private static final String mApgPackageName = "org.thialfihar.android.apg";
|
||||
private static final int mMinRequiredVersion = 16;
|
||||
|
||||
public static final String AUTHORITY = "org.thialfihar.android.apg.provider";
|
||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID =
|
||||
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/key_id/");
|
||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS =
|
||||
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/emails/");
|
||||
|
||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID =
|
||||
Uri.parse("content://" + AUTHORITY + "/key_rings/public/key_id/");
|
||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS =
|
||||
Uri.parse("content://" + AUTHORITY + "/key_rings/public/emails/");
|
||||
|
||||
public static class Intent {
|
||||
public static final String DECRYPT = "org.thialfihar.android.apg.intent.DECRYPT";
|
||||
public static final String ENCRYPT = "org.thialfihar.android.apg.intent.ENCRYPT";
|
||||
public static final String DECRYPT_FILE = "org.thialfihar.android.apg.intent.DECRYPT_FILE";
|
||||
public static final String ENCRYPT_FILE = "org.thialfihar.android.apg.intent.ENCRYPT_FILE";
|
||||
public static final String DECRYPT_AND_RETURN = "org.thialfihar.android.apg.intent.DECRYPT_AND_RETURN";
|
||||
public static final String ENCRYPT_AND_RETURN = "org.thialfihar.android.apg.intent.ENCRYPT_AND_RETURN";
|
||||
public static final String SELECT_PUBLIC_KEYS = "org.thialfihar.android.apg.intent.SELECT_PUBLIC_KEYS";
|
||||
public static final String SELECT_SECRET_KEY = "org.thialfihar.android.apg.intent.SELECT_SECRET_KEY";
|
||||
}
|
||||
|
||||
public static final String EXTRA_TEXT = "text";
|
||||
public static final String EXTRA_DATA = "data";
|
||||
public static final String EXTRA_ERROR = "error";
|
||||
public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage";
|
||||
public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage";
|
||||
public static final String EXTRA_SIGNATURE = "signature";
|
||||
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
|
||||
public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId";
|
||||
public static final String EXTRA_SIGNATURE_SUCCESS = "signatureSuccess";
|
||||
public static final String EXTRA_SIGNATURE_UNKNOWN = "signatureUnknown";
|
||||
public static final String EXTRA_USER_ID = "userId";
|
||||
public static final String EXTRA_KEY_ID = "keyId";
|
||||
public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryptionKeyIds";
|
||||
public static final String EXTRA_SELECTION = "selection";
|
||||
public static final String EXTRA_MESSAGE = "message";
|
||||
public static final String EXTRA_INTENT_VERSION = "intentVersion";
|
||||
|
||||
public static final String INTENT_VERSION = "1";
|
||||
|
||||
// Note: The support package only allows us to use the lower 16 bits of a request code.
|
||||
public static final int DECRYPT_MESSAGE = 0x0000A001;
|
||||
public static final int ENCRYPT_MESSAGE = 0x0000A002;
|
||||
public static final int SELECT_PUBLIC_KEYS = 0x0000A003;
|
||||
public static final int SELECT_SECRET_KEY = 0x0000A004;
|
||||
|
||||
public static Pattern PGP_MESSAGE =
|
||||
Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
|
||||
Pattern.DOTALL);
|
||||
|
||||
public static Pattern PGP_SIGNED_MESSAGE =
|
||||
Pattern.compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
||||
Pattern.DOTALL);
|
||||
|
||||
public static Apg createInstance() {
|
||||
return new Apg();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether APG is installed and at a high enough version.
|
||||
*
|
||||
* @param context
|
||||
* @return whether a suitable version of APG was found
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailable(Context context) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(mApgPackageName, 0);
|
||||
if (pi.versionCode >= mMinRequiredVersion) {
|
||||
return true;
|
||||
} else {
|
||||
Toast.makeText(context,
|
||||
R.string.error_apg_version_not_supported, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// not found
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the signature key.
|
||||
*
|
||||
* @param activity
|
||||
* @param pgpData
|
||||
* @return success or failure
|
||||
*/
|
||||
@Override
|
||||
public boolean selectSecretKey(Activity activity, PgpData pgpData) {
|
||||
android.content.Intent intent = new android.content.Intent(Intent.SELECT_SECRET_KEY);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
try {
|
||||
activity.startActivityForResult(intent, Apg.SELECT_SECRET_KEY);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(activity,
|
||||
R.string.error_activity_not_found,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select encryption keys.
|
||||
*
|
||||
* @param activity
|
||||
* @param emails The emails that should be used for preselection.
|
||||
* @param pgpData
|
||||
* @return success or failure
|
||||
*/
|
||||
@Override
|
||||
public boolean selectEncryptionKeys(Activity activity, String emails, PgpData pgpData) {
|
||||
android.content.Intent intent = new android.content.Intent(Apg.Intent.SELECT_PUBLIC_KEYS);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
long[] initialKeyIds = null;
|
||||
if (!pgpData.hasEncryptionKeys()) {
|
||||
List<Long> keyIds = new ArrayList<Long>();
|
||||
if (pgpData.hasSignatureKey()) {
|
||||
keyIds.add(pgpData.getSignatureKeyId());
|
||||
}
|
||||
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(
|
||||
Apg.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS,
|
||||
emails);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" },
|
||||
null, null, null);
|
||||
if (c != null) {
|
||||
while (c.moveToNext()) {
|
||||
keyIds.add(c.getLong(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(activity,
|
||||
activity.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (!keyIds.isEmpty()) {
|
||||
initialKeyIds = new long[keyIds.size()];
|
||||
for (int i = 0, size = keyIds.size(); i < size; ++i) {
|
||||
initialKeyIds[i] = keyIds.get(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
initialKeyIds = pgpData.getEncryptionKeys();
|
||||
}
|
||||
intent.putExtra(Apg.EXTRA_SELECTION, initialKeyIds);
|
||||
try {
|
||||
activity.startActivityForResult(intent, Apg.SELECT_PUBLIC_KEYS);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(activity,
|
||||
R.string.error_activity_not_found,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get secret key ids based on a given email.
|
||||
*
|
||||
* @param context
|
||||
* @param email The email in question.
|
||||
* @return key ids
|
||||
*/
|
||||
@Override
|
||||
public long[] getSecretKeyIdsFromEmail(Context context, String email) {
|
||||
long ids[] = null;
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS,
|
||||
email);
|
||||
Cursor c = context.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" },
|
||||
null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
ids = new long[c.getCount()];
|
||||
while (c.moveToNext()) {
|
||||
ids[c.getPosition()] = c.getLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(context,
|
||||
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public key ids based on a given email.
|
||||
*
|
||||
* @param context
|
||||
* @param email The email in question.
|
||||
* @return key ids
|
||||
*/
|
||||
@Override
|
||||
public long[] getPublicKeyIdsFromEmail(Context context, String email) {
|
||||
long ids[] = null;
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = context.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
ids = new long[c.getCount()];
|
||||
while (c.moveToNext()) {
|
||||
ids[c.getPosition()] = c.getLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(context,
|
||||
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a given email has a secret key.
|
||||
*
|
||||
* @param context
|
||||
* @param email The email in question.
|
||||
* @return true if there is a secret key for this email.
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSecretKeyForEmail(Context context, String email) {
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = context.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
c.close();
|
||||
return true;
|
||||
}
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(context,
|
||||
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a given email has a public key.
|
||||
*
|
||||
* @param context
|
||||
* @param email The email in question.
|
||||
* @return true if there is a public key for this email.
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPublicKeyForEmail(Context context, String email) {
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = context.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
c.close();
|
||||
return true;
|
||||
}
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(context,
|
||||
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user id based on the key id.
|
||||
*
|
||||
* @param context
|
||||
* @param keyId
|
||||
* @return user id
|
||||
*/
|
||||
@Override
|
||||
public String getUserId(Context context, long keyId) {
|
||||
String userId = null;
|
||||
try {
|
||||
Uri contentUri = ContentUris.withAppendedId(
|
||||
Apg.CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID,
|
||||
keyId);
|
||||
Cursor c = context.getContentResolver().query(contentUri,
|
||||
new String[] { "user_id" },
|
||||
null, null, null);
|
||||
if (c != null && c.moveToFirst()) {
|
||||
userId = c.getString(0);
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(context,
|
||||
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
if (userId == null) {
|
||||
userId = context.getString(R.string.unknown_crypto_signature_user_id);
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the activity results that concern us.
|
||||
*
|
||||
* @param activity
|
||||
* @param requestCode
|
||||
* @param resultCode
|
||||
* @param data
|
||||
* @return handled or not
|
||||
*/
|
||||
@Override
|
||||
public boolean onActivityResult(Activity activity, int requestCode, int resultCode,
|
||||
android.content.Intent data, PgpData pgpData) {
|
||||
switch (requestCode) {
|
||||
case Apg.SELECT_SECRET_KEY:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
break;
|
||||
}
|
||||
pgpData.setSignatureKeyId(data.getLongExtra(Apg.EXTRA_KEY_ID, 0));
|
||||
pgpData.setSignatureUserId(data.getStringExtra(Apg.EXTRA_USER_ID));
|
||||
((MessageCompose) activity).updateEncryptLayout();
|
||||
break;
|
||||
|
||||
case Apg.SELECT_PUBLIC_KEYS:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
pgpData.setEncryptionKeys(null);
|
||||
((MessageCompose) activity).onEncryptionKeySelectionDone();
|
||||
break;
|
||||
}
|
||||
pgpData.setEncryptionKeys(data.getLongArrayExtra(Apg.EXTRA_SELECTION));
|
||||
((MessageCompose) activity).onEncryptionKeySelectionDone();
|
||||
break;
|
||||
|
||||
case Apg.ENCRYPT_MESSAGE:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
pgpData.setEncryptionKeys(null);
|
||||
((MessageCompose) activity).onEncryptDone();
|
||||
break;
|
||||
}
|
||||
pgpData.setEncryptedData(data.getStringExtra(Apg.EXTRA_ENCRYPTED_MESSAGE));
|
||||
// this was a stupid bug in an earlier version, just gonna leave this in for an APG
|
||||
// version or two
|
||||
if (pgpData.getEncryptedData() == null) {
|
||||
pgpData.setEncryptedData(data.getStringExtra(Apg.EXTRA_DECRYPTED_MESSAGE));
|
||||
}
|
||||
if (pgpData.getEncryptedData() != null) {
|
||||
((MessageCompose) activity).onEncryptDone();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDecryptActivityResult(CryptoDecryptCallback callback, int requestCode,
|
||||
int resultCode, android.content.Intent data, PgpData pgpData) {
|
||||
|
||||
switch (requestCode) {
|
||||
case Apg.DECRYPT_MESSAGE: {
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
pgpData.setSignatureUserId(data.getStringExtra(Apg.EXTRA_SIGNATURE_USER_ID));
|
||||
pgpData.setSignatureKeyId(data.getLongExtra(Apg.EXTRA_SIGNATURE_KEY_ID, 0));
|
||||
pgpData.setSignatureSuccess(data.getBooleanExtra(Apg.EXTRA_SIGNATURE_SUCCESS, false));
|
||||
pgpData.setSignatureUnknown(data.getBooleanExtra(Apg.EXTRA_SIGNATURE_UNKNOWN, false));
|
||||
|
||||
pgpData.setDecryptedData(data.getStringExtra(Apg.EXTRA_DECRYPTED_MESSAGE));
|
||||
callback.onDecryptDone(pgpData);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the encrypt activity.
|
||||
*
|
||||
* @param activity
|
||||
* @param data
|
||||
* @param pgpData
|
||||
* @return success or failure
|
||||
*/
|
||||
@Override
|
||||
public boolean encrypt(Activity activity, String data, PgpData pgpData) {
|
||||
android.content.Intent intent = new android.content.Intent(Intent.ENCRYPT_AND_RETURN);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(Apg.EXTRA_TEXT, data);
|
||||
intent.putExtra(Apg.EXTRA_ENCRYPTION_KEY_IDS, pgpData.getEncryptionKeys());
|
||||
intent.putExtra(Apg.EXTRA_SIGNATURE_KEY_ID, pgpData.getSignatureKeyId());
|
||||
try {
|
||||
activity.startActivityForResult(intent, Apg.ENCRYPT_MESSAGE);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(activity,
|
||||
R.string.error_activity_not_found,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the decrypt activity.
|
||||
*
|
||||
* @param fragment
|
||||
* @param data
|
||||
* @param pgpData
|
||||
* @return success or failure
|
||||
*/
|
||||
@Override
|
||||
public boolean decrypt(Fragment fragment, String data, PgpData pgpData) {
|
||||
android.content.Intent intent = new android.content.Intent(Apg.Intent.DECRYPT_AND_RETURN);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
intent.setType("text/plain");
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
intent.putExtra(EXTRA_TEXT, data);
|
||||
fragment.startActivityForResult(intent, Apg.DECRYPT_MESSAGE);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(fragment.getActivity(), R.string.error_activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted(Message message) {
|
||||
String data = null;
|
||||
try {
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
}
|
||||
if (part != null) {
|
||||
data = MimeUtility.getTextFromPart(part);
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
// guess not...
|
||||
// TODO: maybe log this?
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher matcher = PGP_MESSAGE.matcher(data);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSigned(Message message) {
|
||||
String data = null;
|
||||
try {
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
}
|
||||
if (part != null) {
|
||||
data = MimeUtility.getTextFromPart(part);
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
// guess not...
|
||||
// TODO: maybe log this?
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher matcher = PGP_SIGNED_MESSAGE.matcher(data);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the provider.
|
||||
*
|
||||
* @return provider name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the APG installation.
|
||||
*
|
||||
* @return success or failure
|
||||
*/
|
||||
@Override
|
||||
public boolean test(Context context) {
|
||||
if (!isAvailable(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// try out one content provider to check permissions
|
||||
Uri contentUri = ContentUris.withAppendedId(
|
||||
Apg.CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID,
|
||||
12345);
|
||||
Cursor c = context.getContentResolver().query(contentUri,
|
||||
new String[] { "user_id" },
|
||||
null, null, null);
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// if there was a problem, then let the user know, this will not stop K9/APG from
|
||||
// working, but some features won't be available, so we can still return "true"
|
||||
Toast.makeText(context,
|
||||
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package com.fsck.k9.crypto;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.app.Fragment;
|
||||
|
||||
import com.fsck.k9.mail.Message;
|
||||
|
||||
/**
|
||||
* A CryptoProvider provides functionalities such as encryption, decryption, digital signatures.
|
||||
* It currently also stores the results of such encryption or decryption.
|
||||
* TODO: separate the storage from the provider
|
||||
*/
|
||||
abstract public class CryptoProvider {
|
||||
static final long serialVersionUID = 0x21071234;
|
||||
|
||||
abstract public boolean isAvailable(Context context);
|
||||
abstract public boolean isEncrypted(Message message);
|
||||
abstract public boolean isSigned(Message message);
|
||||
abstract public boolean onActivityResult(Activity activity, int requestCode, int resultCode,
|
||||
Intent data, PgpData pgpData);
|
||||
abstract public boolean onDecryptActivityResult(CryptoDecryptCallback callback,
|
||||
int requestCode, int resultCode, Intent data, PgpData pgpData);
|
||||
abstract public boolean selectSecretKey(Activity activity, PgpData pgpData);
|
||||
abstract public boolean selectEncryptionKeys(Activity activity, String emails, PgpData pgpData);
|
||||
abstract public boolean encrypt(Activity activity, String data, PgpData pgpData);
|
||||
abstract public boolean decrypt(Fragment fragment, String data, PgpData pgpData);
|
||||
abstract public long[] getSecretKeyIdsFromEmail(Context context, String email);
|
||||
abstract public long[] getPublicKeyIdsFromEmail(Context context, String email);
|
||||
abstract public boolean hasSecretKeyForEmail(Context context, String email);
|
||||
abstract public boolean hasPublicKeyForEmail(Context context, String email);
|
||||
abstract public String getUserId(Context context, long keyId);
|
||||
abstract public String getName();
|
||||
abstract public boolean test(Context context);
|
||||
|
||||
public static CryptoProvider createInstance(String name) {
|
||||
if (Apg.NAME.equals(name)) {
|
||||
return Apg.createInstance();
|
||||
}
|
||||
|
||||
return None.createInstance();
|
||||
}
|
||||
|
||||
public interface CryptoDecryptCallback {
|
||||
void onDecryptDone(PgpData pgpData);
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package com.fsck.k9.crypto;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.fsck.k9.mail.Message;
|
||||
|
||||
/**
|
||||
* Dummy CryptoProvider for when cryptography is disabled. It is never "available" and doesn't
|
||||
* do anything.
|
||||
*/
|
||||
public class None extends CryptoProvider {
|
||||
static final long serialVersionUID = 0x21071230;
|
||||
public static final String NAME = "";
|
||||
|
||||
public static None createInstance() {
|
||||
return new None();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Context context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectSecretKey(Activity activity, PgpData pgpData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectEncryptionKeys(Activity activity, String emails, PgpData pgpData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getSecretKeyIdsFromEmail(Context context, String email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getPublicKeyIdsFromEmail(Context context, String email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSecretKeyForEmail(Context context, String email) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPublicKeyForEmail(Context context, String email) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserId(Context context, long keyId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(Activity activity, int requestCode, int resultCode,
|
||||
android.content.Intent data, PgpData pgpData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDecryptActivityResult(CryptoDecryptCallback callback, int requestCode,
|
||||
int resultCode, Intent data, PgpData pgpData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean encrypt(Activity activity, String data, PgpData pgpData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decrypt(Fragment fragment, String data, PgpData pgpData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted(Message message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSigned(Message message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Context context) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -30,7 +30,6 @@ import com.fsck.k9.activity.ChooseFolder;
|
||||
import com.fsck.k9.activity.MessageReference;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.CryptoProvider.CryptoDecryptCallback;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
|
||||
import com.fsck.k9.helper.FileBrowserHelper;
|
||||
@ -49,7 +48,7 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
||||
|
||||
public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
CryptoDecryptCallback, ConfirmationDialogFragmentListener {
|
||||
ConfirmationDialogFragmentListener {
|
||||
|
||||
private static final String ARG_REFERENCE = "reference";
|
||||
|
||||
@ -427,10 +426,6 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (mAccount.getCryptoProvider().onDecryptActivityResult(this, requestCode, resultCode, data, mPgpData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
@ -732,20 +727,6 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
// This REALLY should be in MessageCryptoView
|
||||
@Override
|
||||
public void onDecryptDone(PgpData pgpData) {
|
||||
Account account = mAccount;
|
||||
LocalMessage message = (LocalMessage) mMessage;
|
||||
MessagingController controller = mController;
|
||||
Listener listener = mListener;
|
||||
try {
|
||||
mMessageView.setMessage(account, message, pgpData, controller, listener);
|
||||
} catch (MessagingException e) {
|
||||
Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void showDialog(int dialogId) {
|
||||
DialogFragment fragment;
|
||||
switch (dialogId) {
|
||||
|
@ -13,7 +13,6 @@ import com.fsck.k9.Account.SortType;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.Account.FolderMode;
|
||||
import com.fsck.k9.crypto.Apg;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
import com.fsck.k9.preferences.Settings.*;
|
||||
|
||||
@ -50,13 +49,8 @@ public class AccountSettings {
|
||||
new V(1, new ColorSetting(0xFF0000FF))
|
||||
));
|
||||
s.put("cryptoApp", Settings.versions(
|
||||
new V(1, new StringSetting(Apg.NAME))
|
||||
));
|
||||
s.put("cryptoAutoEncrypt", Settings.versions(
|
||||
new V(3, new BooleanSetting(false))
|
||||
));
|
||||
s.put("cryptoAutoSignature", Settings.versions(
|
||||
new V(1, new BooleanSetting(false))
|
||||
new V(1, new StringSetting("apg")),
|
||||
new V(36, new StringSetting(Account.NO_OPENPGP_PROVIDER))
|
||||
));
|
||||
s.put("defaultQuotedTextShown", Settings.versions(
|
||||
new V(1, new BooleanSetting(Account.DEFAULT_QUOTED_TEXT_SHOWN))
|
||||
|
@ -35,7 +35,7 @@ public class Settings {
|
||||
*
|
||||
* @see SettingsExporter
|
||||
*/
|
||||
public static final int VERSION = 35;
|
||||
public static final int VERSION = 36;
|
||||
|
||||
public static Map<String, Object> validate(int version, Map<String,
|
||||
TreeMap<Integer, SettingsDescription>> settings,
|
||||
|
@ -1,140 +0,0 @@
|
||||
package com.fsck.k9.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.app.Fragment;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.*;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
|
||||
|
||||
public class MessageCryptoView extends LinearLayout {
|
||||
|
||||
private Context mContext;
|
||||
private Fragment mFragment;
|
||||
private Button mDecryptButton;
|
||||
private LinearLayout mCryptoSignatureLayout = null;
|
||||
private ImageView mCryptoSignatureStatusImage = null;
|
||||
private TextView mCryptoSignatureUserId = null;
|
||||
private TextView mCryptoSignatureUserIdRest = null;
|
||||
|
||||
|
||||
public MessageCryptoView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setupChildViews() {
|
||||
mCryptoSignatureLayout = (LinearLayout) findViewById(R.id.crypto_signature);
|
||||
mCryptoSignatureStatusImage = (ImageView) findViewById(R.id.ic_crypto_signature_status);
|
||||
mCryptoSignatureUserId = (TextView) findViewById(R.id.userId);
|
||||
mCryptoSignatureUserIdRest = (TextView) findViewById(R.id.userIdRest);
|
||||
mCryptoSignatureLayout.setVisibility(View.INVISIBLE);
|
||||
mDecryptButton = (Button) findViewById(R.id.btn_decrypt);
|
||||
}
|
||||
|
||||
public void setFragment(Fragment fragment) {
|
||||
mFragment = fragment;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void hide() {
|
||||
this.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the decrypt layout with signature data, if known, make controls visible, if
|
||||
* they should be visible.
|
||||
*/
|
||||
public void updateLayout(final CryptoProvider cryptoProvider, final PgpData pgpData, final Message message) {
|
||||
if (pgpData.getSignatureKeyId() != 0) {
|
||||
mCryptoSignatureUserIdRest.setText(
|
||||
mContext.getString(R.string.key_id, Long.toHexString(pgpData.getSignatureKeyId() & 0xffffffffL)));
|
||||
String userId = pgpData.getSignatureUserId();
|
||||
if (userId == null) {
|
||||
userId = mContext.getString(R.string.unknown_crypto_signature_user_id);
|
||||
}
|
||||
String chunks[] = userId.split(" <", 2);
|
||||
String name = chunks[0];
|
||||
if (chunks.length > 1) {
|
||||
mCryptoSignatureUserIdRest.setText("<" + chunks[1]);
|
||||
}
|
||||
mCryptoSignatureUserId.setText(name);
|
||||
if (pgpData.getSignatureSuccess()) {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
|
||||
} else if (pgpData.getSignatureUnknown()) {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||
} else {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||
}
|
||||
mCryptoSignatureLayout.setVisibility(View.VISIBLE);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mCryptoSignatureLayout.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if ((message == null) && (pgpData.getDecryptedData() == null)) {
|
||||
this.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
if (pgpData.getDecryptedData() != null) {
|
||||
if (pgpData.getSignatureKeyId() == 0) {
|
||||
this.setVisibility(View.GONE);
|
||||
} else {
|
||||
// no need to show this after decryption/verification
|
||||
mDecryptButton.setVisibility(View.GONE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mDecryptButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
String data = null;
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
}
|
||||
if (part != null) {
|
||||
data = MimeUtility.getTextFromPart(part);
|
||||
}
|
||||
cryptoProvider.decrypt(mFragment, data, pgpData);
|
||||
} catch (MessagingException me) {
|
||||
Log.e(K9.LOG_TAG, "Unable to decrypt email.", me);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
mDecryptButton.setVisibility(View.VISIBLE);
|
||||
if (cryptoProvider.isEncrypted(message)) {
|
||||
mDecryptButton.setText(R.string.btn_decrypt);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
} else if (cryptoProvider.isSigned(message)) {
|
||||
mDecryptButton.setText(R.string.btn_verify);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
this.setVisibility(View.GONE);
|
||||
try {
|
||||
// check for PGP/MIME encryption
|
||||
Part pgp = MimeUtility.findFirstPartByMimeType(message, "application/pgp-encrypted");
|
||||
if (pgp != null) {
|
||||
Toast.makeText(mContext, R.string.pgp_mime_unsupported, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
// nothing to do...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,7 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.ActivityNotFoundException;
|
||||
@ -41,7 +42,6 @@ import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.MessageViewFragment;
|
||||
import com.fsck.k9.helper.ClipboardManager;
|
||||
@ -87,7 +87,6 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
private static final int DISPLAY_NAME_INDEX = 1;
|
||||
|
||||
|
||||
private MessageCryptoView mCryptoView;
|
||||
private MessageOpenPgpView mOpenPgpView;
|
||||
private MessageWebView mMessageContentView;
|
||||
private MessageHeader mHeaderContainer;
|
||||
@ -125,9 +124,6 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
mHiddenAttachments.setVisibility(View.GONE);
|
||||
mShowHiddenAttachments = (Button) findViewById(R.id.show_hidden_attachments);
|
||||
mShowHiddenAttachments.setVisibility(View.GONE);
|
||||
mCryptoView = (MessageCryptoView) findViewById(R.id.layout_decrypt);
|
||||
mCryptoView.setFragment(fragment);
|
||||
mCryptoView.setupChildViews();
|
||||
mOpenPgpView = (MessageOpenPgpView) findViewById(R.id.layout_decrypt_openpgp);
|
||||
mOpenPgpView.setFragment(fragment);
|
||||
mOpenPgpView.setupChildViews();
|
||||
@ -571,7 +567,6 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
|
||||
if (text != null) {
|
||||
loadBodyFromText(text);
|
||||
updateCryptoLayout(account.getCryptoProvider(), pgpData, message);
|
||||
mOpenPgpView.updateLayout(account, pgpData.getDecryptedData(),
|
||||
pgpData.getSignatureResult(), message);
|
||||
} else {
|
||||
@ -582,17 +577,12 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
public void showStatusMessage(String status) {
|
||||
String text = "<div style=\"text-align:center; color: grey;\">" + status + "</div>";
|
||||
loadBodyFromText(text);
|
||||
mCryptoView.hide();
|
||||
}
|
||||
|
||||
private void loadBodyFromText(String emailText) {
|
||||
mMessageContentView.setText(emailText);
|
||||
}
|
||||
|
||||
public void updateCryptoLayout(CryptoProvider cp, PgpData pgpData, Message message) {
|
||||
mCryptoView.updateLayout(cp, pgpData, message);
|
||||
}
|
||||
|
||||
public void showAttachments(boolean show) {
|
||||
mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
boolean showHidden = (show && mHiddenAttachments.getVisibility() == View.GONE &&
|
||||
|
Loading…
Reference in New Issue
Block a user