From bfb03165831429352434b0150f9d4a79f70816e5 Mon Sep 17 00:00:00 2001 From: Joe Steele Date: Tue, 8 Oct 2013 19:14:08 -0400 Subject: [PATCH] Fix fatal IndexOutOfBoundsException The problem: Configure the account (just an example -- problems can occur in other configurations as well): Message Format: HTML Reply quoting style: Prefix Quote message when replying: yes Reply after quoted text: yes Reply to a message that has a large quantity (20+) of \r\n scattered in the body of its HTML version (not an unusual scenario). Add a reply. Save the message as a draft. Go back & open the draft again. A fatal IndexOutOfBoundsException occurs. The cause: When the draft was saved, the X-K9mail-Identity header was computed and added to the message, then the text of the message was processed with MimeUtility.fixDraftTextBody, replacing all occurrences of \r\n with \n in the quoted message before being saved in LocalStore, thus invalidating the X-K9mail-Identity header. The fix: Remove MimeUtility.fixDraftTextBody and implement MessageCompose$EolConvertingEditText instead. Any message text placed in an EolConvertingEditText widget is assured to have \n line endings. Any message text extracted from an EolConvertingEditText widget is assured to have \r\n line endings. The X-K9mail-Identity header will always be computed correctly. Issues thought to be related: 4782, 5010, 5634, 5725 As noted in some of the referenced issues, errors didn't always result in a fatal exception, but instead with mixed up text. Ref: commit f9a35aeaeeae67bd88c3b253c25d06832ca7da73 --- res/layout/message_compose.xml | 12 ++- src/com/fsck/k9/activity/MessageCompose.java | 81 ++++++++++++++----- .../fsck/k9/mail/internet/MimeUtility.java | 23 +----- 3 files changed, 70 insertions(+), 46 deletions(-) diff --git a/res/layout/message_compose.xml b/res/layout/message_compose.xml index 497b6ffbf..d0ef2f14a 100644 --- a/res/layout/message_compose.xml +++ b/res/layout/message_compose.xml @@ -216,7 +216,8 @@ - - - - body = uri.getQueryParameters("body"); if (!body.isEmpty()) { - mMessageContentView.setText(body.get(0)); + mMessageContentView.setCharacters(body.get(0)); } } @@ -3970,4 +3976,35 @@ public class MessageCompose extends K9Activity implements OnClickListener, private boolean includeQuotedText() { return (mQuotedTextMode == QuotedTextMode.SHOW); } + + /** + * An {@link EditText} extension with methods that convert line endings from + * {@code \r\n} to {@code \n} and back again when setting and getting text. + * + */ + private static class EolConvertingEditText extends EditText { + + public EolConvertingEditText(Context context, AttributeSet attrs) { + super(context, attrs); + } + + /** + * Return the text the EolConvertingEditText is displaying. + * + * @return A string with any line endings converted to {@code \r\n}. + */ + public String getCharacters() { + return getText().toString().replace("\n", "\r\n"); + } + + /** + * Sets the string value of the EolConvertingEditText. Any line endings + * in the string will be converted to {@code \n}. + * + * @param text + */ + public void setCharacters(CharSequence text) { + setText(text.toString().replace("\r\n", "\n")); + } + } } diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index c80100389..0bc532a60 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -3416,7 +3416,7 @@ public class MimeUtility { if (part.isMimeType("text/plain")) { String bodyText = getTextFromPart(part); if (bodyText != null) { - text = fixDraftTextBody(bodyText); + text = bodyText; html = HtmlConverter.textToHtml(text); } } else if (part.isMimeType("multipart/alternative") && @@ -3427,9 +3427,9 @@ public class MimeUtility { String bodyText = getTextFromPart(bodyPart); if (bodyText != null) { if (text.length() == 0 && bodyPart.isMimeType("text/plain")) { - text = fixDraftTextBody(bodyText); + text = bodyText; } else if (html.length() == 0 && bodyPart.isMimeType("text/html")) { - html = fixDraftTextBody(bodyText); + html = bodyText; } } } @@ -3437,21 +3437,4 @@ public class MimeUtility { return new ViewableContainer(text, html, attachments); } - - /** - * Fix line endings of text bodies in draft messages. - * - *

- * We create drafts with LF line endings. The values in the identity header are based on that. - * So we replace CRLF with LF when loading messages (from the server). - *

- * - * @param text - * The body text with CRLF line endings - * - * @return The text with LF line endings - */ - private static String fixDraftTextBody(String text) { - return text.replace("\r\n", "\n"); - } }