Search in sources :

Example 46 with Text

use of com.fsck.k9.mail.internet.Viewable.Text in project k-9 by k9mail.

the class QuotedMessagePresenter method processDraftMessage.

public void processDraftMessage(MessageViewInfo messageViewInfo, Map<IdentityField, String> k9identity) {
    quoteStyle = k9identity.get(IdentityField.QUOTE_STYLE) != null ? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE)) : account.getQuoteStyle();
    int cursorPosition = 0;
    if (k9identity.containsKey(IdentityField.CURSOR_POSITION)) {
        try {
            cursorPosition = Integer.parseInt(k9identity.get(IdentityField.CURSOR_POSITION));
        } catch (Exception e) {
            Timber.e(e, "Could not parse cursor position for MessageCompose; continuing.");
        }
    }
    String showQuotedTextMode;
    if (k9identity.containsKey(IdentityField.QUOTED_TEXT_MODE)) {
        showQuotedTextMode = k9identity.get(IdentityField.QUOTED_TEXT_MODE);
    } else {
        showQuotedTextMode = "NONE";
    }
    int bodyLength = k9identity.get(IdentityField.LENGTH) != null ? Integer.valueOf(k9identity.get(IdentityField.LENGTH)) : UNKNOWN_LENGTH;
    int bodyOffset = k9identity.get(IdentityField.OFFSET) != null ? Integer.valueOf(k9identity.get(IdentityField.OFFSET)) : UNKNOWN_LENGTH;
    Integer bodyFooterOffset = k9identity.get(IdentityField.FOOTER_OFFSET) != null ? Integer.valueOf(k9identity.get(IdentityField.FOOTER_OFFSET)) : null;
    Integer bodyPlainLength = k9identity.get(IdentityField.PLAIN_LENGTH) != null ? Integer.valueOf(k9identity.get(IdentityField.PLAIN_LENGTH)) : null;
    Integer bodyPlainOffset = k9identity.get(IdentityField.PLAIN_OFFSET) != null ? Integer.valueOf(k9identity.get(IdentityField.PLAIN_OFFSET)) : null;
    QuotedTextMode quotedMode;
    try {
        quotedMode = QuotedTextMode.valueOf(showQuotedTextMode);
    } catch (Exception e) {
        quotedMode = QuotedTextMode.NONE;
    }
    // Always respect the user's current composition format preference, even if the
    // draft was saved in a different format.
    // TODO - The current implementation doesn't allow a user in HTML mode to edit a draft that wasn't saved with K9mail.
    String messageFormatString = k9identity.get(IdentityField.MESSAGE_FORMAT);
    MessageFormat messageFormat = null;
    if (messageFormatString != null) {
        try {
            messageFormat = MessageFormat.valueOf(messageFormatString);
        } catch (Exception e) {
        /* do nothing */
        }
    }
    if (messageFormat == null) {
        // This message probably wasn't created by us. The exception is legacy
        // drafts created before the advent of HTML composition. In those cases,
        // we'll display the whole message (including the quoted part) in the
        // composition window. If that's the case, try and convert it to text to
        // match the behavior in text mode.
        view.setMessageContentCharacters(BodyTextExtractor.getBodyTextFromMessage(messageViewInfo.message, SimpleMessageFormat.TEXT));
        forcePlainText = true;
        showOrHideQuotedText(quotedMode);
        return;
    }
    if (messageFormat == MessageFormat.HTML) {
        Part part = MimeUtility.findFirstPartByMimeType(messageViewInfo.message, "text/html");
        if (part != null) {
            // Shouldn't happen if we were the one who saved it.
            quotedTextFormat = SimpleMessageFormat.HTML;
            String text = MessageExtractor.getTextFromPart(part);
            Timber.d("Loading message with offset %d, length %d. Text length is %d.", bodyOffset, bodyLength, text.length());
            if (bodyOffset + bodyLength > text.length()) {
                // The draft was edited outside of K-9 Mail?
                Timber.d("The identity field from the draft contains an invalid LENGTH/OFFSET");
                bodyOffset = 0;
                bodyLength = 0;
            }
            // Grab our reply text.
            String bodyText = text.substring(bodyOffset, bodyOffset + bodyLength);
            view.setMessageContentCharacters(HtmlConverter.htmlToText(bodyText));
            // Regenerate the quoted html without our user content in it.
            StringBuilder quotedHTML = new StringBuilder();
            // stuff before the reply
            quotedHTML.append(text.substring(0, bodyOffset));
            quotedHTML.append(text.substring(bodyOffset + bodyLength));
            if (quotedHTML.length() > 0) {
                quotedHtmlContent = new InsertableHtmlContent();
                quotedHtmlContent.setQuotedContent(quotedHTML);
                // We don't know if bodyOffset refers to the header or to the footer
                quotedHtmlContent.setHeaderInsertionPoint(bodyOffset);
                if (bodyFooterOffset != null) {
                    quotedHtmlContent.setFooterInsertionPoint(bodyFooterOffset);
                } else {
                    quotedHtmlContent.setFooterInsertionPoint(bodyOffset);
                }
                // TODO replace with MessageViewInfo data
                view.setQuotedHtml(quotedHtmlContent.getQuotedContent(), AttachmentResolver.createFromPart(messageViewInfo.rootPart));
            }
        }
        if (bodyPlainOffset != null && bodyPlainLength != null) {
            processSourceMessageText(messageViewInfo.rootPart, bodyPlainOffset, bodyPlainLength, false);
        }
    } else if (messageFormat == MessageFormat.TEXT) {
        quotedTextFormat = SimpleMessageFormat.TEXT;
        processSourceMessageText(messageViewInfo.rootPart, bodyOffset, bodyLength, true);
    } else {
        Timber.e("Unhandled message format.");
    }
    // Set the cursor position if we have it.
    try {
        view.setMessageContentCursorPosition(cursorPosition);
    } catch (Exception e) {
        Timber.e(e, "Could not set cursor position in MessageCompose; ignoring.");
    }
    showOrHideQuotedText(quotedMode);
}
Also used : SimpleMessageFormat(com.fsck.k9.message.SimpleMessageFormat) MessageFormat(com.fsck.k9.Account.MessageFormat) Part(com.fsck.k9.mail.Part) QuotedTextMode(com.fsck.k9.message.QuotedTextMode) InsertableHtmlContent(com.fsck.k9.message.quote.InsertableHtmlContent) MessagingException(com.fsck.k9.mail.MessagingException)

Example 47 with Text

use of com.fsck.k9.mail.internet.Viewable.Text in project k-9 by k9mail.

the class QuotedMessagePresenter method processSourceMessageText.

/**
     * Pull out the parts of the now loaded source message and apply them to the new message
     * depending on the type of message being composed.
     * @param bodyOffset Insertion point for reply.
     * @param bodyLength Length of reply.
     * @param viewMessageContent Update mMessageContentView or not.
     */
private void processSourceMessageText(Part rootMessagePart, int bodyOffset, int bodyLength, boolean viewMessageContent) {
    Part textPart = MimeUtility.findFirstPartByMimeType(rootMessagePart, "text/plain");
    if (textPart == null) {
        return;
    }
    String messageText = MessageExtractor.getTextFromPart(textPart);
    Timber.d("Loading message with offset %d, length %d. Text length is %d.", bodyOffset, bodyLength, messageText.length());
    // and put them in their respective places in the UI.
    if (bodyLength != UNKNOWN_LENGTH) {
        try {
            // Regenerate the quoted text without our user content in it nor added newlines.
            StringBuilder quotedText = new StringBuilder();
            if (bodyOffset == UNKNOWN_LENGTH && messageText.substring(bodyLength, bodyLength + 4).equals("\r\n\r\n")) {
                // top-posting: ignore two newlines at start of quote
                quotedText.append(messageText.substring(bodyLength + 4));
            } else if (bodyOffset + bodyLength == messageText.length() && messageText.substring(bodyOffset - 2, bodyOffset).equals("\r\n")) {
                // bottom-posting: ignore newline at end of quote
                quotedText.append(messageText.substring(0, bodyOffset - 2));
            } else {
                // stuff before the reply
                quotedText.append(messageText.substring(0, bodyOffset));
                quotedText.append(messageText.substring(bodyOffset + bodyLength));
            }
            view.setQuotedText(quotedText.toString());
            messageText = messageText.substring(bodyOffset, bodyOffset + bodyLength);
        } catch (IndexOutOfBoundsException e) {
            // Invalid bodyOffset or bodyLength.  The draft was edited outside of K-9 Mail?
            Timber.d("The identity field from the draft contains an invalid bodyOffset/bodyLength");
        }
    }
    if (viewMessageContent) {
        view.setMessageContentCharacters(messageText);
    }
}
Also used : Part(com.fsck.k9.mail.Part)

Example 48 with Text

use of com.fsck.k9.mail.internet.Viewable.Text in project k-9 by k9mail.

the class QuotedMessagePresenter method populateUIWithQuotedMessage.

/**
     * Build and populate the UI with the quoted message.
     *
     * @param showQuotedText
     *         {@code true} if the quoted text should be shown, {@code false} otherwise.
     */
public void populateUIWithQuotedMessage(MessageViewInfo messageViewInfo, boolean showQuotedText, Action action) throws MessagingException {
    MessageFormat origMessageFormat = account.getMessageFormat();
    if (forcePlainText || origMessageFormat == MessageFormat.TEXT) {
        // Use plain text for the quoted message
        quotedTextFormat = SimpleMessageFormat.TEXT;
    } else if (origMessageFormat == MessageFormat.AUTO) {
        // Figure out which message format to use for the quoted text by looking if the source
        // message contains a text/html part. If it does, we use that.
        quotedTextFormat = (MimeUtility.findFirstPartByMimeType(messageViewInfo.rootPart, "text/html") == null) ? SimpleMessageFormat.TEXT : SimpleMessageFormat.HTML;
    } else {
        quotedTextFormat = SimpleMessageFormat.HTML;
    }
    // Handle the original message in the reply
    // If we already have sourceMessageBody, use that.  It's pre-populated if we've got crypto going on.
    String content = BodyTextExtractor.getBodyTextFromMessage(messageViewInfo.rootPart, quotedTextFormat);
    if (quotedTextFormat == SimpleMessageFormat.HTML) {
        // closing tags such as </div>, </span>, </table>, </pre> will be cut off.
        if (account.isStripSignature() && (action == Action.REPLY || action == Action.REPLY_ALL)) {
            content = HtmlSignatureRemover.stripSignature(content);
        }
        // Add the HTML reply header to the top of the content.
        quotedHtmlContent = HtmlQuoteCreator.quoteOriginalHtmlMessage(resources, messageViewInfo.message, content, quoteStyle);
        // Load the message with the reply header. TODO replace with MessageViewInfo data
        view.setQuotedHtml(quotedHtmlContent.getQuotedContent(), AttachmentResolver.createFromPart(messageViewInfo.rootPart));
        // TODO: Also strip the signature from the text/plain part
        view.setQuotedText(TextQuoteCreator.quoteOriginalTextMessage(resources, messageViewInfo.message, BodyTextExtractor.getBodyTextFromMessage(messageViewInfo.rootPart, SimpleMessageFormat.TEXT), quoteStyle, account.getQuotePrefix()));
    } else if (quotedTextFormat == SimpleMessageFormat.TEXT) {
        if (account.isStripSignature() && (action == Action.REPLY || action == Action.REPLY_ALL)) {
            content = TextSignatureRemover.stripSignature(content);
        }
        view.setQuotedText(TextQuoteCreator.quoteOriginalTextMessage(resources, messageViewInfo.message, content, quoteStyle, account.getQuotePrefix()));
    }
    if (showQuotedText) {
        showOrHideQuotedText(QuotedTextMode.SHOW);
    } else {
        showOrHideQuotedText(QuotedTextMode.HIDE);
    }
}
Also used : SimpleMessageFormat(com.fsck.k9.message.SimpleMessageFormat) MessageFormat(com.fsck.k9.Account.MessageFormat)

Example 49 with Text

use of com.fsck.k9.mail.internet.Viewable.Text in project k-9 by k9mail.

the class MessageCryptoHelper method getDataSinkForDecryptedInlineData.

private OpenPgpDataSink<MimeBodyPart> getDataSinkForDecryptedInlineData() {
    return new OpenPgpDataSink<MimeBodyPart>() {

        @Override
        public MimeBodyPart processData(InputStream is) throws IOException {
            try {
                ByteArrayOutputStream decryptedByteOutputStream = new ByteArrayOutputStream();
                IOUtils.copy(is, decryptedByteOutputStream);
                TextBody body = new TextBody(new String(decryptedByteOutputStream.toByteArray()));
                return new MimeBodyPart(body, "text/plain");
            } catch (MessagingException e) {
                Timber.e(e, "MessagingException");
            }
            return null;
        }
    };
}
Also used : TextBody(com.fsck.k9.mail.internet.TextBody) MessagingException(com.fsck.k9.mail.MessagingException) InputStream(java.io.InputStream) OpenPgpDataSink(org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSink) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MimeBodyPart(com.fsck.k9.mail.internet.MimeBodyPart)

Example 50 with Text

use of com.fsck.k9.mail.internet.Viewable.Text in project k-9 by k9mail.

the class PgpMimeMessageTest method testSignedMessage.

@Test
public void testSignedMessage() throws IOException, MessagingException, PGPException {
    String messageSource = "Date: Mon, 08 Dec 2014 17:44:18 +0100\r\n" + "From: cketti <cketti@googlemail.com>\r\n" + "MIME-Version: 1.0\r\n" + "To: test@example.com\r\n" + "Subject: OpenPGP signature test\r\n" + "Content-Type: multipart/signed; micalg=pgp-sha1;\r\n" + " protocol=\"application/pgp-signature\";\r\n" + " boundary=\"24Bem7EnUI1Ipn9jNXuLgsetqa6wOkIxM\"\r\n" + "\r\n" + "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)\r\n" + "--24Bem7EnUI1Ipn9jNXuLgsetqa6wOkIxM\r\n" + "Content-Type: multipart/mixed;\r\n" + " boundary=\"------------030308060900040601010501\"\r\n" + "\r\n" + "This is a multi-part message in MIME format.\r\n" + "--------------030308060900040601010501\r\n" + "Content-Type: text/plain; charset=utf-8\r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "\r\n" + "Message body\r\n" + "goes here\r\n" + "\r\n" + "\r\n" + "--------------030308060900040601010501\r\n" + "Content-Type: text/plain; charset=UTF-8;\r\n" + " name=\"attachment.txt\"\r\n" + "Content-Transfer-Encoding: base64\r\n" + "Content-Disposition: attachment;\r\n" + " filename=\"attachment.txt\"\r\n" + "\r\n" + "VGV4dCBhdHRhY2htZW50Cg==\r\n" + "--------------030308060900040601010501--\r\n" + "\r\n" + "--24Bem7EnUI1Ipn9jNXuLgsetqa6wOkIxM\r\n" + "Content-Type: application/pgp-signature; name=\"signature.asc\"\r\n" + "Content-Description: OpenPGP digital signature\r\n" + "Content-Disposition: attachment; filename=\"signature.asc\"\r\n" + "\r\n" + "-----BEGIN PGP SIGNATURE-----\r\n" + "Version: GnuPG v1\r\n" + "\r\n" + "iQIcBAEBAgAGBQJUhdVqAAoJEO4v7zp9qOKJ8DQP/1+JE8UF7UmirnN1ZO+25hFC\r\n" + "jAfFMxRWMWXN0gGB+6ySy6ah0bCwmRwHpRBsW/tNcsmOPKb2XBf9zwF06uk/lLp4\r\n" + "ZmGXxSdQ9XJrlaHk8Sitn9Gi/1L+MNWgrsrLROAZv2jfc9wqN3FOrhN9NC1QXQvO\r\n" + "+D7sMorSr3l94majoIDrzvxEnfJVfrZWNTUaulJofOJ55GBZ3UJNob1WKjrnculL\r\n" + "IwmSERmVUoFBUfe/MBqqZH0WDJq9nt//NZFHLunj6nGsrpush1dQRcbR3zzQfXkk\r\n" + "s7zDLDa8VUv6OxcefjsVN/O7EenoWWgNg6GfW6tY2+oUsLSP2OS3JXvYsylQP4hR\r\n" + "iU1V9vvsu2Ax6bVb0+uTqw3jNiqVFy3o4mBigVUqp1EFIwBYmyNbe5wj4ACs9Avj\r\n" + "9t2reFSfXobWQFUS4s71JeMefNAHHJWZI63wNTxE6LOw01YxdJiDaPWGTOyM75MK\r\n" + "yqn7r5uIfeSv8NypGJaUv4firxKbrcZKk7Wpeh/rZuUSgoPcf3I1IzXfGKKIBHjU\r\n" + "WUMhTF5SoC5kIZyeXvHrhTM8HszcS8EoG2XcmcYArwgCUlOunFwZNqLPsfdMTRL6\r\n" + "9rcioaohEtroqoJiGAToJtIz8kqCaamnP/ASBkp9qqJizRd6fqt+tE8BsmJbuPLS\r\n" + "6lBpS8j0TqmaZMYfB9u4\r\n" + "=QvET\r\n" + "-----END PGP SIGNATURE-----\r\n" + "\r\n" + "--24Bem7EnUI1Ipn9jNXuLgsetqa6wOkIxM--\r\n";
    BinaryTempFileBody.setTempDirectory(InstrumentationRegistry.getTargetContext().getCacheDir());
    InputStream messageInputStream = new ByteArrayInputStream(messageSource.getBytes());
    MimeMessage message;
    try {
        message = MimeMessage.parseMimeMessage(messageInputStream, true);
    } finally {
        messageInputStream.close();
    }
    Multipart multipartSigned = (Multipart) message.getBody();
    BodyPart signedPart = multipartSigned.getBodyPart(0);
    ByteArrayOutputStream signedPartOutputStream = new ByteArrayOutputStream();
    signedPart.writeTo(signedPartOutputStream);
    byte[] signedData = signedPartOutputStream.toByteArray();
    Body signatureBody = multipartSigned.getBodyPart(1).getBody();
    ByteArrayOutputStream signatureBodyOutputStream = new ByteArrayOutputStream();
    signatureBody.writeTo(signatureBodyOutputStream);
    byte[] signatureData = signatureBodyOutputStream.toByteArray();
    assertTrue(verifySignature(signedData, signatureData));
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) BinaryTempFileBody(com.fsck.k9.mail.internet.BinaryTempFileBody) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)74 Part (com.fsck.k9.mail.Part)64 MimeBodyPart (com.fsck.k9.mail.internet.MimeBodyPart)37 BodyPart (com.fsck.k9.mail.BodyPart)34 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)33 MessageCreationHelper.createTextPart (com.fsck.k9.message.MessageCreationHelper.createTextPart)27 Message (com.fsck.k9.mail.Message)22 TextBody (com.fsck.k9.mail.internet.TextBody)18 MessageCreationHelper.createEmptyPart (com.fsck.k9.message.MessageCreationHelper.createEmptyPart)16 ArrayList (java.util.ArrayList)16 Body (com.fsck.k9.mail.Body)13 MessagingException (com.fsck.k9.mail.MessagingException)13 MessageCreationHelper.createPart (com.fsck.k9.message.MessageCreationHelper.createPart)13 Multipart (com.fsck.k9.mail.Multipart)10 Viewable (com.fsck.k9.mail.internet.Viewable)10 ByteArrayOutputStream (java.io.ByteArrayOutputStream)9 MimeMultipart (com.fsck.k9.mail.internet.MimeMultipart)8 Intent (android.content.Intent)6 BinaryMemoryBody (com.fsck.k9.mailstore.BinaryMemoryBody)6 ViewableExtractedText (com.fsck.k9.mailstore.MessageViewInfoExtractor.ViewableExtractedText)6