Simplified decryption of inline encrypted messages

pull/162/head
M66B 5 years ago
parent 4a5b65fd72
commit fc41defed7

@ -517,9 +517,10 @@ So, unless your provider can enable this extension, you cannot use FairEmail for
**(12) How does encryption/decryption work?** **(12) How does encryption/decryption work?**
First of all you need to install and configure [OpenKeychain](https://f-droid.org/en/packages/org.sufficientlysecure.keychain/). First of all you need to install and configure [OpenKeychain](https://f-droid.org/en/packages/org.sufficientlysecure.keychain/).
To encrypt and send a message just check the menu *Encrypt* and the message will be encrypted on sending. To encrypt and send a message just check the menu *Encrypt* and the message will be encrypted on sending.
To decrypt a received message, open the message and tap the padlock icon just below the grey message action bar.
If the message is inline encrypted (not advised), select the menu *Decrypt* in the message 'more' three dots menu. To decrypt a received message, open the message and just tap the padlock icon just below the grey message action bar.
The first time you send an encrypted message you might be asked for a sign key. The first time you send an encrypted message you might be asked for a sign key.
FairEmail will automatically store the sign key ID in the selected identity for the next time. FairEmail will automatically store the sign key ID in the selected identity for the next time.

@ -1210,6 +1210,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
attachments = new ArrayList<>(); attachments = new ArrayList<>();
properties.setAttachments(message.id, attachments); properties.setAttachments(message.id, attachments);
boolean iencrypted = properties.getValue("iencrypted", message.id);
boolean show_inline = properties.getValue("inline", message.id); boolean show_inline = properties.getValue("inline", message.id);
Log.i("Show inline=" + show_inline); Log.i("Show inline=" + show_inline);
@ -1260,7 +1261,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
btnDownloadAttachments.setVisibility(download && suitable ? View.VISIBLE : View.GONE); btnDownloadAttachments.setVisibility(download && suitable ? View.VISIBLE : View.GONE);
tvNoInternetAttachments.setVisibility(downloading && !suitable ? View.VISIBLE : View.GONE); tvNoInternetAttachments.setVisibility(downloading && !suitable ? View.VISIBLE : View.GONE);
ibDecrypt.setVisibility(is_encrypted ? View.VISIBLE : View.GONE); ibDecrypt.setVisibility(iencrypted || is_encrypted ? View.VISIBLE : View.GONE);
cbInline.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { cbInline.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
@ -2432,9 +2433,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
popupMenu.getMenu().findItem(R.id.menu_manage_keywords).setEnabled(message.uid != null && !message.folderReadOnly); popupMenu.getMenu().findItem(R.id.menu_manage_keywords).setEnabled(message.uid != null && !message.folderReadOnly);
popupMenu.getMenu().findItem(R.id.menu_decrypt).setEnabled(
message.content && message.to != null && message.to.length > 0);
popupMenu.getMenu().findItem(R.id.menu_resync).setEnabled(message.uid != null); popupMenu.getMenu().findItem(R.id.menu_resync).setEnabled(message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_create_rule).setEnabled(!message.accountPop); popupMenu.getMenu().findItem(R.id.menu_create_rule).setEnabled(!message.accountPop);
@ -2461,9 +2459,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
case R.id.menu_junk: case R.id.menu_junk:
onMenuJunk(message); onMenuJunk(message);
return true; return true;
case R.id.menu_decrypt:
onActionDecrypt(message);
return true;
case R.id.menu_resync: case R.id.menu_resync:
onMenuResync(message); onMenuResync(message);
return true; return true;
@ -2545,6 +2540,12 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
String body = Helper.readText(file); String body = Helper.readText(file);
Document document = Jsoup.parse(body); Document document = Jsoup.parse(body);
// Check for inline encryption
int begin = body.indexOf(Helper.PGP_BEGIN_MESSAGE);
int end = body.indexOf(Helper.PGP_END_MESSAGE);
args.putBoolean("iencrypted", begin >= 0 && begin < end);
// Check for images
boolean has_images = false; boolean has_images = false;
for (Element img : document.select("img")) { for (Element img : document.select("img")) {
if (inline) { if (inline) {
@ -2560,12 +2561,14 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
} }
args.putBoolean("has_images", has_images); args.putBoolean("has_images", has_images);
// Collapse quotes
if (!show_quotes) { if (!show_quotes) {
for (Element quote : document.select("blockquote")) for (Element quote : document.select("blockquote"))
quote.html("&#8230;"); quote.html("&#8230;");
body = document.html(); body = document.html();
} }
// Cleanup message
String html = HtmlHelper.sanitize(context, body, text_color, show_images); String html = HtmlHelper.sanitize(context, body, text_color, show_images);
if (debug) { if (debug) {
Document format = Jsoup.parse(html); Document format = Jsoup.parse(html);
@ -2590,6 +2593,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
} }
}, null); }, null);
// Replace quote spans
SpannableStringBuilder builder = new SpannableStringBuilder(spanned); SpannableStringBuilder builder = new SpannableStringBuilder(spanned);
QuoteSpan[] quoteSpans = builder.getSpans(0, builder.length(), QuoteSpan.class); QuoteSpan[] quoteSpans = builder.getSpans(0, builder.length(), QuoteSpan.class);
for (QuoteSpan quoteSpan : quoteSpans) { for (QuoteSpan quoteSpan : quoteSpans) {
@ -2601,6 +2605,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
builder.removeSpan(quoteSpan); builder.removeSpan(quoteSpan);
} }
// Make collapsed quotes clickable
if (!show_quotes) { if (!show_quotes) {
final int px = Helper.dp2pixels(context, 24 + (zoom) * 8); final int px = Helper.dp2pixels(context, 24 + (zoom) * 8);
@ -2627,6 +2632,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
protected void onExecuted(Bundle args, SpannableStringBuilder body) { protected void onExecuted(Bundle args, SpannableStringBuilder body) {
TupleMessageEx message = (TupleMessageEx) args.getSerializable("message"); TupleMessageEx message = (TupleMessageEx) args.getSerializable("message");
properties.setBody(message.id, body); properties.setBody(message.id, body);
properties.setValue("iencrypted", message.id, args.getBoolean("iencrypted"));
TupleMessageEx amessage = getMessage(); TupleMessageEx amessage = getMessage();
if (amessage == null || !amessage.id.equals(message.id)) if (amessage == null || !amessage.id.equals(message.id))

@ -266,10 +266,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW"; static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW";
static final String ACTION_DECRYPT = BuildConfig.APPLICATION_ID + ".DECRYPT"; static final String ACTION_DECRYPT = BuildConfig.APPLICATION_ID + ".DECRYPT";
private static final String PGP_BEGIN_MESSAGE = "-----BEGIN PGP MESSAGE-----";
private static final String PGP_END_MESSAGE = "-----END PGP MESSAGE-----";
private static final List<String> DUPLICATE_ORDER = Collections.unmodifiableList(Arrays.asList( private static final List<String> DUPLICATE_ORDER = Collections.unmodifiableList(Arrays.asList(
EntityFolder.INBOX, EntityFolder.INBOX,
EntityFolder.OUTBOX, EntityFolder.OUTBOX,
@ -3803,10 +3799,10 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (file.exists()) { if (file.exists()) {
// https://tools.ietf.org/html/rfc4880#section-6.2 // https://tools.ietf.org/html/rfc4880#section-6.2
String body = Helper.readText(file); String body = Helper.readText(file);
int begin = body.indexOf(PGP_BEGIN_MESSAGE); int begin = body.indexOf(Helper.PGP_BEGIN_MESSAGE);
int end = body.indexOf(PGP_END_MESSAGE); int end = body.indexOf(Helper.PGP_END_MESSAGE);
if (begin >= 0 && begin < end) { if (begin >= 0 && begin < end) {
String section = body.substring(begin, end + PGP_END_MESSAGE.length()); String section = body.substring(begin, end + Helper.PGP_END_MESSAGE.length());
String[] lines = section.split("<br>"); String[] lines = section.split("<br>");
List<String> disarmored = new ArrayList<>(); List<String> disarmored = new ArrayList<>();
for (String line : lines) for (String line : lines)

@ -114,6 +114,9 @@ public class Helper {
static final int BUFFER_SIZE = 8192; // Same as in Files class static final int BUFFER_SIZE = 8192; // Same as in Files class
static final String PGP_BEGIN_MESSAGE = "-----BEGIN PGP MESSAGE-----";
static final String PGP_END_MESSAGE = "-----END PGP MESSAGE-----";
static final String FAQ_URI = "https://github.com/M66B/FairEmail/blob/master/FAQ.md"; static final String FAQ_URI = "https://github.com/M66B/FairEmail/blob/master/FAQ.md";
static final String XDA_URI = "https://forum.xda-developers.com/showthread.php?t=3824168"; static final String XDA_URI = "https://forum.xda-developers.com/showthread.php?t=3824168";
static final String SUPPORT_URI = "https://contact.faircode.eu/?product=fairemailsupport"; static final String SUPPORT_URI = "https://contact.faircode.eu/?product=fairemailsupport";

@ -24,10 +24,6 @@
android:id="@+id/menu_junk" android:id="@+id/menu_junk"
android:title="@string/title_spam" /> android:title="@string/title_spam" />
<item
android:id="@+id/menu_decrypt"
android:title="@string/title_decrypt" />
<item <item
android:id="@+id/menu_resync" android:id="@+id/menu_resync"
android:title="@string/title_resync" /> android:title="@string/title_resync" />

Loading…
Cancel
Save