commit
471aed586a
21 changed files with 457 additions and 549 deletions
|
@ -1,5 +1,7 @@
|
|||
package com.fsck.k9.mail.internet;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.mail.Body;
|
||||
|
@ -110,22 +112,15 @@ public class MessageExtractor {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Traverse the MIME tree of a message an extract viewable parts.
|
||||
*
|
||||
* @param part
|
||||
* The message part to start from.
|
||||
* @param attachments
|
||||
* A list that will receive the parts that are considered attachments.
|
||||
*
|
||||
* @return A list of {@link Viewable}s.
|
||||
*
|
||||
* @throws MessagingException
|
||||
* In case of an error.
|
||||
*/
|
||||
public static List<Viewable> getViewables(Part part, List<Part> attachments) throws MessagingException {
|
||||
List<Viewable> viewables = new ArrayList<Viewable>();
|
||||
/** Traverse the MIME tree of a message an extract viewable parts. */
|
||||
public static void findViewablesAndAttachments(Part part,
|
||||
@Nullable List<Viewable> outputViewableParts, @Nullable List<Part> outputNonViewableParts)
|
||||
throws MessagingException {
|
||||
boolean skipSavingNonViewableParts = outputNonViewableParts == null;
|
||||
boolean skipSavingViewableParts = outputViewableParts == null;
|
||||
if (skipSavingNonViewableParts && skipSavingViewableParts) {
|
||||
throw new IllegalArgumentException("method was called but no output is to be collected - this a bug!");
|
||||
}
|
||||
|
||||
Body body = part.getBody();
|
||||
if (body instanceof Multipart) {
|
||||
|
@ -138,20 +133,26 @@ public class MessageExtractor {
|
|||
List<Viewable> text = findTextPart(multipart, true);
|
||||
|
||||
Set<Part> knownTextParts = getParts(text);
|
||||
List<Viewable> html = findHtmlPart(multipart, knownTextParts, attachments, true);
|
||||
List<Viewable> html = findHtmlPart(multipart, knownTextParts, outputNonViewableParts, true);
|
||||
|
||||
if (skipSavingViewableParts) {
|
||||
return;
|
||||
}
|
||||
if (!text.isEmpty() || !html.isEmpty()) {
|
||||
Alternative alternative = new Alternative(text, html);
|
||||
viewables.add(alternative);
|
||||
outputViewableParts.add(alternative);
|
||||
}
|
||||
} else {
|
||||
// For all other multipart parts we recurse to grab all viewable children.
|
||||
for (Part bodyPart : multipart.getBodyParts()) {
|
||||
viewables.addAll(getViewables(bodyPart, attachments));
|
||||
findViewablesAndAttachments(bodyPart, outputViewableParts, outputNonViewableParts);
|
||||
}
|
||||
}
|
||||
} else if (body instanceof Message &&
|
||||
!("attachment".equalsIgnoreCase(getContentDisposition(part)))) {
|
||||
if (skipSavingViewableParts) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* We only care about message/rfc822 parts whose Content-Disposition header has a value
|
||||
* other than "attachment".
|
||||
|
@ -159,35 +160,38 @@ public class MessageExtractor {
|
|||
Message message = (Message) body;
|
||||
|
||||
// We add the Message object so we can extract the filename later.
|
||||
viewables.add(new MessageHeader(part, message));
|
||||
outputViewableParts.add(new MessageHeader(part, message));
|
||||
|
||||
// Recurse to grab all viewable parts and attachments from that message.
|
||||
viewables.addAll(getViewables(message, attachments));
|
||||
findViewablesAndAttachments(message, outputViewableParts, outputNonViewableParts);
|
||||
} else if (isPartTextualBody(part)) {
|
||||
/*
|
||||
* Save text/plain and text/html
|
||||
*/
|
||||
if (skipSavingViewableParts) {
|
||||
return;
|
||||
}
|
||||
String mimeType = part.getMimeType();
|
||||
if (isSameMimeType(mimeType, "text/plain")) {
|
||||
Text text = new Text(part);
|
||||
viewables.add(text);
|
||||
outputViewableParts.add(text);
|
||||
} else {
|
||||
Html html = new Html(part);
|
||||
viewables.add(html);
|
||||
outputViewableParts.add(html);
|
||||
}
|
||||
} else if (isSameMimeType(part.getMimeType(), "application/pgp-signature")) {
|
||||
// ignore this type explicitly
|
||||
} else {
|
||||
if (skipSavingNonViewableParts) {
|
||||
return;
|
||||
}
|
||||
// Everything else is treated as attachment.
|
||||
attachments.add(part);
|
||||
outputNonViewableParts.add(part);
|
||||
}
|
||||
|
||||
return viewables;
|
||||
}
|
||||
|
||||
public static Set<Part> getTextParts(Part part) throws MessagingException {
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
return getParts(getViewables(part, attachments));
|
||||
List<Viewable> viewableParts = new ArrayList<>();
|
||||
List<Part> nonViewableParts = new ArrayList<>();
|
||||
findViewablesAndAttachments(part, viewableParts, nonViewableParts);
|
||||
return getParts(viewableParts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,8 +201,8 @@ public class MessageExtractor {
|
|||
*/
|
||||
public static List<Part> collectAttachments(Message message) throws MessagingException {
|
||||
try {
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
getViewables(message, attachments);
|
||||
List<Part> attachments = new ArrayList<>();
|
||||
findViewablesAndAttachments(message, new ArrayList<Viewable>(), attachments);
|
||||
return attachments;
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Couldn't collect attachment parts", e);
|
||||
|
@ -292,7 +296,7 @@ public class MessageExtractor {
|
|||
*
|
||||
* @param multipart The {@code Multipart} to search through.
|
||||
* @param knownTextParts A set of {@code text/plain} parts that shouldn't be added to 'attachments'.
|
||||
* @param attachments A list that will receive the parts that are considered attachments.
|
||||
* @param outputNonViewableParts A list that will receive the parts that are considered attachments.
|
||||
* @param directChild If {@code true}, this method will add all {@code text/html} parts except the first
|
||||
* found to 'attachments'.
|
||||
*
|
||||
|
@ -301,8 +305,9 @@ public class MessageExtractor {
|
|||
* @throws MessagingException In case of an error.
|
||||
*/
|
||||
private static List<Viewable> findHtmlPart(Multipart multipart, Set<Part> knownTextParts,
|
||||
List<Part> attachments, boolean directChild) throws MessagingException {
|
||||
List<Viewable> viewables = new ArrayList<Viewable>();
|
||||
@Nullable List<Part> outputNonViewableParts, boolean directChild) throws MessagingException {
|
||||
boolean saveNonViewableParts = outputNonViewableParts != null;
|
||||
List<Viewable> viewables = new ArrayList<>();
|
||||
|
||||
boolean partFound = false;
|
||||
for (Part part : multipart.getBodyParts()) {
|
||||
|
@ -311,8 +316,10 @@ public class MessageExtractor {
|
|||
Multipart innerMultipart = (Multipart) body;
|
||||
|
||||
if (directChild && partFound) {
|
||||
// We already found our text/html part. Now we're only looking for attachments.
|
||||
findAttachments(innerMultipart, knownTextParts, attachments);
|
||||
if (saveNonViewableParts) {
|
||||
// We already found our text/html part. Now we're only looking for attachments.
|
||||
findAttachments(innerMultipart, knownTextParts, outputNonViewableParts);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Recurse to find HTML parts. Since this is a multipart that is a child of a
|
||||
|
@ -327,7 +334,7 @@ public class MessageExtractor {
|
|||
* 1.3. image/jpeg
|
||||
*/
|
||||
List<Viewable> htmlViewables = findHtmlPart(innerMultipart, knownTextParts,
|
||||
attachments, false);
|
||||
outputNonViewableParts, false);
|
||||
|
||||
if (!htmlViewables.isEmpty()) {
|
||||
partFound = true;
|
||||
|
@ -340,9 +347,10 @@ public class MessageExtractor {
|
|||
viewables.add(html);
|
||||
partFound = true;
|
||||
} else if (!knownTextParts.contains(part)) {
|
||||
// Only add this part as attachment if it's not a viewable text/plain part found
|
||||
// earlier.
|
||||
attachments.add(part);
|
||||
if (saveNonViewableParts) {
|
||||
// Only add this part as attachment if it's not a viewable text/plain part found earlier
|
||||
outputNonViewableParts.add(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,7 +368,7 @@ public class MessageExtractor {
|
|||
* A list that will receive the parts that are considered attachments.
|
||||
*/
|
||||
private static void findAttachments(Multipart multipart, Set<Part> knownTextParts,
|
||||
List<Part> attachments) {
|
||||
@NonNull List<Part> attachments) {
|
||||
for (Part part : multipart.getBodyParts()) {
|
||||
Body body = part.getBody();
|
||||
if (body instanceof Multipart) {
|
||||
|
@ -385,7 +393,7 @@ public class MessageExtractor {
|
|||
* @see MessageExtractor#findAttachments(Multipart, Set, List)
|
||||
*/
|
||||
private static Set<Part> getParts(List<Viewable> viewables) {
|
||||
Set<Part> parts = new HashSet<Part>();
|
||||
Set<Part> parts = new HashSet<>();
|
||||
|
||||
for (Viewable viewable : viewables) {
|
||||
if (viewable instanceof Textual) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* Empty marker class interface the class hierarchy used by
|
||||
* {@link MessageExtractor#getViewables(com.fsck.k9.mail.Part, java.util.List)}
|
||||
* {@link MessageExtractor#findViewablesAndAttachments(com.fsck.k9.mail.Part, java.util.List)}
|
||||
*
|
||||
* @see Viewable.Text
|
||||
* @see Viewable.Html
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.fsck.k9.mailstore;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -21,15 +22,16 @@ import com.fsck.k9.mail.internet.MimeMessageHelper;
|
|||
import com.fsck.k9.mail.internet.MimeMultipart;
|
||||
import com.fsck.k9.mail.internet.TextBody;
|
||||
import com.fsck.k9.mail.internet.Viewable;
|
||||
import com.fsck.k9.mailstore.MessageViewInfoExtractor.ViewableExtractedText;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static com.fsck.k9.mailstore.LocalMessageExtractor.extractTextAndAttachments;
|
||||
import static com.fsck.k9.mailstore.MessageViewInfoExtractor.extractTextFromViewables;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LocalMessageExtractorTest {
|
||||
public class MessageViewInfoExtractorTest {
|
||||
|
||||
@Test
|
||||
public void testSimplePlainTextMessage() throws MessagingException {
|
||||
|
@ -43,10 +45,11 @@ public class LocalMessageExtractorTest {
|
|||
MimeMessageHelper.setBody(message, body);
|
||||
|
||||
// Extract text
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
List<Viewable> viewables = MessageExtractor.getViewables(message, attachments);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
|
||||
viewables, attachments);
|
||||
List<Part> outputNonViewableParts = new ArrayList<Part>();
|
||||
ArrayList<Viewable> outputViewableParts = new ArrayList<>();
|
||||
MessageExtractor.findViewablesAndAttachments(message, outputViewableParts, outputNonViewableParts);
|
||||
ViewableExtractedText container = extractTextFromViewables(InstrumentationRegistry.getTargetContext(),
|
||||
outputViewableParts);
|
||||
|
||||
String expectedText = bodyText;
|
||||
String expectedHtml =
|
||||
|
@ -72,9 +75,10 @@ public class LocalMessageExtractorTest {
|
|||
|
||||
// Extract text
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
List<Viewable> viewables = MessageExtractor.getViewables(message, attachments);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
|
||||
viewables, attachments);
|
||||
ArrayList<Viewable> outputViewableParts = new ArrayList<>();
|
||||
MessageExtractor.findViewablesAndAttachments(message, outputViewableParts, attachments);
|
||||
ViewableExtractedText container = extractTextFromViewables(InstrumentationRegistry.getTargetContext(),
|
||||
outputViewableParts);
|
||||
|
||||
String expectedText = "K-9 Mail rocks :>";
|
||||
String expectedHtml =
|
||||
|
@ -105,10 +109,11 @@ public class LocalMessageExtractorTest {
|
|||
MimeMessageHelper.setBody(message, multipart);
|
||||
|
||||
// Extract text
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
List<Viewable> viewables = MessageExtractor.getViewables(message, attachments);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
|
||||
viewables, attachments);
|
||||
List<Part> outputNonViewableParts = new ArrayList<Part>();
|
||||
ArrayList<Viewable> outputViewableParts = new ArrayList<>();
|
||||
MessageExtractor.findViewablesAndAttachments(message, outputViewableParts, outputNonViewableParts);
|
||||
ViewableExtractedText container = extractTextFromViewables(InstrumentationRegistry.getTargetContext(),
|
||||
outputViewableParts);
|
||||
|
||||
String expectedText =
|
||||
bodyText1 + "\r\n\r\n" +
|
||||
|
@ -165,10 +170,11 @@ public class LocalMessageExtractorTest {
|
|||
MimeMessageHelper.setBody(message, multipart);
|
||||
|
||||
// Extract text
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
List<Viewable> viewables = MessageExtractor.getViewables(message, attachments);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
|
||||
viewables, attachments);
|
||||
List<Part> outputNonViewableParts = new ArrayList<Part>();
|
||||
ArrayList<Viewable> outputViewableParts = new ArrayList<>();
|
||||
MessageExtractor.findViewablesAndAttachments(message, outputViewableParts, outputNonViewableParts);
|
||||
ViewableExtractedText container = extractTextFromViewables(InstrumentationRegistry.getTargetContext(),
|
||||
outputViewableParts);
|
||||
|
||||
String expectedText =
|
||||
bodyText +
|
|
@ -39,7 +39,6 @@ import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener;
|
|||
import com.fsck.k9.activity.setup.AccountSettings;
|
||||
import com.fsck.k9.activity.setup.FolderSettings;
|
||||
import com.fsck.k9.activity.setup.Prefs;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.MessageListFragment;
|
||||
import com.fsck.k9.fragment.MessageListFragment.MessageListFragmentListener;
|
||||
import com.fsck.k9.preferences.StorageEditor;
|
||||
|
@ -1406,21 +1405,6 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReply(LocalMessage message, PgpData pgpData) {
|
||||
MessageActions.actionReply(this, message, false, pgpData.getDecryptedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplyAll(LocalMessage message, PgpData pgpData) {
|
||||
MessageActions.actionReply(this, message, true, pgpData.getDecryptedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onForward(LocalMessage mMessage, PgpData mPgpData) {
|
||||
MessageActions.actionForward(this, mMessage, mPgpData.getDecryptedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNextMessageOrReturn() {
|
||||
if (K9.messageViewReturnToList() || !showLogicalNextMessage()) {
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
package com.fsck.k9.crypto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
||||
public class PgpData implements Serializable {
|
||||
private static final long serialVersionUID = 6314045536470848410L;
|
||||
protected long mEncryptionKeyIds[] = null;
|
||||
protected long mSignatureKeyId = 0;
|
||||
protected String mSignatureUserId = null;
|
||||
protected boolean mSignatureSuccess = false;
|
||||
protected boolean mSignatureUnknown = false;
|
||||
protected String mDecryptedData = null;
|
||||
protected String mEncryptedData = null;
|
||||
|
||||
// new API
|
||||
protected OpenPgpSignatureResult mSignatureResult;
|
||||
|
||||
public OpenPgpSignatureResult getSignatureResult() {
|
||||
return mSignatureResult;
|
||||
}
|
||||
|
||||
public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
|
||||
this.mSignatureResult = signatureResult;
|
||||
}
|
||||
|
||||
public void setSignatureKeyId(long keyId) {
|
||||
mSignatureKeyId = keyId;
|
||||
}
|
||||
|
||||
public long getSignatureKeyId() {
|
||||
return mSignatureKeyId;
|
||||
}
|
||||
|
||||
public void setEncryptionKeys(long keyIds[]) {
|
||||
mEncryptionKeyIds = keyIds;
|
||||
}
|
||||
|
||||
public long[] getEncryptionKeys() {
|
||||
return mEncryptionKeyIds;
|
||||
}
|
||||
|
||||
public boolean hasSignatureKey() {
|
||||
return mSignatureKeyId != 0;
|
||||
}
|
||||
|
||||
public boolean hasEncryptionKeys() {
|
||||
return (mEncryptionKeyIds != null) && (mEncryptionKeyIds.length > 0);
|
||||
}
|
||||
|
||||
public String getEncryptedData() {
|
||||
return mEncryptedData;
|
||||
}
|
||||
|
||||
public void setEncryptedData(String data) {
|
||||
mEncryptedData = data;
|
||||
}
|
||||
|
||||
public String getDecryptedData() {
|
||||
return mDecryptedData;
|
||||
}
|
||||
|
||||
public void setDecryptedData(String data) {
|
||||
mDecryptedData = data;
|
||||
}
|
||||
|
||||
public void setSignatureUserId(String userId) {
|
||||
mSignatureUserId = userId;
|
||||
}
|
||||
|
||||
public String getSignatureUserId() {
|
||||
return mSignatureUserId;
|
||||
}
|
||||
|
||||
public boolean getSignatureSuccess() {
|
||||
return mSignatureSuccess;
|
||||
}
|
||||
|
||||
public void setSignatureSuccess(boolean success) {
|
||||
mSignatureSuccess = success;
|
||||
}
|
||||
|
||||
public boolean getSignatureUnknown() {
|
||||
return mSignatureUnknown;
|
||||
}
|
||||
|
||||
public void setSignatureUnknown(boolean unknown) {
|
||||
mSignatureUnknown = unknown;
|
||||
}
|
||||
}
|
|
@ -8,12 +8,13 @@ import com.fsck.k9.mail.Message;
|
|||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MessageExtractor;
|
||||
import com.fsck.k9.mail.internet.Viewable;
|
||||
|
||||
|
||||
class AttachmentCounter {
|
||||
public int getAttachmentCount(Message message) throws MessagingException {
|
||||
List<Part> attachments = new ArrayList<Part>();
|
||||
MessageExtractor.getViewables(message, attachments);
|
||||
List<Part> attachments = new ArrayList<>();
|
||||
MessageExtractor.findViewablesAndAttachments(message, new ArrayList<Viewable>(), attachments);
|
||||
|
||||
return attachments.size();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
package com.fsck.k9.mailstore;
|
||||
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.fsck.k9.mail.internet.MimeBodyPart;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
||||
|
||||
public final class CryptoResultAnnotation {
|
||||
@NonNull private final CryptoError errorType;
|
||||
private final MimeBodyPart replacementData;
|
||||
|
||||
private final OpenPgpDecryptionResult openPgpDecryptionResult;
|
||||
private final OpenPgpSignatureResult openPgpSignatureResult;
|
||||
private final OpenPgpError openPgpError;
|
||||
private final PendingIntent openPgpPendingIntent;
|
||||
|
||||
private CryptoResultAnnotation(@NonNull CryptoError errorType, MimeBodyPart replacementData,
|
||||
OpenPgpDecryptionResult openPgpDecryptionResult,
|
||||
OpenPgpSignatureResult openPgpSignatureResult,
|
||||
PendingIntent openPgpPendingIntent, OpenPgpError openPgpError) {
|
||||
this.errorType = errorType;
|
||||
this.replacementData = replacementData;
|
||||
|
||||
this.openPgpDecryptionResult = openPgpDecryptionResult;
|
||||
this.openPgpSignatureResult = openPgpSignatureResult;
|
||||
this.openPgpPendingIntent = openPgpPendingIntent;
|
||||
this.openPgpError = openPgpError;
|
||||
}
|
||||
|
||||
|
||||
public static CryptoResultAnnotation createOpenPgpResultAnnotation(OpenPgpDecryptionResult decryptionResult,
|
||||
OpenPgpSignatureResult signatureResult, PendingIntent pendingIntent, MimeBodyPart replacementPart) {
|
||||
return new CryptoResultAnnotation(CryptoError.NONE, replacementPart,
|
||||
decryptionResult, signatureResult, pendingIntent, null);
|
||||
}
|
||||
|
||||
public static CryptoResultAnnotation createErrorAnnotation(CryptoError error, MimeBodyPart replacementData) {
|
||||
if (error == CryptoError.NONE) {
|
||||
throw new AssertionError("CryptoError must be actual error state!");
|
||||
}
|
||||
return new CryptoResultAnnotation(error, replacementData, null, null, null, null);
|
||||
}
|
||||
|
||||
public static CryptoResultAnnotation createOpenPgpErrorAnnotation(OpenPgpError error) {
|
||||
return new CryptoResultAnnotation(CryptoError.OPENPGP_API_RETURNED_ERROR, null, null, null, null, error);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OpenPgpDecryptionResult getOpenPgpDecryptionResult() {
|
||||
return openPgpDecryptionResult;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OpenPgpSignatureResult getOpenPgpSignatureResult() {
|
||||
return openPgpSignatureResult;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PendingIntent getOpenPgpPendingIntent() {
|
||||
return openPgpPendingIntent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OpenPgpError getOpenPgpError() {
|
||||
return openPgpError;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public CryptoError getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public boolean hasReplacementData() {
|
||||
return replacementData != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MimeBodyPart getReplacementData() {
|
||||
return replacementData;
|
||||
}
|
||||
|
||||
|
||||
public enum CryptoError {
|
||||
NONE,
|
||||
OPENPGP_API_RETURNED_ERROR,
|
||||
SIGNED_BUT_INCOMPLETE,
|
||||
ENCRYPTED_BUT_INCOMPLETE,
|
||||
SIGNED_BUT_UNSUPPORTED,
|
||||
ENCRYPTED_BUT_UNSUPPORTED,
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@ import com.fsck.k9.mail.internet.SizeAware;
|
|||
import com.fsck.k9.mail.message.MessageHeaderParser;
|
||||
import com.fsck.k9.mailstore.LockableDatabase.DbCallback;
|
||||
import com.fsck.k9.mailstore.LockableDatabase.WrappedException;
|
||||
import com.fsck.k9.message.extractors.AttachmentInfoExtractor;
|
||||
import com.fsck.k9.message.extractors.MessagePreviewCreator;
|
||||
import com.fsck.k9.message.extractors.PreviewResult;
|
||||
import com.fsck.k9.message.extractors.PreviewResult.PreviewType;
|
||||
|
@ -1400,7 +1401,7 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
|
|||
}
|
||||
|
||||
private void missingPartToContentValues(ContentValues cv, Part part) throws MessagingException {
|
||||
AttachmentViewInfo attachment = LocalMessageExtractor.extractAttachmentInfo(part);
|
||||
AttachmentViewInfo attachment = AttachmentInfoExtractor.extractAttachmentInfo(part);
|
||||
cv.put("display_name", attachment.displayName);
|
||||
cv.put("data_location", DataLocation.MISSING);
|
||||
cv.put("decoded_body_size", attachment.size);
|
||||
|
@ -1412,7 +1413,7 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
|
|||
|
||||
private File leafPartToContentValues(ContentValues cv, Part part, Body body)
|
||||
throws MessagingException, IOException {
|
||||
AttachmentViewInfo attachment = LocalMessageExtractor.extractAttachmentInfo(part);
|
||||
AttachmentViewInfo attachment = AttachmentInfoExtractor.extractAttachmentInfo(part);
|
||||
cv.put("display_name", attachment.displayName);
|
||||
|
||||
String encoding = getTransferEncoding(part);
|
||||
|
|
|
@ -22,11 +22,11 @@ public class MessageViewInfo {
|
|||
public final String text;
|
||||
public final Part rootPart;
|
||||
public final List<AttachmentViewInfo> attachments;
|
||||
public final OpenPgpResultAnnotation cryptoAnnotation;
|
||||
public final CryptoResultAnnotation cryptoAnnotation;
|
||||
|
||||
|
||||
MessageViewContainer(String text, Part rootPart, List<AttachmentViewInfo> attachments,
|
||||
OpenPgpResultAnnotation cryptoAnnotation) {
|
||||
CryptoResultAnnotation cryptoAnnotation) {
|
||||
this.text = text;
|
||||
this.rootPart = rootPart;
|
||||
this.attachments = attachments;
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package com.fsck.k9.mailstore;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.helper.HtmlConverter;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Body;
|
||||
import com.fsck.k9.mail.BodyPart;
|
||||
|
@ -11,21 +17,13 @@ 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.helper.HtmlConverter;
|
||||
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.MessageViewInfo.MessageViewContainer;
|
||||
import com.fsck.k9.provider.AttachmentProvider;
|
||||
import com.fsck.k9.provider.K9FileProvider;
|
||||
import com.fsck.k9.message.extractors.AttachmentInfoExtractor;
|
||||
import com.fsck.k9.ui.crypto.MessageCryptoAnnotations;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.fsck.k9.mail.internet.MimeUtility.getHeaderParameter;
|
||||
import static com.fsck.k9.mail.internet.Viewable.Alternative;
|
||||
import static com.fsck.k9.mail.internet.Viewable.Html;
|
||||
|
@ -33,7 +31,7 @@ import static com.fsck.k9.mail.internet.Viewable.MessageHeader;
|
|||
import static com.fsck.k9.mail.internet.Viewable.Text;
|
||||
import static com.fsck.k9.mail.internet.Viewable.Textual;
|
||||
|
||||
public class LocalMessageExtractor {
|
||||
public class MessageViewInfoExtractor {
|
||||
private static final String TEXT_DIVIDER =
|
||||
"------------------------------------------------------------------------";
|
||||
private static final int TEXT_DIVIDER_LENGTH = TEXT_DIVIDER.length();
|
||||
|
@ -41,23 +39,99 @@ 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 OpenPgpResultAnnotation NO_ANNOTATIONS = null;
|
||||
private static final CryptoResultAnnotation NO_ANNOTATIONS = null;
|
||||
|
||||
private MessageViewInfoExtractor() {}
|
||||
|
||||
public static MessageViewInfo extractMessageForView(Context context,
|
||||
Message message, MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
// TODO note that we will move away from ViewableContainers, so this method is subject to changes!
|
||||
|
||||
// 1. break mime structure on encryption/signature boundaries
|
||||
List<Part> parts = getCryptPieces(message, annotations);
|
||||
|
||||
// 2. extract viewables/attachments of parts
|
||||
ArrayList<MessageViewContainer> containers = new ArrayList<>();
|
||||
for (Part part : parts) {
|
||||
CryptoResultAnnotation pgpAnnotation = annotations.get(part);
|
||||
|
||||
// TODO properly handle decrypted data part - this just replaces the part
|
||||
if (pgpAnnotation != NO_ANNOTATIONS && pgpAnnotation.hasReplacementData()) {
|
||||
part = pgpAnnotation.getReplacementData();
|
||||
}
|
||||
|
||||
ArrayList<Viewable> viewableParts = new ArrayList<>();
|
||||
ArrayList<Part> attachments = new ArrayList<>();
|
||||
MessageExtractor.findViewablesAndAttachments(part, viewableParts, attachments);
|
||||
|
||||
// 3. parse viewables into html string
|
||||
ViewableExtractedText viewable = MessageViewInfoExtractor.extractTextFromViewables(context, viewableParts);
|
||||
List<AttachmentViewInfo> attachmentInfos = AttachmentInfoExtractor.extractAttachmentInfos(context, attachments);
|
||||
|
||||
MessageViewContainer messageViewContainer =
|
||||
new MessageViewContainer(viewable.html, part, attachmentInfos, pgpAnnotation);
|
||||
|
||||
containers.add(messageViewContainer);
|
||||
}
|
||||
|
||||
return new MessageViewInfo(containers, message);
|
||||
}
|
||||
|
||||
public static List<Part> getCryptPieces(Message message, MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
|
||||
// TODO make sure this method does what it is supposed to
|
||||
/* This method returns a list of mime parts which are to be parsed into
|
||||
* individual MessageViewContainers for display, which each have their
|
||||
* own crypto header. This means parts should be individual for each
|
||||
* multipart/encrypted, multipart/signed, or a multipart/* which does
|
||||
* not contain children of the former types.
|
||||
*/
|
||||
|
||||
ArrayList<Part> parts = new ArrayList<>();
|
||||
if (!getCryptSubPieces(message, parts, annotations)) {
|
||||
parts.add(message);
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
public static boolean getCryptSubPieces(Part part, ArrayList<Part> parts,
|
||||
MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
|
||||
Body body = part.getBody();
|
||||
if (body instanceof Multipart) {
|
||||
Multipart multi = (Multipart) body;
|
||||
if (MimeUtility.isSameMimeType(part.getMimeType(), "multipart/mixed")) {
|
||||
boolean foundSome = false;
|
||||
for (BodyPart sub : multi.getBodyParts()) {
|
||||
foundSome |= getCryptSubPieces(sub, parts, annotations);
|
||||
}
|
||||
if (!foundSome) {
|
||||
parts.add(part);
|
||||
return true;
|
||||
}
|
||||
} else if (annotations.has(part)) {
|
||||
parts.add(part);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private LocalMessageExtractor() {}
|
||||
/**
|
||||
* Extract the viewable textual parts of a message and return the rest as attachments.
|
||||
*
|
||||
* @param context A {@link android.content.Context} instance that will be used to get localized strings.
|
||||
* @return A {@link ViewableContainer} instance containing the textual parts of the message as
|
||||
* @return A {@link ViewableExtractedText} instance containing the textual parts of the message as
|
||||
* plain text and HTML, and a list of message parts considered attachments.
|
||||
*
|
||||
* @throws com.fsck.k9.mail.MessagingException
|
||||
* In case of an error.
|
||||
*/
|
||||
public static ViewableContainer extractTextAndAttachments(Context context, List<Viewable> viewables,
|
||||
List<Part> attachments) throws MessagingException {
|
||||
@VisibleForTesting
|
||||
static ViewableExtractedText extractTextFromViewables(Context context, List<Viewable> viewables)
|
||||
throws MessagingException {
|
||||
try {
|
||||
|
||||
// Collect all viewable parts
|
||||
|
||||
/*
|
||||
|
@ -120,7 +194,7 @@ public class LocalMessageExtractor {
|
|||
}
|
||||
}
|
||||
|
||||
return new ViewableContainer(text.toString(), html.toString(), attachments);
|
||||
return new ViewableExtractedText(text.toString(), html.toString());
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Couldn't extract viewable parts", e);
|
||||
}
|
||||
|
@ -142,8 +216,7 @@ public class LocalMessageExtractor {
|
|||
*
|
||||
* @return The contents of the supplied viewable instance as HTML.
|
||||
*/
|
||||
private static StringBuilder buildHtml(Viewable viewable, boolean prependDivider)
|
||||
{
|
||||
private static StringBuilder buildHtml(Viewable viewable, boolean prependDivider) {
|
||||
StringBuilder html = new StringBuilder();
|
||||
if (viewable instanceof Textual) {
|
||||
Part part = ((Textual)viewable).getPart();
|
||||
|
@ -174,8 +247,7 @@ public class LocalMessageExtractor {
|
|||
return html;
|
||||
}
|
||||
|
||||
private static StringBuilder buildText(Viewable viewable, boolean prependDivider)
|
||||
{
|
||||
private static StringBuilder buildText(Viewable viewable, boolean prependDivider) {
|
||||
StringBuilder text = new StringBuilder();
|
||||
if (viewable instanceof Textual) {
|
||||
Part part = ((Textual)viewable).getPart();
|
||||
|
@ -418,167 +490,14 @@ public class LocalMessageExtractor {
|
|||
html.append("</td></tr>");
|
||||
}
|
||||
|
||||
public static MessageViewInfo decodeMessageForView(Context context,
|
||||
Message message, MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
@VisibleForTesting
|
||||
static class ViewableExtractedText {
|
||||
public final String text;
|
||||
public final String html;
|
||||
|
||||
// 1. break mime structure on encryption/signature boundaries
|
||||
List<Part> parts = getCryptPieces(message, annotations);
|
||||
|
||||
// 2. extract viewables/attachments of parts
|
||||
ArrayList<MessageViewContainer> containers = new ArrayList<>();
|
||||
for (Part part : parts) {
|
||||
OpenPgpResultAnnotation pgpAnnotation = annotations.get(part);
|
||||
|
||||
// TODO properly handle decrypted data part - this just replaces the part
|
||||
if (pgpAnnotation != NO_ANNOTATIONS && pgpAnnotation.hasOutputData()) {
|
||||
part = pgpAnnotation.getOutputData();
|
||||
}
|
||||
|
||||
ArrayList<Part> attachments = new ArrayList<>();
|
||||
List<Viewable> viewables = MessageExtractor.getViewables(part, attachments);
|
||||
|
||||
// 3. parse viewables into html string
|
||||
ViewableContainer viewable = LocalMessageExtractor.extractTextAndAttachments(context, viewables,
|
||||
attachments);
|
||||
List<AttachmentViewInfo> attachmentInfos = extractAttachmentInfos(context, attachments);
|
||||
|
||||
MessageViewContainer messageViewContainer =
|
||||
new MessageViewContainer(viewable.html, part, attachmentInfos, pgpAnnotation);
|
||||
|
||||
containers.add(messageViewContainer);
|
||||
public ViewableExtractedText(String text, String html) {
|
||||
this.text = text;
|
||||
this.html = html;
|
||||
}
|
||||
|
||||
return new MessageViewInfo(containers, message);
|
||||
}
|
||||
|
||||
public static List<Part> getCryptPieces(Message message, MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
|
||||
// TODO make sure this method does what it is supposed to
|
||||
/* This method returns a list of mime parts which are to be parsed into
|
||||
* individual MessageViewContainers for display, which each have their
|
||||
* own crypto header. This means parts should be individual for each
|
||||
* multipart/encrypted, multipart/signed, or a multipart/* which does
|
||||
* not contain children of the former types.
|
||||
*/
|
||||
|
||||
|
||||
ArrayList<Part> parts = new ArrayList<>();
|
||||
if (!getCryptSubPieces(message, parts, annotations)) {
|
||||
parts.add(message);
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
public static boolean getCryptSubPieces(Part part, ArrayList<Part> parts,
|
||||
MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
|
||||
Body body = part.getBody();
|
||||
if (body instanceof Multipart) {
|
||||
Multipart multi = (Multipart) body;
|
||||
if (MimeUtility.isSameMimeType(part.getMimeType(), "multipart/mixed")) {
|
||||
boolean foundSome = false;
|
||||
for (BodyPart sub : multi.getBodyParts()) {
|
||||
foundSome |= getCryptSubPieces(sub, parts, annotations);
|
||||
}
|
||||
if (!foundSome) {
|
||||
parts.add(part);
|
||||
return true;
|
||||
}
|
||||
} else if (annotations.has(part)) {
|
||||
parts.add(part);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<AttachmentViewInfo> extractAttachmentInfos(Context context, List<Part> attachmentParts)
|
||||
throws MessagingException {
|
||||
|
||||
List<AttachmentViewInfo> attachments = new ArrayList<>();
|
||||
for (Part part : attachmentParts) {
|
||||
attachments.add(extractAttachmentInfo(context, part));
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public static AttachmentViewInfo extractAttachmentInfo(Context context, Part part) throws MessagingException {
|
||||
if (part instanceof LocalPart) {
|
||||
LocalPart localPart = (LocalPart) part;
|
||||
String accountUuid = localPart.getAccountUuid();
|
||||
long messagePartId = localPart.getId();
|
||||
String mimeType = part.getMimeType();
|
||||
String displayName = localPart.getDisplayName();
|
||||
long size = localPart.getSize();
|
||||
boolean firstClassAttachment = localPart.isFirstClassAttachment();
|
||||
Uri uri = AttachmentProvider.getAttachmentUri(accountUuid, messagePartId);
|
||||
|
||||
return new AttachmentViewInfo(mimeType, displayName, size, uri, firstClassAttachment, part);
|
||||
} else {
|
||||
Body body = part.getBody();
|
||||
if (body instanceof DecryptedTempFileBody) {
|
||||
DecryptedTempFileBody decryptedTempFileBody = (DecryptedTempFileBody) body;
|
||||
File file = decryptedTempFileBody.getFile();
|
||||
Uri uri = K9FileProvider.getUriForFile(context, file, part.getMimeType());
|
||||
long size = file.length();
|
||||
return extractAttachmentInfo(part, uri, size);
|
||||
} else {
|
||||
throw new RuntimeException("Not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AttachmentViewInfo extractAttachmentInfo(Part part) throws MessagingException {
|
||||
return extractAttachmentInfo(part, Uri.EMPTY, AttachmentViewInfo.UNKNOWN_SIZE);
|
||||
}
|
||||
|
||||
private static AttachmentViewInfo extractAttachmentInfo(Part part, Uri uri, long size) throws MessagingException {
|
||||
boolean firstClassAttachment = true;
|
||||
|
||||
String mimeType = part.getMimeType();
|
||||
String contentTypeHeader = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
|
||||
String name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
||||
if (name == null) {
|
||||
name = MimeUtility.getHeaderParameter(contentTypeHeader, "name");
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
firstClassAttachment = false;
|
||||
String extension = MimeUtility.getExtensionByMimeType(mimeType);
|
||||
name = "noname" + ((extension != null) ? "." + extension : "");
|
||||
}
|
||||
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Only show them if the user pressed the button to show more
|
||||
// attachments.
|
||||
if (contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)") &&
|
||||
part.getHeader(MimeHeader.HEADER_CONTENT_ID).length > 0) {
|
||||
firstClassAttachment = false;
|
||||
}
|
||||
|
||||
long attachmentSize = extractAttachmentSize(contentDisposition, size);
|
||||
|
||||
return new AttachmentViewInfo(mimeType, name, attachmentSize, uri, firstClassAttachment, part);
|
||||
}
|
||||
|
||||
private static long extractAttachmentSize(String contentDisposition, long size) {
|
||||
if (size != AttachmentViewInfo.UNKNOWN_SIZE) {
|
||||
return size;
|
||||
}
|
||||
|
||||
long result = AttachmentViewInfo.UNKNOWN_SIZE;
|
||||
String sizeParam = MimeUtility.getHeaderParameter(contentDisposition, "size");
|
||||
if (sizeParam != null) {
|
||||
try {
|
||||
result = Integer.parseInt(sizeParam);
|
||||
} catch (NumberFormatException e) { /* ignore */ }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
package com.fsck.k9.mailstore;
|
||||
|
||||
|
||||
import android.app.PendingIntent;
|
||||
|
||||
import com.fsck.k9.mail.internet.MimeBodyPart;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
||||
|
||||
public final class OpenPgpResultAnnotation {
|
||||
private OpenPgpDecryptionResult decryptionResult;
|
||||
private OpenPgpSignatureResult signatureResult;
|
||||
private OpenPgpError error;
|
||||
private CryptoError errorType = CryptoError.NONE;
|
||||
private PendingIntent pendingIntent;
|
||||
private MimeBodyPart outputData;
|
||||
|
||||
public OpenPgpDecryptionResult getDecryptionResult() {
|
||||
return decryptionResult;
|
||||
}
|
||||
|
||||
public void setDecryptionResult(OpenPgpDecryptionResult decryptionResult) {
|
||||
this.decryptionResult = decryptionResult;
|
||||
}
|
||||
|
||||
public OpenPgpSignatureResult getSignatureResult() {
|
||||
return signatureResult;
|
||||
}
|
||||
|
||||
public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
|
||||
this.signatureResult = signatureResult;
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
return pendingIntent;
|
||||
}
|
||||
|
||||
public void setPendingIntent(PendingIntent pendingIntent) {
|
||||
this.pendingIntent = pendingIntent;
|
||||
}
|
||||
|
||||
public OpenPgpError getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(OpenPgpError error) {
|
||||
this.error = error;
|
||||
setErrorType(CryptoError.CRYPTO_API_RETURNED_ERROR);
|
||||
}
|
||||
|
||||
public CryptoError getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public void setErrorType(CryptoError errorType) {
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
public boolean hasOutputData() {
|
||||
return outputData != null;
|
||||
}
|
||||
|
||||
public void setOutputData(MimeBodyPart outputData) {
|
||||
this.outputData = outputData;
|
||||
}
|
||||
|
||||
public MimeBodyPart getOutputData() {
|
||||
return outputData;
|
||||
}
|
||||
|
||||
|
||||
public enum CryptoError {
|
||||
NONE,
|
||||
CRYPTO_API_RETURNED_ERROR,
|
||||
SIGNED_BUT_INCOMPLETE,
|
||||
ENCRYPTED_BUT_INCOMPLETE
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package com.fsck.k9.mailstore;
|
||||
|
||||
import com.fsck.k9.mail.Part;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Store viewable text of a message as plain text and HTML, and the parts considered
|
||||
* attachments.
|
||||
*
|
||||
* @see LocalMessageExtractor#extractTextAndAttachments(android.content.Context, com.fsck.k9.mail.Message)
|
||||
*/
|
||||
public class ViewableContainer {
|
||||
/**
|
||||
* The viewable text of the message in plain text.
|
||||
*/
|
||||
public final String text;
|
||||
|
||||
/**
|
||||
* The viewable text of the message in HTML.
|
||||
*/
|
||||
public final String html;
|
||||
|
||||
/**
|
||||
* The parts of the message considered attachments (everything not viewable).
|
||||
*/
|
||||
public final List<Part> attachments;
|
||||
|
||||
public ViewableContainer(String text, String html, List<Part> attachments) {
|
||||
this.text = text;
|
||||
this.html = html;
|
||||
this.attachments = attachments;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package com.fsck.k9.message.extractors;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.fsck.k9.mail.Body;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeHeader;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import com.fsck.k9.mailstore.DecryptedTempFileBody;
|
||||
import com.fsck.k9.mailstore.LocalPart;
|
||||
import com.fsck.k9.provider.AttachmentProvider;
|
||||
import com.fsck.k9.provider.K9FileProvider;
|
||||
|
||||
|
||||
public class AttachmentInfoExtractor {
|
||||
public static List<AttachmentViewInfo> extractAttachmentInfos(Context context, List<Part> attachmentParts)
|
||||
throws MessagingException {
|
||||
|
||||
List<AttachmentViewInfo> attachments = new ArrayList<>();
|
||||
for (Part part : attachmentParts) {
|
||||
attachments.add(extractAttachmentInfo(context, part));
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public static AttachmentViewInfo extractAttachmentInfo(Context context, Part part) throws MessagingException {
|
||||
if (part instanceof LocalPart) {
|
||||
LocalPart localPart = (LocalPart) part;
|
||||
String accountUuid = localPart.getAccountUuid();
|
||||
long messagePartId = localPart.getId();
|
||||
String mimeType = part.getMimeType();
|
||||
String displayName = localPart.getDisplayName();
|
||||
long size = localPart.getSize();
|
||||
boolean firstClassAttachment = localPart.isFirstClassAttachment();
|
||||
Uri uri = AttachmentProvider.getAttachmentUri(accountUuid, messagePartId);
|
||||
|
||||
return new AttachmentViewInfo(mimeType, displayName, size, uri, firstClassAttachment, part);
|
||||
} else {
|
||||
Body body = part.getBody();
|
||||
if (body instanceof DecryptedTempFileBody) {
|
||||
DecryptedTempFileBody decryptedTempFileBody = (DecryptedTempFileBody) body;
|
||||
File file = decryptedTempFileBody.getFile();
|
||||
Uri uri = K9FileProvider.getUriForFile(context, file, part.getMimeType());
|
||||
long size = file.length();
|
||||
return extractAttachmentInfo(part, uri, size);
|
||||
} else {
|
||||
throw new RuntimeException("Not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AttachmentViewInfo extractAttachmentInfo(Part part) throws MessagingException {
|
||||
return extractAttachmentInfo(part, Uri.EMPTY, AttachmentViewInfo.UNKNOWN_SIZE);
|
||||
}
|
||||
|
||||
private static AttachmentViewInfo extractAttachmentInfo(Part part, Uri uri, long size) throws MessagingException {
|
||||
boolean firstClassAttachment = true;
|
||||
|
||||
String mimeType = part.getMimeType();
|
||||
String contentTypeHeader = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
|
||||
String name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
||||
if (name == null) {
|
||||
name = MimeUtility.getHeaderParameter(contentTypeHeader, "name");
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
firstClassAttachment = false;
|
||||
String extension = MimeUtility.getExtensionByMimeType(mimeType);
|
||||
name = "noname" + ((extension != null) ? "." + extension : "");
|
||||
}
|
||||
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Only show them if the user pressed the button to show more
|
||||
// attachments.
|
||||
if (contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)") &&
|
||||
part.getHeader(MimeHeader.HEADER_CONTENT_ID).length > 0) {
|
||||
firstClassAttachment = false;
|
||||
}
|
||||
|
||||
long attachmentSize = extractAttachmentSize(contentDisposition, size);
|
||||
|
||||
return new AttachmentViewInfo(mimeType, name, attachmentSize, uri, firstClassAttachment, part);
|
||||
}
|
||||
|
||||
private static long extractAttachmentSize(String contentDisposition, long size) {
|
||||
if (size != AttachmentViewInfo.UNKNOWN_SIZE) {
|
||||
return size;
|
||||
}
|
||||
|
||||
long result = AttachmentViewInfo.UNKNOWN_SIZE;
|
||||
String sizeParam = MimeUtility.getHeaderParameter(contentDisposition, "size");
|
||||
if (sizeParam != null) {
|
||||
try {
|
||||
result = Integer.parseInt(sizeParam);
|
||||
} catch (NumberFormatException e) { /* ignore */ }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -4,21 +4,21 @@ package com.fsck.k9.ui.crypto;
|
|||
import java.util.HashMap;
|
||||
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mailstore.OpenPgpResultAnnotation;
|
||||
import com.fsck.k9.mailstore.CryptoResultAnnotation;
|
||||
|
||||
|
||||
public class MessageCryptoAnnotations {
|
||||
private HashMap<Part, OpenPgpResultAnnotation> annotations = new HashMap<Part, OpenPgpResultAnnotation>();
|
||||
private HashMap<Part, CryptoResultAnnotation> annotations = new HashMap<Part, CryptoResultAnnotation>();
|
||||
|
||||
MessageCryptoAnnotations() {
|
||||
// Package-private constructor
|
||||
}
|
||||
|
||||
void put(Part part, OpenPgpResultAnnotation annotation) {
|
||||
void put(Part part, CryptoResultAnnotation annotation) {
|
||||
annotations.put(part, annotation);
|
||||
}
|
||||
|
||||
public OpenPgpResultAnnotation get(Part part) {
|
||||
public CryptoResultAnnotation get(Part part) {
|
||||
return annotations.get(part);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,8 @@ import com.fsck.k9.mail.internet.TextBody;
|
|||
import com.fsck.k9.mailstore.DecryptStreamParser;
|
||||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.MessageHelper;
|
||||
import com.fsck.k9.mailstore.OpenPgpResultAnnotation;
|
||||
import com.fsck.k9.mailstore.OpenPgpResultAnnotation.CryptoError;
|
||||
import org.openintents.openpgp.IOpenPgpService;
|
||||
import com.fsck.k9.mailstore.CryptoResultAnnotation;
|
||||
import com.fsck.k9.mailstore.CryptoResultAnnotation.CryptoError;
|
||||
import org.openintents.openpgp.IOpenPgpService2;
|
||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
|
@ -58,7 +57,7 @@ public class MessageCryptoHelper {
|
|||
private final Account account;
|
||||
private LocalMessage message;
|
||||
|
||||
private Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<CryptoPart>();
|
||||
private Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>();
|
||||
private OpenPgpApi openPgpApi;
|
||||
private CryptoPart currentCryptoPart;
|
||||
private Intent currentCryptoResult;
|
||||
|
@ -109,10 +108,8 @@ public class MessageCryptoHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private void addErrorAnnotation(Part part, CryptoError error, MimeBodyPart outputData) {
|
||||
OpenPgpResultAnnotation annotation = new OpenPgpResultAnnotation();
|
||||
annotation.setErrorType(error);
|
||||
annotation.setOutputData(outputData);
|
||||
private void addErrorAnnotation(Part part, CryptoError error, MimeBodyPart replacementPart) {
|
||||
CryptoResultAnnotation annotation = CryptoResultAnnotation.createErrorAnnotation(error, replacementPart);
|
||||
messageAnnotations.put(part, annotation);
|
||||
}
|
||||
|
||||
|
@ -411,11 +408,8 @@ public class MessageCryptoHelper {
|
|||
currentCryptoResult.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
|
||||
PendingIntent pendingIntent = currentCryptoResult.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
||||
|
||||
OpenPgpResultAnnotation resultAnnotation = new OpenPgpResultAnnotation();
|
||||
resultAnnotation.setOutputData(outputPart);
|
||||
resultAnnotation.setDecryptionResult(decryptionResult);
|
||||
resultAnnotation.setSignatureResult(signatureResult);
|
||||
resultAnnotation.setPendingIntent(pendingIntent);
|
||||
CryptoResultAnnotation resultAnnotation = CryptoResultAnnotation.createOpenPgpResultAnnotation(
|
||||
decryptionResult, signatureResult, pendingIntent, outputPart);
|
||||
|
||||
onCryptoSuccess(resultAnnotation);
|
||||
}
|
||||
|
@ -433,23 +427,22 @@ public class MessageCryptoHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private void onCryptoSuccess(OpenPgpResultAnnotation resultAnnotation) {
|
||||
addOpenPgpResultPartToMessage(resultAnnotation);
|
||||
private void onCryptoSuccess(CryptoResultAnnotation resultAnnotation) {
|
||||
addCryptoResultAnnotationToMessage(resultAnnotation);
|
||||
onCryptoFinished();
|
||||
}
|
||||
|
||||
private void addOpenPgpResultPartToMessage(OpenPgpResultAnnotation resultAnnotation) {
|
||||
Part part = currentCryptoPart.part;
|
||||
messageAnnotations.put(part, resultAnnotation);
|
||||
}
|
||||
|
||||
private void onCryptoFailed(OpenPgpError error) {
|
||||
OpenPgpResultAnnotation errorPart = new OpenPgpResultAnnotation();
|
||||
errorPart.setError(error);
|
||||
addOpenPgpResultPartToMessage(errorPart);
|
||||
CryptoResultAnnotation errorPart = CryptoResultAnnotation.createOpenPgpErrorAnnotation(error);
|
||||
addCryptoResultAnnotationToMessage(errorPart);
|
||||
onCryptoFinished();
|
||||
}
|
||||
|
||||
private void addCryptoResultAnnotationToMessage(CryptoResultAnnotation resultAnnotation) {
|
||||
Part part = currentCryptoPart.part;
|
||||
messageAnnotations.put(part, resultAnnotation);
|
||||
}
|
||||
|
||||
private void onCryptoFinished() {
|
||||
partsToDecryptOrVerify.removeFirst();
|
||||
decryptOrVerifyNextPart();
|
||||
|
|
|
@ -9,19 +9,19 @@ import android.widget.Toast;
|
|||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mailstore.LocalMessageExtractor;
|
||||
import com.fsck.k9.mailstore.MessageViewInfoExtractor;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.ui.crypto.MessageCryptoAnnotations;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
public class DecodeMessageLoader extends AsyncTaskLoader<MessageViewInfo> {
|
||||
public class LocalMessageExtractorLoader extends AsyncTaskLoader<MessageViewInfo> {
|
||||
private final Message message;
|
||||
private MessageViewInfo messageViewInfo;
|
||||
private MessageCryptoAnnotations annotations;
|
||||
|
||||
public DecodeMessageLoader(Context context, Message message, MessageCryptoAnnotations annotations) {
|
||||
public LocalMessageExtractorLoader(Context context, Message message, MessageCryptoAnnotations annotations) {
|
||||
super(context);
|
||||
this.message = message;
|
||||
this.annotations = annotations;
|
||||
|
@ -47,7 +47,7 @@ public class DecodeMessageLoader extends AsyncTaskLoader<MessageViewInfo> {
|
|||
@Override
|
||||
public MessageViewInfo loadInBackground() {
|
||||
try {
|
||||
return LocalMessageExtractor.decodeMessageForView(getContext(), message, annotations);
|
||||
return MessageViewInfoExtractor.extractMessageForView(getContext(), message, annotations);
|
||||
} catch (Exception e) {
|
||||
Log.e(K9.LOG_TAG, "Error while decoding message", e);
|
||||
return null;
|
|
@ -38,8 +38,8 @@ import com.fsck.k9.mail.MessagingException;
|
|||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo.MessageViewContainer;
|
||||
|
||||
import com.fsck.k9.mailstore.OpenPgpResultAnnotation;
|
||||
import com.fsck.k9.mailstore.OpenPgpResultAnnotation.CryptoError;
|
||||
import com.fsck.k9.mailstore.CryptoResultAnnotation;
|
||||
import com.fsck.k9.mailstore.CryptoResultAnnotation.CryptoError;
|
||||
import com.fsck.k9.view.K9WebViewClient;
|
||||
import com.fsck.k9.view.MessageHeader.OnLayoutChangedListener;
|
||||
import com.fsck.k9.view.MessageWebView;
|
||||
|
@ -443,7 +443,7 @@ public class MessageContainerView extends LinearLayout implements OnClickListene
|
|||
ViewStub openPgpHeaderStub = (ViewStub) findViewById(R.id.openpgp_header_stub);
|
||||
OpenPgpHeaderView openPgpHeaderView = (OpenPgpHeaderView) openPgpHeaderStub.inflate();
|
||||
|
||||
OpenPgpResultAnnotation cryptoAnnotation = messageViewContainer.cryptoAnnotation;
|
||||
CryptoResultAnnotation cryptoAnnotation = messageViewContainer.cryptoAnnotation;
|
||||
openPgpHeaderView.setOpenPgpData(cryptoAnnotation);
|
||||
openPgpHeaderView.setCallback(openPgpHeaderViewCallback);
|
||||
mSidebar.setVisibility(View.VISIBLE);
|
||||
|
@ -462,16 +462,16 @@ public class MessageContainerView extends LinearLayout implements OnClickListene
|
|||
}
|
||||
|
||||
private String getTextToDisplay(MessageViewContainer messageViewContainer) {
|
||||
OpenPgpResultAnnotation cryptoAnnotation = messageViewContainer.cryptoAnnotation;
|
||||
CryptoResultAnnotation cryptoAnnotation = messageViewContainer.cryptoAnnotation;
|
||||
if (cryptoAnnotation == null) {
|
||||
return messageViewContainer.text;
|
||||
}
|
||||
|
||||
CryptoError errorType = cryptoAnnotation.getErrorType();
|
||||
switch (errorType) {
|
||||
case CRYPTO_API_RETURNED_ERROR: {
|
||||
case OPENPGP_API_RETURNED_ERROR: {
|
||||
// TODO make a nice view for this
|
||||
return wrapStatusMessage(cryptoAnnotation.getError().getMessage());
|
||||
return wrapStatusMessage(cryptoAnnotation.getOpenPgpError().getMessage());
|
||||
}
|
||||
case ENCRYPTED_BUT_INCOMPLETE: {
|
||||
return wrapStatusMessage(getContext().getString(R.string.crypto_download_complete_message_to_decrypt));
|
||||
|
|
|
@ -36,7 +36,6 @@ import com.fsck.k9.activity.ChooseFolder;
|
|||
import com.fsck.k9.activity.MessageReference;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment;
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
|
||||
import com.fsck.k9.fragment.ProgressDialogFragment;
|
||||
|
@ -50,7 +49,7 @@ import com.fsck.k9.mailstore.MessageViewInfo;
|
|||
import com.fsck.k9.mailstore.MessageViewInfo.MessageViewContainer;
|
||||
import com.fsck.k9.ui.crypto.MessageCryptoCallback;
|
||||
import com.fsck.k9.ui.crypto.MessageCryptoHelper;
|
||||
import com.fsck.k9.ui.message.DecodeMessageLoader;
|
||||
import com.fsck.k9.ui.message.LocalMessageExtractorLoader;
|
||||
import com.fsck.k9.ui.message.LocalMessageLoader;
|
||||
import com.fsck.k9.ui.crypto.MessageCryptoAnnotations;
|
||||
import com.fsck.k9.view.MessageHeader;
|
||||
|
@ -80,7 +79,6 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
}
|
||||
|
||||
private MessageTopView mMessageView;
|
||||
private PgpData mPgpData;
|
||||
private Account mAccount;
|
||||
private MessageReference mMessageReference;
|
||||
private LocalMessage mMessage;
|
||||
|
@ -175,28 +173,12 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
initializePgpData(savedInstanceState);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
MessageReference messageReference = arguments.getParcelable(ARG_REFERENCE);
|
||||
|
||||
displayMessage(messageReference);
|
||||
}
|
||||
|
||||
private void initializePgpData(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
mPgpData = (PgpData) savedInstanceState.get(STATE_PGP_DATA);
|
||||
} else {
|
||||
mPgpData = new PgpData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(STATE_PGP_DATA, mPgpData);
|
||||
}
|
||||
|
||||
private void displayMessage(MessageReference messageReference) {
|
||||
mMessageReference = messageReference;
|
||||
if (K9.DEBUG) {
|
||||
|
@ -363,19 +345,19 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
|
||||
public void onReply() {
|
||||
if (mMessage != null) {
|
||||
mFragmentListener.onReply(mMessage, mPgpData);
|
||||
mFragmentListener.onReply(mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void onReplyAll() {
|
||||
if (mMessage != null) {
|
||||
mFragmentListener.onReplyAll(mMessage, mPgpData);
|
||||
mFragmentListener.onReplyAll(mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void onForward() {
|
||||
if (mMessage != null) {
|
||||
mFragmentListener.onForward(mMessage, mPgpData);
|
||||
mFragmentListener.onForward(mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,10 +696,10 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
}
|
||||
|
||||
public interface MessageViewFragmentListener {
|
||||
public void onForward(LocalMessage mMessage, PgpData mPgpData);
|
||||
public void onForward(LocalMessage mMessage);
|
||||
public void disableDeleteAction();
|
||||
public void onReplyAll(LocalMessage mMessage, PgpData mPgpData);
|
||||
public void onReply(LocalMessage mMessage, PgpData mPgpData);
|
||||
public void onReplyAll(LocalMessage mMessage);
|
||||
public void onReply(LocalMessage mMessage);
|
||||
public void displayMessageSubject(String title);
|
||||
public void setProgress(boolean b);
|
||||
public void showNextMessageOrReturn();
|
||||
|
@ -757,18 +739,27 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
class DecodeMessageLoaderCallback implements LoaderCallbacks<MessageViewInfo> {
|
||||
@Override
|
||||
public Loader<MessageViewInfo> onCreateLoader(int id, Bundle args) {
|
||||
if (id != DECODE_MESSAGE_LOADER_ID) {
|
||||
throw new IllegalStateException("loader id must be message decoder id");
|
||||
}
|
||||
setProgress(true);
|
||||
return new DecodeMessageLoader(mContext, mMessage, messageAnnotations);
|
||||
return new LocalMessageExtractorLoader(mContext, mMessage, messageAnnotations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<MessageViewInfo> loader, MessageViewInfo messageViewInfo) {
|
||||
if (loader.getId() != DECODE_MESSAGE_LOADER_ID) {
|
||||
throw new IllegalStateException("loader id must be message decoder id");
|
||||
}
|
||||
setProgress(false);
|
||||
onDecodeMessageFinished(messageViewInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<MessageViewInfo> loader) {
|
||||
if (loader.getId() != DECODE_MESSAGE_LOADER_ID) {
|
||||
throw new IllegalStateException("loader id must be message decoder id");
|
||||
}
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import android.widget.LinearLayout;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.mailstore.OpenPgpResultAnnotation;
|
||||
import com.fsck.k9.mailstore.CryptoResultAnnotation;
|
||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
@ -28,7 +28,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
private Context context;
|
||||
private OpenPgpHeaderViewCallback callback;
|
||||
|
||||
private OpenPgpResultAnnotation cryptoAnnotation;
|
||||
private CryptoResultAnnotation cryptoAnnotation;
|
||||
|
||||
private ImageView resultEncryptionIcon;
|
||||
private TextView resultEncryptionText;
|
||||
|
@ -63,7 +63,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void setOpenPgpData(OpenPgpResultAnnotation cryptoAnnotation) {
|
||||
public void setOpenPgpData(CryptoResultAnnotation cryptoAnnotation) {
|
||||
this.cryptoAnnotation = cryptoAnnotation;
|
||||
|
||||
initializeEncryptionHeader();
|
||||
|
@ -78,7 +78,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
|
||||
switch (cryptoAnnotation.getErrorType()) {
|
||||
case NONE: {
|
||||
OpenPgpDecryptionResult decryptionResult = cryptoAnnotation.getDecryptionResult();
|
||||
OpenPgpDecryptionResult decryptionResult = cryptoAnnotation.getOpenPgpDecryptionResult();
|
||||
switch (decryptionResult.getResult()) {
|
||||
case OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED: {
|
||||
displayNotEncrypted();
|
||||
|
@ -97,7 +97,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CRYPTO_API_RETURNED_ERROR: {
|
||||
case OPENPGP_API_RETURNED_ERROR: {
|
||||
displayEncryptionError();
|
||||
break;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
private void displayEncryptionError() {
|
||||
setEncryptionImageAndTextColor(CryptoState.INVALID);
|
||||
|
||||
OpenPgpError error = cryptoAnnotation.getError();
|
||||
OpenPgpError error = cryptoAnnotation.getOpenPgpError();
|
||||
String text;
|
||||
if (error == null) {
|
||||
text = context.getString(R.string.openpgp_unknown_error);
|
||||
|
@ -158,7 +158,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
}
|
||||
|
||||
switch (cryptoAnnotation.getErrorType()) {
|
||||
case CRYPTO_API_RETURNED_ERROR:
|
||||
case OPENPGP_API_RETURNED_ERROR:
|
||||
displayEncryptionError();
|
||||
hideVerificationState();
|
||||
break;
|
||||
|
@ -187,7 +187,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
}
|
||||
|
||||
private void displayVerificationResult() {
|
||||
OpenPgpSignatureResult signatureResult = cryptoAnnotation.getSignatureResult();
|
||||
OpenPgpSignatureResult signatureResult = cryptoAnnotation.getOpenPgpSignatureResult();
|
||||
|
||||
switch (signatureResult.getResult()) {
|
||||
case OpenPgpSignatureResult.RESULT_NO_SIGNATURE: {
|
||||
|
@ -239,11 +239,11 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
}
|
||||
|
||||
private boolean isSignatureButtonUsed() {
|
||||
return cryptoAnnotation.getPendingIntent() != null;
|
||||
return cryptoAnnotation.getOpenPgpPendingIntent() != null;
|
||||
}
|
||||
|
||||
private void setSignatureButtonClickListener() {
|
||||
final PendingIntent pendingIntent = cryptoAnnotation.getPendingIntent();
|
||||
final PendingIntent pendingIntent = cryptoAnnotation.getOpenPgpPendingIntent();
|
||||
resultSignatureButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -287,7 +287,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
setSignatureImageAndTextColor(CryptoState.UNKNOWN_KEY);
|
||||
resultSignatureText.setText(R.string.openpgp_result_signature_missing_key);
|
||||
|
||||
setUserId(cryptoAnnotation.getSignatureResult());
|
||||
setUserId(cryptoAnnotation.getOpenPgpSignatureResult());
|
||||
showSignatureButtonWithTextIfNecessary(R.string.openpgp_result_action_lookup);
|
||||
showSignatureLayout();
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ public class OpenPgpHeaderView extends LinearLayout {
|
|||
}
|
||||
|
||||
private void displayUserIdAndSignatureButton() {
|
||||
setUserId(cryptoAnnotation.getSignatureResult());
|
||||
setUserId(cryptoAnnotation.getOpenPgpSignatureResult());
|
||||
showSignatureButtonWithTextIfNecessary(R.string.openpgp_result_action_show);
|
||||
showSignatureLayout();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import com.fsck.k9.mail.Body;
|
|||
import com.fsck.k9.mail.Multipart;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import com.fsck.k9.mailstore.LocalMessageExtractor;
|
||||
import com.fsck.k9.message.extractors.AttachmentInfoExtractor;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -101,7 +101,7 @@ public abstract class K9WebViewClient extends WebViewClient {
|
|||
Context context = webView.getContext();
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
try {
|
||||
AttachmentViewInfo attachmentInfo = LocalMessageExtractor.extractAttachmentInfo(context, part);
|
||||
AttachmentViewInfo attachmentInfo = AttachmentInfoExtractor.extractAttachmentInfo(context, part);
|
||||
String mimeType = attachmentInfo.mimeType;
|
||||
InputStream inputStream = contentResolver.openInputStream(attachmentInfo.uri);
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import com.fsck.k9.mail.Message;
|
|||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
|
||||
|
||||
public class MessageHeader extends LinearLayout implements OnClickListener, OnLongClickListener {
|
||||
private Context mContext;
|
||||
private TextView mFromView;
|
||||
|
|
Loading…
Reference in a new issue