[geary/wip/713830-disposition] Upgrade attachment table to include Content-ID and Content-Description



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]