mirror of
https://github.com/moparisthebest/k-9
synced 2024-12-25 00:58:50 -05:00
Improve our display of inline images in HTML mail to not also offer
themselves up for download. To do so, we need to start storing the original content-id and content-disposition for attachments - this includes a database upgrade. Based on a patch from @achen.code
This commit is contained in:
parent
95fd605b0e
commit
73c3872dd0
@ -11,6 +11,8 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@ -1887,18 +1889,14 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Don't show attachment download buttons for them.
|
||||
//
|
||||
// TODO: This code won't work until we correct attachment storage
|
||||
|
||||
if ("inline".equalsIgnoreCase(MimeUtility.getHeaderParameter(contentDisposition, null))
|
||||
&& part.getHeader("Content-Id") != null)
|
||||
if ( contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
|
||||
&& part.getHeader("Content-ID") != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
||||
@ -2140,22 +2138,15 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Only check for external (non inline) images
|
||||
final boolean hasPictures = text.contains("<img");
|
||||
|
||||
// If the message contains pictures and the "Show pictures"
|
||||
// button wasn't already pressed...
|
||||
if (hasPictures && (mShowPictures == false))
|
||||
// If the message contains external pictures and the "Show pictures"
|
||||
// button wasn't already pressed, see if the user's preferences has us
|
||||
// showing them anyway.
|
||||
if ( hasExternalImages(MimeUtility.unfoldAndDecode(text))
|
||||
&& (mShowPictures == false))
|
||||
{
|
||||
boolean forceShowPictures = false;
|
||||
if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) ||
|
||||
((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) &&
|
||||
mContacts.isInContacts(message.getFrom()[0].getAddress())))
|
||||
{
|
||||
forceShowPictures = true;
|
||||
}
|
||||
|
||||
if (forceShowPictures)
|
||||
{
|
||||
onShowPictures();
|
||||
}
|
||||
@ -2188,6 +2179,21 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
}
|
||||
}//loadMessageForViewBodyAvailable
|
||||
|
||||
private static final String IMG_SRC_REGEX = "(?is:<img[^>]+src\\s*=\\s*['\"]?([a-z]+)\\:)";
|
||||
private boolean hasExternalImages(final String message) {
|
||||
Pattern mImgPattern = Pattern.compile(IMG_SRC_REGEX);
|
||||
Matcher mImgMatches = mImgPattern.matcher(message);
|
||||
while(mImgMatches.find()) {
|
||||
if(!mImgMatches.group(1).equals("content")) {
|
||||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, "External images found.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, "No external images.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewFailed(Account account, String folder, String uid,
|
||||
|
@ -44,7 +44,7 @@ public class LocalStore extends Store implements Serializable
|
||||
*/
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private static final int DB_VERSION = 35;
|
||||
private static final int DB_VERSION = 37;
|
||||
private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.X_DESTROYED, Flag.SEEN, Flag.FLAGGED };
|
||||
|
||||
private String mPath;
|
||||
@ -62,6 +62,8 @@ public class LocalStore extends Store implements Serializable
|
||||
HEADERS_TO_SAVE.add("From");
|
||||
HEADERS_TO_SAVE.add("In-Reply-To");
|
||||
HEADERS_TO_SAVE.add("References");
|
||||
HEADERS_TO_SAVE.add("Content-ID");
|
||||
HEADERS_TO_SAVE.add("Content-Disposition");
|
||||
HEADERS_TO_SAVE.add("X-User-Agent");
|
||||
}
|
||||
/*
|
||||
@ -164,7 +166,7 @@ public class LocalStore extends Store implements Serializable
|
||||
mDb.execSQL("DROP TABLE IF EXISTS attachments");
|
||||
mDb.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
|
||||
+ "store_data TEXT, content_uri TEXT, size INTEGER, name TEXT,"
|
||||
+ "mime_type TEXT)");
|
||||
+ "mime_type TEXT, content_id TEXT, content_disposition TEXT)");
|
||||
|
||||
mDb.execSQL("DROP TABLE IF EXISTS pending_commands");
|
||||
mDb.execSQL("CREATE TABLE pending_commands " +
|
||||
@ -244,6 +246,28 @@ public class LocalStore extends Store implements Serializable
|
||||
Log.e(K9.LOG_TAG, "Unable to get rid of obsolete flag X_NO_SEEN_INFO", e);
|
||||
}
|
||||
}
|
||||
if (mDb.getVersion() < 36)
|
||||
{
|
||||
try
|
||||
{
|
||||
mDb.execSQL("ALTER TABLE attachments ADD content_id TEXT");
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Unable to add content_id column to attachments");
|
||||
}
|
||||
}
|
||||
if (mDb.getVersion() < 37)
|
||||
{
|
||||
try
|
||||
{
|
||||
mDb.execSQL("ALTER TABLE attachments ADD content_disposition TEXT");
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Unable to add content_disposition column to attachments");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1391,7 +1415,9 @@ public class LocalStore extends Store implements Serializable
|
||||
"name",
|
||||
"mime_type",
|
||||
"store_data",
|
||||
"content_uri"
|
||||
"content_uri",
|
||||
"content_id",
|
||||
"content_disposition"
|
||||
},
|
||||
"message_id = ?",
|
||||
new String[] { Long.toString(localMessage.mId) },
|
||||
@ -1407,7 +1433,15 @@ public class LocalStore extends Store implements Serializable
|
||||
String type = cursor.getString(3);
|
||||
String storeData = cursor.getString(4);
|
||||
String contentUri = cursor.getString(5);
|
||||
String contentId = cursor.getString(6);
|
||||
String contentDisposition = cursor.getString(7);
|
||||
Body body = null;
|
||||
|
||||
if (contentDisposition == null )
|
||||
{
|
||||
contentDisposition = "attachment";
|
||||
}
|
||||
|
||||
if (contentUri != null)
|
||||
{
|
||||
body = new LocalAttachmentBody(Uri.parse(contentUri), mApplication);
|
||||
@ -1419,10 +1453,12 @@ public class LocalStore extends Store implements Serializable
|
||||
name));
|
||||
bp.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
|
||||
bp.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
|
||||
String.format("attachment;\n filename=\"%s\";\n size=%d",
|
||||
String.format("%s;\n filename=\"%s\";\n size=%d",
|
||||
contentDisposition,
|
||||
name,
|
||||
size));
|
||||
|
||||
bp.setHeader(MimeHeader.HEADER_CONTENT_ID, contentId);
|
||||
/*
|
||||
* HEADER_ANDROID_ATTACHMENT_STORE_DATA is a custom header we add to that
|
||||
* we can later pull the attachment from the remote store if neccesary.
|
||||
@ -2040,6 +2076,8 @@ public class LocalStore extends Store implements Serializable
|
||||
cv.put("size", size);
|
||||
cv.put("name", name);
|
||||
cv.put("mime_type", attachment.getMimeType());
|
||||
cv.put("content_id", contentId);
|
||||
cv.put("content_disposition", contentDisposition);
|
||||
|
||||
attachmentId = mDb.insert("attachments", "message_id", cv);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user