Add helper method to decode message bodies

Depending on whether a Body implements RawDataBody (which indicates the class
retains the original encoding) the helper method either strips the transfer
encoding or simply returns the result of Body.getInputStream().

This should restore the original functionality. So saving messages in the
database should work fine again.
This commit is contained in:
cketti 2014-11-26 01:11:26 +01:00
parent f7d3eaa006
commit d1d7b60a09
5 changed files with 70 additions and 8 deletions

View File

@ -15,7 +15,7 @@ import java.io.*;
* and writeTo one time. After writeTo is called, or the InputStream returned from
* getInputStream is closed the file is deleted and the Body should be considered disposed of.
*/
public class BinaryTempFileBody implements Body {
public class BinaryTempFileBody implements RawDataBody {
private static File mTempDirectory;
private File mFile;
@ -26,6 +26,11 @@ public class BinaryTempFileBody implements Body {
mTempDirectory = tempDirectory;
}
@Override
public String getEncoding() {
return mEncoding;
}
public void setEncoding(String encoding) throws MessagingException {
if (mEncoding != null && mEncoding.equalsIgnoreCase(encoding)) {
return;

View File

@ -2,6 +2,7 @@
package com.fsck.k9.mail.internet;
import android.content.Context;
import android.util.Base64;
import android.util.Log;
import com.fsck.k9.K9;
import com.fsck.k9.R;
@ -10,6 +11,7 @@ import com.fsck.k9.mail.*;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.mail.internet.BinaryTempFileBody.BinaryTempFileBodyInputStream;
import com.fsck.k9.view.MessageHeader;
import org.apache.commons.io.IOUtils;
import org.apache.james.mime4j.codec.Base64InputStream;
import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
@ -1026,7 +1028,7 @@ public class MimeUtility {
* determine the charset from HTML message.
*/
if (mimeType.equalsIgnoreCase("text/html") && charset == null) {
InputStream in = part.getBody().getInputStream();
InputStream in = MimeUtility.decodeBody(part.getBody());
try {
byte[] buf = new byte[256];
in.read(buf, 0, buf.length);
@ -1062,7 +1064,7 @@ public class MimeUtility {
* Now we read the part into a buffer for further processing. Because
* the stream is now wrapped we'll remove any transfer encoding at this point.
*/
InputStream in = part.getBody().getInputStream();
InputStream in = MimeUtility.decodeBody(part.getBody());
try {
String text = readToString(in, charset);
@ -1151,6 +1153,49 @@ public class MimeUtility {
return tempBody;
}
/**
* Get decoded contents of a body.
* <p/>
* Right now only some classes retain the original encoding of the body contents. Those classes have to implement
* the {@link RawDataBody} interface in order for this method to decode the data delivered by
* {@link Body#getInputStream()}.
* <p/>
* The ultimate goal is to get to a point where all classes retain the original data and {@code RawDataBody} can be
* merged into {@link Body}.
*/
public static InputStream decodeBody(Body body) throws MessagingException {
InputStream inputStream;
if (body instanceof RawDataBody) {
RawDataBody rawDataBody = (RawDataBody) body;
String encoding = rawDataBody.getEncoding();
final InputStream rawInputStream = rawDataBody.getInputStream();
if (MimeUtil.ENC_7BIT.equalsIgnoreCase(encoding) || MimeUtil.ENC_8BIT.equalsIgnoreCase(encoding)) {
inputStream = rawInputStream;
} else if (MimeUtil.ENC_BASE64.equalsIgnoreCase(encoding)) {
inputStream = new Base64InputStream(rawInputStream, false) {
@Override
public void close() throws IOException {
super.close();
rawInputStream.close();
}
};
} else if (MimeUtil.ENC_QUOTED_PRINTABLE.equalsIgnoreCase(encoding)) {
inputStream = new QuotedPrintableInputStream(rawInputStream) {
@Override
public void close() throws IOException {
super.close();
rawInputStream.close();
}
};
} else {
throw new RuntimeException("Encoding for RawDataBody not supported: " + encoding);
}
} else {
inputStream = body.getInputStream();
}
return inputStream;
}
/**
* Empty base class for the class hierarchy used by

View File

@ -0,0 +1,12 @@
package com.fsck.k9.mail.internet;
import com.fsck.k9.mail.Body;
/**
* See {@link MimeUtility#decodeBody(Body)}
*/
public interface RawDataBody extends Body {
String getEncoding();
}

View File

@ -1561,7 +1561,7 @@ public class LocalFolder extends Folder implements Serializable {
* If the attachment has a body we're expected to save it into the local store
* so we copy the data into a cached attachment file.
*/
InputStream in = attachment.getBody().getInputStream();
InputStream in = MimeUtility.decodeBody(attachment.getBody());
try {
tempAttachmentFile = File.createTempFile("att", null, attachmentDirectory);
FileOutputStream out = new FileOutputStream(tempAttachmentFile);

View File

@ -63,7 +63,7 @@ public class MimeMessageParseTest extends AndroidTestCase {
private static void checkLeafParts(MimeMessage msg, String... expectedParts) throws Exception {
List<String> actual = new ArrayList<String>();
for (Body leaf : getLeafParts(msg.getBody())) {
actual.add(streamToString(leaf.getInputStream()));
actual.add(streamToString(MimeUtility.decodeBody(leaf)));
}
assertEquals(Arrays.asList(expectedParts), actual);
}
@ -83,7 +83,7 @@ public class MimeMessageParseTest extends AndroidTestCase {
checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org");
assertEquals("Testmail", msg.getSubject());
assertEquals("text/plain", msg.getContentType());
assertEquals("this is some test text.", streamToString(msg.getBody().getInputStream()));
assertEquals("this is some test text.", streamToString(MimeUtility.decodeBody(msg.getBody())));
}
public static void testSinglePart8BitRecurse() throws Exception {
@ -101,7 +101,7 @@ public class MimeMessageParseTest extends AndroidTestCase {
checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org");
assertEquals("Testmail", msg.getSubject());
assertEquals("text/plain; encoding=ISO-8859-1", msg.getContentType());
assertEquals("gefährliche Umlaute", streamToString(msg.getBody().getInputStream()));
assertEquals("gefährliche Umlaute", streamToString(MimeUtility.decodeBody(msg.getBody())));
}
public static void testSinglePartBase64NoRecurse() throws Exception {
@ -119,7 +119,7 @@ public class MimeMessageParseTest extends AndroidTestCase {
checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org");
assertEquals("Testmail", msg.getSubject());
assertEquals("text/plain", msg.getContentType());
assertEquals("this is some more test text.", streamToString(msg.getBody().getInputStream()));
assertEquals("this is some more test text.", streamToString(MimeUtility.decodeBody(msg.getBody())));
}
public static void testMultipartSingleLayerNoRecurse() throws Exception {