clean up TextBody, make it slightly more failfast
Previously, TextBody supported only 8bit or quoted printable encodings, defaulting to quoted printable if the encoding was not equal to "8bit". This behavior is now changed to throw a runtime exception when an unsupported encoding has been selected. The `setEncoding` method also throws if an unsupported encoding is selected.
This commit is contained in:
parent
b0e5912891
commit
08ef3d5ce5
4 changed files with 53 additions and 44 deletions
|
@ -47,7 +47,7 @@ public class MessageExtractor {
|
|||
if ((part != null) && (part.getBody() != null)) {
|
||||
final Body body = part.getBody();
|
||||
if (body instanceof TextBody) {
|
||||
return ((TextBody)body).getText();
|
||||
return ((TextBody)body).getRawText();
|
||||
}
|
||||
final String mimeType = part.getMimeType();
|
||||
if (mimeType != null && MimeUtility.mimeTypeMatches(mimeType, "text/*") ||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package com.fsck.k9.mail.internet;
|
||||
|
||||
import com.fsck.k9.mail.Body;
|
||||
import com.fsck.k9.mail.K9MailLib;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -10,6 +11,9 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.mail.filter.CountingOutputStream;
|
||||
import com.fsck.k9.mail.filter.SignSafeOutputStream;
|
||||
|
||||
|
@ -17,102 +21,107 @@ import org.apache.james.mime4j.codec.QuotedPrintableOutputStream;
|
|||
import org.apache.james.mime4j.util.MimeUtil;
|
||||
|
||||
public class TextBody implements Body, SizeAware {
|
||||
|
||||
/**
|
||||
* Immutable empty byte array
|
||||
*/
|
||||
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
|
||||
private final String mBody;
|
||||
private String mEncoding;
|
||||
private String mCharset = "UTF-8";
|
||||
|
||||
private final String text;
|
||||
private String encoding;
|
||||
private String charset = "UTF-8";
|
||||
// Length of the message composed (as opposed to quoted). I don't like the name of this variable and am open to
|
||||
// suggestions as to what it should otherwise be. -achen 20101207
|
||||
private Integer mComposedMessageLength;
|
||||
@Nullable
|
||||
private Integer composedMessageLength;
|
||||
// Offset from position 0 where the composed message begins.
|
||||
private Integer mComposedMessageOffset;
|
||||
@Nullable
|
||||
private Integer composedMessageOffset;
|
||||
|
||||
public TextBody(String body) {
|
||||
this.mBody = body;
|
||||
this.text = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
if (mBody != null) {
|
||||
byte[] bytes = mBody.getBytes(mCharset);
|
||||
if (MimeUtil.ENC_8BIT.equalsIgnoreCase(mEncoding)) {
|
||||
out.write(bytes);
|
||||
} else {
|
||||
if (text != null) {
|
||||
byte[] bytes = text.getBytes(charset);
|
||||
if (MimeUtil.ENC_QUOTED_PRINTABLE.equalsIgnoreCase(encoding)) {
|
||||
SignSafeOutputStream signSafeOutputStream = new SignSafeOutputStream(out);
|
||||
QuotedPrintableOutputStream signSafeQuotedPrintableOutputStream =
|
||||
new QuotedPrintableOutputStream(signSafeOutputStream, false);
|
||||
signSafeQuotedPrintableOutputStream.write(bytes);
|
||||
signSafeQuotedPrintableOutputStream.flush();
|
||||
signSafeOutputStream.flush();
|
||||
} else if (MimeUtil.ENC_8BIT.equalsIgnoreCase(encoding)) {
|
||||
out.write(bytes);
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot get size for encoding!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text of the body in it's unencoded format.
|
||||
* @return
|
||||
*/
|
||||
public String getText() {
|
||||
return mBody;
|
||||
public String getRawText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputStream that reads this body's text.
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws MessagingException {
|
||||
try {
|
||||
byte[] b;
|
||||
if (mBody != null) {
|
||||
b = mBody.getBytes(mCharset);
|
||||
if (text != null) {
|
||||
b = text.getBytes(charset);
|
||||
} else {
|
||||
b = EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
return new ByteArrayInputStream(b);
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
Log.e(K9MailLib.LOG_TAG, "Unsupported charset: " + charset, uee);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEncoding(String encoding) {
|
||||
mEncoding = encoding;
|
||||
boolean isSupportedEncoding = MimeUtil.ENC_QUOTED_PRINTABLE.equalsIgnoreCase(encoding) ||
|
||||
MimeUtil.ENC_8BIT.equalsIgnoreCase(encoding);
|
||||
if (!isSupportedEncoding) {
|
||||
throw new IllegalArgumentException("Cannot encode to " + encoding);
|
||||
}
|
||||
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public void setCharset(String charset) {
|
||||
mCharset = charset;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getComposedMessageLength() {
|
||||
return mComposedMessageLength;
|
||||
return composedMessageLength;
|
||||
}
|
||||
|
||||
public void setComposedMessageLength(Integer composedMessageLength) {
|
||||
this.mComposedMessageLength = composedMessageLength;
|
||||
public void setComposedMessageLength(@Nullable Integer composedMessageLength) {
|
||||
this.composedMessageLength = composedMessageLength;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getComposedMessageOffset() {
|
||||
return mComposedMessageOffset;
|
||||
return composedMessageOffset;
|
||||
}
|
||||
|
||||
public void setComposedMessageOffset(Integer composedMessageOffset) {
|
||||
this.mComposedMessageOffset = composedMessageOffset;
|
||||
public void setComposedMessageOffset(@Nullable Integer composedMessageOffset) {
|
||||
this.composedMessageOffset = composedMessageOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
try {
|
||||
byte[] bytes = mBody.getBytes(mCharset);
|
||||
byte[] bytes = text.getBytes(charset);
|
||||
|
||||
if (MimeUtil.ENC_8BIT.equalsIgnoreCase(mEncoding)) {
|
||||
if (MimeUtil.ENC_QUOTED_PRINTABLE.equalsIgnoreCase(encoding)) {
|
||||
return getLengthWhenQuotedPrintableEncoded(bytes);
|
||||
} else if (MimeUtil.ENC_8BIT.equalsIgnoreCase(encoding)) {
|
||||
return bytes.length;
|
||||
} else {
|
||||
return getLengthWhenQuotedPrintableEncoded(bytes);
|
||||
throw new IllegalStateException("Cannot get size for encoding!");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Couldn't get body size", e);
|
||||
|
@ -134,6 +143,6 @@ public class TextBody implements Body, SizeAware {
|
|||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return mEncoding;
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class IdentityHeaderBuilder {
|
|||
appendValue(IdentityField.OFFSET, body.getComposedMessageOffset());
|
||||
} else {
|
||||
// If not, calculate it now.
|
||||
appendValue(IdentityField.LENGTH, body.getText().length());
|
||||
appendValue(IdentityField.LENGTH, body.getRawText().length());
|
||||
appendValue(IdentityField.OFFSET, 0);
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class IdentityHeaderBuilder {
|
|||
appendValue(IdentityField.PLAIN_OFFSET, composedMessageOffset);
|
||||
} else {
|
||||
// If not, calculate it now.
|
||||
appendValue(IdentityField.PLAIN_LENGTH, body.getText().length());
|
||||
appendValue(IdentityField.PLAIN_LENGTH, body.getRawText().length());
|
||||
appendValue(IdentityField.PLAIN_OFFSET, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,10 +109,10 @@ public class TextBodyBuilderTest {
|
|||
TextBody textBody = textBodyBuilder.buildTextPlain();
|
||||
|
||||
assertThat(textBody, instanceOf(TextBody.class));
|
||||
assertThat(textBody.getText(), is(expectedText));
|
||||
assertThat(textBody.getRawText(), is(expectedText));
|
||||
assertThat(textBody.getComposedMessageLength(), is(expectedMessageLength));
|
||||
assertThat(textBody.getComposedMessageOffset(), is(expectedMessagePosition));
|
||||
assertThat(textBody.getText().substring(expectedMessagePosition, expectedMessagePosition + expectedMessageLength),
|
||||
assertThat(textBody.getRawText().substring(expectedMessagePosition, expectedMessagePosition + expectedMessageLength),
|
||||
is("message content"));
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ public class TextBodyBuilderTest {
|
|||
TextBody textBody = textBodyBuilder.buildTextHtml();
|
||||
|
||||
assertThat(textBody, instanceOf(TextBody.class));
|
||||
assertThat(textBody.getText(), is(expectedText));
|
||||
assertThat(textBody.getRawText(), is(expectedText));
|
||||
assertThat(textBody.getComposedMessageLength(), is(expectedMessageLength));
|
||||
assertThat(textBody.getComposedMessageOffset(), is(expectedMessagePosition));
|
||||
assertThat(insertableHtmlContent.toDebugString(), is(expectedHtmlContent));
|
||||
|
|
Loading…
Reference in a new issue