1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-01-14 07:08:00 -05:00

preliminary support for pgp/inline

This commit is contained in:
Vincent Breitmoser 2015-01-30 14:51:44 +01:00
parent de8da4dab4
commit 4bec165fdc
3 changed files with 63 additions and 15 deletions

View File

@ -12,6 +12,8 @@ import com.fsck.k9.mail.BodyPart;
import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Multipart; import com.fsck.k9.mail.Multipart;
import com.fsck.k9.mail.Part; import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.internet.MessageExtractor;
import org.openintents.openpgp.util.OpenPgpUtils;
public class MessageDecryptVerifier { public class MessageDecryptVerifier {
@ -20,6 +22,8 @@ public class MessageDecryptVerifier {
private static final String PROTOCOL_PARAMETER = "protocol"; private static final String PROTOCOL_PARAMETER = "protocol";
private static final String APPLICATION_PGP_ENCRYPTED = "application/pgp-encrypted"; private static final String APPLICATION_PGP_ENCRYPTED = "application/pgp-encrypted";
private static final String APPLICATION_PGP_SIGNATURE = "application/pgp-signature"; private static final String APPLICATION_PGP_SIGNATURE = "application/pgp-signature";
private static final String TEXT_PLAIN = "text/plain";
public static List<Part> findEncryptedParts(Part startPart) { public static List<Part> findEncryptedParts(Part startPart) {
List<Part> encryptedParts = new ArrayList<Part>(); List<Part> encryptedParts = new ArrayList<Part>();
@ -69,6 +73,35 @@ public class MessageDecryptVerifier {
return signedParts; return signedParts;
} }
public static List<Part> findPgpInlineParts(Part startPart) {
List<Part> inlineParts = new ArrayList<Part>();
Stack<Part> partsToCheck = new Stack<Part>();
partsToCheck.push(startPart);
while (!partsToCheck.isEmpty()) {
Part part = partsToCheck.pop();
String mimeType = part.getMimeType();
Body body = part.getBody();
if (TEXT_PLAIN.equals(mimeType)) {
String text = MessageExtractor.getTextFromPart(part);
switch (OpenPgpUtils.parseMessage(text)) {
case OpenPgpUtils.PARSE_RESULT_MESSAGE:
case OpenPgpUtils.PARSE_RESULT_SIGNED_MESSAGE:
inlineParts.add(part);
}
} else if (body instanceof Multipart) {
Multipart multipart = (Multipart) body;
for (int i = multipart.getCount() - 1; i >= 0; i--) {
BodyPart bodyPart = multipart.getBodyPart(i);
partsToCheck.push(bodyPart);
}
}
}
return inlineParts;
}
public static byte[] getSignatureData(Part part) throws IOException, MessagingException { public static byte[] getSignatureData(Part part) throws IOException, MessagingException {
if (MULTIPART_SIGNED.equals(part.getMimeType())) { if (MULTIPART_SIGNED.equals(part.getMimeType())) {

View File

@ -9,13 +9,13 @@ import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
public class OpenPgpResultBodyPart extends MimeBodyPart { public class OpenPgpResultAnnotation extends MimeBodyPart {
private boolean wasEncrypted; private boolean wasEncrypted;
private OpenPgpSignatureResult signatureResult; private OpenPgpSignatureResult signatureResult;
private OpenPgpError error; private OpenPgpError error;
private PendingIntent pendingIntent; private PendingIntent pendingIntent;
public OpenPgpResultBodyPart(boolean wasEncrypted) throws MessagingException { public OpenPgpResultAnnotation(boolean wasEncrypted) throws MessagingException {
this.wasEncrypted = wasEncrypted; this.wasEncrypted = wasEncrypted;
} }

View File

@ -29,6 +29,7 @@ import com.fsck.k9.mail.BodyPart;
import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Multipart; import com.fsck.k9.mail.Multipart;
import com.fsck.k9.mail.Part; import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.internet.MessageExtractor;
import com.fsck.k9.mailstore.DecryptStreamParser; import com.fsck.k9.mailstore.DecryptStreamParser;
import com.fsck.k9.mailstore.LocalMessage; import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.OpenPgpResultBodyPart; import com.fsck.k9.mailstore.OpenPgpResultBodyPart;
@ -66,10 +67,12 @@ class MessageCryptoHelper {
List<Part> encryptedParts = MessageDecryptVerifier.findEncryptedParts(message); List<Part> encryptedParts = MessageDecryptVerifier.findEncryptedParts(message);
List<Part> signedParts = MessageDecryptVerifier.findSignedParts(message); List<Part> signedParts = MessageDecryptVerifier.findSignedParts(message);
if (!encryptedParts.isEmpty() || !signedParts.isEmpty()) { List<Part> inlineParts = MessageDecryptVerifier.findPgpInlineParts(message);
if (!encryptedParts.isEmpty() || !signedParts.isEmpty() || !inlineParts.isEmpty()) {
partsToDecryptOrVerify = new ArrayDeque<Part>(); partsToDecryptOrVerify = new ArrayDeque<Part>();
partsToDecryptOrVerify.addAll(encryptedParts); partsToDecryptOrVerify.addAll(encryptedParts);
partsToDecryptOrVerify.addAll(signedParts); partsToDecryptOrVerify.addAll(signedParts);
partsToDecryptOrVerify.addAll(inlineParts);
decryptOrVerifyNextPartOrStartExtractingTextAndAttachments(); decryptOrVerifyNextPartOrStartExtractingTextAndAttachments();
} else { } else {
returnResultToFragment(); returnResultToFragment();
@ -80,7 +83,14 @@ class MessageCryptoHelper {
if (!partsToDecryptOrVerify.isEmpty()) { if (!partsToDecryptOrVerify.isEmpty()) {
Part part = partsToDecryptOrVerify.peekFirst(); Part part = partsToDecryptOrVerify.peekFirst();
if (MessageDecryptVerifier.isPgpMimePart(part)) { if ("text/plain".equalsIgnoreCase(part.getMimeType())) {
startDecryptingOrVerifyingPart(part);
} else if (MessageDecryptVerifier.isPgpMimePart(part)) {
Multipart multipart = (Multipart) part.getBody();
if (multipart == null) {
throw new RuntimeException("Downloading missing parts before decryption isn't supported yet");
}
startDecryptingOrVerifyingPart(part); startDecryptingOrVerifyingPart(part);
} else { } else {
partsToDecryptOrVerify.removeFirst(); partsToDecryptOrVerify.removeFirst();
@ -95,11 +105,6 @@ class MessageCryptoHelper {
} }
private void startDecryptingOrVerifyingPart(Part part) { private void startDecryptingOrVerifyingPart(Part part) {
Multipart multipart = (Multipart) part.getBody();
if (multipart == null) {
throw new RuntimeException("Downloading missing parts before decryption isn't supported yet");
}
if (!isBoundToCryptoProviderService()) { if (!isBoundToCryptoProviderService()) {
connectToCryptoProviderService(); connectToCryptoProviderService();
} else { } else {
@ -156,7 +161,7 @@ class MessageCryptoHelper {
private void callAsyncDecrypt(Intent intent) throws IOException { private void callAsyncDecrypt(Intent intent) throws IOException {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
PipedInputStream pipedInputStream = getPipedInputStreamForEncryptedData(); PipedInputStream pipedInputStream = getPipedInputStreamForEncryptedOrInlineData();
PipedOutputStream decryptedOutputStream = getPipedOutputStreamForDecryptedData(latch); PipedOutputStream decryptedOutputStream = getPipedOutputStreamForDecryptedData(latch);
openPgpApi.executeApiAsync(intent, pipedInputStream, decryptedOutputStream, new IOpenPgpCallback() { openPgpApi.executeApiAsync(intent, pipedInputStream, decryptedOutputStream, new IOpenPgpCallback() {
@ -210,7 +215,7 @@ class MessageCryptoHelper {
return pipedInputStream; return pipedInputStream;
} }
private PipedInputStream getPipedInputStreamForEncryptedData() throws IOException { private PipedInputStream getPipedInputStreamForEncryptedOrInlineData() throws IOException {
PipedInputStream pipedInputStream = new PipedInputStream(); PipedInputStream pipedInputStream = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(pipedInputStream); final PipedOutputStream out = new PipedOutputStream(pipedInputStream);
@ -218,10 +223,16 @@ class MessageCryptoHelper {
@Override @Override
public void run() { public void run() {
try { try {
Multipart multipartEncryptedMultipart = (Multipart) currentlyDecrypringOrVerifyingPart.getBody(); if (currentlyDecrypringOrVerifyingPart instanceof Multipart) {
BodyPart encryptionPayloadPart = multipartEncryptedMultipart.getBodyPart(1); Multipart multipartEncryptedMultipart =
Body encryptionPayloadBody = encryptionPayloadPart.getBody(); (Multipart) currentlyDecrypringOrVerifyingPart.getBody();
encryptionPayloadBody.writeTo(out); BodyPart encryptionPayloadPart = multipartEncryptedMultipart.getBodyPart(1);
Body encryptionPayloadBody = encryptionPayloadPart.getBody();
encryptionPayloadBody.writeTo(out);
} else {
String text = MessageExtractor.getTextFromPart(currentlyDecrypringOrVerifyingPart);
out.write(text.getBytes());
}
} catch (Exception e) { } catch (Exception e) {
Log.e(K9.LOG_TAG, "Exception while writing message to crypto provider", e); Log.e(K9.LOG_TAG, "Exception while writing message to crypto provider", e);
} finally { } finally {
@ -345,6 +356,10 @@ class MessageCryptoHelper {
} }
private void addOpenPgpResultPartToMessage(OpenPgpResultBodyPart decryptedPart) { private void addOpenPgpResultPartToMessage(OpenPgpResultBodyPart decryptedPart) {
if ( ! (currentlyDecrypringOrVerifyingPart.getBody() instanceof Multipart)) {
// TODO this is a text/plain part - care about this later!
return;
}
Multipart multipart = (Multipart) currentlyDecrypringOrVerifyingPart.getBody(); Multipart multipart = (Multipart) currentlyDecrypringOrVerifyingPart.getBody();
multipart.addBodyPart(decryptedPart); multipart.addBodyPart(decryptedPart);
} }