diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/DecryptStreamParser.java b/k9mail/src/main/java/com/fsck/k9/mailstore/DecryptStreamParser.java index d95ab2df0..13cd6c87d 100644 --- a/k9mail/src/main/java/com/fsck/k9/mailstore/DecryptStreamParser.java +++ b/k9mail/src/main/java/com/fsck/k9/mailstore/DecryptStreamParser.java @@ -24,11 +24,13 @@ import org.apache.james.mime4j.parser.MimeStreamParser; import org.apache.james.mime4j.stream.BodyDescriptor; import org.apache.james.mime4j.stream.Field; import org.apache.james.mime4j.stream.MimeConfig; +import org.openintents.openpgp.OpenPgpError; +import org.openintents.openpgp.OpenPgpSignatureResult; public class DecryptStreamParser { - public static DecryptedBodyPart parse(Part multipartEncrypted, InputStream inputStream) throws MessagingException, IOException { - DecryptedBodyPart decryptedRootPart = new DecryptedBodyPart(multipartEncrypted); + public static DecryptedBodyPart parse(InputStream inputStream) throws MessagingException, IOException { + DecryptedBodyPart decryptedRootPart = new DecryptedBodyPart(); MimeConfig parserConfig = new MimeConfig(); parserConfig.setMaxHeaderLen(-1); @@ -36,7 +38,7 @@ public class DecryptStreamParser { parserConfig.setMaxHeaderCount(-1); MimeStreamParser parser = new MimeStreamParser(parserConfig); - parser.setContentHandler(new PartBuilder(multipartEncrypted, decryptedRootPart)); + parser.setContentHandler(new PartBuilder(decryptedRootPart)); parser.setRecurse(); try { @@ -64,12 +66,10 @@ public class DecryptStreamParser { private static class PartBuilder implements ContentHandler { - private final Part multipartEncrypted; private final DecryptedBodyPart decryptedRootPart; private final Stack stack = new Stack(); - public PartBuilder(Part multipartEncrypted, DecryptedBodyPart decryptedRootPart) throws MessagingException { - this.multipartEncrypted = multipartEncrypted; + public PartBuilder(DecryptedBodyPart decryptedRootPart) throws MessagingException { this.decryptedRootPart = decryptedRootPart; } @@ -80,7 +80,7 @@ public class DecryptStreamParser { } else { Part part = (Part) stack.peek(); - Message innerMessage = new DecryptedMimeMessage(multipartEncrypted); + Message innerMessage = new MimeMessage(); part.setBody(innerMessage); stack.push(innerMessage); @@ -97,7 +97,7 @@ public class DecryptStreamParser { try { Multipart multipart = (Multipart) stack.peek(); - BodyPart bodyPart = new DecryptedBodyPart(multipartEncrypted); + BodyPart bodyPart = new MimeBodyPart(); multipart.addBodyPart(bodyPart); stack.push(bodyPart); @@ -183,18 +183,27 @@ public class DecryptStreamParser { } public static class DecryptedBodyPart extends MimeBodyPart { - private final Part multipartEncrypted; + private OpenPgpSignatureResult signatureResult; + private OpenPgpError error; - public DecryptedBodyPart(Part multipartEncrypted) throws MessagingException { - this.multipartEncrypted = multipartEncrypted; + public DecryptedBodyPart() throws MessagingException { + // Do nothing } - } - public static class DecryptedMimeMessage extends MimeMessage { - private final Part multipartEncrypted; + public OpenPgpSignatureResult getSignatureResult() { + return signatureResult; + } - public DecryptedMimeMessage(Part multipartEncrypted) { - this.multipartEncrypted = multipartEncrypted; + public void setSignatureResult(OpenPgpSignatureResult signatureResult) { + this.signatureResult = signatureResult; + } + + public OpenPgpError getError() { + return error; + } + + public void setError(OpenPgpError error) { + this.error = error; } } } diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalMessageExtractor.java b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalMessageExtractor.java index 75139527c..ffda014de 100644 --- a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalMessageExtractor.java +++ b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalMessageExtractor.java @@ -20,6 +20,7 @@ import com.fsck.k9.mail.internet.MessageExtractor; import com.fsck.k9.mail.internet.MimeHeader; import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mail.internet.Viewable; +import com.fsck.k9.mailstore.DecryptStreamParser.DecryptedBodyPart; import com.fsck.k9.mailstore.MessageViewInfo.MessageViewContainer; import com.fsck.k9.provider.AttachmentProvider; import org.openintents.openpgp.OpenPgpError; @@ -44,6 +45,7 @@ public class LocalMessageExtractor { private static final int FILENAME_PREFIX_LENGTH = FILENAME_PREFIX.length(); private static final String FILENAME_SUFFIX = " "; private static final int FILENAME_SUFFIX_LENGTH = FILENAME_SUFFIX.length(); + private static final OpenPgpSignatureResult NO_SIGNATURE_RESULT = null; private LocalMessageExtractor() {} /** @@ -439,7 +441,7 @@ public class LocalMessageExtractor { List attachmentInfos = extractAttachmentInfos(attachments); // TODO fill from part - OpenPgpSignatureResult pgpResult = null; + OpenPgpSignatureResult pgpResult = getSignatureResultForPart(part); OpenPgpError pgpError = null; boolean wasEncrypted = false; PendingIntent pendingIntent = null; @@ -490,6 +492,15 @@ public class LocalMessageExtractor { && ((Multipart) part.getBody()).getBodyParts().size() == 3; } + private static OpenPgpSignatureResult getSignatureResultForPart(Part part) { + if (part instanceof DecryptedBodyPart) { + DecryptedBodyPart decryptedBodyPart = (DecryptedBodyPart) part; + return decryptedBodyPart.getSignatureResult(); + } + + return NO_SIGNATURE_RESULT; + } + private static List extractAttachmentInfos(List attachmentParts) throws MessagingException { diff --git a/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java b/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java index 8eaab42d3..3deb3ca4a 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java +++ b/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java @@ -94,6 +94,8 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF private static final int LOCAL_MESSAGE_LOADER_ID = 1; private static final int DECODE_MESSAGE_LOADER_ID = 2; + private static final int INVALID_OPENPGP_RESULT_CODE = -1; + public static MessageViewFragment newInstance(MessageReference reference) { MessageViewFragment fragment = new MessageViewFragment(); @@ -381,7 +383,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF protected DecryptedBodyPart doInBackground(Void... params) { DecryptedBodyPart decryptedPart = null; try { - decryptedPart = DecryptStreamParser.parse(currentlyDecryptingPart, decryptedInputStream); + decryptedPart = DecryptStreamParser.parse(decryptedInputStream); latch.await(); } catch (InterruptedException e) { @@ -402,57 +404,66 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF } private void onDecryptionConverge (DecryptedBodyPart decryptedPart) { - try { - if (currentDecryptingResult == null) { - Log.e(K9.LOG_TAG, "internal error, we should have a result here!"); + Log.e(K9.LOG_TAG, "Internal error: we should have a result here!"); return; } - int resultCode = currentDecryptingResult.getIntExtra(OpenPgpApi.RESULT_CODE, -1); - Log.d(K9.LOG_TAG, "result: " + resultCode); + int resultCode = currentDecryptingResult.getIntExtra(OpenPgpApi.RESULT_CODE, INVALID_OPENPGP_RESULT_CODE); + if (K9.DEBUG) { + Log.d(K9.LOG_TAG, "OpenPGP API decryptVerify result code: " + resultCode); + } switch (resultCode) { - case -1: - Log.e(K9.LOG_TAG, "internal error: no result code!"); - return; - + case INVALID_OPENPGP_RESULT_CODE: { + Log.e(K9.LOG_TAG, "Internal error: no result code!"); + break; + } case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { PendingIntent pendingIntent = currentDecryptingResult.getParcelableExtra(OpenPgpApi.RESULT_INTENT); if (pendingIntent == null) { throw new AssertionError("Expecting PendingIntent on USER_INTERACTION_REQUIRED!"); } + try { getActivity().startIntentSenderForResult(pendingIntent.getIntentSender(), MessageList.REQUEST_CODE_CRYPTO, null, 0, 0, 0); } catch (SendIntentException e) { - Log.e(K9.LOG_TAG, "internal error on starting pendingintent!", e); + Log.e(K9.LOG_TAG, "Internal error on starting pendingintent!", e); } - return; + break; } - case OpenPgpApi.RESULT_CODE_ERROR: { - Log.e(K9.LOG_TAG, "error msg: " + currentDecryptingResult.getStringExtra(OpenPgpApi.RESULT_ERROR)); - onDecryptionFailed(); - return; - } + OpenPgpError error = currentDecryptingResult.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + if (K9.DEBUG) { + Log.w(K9.LOG_TAG, "OpenPGP API error: " + error.getMessage()); + } + + onDecryptionFailed(error); + break; + } case OpenPgpApi.RESULT_CODE_SUCCESS: { + OpenPgpSignatureResult signatureResult = + currentDecryptingResult.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); + decryptedPart.setSignatureResult(signatureResult); + onDecryptionSuccess(decryptedPart); + break; } } } finally { currentDecryptingResult = null; } - } public void handleCryptoResult(int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { decryptNextPartOrStartExtractingTextAndAttachments(); } else { - onDecryptionFailed(); + //FIXME: don't pass null + onDecryptionFailed(null); } } @@ -466,8 +477,14 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF multipart.addBodyPart(decryptedPart); } - private void onDecryptionFailed() { - // TODO: display error to user? + private void onDecryptionFailed(OpenPgpError error) { + try { + DecryptedBodyPart errorPart = new DecryptedBodyPart(); + errorPart.setError(error); + addDecryptedPartToMessage(errorPart); + } catch (MessagingException e) { + Log.e(K9.LOG_TAG, "This shouldn't happen", e); + } onDecryptionFinished(); }