Loading k9mail-library/src/main/java/com/fsck/k9/mail/store/imap/ImapList.java +9 −9 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ public class ImapList extends ArrayList<Object> { return getDate(getString(index)); } public Date getKeyedDate(Object key) throws MessagingException { public Date getKeyedDate(String key) throws MessagingException { return getDate(getKeyedString(key)); } Loading @@ -60,7 +60,7 @@ public class ImapList extends ArrayList<Object> { } public Object getKeyedValue(Object key) { public Object getKeyedValue(String key) { for (int i = 0, count = size() - 1; i < count; i++) { if (ImapResponseParser.equalsIgnoreCase(get(i), key)) { return get(i + 1); Loading @@ -69,34 +69,34 @@ public class ImapList extends ArrayList<Object> { return null; } public ImapList getKeyedList(Object key) { public ImapList getKeyedList(String key) { return (ImapList)getKeyedValue(key); } public String getKeyedString(Object key) { public String getKeyedString(String key) { return (String)getKeyedValue(key); } public int getKeyedNumber(Object key) { public int getKeyedNumber(String key) { return Integer.parseInt(getKeyedString(key)); } public boolean containsKey(Object key) { public boolean containsKey(String key) { if (key == null) { return false; } for (int i = 0, count = size() - 1; i < count; i++) { if (ImapResponseParser.equalsIgnoreCase(key, get(i))) { if (ImapResponseParser.equalsIgnoreCase(get(i), key)) { return true; } } return false; } public int getKeyIndex(Object key) { public int getKeyIndex(String key) { for (int i = 0, count = size() - 1; i < count; i++) { if (ImapResponseParser.equalsIgnoreCase(key, get(i))) { if (ImapResponseParser.equalsIgnoreCase(get(i), key)) { return i; } } Loading k9mail-library/src/main/java/com/fsck/k9/mail/store/imap/ImapResponse.java +27 −16 Original line number Diff line number Diff line Loading @@ -8,40 +8,51 @@ package com.fsck.k9.mail.store.imap; * object will contain all of the available tokens at the time the response is received. * </p> */ public class ImapResponse extends ImapList { class ImapResponse extends ImapList { private static final long serialVersionUID = 6886458551615975669L; private ImapResponseCallback mCallback; private final boolean mCommandContinuationRequested; private final String mTag; private ImapResponseCallback callback; private final boolean commandContinuationRequested; private final String tag; public ImapResponse(ImapResponseCallback callback, boolean mCommandContinuationRequested, String mTag) { this.mCallback = callback; this.mCommandContinuationRequested = mCommandContinuationRequested; this.mTag = mTag; private ImapResponse(ImapResponseCallback callback, boolean commandContinuationRequested, String tag) { this.callback = callback; this.commandContinuationRequested = commandContinuationRequested; this.tag = tag; } public static ImapResponse newContinuationRequest(ImapResponseCallback callback) { return new ImapResponse(callback, true, null); } public static ImapResponse newUntaggedResponse(ImapResponseCallback callback) { return new ImapResponse(callback, false, null); } public static ImapResponse newTaggedResponse(ImapResponseCallback callback, String tag) { return new ImapResponse(callback, false, tag); } public boolean isContinuationRequested() { return mCommandContinuationRequested; return commandContinuationRequested; } public String getTag() { return mTag; return tag; } public ImapResponseCallback getCallback() { return mCallback; return callback; } public void setCallback(ImapResponseCallback mCallback) { this.mCallback = mCallback; public void setCallback(ImapResponseCallback callback) { this.callback = callback; } public String getAlertText() { if (size() > 1 && ImapResponseParser.equalsIgnoreCase("[ALERT]", get(1))) { if (size() > 1 && ImapResponseParser.equalsIgnoreCase(get(1), "[ALERT]")) { StringBuilder sb = new StringBuilder(); for (int i = 2, count = size(); i < count; i++) { sb.append(get(i).toString()); Loading @@ -55,6 +66,6 @@ public class ImapResponse extends ImapList { @Override public String toString() { return "#" + (mCommandContinuationRequested ? "+" : mTag) + "# " + super.toString(); return "#" + (commandContinuationRequested ? "+" : tag) + "# " + super.toString(); } } k9mail-library/src/main/java/com/fsck/k9/mail/store/imap/ImapResponseParser.java +86 −72 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ class ImapResponseParser { private ImapResponse response; private Exception exception; public ImapResponseParser(PeekableInputStream in) { this.inputStream = in; } Loading @@ -40,17 +41,13 @@ class ImapResponseParser { */ public ImapResponse readResponse(ImapResponseCallback callback) throws IOException { try { int ch = inputStream.peek(); if (ch == '*') { parseUntaggedResponse(); response = new ImapResponse(callback, false, null); readTokens(response); } else if (ch == '+') { response = new ImapResponse(callback, parseCommandContinuationRequest(), null); parseResponseText(response); int peek = inputStream.peek(); if (peek == '+') { readContinuationRequest(callback); } else if (peek == '*') { readUntaggedResponse(callback); } else { response = new ImapResponse(callback, false, parseTaggedResponse()); readTokens(response); readTaggedResponse(callback); } if (exception != null) { Loading @@ -64,6 +61,29 @@ class ImapResponseParser { } } private void readContinuationRequest(ImapResponseCallback callback) throws IOException { parseCommandContinuationRequest(); response = ImapResponse.newContinuationRequest(callback); skipIfSpace(); String rest = readStringUntilEndOfLine(); response.add(rest); } private void readUntaggedResponse(ImapResponseCallback callback) throws IOException { parseUntaggedResponse(); response = ImapResponse.newUntaggedResponse(callback); readTokens(response); } private void readTaggedResponse(ImapResponseCallback callback) throws IOException { String tag = parseTaggedResponse(); response = ImapResponse.newTaggedResponse(callback, tag); readTokens(response); } List<ImapResponse> readStatusResponse(String tag, String commandToLog, String logId, UntaggedHandler untaggedHandler) throws IOException, MessagingException { Loading Loading @@ -148,6 +168,8 @@ class ImapResponseParser { if (isStatusResponse(firstToken)) { parseResponseText(response); } else if (equalsIgnoreCase(firstToken, "LIST")) { parseListResponse(response); } else { Object token; while ((token = readToken(response)) != null) { Loading Loading @@ -187,12 +209,11 @@ class ImapResponseParser { int next = inputStream.peek(); if (next == '[') { parseSequence(parent); parseList(parent, '[', ']'); skipIfSpace(); } String rest = readStringUntil('\r'); expect('\n'); String rest = readStringUntilEndOfLine(); if (!TextUtils.isEmpty(rest)) { // The rest is free-form text. Loading @@ -200,6 +221,17 @@ class ImapResponseParser { } } private void parseListResponse(ImapResponse response) throws IOException { expect(' '); parseList(response, '(', ')'); expect(' '); String delimiter = parseQuoted(); response.add(delimiter); expect(' '); String name = parseString(); response.add(name); } private void skipIfSpace() throws IOException { if (inputStream.peek() == ' ') { expect(' '); Loading Loading @@ -229,9 +261,9 @@ class ImapResponseParser { int ch = inputStream.peek(); if (ch == '(') { return parseList(parent); return parseList(parent, '(', ')'); } else if (ch == '[') { return parseSequence(parent); return parseList(parent, '[', ']'); } else if (ch == ')') { expect(')'); return ")"; Loading @@ -254,66 +286,53 @@ class ImapResponseParser { } else if (ch == '\t') { expect('\t'); } else { return parseAtom(); return parseBareString(true); } } } private String parseString() throws IOException { int ch = inputStream.peek(); if (ch == '"') { return parseQuoted(); } else if (ch == '{') { return (String) parseLiteral(); } else { return parseBareString(false); } } private boolean parseCommandContinuationRequest() throws IOException { expect('+'); return true; } // * OK [UIDNEXT 175] Predicted next UID private void parseUntaggedResponse() throws IOException { expect('*'); expect(' '); } // 3 OK [READ-WRITE] Select completed. private String parseTaggedResponse() throws IOException { return readStringUntil(' '); } private ImapList parseList(ImapList parent) throws IOException { expect('('); private ImapList parseList(ImapList parent, char start, char end) throws IOException { expect(start); ImapList list = new ImapList(); parent.add(list); Object token; while (true) { token = parseToken(list); if (token == null) { return null; } else if (token.equals(")")) { break; } else if (token instanceof ImapList) { // Do nothing } else { list.add(token); } } return list; } private ImapList parseSequence(ImapList parent) throws IOException { expect('['); ImapList list = new ImapList(); parent.add(list); String endString = String.valueOf(end); Object token; while (true) { token = parseToken(list); if (token == null) { return null; } else if (token.equals("]")) { } else if (token.equals(endString)) { break; } else if (token instanceof ImapList) { // Do nothing } else { } else if (!(token instanceof ImapList)) { list.add(token); } } Loading @@ -321,27 +340,22 @@ class ImapResponseParser { return list; } private String parseAtom() throws IOException { private String parseBareString(boolean allowBrackets) throws IOException { StringBuilder sb = new StringBuilder(); int ch; while (true) { ch = inputStream.peek(); if (ch == -1) { throw new IOException("parseAtom(): end of stream reached"); } else if (ch == '(' || ch == ')' || ch == '{' || ch == ' ' || ch == '[' || ch == ']' || // docs claim that flags are \ atom but atom isn't supposed to // contain // * and some flags contain * // ch == '%' || ch == '*' || // ch == '%' || // TODO probably should not allow \ and should recognize // it as a flag instead // ch == '"' || ch == '\' || ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f) { throw new IOException("parseBareString(): end of stream reached"); } if (ch == '(' || ch == ')' || (allowBrackets && (ch == '[' || ch == ']')) || ch == '{' || ch == ' ' || ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f) { if (sb.length() == 0) { throw new IOException(String.format("parseAtom(): (%04x %c)", ch, ch)); throw new IOException(String.format("parseBareString(): (%04x %c)", ch, ch)); } return sb.toString(); Loading Loading @@ -441,6 +455,13 @@ class ImapResponseParser { throw new IOException("readStringUntil(): end of stream reached"); } private String readStringUntilEndOfLine() throws IOException { String rest = readStringUntil('\r'); expect('\n'); return rest; } private void expect(char expected) throws IOException { int readByte = inputStream.read(); if (readByte != expected) { Loading @@ -457,18 +478,11 @@ class ImapResponseParser { symbol.equalsIgnoreCase("BYE"); } static boolean equalsIgnoreCase(Object o1, Object o2) { if (o1 != null && o2 != null && o1 instanceof String && o2 instanceof String) { String s1 = (String) o1; String s2 = (String) o2; return s1.equalsIgnoreCase(s2); } else if (o1 != null) { return o1.equals(o2); } else if (o2 != null) { return o2.equals(o1); } else { // Both o1 and o2 are null return true; static boolean equalsIgnoreCase(Object token, String symbol) { if (token == null || !(token instanceof String)) { return false; } return symbol.equalsIgnoreCase((String) token); } } k9mail-library/src/test/java/com/fsck/k9/mail/store/imap/ImapResponseParserTest.java +48 −1 Original line number Diff line number Diff line Loading @@ -338,6 +338,53 @@ public class ImapResponseParserTest { parser.readResponse(); } @Test public void testListResponseContainingFolderNameWithBrackets() throws Exception { ImapResponseParser parser = createParser("* LIST (\\HasNoChildren) \".\" [FolderName]\r\n"); ImapResponse response = parser.readResponse(); assertEquals(4, response.size()); assertEquals("LIST", response.get(0)); assertEquals(1, response.getList(1).size()); assertEquals("\\HasNoChildren", response.getList(1).getString(0)); assertEquals(".", response.get(2)); assertEquals("[FolderName]", response.get(3)); } @Test public void testFetchResponse() throws Exception { ImapResponseParser parser = createParser("* 1 FETCH (" + "UID 23 " + "INTERNALDATE \"01-Jul-2015 12:34:56 +0200\" " + "RFC822.SIZE 3456 " + "BODY[HEADER.FIELDS (date subject from)] \"<headers>\" " + "FLAGS (\\Seen))\r\n"); ImapResponse response = parser.readResponse(); assertEquals(3, response.size()); assertEquals("1", response.getString(0)); assertEquals("FETCH", response.getString(1)); assertEquals("UID", response.getList(2).getString(0)); assertEquals(23, response.getList(2).getNumber(1)); assertEquals("INTERNALDATE", response.getList(2).getString(2)); assertEquals("01-Jul-2015 12:34:56 +0200", response.getList(2).getString(3)); assertEquals("RFC822.SIZE", response.getList(2).getString(4)); assertEquals(3456, response.getList(2).getNumber(5)); assertEquals("BODY", response.getList(2).getString(6)); assertEquals(2, response.getList(2).getList(7).size()); assertEquals("HEADER.FIELDS", response.getList(2).getList(7).getString(0)); assertEquals(3, response.getList(2).getList(7).getList(1).size()); assertEquals("date", response.getList(2).getList(7).getList(1).getString(0)); assertEquals("subject", response.getList(2).getList(7).getList(1).getString(1)); assertEquals("from", response.getList(2).getList(7).getList(1).getString(2)); assertEquals("<headers>", response.getList(2).getString(8)); assertEquals("FLAGS", response.getList(2).getString(9)); assertEquals(1, response.getList(2).getList(10).size()); assertEquals("\\Seen", response.getList(2).getList(10).getString(0)); } private ImapResponseParser createParser(String response) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(response.getBytes()); PeekableInputStream peekableInputStream = new PeekableInputStream(byteArrayInputStream); Loading @@ -345,7 +392,7 @@ public class ImapResponseParserTest { } private ImapResponse createResponse(Object... tokens) { ImapResponse response = new ImapResponse(null, false, null); ImapResponse response = ImapResponse.newUntaggedResponse(null); response.addAll(Arrays.asList(tokens)); return response; } Loading Loading
k9mail-library/src/main/java/com/fsck/k9/mail/store/imap/ImapList.java +9 −9 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ public class ImapList extends ArrayList<Object> { return getDate(getString(index)); } public Date getKeyedDate(Object key) throws MessagingException { public Date getKeyedDate(String key) throws MessagingException { return getDate(getKeyedString(key)); } Loading @@ -60,7 +60,7 @@ public class ImapList extends ArrayList<Object> { } public Object getKeyedValue(Object key) { public Object getKeyedValue(String key) { for (int i = 0, count = size() - 1; i < count; i++) { if (ImapResponseParser.equalsIgnoreCase(get(i), key)) { return get(i + 1); Loading @@ -69,34 +69,34 @@ public class ImapList extends ArrayList<Object> { return null; } public ImapList getKeyedList(Object key) { public ImapList getKeyedList(String key) { return (ImapList)getKeyedValue(key); } public String getKeyedString(Object key) { public String getKeyedString(String key) { return (String)getKeyedValue(key); } public int getKeyedNumber(Object key) { public int getKeyedNumber(String key) { return Integer.parseInt(getKeyedString(key)); } public boolean containsKey(Object key) { public boolean containsKey(String key) { if (key == null) { return false; } for (int i = 0, count = size() - 1; i < count; i++) { if (ImapResponseParser.equalsIgnoreCase(key, get(i))) { if (ImapResponseParser.equalsIgnoreCase(get(i), key)) { return true; } } return false; } public int getKeyIndex(Object key) { public int getKeyIndex(String key) { for (int i = 0, count = size() - 1; i < count; i++) { if (ImapResponseParser.equalsIgnoreCase(key, get(i))) { if (ImapResponseParser.equalsIgnoreCase(get(i), key)) { return i; } } Loading
k9mail-library/src/main/java/com/fsck/k9/mail/store/imap/ImapResponse.java +27 −16 Original line number Diff line number Diff line Loading @@ -8,40 +8,51 @@ package com.fsck.k9.mail.store.imap; * object will contain all of the available tokens at the time the response is received. * </p> */ public class ImapResponse extends ImapList { class ImapResponse extends ImapList { private static final long serialVersionUID = 6886458551615975669L; private ImapResponseCallback mCallback; private final boolean mCommandContinuationRequested; private final String mTag; private ImapResponseCallback callback; private final boolean commandContinuationRequested; private final String tag; public ImapResponse(ImapResponseCallback callback, boolean mCommandContinuationRequested, String mTag) { this.mCallback = callback; this.mCommandContinuationRequested = mCommandContinuationRequested; this.mTag = mTag; private ImapResponse(ImapResponseCallback callback, boolean commandContinuationRequested, String tag) { this.callback = callback; this.commandContinuationRequested = commandContinuationRequested; this.tag = tag; } public static ImapResponse newContinuationRequest(ImapResponseCallback callback) { return new ImapResponse(callback, true, null); } public static ImapResponse newUntaggedResponse(ImapResponseCallback callback) { return new ImapResponse(callback, false, null); } public static ImapResponse newTaggedResponse(ImapResponseCallback callback, String tag) { return new ImapResponse(callback, false, tag); } public boolean isContinuationRequested() { return mCommandContinuationRequested; return commandContinuationRequested; } public String getTag() { return mTag; return tag; } public ImapResponseCallback getCallback() { return mCallback; return callback; } public void setCallback(ImapResponseCallback mCallback) { this.mCallback = mCallback; public void setCallback(ImapResponseCallback callback) { this.callback = callback; } public String getAlertText() { if (size() > 1 && ImapResponseParser.equalsIgnoreCase("[ALERT]", get(1))) { if (size() > 1 && ImapResponseParser.equalsIgnoreCase(get(1), "[ALERT]")) { StringBuilder sb = new StringBuilder(); for (int i = 2, count = size(); i < count; i++) { sb.append(get(i).toString()); Loading @@ -55,6 +66,6 @@ public class ImapResponse extends ImapList { @Override public String toString() { return "#" + (mCommandContinuationRequested ? "+" : mTag) + "# " + super.toString(); return "#" + (commandContinuationRequested ? "+" : tag) + "# " + super.toString(); } }
k9mail-library/src/main/java/com/fsck/k9/mail/store/imap/ImapResponseParser.java +86 −72 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ class ImapResponseParser { private ImapResponse response; private Exception exception; public ImapResponseParser(PeekableInputStream in) { this.inputStream = in; } Loading @@ -40,17 +41,13 @@ class ImapResponseParser { */ public ImapResponse readResponse(ImapResponseCallback callback) throws IOException { try { int ch = inputStream.peek(); if (ch == '*') { parseUntaggedResponse(); response = new ImapResponse(callback, false, null); readTokens(response); } else if (ch == '+') { response = new ImapResponse(callback, parseCommandContinuationRequest(), null); parseResponseText(response); int peek = inputStream.peek(); if (peek == '+') { readContinuationRequest(callback); } else if (peek == '*') { readUntaggedResponse(callback); } else { response = new ImapResponse(callback, false, parseTaggedResponse()); readTokens(response); readTaggedResponse(callback); } if (exception != null) { Loading @@ -64,6 +61,29 @@ class ImapResponseParser { } } private void readContinuationRequest(ImapResponseCallback callback) throws IOException { parseCommandContinuationRequest(); response = ImapResponse.newContinuationRequest(callback); skipIfSpace(); String rest = readStringUntilEndOfLine(); response.add(rest); } private void readUntaggedResponse(ImapResponseCallback callback) throws IOException { parseUntaggedResponse(); response = ImapResponse.newUntaggedResponse(callback); readTokens(response); } private void readTaggedResponse(ImapResponseCallback callback) throws IOException { String tag = parseTaggedResponse(); response = ImapResponse.newTaggedResponse(callback, tag); readTokens(response); } List<ImapResponse> readStatusResponse(String tag, String commandToLog, String logId, UntaggedHandler untaggedHandler) throws IOException, MessagingException { Loading Loading @@ -148,6 +168,8 @@ class ImapResponseParser { if (isStatusResponse(firstToken)) { parseResponseText(response); } else if (equalsIgnoreCase(firstToken, "LIST")) { parseListResponse(response); } else { Object token; while ((token = readToken(response)) != null) { Loading Loading @@ -187,12 +209,11 @@ class ImapResponseParser { int next = inputStream.peek(); if (next == '[') { parseSequence(parent); parseList(parent, '[', ']'); skipIfSpace(); } String rest = readStringUntil('\r'); expect('\n'); String rest = readStringUntilEndOfLine(); if (!TextUtils.isEmpty(rest)) { // The rest is free-form text. Loading @@ -200,6 +221,17 @@ class ImapResponseParser { } } private void parseListResponse(ImapResponse response) throws IOException { expect(' '); parseList(response, '(', ')'); expect(' '); String delimiter = parseQuoted(); response.add(delimiter); expect(' '); String name = parseString(); response.add(name); } private void skipIfSpace() throws IOException { if (inputStream.peek() == ' ') { expect(' '); Loading Loading @@ -229,9 +261,9 @@ class ImapResponseParser { int ch = inputStream.peek(); if (ch == '(') { return parseList(parent); return parseList(parent, '(', ')'); } else if (ch == '[') { return parseSequence(parent); return parseList(parent, '[', ']'); } else if (ch == ')') { expect(')'); return ")"; Loading @@ -254,66 +286,53 @@ class ImapResponseParser { } else if (ch == '\t') { expect('\t'); } else { return parseAtom(); return parseBareString(true); } } } private String parseString() throws IOException { int ch = inputStream.peek(); if (ch == '"') { return parseQuoted(); } else if (ch == '{') { return (String) parseLiteral(); } else { return parseBareString(false); } } private boolean parseCommandContinuationRequest() throws IOException { expect('+'); return true; } // * OK [UIDNEXT 175] Predicted next UID private void parseUntaggedResponse() throws IOException { expect('*'); expect(' '); } // 3 OK [READ-WRITE] Select completed. private String parseTaggedResponse() throws IOException { return readStringUntil(' '); } private ImapList parseList(ImapList parent) throws IOException { expect('('); private ImapList parseList(ImapList parent, char start, char end) throws IOException { expect(start); ImapList list = new ImapList(); parent.add(list); Object token; while (true) { token = parseToken(list); if (token == null) { return null; } else if (token.equals(")")) { break; } else if (token instanceof ImapList) { // Do nothing } else { list.add(token); } } return list; } private ImapList parseSequence(ImapList parent) throws IOException { expect('['); ImapList list = new ImapList(); parent.add(list); String endString = String.valueOf(end); Object token; while (true) { token = parseToken(list); if (token == null) { return null; } else if (token.equals("]")) { } else if (token.equals(endString)) { break; } else if (token instanceof ImapList) { // Do nothing } else { } else if (!(token instanceof ImapList)) { list.add(token); } } Loading @@ -321,27 +340,22 @@ class ImapResponseParser { return list; } private String parseAtom() throws IOException { private String parseBareString(boolean allowBrackets) throws IOException { StringBuilder sb = new StringBuilder(); int ch; while (true) { ch = inputStream.peek(); if (ch == -1) { throw new IOException("parseAtom(): end of stream reached"); } else if (ch == '(' || ch == ')' || ch == '{' || ch == ' ' || ch == '[' || ch == ']' || // docs claim that flags are \ atom but atom isn't supposed to // contain // * and some flags contain * // ch == '%' || ch == '*' || // ch == '%' || // TODO probably should not allow \ and should recognize // it as a flag instead // ch == '"' || ch == '\' || ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f) { throw new IOException("parseBareString(): end of stream reached"); } if (ch == '(' || ch == ')' || (allowBrackets && (ch == '[' || ch == ']')) || ch == '{' || ch == ' ' || ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f) { if (sb.length() == 0) { throw new IOException(String.format("parseAtom(): (%04x %c)", ch, ch)); throw new IOException(String.format("parseBareString(): (%04x %c)", ch, ch)); } return sb.toString(); Loading Loading @@ -441,6 +455,13 @@ class ImapResponseParser { throw new IOException("readStringUntil(): end of stream reached"); } private String readStringUntilEndOfLine() throws IOException { String rest = readStringUntil('\r'); expect('\n'); return rest; } private void expect(char expected) throws IOException { int readByte = inputStream.read(); if (readByte != expected) { Loading @@ -457,18 +478,11 @@ class ImapResponseParser { symbol.equalsIgnoreCase("BYE"); } static boolean equalsIgnoreCase(Object o1, Object o2) { if (o1 != null && o2 != null && o1 instanceof String && o2 instanceof String) { String s1 = (String) o1; String s2 = (String) o2; return s1.equalsIgnoreCase(s2); } else if (o1 != null) { return o1.equals(o2); } else if (o2 != null) { return o2.equals(o1); } else { // Both o1 and o2 are null return true; static boolean equalsIgnoreCase(Object token, String symbol) { if (token == null || !(token instanceof String)) { return false; } return symbol.equalsIgnoreCase((String) token); } }
k9mail-library/src/test/java/com/fsck/k9/mail/store/imap/ImapResponseParserTest.java +48 −1 Original line number Diff line number Diff line Loading @@ -338,6 +338,53 @@ public class ImapResponseParserTest { parser.readResponse(); } @Test public void testListResponseContainingFolderNameWithBrackets() throws Exception { ImapResponseParser parser = createParser("* LIST (\\HasNoChildren) \".\" [FolderName]\r\n"); ImapResponse response = parser.readResponse(); assertEquals(4, response.size()); assertEquals("LIST", response.get(0)); assertEquals(1, response.getList(1).size()); assertEquals("\\HasNoChildren", response.getList(1).getString(0)); assertEquals(".", response.get(2)); assertEquals("[FolderName]", response.get(3)); } @Test public void testFetchResponse() throws Exception { ImapResponseParser parser = createParser("* 1 FETCH (" + "UID 23 " + "INTERNALDATE \"01-Jul-2015 12:34:56 +0200\" " + "RFC822.SIZE 3456 " + "BODY[HEADER.FIELDS (date subject from)] \"<headers>\" " + "FLAGS (\\Seen))\r\n"); ImapResponse response = parser.readResponse(); assertEquals(3, response.size()); assertEquals("1", response.getString(0)); assertEquals("FETCH", response.getString(1)); assertEquals("UID", response.getList(2).getString(0)); assertEquals(23, response.getList(2).getNumber(1)); assertEquals("INTERNALDATE", response.getList(2).getString(2)); assertEquals("01-Jul-2015 12:34:56 +0200", response.getList(2).getString(3)); assertEquals("RFC822.SIZE", response.getList(2).getString(4)); assertEquals(3456, response.getList(2).getNumber(5)); assertEquals("BODY", response.getList(2).getString(6)); assertEquals(2, response.getList(2).getList(7).size()); assertEquals("HEADER.FIELDS", response.getList(2).getList(7).getString(0)); assertEquals(3, response.getList(2).getList(7).getList(1).size()); assertEquals("date", response.getList(2).getList(7).getList(1).getString(0)); assertEquals("subject", response.getList(2).getList(7).getList(1).getString(1)); assertEquals("from", response.getList(2).getList(7).getList(1).getString(2)); assertEquals("<headers>", response.getList(2).getString(8)); assertEquals("FLAGS", response.getList(2).getString(9)); assertEquals(1, response.getList(2).getList(10).size()); assertEquals("\\Seen", response.getList(2).getList(10).getString(0)); } private ImapResponseParser createParser(String response) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(response.getBytes()); PeekableInputStream peekableInputStream = new PeekableInputStream(byteArrayInputStream); Loading @@ -345,7 +392,7 @@ public class ImapResponseParserTest { } private ImapResponse createResponse(Object... tokens) { ImapResponse response = new ImapResponse(null, false, null); ImapResponse response = ImapResponse.newUntaggedResponse(null); response.addAll(Arrays.asList(tokens)); return response; } Loading