[geary/wip/713830-disposition] Upgrade attachment table to include Content-ID and Content-Description
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713830-disposition] Upgrade attachment table to include Content-ID and Content-Description
- Date: Thu, 31 Jul 2014 21:35:24 +0000 (UTC)
commit d71b31e0069c702586ea3abdef1c5eb6a390bb83
Author: Jim Nelson <jim yorba org>
Date: Thu Jul 31 14:15:48 2014 -0700
Upgrade attachment table to include Content-ID and Content-Description
sql/version-022.sql | 6 ++++
src/engine/api/geary-attachment.vala | 19 +++++++++++++-
src/engine/imap-db/imap-db-attachment.vala | 6 +++-
src/engine/imap-db/imap-db-database.vala | 39 +--------------------------
src/engine/imap-db/imap-db-folder.vala | 23 ++++++++++-----
src/engine/mime/mime-content-type.vala | 5 +++
6 files changed, 50 insertions(+), 48 deletions(-)
---
diff --git a/sql/version-022.sql b/sql/version-022.sql
index df69e30..b77872f 100644
--- a/sql/version-022.sql
+++ b/sql/version-022.sql
@@ -1,4 +1,10 @@
--
-- Dummy database upgrade to repopulate attachments. Bug #713830 revealed that
-- non-text and non-image files with no Content-Disposition were being dropped.
+-- Also add Content-ID to database so attachments in RCF822 messages can be paired
+-- to extracted attachments on filesystem.
--
+
+ALTER TABLE MessageAttachmentTable ADD COLUMN content_id TEXT DEFAULT NULL;
+ALTER TABLE MessageAttachmentTable ADD COLUMN description TEXT DEFAULT NULL;
+
diff --git a/src/engine/api/geary-attachment.vala b/src/engine/api/geary-attachment.vala
index cd16994..d483352 100644
--- a/src/engine/api/geary-attachment.vala
+++ b/src/engine/api/geary-attachment.vala
@@ -49,14 +49,31 @@ public abstract class Geary.Attachment : BaseObject {
*/
public Mime.ContentDisposition content_disposition { get; private set; }
+ /**
+ * The Content-ID of the attachment.
+ *
+ * See [[https://tools.ietf.org/html/rfc2111]]
+ */
+ public string? content_id { get; private set; }
+
+ /**
+ * The Content-Description of the attachment.
+ *
+ * See [[https://tools.ietf.org/html/rfc2045#section-8]]
+ */
+ public string? content_description { get; private set; }
+
protected Attachment(string id, File file, bool has_supplied_filename, Mime.ContentType content_type,
- int64 filesize, Mime.ContentDisposition content_disposition) {
+ int64 filesize, Mime.ContentDisposition content_disposition, string? content_id,
+ string? content_description) {
this.id = id;
this.file = file;
this.has_supplied_filename = has_supplied_filename;
this.content_type = content_type;
this.filesize = filesize;
this.content_disposition = content_disposition;
+ this.content_id = content_id;
+ this.content_description = content_description;
}
}
diff --git a/src/engine/imap-db/imap-db-attachment.vala b/src/engine/imap-db/imap-db-attachment.vala
index b8b5226..def821c 100644
--- a/src/engine/imap-db/imap-db-attachment.vala
+++ b/src/engine/imap-db/imap-db-attachment.vala
@@ -10,9 +10,11 @@ private class Geary.ImapDB.Attachment : Geary.Attachment {
private const string ATTACHMENTS_DIR = "attachments";
protected Attachment(File data_dir, string? filename, Mime.ContentType content_type, int64 filesize,
- int64 message_id, int64 attachment_id, Mime.ContentDisposition content_disposition) {
+ int64 message_id, int64 attachment_id, Mime.ContentDisposition content_disposition,
+ string? content_id, string? content_description) {
base (generate_id(attachment_id),generate_file(data_dir, message_id, attachment_id, filename),
- !String.is_empty(filename), content_type, filesize, content_disposition);
+ !String.is_empty(filename), content_type, filesize, content_disposition, content_id,
+ content_description);
}
private static string generate_id(int64 attachment_id) {
diff --git a/src/engine/imap-db/imap-db-database.vala b/src/engine/imap-db/imap-db-database.vala
index c775895..89908e2 100644
--- a/src/engine/imap-db/imap-db-database.vala
+++ b/src/engine/imap-db/imap-db-database.vala
@@ -422,8 +422,6 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
if (results.finished)
return Db.TransactionOutcome.ROLLBACK;
- Gee.HashSet<int64?> deleted_ids = new Gee.HashSet<int64?>(
- Collection.int64_hash_func, Collection.int64_equal_func);
do {
int64 message_id = results.rowid_at(0);
Geary.Memory.Buffer header = results.string_buffer_at(1);
@@ -442,16 +440,6 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
// build a list of attachments in the message itself
Gee.List<GMime.Part> msg_attachments = message.get_attachments();
- // get known attachments stored in database and on disk
- Gee.List<Geary.Attachment>? known_attachments = ImapDB.Folder.do_list_attachments(
- cx, message_id, null);
- int known_attachments_count = (known_attachments != null)
- ? known_attachments.size : 0;
-
- // if the same count, consider all present and accounted for
- if (msg_attachments.size == known_attachments_count)
- continue;
-
// delete all attachments for this message
try {
Geary.ImapDB.Folder.do_delete_attachments(cx, message_id);
@@ -470,33 +458,10 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
// fallthrough
}
-
- deleted_ids.add(message_id);
} while (results.next());
- // rebuild rows with potentially new attachments
- if (deleted_ids.size > 0) {
- StringBuilder builder = new StringBuilder("""
- DELETE FROM MessageSearchTable WHERE docid IN (
- """);
- bool first = true;
- foreach (int64 message_id in deleted_ids) {
- if (!first)
- builder.append(", ");
-
- builder.append(message_id.to_string());
- first = false;
- }
- builder.append(")");
-
- try {
- cx.exec(builder.str);
- } catch (Error err) {
- debug("Unable to do partial delete of search table: %s", err.message);
-
- throw err;
- }
- }
+ // rebuild search table due to potentially new attachments
+ cx.exec("DELETE FROM MessageSearchTable");
return Db.TransactionOutcome.COMMIT;
});
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
index 9ce333a..32a58d2 100644
--- a/src/engine/imap-db/imap-db-folder.vala
+++ b/src/engine/imap-db/imap-db-folder.vala
@@ -1871,10 +1871,10 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
unread_count_change += new_unread_count;
}
- public static Gee.List<Geary.Attachment>? do_list_attachments(Db.Connection cx, int64 message_id,
+ private static Gee.List<Geary.Attachment>? do_list_attachments(Db.Connection cx, int64 message_id,
Cancellable? cancellable) throws Error {
Db.Statement stmt = cx.prepare("""
- SELECT id, filename, mime_type, filesize, disposition
+ SELECT id, filename, mime_type, filesize, disposition, content_id, description
FROM MessageAttachmentTable
WHERE message_id = ?
ORDER BY id
@@ -1891,7 +1891,8 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
Mime.DispositionType.from_int(results.int_at(4)));
list.add(new ImapDB.Attachment(cx.database.db_file.get_parent(), results.string_at(1),
Mime.ContentType.deserialize(results.nonnull_string_at(2)), results.int64_at(3),
- message_id, results.rowid_at(0), disposition));
+ message_id, results.rowid_at(0), disposition, results.string_at(5),
+ results.string_at(6)));
} while (results.next(cancellable));
return list;
@@ -1909,13 +1910,17 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
return;
foreach (GMime.Part attachment in attachments) {
- unowned GMime.ContentType? content_type = attachment.get_content_type();
- string mime_type = (content_type != null) ? content_type.to_string() :
"application/octet-stream";
+ GMime.ContentType? content_type = attachment.get_content_type();
+ string mime_type = (content_type != null)
+ ? content_type.to_string()
+ : Mime.ContentType.DEFAULT_CONTENT_TYPE;
string? disposition = attachment.get_disposition();
+ string? content_id = attachment.get_content_id();
+ string? description = attachment.get_content_description();
string filename = RFC822.Utils.get_clean_attachment_filename(attachment);
// Convert the attachment content into a usable ByteArray.
- GMime.DataWrapper attachment_data = attachment.get_content_object();
+ GMime.DataWrapper? attachment_data = attachment.get_content_object();
ByteArray byte_array = new ByteArray();
GMime.StreamMem stream = new GMime.StreamMem.with_byte_array(byte_array);
stream.set_owner(false);
@@ -1933,14 +1938,16 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
// Insert it into the database.
Db.Statement stmt = cx.prepare("""
- INSERT INTO MessageAttachmentTable (message_id, filename, mime_type, filesize, disposition)
- VALUES (?, ?, ?, ?, ?)
+ INSERT INTO MessageAttachmentTable (message_id, filename, mime_type, filesize, disposition,
content_id, description)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
""");
stmt.bind_rowid(0, message_id);
stmt.bind_string(1, filename);
stmt.bind_string(2, mime_type);
stmt.bind_uint(3, filesize);
stmt.bind_int(4, disposition_type);
+ stmt.bind_string(5, content_id);
+ stmt.bind_string(6, description);
int64 attachment_id = stmt.exec_insert(cancellable);
diff --git a/src/engine/mime/mime-content-type.vala b/src/engine/mime/mime-content-type.vala
index e61ade3..ec26769 100644
--- a/src/engine/mime/mime-content-type.vala
+++ b/src/engine/mime/mime-content-type.vala
@@ -19,6 +19,11 @@ public class Geary.Mime.ContentType : Geary.BaseObject {
public const string WILDCARD = "*";
/**
+ * Default Content-Type for unknown or unmarked content.
+ */
+ public const string DEFAULT_CONTENT_TYPE = "application/octet-stream";
+
+ /**
* The type (discrete or concrete) portion of the Content-Type field.
*
* It's highly recommended the caller use the various ''has'' and ''is'' methods when performing
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]