mirror of
https://github.com/moparisthebest/k-9
synced 2024-12-24 08:38:51 -05:00
Merge branch 'imap_parser'
This commit is contained in:
commit
4f060642ee
@ -916,8 +916,8 @@ public class AccountSettings extends K9PreferenceActivity {
|
||||
}
|
||||
}
|
||||
|
||||
allFolderValues = new String[folders.size()+1];
|
||||
allFolderLabels = new String[folders.size()+1];
|
||||
allFolderValues = new String[folders.size() + 1];
|
||||
allFolderLabels = new String[folders.size() + 1];
|
||||
|
||||
allFolderValues[0] = K9.FOLDER_NONE;
|
||||
allFolderLabels[0] = K9.FOLDER_NONE;
|
||||
|
@ -1081,7 +1081,7 @@ public class MimeUtility {
|
||||
*/
|
||||
if (contentTransferEncoding != null) {
|
||||
contentTransferEncoding =
|
||||
MimeUtility.getHeaderParameter(contentTransferEncoding, null);
|
||||
MimeUtility.getHeaderParameter(contentTransferEncoding, null);
|
||||
if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
|
||||
in = new QuotedPrintableInputStream(in);
|
||||
} else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
|
||||
@ -1107,7 +1107,7 @@ public class MimeUtility {
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public static void collectParts(Part part, ArrayList<Part> viewables,
|
||||
ArrayList<Part> attachments) throws MessagingException {
|
||||
ArrayList<Part> attachments) throws MessagingException {
|
||||
/*
|
||||
* If the part is Multipart but not alternative it's either mixed or
|
||||
* something we don't know about, which means we treat it as mixed
|
||||
@ -1334,10 +1334,10 @@ public class MimeUtility {
|
||||
|
||||
private static String getJisVariantFromAddress(String address) {
|
||||
if (isInDomain(address, "docomo.ne.jp") || isInDomain(address, "dwmail.jp") ||
|
||||
isInDomain(address, "pdx.ne.jp") || isInDomain(address, "willcom.com"))
|
||||
isInDomain(address, "pdx.ne.jp") || isInDomain(address, "willcom.com"))
|
||||
return "docomo";
|
||||
else if (isInDomain(address, "softbank.ne.jp") || isInDomain(address, "vodafone.ne.jp") ||
|
||||
isInDomain(address, "disney.ne.jp") || isInDomain(address, "vertuclub.ne.jp"))
|
||||
isInDomain(address, "disney.ne.jp") || isInDomain(address, "vertuclub.ne.jp"))
|
||||
return "softbank";
|
||||
else if (isInDomain(address, "ezweb.ne.jp") || isInDomain(address, "ido.ne.jp"))
|
||||
return "kddi";
|
||||
@ -1372,14 +1372,14 @@ public class MimeUtility {
|
||||
|
||||
// iso-2022-jp variants are supported by no versions as of Dec 2010.
|
||||
if (charset.length() > 19 && charset.startsWith("x-") &&
|
||||
charset.endsWith("-iso-2022-jp-2007") && !Charset.isSupported(charset)) {
|
||||
charset.endsWith("-iso-2022-jp-2007") && !Charset.isSupported(charset)) {
|
||||
in = new Iso2022JpToShiftJisInputStream(in);
|
||||
charset = "x-" + charset.substring(2, charset.length() - 17) + "-shift_jis-2007";
|
||||
}
|
||||
|
||||
// shift_jis variants are supported by Eclair and later.
|
||||
if (charset.length() > 17 && charset.startsWith("x-") &&
|
||||
charset.endsWith("-shift_jis-2007") && !Charset.isSupported(charset)) {
|
||||
charset.endsWith("-shift_jis-2007") && !Charset.isSupported(charset)) {
|
||||
// If the JIS variant is iPhone, map the Unicode private use area in iPhone to the one in Android after
|
||||
// converting the character set from the standard Shift JIS to Unicode.
|
||||
if (charset.substring(2, charset.length() - 15).equals("iphone"))
|
||||
@ -1400,7 +1400,7 @@ public class MimeUtility {
|
||||
}
|
||||
if (!supported) {
|
||||
Log.e(K9.LOG_TAG, "I don't know how to deal with the charset " + charset +
|
||||
". Falling back to US-ASCII");
|
||||
". Falling back to US-ASCII");
|
||||
charset = "US-ASCII";
|
||||
}
|
||||
/*
|
||||
@ -2401,12 +2401,12 @@ public class MimeUtility {
|
||||
|
||||
public static void setCharset(String charset, Part part) throws MessagingException {
|
||||
part.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
|
||||
part.getMimeType() + ";\n charset=" + getExternalCharset(charset));
|
||||
part.getMimeType() + ";\n charset=" + getExternalCharset(charset));
|
||||
}
|
||||
|
||||
public static String getExternalCharset(String charset) {
|
||||
if (charset.length() > 17 && charset.startsWith("x-") &&
|
||||
charset.endsWith("-shift_jis-2007"))
|
||||
charset.endsWith("-shift_jis-2007"))
|
||||
return "shift_jis";
|
||||
|
||||
return charset;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.fsck.k9.mail.store;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.filter.FixedLengthInputStream;
|
||||
import com.fsck.k9.mail.filter.PeekableInputStream;
|
||||
@ -44,10 +45,8 @@ public class ImapResponseParser {
|
||||
parseUntaggedResponse();
|
||||
readTokens(response);
|
||||
} else if (ch == '+') {
|
||||
response.mCommandContinuationRequested =
|
||||
parseCommandContinuationRequest();
|
||||
//TODO: Add special "resp-text" parsing
|
||||
readTokens(response);
|
||||
response.mCommandContinuationRequested = parseCommandContinuationRequest();
|
||||
parseResponseText(response);
|
||||
} else {
|
||||
response.mTag = parseTaggedResponse();
|
||||
readTokens(response);
|
||||
@ -67,24 +66,72 @@ public class ImapResponseParser {
|
||||
|
||||
private void readTokens(ImapResponse response) throws IOException {
|
||||
response.clear();
|
||||
Object token;
|
||||
while ((token = readToken(response)) != null) {
|
||||
if (!(token instanceof ImapList)) {
|
||||
response.add(token);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Check for responses ("OK", "PREAUTH", "BYE", "NO", "BAD")
|
||||
* that can contain resp-text tokens. If found, hand over to a special
|
||||
* method that parses a resp-text token. There's no need to use
|
||||
* readToken()/parseToken() on that data.
|
||||
*
|
||||
* See RFC 3501, Section 9 Formal Syntax (resp-text)
|
||||
*/
|
||||
String firstToken = (String) readToken(response);
|
||||
response.add(firstToken);
|
||||
|
||||
if (isStatusResponse(firstToken)) {
|
||||
parseResponseText(response);
|
||||
} else {
|
||||
Object token;
|
||||
while ((token = readToken(response)) != null) {
|
||||
if (!(token instanceof ImapList)) {
|
||||
response.add(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
response.mCompleted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse {@code resp-text} tokens
|
||||
*
|
||||
* <p>
|
||||
* Responses "OK", "PREAUTH", "BYE", "NO", "BAD", and continuation request responses can
|
||||
* contain {@code resp-text} tokens. We parse the {@code resp-text-code} part as tokens and
|
||||
* read the rest as sequence of characters to avoid the parser interpreting things like
|
||||
* "{123}" as start of a literal.
|
||||
* </p>
|
||||
* <p>Example:</p>
|
||||
* <p>
|
||||
* {@code * OK [UIDVALIDITY 3857529045] UIDs valid}
|
||||
* </p>
|
||||
* <p>
|
||||
* See RFC 3501, Section 9 Formal Syntax (resp-text)
|
||||
* </p>
|
||||
*
|
||||
* @param parent
|
||||
* The {@link ImapResponse} instance that holds the parsed tokens of the response.
|
||||
*
|
||||
* @throws IOException
|
||||
* If there's a network error.
|
||||
*
|
||||
* @see #isStatusResponse(String)
|
||||
*/
|
||||
private void parseResponseText(ImapResponse parent) throws IOException {
|
||||
skipIfSpace();
|
||||
|
||||
int next = mIn.peek();
|
||||
if (next == '[') {
|
||||
parseSequence(parent);
|
||||
skipIfSpace();
|
||||
}
|
||||
|
||||
String rest = readStringUntil('\r');
|
||||
expect('\n');
|
||||
|
||||
if (!TextUtils.isEmpty(rest)) {
|
||||
// The rest is free-form text.
|
||||
parent.add(rest);
|
||||
}
|
||||
}
|
||||
|
||||
private void skipIfSpace() throws IOException {
|
||||
if (mIn.peek() == ' ') {
|
||||
expect(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next token of the response. The token can be one of: String -
|
||||
* for NIL, QUOTED, NUMBER, ATOM. Object - for LITERAL.
|
||||
@ -480,6 +527,14 @@ public class ImapResponseParser {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStatusResponse(String symbol) {
|
||||
return symbol.equalsIgnoreCase("OK") ||
|
||||
symbol.equalsIgnoreCase("NO") ||
|
||||
symbol.equalsIgnoreCase("BAD") ||
|
||||
symbol.equalsIgnoreCase("PREAUTH") ||
|
||||
symbol.equalsIgnoreCase("BYE");
|
||||
}
|
||||
|
||||
public static boolean equalsIgnoreCase(Object o1, Object o2) {
|
||||
if (o1 != null && o2 != null && o1 instanceof String && o2 instanceof String) {
|
||||
String s1 = (String)o1;
|
||||
|
67
tests/src/com/fsck/k9/mail/store/ImapResponseParserTest.java
Normal file
67
tests/src/com/fsck/k9/mail/store/ImapResponseParserTest.java
Normal file
@ -0,0 +1,67 @@
|
||||
package com.fsck.k9.mail.store;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import com.fsck.k9.mail.filter.PeekableInputStream;
|
||||
import com.fsck.k9.mail.store.ImapResponseParser.ImapList;
|
||||
import com.fsck.k9.mail.store.ImapResponseParser.ImapResponse;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class ImapResponseParserTest extends TestCase {
|
||||
|
||||
public void testSimpleOkResponse() throws IOException {
|
||||
ImapResponseParser parser = createParser("* OK\r\n");
|
||||
ImapResponse response = parser.readResponse();
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(1, response.size());
|
||||
assertEquals("OK", response.get(0));
|
||||
}
|
||||
|
||||
public void testOkResponseWithText() throws IOException {
|
||||
ImapResponseParser parser = createParser("* OK Some text here\r\n");
|
||||
ImapResponse response = parser.readResponse();
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(2, response.size());
|
||||
assertEquals("OK", response.get(0));
|
||||
assertEquals("Some text here", response.get(1));
|
||||
}
|
||||
|
||||
public void testOkResponseWithRespTextCode() throws IOException {
|
||||
ImapResponseParser parser = createParser("* OK [UIDVALIDITY 3857529045]\r\n");
|
||||
ImapResponse response = parser.readResponse();
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(2, response.size());
|
||||
assertEquals("OK", response.get(0));
|
||||
assertTrue(response.get(1) instanceof ImapList);
|
||||
|
||||
ImapList respTextCode = (ImapList) response.get(1);
|
||||
assertEquals(2, respTextCode.size());
|
||||
assertEquals("UIDVALIDITY", respTextCode.get(0));
|
||||
assertEquals("3857529045", respTextCode.get(1));
|
||||
}
|
||||
|
||||
public void testOkResponseWithRespTextCodeAndText() throws IOException {
|
||||
ImapResponseParser parser = createParser("* OK [token1 token2] {x} test [...]\r\n");
|
||||
ImapResponse response = parser.readResponse();
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(3, response.size());
|
||||
assertEquals("OK", response.get(0));
|
||||
assertTrue(response.get(1) instanceof ImapList);
|
||||
assertEquals("{x} test [...]", response.get(2));
|
||||
|
||||
ImapList respTextCode = (ImapList) response.get(1);
|
||||
assertEquals(2, respTextCode.size());
|
||||
assertEquals("token1", respTextCode.get(0));
|
||||
assertEquals("token2", respTextCode.get(1));
|
||||
}
|
||||
|
||||
private ImapResponseParser createParser(String response) {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(response.getBytes());
|
||||
PeekableInputStream pin = new PeekableInputStream(in);
|
||||
return new ImapResponseParser(pin);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user