1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-02-17 07:30:16 -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:
Jesse Vincent 2010-08-15 02:37:06 +00:00
parent 95fd605b0e
commit 73c3872dd0
2 changed files with 67 additions and 23 deletions

View File

@ -11,6 +11,8 @@ import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils; 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 // Inline parts with a content-id are almost certainly components of an HTML message
// not attachments. Don't show attachment download buttons for them. // 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)) if ( contentDisposition != null &&
&& part.getHeader("Content-Id") != null) MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
&& part.getHeader("Content-ID") != null)
{ {
return; return;
} }
if (name == null) if (name == null)
{ {
name = MimeUtility.getHeaderParameter(contentDisposition, "filename"); name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
@ -2140,22 +2138,15 @@ public class MessageView extends K9Activity implements OnClickListener
} }
}); });
// TODO: Only check for external (non inline) images // If the message contains external pictures and the "Show pictures"
final boolean hasPictures = text.contains("<img"); // button wasn't already pressed, see if the user's preferences has us
// showing them anyway.
// If the message contains pictures and the "Show pictures" if ( hasExternalImages(MimeUtility.unfoldAndDecode(text))
// button wasn't already pressed... && (mShowPictures == false))
if (hasPictures && (mShowPictures == false))
{ {
boolean forceShowPictures = false;
if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) || if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) ||
((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) && ((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) &&
mContacts.isInContacts(message.getFrom()[0].getAddress()))) mContacts.isInContacts(message.getFrom()[0].getAddress())))
{
forceShowPictures = true;
}
if (forceShowPictures)
{ {
onShowPictures(); onShowPictures();
} }
@ -2188,6 +2179,21 @@ public class MessageView extends K9Activity implements OnClickListener
} }
}//loadMessageForViewBodyAvailable }//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 @Override
public void loadMessageForViewFailed(Account account, String folder, String uid, public void loadMessageForViewFailed(Account account, String folder, String uid,

View File

@ -44,7 +44,7 @@ public class LocalStore extends Store implements Serializable
*/ */
private static final String[] EMPTY_STRING_ARRAY = new String[0]; 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 static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.X_DESTROYED, Flag.SEEN, Flag.FLAGGED };
private String mPath; private String mPath;
@ -62,6 +62,8 @@ public class LocalStore extends Store implements Serializable
HEADERS_TO_SAVE.add("From"); HEADERS_TO_SAVE.add("From");
HEADERS_TO_SAVE.add("In-Reply-To"); HEADERS_TO_SAVE.add("In-Reply-To");
HEADERS_TO_SAVE.add("References"); HEADERS_TO_SAVE.add("References");
HEADERS_TO_SAVE.add("Content-ID");
HEADERS_TO_SAVE.add("Content-Disposition");
HEADERS_TO_SAVE.add("X-User-Agent"); 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("DROP TABLE IF EXISTS attachments");
mDb.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER," mDb.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
+ "store_data TEXT, content_uri TEXT, size INTEGER, name TEXT," + "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("DROP TABLE IF EXISTS pending_commands");
mDb.execSQL("CREATE TABLE 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); 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", "name",
"mime_type", "mime_type",
"store_data", "store_data",
"content_uri" "content_uri",
"content_id",
"content_disposition"
}, },
"message_id = ?", "message_id = ?",
new String[] { Long.toString(localMessage.mId) }, new String[] { Long.toString(localMessage.mId) },
@ -1407,7 +1433,15 @@ public class LocalStore extends Store implements Serializable
String type = cursor.getString(3); String type = cursor.getString(3);
String storeData = cursor.getString(4); String storeData = cursor.getString(4);
String contentUri = cursor.getString(5); String contentUri = cursor.getString(5);
String contentId = cursor.getString(6);
String contentDisposition = cursor.getString(7);
Body body = null; Body body = null;
if (contentDisposition == null )
{
contentDisposition = "attachment";
}
if (contentUri != null) if (contentUri != null)
{ {
body = new LocalAttachmentBody(Uri.parse(contentUri), mApplication); body = new LocalAttachmentBody(Uri.parse(contentUri), mApplication);
@ -1419,10 +1453,12 @@ public class LocalStore extends Store implements Serializable
name)); name));
bp.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); bp.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
bp.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 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, name,
size)); size));
bp.setHeader(MimeHeader.HEADER_CONTENT_ID, contentId);
/* /*
* HEADER_ANDROID_ATTACHMENT_STORE_DATA is a custom header we add to that * 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. * 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("size", size);
cv.put("name", name); cv.put("name", name);
cv.put("mime_type", attachment.getMimeType()); cv.put("mime_type", attachment.getMimeType());
cv.put("content_id", contentId);
cv.put("content_disposition", contentDisposition);
attachmentId = mDb.insert("attachments", "message_id", cv); attachmentId = mDb.insert("attachments", "message_id", cv);
} }