From ca5089efb84fd3c60cf317de474f8e313b8119e5 Mon Sep 17 00:00:00 2001 From: Mihai Preda Date: Thu, 4 Jun 2009 09:39:24 -0700 Subject: [PATCH] AI 149564: Escape special characters such as '<>&' in text/plain for display in WebView. Integrate CL 144586,145919 from imode. Remove the Emoji escaping/workaround for WebView. Also integrate MimeHeader.java from CL 143064 from imode. BUG=1785319,1860250 Automated import of CL 149564 --- .../android/email/activity/MessageView.java | 53 +++++++++++++++++-- .../email/mail/internet/MimeHeader.java | 2 +- .../email/activity/MessageViewTests.java | 29 ++++++++++ 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/com/android/email/activity/MessageView.java b/src/com/android/email/activity/MessageView.java index 6856d959e..7831b9c63 100644 --- a/src/com/android/email/activity/MessageView.java +++ b/src/com/android/email/activity/MessageView.java @@ -94,9 +94,13 @@ public class MessageView extends Activity }; private static final int METHODS_STATUS_COLUMN = 1; - // regex that matches start of img tag. '<(?i)img\s+'. + // Regex that matches start of img tag. '<(?i)img\s+'. private static final Pattern IMG_TAG_START_REGEX = Pattern.compile("<(?i)img\\s+"); + // Regex that matches characters that has special meaning in HTML. '<', '>', '&' and + // continuous spaces at least two. + private static final Pattern PLAIN_TEXT_TO_ESCAPE = Pattern.compile("[<>&]| {2,}|\r?\n"); + private TextView mSubjectView; private TextView mFromView; private TextView mDateView; @@ -899,6 +903,10 @@ public class MessageView extends Activity text = EmailHtmlUtil.resolveInlineImage( getContentResolver(), mAccount, text, mMessage, 0); } else { + // And also escape special character, such as "<>&", + // to HTML escape sequence. + text = escapeCharacterToDisplay(text); + /* * Linkify the plain text and convert it to HTML by replacing * \r?\n with
and adding a html/body wrapper. @@ -923,7 +931,7 @@ public class MessageView extends Activity m.appendTail(sb); } sb.append(""); - text = sb.toString().replaceAll("\r?\n", "
"); + text = sb.toString(); } /* @@ -1115,5 +1123,44 @@ public class MessageView extends Activity } } } + + /** + * Escape some special character as HTML escape sequence. + * + * @param text Text to be displayed using WebView. + * @return Text correctly escaped. + */ + /* package */ static String escapeCharacterToDisplay(String text) { + Pattern pattern = PLAIN_TEXT_TO_ESCAPE; + Matcher match = pattern.matcher(text); + + if (match.find()) { + StringBuilder out = new StringBuilder(); + int end = 0; + do { + int start = match.start(); + out.append(text.substring(end, start)); + end = match.end(); + int c = text.codePointAt(start); + if (c == ' ') { + // Escape successive spaces into series of " ". + for (int i = 1, n = end - start; i < n; ++i) { + out.append(" "); + } + out.append(' '); + } else if (c == '\r' || c == '\n') { + out.append("
"); + } else if (c == '<') { + out.append("<"); + } else if (c == '>') { + out.append(">"); + } else if (c == '&') { + out.append("&"); + } + } while (match.find()); + out.append(text.substring(end)); + text = out.toString(); + } + return text; + } } - diff --git a/src/com/android/email/mail/internet/MimeHeader.java b/src/com/android/email/mail/internet/MimeHeader.java index 2f58e0e7a..ab21faa4c 100644 --- a/src/com/android/email/mail/internet/MimeHeader.java +++ b/src/com/android/email/mail/internet/MimeHeader.java @@ -65,7 +65,7 @@ public class MimeHeader { } public void addHeader(String name, String value) throws MessagingException { - mFields.add(new Field(name, MimeUtility.foldAndEncode(value))); + mFields.add(new Field(name, value)); } public void setHeader(String name, String value) throws MessagingException { diff --git a/tests/src/com/android/email/activity/MessageViewTests.java b/tests/src/com/android/email/activity/MessageViewTests.java index c403013fc..6cd89f7bd 100644 --- a/tests/src/com/android/email/activity/MessageViewTests.java +++ b/tests/src/com/android/email/activity/MessageViewTests.java @@ -74,6 +74,10 @@ public class MessageViewTests private WebView mMessageContentView; private Context mContext; + private static final String textTags = "Plain &"; + private static final String textSpaces = "3 spaces end."; + private static final String textNewlines = "ab \r\n \n \n\r\n"; + public MessageViewTests() { super("com.android.email", MessageView.class); } @@ -168,4 +172,29 @@ public class MessageViewTests } } + /** + * Test for escapeCharacterToDisplay in plain text mode. + */ + public void testEscapeCharacterToDisplayPlainText() { + // HTML tag will be escaped. + String plainTags = MessageView.escapeCharacterToDisplay(textTags); + assertEquals("plain tag", "<b>Plain</b> &", plainTags); + + // Successive spaces will be escaped as " " + String plainSpaces = MessageView.escapeCharacterToDisplay(textSpaces); + assertEquals("plain spaces", "3 spaces   end.", plainSpaces); + + // Newlines will be escaped as "
" + String plainNewlines = MessageView.escapeCharacterToDisplay(textNewlines); + assertEquals("plain spaces", "ab
 
  

", plainNewlines); + + // All combinations. + String textAll = textTags + "\n" + textSpaces + "\n" + textNewlines; + String plainAll = MessageView.escapeCharacterToDisplay(textAll); + assertEquals("plain all", + "<b>Plain</b> &
" + + "3 spaces   end.
" + + "ab
 
  

", + plainAll); + } }