1
0
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:
cketti 2011-11-16 04:52:05 +01:00
commit 4f060642ee
4 changed files with 150 additions and 28 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View 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);
}
}