[gmime: 14/23] Autocrypt: add g_mime_message_get_autocrypt_headers()



commit 339ae293e956f5eddf0094c28ce303103d92b505
Author: Daniel Kahn Gillmor <dkg fifthhorseman net>
Date:   Mon Oct 23 11:31:56 2017 -0400

    Autocrypt: add g_mime_message_get_autocrypt_headers()
    
    This is the main function that I expect MUA implementers to need to
    use.  Given a message, give me a list of autocrypt headers for all the
    senders.
    
    In the (likely) event that a sender has no Autocrypt header in the
    e-mail, we should still return an "incomplete" header for that sender,
    because that will affect the MUA's knowledge about the peer's keys.
    
    At first blush, it seems odd that this is a list, rather than a single
    GMimeAutocryptHeader.  However, it's possible for an e-mail to have a
    header like:
    
        From: alice example net, bob example net
    
    or:
    
        From: undisclosed sender: ;
    
    So the API needs to be able to handle those cases.

 docs/reference/gmime-sections.txt |    1 +
 gmime/gmime-message.c             |  105 +++++++++++++++++++++++++++++++++++++
 gmime/gmime-message.h             |    3 +
 3 files changed, 109 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index e6660da..3586ad2 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -1001,6 +1001,7 @@ g_mime_message_set_mime_part
 g_mime_message_get_mime_part
 g_mime_message_foreach
 g_mime_message_get_body
+g_mime_message_get_autocrypt_headers
 
 <SUBSECTION Private>
 g_mime_message_get_type
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 9d4dac4..9e14504 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -1182,3 +1182,108 @@ g_mime_message_get_body (GMimeMessage *message)
        
        return NULL;
 }
+
+
+/**
+ * g_mime_message_get_autocrypt_headers:
+ * @message: a #GMimeMessage object.
+ * @actype: the desired version of autocrypt headers
+ * @now: a #GDateTime object, or %NULL
+ *
+ * Creates a new #GMimeAutocryptHeaderList of relevant headers of the
+ * given type based on the sender(s) of an e-mail message.
+ *
+ * Each header in the list will have a valid address and will be of
+ * the type requested.
+ *
+ * If no Autocrypt header is found for a sender, the returned
+ * #GMimeAutocryptHeader associated with that address will be in the
+ * list, but it will not be complete (see
+ * #g_mime_autocrypt_header_is_complete).
+ *
+ * Note that the following types of Autocrypt headers will not be
+ * returned by this function:
+ *
+ *  - headers of an unrequested type
+ *  - headers that do not match an address in "From:"
+ *  - unparseable headers
+ *  - headers with unknown critical attributes
+ *  - duplicate valid headers for a given address
+ * 
+ * On error (e.g. if this version of GMime cannot handle the requested
+ * Autocrypt type), returns %NULL
+ *
+ * The returned Autocrypt headers will have their effective_date set
+ * to the earliest of either:
+ *
+ * - the Date: header of the message or 
+ * - @now (or the current time, if @now is %NULL)
+ *
+ * Returns: (transfer full): a new #GMimeAutocryptHeaderList object
+ **/
+GMimeAutocryptHeaderList *
+g_mime_message_get_autocrypt_headers (GMimeMessage *message, gint actype, GDateTime *now)
+{
+       g_return_val_if_fail (GMIME_IS_MESSAGE (message), NULL);
+       if (actype != 1)
+               return NULL;
+       
+       GMimeObject *mime_part = GMIME_OBJECT (message);
+       int i;
+
+       InternetAddressList *addresses = message->addrlists[GMIME_ADDRESS_TYPE_FROM];
+
+       GMimeAutocryptHeaderList *ret = g_mime_autocrypt_header_list_new ();
+       guint count = g_mime_autocrypt_header_list_add_missing_addresses (ret, addresses);
+       if (!count)
+               return ret;
+       
+       /* scan for Autocrypt headers whose type=actype, and addr=
+        * attribute matches the From: header.  calculate
+        * effective_date based on now and the Date: header. */
+       
+       GMimeHeaderList *headers = g_mime_object_get_header_list(mime_part);
+       for (i = 0; i < g_mime_header_list_get_count (headers); i++) {
+               GMimeHeader *header = g_mime_header_list_get_header_at (headers, i);
+               if (g_ascii_strcasecmp ("autocrypt", header->name) == 0) {
+                       GMimeAutocryptHeader *ah = g_mime_autocrypt_header_new_from_string 
(g_mime_header_get_value (header));
+                       if (!ah || ah->actype != actype || ! g_mime_autocrypt_header_is_complete (ah))
+                               goto done;
+                       GMimeAutocryptHeader *prev = g_mime_autocrypt_header_list_get_header_for_address 
(ret, ah->address);
+                       if (!prev) /* not a valid address (was not in From:) */
+                               goto done;
+                       if (g_mime_autocrypt_header_is_complete (prev)) {
+                               /* this is a duplicate (we use actype=0 as an internal marker for this) */
+                               prev->actype = 0;
+                       } else {
+                               g_mime_autocrypt_header_clone (prev, ah);
+                       }
+               done:
+                       if (ah)
+                               g_object_unref (ah);
+               }
+                       
+       }
+       GDateTime *newnow = NULL;
+       if (now == NULL)
+               now = newnow = g_date_time_new_now_utc ();
+       GDateTime *effective = now;
+       if (message->date && g_date_time_compare (message->date, now) < 0)
+               effective = message->date;
+       for (i = 0; i < g_mime_autocrypt_header_list_get_count (ret); i++) {
+               GMimeAutocryptHeader *ah = g_mime_autocrypt_header_list_get_header_at (ret, i);
+               g_mime_autocrypt_header_set_effective_date (ah, effective);
+               /* drop keydata from duplicates */
+               if (ah->actype == 0) {
+                       g_mime_autocrypt_header_set_keydata (ah, NULL);
+                       ah->actype = actype;
+               }
+       }
+       if (newnow)
+               g_date_time_unref (newnow);
+       return ret;
+}
+
+
+/* TODO: Autocrypt: a function that produces a list of
+   Autocrypt-Gossip headers from a message */
diff --git a/gmime/gmime-message.h b/gmime/gmime-message.h
index 9cabd6f..7357242 100644
--- a/gmime/gmime-message.h
+++ b/gmime/gmime-message.h
@@ -30,6 +30,7 @@
 #include <gmime/gmime-object.h>
 #include <gmime/gmime-header.h>
 #include <gmime/gmime-stream.h>
+#include <gmime/gmime-autocrypt.h>
 
 G_BEGIN_DECLS
 
@@ -122,6 +123,8 @@ const char *g_mime_message_get_message_id (GMimeMessage *message);
 GMimeObject *g_mime_message_get_mime_part (GMimeMessage *message);
 void g_mime_message_set_mime_part (GMimeMessage *message, GMimeObject *mime_part);
 
+GMimeAutocryptHeaderList *g_mime_message_get_autocrypt_headers (GMimeMessage *part, gint actype, GDateTime 
*now);
+
 /* convenience functions */
 
 void g_mime_message_foreach (GMimeMessage *message, GMimeObjectForeachFunc callback,


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