[gmime: 14/23] Autocrypt: add g_mime_message_get_autocrypt_headers()
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime: 14/23] Autocrypt: add g_mime_message_get_autocrypt_headers()
- Date: Sun, 29 Oct 2017 14:16:49 +0000 (UTC)
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]