diff --git a/k9mail/src/main/java/com/fsck/k9/crypto/MessageDecryptVerifier.java b/k9mail/src/main/java/com/fsck/k9/crypto/MessageDecryptVerifier.java index bd11d070e..b73f58059 100644 --- a/k9mail/src/main/java/com/fsck/k9/crypto/MessageDecryptVerifier.java +++ b/k9mail/src/main/java/com/fsck/k9/crypto/MessageDecryptVerifier.java @@ -31,8 +31,8 @@ public class MessageDecryptVerifier { public static List findEncryptedParts(Part startPart) { - List encryptedParts = new ArrayList(); - Stack partsToCheck = new Stack(); + List encryptedParts = new ArrayList<>(); + Stack partsToCheck = new Stack<>(); partsToCheck.push(startPart); while (!partsToCheck.isEmpty()) { @@ -54,8 +54,8 @@ public class MessageDecryptVerifier { } public static List findSignedParts(Part startPart) { - List signedParts = new ArrayList(); - Stack partsToCheck = new Stack(); + List signedParts = new ArrayList<>(); + Stack partsToCheck = new Stack<>(); partsToCheck.push(startPart); while (!partsToCheck.isEmpty()) { @@ -77,8 +77,8 @@ public class MessageDecryptVerifier { } public static List findPgpInlineParts(Part startPart) { - List inlineParts = new ArrayList(); - Stack partsToCheck = new Stack(); + List inlineParts = new ArrayList<>(); + Stack partsToCheck = new Stack<>(); partsToCheck.push(startPart); while (!partsToCheck.isEmpty()) { diff --git a/k9mail/src/test/java/com/fsck/k9/crypto/MessageDecryptVerifierTest.java b/k9mail/src/test/java/com/fsck/k9/crypto/MessageDecryptVerifierTest.java index 6b7c4e232..dd01181f5 100644 --- a/k9mail/src/test/java/com/fsck/k9/crypto/MessageDecryptVerifierTest.java +++ b/k9mail/src/test/java/com/fsck/k9/crypto/MessageDecryptVerifierTest.java @@ -3,7 +3,10 @@ package com.fsck.k9.crypto; import java.util.List; +import com.fsck.k9.mail.BodyPart; +import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; +import com.fsck.k9.mail.Multipart; import com.fsck.k9.mail.Part; import com.fsck.k9.mail.internet.MimeBodyPart; import com.fsck.k9.mail.internet.MimeHeader; @@ -86,8 +89,212 @@ public class MessageDecryptVerifierTest { assertSame(bodyPartThree, encryptedParts.get(1)); } + @Test + public void findEncrypted__withMultipartEncrypted__shouldReturnRoot() throws Exception { + Message message = messageFromBody( + multipart("encrypted", + bodypart("application/pgp-encrypted"), + bodypart("application/octet-stream") + ) + ); + + List encryptedParts = MessageDecryptVerifier.findEncryptedParts(message); + + assertEquals(1, encryptedParts.size()); + assertSame(message, encryptedParts.get(0)); + } + + @Test + public void findEncrypted__withMultipartMixedSubEncrypted__shouldReturnRoot() throws Exception { + Message message = messageFromBody( + multipart("mixed", + multipart("encrypted", + bodypart("application/pgp-encrypted"), + bodypart("application/octet-stream") + ) + ) + ); + + List encryptedParts = MessageDecryptVerifier.findEncryptedParts(message); + + assertEquals(1, encryptedParts.size()); + assertSame(getPart(message, 0), encryptedParts.get(0)); + } + + @Test + public void findEncrypted__withMultipartMixedSubEncryptedAndEncrypted__shouldReturnBoth() + throws Exception { + Message message = messageFromBody( + multipart("mixed", + multipart("encrypted", + bodypart("application/pgp-encrypted"), + bodypart("application/octet-stream") + ), + multipart("encrypted", + bodypart("application/pgp-encrypted"), + bodypart("application/octet-stream") + ) + ) + ); + + List encryptedParts = MessageDecryptVerifier.findEncryptedParts(message); + + assertEquals(2, encryptedParts.size()); + assertSame(getPart(message, 0), encryptedParts.get(0)); + assertSame(getPart(message, 1), encryptedParts.get(1)); + } + + @Test + public void findEncrypted__withMultipartMixedSubTextAndEncrypted__shouldReturnEncrypted() throws Exception { + Message message = messageFromBody( + multipart("mixed", + bodypart("text/plain"), + multipart("encrypted", + bodypart("application/pgp-encrypted"), + bodypart("application/octet-stream") + ) + ) + ); + + List encryptedParts = MessageDecryptVerifier.findEncryptedParts(message); + + assertEquals(1, encryptedParts.size()); + assertSame(getPart(message, 1), encryptedParts.get(0)); + } + + @Test + public void findEncrypted__withMultipartMixedSubEncryptedAndText__shouldReturnEncrypted() throws Exception { + Message message = messageFromBody( + multipart("mixed", + multipart("encrypted", + bodypart("application/pgp-encrypted"), + bodypart("application/octet-stream") + ), + bodypart("text/plain") + ) + ); + + List encryptedParts = MessageDecryptVerifier.findEncryptedParts(message); + + assertEquals(1, encryptedParts.size()); + assertSame(getPart(message, 0), encryptedParts.get(0)); + } + + @Test + public void findSigned__withSimpleMultipartSigned__shouldReturnRoot() throws Exception { + Message message = messageFromBody( + multipart("signed", + bodypart("text/plain"), + bodypart("application/pgp-signature") + ) + ); + + List signedParts = MessageDecryptVerifier.findSignedParts(message); + + assertEquals(1, signedParts.size()); + assertSame(message, signedParts.get(0)); + } + + @Test + public void findSigned__withComplexMultipartSigned__shouldReturnRoot() throws Exception { + Message message = messageFromBody( + multipart("signed", + multipart("mixed", + bodypart("text/plain"), + bodypart("application/pdf") + ), + bodypart("application/pgp-signature") + ) + ); + + List signedParts = MessageDecryptVerifier.findSignedParts(message); + + assertEquals(1, signedParts.size()); + assertSame(message, signedParts.get(0)); + } + + @Test + public void findEncrypted__withMultipartMixedSubSigned__shouldReturnSigned() throws Exception { + Message message = messageFromBody( + multipart("mixed", + multipart("signed", + bodypart("text/plain"), + bodypart("application/pgp-signature") + ) + ) + ); + + List signedParts = MessageDecryptVerifier.findSignedParts(message); + + assertEquals(1, signedParts.size()); + assertSame(getPart(message, 0), signedParts.get(0)); + } + + @Test + public void findEncrypted__withMultipartMixedSubSignedAndText__shouldReturnSigned() throws Exception { + Message message = messageFromBody( + multipart("mixed", + multipart("signed", + bodypart("text/plain"), + bodypart("application/pgp-signature") + ), + bodypart("text/plain") + ) + ); + + List signedParts = MessageDecryptVerifier.findSignedParts(message); + + assertEquals(1, signedParts.size()); + assertSame(getPart(message, 0), signedParts.get(0)); + } + + @Test + public void findEncrypted__withMultipartMixedSubTextAndSigned__shouldReturnSigned() throws Exception { + Message message = messageFromBody( + multipart("mixed", + bodypart("text/plain"), + multipart("signed", + bodypart("text/plain"), + bodypart("application/pgp-signature") + ) + ) + ); + + List signedParts = MessageDecryptVerifier.findSignedParts(message); + + assertEquals(1, signedParts.size()); + assertSame(getPart(message, 1), signedParts.get(0)); + } + + MimeMessage messageFromBody(BodyPart bodyPart) throws MessagingException { + MimeMessage message = new MimeMessage(); + MimeMessageHelper.setBody(message, bodyPart.getBody()); + return message; + } + + MimeBodyPart multipart(String type, BodyPart... subParts) throws MessagingException { + MimeMultipart multiPart = new MimeMultipart(); + multiPart.setSubType(type); + for (BodyPart subPart : subParts) { + multiPart.addBodyPart(subPart); + } + return new MimeBodyPart(multiPart); + } + + BodyPart bodypart(String type) throws MessagingException { + return new MimeBodyPart(null, type); + } + + public static Part getPart(Part searchRootPart, int... indexes) { + Part part = searchRootPart; + for (int index : indexes) { + part = ((Multipart) part.getBody()).getBodyPart(index); + } + return part; + } + //TODO: Find a cleaner way to do this - private void addProtocolParameter(Part part) throws MessagingException { + private static void addProtocolParameter(Part part) throws MessagingException { String contentType = part.getContentType(); part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType + "; protocol=\"application/pgp-encrypted\""); }