DO NOT MERGE: Relax MIME date parser.

Make the date parser accept invalid dates like
"Thu, 10 Dec 09 15:08:08 GMT-0700" which was observed in an email from eBay.

Per RFC, timezone must be either obs-zone (e.g. "GMT") or +/- with 4 digits.
The GMT+/-digits format is not permitted.

Bug 2367124

Backport of I59968274160aeadea70223208b463ee692660056

Change-Id: I3c80eee28d1dcf4c0c211f773a50de0f0839e4ad
This commit is contained in:
Makoto Onuki 2010-04-22 18:03:00 -07:00
parent a8a68b827d
commit a780e12db2
4 changed files with 72 additions and 5 deletions

View File

@ -35,6 +35,7 @@ import android.os.AsyncTask;
import android.security.MessageDigest;
import android.telephony.TelephonyManager;
import android.text.Editable;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.widget.TextView;
@ -50,10 +51,15 @@ import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.regex.Pattern;
public class Utility {
public static final Charset UTF_8 = Charset.forName("UTF-8");
// "GMT" + "+" or "-" + 4 digits
private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE =
Pattern.compile("GMT([-+]\\d{4})$");
public final static String readInputStream(InputStream in, String encoding) throws IOException {
InputStreamReader reader = new InputStreamReader(in, encoding);
StringBuffer sb = new StringBuffer();
@ -96,7 +102,6 @@ public class Utility {
}
return sb.toString();
}
public static String base64Decode(String encoded) {
if (encoded == null) {
return null;
@ -572,4 +577,20 @@ public class Utility {
| ((sha1[offset + 2] & 0xff) << 8)
| ((sha1[offset + 3] & 0xff));
}
/**
* Try to make a date MIME(RFC 2822/5322)-compliant.
*
* It fixes:
* - "Thu, 10 Dec 09 15:08:08 GMT-0700" to "Thu, 10 Dec 09 15:08:08 -0700"
* (4 digit zone value can't be preceded by "GMT")
* We got a report saying eBay sends a date in this format
*/
public static String cleanUpMimeDate(String date) {
if (TextUtils.isEmpty(date)) {
return date;
}
date = DATE_CLEANUP_PATTERN_WRONG_TIMEZONE.matcher(date).replaceFirst("$1");
return date;
}
}

View File

@ -49,9 +49,12 @@ public class DateTimeField extends Field {
public static class Parser implements FieldParser {
private static Log log = LogFactory.getLog(Parser.class);
public Field parse(final String name, final String body, final String raw) {
public Field parse(final String name, String body, final String raw) {
Date date = null;
ParseException parseException = null;
//BEGIN android-changed
body = com.android.email.Utility.cleanUpMimeDate(body);
//END android-changed
try {
date = DateTime.parse(body).getDate();
}

View File

@ -205,4 +205,22 @@ public class UtilityUnitTests extends AndroidTestCase {
Utility.getSmallHashFromSha1(sha1);
}
}
public void testCleanUpMimeDate() {
assertNull(Utility.cleanUpMimeDate(null));
assertEquals("", Utility.cleanUpMimeDate(""));
assertEquals("abc", Utility.cleanUpMimeDate("abc"));
assertEquals("GMT", Utility.cleanUpMimeDate("GMT"));
assertEquals("0000", Utility.cleanUpMimeDate("0000"));
assertEquals("-0000", Utility.cleanUpMimeDate("-0000"));
assertEquals("+1234", Utility.cleanUpMimeDate("GMT+1234"));
assertEquals("-1234", Utility.cleanUpMimeDate("GMT-1234"));
assertEquals("gmt-1234", Utility.cleanUpMimeDate("gmt-1234"));
assertEquals("GMT-123", Utility.cleanUpMimeDate("GMT-123"));
assertEquals("Thu, 10 Dec 09 15:08:08 -0700",
Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 GMT-0700"));
assertEquals("Thu, 10 Dec 09 15:08:08 -0700",
Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 -0700"));
}
}

View File

@ -16,11 +16,13 @@
package com.android.email.mail.internet;
import com.android.email.Email;
import com.android.email.mail.Address;
import com.android.email.mail.Flag;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Message.RecipientType;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.MediumTest;
@ -32,14 +34,12 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import junit.framework.TestCase;
/**
* This is a series of unit tests for the MimeMessage class. These tests must be locally
* complete - no server(s) required.
*/
@SmallTest
public class MimeMessageTest extends TestCase {
public class MimeMessageTest extends AndroidTestCase {
/** up arrow, down arrow, left arrow, right arrow */
private final String SHORT_UNICODE = "\u2191\u2193\u2190\u2192";
@ -61,6 +61,12 @@ public class MimeMessageTest extends TestCase {
private final String LONG_PLAIN_256 =
LONG_PLAIN_64 + LONG_PLAIN_64 + LONG_PLAIN_64 + LONG_PLAIN_64;
@Override
protected void setUp() throws Exception {
super.setUp();
Email.setTempDirectory(getContext());
}
/**
* Confirms that setSentDate() correctly set the "Date" header of a Mime message.
*
@ -520,5 +526,24 @@ public class MimeMessageTest extends TestCase {
assertNull(mm.getMessageId());
}
/**
* Make sure the parser accepts the "eBay style" date format.
*
* Messages from ebay have been seen that they use the wrong date format.
* @see com.android.email.Utility#cleanUpMimeDate
*/
public void testEbayDate() throws MessagingException, IOException {
String entireMessage =
"To:a@b.com\r\n" +
"Date:Thu, 10 Dec 09 15:08:08 GMT-0700" +
"\r\n" +
"\r\n";
MimeMessage mm = null;
mm = new MimeMessage(new ByteArrayInputStream(entireMessage.getBytes("us-ascii")));
Date actual = mm.getSentDate();
Date expected = new Date(Date.UTC(109, 11, 10, 15, 8, 8) + 7 * 60 * 60 * 1000);
assertEquals(expected, actual);
}
// TODO more test for writeTo()
}