[geary/mjog/rfc822-cleanup-part-deux: 5/8] Geary.RFC822.Message: Add accessors for message headers and raw body



commit 1ab803675ca6545b8dba2bb3733d680bfd7d4953
Author: Michael Gratton <mike vee net>
Date:   Tue Jun 30 14:33:06 2020 +1000

    Geary.RFC822.Message: Add accessors for message headers and raw body
    
    Allow accessing Header and Text representations of the message.

 src/engine/rfc822/rfc822-message-data.vala  | 70 +++++++++++++++++++++++++----
 src/engine/rfc822/rfc822-message.vala       | 15 +++++++
 test/engine/rfc822/rfc822-message-test.vala | 14 ++++++
 3 files changed, 91 insertions(+), 8 deletions(-)
---
diff --git a/src/engine/rfc822/rfc822-message-data.vala b/src/engine/rfc822/rfc822-message-data.vala
index 91ec0f8ce..ee06727ae 100644
--- a/src/engine/rfc822/rfc822-message-data.vala
+++ b/src/engine/rfc822/rfc822-message-data.vala
@@ -369,9 +369,15 @@ public class Geary.RFC822.Header :
     Geary.MessageData.BlockMessageData, EncodedMessageData {
 
 
-    private GMime.Message? message = null;
+    private GMime.HeaderList headers;
     private string[]? names = null;
 
+
+    // The ctors for this class seem the wrong way around, but the
+    // default accepts a memory buffer and not a GMime.HeaderList to
+    // keep it consistent with other EncodedMessageData
+    // implementations.
+
     public Header(Memory.Buffer buffer) throws Error {
         base("RFC822.Header", buffer);
 
@@ -381,15 +387,25 @@ public class Geary.RFC822.Header :
         parser.set_respect_content_length(false);
         parser.set_format(MESSAGE);
 
-        this.message = parser.construct_message(null);
-        if (this.message == null) {
+        var message = parser.construct_message(null);
+        if (message == null) {
             throw new Error.INVALID("Unable to parse RFC 822 headers");
         }
+
+        this.headers = message.get_header_list();
+    }
+
+    public Header.from_gmime(GMime.Object gmime) {
+        base(
+            "RFC822.Header",
+            new Memory.StringBuffer(gmime.get_headers(get_format_options()))
+        );
+        this.headers = gmime.get_header_list();
     }
 
     public string? get_header(string name) {
         string? value = null;
-        var header = this.message.get_header_list().get_header(name);
+        var header = this.headers.get_header(name);
         if (header != null) {
             value = header.get_value();
         }
@@ -398,7 +414,7 @@ public class Geary.RFC822.Header :
 
     public string? get_raw_header(string name) {
         string? value = null;
-        var header = this.message.get_header_list().get_header(name);
+        var header = this.headers.get_header(name);
         if (header != null) {
             value = header.get_raw_value();
         }
@@ -407,10 +423,9 @@ public class Geary.RFC822.Header :
 
     public string[] get_header_names() {
         if (this.names == null) {
-            GMime.HeaderList headers = this.message.get_header_list();
-            var names = new string[headers.get_count()];
+            var names = new string[this.headers.get_count()];
             for (int i = 0; i < names.length; i++) {
-                names[i] = headers.get_header_at(i).get_name();
+                names[i] = this.headers.get_header_at(i).get_name();
             }
             this.names = names;
         }
@@ -422,10 +437,49 @@ public class Geary.RFC822.Header :
 public class Geary.RFC822.Text :
     Geary.MessageData.BlockMessageData, EncodedMessageData {
 
+
+    private class GMimeBuffer : Memory.Buffer, Memory.UnownedBytesBuffer {
+
+
+        public override size_t allocated_size {
+            get { return (size_t) this.stream.length; }
+        }
+
+        public override size_t size {
+            get { return (size_t) this.stream.length; }
+        }
+
+        private GMime.Stream stream;
+        private GLib.Bytes buf = null;
+
+        public GMimeBuffer(GMime.Stream stream) {
+            this.stream = stream;
+        }
+
+        public override GLib.Bytes get_bytes() {
+            if (this.buf == null) {
+                this.stream.seek(0, SET);
+                uint8[] bytes = new uint8[this.stream.length()];
+                this.stream.read(bytes);
+                this.buf = new GLib.Bytes.take(bytes);
+            }
+            return this.buf;
+        }
+
+        public unowned uint8[] to_unowned_uint8_array() {
+            return get_bytes().get_data();
+        }
+
+    }
+
     public Text(Memory.Buffer buffer) {
         base("RFC822.Text", buffer);
     }
 
+    public Text.from_gmime(GMime.Stream gmime) {
+        base("RFC822.Text", new GMimeBuffer(gmime));
+    }
+
 }
 
 public class Geary.RFC822.Full :
diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala
index 0a98a698a..6d190b4b0 100644
--- a/src/engine/rfc822/rfc822-message.vala
+++ b/src/engine/rfc822/rfc822-message.vala
@@ -658,6 +658,21 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
         return (addrs.size > 0) ? addrs : null;
     }
 
+    /**
+     * Returns the header of the message.
+     */
+    public Header get_header() {
+        return new Header.from_gmime(this.message);
+    }
+
+    /**
+     * Returns the possibly body of the message.
+     */
+    public Text get_body() {
+        GMime.Part part = (GMime.Part) this.message.get_mime_part();
+        return new Text.from_gmime(part.get_content().get_stream());
+    }
+
     /**
      * Serialises the message using native (i.e. LF) line endings.
      */
diff --git a/test/engine/rfc822/rfc822-message-test.vala b/test/engine/rfc822/rfc822-message-test.vala
index 478d56339..8ba97a6aa 100644
--- a/test/engine/rfc822/rfc822-message-test.vala
+++ b/test/engine/rfc822/rfc822-message-test.vala
@@ -53,6 +53,8 @@ This is the second line.
                  multipart_alternative_as_converted_html);
         add_test("multipart_alternative_as_html",
                  multipart_alternative_as_html);
+        add_test("get_header", get_header);
+        add_test("get_body", get_body);
         add_test("get_preview", get_preview);
         add_test("get_recipients", get_recipients);
         add_test("get_searchable_body", get_searchable_body);
@@ -177,6 +179,18 @@ This is the second line.
         assert_string(BASIC_HTML_BODY, test.get_html_body(null));
     }
 
+    public void get_header() throws GLib.Error {
+        Message message = resource_to_message(BASIC_TEXT_PLAIN);
+        Header header = message.get_header();
+        assert(header.get_header("From") == "Alice <alice example net>");
+    }
+
+    public void get_body() throws GLib.Error {
+        Message message = resource_to_message(BASIC_TEXT_PLAIN);
+        Text body = message.get_body();
+        assert(body.buffer.to_string().replace("\r", "") == BASIC_PLAIN_BODY);
+    }
+
     public void get_preview() throws GLib.Error {
         Message multipart_signed = string_to_message(MULTIPART_SIGNED_MESSAGE_TEXT);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]