Don't allow user to supply content of type message/*
Instead we rewrite the MIME type to application/octet-stream. This is so we don't create broken messages in case the user-supplied content is not a valid message. In the future we could add some validation code and allow the user to attach well-formed messages using the proper MIME type.
This commit is contained in:
parent
1da373ad06
commit
6b28c5b41b
6 changed files with 40 additions and 14 deletions
|
@ -1129,6 +1129,10 @@ public class MimeUtility {
|
|||
return isSameMimeType(mimeType, "message/rfc822");
|
||||
}
|
||||
|
||||
public static boolean isMessageType(String mimeType) {
|
||||
return mimeType != null && mimeType.toLowerCase(Locale.ROOT).startsWith("message/");
|
||||
}
|
||||
|
||||
public static boolean isSameMimeType(String mimeType, String otherMimeType) {
|
||||
return mimeType != null && mimeType.equalsIgnoreCase(otherMimeType);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ public class AttachmentPresenter {
|
|||
|
||||
int loaderId = getNextFreeLoaderId();
|
||||
Attachment attachment = Attachment.createAttachment(
|
||||
attachmentViewInfo.internalUri, loaderId, attachmentViewInfo.mimeType);
|
||||
attachmentViewInfo.internalUri, loaderId, attachmentViewInfo.mimeType, true);
|
||||
attachment = attachment.deriveWithMetadataLoaded(
|
||||
attachmentViewInfo.mimeType, attachmentViewInfo.displayName, attachmentViewInfo.size);
|
||||
|
||||
|
@ -154,12 +154,16 @@ public class AttachmentPresenter {
|
|||
}
|
||||
|
||||
public void addAttachment(Uri uri, String contentType) {
|
||||
addAttachment(uri, contentType, false);
|
||||
}
|
||||
|
||||
private void addAttachment(Uri uri, String contentType, boolean allowMessageType) {
|
||||
if (attachments.containsKey(uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int loaderId = getNextFreeLoaderId();
|
||||
Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType);
|
||||
Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType, allowMessageType);
|
||||
|
||||
addAttachmentAndStartLoader(attachment);
|
||||
}
|
||||
|
@ -188,7 +192,9 @@ public class AttachmentPresenter {
|
|||
}
|
||||
}
|
||||
|
||||
public void processMessageToForwardAsAttachment(MessageViewInfo messageViewInfo) throws IOException, MessagingException {
|
||||
public void processMessageToForwardAsAttachment(MessageViewInfo messageViewInfo) throws IOException,
|
||||
MessagingException {
|
||||
|
||||
if (messageViewInfo.isMessageIncomplete) {
|
||||
attachmentMvpView.showMissingAttachmentsPartialMessageForwardWarning();
|
||||
} else {
|
||||
|
@ -196,7 +202,7 @@ public class AttachmentPresenter {
|
|||
MessageReference messageReference = localMessage.makeMessageReference();
|
||||
Uri rawMessageUri = RawMessageProvider.getRawMessageUri(messageReference);
|
||||
|
||||
addAttachment(rawMessageUri, "message/rfc822");
|
||||
addAttachment(rawMessageUri, "message/rfc822", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,10 @@ public class AttachmentInfoLoader extends AsyncTaskLoader<Attachment> {
|
|||
usableContentType = MimeUtility.getMimeTypeByExtension(name);
|
||||
}
|
||||
|
||||
if (!sourceAttachment.allowMessageType && MimeUtility.isMessageType(usableContentType)) {
|
||||
usableContentType = MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE;
|
||||
}
|
||||
|
||||
if (size <= 0) {
|
||||
String uriString = uri.toString();
|
||||
if (uriString.startsWith("file://")) {
|
||||
|
|
|
@ -34,6 +34,11 @@ public class Attachment implements Parcelable {
|
|||
*/
|
||||
public final String contentType;
|
||||
|
||||
/**
|
||||
* {@code true} if we allow MIME types of {@code message/*}, e.g. {@code message/rfc822}.
|
||||
*/
|
||||
public final boolean allowMessageType;
|
||||
|
||||
/**
|
||||
* The (file)name of the attachment.
|
||||
*
|
||||
|
@ -62,12 +67,13 @@ public class Attachment implements Parcelable {
|
|||
CANCELLED
|
||||
}
|
||||
|
||||
private Attachment(Uri uri, LoadingState state, int loaderId, String contentType, String name, Long size,
|
||||
String filename) {
|
||||
private Attachment(Uri uri, LoadingState state, int loaderId, String contentType, boolean allowMessageType,
|
||||
String name, Long size, String filename) {
|
||||
this.uri = uri;
|
||||
this.state = state;
|
||||
this.loaderId = loaderId;
|
||||
this.contentType = contentType;
|
||||
this.allowMessageType = allowMessageType;
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
this.filename = filename;
|
||||
|
@ -78,6 +84,7 @@ public class Attachment implements Parcelable {
|
|||
state = (LoadingState) in.readSerializable();
|
||||
loaderId = in.readInt();
|
||||
contentType = in.readString();
|
||||
allowMessageType = in.readInt() != 0;
|
||||
name = in.readString();
|
||||
if (in.readInt() != 0) {
|
||||
size = in.readLong();
|
||||
|
@ -87,29 +94,33 @@ public class Attachment implements Parcelable {
|
|||
filename = in.readString();
|
||||
}
|
||||
|
||||
public static Attachment createAttachment(Uri uri, int loaderId, String contentType) {
|
||||
return new Attachment(uri, Attachment.LoadingState.URI_ONLY, loaderId, contentType, null, null, null);
|
||||
public static Attachment createAttachment(Uri uri, int loaderId, String contentType, boolean allowMessageType) {
|
||||
return new Attachment(uri, Attachment.LoadingState.URI_ONLY, loaderId, contentType, allowMessageType, null,
|
||||
null, null);
|
||||
}
|
||||
|
||||
public Attachment deriveWithMetadataLoaded(String usableContentType, String name, long size) {
|
||||
if (state != Attachment.LoadingState.URI_ONLY) {
|
||||
throw new IllegalStateException("deriveWithMetadataLoaded can only be called on a URI_ONLY attachment!");
|
||||
}
|
||||
return new Attachment(uri, Attachment.LoadingState.METADATA, loaderId, usableContentType, name, size, null);
|
||||
return new Attachment(uri, Attachment.LoadingState.METADATA, loaderId, usableContentType, allowMessageType,
|
||||
name, size, null);
|
||||
}
|
||||
|
||||
public Attachment deriveWithLoadCancelled() {
|
||||
if (state != Attachment.LoadingState.METADATA) {
|
||||
throw new IllegalStateException("deriveWitLoadCancelled can only be called on a METADATA attachment!");
|
||||
}
|
||||
return new Attachment(uri, Attachment.LoadingState.CANCELLED, loaderId, contentType, name, size, null);
|
||||
return new Attachment(uri, Attachment.LoadingState.CANCELLED, loaderId, contentType, allowMessageType, name,
|
||||
size, null);
|
||||
}
|
||||
|
||||
public Attachment deriveWithLoadComplete(String absolutePath) {
|
||||
if (state != Attachment.LoadingState.METADATA) {
|
||||
throw new IllegalStateException("deriveWithLoadComplete can only be called on a METADATA attachment!");
|
||||
}
|
||||
return new Attachment(uri, Attachment.LoadingState.COMPLETE, loaderId, contentType, name, size, absolutePath);
|
||||
return new Attachment(uri, Attachment.LoadingState.COMPLETE, loaderId, contentType, allowMessageType, name,
|
||||
size, absolutePath);
|
||||
}
|
||||
|
||||
// === Parcelable ===
|
||||
|
@ -125,6 +136,7 @@ public class Attachment implements Parcelable {
|
|||
dest.writeSerializable(state);
|
||||
dest.writeInt(loaderId);
|
||||
dest.writeString(contentType);
|
||||
dest.writeInt(allowMessageType ? 1 : 0);
|
||||
dest.writeString(name);
|
||||
if (size != null) {
|
||||
dest.writeInt(1);
|
||||
|
|
|
@ -274,7 +274,7 @@ public class MessageBuilderTest {
|
|||
fileOutputStream.write(bytes);
|
||||
fileOutputStream.close();
|
||||
|
||||
return Attachment.createAttachment(null, 0, mimeType)
|
||||
return Attachment.createAttachment(null, 0, mimeType, true)
|
||||
.deriveWithMetadataLoaded(mimeType, filename, bytes.length)
|
||||
.deriveWithLoadComplete(tempFile.getAbsolutePath());
|
||||
}
|
||||
|
|
|
@ -464,7 +464,7 @@ public class PgpMessageBuilderTest {
|
|||
.setEnablePgpInline(true)
|
||||
.build();
|
||||
pgpMessageBuilder.setCryptoStatus(cryptoStatus);
|
||||
pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null)));
|
||||
pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null, true)));
|
||||
|
||||
Callback mockCallback = mock(Callback.class);
|
||||
pgpMessageBuilder.buildAsync(mockCallback);
|
||||
|
@ -481,7 +481,7 @@ public class PgpMessageBuilderTest {
|
|||
.setEnablePgpInline(true)
|
||||
.build();
|
||||
pgpMessageBuilder.setCryptoStatus(cryptoStatus);
|
||||
pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null)));
|
||||
pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null, true)));
|
||||
|
||||
Callback mockCallback = mock(Callback.class);
|
||||
pgpMessageBuilder.buildAsync(mockCallback);
|
||||
|
|
Loading…
Reference in a new issue