Related attachments

pull/194/merge
M66B 4 years ago
parent 0814865d0c
commit c95cc95994

File diff suppressed because it is too large Load Diff

@ -175,8 +175,11 @@ public class AdapterAttachment extends RecyclerView.Adapter<AdapterAttachment.Vi
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(attachment.type); sb.append(attachment.type);
if (debug || BuildConfig.DEBUG) { if (debug || BuildConfig.DEBUG) {
if (attachment.cid != null) if (attachment.cid != null) {
sb.append(' ').append(attachment.cid); sb.append(' ').append(attachment.cid);
if (attachment.related != null)
sb.append(' ').append(attachment.related);
}
if (attachment.isEncryption()) if (attachment.isEncryption())
sb.append(' ').append(attachment.encryption); sb.append(' ').append(attachment.encryption);
} }

@ -71,7 +71,7 @@ import io.requery.android.database.sqlite.SQLiteDatabase;
// https://developer.android.com/topic/libraries/architecture/room.html // https://developer.android.com/topic/libraries/architecture/room.html
@Database( @Database(
version = 222, version = 223,
entities = { entities = {
EntityIdentity.class, EntityIdentity.class,
EntityAccount.class, EntityAccount.class,
@ -475,7 +475,7 @@ public abstract class DB extends RoomDatabase {
" UPDATE message SET attachments = attachments + 1" + " UPDATE message SET attachments = attachments + 1" +
" WHERE message.id = NEW.message" + " WHERE message.id = NEW.message" +
" AND NEW.encryption IS NULL" + " AND NEW.encryption IS NULL" +
" AND NOT ((NEW.disposition = 'inline' OR NEW.cid IS NOT NULL) AND NEW.type IN (" + images + "));" + " AND NOT ((NEW.disposition = 'inline' OR (NEW.related IS NOT 0 AND NEW.cid IS NOT NULL)) AND NEW.type IN (" + images + "));" +
" END"); " END");
db.execSQL("CREATE TRIGGER IF NOT EXISTS attachment_delete" + db.execSQL("CREATE TRIGGER IF NOT EXISTS attachment_delete" +
" AFTER DELETE ON attachment" + " AFTER DELETE ON attachment" +
@ -483,7 +483,7 @@ public abstract class DB extends RoomDatabase {
" UPDATE message SET attachments = attachments - 1" + " UPDATE message SET attachments = attachments - 1" +
" WHERE message.id = OLD.message" + " WHERE message.id = OLD.message" +
" AND OLD.encryption IS NULL" + " AND OLD.encryption IS NULL" +
" AND NOT ((OLD.disposition = 'inline' OR OLD.cid IS NOT NULL) AND OLD.type IN (" + images + "));" + " AND NOT ((OLD.disposition = 'inline' OR (OLD.related IS NOT 0 AND OLD.cid IS NOT NULL)) AND OLD.type IN (" + images + "));" +
" END"); " END");
} }
@ -2251,6 +2251,15 @@ public abstract class DB extends RoomDatabase {
logMigration(startVersion, endVersion); logMigration(startVersion, endVersion);
db.execSQL("ALTER TABLE `answer` ADD COLUMN `color` INTEGER"); db.execSQL("ALTER TABLE `answer` ADD COLUMN `color` INTEGER");
} }
}).addMigrations(new Migration(222, 223) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
logMigration(startVersion, endVersion);
db.execSQL("ALTER TABLE `attachment` ADD COLUMN `related` INTEGER");
db.execSQL("DROP TRIGGER IF EXISTS `attachment_insert`");
db.execSQL("DROP TRIGGER IF EXISTS `attachment_delete`");
createTriggers(db);
}
}).addMigrations(new Migration(998, 999) { }).addMigrations(new Migration(998, 999) {
@Override @Override
public void migrate(@NonNull SupportSQLiteDatabase db) { public void migrate(@NonNull SupportSQLiteDatabase db) {

@ -117,8 +117,9 @@ public interface DaoAttachment {
@Query("UPDATE attachment" + @Query("UPDATE attachment" +
" SET cid = :cid" + " SET cid = :cid" +
" WHERE id = :id" + " WHERE id = :id" +
" AND NOT (cid IS :cid)") " AND NOT (cid IS :cid)" +
void setCid(long id, String cid); " AND NOT (related IS :related)")
void setCid(long id, String cid, Boolean related);
@Query("UPDATE attachment" + @Query("UPDATE attachment" +
" SET available = 0" + " SET available = 0" +

@ -76,6 +76,7 @@ public class EntityAttachment {
public String type; public String type;
public String disposition; public String disposition;
public String cid; // Content-ID public String cid; // Content-ID
public Boolean related; // inline
public Integer encryption; public Integer encryption;
public Long size; public Long size;
public Integer progress; public Integer progress;
@ -86,7 +87,8 @@ public class EntityAttachment {
// Gmail sends inline images as attachments with a name and cid // Gmail sends inline images as attachments with a name and cid
boolean isInline() { boolean isInline() {
return (Part.INLINE.equals(disposition) || cid != null); return (Part.INLINE.equals(disposition) ||
(!Boolean.FALSE.equals(related) && cid != null));
} }
boolean isAttachment() { boolean isAttachment() {

@ -3928,7 +3928,8 @@ public class FragmentCompose extends FragmentBase {
if (image) { if (image) {
attachment.cid = "<" + BuildConfig.APPLICATION_ID + "." + attachment.id + ">"; attachment.cid = "<" + BuildConfig.APPLICATION_ID + "." + attachment.id + ">";
db.attachment().setCid(attachment.id, attachment.cid); attachment.related = true;
db.attachment().setCid(attachment.id, attachment.cid, attachment.related);
} }
} finally { } finally {
try { try {
@ -4822,6 +4823,7 @@ public class FragmentCompose extends FragmentBase {
attachment.disposition = Part.INLINE; attachment.disposition = Part.INLINE;
else { else {
attachment.cid = null; attachment.cid = null;
attachment.related = false;
attachment.disposition = Part.ATTACHMENT; attachment.disposition = Part.ATTACHMENT;
} }

@ -964,6 +964,7 @@ public class MessageHelper {
attachment.type = type; attachment.type = type;
attachment.disposition = Part.INLINE; attachment.disposition = Part.INLINE;
attachment.cid = acid; attachment.cid = acid;
attachment.related = true;
attachment.size = null; attachment.size = null;
attachment.progress = 0; attachment.progress = 0;
attachment.id = db.attachment().insertAttachment(attachment); attachment.id = db.attachment().insertAttachment(attachment);
@ -1304,7 +1305,7 @@ public class MessageHelper {
if ("delivery-status".equalsIgnoreCase(reportType) || if ("delivery-status".equalsIgnoreCase(reportType) ||
"disposition-notification".equalsIgnoreCase(reportType)) { "disposition-notification".equalsIgnoreCase(reportType)) {
MessageParts parts = new MessageParts(); MessageParts parts = new MessageParts();
getMessageParts(imessage, parts, null); getMessageParts(null, imessage, parts, null);
for (AttachmentPart apart : parts.attachments) for (AttachmentPart apart : parts.attachments)
if ("text/rfc822-headers".equalsIgnoreCase(apart.attachment.type)) { if ("text/rfc822-headers".equalsIgnoreCase(apart.attachment.type)) {
reportHeaders = new InternetHeaders(apart.part.getInputStream()); reportHeaders = new InternetHeaders(apart.part.getInputStream());
@ -2802,6 +2803,7 @@ public class MessageHelper {
!Part.ATTACHMENT.equals(apart.attachment.disposition)) { !Part.ATTACHMENT.equals(apart.attachment.disposition)) {
Log.i("Normalizing " + apart.attachment); Log.i("Normalizing " + apart.attachment);
apart.attachment.cid = null; apart.attachment.cid = null;
apart.attachment.related = false;
apart.attachment.disposition = Part.ATTACHMENT; apart.attachment.disposition = Part.ATTACHMENT;
} }
} }
@ -3579,8 +3581,8 @@ public class MessageHelper {
if (content instanceof Multipart) { if (content instanceof Multipart) {
Multipart multipart = (Multipart) content; Multipart multipart = (Multipart) content;
if (multipart.getCount() == 2) { if (multipart.getCount() == 2) {
getMessageParts(multipart.getBodyPart(0), parts, null); getMessageParts(part, multipart.getBodyPart(0), parts, null);
getMessageParts(multipart.getBodyPart(1), parts, getMessageParts(part, multipart.getBodyPart(1), parts,
"application/pgp-signature".equals(protocol) "application/pgp-signature".equals(protocol)
? EntityAttachment.PGP_SIGNATURE ? EntityAttachment.PGP_SIGNATURE
: EntityAttachment.SMIME_SIGNATURE); : EntityAttachment.SMIME_SIGNATURE);
@ -3623,7 +3625,7 @@ public class MessageHelper {
Multipart multipart = (Multipart) content; Multipart multipart = (Multipart) content;
if (multipart.getCount() == 2) { if (multipart.getCount() == 2) {
// Ignore header // Ignore header
getMessageParts(multipart.getBodyPart(1), parts, EntityAttachment.PGP_MESSAGE); getMessageParts(part, multipart.getBodyPart(1), parts, EntityAttachment.PGP_MESSAGE);
return parts; return parts;
} else { } else {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -3641,10 +3643,10 @@ public class MessageHelper {
ContentType ct = new ContentType(part.getContentType()); ContentType ct = new ContentType(part.getContentType());
String smimeType = ct.getParameter("smime-type"); String smimeType = ct.getParameter("smime-type");
if ("enveloped-data".equalsIgnoreCase(smimeType)) { if ("enveloped-data".equalsIgnoreCase(smimeType)) {
getMessageParts(part, parts, EntityAttachment.SMIME_MESSAGE); getMessageParts(null, part, parts, EntityAttachment.SMIME_MESSAGE);
return parts; return parts;
} else if ("signed-data".equalsIgnoreCase(smimeType)) { } else if ("signed-data".equalsIgnoreCase(smimeType)) {
getMessageParts(part, parts, EntityAttachment.SMIME_SIGNED_DATA); getMessageParts(null, part, parts, EntityAttachment.SMIME_SIGNED_DATA);
return parts; return parts;
} else if ("signed-receipt".equalsIgnoreCase(smimeType)) { } else if ("signed-receipt".equalsIgnoreCase(smimeType)) {
// https://datatracker.ietf.org/doc/html/rfc2634#section-2 // https://datatracker.ietf.org/doc/html/rfc2634#section-2
@ -3652,10 +3654,10 @@ public class MessageHelper {
if (TextUtils.isEmpty(smimeType)) { if (TextUtils.isEmpty(smimeType)) {
String name = ct.getParameter("name"); String name = ct.getParameter("name");
if ("smime.p7m".equalsIgnoreCase(name)) { if ("smime.p7m".equalsIgnoreCase(name)) {
getMessageParts(part, parts, EntityAttachment.SMIME_MESSAGE); getMessageParts(null, part, parts, EntityAttachment.SMIME_MESSAGE);
return parts; return parts;
} else if ("smime.p7s".equalsIgnoreCase(name)) { } else if ("smime.p7s".equalsIgnoreCase(name)) {
getMessageParts(part, parts, EntityAttachment.SMIME_SIGNED_DATA); getMessageParts(null, part, parts, EntityAttachment.SMIME_SIGNED_DATA);
return parts; return parts;
} }
} }
@ -3668,7 +3670,7 @@ public class MessageHelper {
Log.w(ex); Log.w(ex);
} }
getMessageParts(imessage, parts, null); getMessageParts(null, imessage, parts, null);
} catch (OutOfMemoryError ex) { } catch (OutOfMemoryError ex) {
Log.e(ex); Log.e(ex);
parts.warnings.add(Log.formatThrowable(ex, false)); parts.warnings.add(Log.formatThrowable(ex, false));
@ -3692,7 +3694,7 @@ public class MessageHelper {
return parts; return parts;
} }
private void getMessageParts(Part part, MessageParts parts, Integer encrypt) throws IOException, MessagingException { private void getMessageParts(Part parent, Part part, MessageParts parts, Integer encrypt) throws IOException, MessagingException {
try { try {
Log.d("Part class=" + part.getClass() + " type=" + part.getContentType()); Log.d("Part class=" + part.getClass() + " type=" + part.getContentType());
@ -3728,7 +3730,7 @@ public class MessageHelper {
if (alternative && count > 1 && child.isMimeType("text/plain")) if (alternative && count > 1 && child.isMimeType("text/plain"))
plain.add(child); plain.add(child);
else { else {
getMessageParts(child, parts, encrypt); getMessageParts(part, child, parts, encrypt);
other = true; other = true;
} }
} catch (ParseException ex) { } catch (ParseException ex) {
@ -3741,7 +3743,7 @@ public class MessageHelper {
if (alternative && count > 1 && !other) if (alternative && count > 1 && !other)
for (Part child : plain) for (Part child : plain)
try { try {
getMessageParts(child, parts, encrypt); getMessageParts(part, child, parts, encrypt);
} catch (ParseException ex) { } catch (ParseException ex) {
// Nested body: try to continue // Nested body: try to continue
// ParseException: In parameter list boundary="...">, expected parameter name, got ";" // ParseException: In parameter list boundary="...">, expected parameter name, got ";"
@ -3837,12 +3839,21 @@ public class MessageHelper {
parts.warnings.add(Log.formatThrowable(ex, false)); parts.warnings.add(Log.formatThrowable(ex, false));
} }
Boolean related = null;
if (parent != null)
try {
related = parent.isMimeType("multipart/related");
} catch (MessagingException ex) {
Log.w(ex);
}
apart.attachment = new EntityAttachment(); apart.attachment = new EntityAttachment();
apart.attachment.disposition = apart.disposition; apart.attachment.disposition = apart.disposition;
apart.attachment.name = apart.filename; apart.attachment.name = apart.filename;
apart.attachment.type = contentType.getBaseType().toLowerCase(Locale.ROOT); apart.attachment.type = contentType.getBaseType().toLowerCase(Locale.ROOT);
apart.attachment.size = (long) apart.part.getSize(); apart.attachment.size = (long) apart.part.getSize();
apart.attachment.cid = cid; apart.attachment.cid = cid;
apart.attachment.related = related;
apart.attachment.encryption = apart.encrypt; apart.attachment.encryption = apart.encrypt;
if ("text/calendar".equalsIgnoreCase(apart.attachment.type) && if ("text/calendar".equalsIgnoreCase(apart.attachment.type) &&

Loading…
Cancel
Save