Use MimeParameterEncoder to encode attachment names

This commit is contained in:
cketti 2018-04-29 03:50:36 +02:00
parent 19bfa97a9b
commit ac9fc251f3
3 changed files with 46 additions and 60 deletions

View file

@ -0,0 +1,20 @@
package com.fsck.k9.mail.internet
object Headers {
@JvmStatic
fun contentType(mimeType: String, name: String): String {
return MimeParameterEncoder.encode(mimeType, mapOf("name" to name))
}
@JvmStatic
@JvmOverloads
fun contentDisposition(disposition: String, fileName: String, size: Long? = null): String {
val parameters = if (size == null) {
mapOf("filename" to fileName)
} else {
mapOf("filename" to fileName, "size" to size.toString())
}
return MimeParameterEncoder.encode(disposition, parameters)
}
}

View file

@ -3,13 +3,14 @@ package com.fsck.k9.message;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import com.fsck.k9.mail.internet.Headers;
import timber.log.Timber;
import com.fsck.k9.Account.QuoteStyle;
@ -34,7 +35,6 @@ import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.internet.TextBody;
import com.fsck.k9.mailstore.TempFileBody;
import com.fsck.k9.message.quote.InsertableHtmlContent;
import org.apache.james.mime4j.codec.EncoderUtil;
import org.apache.james.mime4j.util.MimeUtil;
@ -233,51 +233,18 @@ public abstract class MessageBuilder {
}
}
/*
* Content-Type is defined in RFC 2045
*
* Example:
*
* Content-Type: text/plain; charset=us-ascii (Plain text)
*
* TODO: RFC 2231/2184 long parameter encoding
* Example:
*
* Content-Type: application/x-stuff
* title*1*=us-ascii'en'This%20is%20even%20more%20
* title*2*=%2A%2A%2Afun%2A%2A%2A%20
* title*3="isn't it!"
*/
private void addContentType(MimeBodyPart bp, String contentType, String name) throws MessagingException {
/*
* Correctly encode the filename here. Otherwise the whole
* header value (all parameters at once) will be encoded by
* MimeHeader.writeTo().
*/
bp.addHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\r\n name=\"%s\"",
contentType,
EncoderUtil.encodeIfNecessary(name,
EncoderUtil.Usage.WORD_ENTITY, 7)));
private void addContentType(MimeBodyPart bodyPart, String contentType, String name) throws MessagingException {
String value = Headers.contentType(contentType, name);
bodyPart.addHeader(MimeHeader.HEADER_CONTENT_TYPE, value);
if (!MimeUtil.isMessage(contentType)) {
bp.setEncoding(MimeUtility.getEncodingforType(contentType));
bodyPart.setEncoding(MimeUtility.getEncodingforType(contentType));
}
}
/*
* TODO: RFC 2231/2184 long parameter encoding
*
* From RFC 2183 (The Content-Disposition Header Field):
* "Parameter values longer than 78 characters, or which
* contain non-ASCII characters, MUST be encoded as specified
* in [RFC 2184]."
*
*/
private void addContentDisposition(MimeBodyPart bp, String name, Long size) {
bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, String.format(Locale.US,
"attachment;\r\n filename=\"%s\";\r\n size=%d",
EncoderUtil.encodeIfNecessary(name, EncoderUtil.Usage.WORD_ENTITY, 7),
size));
private void addContentDisposition(MimeBodyPart bodyPart, String fileName, Long size) {
String value = Headers.contentDisposition("attachment", fileName, size);
bodyPart.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, value);
}
/**

View file

@ -29,7 +29,6 @@ import com.fsck.k9.mail.internet.MimeMultipart;
import com.fsck.k9.message.MessageBuilder.Callback;
import com.fsck.k9.message.quote.InsertableHtmlContent;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.robolectric.Robolectric;
@ -99,24 +98,22 @@ public class MessageBuilderTest extends RobolectricTest {
"text =E2=98=AD\r\n" +
"--" + BOUNDARY_1 + "\r\n" +
"Content-Type: text/plain;\r\n" +
" name=\"attach.txt\"\r\n" +
" name=attach.txt\r\n" +
"Content-Transfer-Encoding: base64\r\n" +
"Content-Disposition: attachment;\r\n" +
" filename=\"attach.txt\";\r\n" +
" filename=attach.txt;\r\n" +
" size=23\r\n" +
"\r\n" +
"dGV4dCBkYXRhIGluIGF0dGFjaG1lbnQ=\r\n" +
"\r\n" +
"--" + BOUNDARY_1 + "--\r\n";
private static final String MESSAGE_CONTENT_WITH_LONG_CONTENT_TYPE =
private static final String MESSAGE_CONTENT_WITH_LONG_FILE_NAME =
"Content-Type: multipart/mixed; boundary=\"" + BOUNDARY_1 + "\"\r\n" +
"Content-Transfer-Encoding: 7bit\r\n" +
"\r\n" +
"--" + BOUNDARY_1 + "\r\n" +
"Content-Type: text/plain;\r\n" +
" title*1*=1234567891123456789212345678931234567894123456789\r\n" +
" title*2*=5123456789612345678971234567898123456789091234567890;\r\n" +
" charset=utf-8\r\n" +
"Content-Transfer-Encoding: quoted-printable\r\n" +
"\r\n" +
@ -124,10 +121,12 @@ public class MessageBuilderTest extends RobolectricTest {
"text =E2=98=AD\r\n" +
"--" + BOUNDARY_1 + "\r\n" +
"Content-Type: text/plain;\r\n" +
" name=\"attach.txt\"\r\n" +
" name*0*=UTF-8''~~~~~~~~~1~~~~~~~~~2~~~~~~~~~3~~~~~~~~~4~~~~~~~~~5~~~~~~~~~6~;\r\n" +
" name*1*=~~~~~~~~7.txt\r\n" +
"Content-Transfer-Encoding: base64\r\n" +
"Content-Disposition: attachment;\r\n" +
" filename=\"attach.txt\";\r\n" +
" filename*0*=UTF-8''~~~~~~~~~1~~~~~~~~~2~~~~~~~~~3~~~~~~~~~4~~~~~~~~~5~~~~~~~;\r\n" +
" filename*1*=~~6~~~~~~~~~7.txt;\r\n" +
" size=23\r\n" +
"\r\n" +
"dGV4dCBkYXRhIGluIGF0dGFjaG1lbnQ=\r\n" +
@ -148,10 +147,10 @@ public class MessageBuilderTest extends RobolectricTest {
"text =E2=98=AD\r\n" +
"--" + BOUNDARY_1 + "\r\n" +
"Content-Type: text/plain;\r\n" +
" name=\"=?UTF-8?B?44OG44K544OI5paH5pu4LnR4dA==?=\"\r\n" +
" name*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88%E6%96%87%E6%9B%B8.txt\r\n" +
"Content-Transfer-Encoding: base64\r\n" +
"Content-Disposition: attachment;\r\n" +
" filename=\"=?UTF-8?B?44OG44K544OI5paH5pu4LnR4dA==?=\";\r\n" +
" filename*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88%E6%96%87%E6%9B%B8.txt;\r\n" +
" size=23\r\n" +
"\r\n" +
"dGV4dCBkYXRhIGluIGF0dGFjaG1lbnQ=\r\n" +
@ -171,9 +170,9 @@ public class MessageBuilderTest extends RobolectricTest {
"text =E2=98=AD\r\n" +
"--" + BOUNDARY_1 + "\r\n" +
"Content-Type: message/rfc822;\r\n" +
" name=\"attach.txt\"\r\n" +
" name=attach.txt\r\n" +
"Content-Disposition: attachment;\r\n" +
" filename=\"attach.txt\";\r\n" +
" filename=attach.txt;\r\n" +
" size=23\r\n" +
"\r\n" +
"text data in attachment" +
@ -228,19 +227,19 @@ public class MessageBuilderTest extends RobolectricTest {
assertEquals(MESSAGE_HEADERS + MESSAGE_CONTENT_WITH_ATTACH, getMessageContents(message));
}
@Ignore("RFC2231/2184 not implemented") @Test
public void build_withAttachment_longContentType_shouldSucceed() throws Exception {
@Test
public void build_withAttachment_longFileName() throws Exception {
MessageBuilder messageBuilder = createSimpleMessageBuilder();
Attachment attachment = createAttachmentWithContent(
"text/plain;title=1234567891123456789212345678931234567894123456789" +
"5123456789612345678971234567898123456789091234567890",
"attach.txt", TEST_ATTACHMENT_TEXT);
"text/plain",
"~~~~~~~~~1~~~~~~~~~2~~~~~~~~~3~~~~~~~~~4~~~~~~~~~5~~~~~~~~~6~~~~~~~~~7.txt",
TEST_ATTACHMENT_TEXT);
messageBuilder.setAttachments(Collections.singletonList(attachment));
messageBuilder.buildAsync(callback);
MimeMessage message = getMessageFromCallback();
assertEquals(MESSAGE_HEADERS + MESSAGE_CONTENT_WITH_LONG_CONTENT_TYPE,
assertEquals(MESSAGE_HEADERS + MESSAGE_CONTENT_WITH_LONG_FILE_NAME,
getMessageContents(message));
}