mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-11 03:55:04 -05:00
Merge from apg-integration
This commit is contained in:
parent
bae8a9736d
commit
7a4d12b53b
@ -22,6 +22,8 @@
|
|||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
|
||||||
|
|
||||||
<permission android:name="com.fsck.k9.permission.READ_ATTACHMENT"
|
<permission android:name="com.fsck.k9.permission.READ_ATTACHMENT"
|
||||||
android:permissionGroup="android.permission-group.MESSAGES"
|
android:permissionGroup="android.permission-group.MESSAGES"
|
||||||
android:protectionLevel="dangerous"
|
android:protectionLevel="dangerous"
|
||||||
|
BIN
res/drawable/overlay_error.png
Normal file
BIN
res/drawable/overlay_error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
res/drawable/overlay_ok.png
Normal file
BIN
res/drawable/overlay_ok.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable/signed_large.png
Normal file
BIN
res/drawable/signed_large.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:background="#ffffff" >
|
android:background="#ffffff" >
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
@ -70,6 +70,66 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_encrypt"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:paddingLeft="6dip"
|
||||||
|
android:paddingRight="6dip">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:text="@string/btn_crypto_sign"
|
||||||
|
android:id="@+id/cb_crypto_signature"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:paddingRight="2dip">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/userId"
|
||||||
|
android:text=""
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/userIdRest"
|
||||||
|
android:text=""
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:text="@string/btn_encrypt"
|
||||||
|
android:id="@+id/cb_encrypt"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/subject"
|
android:id="@+id/subject"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
@ -77,7 +137,7 @@
|
|||||||
android:layout_marginLeft="6dip"
|
android:layout_marginLeft="6dip"
|
||||||
android:layout_marginRight="6dip"
|
android:layout_marginRight="6dip"
|
||||||
android:hint="@string/message_compose_subject_hint"
|
android:hint="@string/message_compose_subject_hint"
|
||||||
android:inputType="textEmailSubject|textAutoCorrect|textCapSentences|textImeMultiLine"
|
android:inputType="textEmailSubject|textAutoCorrect|textCapSentences|textImeMultiLine"
|
||||||
android:imeOptions="actionNext"
|
android:imeOptions="actionNext"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textColor="@android:color/primary_text_light"
|
android:textColor="@android:color/primary_text_light"
|
||||||
@ -106,10 +166,10 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1.0"
|
android:layout_weight="1.0"
|
||||||
android:gravity="left|top"
|
android:gravity="left|top"
|
||||||
android:hint="@string/message_compose_content_hint"
|
android:hint="@string/message_compose_content_hint"
|
||||||
android:inputType="textMultiLine|textAutoCorrect|textCapSentences"
|
android:inputType="textMultiLine|textAutoCorrect|textCapSentences"
|
||||||
android:imeOptions="actionDone|flagNoEnterAction"
|
android:imeOptions="actionDone|flagNoEnterAction"
|
||||||
android:minLines="3"
|
android:minLines="3"
|
||||||
android:textColor="@android:color/primary_text_light"
|
android:textColor="@android:color/primary_text_light"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
>
|
>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
@ -27,7 +27,7 @@
|
|||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="4dip"
|
android:paddingLeft="4dip"
|
||||||
android:layout_weight="5"
|
android:layout_weight="5"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
<TextView android:id="@+id/subject"
|
<TextView android:id="@+id/subject"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
@ -112,7 +112,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout android:id="@+id/topright_container"
|
<LinearLayout android:id="@+id/topright_container"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_weight="0.1"
|
android:layout_weight="0.1"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
@ -179,6 +179,73 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/message_view_show_pictures_action" />
|
android:text="@string/message_view_show_pictures_action" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
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"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
<!-- Content area -->
|
<!-- Content area -->
|
||||||
<WebView
|
<WebView
|
||||||
android:id="@+id/message_content"
|
android:id="@+id/message_content"
|
||||||
|
@ -470,7 +470,6 @@ K-9 Mail セットアップにようこそ。\nK-9 はオープンソースで
|
|||||||
<string name="account_setup_options_mail_display_count_500">500件</string>
|
<string name="account_setup_options_mail_display_count_500">500件</string>
|
||||||
<string name="account_setup_options_mail_display_count_1000">1000件</string>
|
<string name="account_setup_options_mail_display_count_1000">1000件</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="move_copy_cannot_copy_unsynced_message">サーバーと同期されていないメールをコピーまたは移動できません</string>
|
<string name="move_copy_cannot_copy_unsynced_message">サーバーと同期されていないメールをコピーまたは移動できません</string>
|
||||||
|
|
||||||
<string name="account_setup_failed_dlg_title">設定エラー</string>
|
<string name="account_setup_failed_dlg_title">設定エラー</string>
|
||||||
@ -886,7 +885,6 @@ K-9 Mail セットアップにようこそ。\nK-9 はオープンソースで
|
|||||||
|
|
||||||
<string name="save_or_discard_draft_message_dlg_title">メッセージの下書き保存</string>
|
<string name="save_or_discard_draft_message_dlg_title">メッセージの下書き保存</string>
|
||||||
<string name="save_or_discard_draft_message_instructions_fmt">メッセージを保存しますか?</string>
|
<string name="save_or_discard_draft_message_instructions_fmt">メッセージを保存しますか?</string>
|
||||||
|
|
||||||
<string name="charset_not_found">このメッセージに使われている文字セット \"<xliff:g id="charset">%s</xliff:g>\" は存在していません</string>
|
<string name="charset_not_found">このメッセージに使われている文字セット \"<xliff:g id="charset">%s</xliff:g>\" は存在していません</string>
|
||||||
|
|
||||||
<string name="select_text_now">選択したテキストをコピーします</string>
|
<string name="select_text_now">選択したテキストをコピーします</string>
|
||||||
|
@ -589,4 +589,14 @@
|
|||||||
<item>5</item>
|
<item>5</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="account_settings_crypto_app_entries">
|
||||||
|
<item>@string/account_settings_crypto_app_none</item>
|
||||||
|
<item>APG</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="account_settings_crypto_app_values">
|
||||||
|
<item></item>
|
||||||
|
<item>apg</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -512,6 +512,12 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
|
|||||||
<string name="account_settings_message_lists">Listing messages</string>
|
<string name="account_settings_message_lists">Listing messages</string>
|
||||||
<string name="account_settings_message_view">Viewing messages</string>
|
<string name="account_settings_message_view">Viewing messages</string>
|
||||||
<string name="account_settings_quote_prefix_label">Quote prefix</string>
|
<string name="account_settings_quote_prefix_label">Quote prefix</string>
|
||||||
|
<string name="account_settings_crypto">Cryptography</string>
|
||||||
|
<string name="account_settings_crypto_app">OpenPGP Provider</string>
|
||||||
|
<string name="account_settings_crypto_app_none">None</string>
|
||||||
|
<string name="account_settings_crypto_app_not_available">not available</string>
|
||||||
|
<string name="account_settings_crypto_auto_signature">Auto-sign</string>
|
||||||
|
<string name="account_settings_crypto_auto_signature_summary">Use the account\'s email address to guess the signature key.</string>
|
||||||
|
|
||||||
<string name="account_settings_mail_check_frequency_label">Folder poll check frequency</string>
|
<string name="account_settings_mail_check_frequency_label">Folder poll check frequency</string>
|
||||||
<string name="account_settings_second_class_check_frequency_label">2nd class check frequency</string>
|
<string name="account_settings_second_class_check_frequency_label">2nd class check frequency</string>
|
||||||
@ -891,6 +897,20 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
|
|||||||
<string name="misc_preferences_attachment_title">Use Gallery bug work-around</string>
|
<string name="misc_preferences_attachment_title">Use Gallery bug work-around</string>
|
||||||
<string name="misc_preferences_attachment_description">Show buttons to add image/video attachments (to work around a Gallery 3D bug)</string>
|
<string name="misc_preferences_attachment_description">Show buttons to add image/video attachments (to work around a Gallery 3D bug)</string>
|
||||||
|
|
||||||
|
<!-- APG related -->
|
||||||
|
<string name="error_activity_not_found">No suitable application for this action found.</string>
|
||||||
|
<string name="error_apg_version_not_supported">The installed APG version is not supported.</string>
|
||||||
|
<string name="btn_crypto_sign">Sign</string>
|
||||||
|
<string name="btn_encrypt">Encrypt</string>
|
||||||
|
<string name="btn_decrypt">Decrypt</string>
|
||||||
|
<string name="btn_verify">Verify</string>
|
||||||
|
<string name="unknown_crypto_signature_user_id"><unknown></string>
|
||||||
|
<string name="key_id">id: %s</string>
|
||||||
|
<string name="insufficient_apg_permissions">K-9 doesn\'t have permission to access APG fully, please reinstall K-9 to fix that.</string>
|
||||||
|
<string name="pgp_mime_unsupported">PGP/MIME messages are not supported yet.</string>
|
||||||
|
<string name="attachment_encryption_unsupported">Warning: attachments are NOT signed or encrypted yet.</string>
|
||||||
|
<string name="send_aborted">Send aborted.</string>
|
||||||
|
|
||||||
<string name="save_or_discard_draft_message_dlg_title">Save draft message?</string>
|
<string name="save_or_discard_draft_message_dlg_title">Save draft message?</string>
|
||||||
<string name="save_or_discard_draft_message_instructions_fmt">Save or Discard this message?</string>
|
<string name="save_or_discard_draft_message_instructions_fmt">Save or Discard this message?</string>
|
||||||
|
|
||||||
|
@ -207,6 +207,22 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/account_settings_crypto">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:key="crypto_app"
|
||||||
|
android:title="@string/account_settings_crypto_app"
|
||||||
|
android:entries="@array/account_settings_crypto_app_entries"
|
||||||
|
android:entryValues="@array/account_settings_crypto_app_values"
|
||||||
|
android:dialogTitle="@string/account_settings_crypto_app" />
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="crypto_auto_signature"
|
||||||
|
android:title="@string/account_settings_crypto_auto_signature"
|
||||||
|
android:summary="@string/account_settings_crypto_auto_signature_summary"
|
||||||
|
android:dependency="crypto_app"/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/account_settings_notifications">
|
<PreferenceCategory android:title="@string/account_settings_notifications">
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
|
@ -107,6 +107,8 @@ public class Account implements BaseAccount
|
|||||||
private boolean mRingNotified;
|
private boolean mRingNotified;
|
||||||
private String mQuotePrefix;
|
private String mQuotePrefix;
|
||||||
private boolean mSyncRemoteDeletions;
|
private boolean mSyncRemoteDeletions;
|
||||||
|
private String mCryptoApp;
|
||||||
|
private boolean mCryptoAutoSignature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the folder that was last selected for a copy or move operation.
|
* Name of the folder that was last selected for a copy or move operation.
|
||||||
@ -171,6 +173,8 @@ public class Account implements BaseAccount
|
|||||||
maximumAutoDownloadMessageSize = 32768;
|
maximumAutoDownloadMessageSize = 32768;
|
||||||
mQuotePrefix = DEFAULT_QUOTE_PREFIX;
|
mQuotePrefix = DEFAULT_QUOTE_PREFIX;
|
||||||
mSyncRemoteDeletions = true;
|
mSyncRemoteDeletions = true;
|
||||||
|
mCryptoApp = "";
|
||||||
|
mCryptoAutoSignature = false;
|
||||||
|
|
||||||
searchableFolders = Searchable.ALL;
|
searchableFolders = Searchable.ALL;
|
||||||
|
|
||||||
@ -270,14 +274,12 @@ public class Account implements BaseAccount
|
|||||||
(random.nextInt(0x70) * 0xff) +
|
(random.nextInt(0x70) * 0xff) +
|
||||||
(random.nextInt(0x70) * 0xffff) +
|
(random.nextInt(0x70) * 0xffff) +
|
||||||
0xff000000);
|
0xff000000);
|
||||||
|
|
||||||
mLedColor = prefs.getInt(mUuid+".ledColor", mChipColor);
|
mLedColor = prefs.getInt(mUuid+".ledColor", mChipColor);
|
||||||
|
|
||||||
mVibrate = prefs.getBoolean(mUuid + ".vibrate", false);
|
mVibrate = prefs.getBoolean(mUuid + ".vibrate", false);
|
||||||
mVibratePattern = prefs.getInt(mUuid + ".vibratePattern", 0);
|
mVibratePattern = prefs.getInt(mUuid + ".vibratePattern", 0);
|
||||||
mVibrateTimes = prefs.getInt(mUuid + ".vibrateTimes", 5);
|
mVibrateTimes = prefs.getInt(mUuid + ".vibrateTimes", 5);
|
||||||
|
|
||||||
|
|
||||||
mRing = prefs.getBoolean(mUuid + ".ring", true);
|
mRing = prefs.getBoolean(mUuid + ".ring", true);
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -356,6 +358,9 @@ public class Account implements BaseAccount
|
|||||||
|
|
||||||
mIsSignatureBeforeQuotedText = prefs.getBoolean(mUuid + ".signatureBeforeQuotedText", false);
|
mIsSignatureBeforeQuotedText = prefs.getBoolean(mUuid + ".signatureBeforeQuotedText", false);
|
||||||
identities = loadIdentities(prefs);
|
identities = loadIdentities(prefs);
|
||||||
|
|
||||||
|
mCryptoApp = prefs.getString(mUuid + ".cryptoApp", "");
|
||||||
|
mCryptoAutoSignature = prefs.getBoolean(mUuid + ".cryptoAutoSignature", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -518,6 +523,8 @@ public class Account implements BaseAccount
|
|||||||
editor.putInt(mUuid + ".maximumPolledMessageAge", maximumPolledMessageAge);
|
editor.putInt(mUuid + ".maximumPolledMessageAge", maximumPolledMessageAge);
|
||||||
editor.putInt(mUuid + ".maximumAutoDownloadMessageSize", maximumAutoDownloadMessageSize);
|
editor.putInt(mUuid + ".maximumAutoDownloadMessageSize", maximumAutoDownloadMessageSize);
|
||||||
editor.putString(mUuid + ".quotePrefix", mQuotePrefix);
|
editor.putString(mUuid + ".quotePrefix", mQuotePrefix);
|
||||||
|
editor.putString(mUuid + ".cryptoApp", mCryptoApp);
|
||||||
|
editor.putBoolean(mUuid + ".cryptoAutoSignature", mCryptoAutoSignature);
|
||||||
|
|
||||||
for (String type : networkTypes)
|
for (String type : networkTypes)
|
||||||
{
|
{
|
||||||
@ -1411,6 +1418,25 @@ public class Account implements BaseAccount
|
|||||||
mEnableMoveButtons = enableMoveButtons;
|
mEnableMoveButtons = enableMoveButtons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCryptoApp()
|
||||||
|
{
|
||||||
|
return mCryptoApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCryptoApp(String cryptoApp)
|
||||||
|
{
|
||||||
|
mCryptoApp = cryptoApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getCryptoAutoSignature()
|
||||||
|
{
|
||||||
|
return mCryptoAutoSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCryptoAutoSignature(boolean cryptoAutoSignature)
|
||||||
|
{
|
||||||
|
mCryptoAutoSignature = cryptoAutoSignature;
|
||||||
|
}
|
||||||
public synchronized boolean syncRemoteDeletions()
|
public synchronized boolean syncRemoteDeletions()
|
||||||
{
|
{
|
||||||
return mSyncRemoteDeletions;
|
return mSyncRemoteDeletions;
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
|
|
||||||
package com.fsck.k9.activity;
|
package com.fsck.k9.activity;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import org.apache.james.mime4j.codec.EncoderUtil;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
@ -26,25 +36,42 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.View.OnFocusChangeListener;
|
import android.view.View.OnFocusChangeListener;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.AutoCompleteTextView.Validator;
|
import android.widget.AutoCompleteTextView.Validator;
|
||||||
import android.widget.*;
|
import android.widget.Button;
|
||||||
import com.fsck.k9.*;
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.MultiAutoCompleteTextView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
|
import com.fsck.k9.EmailAddressAdapter;
|
||||||
|
import com.fsck.k9.EmailAddressValidator;
|
||||||
|
import com.fsck.k9.Identity;
|
||||||
|
import com.fsck.k9.K9;
|
||||||
|
import com.fsck.k9.Preferences;
|
||||||
|
import com.fsck.k9.R;
|
||||||
import com.fsck.k9.controller.MessagingController;
|
import com.fsck.k9.controller.MessagingController;
|
||||||
import com.fsck.k9.controller.MessagingListener;
|
import com.fsck.k9.controller.MessagingListener;
|
||||||
|
import com.fsck.k9.crypto.CryptoProvider;
|
||||||
import com.fsck.k9.helper.Utility;
|
import com.fsck.k9.helper.Utility;
|
||||||
import com.fsck.k9.mail.*;
|
import com.fsck.k9.mail.Address;
|
||||||
|
import com.fsck.k9.mail.Body;
|
||||||
|
import com.fsck.k9.mail.Flag;
|
||||||
|
import com.fsck.k9.mail.Message;
|
||||||
import com.fsck.k9.mail.Message.RecipientType;
|
import com.fsck.k9.mail.Message.RecipientType;
|
||||||
import com.fsck.k9.mail.internet.*;
|
import com.fsck.k9.mail.MessagingException;
|
||||||
|
import com.fsck.k9.mail.Multipart;
|
||||||
|
import com.fsck.k9.mail.Part;
|
||||||
|
import com.fsck.k9.mail.internet.MimeBodyPart;
|
||||||
|
import com.fsck.k9.mail.internet.MimeHeader;
|
||||||
|
import com.fsck.k9.mail.internet.MimeMessage;
|
||||||
|
import com.fsck.k9.mail.internet.MimeMultipart;
|
||||||
|
import com.fsck.k9.mail.internet.MimeUtility;
|
||||||
|
import com.fsck.k9.mail.internet.TextBody;
|
||||||
import com.fsck.k9.mail.store.LocalStore;
|
import com.fsck.k9.mail.store.LocalStore;
|
||||||
import com.fsck.k9.mail.store.LocalStore.LocalAttachmentBody;
|
import com.fsck.k9.mail.store.LocalStore.LocalAttachmentBody;
|
||||||
import java.io.File;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import org.apache.james.mime4j.codec.EncoderUtil;
|
|
||||||
|
|
||||||
public class MessageCompose extends K9Activity implements OnClickListener, OnFocusChangeListener
|
public class MessageCompose extends K9Activity implements OnClickListener, OnFocusChangeListener
|
||||||
{
|
{
|
||||||
@ -55,8 +82,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private static final String ACTION_FORWARD = "com.fsck.k9.intent.action.FORWARD";
|
private static final String ACTION_FORWARD = "com.fsck.k9.intent.action.FORWARD";
|
||||||
private static final String ACTION_EDIT_DRAFT = "com.fsck.k9.intent.action.EDIT_DRAFT";
|
private static final String ACTION_EDIT_DRAFT = "com.fsck.k9.intent.action.EDIT_DRAFT";
|
||||||
|
|
||||||
|
|
||||||
private static final String EXTRA_ACCOUNT = "account";
|
private static final String EXTRA_ACCOUNT = "account";
|
||||||
|
private static final String EXTRA_MESSAGE_BODY = "messageBody";
|
||||||
private static final String EXTRA_MESSAGE_REFERENCE = "message_reference";
|
private static final String EXTRA_MESSAGE_REFERENCE = "message_reference";
|
||||||
|
|
||||||
private static final String STATE_KEY_ATTACHMENTS =
|
private static final String STATE_KEY_ATTACHMENTS =
|
||||||
@ -75,6 +102,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
"com.fsck.k9.activity.MessageCompose.identityChanged";
|
"com.fsck.k9.activity.MessageCompose.identityChanged";
|
||||||
private static final String STATE_IDENTITY =
|
private static final String STATE_IDENTITY =
|
||||||
"com.fsck.k9.activity.MessageCompose.identity";
|
"com.fsck.k9.activity.MessageCompose.identity";
|
||||||
|
private static final String STATE_CRYPTO = "crypto";
|
||||||
private static final String STATE_IN_REPLY_TO = "com.fsck.k9.activity.MessageCompose.inReplyTo";
|
private static final String STATE_IN_REPLY_TO = "com.fsck.k9.activity.MessageCompose.inReplyTo";
|
||||||
private static final String STATE_REFERENCES = "com.fsck.k9.activity.MessageCompose.references";
|
private static final String STATE_REFERENCES = "com.fsck.k9.activity.MessageCompose.references";
|
||||||
|
|
||||||
@ -110,6 +138,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private MessageReference mMessageReference;
|
private MessageReference mMessageReference;
|
||||||
|
|
||||||
private Message mSourceMessage;
|
private Message mSourceMessage;
|
||||||
|
private String mSourceMessageBody;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the source message has been processed at least once and should not
|
* Indicates that the source message has been processed at least once and should not
|
||||||
@ -130,11 +159,19 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private View mQuotedTextBar;
|
private View mQuotedTextBar;
|
||||||
private ImageButton mQuotedTextDelete;
|
private ImageButton mQuotedTextDelete;
|
||||||
private EditText mQuotedText;
|
private EditText mQuotedText;
|
||||||
|
private View mEncryptLayout;
|
||||||
|
private CheckBox mCryptoSignatureCheckbox;
|
||||||
|
private CheckBox mEncryptCheckbox;
|
||||||
|
private TextView mCryptoSignatureUserId;
|
||||||
|
private TextView mCryptoSignatureUserIdRest;
|
||||||
|
|
||||||
|
private CryptoProvider mCrypto = null;
|
||||||
|
|
||||||
private String mReferences;
|
private String mReferences;
|
||||||
private String mInReplyTo;
|
private String mInReplyTo;
|
||||||
|
|
||||||
private boolean mDraftNeedsSaving = false;
|
private boolean mDraftNeedsSaving = false;
|
||||||
|
private boolean mPreventDraftSaving = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The draft uid of this message. This is used when saving drafts so that the same draft is
|
* The draft uid of this message. This is used when saving drafts so that the same draft is
|
||||||
@ -220,14 +257,17 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
* @param account
|
* @param account
|
||||||
* @param message
|
* @param message
|
||||||
* @param replyAll
|
* @param replyAll
|
||||||
|
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||||
*/
|
*/
|
||||||
public static void actionReply(
|
public static void actionReply(
|
||||||
Context context,
|
Context context,
|
||||||
Account account,
|
Account account,
|
||||||
Message message,
|
Message message,
|
||||||
boolean replyAll)
|
boolean replyAll,
|
||||||
|
String messageBody)
|
||||||
{
|
{
|
||||||
Intent i = new Intent(context, MessageCompose.class);
|
Intent i = new Intent(context, MessageCompose.class);
|
||||||
|
i.putExtra(EXTRA_MESSAGE_BODY, messageBody);
|
||||||
i.putExtra(EXTRA_MESSAGE_REFERENCE, message.makeMessageReference());
|
i.putExtra(EXTRA_MESSAGE_REFERENCE, message.makeMessageReference());
|
||||||
if (replyAll)
|
if (replyAll)
|
||||||
{
|
{
|
||||||
@ -245,10 +285,16 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
* @param context
|
* @param context
|
||||||
* @param account
|
* @param account
|
||||||
* @param message
|
* @param message
|
||||||
|
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||||
*/
|
*/
|
||||||
public static void actionForward(Context context, Account account, Message message)
|
public static void actionForward(
|
||||||
|
Context context,
|
||||||
|
Account account,
|
||||||
|
Message message,
|
||||||
|
String messageBody)
|
||||||
{
|
{
|
||||||
Intent i = new Intent(context, MessageCompose.class);
|
Intent i = new Intent(context, MessageCompose.class);
|
||||||
|
i.putExtra(EXTRA_MESSAGE_BODY, messageBody);
|
||||||
i.putExtra(EXTRA_MESSAGE_REFERENCE, message.makeMessageReference());
|
i.putExtra(EXTRA_MESSAGE_REFERENCE, message.makeMessageReference());
|
||||||
i.setAction(ACTION_FORWARD);
|
i.setAction(ACTION_FORWARD);
|
||||||
context.startActivity(i);
|
context.startActivity(i);
|
||||||
@ -282,6 +328,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
|
|
||||||
mMessageReference = (MessageReference) intent.getSerializableExtra(EXTRA_MESSAGE_REFERENCE);
|
mMessageReference = (MessageReference) intent.getSerializableExtra(EXTRA_MESSAGE_REFERENCE);
|
||||||
|
mSourceMessageBody = (String) intent.getStringExtra(EXTRA_MESSAGE_BODY);
|
||||||
|
|
||||||
final String accountUuid = (mMessageReference != null) ?
|
final String accountUuid = (mMessageReference != null) ?
|
||||||
mMessageReference.accountUuid :
|
mMessageReference.accountUuid :
|
||||||
@ -613,9 +660,113 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
mMessageContentView.requestFocus();
|
mMessageContentView.requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mEncryptLayout = (View)findViewById(R.id.layout_encrypt);
|
||||||
|
mCryptoSignatureCheckbox = (CheckBox)findViewById(R.id.cb_crypto_signature);
|
||||||
|
mCryptoSignatureUserId = (TextView)findViewById(R.id.userId);
|
||||||
|
mCryptoSignatureUserIdRest = (TextView)findViewById(R.id.userIdRest);
|
||||||
|
mEncryptCheckbox = (CheckBox)findViewById(R.id.cb_encrypt);
|
||||||
|
|
||||||
|
initializeCrypto();
|
||||||
|
if (mCrypto.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 (!mCrypto.selectSecretKey(MessageCompose.this))
|
||||||
|
{
|
||||||
|
mPreventDraftSaving = false;
|
||||||
|
}
|
||||||
|
checkBox.setChecked(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCrypto.setSignatureKeyId(0);
|
||||||
|
updateEncryptLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mAccount.getCryptoAutoSignature())
|
||||||
|
{
|
||||||
|
long ids[] = mCrypto.getSecretKeyIdsFromEmail(this, mIdentity.getEmail());
|
||||||
|
if (ids != null && ids.length > 0)
|
||||||
|
{
|
||||||
|
mCrypto.setSignatureKeyId(ids[0]);
|
||||||
|
mCrypto.setSignatureUserId(mCrypto.getUserId(this, ids[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCrypto.setSignatureKeyId(0);
|
||||||
|
mCrypto.setSignatureUserId(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateEncryptLayout();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mEncryptLayout.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
mDraftNeedsSaving = false;
|
mDraftNeedsSaving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeCrypto()
|
||||||
|
{
|
||||||
|
if (mCrypto != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mCrypto = CryptoProvider.createInstance(mAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the encrypt layout with the latest data about signature key and encryption keys.
|
||||||
|
*/
|
||||||
|
public void updateEncryptLayout()
|
||||||
|
{
|
||||||
|
if (!mCrypto.hasSignatureKey())
|
||||||
|
{
|
||||||
|
mCryptoSignatureCheckbox.setText(R.string.btn_crypto_sign);
|
||||||
|
mCryptoSignatureCheckbox.setChecked(false);
|
||||||
|
mCryptoSignatureUserId.setVisibility(View.INVISIBLE);
|
||||||
|
mCryptoSignatureUserIdRest.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if a signature key is selected, then the checkbox itself has no text
|
||||||
|
mCryptoSignatureCheckbox.setText("");
|
||||||
|
mCryptoSignatureCheckbox.setChecked(true);
|
||||||
|
mCryptoSignatureUserId.setVisibility(View.VISIBLE);
|
||||||
|
mCryptoSignatureUserIdRest.setVisibility(View.VISIBLE);
|
||||||
|
mCryptoSignatureUserId.setText(R.string.unknown_crypto_signature_user_id);
|
||||||
|
mCryptoSignatureUserIdRest.setText("");
|
||||||
|
|
||||||
|
String userId = mCrypto.getSignatureUserId();
|
||||||
|
if (userId == null)
|
||||||
|
{
|
||||||
|
userId = mCrypto.getUserId(this, mCrypto.getSignatureKeyId());
|
||||||
|
mCrypto.setSignatureUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userId != null)
|
||||||
|
{
|
||||||
|
String chunks[] = mCrypto.getSignatureUserId().split(" <", 2);
|
||||||
|
mCryptoSignatureUserId.setText(chunks[0]);
|
||||||
|
if (chunks.length > 1)
|
||||||
|
{
|
||||||
|
mCryptoSignatureUserIdRest.setText("<" + chunks[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume()
|
public void onResume()
|
||||||
{
|
{
|
||||||
@ -659,6 +810,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
|
outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
|
||||||
outState.putSerializable(STATE_IDENTITY, mIdentity);
|
outState.putSerializable(STATE_IDENTITY, mIdentity);
|
||||||
outState.putBoolean(STATE_IDENTITY_CHANGED, mIdentityChanged);
|
outState.putBoolean(STATE_IDENTITY_CHANGED, mIdentityChanged);
|
||||||
|
outState.putSerializable(STATE_CRYPTO, mCrypto);
|
||||||
outState.putString(STATE_IN_REPLY_TO, mInReplyTo);
|
outState.putString(STATE_IN_REPLY_TO, mInReplyTo);
|
||||||
outState.putString(STATE_REFERENCES, mReferences);
|
outState.putString(STATE_REFERENCES, mReferences);
|
||||||
}
|
}
|
||||||
@ -682,10 +834,14 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
|
mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
|
||||||
mIdentity = (Identity)savedInstanceState.getSerializable(STATE_IDENTITY);
|
mIdentity = (Identity)savedInstanceState.getSerializable(STATE_IDENTITY);
|
||||||
mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED);
|
mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED);
|
||||||
|
mCrypto = (CryptoProvider) savedInstanceState.getSerializable(STATE_CRYPTO);
|
||||||
mInReplyTo = savedInstanceState.getString(STATE_IN_REPLY_TO);
|
mInReplyTo = savedInstanceState.getString(STATE_IN_REPLY_TO);
|
||||||
mReferences = savedInstanceState.getString(STATE_REFERENCES);
|
mReferences = savedInstanceState.getString(STATE_REFERENCES);
|
||||||
|
|
||||||
|
initializeCrypto();
|
||||||
updateFrom();
|
updateFrom();
|
||||||
updateSignature();
|
updateSignature();
|
||||||
|
updateEncryptLayout();
|
||||||
|
|
||||||
mDraftNeedsSaving = false;
|
mDraftNeedsSaving = false;
|
||||||
}
|
}
|
||||||
@ -733,6 +889,32 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String buildText(boolean appendSig)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Build the Body that will contain the text of the message. We'll decide where to
|
||||||
|
* include it later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
String text = mMessageContentView.getText().toString();
|
||||||
|
if (appendSig && mAccount.isSignatureBeforeQuotedText())
|
||||||
|
{
|
||||||
|
text = appendSignature(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mQuotedTextBar.getVisibility() == View.VISIBLE)
|
||||||
|
{
|
||||||
|
text += "\n" + mQuotedText.getText().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appendSig && mAccount.isSignatureBeforeQuotedText() == false)
|
||||||
|
{
|
||||||
|
text = appendSignature(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
private MimeMessage createMessage(boolean appendSig) throws MessagingException
|
private MimeMessage createMessage(boolean appendSig) throws MessagingException
|
||||||
{
|
{
|
||||||
MimeMessage message = new MimeMessage();
|
MimeMessage message = new MimeMessage();
|
||||||
@ -761,27 +943,14 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
message.setReferences(mReferences);
|
message.setReferences(mReferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String text = null;
|
||||||
/*
|
if (mCrypto.getEncryptedData() != null)
|
||||||
* Build the Body that will contain the text of the message. We'll decide where to
|
|
||||||
* include it later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
String text = mMessageContentView.getText().toString();
|
|
||||||
if (appendSig && mAccount.isSignatureBeforeQuotedText())
|
|
||||||
{
|
{
|
||||||
text = appendSignature(text);
|
text = mCrypto.getEncryptedData();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (mQuotedTextBar.getVisibility() == View.VISIBLE)
|
|
||||||
{
|
{
|
||||||
text += "\n" + mQuotedText.getText().toString();
|
text = buildText(appendSig);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (appendSig && mAccount.isSignatureBeforeQuotedText() == false)
|
|
||||||
{
|
|
||||||
text = appendSignature(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextBody body = new TextBody(text);
|
TextBody body = new TextBody(text);
|
||||||
@ -869,7 +1038,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void sendMessage()
|
private void sendMessage()
|
||||||
{
|
{
|
||||||
new SendMessageTask().execute();
|
new SendMessageTask().execute();
|
||||||
@ -881,10 +1049,37 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
|
|
||||||
private void saveIfNeeded()
|
private void saveIfNeeded()
|
||||||
{
|
{
|
||||||
if (!mDraftNeedsSaving)
|
if (!mDraftNeedsSaving || mPreventDraftSaving || mCrypto.hasEncryptionKeys())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDraftNeedsSaving = false;
|
||||||
|
saveMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEncryptionKeySelectionDone()
|
||||||
|
{
|
||||||
|
if (mCrypto.hasEncryptionKeys())
|
||||||
|
{
|
||||||
|
onSend();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Toast.makeText(this, R.string.send_aborted, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEncryptDone()
|
||||||
|
{
|
||||||
|
if (mCrypto.getEncryptedData() != null)
|
||||||
|
{
|
||||||
|
onSend();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Toast.makeText(this, R.string.send_aborted, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
mDraftNeedsSaving = false;
|
mDraftNeedsSaving = false;
|
||||||
saveMessage();
|
saveMessage();
|
||||||
}
|
}
|
||||||
@ -897,6 +1092,51 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
Toast.makeText(this, getString(R.string.message_compose_error_no_recipients), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, getString(R.string.message_compose_error_no_recipients), Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mEncryptCheckbox.isChecked() && !mCrypto.hasEncryptionKeys())
|
||||||
|
{
|
||||||
|
// key selection before encryption
|
||||||
|
String emails = "";
|
||||||
|
Address[][] addresses = new Address[][] { getAddresses(mToView),
|
||||||
|
getAddresses(mCcView),
|
||||||
|
getAddresses(mBccView)
|
||||||
|
};
|
||||||
|
for (Address[] addressArray : addresses)
|
||||||
|
{
|
||||||
|
for (Address address : addressArray)
|
||||||
|
{
|
||||||
|
if (emails.length() != 0)
|
||||||
|
{
|
||||||
|
emails += ",";
|
||||||
|
}
|
||||||
|
emails += address.getAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (emails.length() != 0)
|
||||||
|
{
|
||||||
|
emails += ",";
|
||||||
|
}
|
||||||
|
emails += mIdentity.getEmail();
|
||||||
|
|
||||||
|
mPreventDraftSaving = true;
|
||||||
|
if (!mCrypto.selectEncryptionKeys(MessageCompose.this, emails))
|
||||||
|
{
|
||||||
|
mPreventDraftSaving = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mCrypto.hasEncryptionKeys() || mCrypto.hasSignatureKey())
|
||||||
|
{
|
||||||
|
if (mCrypto.getEncryptedData() == null)
|
||||||
|
{
|
||||||
|
String text = buildText(true);
|
||||||
|
mPreventDraftSaving = true;
|
||||||
|
if (!mCrypto.encrypt(this, text))
|
||||||
|
{
|
||||||
|
mPreventDraftSaving = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
sendMessage();
|
sendMessage();
|
||||||
mDraftNeedsSaving = false;
|
mDraftNeedsSaving = false;
|
||||||
finish();
|
finish();
|
||||||
@ -956,6 +1196,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
*/
|
*/
|
||||||
private void onAddAttachment2(final String mime_type)
|
private void onAddAttachment2(final String mime_type)
|
||||||
{
|
{
|
||||||
|
if (mCrypto.isAvailable(this))
|
||||||
|
{
|
||||||
|
Toast.makeText(this, R.string.attachment_encryption_unsupported, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
i.addCategory(Intent.CATEGORY_OPENABLE);
|
i.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
i.setType(mime_type);
|
i.setType(mime_type);
|
||||||
@ -1050,6 +1294,14 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||||
{
|
{
|
||||||
|
// if a CryptoSystem activity is returning, then mPreventDraftSaving was set to true
|
||||||
|
mPreventDraftSaving = false;
|
||||||
|
|
||||||
|
if (mCrypto.onActivityResult(this, requestCode, resultCode, data))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (resultCode != RESULT_OK)
|
if (resultCode != RESULT_OK)
|
||||||
return;
|
return;
|
||||||
if (data == null)
|
if (data == null)
|
||||||
@ -1059,7 +1311,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
switch (requestCode)
|
switch (requestCode)
|
||||||
{
|
{
|
||||||
case ACTIVITY_REQUEST_PICK_ATTACHMENT:
|
case ACTIVITY_REQUEST_PICK_ATTACHMENT:
|
||||||
|
|
||||||
addAttachment(data.getData());
|
addAttachment(data.getData());
|
||||||
mDraftNeedsSaving = true;
|
mDraftNeedsSaving = true;
|
||||||
break;
|
break;
|
||||||
@ -1196,6 +1447,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
switch (item.getItemId())
|
switch (item.getItemId())
|
||||||
{
|
{
|
||||||
case R.id.send:
|
case R.id.send:
|
||||||
|
mCrypto.setEncryptionKeys(null);
|
||||||
onSend();
|
onSend();
|
||||||
break;
|
break;
|
||||||
case R.id.save:
|
case R.id.save:
|
||||||
@ -1442,7 +1694,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
|
|
||||||
Part part = MimeUtility.findFirstPartByMimeType(mSourceMessage,
|
Part part = MimeUtility.findFirstPartByMimeType(mSourceMessage,
|
||||||
"text/plain");
|
"text/plain");
|
||||||
if (part != null)
|
if (part != null || mSourceMessageBody != null)
|
||||||
{
|
{
|
||||||
String quotedText = String.format(
|
String quotedText = String.format(
|
||||||
getString(R.string.message_compose_reply_header_fmt),
|
getString(R.string.message_compose_reply_header_fmt),
|
||||||
@ -1452,8 +1704,16 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
// "$" and "\" in the quote prefix have to be escaped for
|
// "$" and "\" in the quote prefix have to be escaped for
|
||||||
// the replaceAll() invocation.
|
// the replaceAll() invocation.
|
||||||
final String escapedPrefix = prefix.replaceAll("(\\\\|\\$)", "\\\\$1");
|
final String escapedPrefix = prefix.replaceAll("(\\\\|\\$)", "\\\\$1");
|
||||||
quotedText += MimeUtility.getTextFromPart(part).replaceAll(
|
|
||||||
"(?m)^", escapedPrefix);
|
if (mSourceMessageBody != null)
|
||||||
|
{
|
||||||
|
quotedText += mSourceMessageBody.replaceAll("(?m)^", escapedPrefix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
quotedText += MimeUtility.getTextFromPart(part).replaceAll(
|
||||||
|
"(?m)^", escapedPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
quotedText = quotedText.replaceAll("\\\r", "");
|
quotedText = quotedText.replaceAll("\\\r", "");
|
||||||
mQuotedText.setText(quotedText);
|
mQuotedText.setText(quotedText);
|
||||||
@ -1548,9 +1808,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
{
|
{
|
||||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||||
}
|
}
|
||||||
if (part != null)
|
if (part != null || mSourceMessageBody != null)
|
||||||
{
|
{
|
||||||
String quotedText = MimeUtility.getTextFromPart(part);
|
String quotedText = mSourceMessageBody;
|
||||||
|
if (quotedText == null)
|
||||||
|
{
|
||||||
|
quotedText = MimeUtility.getTextFromPart(part);
|
||||||
|
}
|
||||||
if (quotedText != null)
|
if (quotedText != null)
|
||||||
{
|
{
|
||||||
String text = String.format(
|
String text = String.format(
|
||||||
|
@ -1103,17 +1103,17 @@ public class MessageList
|
|||||||
|
|
||||||
private void onReply(MessageInfoHolder holder)
|
private void onReply(MessageInfoHolder holder)
|
||||||
{
|
{
|
||||||
MessageCompose.actionReply(this, holder.message.getFolder().getAccount(), holder.message, false);
|
MessageCompose.actionReply(this, holder.message.getFolder().getAccount(), holder.message, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onReplyAll(MessageInfoHolder holder)
|
private void onReplyAll(MessageInfoHolder holder)
|
||||||
{
|
{
|
||||||
MessageCompose.actionReply(this, holder.message.getFolder().getAccount(), holder.message, true);
|
MessageCompose.actionReply(this, holder.message.getFolder().getAccount(), holder.message, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onForward(MessageInfoHolder holder)
|
private void onForward(MessageInfoHolder holder)
|
||||||
{
|
{
|
||||||
MessageCompose.actionForward(this, holder.message.getFolder().getAccount(), holder.message);
|
MessageCompose.actionForward(this, holder.message.getFolder().getAccount(), holder.message, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onMarkAllAsRead(final Account account, final String folder)
|
private void onMarkAllAsRead(final Account account, final String folder)
|
||||||
|
@ -64,6 +64,7 @@ import com.fsck.k9.Preferences;
|
|||||||
import com.fsck.k9.R;
|
import com.fsck.k9.R;
|
||||||
import com.fsck.k9.controller.MessagingController;
|
import com.fsck.k9.controller.MessagingController;
|
||||||
import com.fsck.k9.controller.MessagingListener;
|
import com.fsck.k9.controller.MessagingListener;
|
||||||
|
import com.fsck.k9.crypto.CryptoProvider;
|
||||||
import com.fsck.k9.mail.Address;
|
import com.fsck.k9.mail.Address;
|
||||||
import com.fsck.k9.mail.Flag;
|
import com.fsck.k9.mail.Flag;
|
||||||
import com.fsck.k9.mail.Message;
|
import com.fsck.k9.mail.Message;
|
||||||
@ -83,6 +84,8 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
private static final String EXTRA_MESSAGE_REFERENCES = "com.fsck.k9.MessageView_messageReferences";
|
private static final String EXTRA_MESSAGE_REFERENCES = "com.fsck.k9.MessageView_messageReferences";
|
||||||
private static final String EXTRA_NEXT = "com.fsck.k9.MessageView_next";
|
private static final String EXTRA_NEXT = "com.fsck.k9.MessageView_next";
|
||||||
|
|
||||||
|
private static final String STATE_CRYPTO = "crypto";
|
||||||
|
|
||||||
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
|
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
|
||||||
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
|
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
|
||||||
|
|
||||||
@ -95,6 +98,12 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
public View chip;
|
public View chip;
|
||||||
private CheckBox mFlagged;
|
private CheckBox mFlagged;
|
||||||
private int defaultSubjectColor;
|
private int defaultSubjectColor;
|
||||||
|
private View mDecryptLayout;
|
||||||
|
private Button mDecryptButton;
|
||||||
|
private LinearLayout mCryptoSignatureLayout = null;
|
||||||
|
private ImageView mCryptoSignatureStatusImage = null;
|
||||||
|
private TextView mCryptoSignatureUserId = null;
|
||||||
|
private TextView mCryptoSignatureUserIdRest = null;
|
||||||
private WebView mMessageContentView;
|
private WebView mMessageContentView;
|
||||||
private LinearLayout mHeaderContainer;
|
private LinearLayout mHeaderContainer;
|
||||||
private LinearLayout mAttachments;
|
private LinearLayout mAttachments;
|
||||||
@ -125,17 +134,16 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
private ArrayList<MessageReference> mMessageReferences;
|
private ArrayList<MessageReference> mMessageReferences;
|
||||||
|
|
||||||
private Message mMessage;
|
private Message mMessage;
|
||||||
|
private CryptoProvider mCrypto = null;
|
||||||
|
|
||||||
private static final int PREVIOUS = 1;
|
private static final int PREVIOUS = 1;
|
||||||
private static final int NEXT = 2;
|
private static final int NEXT = 2;
|
||||||
|
|
||||||
private int mLastDirection = PREVIOUS;
|
private int mLastDirection = PREVIOUS;
|
||||||
|
|
||||||
|
|
||||||
private MessageReference mNextMessage = null;
|
private MessageReference mNextMessage = null;
|
||||||
private MessageReference mPreviousMessage = null;
|
private MessageReference mPreviousMessage = null;
|
||||||
|
|
||||||
|
|
||||||
private Menu optionsMenu = null;
|
private Menu optionsMenu = null;
|
||||||
|
|
||||||
private Listener mListener = new Listener();
|
private Listener mListener = new Listener();
|
||||||
@ -734,6 +742,39 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
mTopView = mToggleScrollView = (ToggleScrollView)findViewById(R.id.top_view);
|
mTopView = mToggleScrollView = (ToggleScrollView)findViewById(R.id.top_view);
|
||||||
mMessageContentView = (WebView)findViewById(R.id.message_content);
|
mMessageContentView = (WebView)findViewById(R.id.message_content);
|
||||||
|
|
||||||
|
mDecryptLayout = (View)findViewById(R.id.layout_decrypt);
|
||||||
|
mDecryptButton = (Button)findViewById(R.id.btn_decrypt);
|
||||||
|
mDecryptButton.setOnClickListener(new OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String data = null;
|
||||||
|
Part part = MimeUtility.findFirstPartByMimeType(mMessage, "text/plain");
|
||||||
|
if (part == null)
|
||||||
|
{
|
||||||
|
part = MimeUtility.findFirstPartByMimeType(mMessage, "text/html");
|
||||||
|
}
|
||||||
|
if (part != null)
|
||||||
|
{
|
||||||
|
data = MimeUtility.getTextFromPart(part);
|
||||||
|
}
|
||||||
|
mCrypto.decrypt(MessageView.this, data);
|
||||||
|
}
|
||||||
|
catch (MessagingException me)
|
||||||
|
{
|
||||||
|
Log.e(K9.LOG_TAG, "Unable to decrypt email.", me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
|
||||||
mAttachments = (LinearLayout)findViewById(R.id.attachments);
|
mAttachments = (LinearLayout)findViewById(R.id.attachments);
|
||||||
mAttachmentIcon = findViewById(R.id.attachment);
|
mAttachmentIcon = findViewById(R.id.attachment);
|
||||||
mShowPicturesSection = findViewById(R.id.show_pictures_section);
|
mShowPicturesSection = findViewById(R.id.show_pictures_section);
|
||||||
@ -808,14 +849,17 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
Uri uri = intent.getData();
|
Uri uri = intent.getData();
|
||||||
|
|
||||||
if (icicle!=null)
|
if (icicle != null)
|
||||||
{
|
{
|
||||||
mMessageReference = (MessageReference)icicle.getSerializable(EXTRA_MESSAGE_REFERENCE);
|
mMessageReference = (MessageReference)icicle.getSerializable(EXTRA_MESSAGE_REFERENCE);
|
||||||
mMessageReferences = (ArrayList<MessageReference>)icicle.getSerializable(EXTRA_MESSAGE_REFERENCES);
|
mMessageReferences = (ArrayList<MessageReference>)icicle.getSerializable(EXTRA_MESSAGE_REFERENCES);
|
||||||
|
|
||||||
|
mCrypto = (CryptoProvider) icicle.getSerializable(STATE_CRYPTO);
|
||||||
|
updateDecryptLayout();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (uri==null)
|
if (uri == null)
|
||||||
{
|
{
|
||||||
mMessageReference = (MessageReference)intent.getSerializableExtra(EXTRA_MESSAGE_REFERENCE);
|
mMessageReference = (MessageReference)intent.getSerializableExtra(EXTRA_MESSAGE_REFERENCE);
|
||||||
mMessageReferences = (ArrayList<MessageReference>)intent.getSerializableExtra(EXTRA_MESSAGE_REFERENCES);
|
mMessageReferences = (ArrayList<MessageReference>)intent.getSerializableExtra(EXTRA_MESSAGE_REFERENCES);
|
||||||
@ -823,7 +867,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<String> segmentList = uri.getPathSegments();
|
List<String> segmentList = uri.getPathSegments();
|
||||||
if (segmentList.size()==3)
|
if (segmentList.size() == 3)
|
||||||
{
|
{
|
||||||
String accountId = segmentList.get(0);
|
String accountId = segmentList.get(0);
|
||||||
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
||||||
@ -859,6 +903,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.d(K9.LOG_TAG, "MessageView got message " + mMessageReference);
|
Log.d(K9.LOG_TAG, "MessageView got message " + mMessageReference);
|
||||||
|
|
||||||
@ -953,6 +998,18 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
{
|
{
|
||||||
outState.putSerializable(EXTRA_MESSAGE_REFERENCE, mMessageReference);
|
outState.putSerializable(EXTRA_MESSAGE_REFERENCE, mMessageReference);
|
||||||
outState.putSerializable(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
|
outState.putSerializable(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
|
||||||
|
outState.putSerializable(STATE_CRYPTO, mCrypto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRestoreInstanceState(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onRestoreInstanceState(savedInstanceState);
|
||||||
|
|
||||||
|
mCrypto = (CryptoProvider) savedInstanceState.getSerializable(STATE_CRYPTO);
|
||||||
|
initializeCrypto();
|
||||||
|
|
||||||
|
updateDecryptLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayMessage(MessageReference ref)
|
private void displayMessage(MessageReference ref)
|
||||||
@ -970,6 +1027,9 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
mAttachments.removeAllViews();
|
mAttachments.removeAllViews();
|
||||||
findSurroundingMessagesUid();
|
findSurroundingMessagesUid();
|
||||||
|
|
||||||
|
mCrypto = null;
|
||||||
|
initializeCrypto();
|
||||||
|
|
||||||
setupDisplayMessageButtons();
|
setupDisplayMessageButtons();
|
||||||
|
|
||||||
MessagingController.getInstance(getApplication()).loadMessageForView(
|
MessagingController.getInstance(getApplication()).loadMessageForView(
|
||||||
@ -1251,7 +1311,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
{
|
{
|
||||||
if (mMessage != null)
|
if (mMessage != null)
|
||||||
{
|
{
|
||||||
MessageCompose.actionReply(this, mAccount, mMessage, false);
|
MessageCompose.actionReply(this, mAccount, mMessage, false, mCrypto.getDecryptedData());
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1260,7 +1320,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
{
|
{
|
||||||
if (mMessage != null)
|
if (mMessage != null)
|
||||||
{
|
{
|
||||||
MessageCompose.actionReply(this, mAccount, mMessage, true);
|
MessageCompose.actionReply(this, mAccount, mMessage, true, mCrypto.getDecryptedData());
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1269,7 +1329,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
{
|
{
|
||||||
if (mMessage != null)
|
if (mMessage != null)
|
||||||
{
|
{
|
||||||
MessageCompose.actionForward(this, mAccount, mMessage);
|
MessageCompose.actionForward(this, mAccount, mMessage, mCrypto.getDecryptedData());
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1376,6 +1436,11 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||||
{
|
{
|
||||||
|
if (mCrypto.onActivityResult(this, requestCode, resultCode, data))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (resultCode != RESULT_OK)
|
if (resultCode != RESULT_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1409,6 +1474,9 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1966,6 +2034,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
mMessageContentView.loadUrl("file:///android_asset/downloading.html");
|
mMessageContentView.loadUrl("file:///android_asset/downloading.html");
|
||||||
|
updateDecryptLayout();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2007,30 +2076,39 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
mHandler.removeAllAttachments();
|
mHandler.removeAllAttachments();
|
||||||
|
|
||||||
String text;
|
String text;
|
||||||
Part part = MimeUtility.findFirstPartByMimeType(mMessage, "text/html");
|
String type = "text/html";
|
||||||
if (part == null)
|
if (mCrypto.getDecryptedData() != null)
|
||||||
{
|
{
|
||||||
part = MimeUtility.findFirstPartByMimeType(mMessage, "text/plain");
|
text = mCrypto.getDecryptedData();
|
||||||
|
type = "text/plain";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Part part = MimeUtility.findFirstPartByMimeType(mMessage, "text/html");
|
||||||
if (part == null)
|
if (part == null)
|
||||||
{
|
{
|
||||||
text = null;
|
part = MimeUtility.findFirstPartByMimeType(mMessage, "text/plain");
|
||||||
}
|
if (part == null)
|
||||||
else
|
|
||||||
{
|
|
||||||
LocalTextBody body = (LocalTextBody)part.getBody();
|
|
||||||
if (body == null)
|
|
||||||
{
|
{
|
||||||
text = null;
|
text = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text = body.getBodyForDisplay();
|
LocalTextBody body = (LocalTextBody)part.getBody();
|
||||||
|
if (body == null)
|
||||||
|
{
|
||||||
|
text = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = body.getBodyForDisplay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
text = MimeUtility.getTextFromPart(part);
|
||||||
text = MimeUtility.getTextFromPart(part);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text != null)
|
if (text != null)
|
||||||
@ -2040,11 +2118,13 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
* get background images and a million other things that HTML allows.
|
* get background images and a million other things that HTML allows.
|
||||||
*/
|
*/
|
||||||
final String emailText = text;
|
final String emailText = text;
|
||||||
|
final String mimeType = type;
|
||||||
mHandler.post(new Runnable()
|
mHandler.post(new Runnable()
|
||||||
{
|
{
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
mMessageContentView.loadDataWithBaseURL("http://", emailText, "text/html", "utf-8", null);
|
mMessageContentView.loadDataWithBaseURL("http://", emailText, mimeType, "utf-8", null);
|
||||||
|
updateDecryptLayout();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mHandler.showShowPictures(text.contains("<img"));
|
mHandler.showShowPictures(text.contains("<img"));
|
||||||
@ -2056,6 +2136,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
mMessageContentView.loadUrl("file:///android_asset/empty.html");
|
mMessageContentView.loadUrl("file:///android_asset/empty.html");
|
||||||
|
updateDecryptLayout();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2099,6 +2180,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
!MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL))
|
!MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL))
|
||||||
{
|
{
|
||||||
mMessageContentView.loadUrl("file:///android_asset/empty.html");
|
mMessageContentView.loadUrl("file:///android_asset/empty.html");
|
||||||
|
updateDecryptLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -2137,6 +2219,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
mMessageContentView.loadUrl("file:///android_asset/loading.html");
|
mMessageContentView.loadUrl("file:///android_asset/loading.html");
|
||||||
|
updateDecryptLayout();
|
||||||
setProgressBarIndeterminateVisibility(true);
|
setProgressBarIndeterminateVisibility(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -2293,7 +2376,118 @@ public class MessageView extends K9Activity implements OnClickListener
|
|||||||
return slide;
|
return slide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeCrypto()
|
||||||
|
{
|
||||||
|
if (mCrypto != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mAccount == null)
|
||||||
|
{
|
||||||
|
mAccount = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
||||||
|
}
|
||||||
|
mCrypto = CryptoProvider.createInstance(mAccount);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Fill the decrypt layout with signature data, if known, make controls visible, if
|
||||||
|
* they should be visible.
|
||||||
|
*/
|
||||||
|
public void updateDecryptLayout()
|
||||||
|
{
|
||||||
|
if (mCrypto.getSignatureKeyId() != 0)
|
||||||
|
{
|
||||||
|
mCryptoSignatureUserIdRest.setText(
|
||||||
|
getString(R.string.key_id, Long.toHexString(mCrypto.getSignatureKeyId() & 0xffffffffL)));
|
||||||
|
String userId = mCrypto.getSignatureUserId();
|
||||||
|
if (userId == null)
|
||||||
|
{
|
||||||
|
userId = 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 (mCrypto.getSignatureSuccess())
|
||||||
|
{
|
||||||
|
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
|
||||||
|
}
|
||||||
|
else if (mCrypto.getSignatureUnknown())
|
||||||
|
{
|
||||||
|
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||||
|
}
|
||||||
|
mCryptoSignatureLayout.setVisibility(View.VISIBLE);
|
||||||
|
mDecryptLayout.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!true || ((mMessage == null) && (mCrypto.getDecryptedData() == null)))
|
||||||
|
{
|
||||||
|
mDecryptLayout.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCrypto.getDecryptedData() != null)
|
||||||
|
{
|
||||||
|
if (mCrypto.getSignatureKeyId() == 0)
|
||||||
|
{
|
||||||
|
mDecryptLayout.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no need to show this after decryption/verification
|
||||||
|
mDecryptButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDecryptButton.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (mCrypto.isEncrypted(mMessage))
|
||||||
|
{
|
||||||
|
mDecryptButton.setText(R.string.btn_decrypt);
|
||||||
|
mDecryptLayout.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
else if (mCrypto.isSigned(mMessage))
|
||||||
|
{
|
||||||
|
mDecryptButton.setText(R.string.btn_verify);
|
||||||
|
mDecryptLayout.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mDecryptLayout.setVisibility(View.GONE);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// check for PGP/MIME encryption
|
||||||
|
Part pgp = MimeUtility.findFirstPartByMimeType(mMessage, "application/pgp-encrypted");
|
||||||
|
if (pgp != null)
|
||||||
|
{
|
||||||
|
Toast.makeText(this, R.string.pgp_mime_unsupported, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MessagingException e)
|
||||||
|
{
|
||||||
|
// nothing to do...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDecryptDone()
|
||||||
|
{
|
||||||
|
// TODO: this might not be enough if the orientation was changed while in APG,
|
||||||
|
// sometimes shows the original encrypted content
|
||||||
|
mMessageContentView.loadDataWithBaseURL("email://", mCrypto.getDecryptedData(), "text/plain", "utf-8", null);
|
||||||
|
updateDecryptLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* Emulate the shift key being pressed to trigger the text selection mode
|
* Emulate the shift key being pressed to trigger the text selection mode
|
||||||
* of a WebView.
|
* of a WebView.
|
||||||
*/
|
*/
|
||||||
|
@ -5,16 +5,25 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.*;
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.EditTextPreference;
|
||||||
|
import android.preference.ListPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.preference.RingtonePreference;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import com.fsck.k9.*;
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
import com.fsck.k9.Account.FolderMode;
|
import com.fsck.k9.Account.FolderMode;
|
||||||
|
import com.fsck.k9.K9;
|
||||||
|
import com.fsck.k9.Preferences;
|
||||||
|
import com.fsck.k9.R;
|
||||||
import com.fsck.k9.activity.ChooseFolder;
|
import com.fsck.k9.activity.ChooseFolder;
|
||||||
import com.fsck.k9.activity.ChooseIdentity;
|
import com.fsck.k9.activity.ChooseIdentity;
|
||||||
import com.fsck.k9.activity.ColorPickerDialog;
|
import com.fsck.k9.activity.ColorPickerDialog;
|
||||||
import com.fsck.k9.activity.K9PreferenceActivity;
|
import com.fsck.k9.activity.K9PreferenceActivity;
|
||||||
import com.fsck.k9.activity.ManageIdentities;
|
import com.fsck.k9.activity.ManageIdentities;
|
||||||
|
import com.fsck.k9.crypto.Apg;
|
||||||
import com.fsck.k9.mail.Store;
|
import com.fsck.k9.mail.Store;
|
||||||
import com.fsck.k9.service.MailService;
|
import com.fsck.k9.service.MailService;
|
||||||
|
|
||||||
@ -60,7 +69,8 @@ public class AccountSettings extends K9PreferenceActivity
|
|||||||
private static final String PREFERENCE_MESSAGE_SIZE = "account_autodownload_size";
|
private static final String PREFERENCE_MESSAGE_SIZE = "account_autodownload_size";
|
||||||
private static final String PREFERENCE_QUOTE_PREFIX = "account_quote_prefix";
|
private static final String PREFERENCE_QUOTE_PREFIX = "account_quote_prefix";
|
||||||
private static final String PREFERENCE_SYNC_REMOTE_DELETIONS = "account_sync_remote_deletetions";
|
private static final String PREFERENCE_SYNC_REMOTE_DELETIONS = "account_sync_remote_deletetions";
|
||||||
|
private static final String PREFERENCE_CRYPTO_APP = "crypto_app";
|
||||||
|
private static final String PREFERENCE_CRYPTO_AUTO_SIGNATURE = "crypto_auto_signature";
|
||||||
|
|
||||||
private Account mAccount;
|
private Account mAccount;
|
||||||
|
|
||||||
@ -94,7 +104,8 @@ public class AccountSettings extends K9PreferenceActivity
|
|||||||
private CheckBoxPreference mNotificationOpensUnread;
|
private CheckBoxPreference mNotificationOpensUnread;
|
||||||
private EditTextPreference mAccountQuotePrefix;
|
private EditTextPreference mAccountQuotePrefix;
|
||||||
private CheckBoxPreference mSyncRemoteDeletions;
|
private CheckBoxPreference mSyncRemoteDeletions;
|
||||||
|
private ListPreference mCryptoApp;
|
||||||
|
private CheckBoxPreference mCryptoAutoSignature;
|
||||||
|
|
||||||
public static void actionSettings(Context context, Account account)
|
public static void actionSettings(Context context, Account account)
|
||||||
{
|
{
|
||||||
@ -510,6 +521,53 @@ public class AccountSettings extends K9PreferenceActivity
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mCryptoApp = (ListPreference) findPreference(PREFERENCE_CRYPTO_APP);
|
||||||
|
CharSequence cryptoAppEntries[] = mCryptoApp.getEntries();
|
||||||
|
if (!new Apg().isAvailable(this))
|
||||||
|
{
|
||||||
|
int apgIndex = mCryptoApp.findIndexOfValue(Apg.NAME);
|
||||||
|
if (apgIndex >= 0)
|
||||||
|
{
|
||||||
|
cryptoAppEntries[apgIndex] = "APG (" + getResources().getString(R.string.account_settings_crypto_app_not_available) + ")";
|
||||||
|
mCryptoApp.setEntries(cryptoAppEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCryptoApp.setValue(String.valueOf(mAccount.getCryptoApp()));
|
||||||
|
mCryptoApp.setSummary(mCryptoApp.getEntry());
|
||||||
|
mCryptoApp.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||||
|
{
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||||
|
{
|
||||||
|
String value = newValue.toString();
|
||||||
|
int index = mCryptoApp.findIndexOfValue(value);
|
||||||
|
mCryptoApp.setSummary(mCryptoApp.getEntries()[index]);
|
||||||
|
mCryptoApp.setValue(value);
|
||||||
|
handleCryptoAppDependencies();
|
||||||
|
if (Apg.NAME.equals(value))
|
||||||
|
{
|
||||||
|
Apg.createInstance(null).test(AccountSettings.this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mCryptoAutoSignature = (CheckBoxPreference) findPreference(PREFERENCE_CRYPTO_AUTO_SIGNATURE);
|
||||||
|
mCryptoAutoSignature.setChecked(mAccount.getCryptoAutoSignature());
|
||||||
|
|
||||||
|
handleCryptoAppDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleCryptoAppDependencies()
|
||||||
|
{
|
||||||
|
if ("".equals(mCryptoApp.getValue()))
|
||||||
|
{
|
||||||
|
mCryptoAutoSignature.setEnabled(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCryptoAutoSignature.setEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -543,6 +601,8 @@ public class AccountSettings extends K9PreferenceActivity
|
|||||||
mAccount.setSyncRemoteDeletions(mSyncRemoteDeletions.isChecked());
|
mAccount.setSyncRemoteDeletions(mSyncRemoteDeletions.isChecked());
|
||||||
mAccount.setSearchableFolders(Account.Searchable.valueOf(mSearchableFolders.getValue()));
|
mAccount.setSearchableFolders(Account.Searchable.valueOf(mSearchableFolders.getValue()));
|
||||||
mAccount.setQuotePrefix(mAccountQuotePrefix.getText());
|
mAccount.setQuotePrefix(mAccountQuotePrefix.getText());
|
||||||
|
mAccount.setCryptoApp(mCryptoApp.getValue());
|
||||||
|
mAccount.setCryptoAutoSignature(mCryptoAutoSignature.isChecked());
|
||||||
|
|
||||||
boolean needsRefresh = mAccount.setAutomaticCheckIntervalMinutes(Integer.parseInt(mCheckFrequency.getValue()));
|
boolean needsRefresh = mAccount.setAutomaticCheckIntervalMinutes(Integer.parseInt(mCheckFrequency.getValue()));
|
||||||
needsRefresh |= mAccount.setFolderSyncMode(Account.FolderMode.valueOf(mSyncMode.getValue()));
|
needsRefresh |= mAccount.setFolderSyncMode(Account.FolderMode.valueOf(mSyncMode.getValue()));
|
||||||
|
556
src/com/fsck/k9/crypto/Apg.java
Normal file
556
src/com/fsck/k9/crypto/Apg.java
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
package com.fsck.k9.crypto;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
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.Account;
|
||||||
|
import com.fsck.k9.R;
|
||||||
|
import com.fsck.k9.activity.MessageCompose;
|
||||||
|
import com.fsck.k9.activity.MessageView;
|
||||||
|
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 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_STATUS = "status";
|
||||||
|
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_REPLY_TO = "replyTo";
|
||||||
|
public static final String EXTRA_SEND_TO = "sendTo";
|
||||||
|
public static final String EXTRA_SUBJECT = "subject";
|
||||||
|
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_PROGRESS = "progress";
|
||||||
|
public static final String EXTRA_MAX = "max";
|
||||||
|
public static final String EXTRA_ACCOUNT = "account";
|
||||||
|
|
||||||
|
public static final int DECRYPT_MESSAGE = 0x21070001;
|
||||||
|
public static final int ENCRYPT_MESSAGE = 0x21070002;
|
||||||
|
public static final int SELECT_PUBLIC_KEYS = 0x21070003;
|
||||||
|
public static final int SELECT_SECRET_KEY = 0x21070004;
|
||||||
|
|
||||||
|
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(Account account)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
* @return success or failure
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean selectSecretKey(Activity activity)
|
||||||
|
{
|
||||||
|
android.content.Intent intent = new android.content.Intent(Intent.SELECT_SECRET_KEY);
|
||||||
|
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.
|
||||||
|
* @return success or failure
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean selectEncryptionKeys(Activity activity, String emails)
|
||||||
|
{
|
||||||
|
android.content.Intent intent = new android.content.Intent(Apg.Intent.SELECT_PUBLIC_KEYS);
|
||||||
|
long[] initialKeyIds = null;
|
||||||
|
if (!hasEncryptionKeys())
|
||||||
|
{
|
||||||
|
Vector<Long> keyIds = new Vector<Long>();
|
||||||
|
if (hasSignatureKey())
|
||||||
|
{
|
||||||
|
keyIds.add(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.size() > 0)
|
||||||
|
{
|
||||||
|
initialKeyIds = new long[keyIds.size()];
|
||||||
|
for (int i = 0, size = keyIds.size(); i < size; ++i)
|
||||||
|
{
|
||||||
|
initialKeyIds[i] = keyIds.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
initialKeyIds = mEncryptionKeyIds;
|
||||||
|
}
|
||||||
|
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 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)
|
||||||
|
{
|
||||||
|
switch (requestCode)
|
||||||
|
{
|
||||||
|
case Apg.SELECT_SECRET_KEY:
|
||||||
|
if (resultCode != Activity.RESULT_OK || data == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setSignatureKeyId(data.getLongExtra(Apg.EXTRA_KEY_ID, 0));
|
||||||
|
setSignatureUserId(data.getStringExtra(Apg.EXTRA_USER_ID));
|
||||||
|
((MessageCompose) activity).updateEncryptLayout();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Apg.SELECT_PUBLIC_KEYS:
|
||||||
|
if (resultCode != Activity.RESULT_OK || data == null)
|
||||||
|
{
|
||||||
|
mEncryptionKeyIds = null;
|
||||||
|
((MessageCompose) activity).onEncryptionKeySelectionDone();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mEncryptionKeyIds = data.getLongArrayExtra(Apg.EXTRA_SELECTION);
|
||||||
|
((MessageCompose) activity).onEncryptionKeySelectionDone();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Apg.ENCRYPT_MESSAGE:
|
||||||
|
if (resultCode != Activity.RESULT_OK || data == null)
|
||||||
|
{
|
||||||
|
mEncryptedData = null;
|
||||||
|
((MessageCompose) activity).onEncryptDone();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mEncryptedData = 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 (mEncryptedData == null) {
|
||||||
|
mEncryptedData = data.getStringExtra(Apg.EXTRA_DECRYPTED_MESSAGE);
|
||||||
|
}
|
||||||
|
if (mEncryptedData != null)
|
||||||
|
{
|
||||||
|
((MessageCompose) activity).onEncryptDone();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Apg.DECRYPT_MESSAGE:
|
||||||
|
if (resultCode != Activity.RESULT_OK || data == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSignatureUserId = data.getStringExtra(Apg.EXTRA_SIGNATURE_USER_ID);
|
||||||
|
mSignatureKeyId = data.getLongExtra(Apg.EXTRA_SIGNATURE_KEY_ID, 0);
|
||||||
|
mSignatureSuccess = data.getBooleanExtra(Apg.EXTRA_SIGNATURE_SUCCESS, false);
|
||||||
|
mSignatureUnknown = data.getBooleanExtra(Apg.EXTRA_SIGNATURE_UNKNOWN, false);
|
||||||
|
|
||||||
|
mDecryptedData = data.getStringExtra(Apg.EXTRA_DECRYPTED_MESSAGE);
|
||||||
|
((MessageView) activity).onDecryptDone();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the encrypt activity.
|
||||||
|
*
|
||||||
|
* @param activity
|
||||||
|
* @param data
|
||||||
|
* @return success or failure
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean encrypt(Activity activity, String data)
|
||||||
|
{
|
||||||
|
android.content.Intent intent = new android.content.Intent(Intent.ENCRYPT_AND_RETURN);
|
||||||
|
intent.setType("text/plain");
|
||||||
|
intent.putExtra(Apg.EXTRA_TEXT, data);
|
||||||
|
intent.putExtra(Apg.EXTRA_ENCRYPTION_KEY_IDS, mEncryptionKeyIds);
|
||||||
|
intent.putExtra(Apg.EXTRA_SIGNATURE_KEY_ID, mSignatureKeyId);
|
||||||
|
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 activity
|
||||||
|
* @param data
|
||||||
|
* @return success or failure
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean decrypt(Activity activity, String data)
|
||||||
|
{
|
||||||
|
android.content.Intent intent = new android.content.Intent(Apg.Intent.DECRYPT_AND_RETURN);
|
||||||
|
intent.setType("text/plain");
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
intent.putExtra(EXTRA_TEXT, data);
|
||||||
|
activity.startActivityForResult(intent, Apg.DECRYPT_MESSAGE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ActivityNotFoundException e)
|
||||||
|
{
|
||||||
|
Toast.makeText(activity,
|
||||||
|
R.string.error_activity_not_found,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
107
src/com/fsck/k9/crypto/CryptoProvider.java
Normal file
107
src/com/fsck/k9/crypto/CryptoProvider.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package com.fsck.k9.crypto;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
|
import com.fsck.k9.mail.Message;
|
||||||
|
|
||||||
|
abstract public class CryptoProvider implements Serializable
|
||||||
|
{
|
||||||
|
static final long serialVersionUID = 0x21071234;
|
||||||
|
|
||||||
|
protected long mEncryptionKeyIds[] = null;
|
||||||
|
protected long mSignatureKeyId = 0;
|
||||||
|
protected String mSignatureUserId = null;
|
||||||
|
protected boolean mSignatureSuccess = false;
|
||||||
|
protected boolean mSignatureUnknown = false;
|
||||||
|
protected String mDecryptedData = null;
|
||||||
|
protected String mEncryptedData = null;
|
||||||
|
|
||||||
|
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);
|
||||||
|
abstract public boolean selectSecretKey(Activity activity);
|
||||||
|
abstract public boolean selectEncryptionKeys(Activity activity, String emails);
|
||||||
|
abstract public boolean encrypt(Activity activity, String data);
|
||||||
|
abstract public boolean decrypt(Activity activity, String data);
|
||||||
|
abstract public long[] getSecretKeyIdsFromEmail(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(Account account)
|
||||||
|
{
|
||||||
|
if (Apg.NAME.equals(account.getCryptoApp()))
|
||||||
|
{
|
||||||
|
return Apg.createInstance(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
return None.createInstance(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignatureKeyId(long keyId)
|
||||||
|
{
|
||||||
|
mSignatureKeyId = keyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSignatureKeyId()
|
||||||
|
{
|
||||||
|
return mSignatureKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEncryptionKeys(long keyIds[])
|
||||||
|
{
|
||||||
|
mEncryptionKeyIds = keyIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long[] getEncryptionKeys()
|
||||||
|
{
|
||||||
|
return mEncryptionKeyIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSignatureKey()
|
||||||
|
{
|
||||||
|
return mSignatureKeyId != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEncryptionKeys()
|
||||||
|
{
|
||||||
|
return (mEncryptionKeyIds != null) && (mEncryptionKeyIds.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncryptedData()
|
||||||
|
{
|
||||||
|
return mEncryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDecryptedData()
|
||||||
|
{
|
||||||
|
return mDecryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignatureUserId(String userId)
|
||||||
|
{
|
||||||
|
mSignatureUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignatureUserId()
|
||||||
|
{
|
||||||
|
return mSignatureUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSignatureSuccess()
|
||||||
|
{
|
||||||
|
return mSignatureSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSignatureUnknown()
|
||||||
|
{
|
||||||
|
return mSignatureUnknown;
|
||||||
|
}
|
||||||
|
}
|
89
src/com/fsck/k9/crypto/None.java
Normal file
89
src/com/fsck/k9/crypto/None.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package com.fsck.k9.crypto;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
|
import com.fsck.k9.mail.Message;
|
||||||
|
|
||||||
|
public class None extends CryptoProvider
|
||||||
|
{
|
||||||
|
static final long serialVersionUID = 0x21071230;
|
||||||
|
public static final String NAME = "";
|
||||||
|
|
||||||
|
public static None createInstance(Account account)
|
||||||
|
{
|
||||||
|
return new None();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable(Context context)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean selectSecretKey(Activity activity)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean selectEncryptionKeys(Activity activity, String emails)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long[] getSecretKeyIdsFromEmail(Context context, String email)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUserId(Context context, long keyId)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onActivityResult(Activity activity, int requestCode, int resultCode,
|
||||||
|
android.content.Intent data)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean encrypt(Activity activity, String data)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean decrypt(Activity activity, String data)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEncrypted(Message message)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSigned(Message message)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(Context context)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user