DO NOT MERGE: Follow-up to the new IMAP parser.

- Replace string literals in ImapStore with constants.
- Simplifies ImapStore.en/decodeFolderName
- Mix cases in the test data to test for case-insensitivity

Backport of I88424357227bcf78528df5e6a1c4ba45d54cc65b

Change-Id: I254fe82324f6ff530e40ca0cff7073f670cf9aa3
This commit is contained in:
Makoto Onuki 2010-05-28 17:34:47 -07:00
parent ff0712cb1e
commit 57ab324a11
3 changed files with 153 additions and 162 deletions

View File

@ -85,8 +85,6 @@ import javax.net.ssl.SSLException;
* TODO Collect ALERT messages and show them to users.
* something else we can try to do a pre-fetch first.
*
* TODO Replace literal strings with ImapConstants.
*
* ftp://ftp.isi.edu/in-notes/rfc2683.txt When a client asks for
* certain information in a FETCH command, the server may return the requested
* information in any order, not necessarily in the order that it was requested.
@ -191,7 +189,8 @@ public class ImapStore extends Store {
// build the LOGIN string once (instead of over-and-over again.)
// apply the quoting here around the built-up password
mLoginPhrase = "LOGIN " + mUsername + " " + Utility.imapQuoted(mPassword);
mLoginPhrase = ImapConstants.LOGIN + " " + mUsername + " "
+ Utility.imapQuoted(mPassword);
}
}
@ -384,9 +383,9 @@ public class ImapStore extends Store {
ImapConnection connection = getConnection();
try {
ArrayList<Folder> folders = new ArrayList<Folder>();
List<ImapResponse> responses =
connection.executeSimpleCommand(String.format("LIST \"\" \"%s*\"",
mPathPrefix == null ? "" : mPathPrefix));
List<ImapResponse> responses = connection.executeSimpleCommand(
String.format(ImapConstants.LIST + " \"\" \"%s*\"",
mPathPrefix == null ? "" : mPathPrefix));
for (ImapResponse response : responses) {
// S: * LIST (\Noselect) "/" ~/Mail/foo
if (response.isDataResponse(0, ImapConstants.LIST)) {
@ -409,7 +408,7 @@ public class ImapStore extends Store {
}
}
}
folders.add(getFolder("INBOX"));
folders.add(getFolder(ImapConstants.INBOX));
return folders.toArray(new Folder[] {});
} catch (IOException ioe) {
connection.close();
@ -463,18 +462,10 @@ public class ImapStore extends Store {
}
/* package */ static String encodeFolderName(String name) {
try {
ByteBuffer bb = MODIFIED_UTF_7_CHARSET.encode(name);
byte[] b = new byte[bb.limit()];
bb.get(b);
return new String(b, "US-ASCII");
} catch (UnsupportedEncodingException uee) {
/*
* The only thing that can throw this is getBytes("US-ASCII") and if US-ASCII doesn't
* exist we're totally screwed.
*/
throw new RuntimeException("Unabel to encode folder name: " + name, uee);
}
ByteBuffer bb = MODIFIED_UTF_7_CHARSET.encode(name);
byte[] b = new byte[bb.limit()];
bb.get(b);
return Utility.fromAscii(b);
}
/* package */ static String decodeFolderName(String name) {
@ -482,17 +473,7 @@ public class ImapStore extends Store {
* Convert the encoded name to US-ASCII, then pass it through the modified UTF-7
* decoder and return the Unicode String.
*/
try {
byte[] encoded = name.getBytes("US-ASCII");
CharBuffer cb = MODIFIED_UTF_7_CHARSET.decode(ByteBuffer.wrap(encoded));
return cb.toString();
} catch (UnsupportedEncodingException uee) {
/*
* The only thing that can throw this is getBytes("US-ASCII") and if US-ASCII doesn't
* exist we're totally screwed.
*/
throw new RuntimeException("Unable to decode folder name: " + name, uee);
}
return MODIFIED_UTF_7_CHARSET.decode(ByteBuffer.wrap(Utility.toAscii(name))).toString();
}
/**
@ -559,7 +540,7 @@ public class ImapStore extends Store {
// 2 OK [READ-WRITE] Select completed.
try {
List<ImapResponse> responses = mConnection.executeSimpleCommand(
String.format("SELECT \"%s\"",
String.format(ImapConstants.SELECT + " \"%s\"",
encodeFolderName(mName)));
/*
* If the command succeeds we expect the folder has been opened read-write
@ -645,7 +626,8 @@ public class ImapStore extends Store {
}
}
try {
connection.executeSimpleCommand(String.format("STATUS \"%s\" (UIDVALIDITY)",
connection.executeSimpleCommand(String.format(
ImapConstants.STATUS + " \"%s\" (" + ImapConstants.UIDVALIDITY + ")",
encodeFolderName(mName)));
mExists = true;
return true;
@ -685,7 +667,7 @@ public class ImapStore extends Store {
}
}
try {
connection.executeSimpleCommand(String.format("CREATE \"%s\"",
connection.executeSimpleCommand(String.format(ImapConstants.CREATE + " \"%s\"",
encodeFolderName(mName)));
return true;
@ -707,9 +689,10 @@ public class ImapStore extends Store {
MessageUpdateCallbacks callbacks) throws MessagingException {
checkOpen();
try {
mConnection.executeSimpleCommand(String.format("UID COPY %s \"%s\"",
joinMessageUids(messages),
encodeFolderName(folder.getName())));
mConnection.executeSimpleCommand(
String.format(ImapConstants.UID_COPY + " %s \"%s\"",
joinMessageUids(messages),
encodeFolderName(folder.getName())));
} catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe);
}
@ -725,9 +708,9 @@ public class ImapStore extends Store {
checkOpen();
try {
int unreadMessageCount = 0;
List<ImapResponse> responses = mConnection.executeSimpleCommand(
String.format("STATUS \"%s\" (UNSEEN)",
encodeFolderName(mName)));
List<ImapResponse> responses = mConnection.executeSimpleCommand(String.format(
ImapConstants.STATUS + " \"%s\" (" + ImapConstants.UNSEEN + ")",
encodeFolderName(mName)));
// S: * STATUS mboxname (MESSAGES 231 UIDNEXT 44292)
for (ImapResponse response : responses) {
if (response.isDataResponse(0, ImapConstants.STATUS)) {
@ -751,7 +734,8 @@ public class ImapStore extends Store {
checkOpen();
List<ImapResponse> responses;
try {
responses = mConnection.executeSimpleCommand("UID SEARCH " + searchCriteria);
responses = mConnection.executeSimpleCommand(
ImapConstants.UID_SEARCH + " " + searchCriteria);
} catch (ImapException e) {
return Utility.EMPTY_STRINGS; // not found;
} catch (IOException ioe) {
@ -784,7 +768,7 @@ public class ImapStore extends Store {
public Message getMessage(String uid) throws MessagingException {
checkOpen();
String[] uids = searchForUids("UID " + uid);
String[] uids = searchForUids(ImapConstants.UID + " " + uid);
for (int i = 0; i < uids.length; i++) {
if (uids[i].equals(uid)) {
return new ImapMessage(uid, this);
@ -898,8 +882,8 @@ public class ImapStore extends Store {
}
try {
String tag = mConnection.sendCommand(String.format("UID FETCH %s (%s)",
joinMessageUids(messages),
String tag = mConnection.sendCommand(String.format(
ImapConstants.UID_FETCH + " %s (%s)", joinMessageUids(messages),
Utility.combine(fetchFields.toArray(new String[fetchFields.size()]), ' ')
), false);
ImapResponse response;
@ -953,7 +937,7 @@ public class ImapStore extends Store {
ImapConstants.BODYSTRUCTURE);
if (!bs.isEmpty()) {
try {
parseBodyStructure(bs, message, "TEXT");
parseBodyStructure(bs, message, ImapConstants.TEXT);
} catch (MessagingException e) {
if (Email.LOGD) {
Log.v(Email.LOG_TAG, "Error handling message", e);
@ -1037,7 +1021,7 @@ public class ImapStore extends Store {
* into it.
*/
MimeBodyPart bp = new MimeBodyPart();
if (id.equals("TEXT")) {
if (id.equals(ImapConstants.TEXT)) {
parseBodyStructure(bs.getListOrEmpty(i), bp, Integer.toString(i + 1));
} else {
@ -1117,7 +1101,7 @@ public class ImapStore extends Store {
// Extension items
final ImapList bodyDisposition;
if (type.is("text") && bs.getElementOrNone(9).isList()) {
if (type.is(ImapConstants.TEXT) && bs.getElementOrNone(9).isList()) {
// If media-type is TEXT, 9th element might be: [body-fld-lines] := number
// So, if it's not a list, use 10th element.
// (Couldn't find evidence in the RFC if it's ALWAYS 10th element.)
@ -1220,9 +1204,9 @@ public class ImapStore extends Store {
for (int i = 0, count = flags.length; i < count; i++) {
Flag flag = flags[i];
if (flag == Flag.SEEN) {
sb.append(" \\Seen");
sb.append(" " + ImapConstants.FLAG_SEEN);
} else if (flag == Flag.FLAGGED) {
sb.append(" \\Flagged");
sb.append(" " + ImapConstants.FLAG_FLAGGED);
}
}
if (sb.length() > 0) {
@ -1231,7 +1215,7 @@ public class ImapStore extends Store {
}
mConnection.sendCommand(
String.format("APPEND \"%s\" (%s) {%d}",
String.format(ImapConstants.APPEND + " \"%s\" (%s) {%d}",
encodeFolderName(mName),
flagList,
out.getCount()), false);
@ -1289,7 +1273,7 @@ public class ImapStore extends Store {
public Message[] expunge() throws MessagingException {
checkOpen();
try {
handleUntaggedResponses(mConnection.executeSimpleCommand("EXPUNGE"));
handleUntaggedResponses(mConnection.executeSimpleCommand(ImapConstants.EXPUNGE));
} catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe);
}
@ -1307,17 +1291,18 @@ public class ImapStore extends Store {
for (int i = 0, count = flags.length; i < count; i++) {
Flag flag = flags[i];
if (flag == Flag.SEEN) {
flagList.append(" \\Seen");
flagList.append(" " + ImapConstants.FLAG_SEEN);
} else if (flag == Flag.DELETED) {
flagList.append(" \\Deleted");
flagList.append(" " + ImapConstants.FLAG_DELETED);
} else if (flag == Flag.FLAGGED) {
flagList.append(" \\Flagged");
flagList.append(" " + ImapConstants.FLAG_FLAGGED);
}
}
allFlags = flagList.substring(1);
}
try {
mConnection.executeSimpleCommand(String.format("UID STORE %s %sFLAGS.SILENT (%s)",
mConnection.executeSimpleCommand(String.format(
ImapConstants.UID_STORE + " %s %s" + ImapConstants.FLAGS_SILENT + " (%s)",
joinMessageUids(messages),
value ? "+" : "-",
allFlags));
@ -1417,9 +1402,9 @@ public class ImapStore extends Store {
String mUserAgent = getImapId(mContext, mUsername, mRootTransport.getHost(),
capabilityResponse.flatten());
if (mUserAgent != null) {
mIdPhrase = "ID (" + mUserAgent + ")";
mIdPhrase = ImapConstants.ID + " (" + mUserAgent + ")";
} else if (DEBUG_FORCE_SEND_ID) {
mIdPhrase = "ID NIL";
mIdPhrase = ImapConstants.ID + " " + ImapConstants.NIL;
}
// else: mIdPhrase = null, no ID will be emitted

View File

@ -28,11 +28,6 @@ public final class ImapConstants {
public static final String FETCH_FIELD_HEADERS =
"BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc message-id)]";
public static final String FLAG_ANSWERED = "\\ANSWERED";
public static final String FLAG_DELETED = "\\DELETED";
public static final String FLAG_FLAGGED = "\\FLAGGED";
public static final String FLAG_NO_SELECT = "\\NOSELECT";
public static final String FLAG_SEEN = "\\SEEN";
public static final String ALERT = "ALERT";
public static final String APPEND = "APPEND";
public static final String BAD = "BAD";
@ -51,7 +46,14 @@ public final class ImapConstants {
public static final String EXISTS = "EXISTS";
public static final String EXPUNGE = "EXPUNGE";
public static final String FETCH = "FETCH";
public static final String FLAG_ANSWERED = "\\ANSWERED";
public static final String FLAG_DELETED = "\\DELETED";
public static final String FLAG_FLAGGED = "\\FLAGGED";
public static final String FLAG_NO_SELECT = "\\NOSELECT";
public static final String FLAG_SEEN = "\\SEEN";
public static final String FLAGS = "FLAGS";
public static final String FLAGS_SILENT = "FLAGS.SILENT";
public static final String ID = "ID";
public static final String INBOX = "INBOX";
public static final String INTERNALDATE = "INTERNALDATE";
public static final String LIST = "LIST";
@ -74,8 +76,13 @@ public final class ImapConstants {
public static final String STATUS = "STATUS";
public static final String STORE = "STORE";
public static final String SUBSCRIBE = "SUBSCRIBE";
public static final String TEXT = "TEXT";
public static final String TRYCREATE = "TRYCREATE";
public static final String UID = "UID";
public static final String UID_COPY = "UID COPY";
public static final String UID_FETCH = "UID FETCH";
public static final String UID_SEARCH = "UID SEARCH";
public static final String UID_STORE = "UID STORE";
public static final String UIDNEXT = "UIDNEXT";
public static final String UIDVALIDITY = "UIDVALIDITY";
public static final String UNSEEN = "UNSEEN";

View File

@ -59,7 +59,6 @@ import java.util.regex.Pattern;
* TODO Check if callback is really called
* TODO test for BAD response in various places?
* TODO test for BYE response in various places?
* TODO test for case-insensitivity (e.g. replace FETCH -> FeTCH)
*/
@SmallTest
public class ImapStoreUnitTests extends AndroidTestCase {
@ -123,7 +122,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
public void testLoginFailure() throws Exception {
MockTransport mockTransport = openAndInjectMockTransport();
expectLogin(mockTransport, new String[] {"* ID NIL", "OK"}, "NO authentication failed");
expectLogin(mockTransport, new String[] {"* iD nIL", "oK"}, "nO authentication failed");
try {
mStore.getConnection().open();
@ -271,7 +270,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
"* ID (\"name\" \"Cyrus\" \"version\" \"1.5\"" +
" \"os\" \"sunos\" \"os-version\" \"5.5\"" +
" \"support-url\" \"mailto:cyrus-bugs+@andrew.cmu.edu\")",
"OK"}, "READ-WRITE");
"oK"}, "rEAD-wRITE");
mFolder.open(OpenMode.READ_WRITE, null);
}
@ -283,8 +282,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// try to open it
setupOpenFolder(mockTransport, new String[] {
"* ID NIL",
"OK [ID] bad-char-%"}, "READ-WRITE");
"* iD nIL",
"oK [iD] bad-char-%"}, "rEAD-wRITE");
mFolder.open(OpenMode.READ_WRITE, null);
}
@ -296,7 +295,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// try to open it
setupOpenFolder(mockTransport, new String[] {
"BAD unknown command bad-char-%"}, "READ-WRITE");
"bAD unknown command bad-char-%"}, "rEAD-wRITE");
mFolder.open(OpenMode.READ_WRITE, null);
}
@ -366,7 +365,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
* @param mockTransport the mock transport we're using
*/
private void setupOpenFolder(MockTransport mockTransport) {
setupOpenFolder(mockTransport, "READ-WRITE");
setupOpenFolder(mockTransport, "rEAD-wRITE");
}
/**
@ -376,7 +375,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
*/
private void setupOpenFolder(MockTransport mockTransport, String readWriteMode) {
setupOpenFolder(mockTransport, new String[] {
"* ID NIL", "OK"}, readWriteMode);
"* iD nIL", "oK"}, readWriteMode);
}
/**
@ -397,32 +396,32 @@ public class ImapStoreUnitTests extends AndroidTestCase {
expectLogin(mockTransport, imapIdResponse);
mockTransport.expect(
getNextTag(false) + " SELECT \"" + FOLDER_ENCODED + "\"", new String[] {
"* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
"* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
"* 0 EXISTS",
"* 0 RECENT",
"* OK [UNSEEN 0]",
"* OK [UIDNEXT 1]",
getNextTag(true) + " OK [" + readWriteMode + "] " +
"* fLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)",
"* oK [pERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)]",
"* 0 eXISTS",
"* 0 rECENT",
"* OK [uNSEEN 0]",
"* OK [uIDNEXT 1]",
getNextTag(true) + " oK [" + readWriteMode + "] " +
FOLDER_ENCODED + " selected. (Success)"});
}
private void expectLogin(MockTransport mockTransport) {
expectLogin(mockTransport, new String[] {"* ID NIL", "OK"});
expectLogin(mockTransport, new String[] {"* iD nIL", "oK"});
}
private void expectLogin(MockTransport mockTransport, String[] imapIdResponse) {
expectLogin(mockTransport, imapIdResponse, "OK user authenticated (Success)");
expectLogin(mockTransport, imapIdResponse, "oK user authenticated (Success)");
}
private void expectLogin(MockTransport mockTransport, String[] imapIdResponse,
String loginResponse) {
// inject boilerplate commands that match our typical login
mockTransport.expect(null, "* OK Imap 2000 Ready To Assist You");
mockTransport.expect(null, "* oK Imap 2000 Ready To Assist You");
mockTransport.expect(getNextTag(false) + " CAPABILITY", new String[] {
"* CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED",
getNextTag(true) + " OK CAPABILITY completed"});
"* cAPABILITY iMAP4rev1 sTARTTLS aUTH=gSSAPI lOGINDISABLED",
getNextTag(true) + " oK CAPABILITY completed"});
String expectedNextTag = getNextTag(false);
// Fix the tag # of the ID response
@ -438,7 +437,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
}
private void expectNoop(MockTransport mockTransport, boolean ok) {
String response = ok ? " OK success" : " NO timeout";
String response = ok ? " oK success" : " nO timeout";
mockTransport.expect(getNextTag(false) + " NOOP",
new String[] {getNextTag(true) + response});
}
@ -461,7 +460,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
*/
public void testReadWrite() throws MessagingException {
MockTransport mock = openAndInjectMockTransport();
setupOpenFolder(mock, "READ-WRITE");
setupOpenFolder(mock, "rEAD-WRITE");
mFolder.open(OpenMode.READ_WRITE, null);
assertEquals(OpenMode.READ_WRITE, mFolder.getMode());
}
@ -472,7 +471,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
*/
public void testReadOnly() throws MessagingException {
MockTransport mock = openAndInjectMockTransport();
setupOpenFolder(mock, "READ-ONLY");
setupOpenFolder(mock, "rEAD-ONLY");
mFolder.open(OpenMode.READ_ONLY, null);
assertEquals(OpenMode.READ_ONLY, mFolder.getMode());
}
@ -486,8 +485,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " STATUS \"" + FOLDER_ENCODED + "\" \\(UNSEEN\\)",
new String[] {
"* STATUS \"" + FOLDER_ENCODED + "\" (UNSEEN 2)",
getNextTag(true) + " OK STATUS completed"});
"* sTATUS \"" + FOLDER_ENCODED + "\" (uNSEEN 2)",
getNextTag(true) + " oK STATUS completed"});
mFolder.open(OpenMode.READ_WRITE, null);
int unreadCount = mFolder.getUnreadMessageCount();
assertEquals("getUnreadMessageCount with quoted string", 2, unreadCount);
@ -502,9 +501,9 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " STATUS \"" + FOLDER_ENCODED + "\" \\(UNSEEN\\)",
new String[] {
"* STATUS {5}",
FOLDER_ENCODED + " (UNSEEN 10)",
getNextTag(true) + " OK STATUS completed"});
"* sTATUS {5}",
FOLDER_ENCODED + " (uNSEEN 10)",
getNextTag(true) + " oK STATUS completed"});
mFolder.open(OpenMode.READ_WRITE, null);
int unreadCount = mFolder.getUnreadMessageCount();
assertEquals("getUnreadMessageCount with literal string", 10, unreadCount);
@ -523,9 +522,9 @@ public class ImapStoreUnitTests extends AndroidTestCase {
" UID FETCH 1 \\(UID FLAGS INTERNALDATE RFC822\\.SIZE BODY\\.PEEK\\[HEADER.FIELDS" +
" \\(date subject from content-type to cc message-id\\)\\]\\)",
new String[] {
"* 9 FETCH (UID 1 RFC822.SIZE 120626 INTERNALDATE \"17-May-2010 22:00:15 +0000\"" +
"FLAGS (\\Seen) BODY[HEADER.FIELDS (date subject from content-type to cc" +
" message-id)]" +
"* 9 fETCH (uID 1 rFC822.sIZE 120626 iNTERNALDATE \"17-may-2010 22:00:15 +0000\"" +
"fLAGS (\\Seen) bODY[hEADER.FIELDS (dAte sUbject fRom cOntent-type tO cC" +
" mEssage-id)]" +
" {279}",
"From: Xxxxxx Yyyyy <userxx@android.com>",
"Date: Mon, 17 May 2010 14:59:52 -0700",
@ -535,7 +534,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
"Content-Type: multipart/mixed; boundary=a00000000000000000000000000b",
"",
")",
getNextTag(true) + " OK SUCCESS"
getNextTag(true) + " oK SUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
@ -561,9 +560,9 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.STRUCTURE);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
new String[] {
"* 9 FETCH (UID 1 BODYSTRUCTURE (\"TEXT\" \"PLAIN\" NIL" +
" NIL NIL NIL 18 3 NIL NIL NIL))",
getNextTag(true) + " OK SUCCESS"
"* 9 fETCH (uID 1 bODYSTRUCTURE (\"tEXT\" \"pLAIN\" nIL" +
" nIL nIL nIL 18 3 nIL nIL nIL))",
getNextTag(true) + " oK sUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
@ -600,18 +599,18 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.STRUCTURE);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
new String[] {
"* 9 FETCH (UID 1 BODYSTRUCTURE ((\"TEXT\" \"PLAIN\" () {20}",
"* 9 fETCH (uID 1 bODYSTRUCTURE ((\"tEXT\" \"pLAIN\" () {20}",
"long content id#@!@#" +
" NIL \"7BIT\" 18 3 NIL NIL NIL)" +
"(\"IMAGE\" \"PNG\" (\"NAME\" {10}",
"device.png) NIL NIL \"BASE64\" {6}",
"117840 NIL (\"ATTACHMENT\" (\"FILENAME\" \"device.png\")) NIL)" +
"(\"TEXT\" \"HTML\" () NIL NIL \"7BIT\" 100 NIL 123 (\"ATTACHMENT\"" +
"(\"FILENAME\" {15}",
"117840 NIL (\"aTTACHMENT\" (\"fILENAME\" \"device.png\")) NIL)" +
"(\"TEXT\" \"HTML\" () NIL NIL \"7BIT\" 100 NIL 123 (\"aTTACHMENT\"" +
"(\"fILENAME\" {15}",
"attachment.html \"SIZE\" 555)) NIL)" +
"((\"TEXT\" \"HTML\" NIL NIL \"BASE64\")(\"XXX\" \"YYY\"))" + // Nested
"\"MIXED\" (\"BOUNDARY\" \"00032556278a7005e40486d159ca\") NIL NIL))",
getNextTag(true) + " OK SUCCESS"
"\"mIXED\" (\"bOUNDARY\" \"00032556278a7005e40486d159ca\") NIL NIL))",
getNextTag(true) + " oK SUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
@ -722,12 +721,12 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.BODY_SANE);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[\\]<0.51200>\\)",
new String[] {
"* 9 FETCH (UID 1 BODY[] {23}",
"* 9 fETCH (uID 1 bODY[] {23}",
"from: a@b.com", // 15 bytes
"", // 2
"test", // 6
")",
getNextTag(true) + " OK SUCCESS"
getNextTag(true) + " oK SUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
assertEquals("a@b.com", message.getHeader("from")[0]);
@ -745,12 +744,12 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.BODY);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[\\]\\)",
new String[] {
"* 9 FETCH (UID 1 BODY[] {23}",
"* 9 fETCH (uID 1 bODY[] {23}",
"from: a@b.com", // 15 bytes
"", // 2
"test", // 6
")",
getNextTag(true) + " OK SUCCESS"
getNextTag(true) + " oK SUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
assertEquals("a@b.com", message.getHeader("from")[0]);
@ -768,12 +767,12 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.STRUCTURE);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)",
new String[] {
"* 9 FETCH (UID 1 BODYSTRUCTURE ((\"TEXT\" \"PLAIN\" (\"CHARSET\" \"ISO-8859-1\")" +
" CID NIL \"7BIT\" 18 3 NIL NIL NIL)" +
"* 9 fETCH (uID 1 bODYSTRUCTURE ((\"tEXT\" \"PLAIN\" (\"cHARSET\" \"iSO-8859-1\")" +
" CID nIL \"7bIT\" 18 3 NIL NIL NIL)" +
"(\"IMAGE\" \"PNG\"" +
" (\"NAME\" \"device.png\") NIL NIL \"BASE64\" 117840 NIL (\"ATTACHMENT\"" +
"(\"FILENAME\" \"device.png\")) NIL)" +
"\"MIXED\"))",
" (\"nAME\" \"device.png\") NIL NIL \"bASE64\" 117840 NIL (\"aTTACHMENT\"" +
"(\"fILENAME\" \"device.png\")) NIL)" +
"\"mIXED\"))",
getNextTag(true) + " OK SUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
@ -793,9 +792,9 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(mimePart1);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[2\\]\\)",
new String[] {
"* 9 FETCH (UID 1 BODY[2] {4}",
"* 9 fETCH (uID 1 bODY[2] {4}",
"YWJj)", // abc in base64
getNextTag(true) + " OK SUCCESS"
getNextTag(true) + " oK SUCCESS"
});
mFolder.fetch(new Message[] { message }, fp, null);
@ -819,8 +818,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.STRUCTURE);
Message message1 = mFolder.createMessage("1");
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODYSTRUCTURE\\)", new String[] {
"* 1 FETCH (UID 1 BODYSTRUCTURE (TEXT PLAIN NIL NIL NIL 7BIT 0 0 NIL NIL NIL))",
getNextTag(true) + " OK SUCCESS"
"* 1 fETCH (uID 1 bODYSTRUCTURE (tEXT pLAIN nIL nIL nIL 7bIT 0 0 nIL nIL nIL))",
getNextTag(true) + " oK SUCCESS"
});
mFolder.fetch(new Message[] { message1 }, fp, null);
@ -832,8 +831,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// The rest of this test is confirming that this is the case.
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID BODY.PEEK\\[TEXT\\]\\)", new String[] {
"* 1 FETCH (UID 1 BODY[TEXT] NIL)",
getNextTag(true) + " OK SUCCESS"
"* 1 fETCH (uID 1 bODY[tEXT] nIL)",
getNextTag(true) + " oK SUCCESS"
});
ArrayList<Part> viewables = new ArrayList<Part>();
ArrayList<Part> attachments = new ArrayList<Part>();
@ -879,9 +878,9 @@ public class ImapStoreUnitTests extends AndroidTestCase {
fp.add(FetchProfile.Item.FLAGS);
mock.expect(getNextTag(false) + " UID FETCH 1 \\(UID FLAGS\\)",
new String[] {
"* 1 FETCH (UID 1 FLAGS (\\Seen))",
"* 2 FETCH (FLAGS (\\Seen))",
getNextTag(true) + " OK SUCCESS"
"* 1 fETCH (uID 1 fLAGS (\\Seen))",
"* 2 fETCH (fLAGS (\\Seen))",
getNextTag(true) + " oK SUCCESS"
});
// Shouldn't crash
@ -905,8 +904,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// OK [APPENDUID 627684530 17] (Success)
mock.expect(getNextTag(false) +
" APPEND \\\"" + FOLDER_ENCODED + "\\\" \\(\\\\Seen\\) \\{166\\}",
new String[] {"+ go ahead"});
" APPEND \\\"" + FOLDER_ENCODED + "\\\" \\(\\\\SEEN\\) \\{166\\}",
new String[] {"+ gO aHead"});
mock.expectLiterally("From: me@test.com", NO_REPLY);
mock.expectLiterally("To: you@test.com", NO_REPLY);
@ -917,7 +916,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expectLiterally("", NO_REPLY);
mock.expectLiterally("VGVzdCBCb2R5", NO_REPLY);
mock.expectLiterally("", new String[] {
"* 7 EXISTS",
"* 7 eXISTS",
getNextTag(true) + " " + response
});
return message;
@ -931,7 +930,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
setupOpenFolder(mock);
mFolder.open(OpenMode.READ_WRITE, null);
ImapMessage message = prepareForAppendTest(mock, "OK [APPENDUID 1234567 13] (Success)");
ImapMessage message = prepareForAppendTest(mock, "oK [aPPENDUID 1234567 13] (Success)");
mFolder.appendMessages(new Message[] {message});
@ -952,8 +951,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expectLiterally(
getNextTag(false) + " UID SEARCH (HEADER MESSAGE-ID <message.id@test.com>)",
new String[] {
"* SEARCH 321",
getNextTag(true) + " OK success"
"* sEARCH 321",
getNextTag(true) + " oK success"
});
mFolder.appendMessages(new Message[] {message});
@ -979,8 +978,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expectLiterally(
getNextTag(false) + " UID SEARCH (HEADER MESSAGE-ID <message.id@test.com>)",
new String[] {
"* SEARCH", // not found
getNextTag(true) + " OK Search completed."
"* sEARCH", // not found
getNextTag(true) + " oK Search completed."
});
mFolder.appendMessages(new Message[] {message});
@ -995,11 +994,11 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(getNextTag(false) + " LIST \"\" \"\\*\"",
new String[] {
"* LIST (\\HasNoChildren) \"/\" \"inbox\"",
"* LIST (\\hasnochildren) \"/\" \"Drafts\"",
"* LIST (\\noselect) \"/\" \"no select\"",
"* LIST (\\HasNoChildren) \"/\" \"&ZeVnLIqe-\"", // Japanese folder name
getNextTag(true) + " OK SUCCESS"
"* lIST (\\HAsNoChildren) \"/\" \"inbox\"",
"* lIST (\\hAsnochildren) \"/\" \"Drafts\"",
"* lIST (\\nOselect) \"/\" \"no select\"",
"* lIST (\\HAsNoChildren) \"/\" \"&ZeVnLIqe-\"", // Japanese folder name
getNextTag(true) + " oK SUCCESS"
});
Folder[] folders = mStore.getPersonalNamespaces();
@ -1041,7 +1040,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// Not exist
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
new String[] {
getNextTag(true) + " NO no such mailbox"
getNextTag(true) + " nO no such mailbox"
});
try {
folder.open(OpenMode.READ_WRITE, null);
@ -1053,8 +1052,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
expectNoop(mock, true); // Need it because we reuse the connection.
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
new String[] {
"* 1 EXISTS",
getNextTag(true) + " OK [READ-WRITE]"
"* 1 eXISTS",
getNextTag(true) + " oK [rEAD-wRITE]"
});
folder.open(OpenMode.READ_WRITE, null);
@ -1070,8 +1069,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
expectNoop(mock, true); // Need it because we reuse the connection.
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
new String[] {
"* 2 EXISTS",
getNextTag(true) + " OK [READ-ONLY]"
"* 2 eXISTS",
getNextTag(true) + " oK [rEAD-oNLY]"
});
folder.open(OpenMode.READ_WRITE, null);
@ -1083,8 +1082,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
expectNoop(mock, true); // Need it because we reuse the connection.
mock.expect(getNextTag(false) + " SELECT \\\"test\\\"",
new String[] {
"* 15 EXISTS",
getNextTag(true) + " OK selected"
"* 15 eXISTS",
getNextTag(true) + " oK selected"
});
folder.open(OpenMode.READ_WRITE, null);
@ -1101,8 +1100,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
Folder folder = mStore.getFolder("\u65E5\u672C\u8A9E");
mock.expect(getNextTag(false) + " STATUS \\\"&ZeVnLIqe-\\\" \\(UIDVALIDITY\\)",
new String[] {
"* STATUS \"&ZeVnLIqe-\" (MESSAGES 10)",
getNextTag(true) + " OK SUCCESS"
"* sTATUS \"&ZeVnLIqe-\" (mESSAGES 10)",
getNextTag(true) + " oK SUCCESS"
});
assertTrue(folder.exists());
@ -1131,7 +1130,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(getNextTag(false) + " CREATE \\\"&ZeVnLIqe-\\\"",
new String[] {
getNextTag(true) + " OK Success"
getNextTag(true) + " oK Success"
});
assertTrue(folder.create(FolderType.HOLDS_MESSAGES));
@ -1142,7 +1141,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// Failure
mock.expect(getNextTag(false) + " CREATE \\\"&ZeVnLIqe-\\\"",
new String[] {
getNextTag(true) + " NO Can't create folder"
getNextTag(true) + " nO Can't create folder"
});
assertFalse(folder.create(FolderType.HOLDS_MESSAGES));
@ -1161,7 +1160,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(getNextTag(false) + " UID COPY 11\\,12 \\\"&ZeVnLIqe-\\\"",
new String[] {
getNextTag(true) + " OK copy completed"
getNextTag(true) + " oK copy completed"
});
mFolder.copyMessages(messages, folderTo, null);
@ -1176,8 +1175,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(getNextTag(false) + " STATUS \\\"" + FOLDER_ENCODED + "\\\" \\(UNSEEN\\)",
new String[] {
"* STATUS \"" + FOLDER_ENCODED + "\" (X 1 UNSEEN 123)",
getNextTag(true) + " OK copy completed"
"* sTATUS \"" + FOLDER_ENCODED + "\" (X 1 uNSEEN 123)",
getNextTag(true) + " oK copy completed"
});
assertEquals(123, mFolder.getUnreadMessageCount());
@ -1190,7 +1189,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(getNextTag(false) + " EXPUNGE",
new String[] {
getNextTag(true) + " OK success"
getNextTag(true) + " oK success"
});
mFolder.expunge();
@ -1210,17 +1209,17 @@ public class ImapStoreUnitTests extends AndroidTestCase {
// Set
mock.expect(
getNextTag(false) + " UID STORE 11\\,12 \\+FLAGS.SILENT \\(\\\\Flagged \\\\Seen\\)",
getNextTag(false) + " UID STORE 11\\,12 \\+FLAGS.SILENT \\(\\\\FLAGGED \\\\SEEN\\)",
new String[] {
getNextTag(true) + " OK success"
getNextTag(true) + " oK success"
});
mFolder.setFlags(messages, new Flag[] {Flag.FLAGGED, Flag.SEEN}, true);
// Clear
mock.expect(
getNextTag(false) + " UID STORE 11\\,12 \\-FLAGS.SILENT \\(\\\\Deleted\\)",
getNextTag(false) + " UID STORE 11\\,12 \\-FLAGS.SILENT \\(\\\\DELETED\\)",
new String[] {
getNextTag(true) + " OK success"
getNextTag(true) + " oK success"
});
mFolder.setFlags(messages, new Flag[] {Flag.DELETED}, false);
@ -1236,8 +1235,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " UID SEARCH UID 123",
new String[] {
"* SEARCH 123",
getNextTag(true) + " OK success"
"* sEARCH 123",
getNextTag(true) + " oK success"
});
assertEquals("123", mFolder.getMessage("123").getUid());
@ -1245,7 +1244,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " UID SEARCH UID 123",
new String[] {
getNextTag(true) + " NO not found"
getNextTag(true) + " nO not found"
});
assertNull(mFolder.getMessage("123"));
}
@ -1260,8 +1259,8 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " UID SEARCH 3:5 NOT DELETED",
new String[] {
"* SEARCH 3 4",
getNextTag(true) + " OK success"
"* sEARCH 3 4",
getNextTag(true) + " oK success"
});
checkMessageUids(new String[] {"3", "4"}, mFolder.getMessages(3, 5, null));
@ -1270,7 +1269,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " UID SEARCH 3:5 NOT DELETED",
new String[] {
getNextTag(true) + " NO not found"
getNextTag(true) + " nO not found"
});
checkMessageUids(new String[] {}, mFolder.getMessages(3, 5, null));
@ -1305,7 +1304,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
mock.expect(
getNextTag(false) + " UID SEARCH 1:\\* NOT DELETED",
new String[] {
"* SEARCH 3 4 5",
"* sEARCH 3 4 5",
getNextTag(true) + " OK success"
});
checkMessageUids(new String[] {"3", "4", "5"},
@ -1361,7 +1360,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
assertEquals(1, mStore.getConnectionPoolForTest().size());
// Get another connection. Should get con1, after verifying the connection.
mock.expect(getNextTag(false) + " NOOP", new String[] {getNextTag(true) + " OK success"});
mock.expect(getNextTag(false) + " NOOP", new String[] {getNextTag(true) + " oK success"});
final ImapConnection con1b = mStore.getConnection();
assertEquals(0, mStore.getConnectionPoolForTest().size()); // No connections left in pool
@ -1373,7 +1372,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
assertEquals(1, mStore.getConnectionPoolForTest().size());
// Try to get connection, but this time, connection gets closed.
mock.expect(getNextTag(false) + " NOOP", new String[] {getNextTag(true) + "* BYE bye"});
mock.expect(getNextTag(false) + " NOOP", new String[] {getNextTag(true) + "* bYE bye"});
final ImapConnection con3 = mStore.getConnection();
assertNotNull(con3);
assertEquals(0, mStore.getConnectionPoolForTest().size()); // No connections left in pool
@ -1389,7 +1388,7 @@ public class ImapStoreUnitTests extends AndroidTestCase {
expectLogin(mock);
mStore.checkSettings();
expectLogin(mock, new String[] {"* ID NIL", "OK"}, "NO authentication failed");
expectLogin(mock, new String[] {"* iD nIL", "oK"}, "nO authentication failed");
try {
mStore.checkSettings();
fail();