mirror of
https://github.com/moparisthebest/k-9
synced 2025-01-12 06:08:25 -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];
|
allFolderValues = new String[folders.size() + 1];
|
||||||
allFolderLabels = new String[folders.size()+1];
|
allFolderLabels = new String[folders.size() + 1];
|
||||||
|
|
||||||
allFolderValues[0] = K9.FOLDER_NONE;
|
allFolderValues[0] = K9.FOLDER_NONE;
|
||||||
allFolderLabels[0] = K9.FOLDER_NONE;
|
allFolderLabels[0] = K9.FOLDER_NONE;
|
||||||
|
@ -1081,7 +1081,7 @@ public class MimeUtility {
|
|||||||
*/
|
*/
|
||||||
if (contentTransferEncoding != null) {
|
if (contentTransferEncoding != null) {
|
||||||
contentTransferEncoding =
|
contentTransferEncoding =
|
||||||
MimeUtility.getHeaderParameter(contentTransferEncoding, null);
|
MimeUtility.getHeaderParameter(contentTransferEncoding, null);
|
||||||
if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
|
if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
|
||||||
in = new QuotedPrintableInputStream(in);
|
in = new QuotedPrintableInputStream(in);
|
||||||
} else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
|
} else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
|
||||||
@ -1107,7 +1107,7 @@ public class MimeUtility {
|
|||||||
* @throws MessagingException
|
* @throws MessagingException
|
||||||
*/
|
*/
|
||||||
public static void collectParts(Part part, ArrayList<Part> viewables,
|
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
|
* 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
|
* 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) {
|
private static String getJisVariantFromAddress(String address) {
|
||||||
if (isInDomain(address, "docomo.ne.jp") || isInDomain(address, "dwmail.jp") ||
|
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";
|
return "docomo";
|
||||||
else if (isInDomain(address, "softbank.ne.jp") || isInDomain(address, "vodafone.ne.jp") ||
|
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";
|
return "softbank";
|
||||||
else if (isInDomain(address, "ezweb.ne.jp") || isInDomain(address, "ido.ne.jp"))
|
else if (isInDomain(address, "ezweb.ne.jp") || isInDomain(address, "ido.ne.jp"))
|
||||||
return "kddi";
|
return "kddi";
|
||||||
@ -1372,14 +1372,14 @@ public class MimeUtility {
|
|||||||
|
|
||||||
// iso-2022-jp variants are supported by no versions as of Dec 2010.
|
// iso-2022-jp variants are supported by no versions as of Dec 2010.
|
||||||
if (charset.length() > 19 && charset.startsWith("x-") &&
|
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);
|
in = new Iso2022JpToShiftJisInputStream(in);
|
||||||
charset = "x-" + charset.substring(2, charset.length() - 17) + "-shift_jis-2007";
|
charset = "x-" + charset.substring(2, charset.length() - 17) + "-shift_jis-2007";
|
||||||
}
|
}
|
||||||
|
|
||||||
// shift_jis variants are supported by Eclair and later.
|
// shift_jis variants are supported by Eclair and later.
|
||||||
if (charset.length() > 17 && charset.startsWith("x-") &&
|
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
|
// 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.
|
// converting the character set from the standard Shift JIS to Unicode.
|
||||||
if (charset.substring(2, charset.length() - 15).equals("iphone"))
|
if (charset.substring(2, charset.length() - 15).equals("iphone"))
|
||||||
@ -1400,7 +1400,7 @@ public class MimeUtility {
|
|||||||
}
|
}
|
||||||
if (!supported) {
|
if (!supported) {
|
||||||
Log.e(K9.LOG_TAG, "I don't know how to deal with the charset " + charset +
|
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";
|
charset = "US-ASCII";
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -2401,12 +2401,12 @@ public class MimeUtility {
|
|||||||
|
|
||||||
public static void setCharset(String charset, Part part) throws MessagingException {
|
public static void setCharset(String charset, Part part) throws MessagingException {
|
||||||
part.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
|
part.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
|
||||||
part.getMimeType() + ";\n charset=" + getExternalCharset(charset));
|
part.getMimeType() + ";\n charset=" + getExternalCharset(charset));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getExternalCharset(String charset) {
|
public static String getExternalCharset(String charset) {
|
||||||
if (charset.length() > 17 && charset.startsWith("x-") &&
|
if (charset.length() > 17 && charset.startsWith("x-") &&
|
||||||
charset.endsWith("-shift_jis-2007"))
|
charset.endsWith("-shift_jis-2007"))
|
||||||
return "shift_jis";
|
return "shift_jis";
|
||||||
|
|
||||||
return charset;
|
return charset;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.fsck.k9.mail.store;
|
package com.fsck.k9.mail.store;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
import com.fsck.k9.mail.MessagingException;
|
import com.fsck.k9.mail.MessagingException;
|
||||||
import com.fsck.k9.mail.filter.FixedLengthInputStream;
|
import com.fsck.k9.mail.filter.FixedLengthInputStream;
|
||||||
import com.fsck.k9.mail.filter.PeekableInputStream;
|
import com.fsck.k9.mail.filter.PeekableInputStream;
|
||||||
@ -44,10 +45,8 @@ public class ImapResponseParser {
|
|||||||
parseUntaggedResponse();
|
parseUntaggedResponse();
|
||||||
readTokens(response);
|
readTokens(response);
|
||||||
} else if (ch == '+') {
|
} else if (ch == '+') {
|
||||||
response.mCommandContinuationRequested =
|
response.mCommandContinuationRequested = parseCommandContinuationRequest();
|
||||||
parseCommandContinuationRequest();
|
parseResponseText(response);
|
||||||
//TODO: Add special "resp-text" parsing
|
|
||||||
readTokens(response);
|
|
||||||
} else {
|
} else {
|
||||||
response.mTag = parseTaggedResponse();
|
response.mTag = parseTaggedResponse();
|
||||||
readTokens(response);
|
readTokens(response);
|
||||||
@ -67,24 +66,72 @@ public class ImapResponseParser {
|
|||||||
|
|
||||||
private void readTokens(ImapResponse response) throws IOException {
|
private void readTokens(ImapResponse response) throws IOException {
|
||||||
response.clear();
|
response.clear();
|
||||||
Object token;
|
|
||||||
while ((token = readToken(response)) != null) {
|
|
||||||
if (!(token instanceof ImapList)) {
|
|
||||||
response.add(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
String firstToken = (String) readToken(response);
|
||||||
* TODO: Check for responses ("OK", "PREAUTH", "BYE", "NO", "BAD")
|
response.add(firstToken);
|
||||||
* 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
|
if (isStatusResponse(firstToken)) {
|
||||||
* readToken()/parseToken() on that data.
|
parseResponseText(response);
|
||||||
*
|
} else {
|
||||||
* See RFC 3501, Section 9 Formal Syntax (resp-text)
|
Object token;
|
||||||
*/
|
while ((token = readToken(response)) != null) {
|
||||||
|
if (!(token instanceof ImapList)) {
|
||||||
|
response.add(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
response.mCompleted = true;
|
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 -
|
* Reads the next token of the response. The token can be one of: String -
|
||||||
* for NIL, QUOTED, NUMBER, ATOM. Object - for LITERAL.
|
* 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) {
|
public static boolean equalsIgnoreCase(Object o1, Object o2) {
|
||||||
if (o1 != null && o2 != null && o1 instanceof String && o2 instanceof String) {
|
if (o1 != null && o2 != null && o1 instanceof String && o2 instanceof String) {
|
||||||
String s1 = (String)o1;
|
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