[evolution-data-server] Camel: Special-case search for the match of the MESSAGE-ID headers



commit f302e70f991d9d351ef27ecc552d8a506d2f9524
Author: Milan Crha <mcrha redhat com>
Date:   Thu Oct 29 12:55:00 2020 +0100

    Camel: Special-case search for the match of the MESSAGE-ID headers
    
    This helps to search for it quickly, by using the local summary data.
    
    Related to https://bugzilla.gnome.org/show_bug.cgi?id=788192

 docs/reference/camel/camel-docs.sgml.in |  4 +++
 src/camel/camel-folder-search.c         | 49 +++++++++++++++++++++++++++++++++
 src/camel/camel-folder-search.h         |  3 ++
 src/camel/camel-folder-summary.c        | 38 +++++--------------------
 src/camel/camel-search-sql-sexp.c       | 15 +++++++++-
 5 files changed, 77 insertions(+), 32 deletions(-)
---
diff --git a/docs/reference/camel/camel-docs.sgml.in b/docs/reference/camel/camel-docs.sgml.in
index 25dd20102..f72214645 100644
--- a/docs/reference/camel/camel-docs.sgml.in
+++ b/docs/reference/camel/camel-docs.sgml.in
@@ -297,6 +297,10 @@
     <title>Index of deprecated symbols</title>
     <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
   </index>
+  <index id="api-index-3-40" role="3.40">
+    <title>Index of new symbols in 3.40</title>
+    <xi:include href="xml/api-index-3.40.xml"><xi:fallback /></xi:include>
+  </index>
   <index id="api-index-3-38" role="3.38">
     <title>Index of new symbols in 3.38</title>
     <xi:include href="xml/api-index-3.38.xml"><xi:fallback /></xi:include>
diff --git a/src/camel/camel-folder-search.c b/src/camel/camel-folder-search.c
index 858ff79f4..b5db023b2 100644
--- a/src/camel/camel-folder-search.c
+++ b/src/camel/camel-folder-search.c
@@ -342,6 +342,7 @@ check_header (CamelSExp *sexp,
                const gchar *header = NULL, *charset = NULL;
                gchar strbuf[32];
                gint i, j;
+               gboolean is_message_id = FALSE;
                camel_search_t type = CAMEL_SEARCH_TYPE_ASIS;
                struct _camel_search_words *words;
                CamelMimeMessage *message = NULL;
@@ -368,6 +369,8 @@ check_header (CamelSExp *sexp,
                } else if (!g_ascii_strcasecmp (headername, "x-camel-mlist")) {
                        header = camel_message_info_get_mlist (search->priv->current);
                        type = CAMEL_SEARCH_TYPE_MLIST;
+               } else if (how == CAMEL_SEARCH_MATCH_EXACT && !g_ascii_strcasecmp (headername, "MESSAGE-ID")) 
{
+                       is_message_id = TRUE;
                } else {
                        message = ref_current_message (search);
                        if (message) {
@@ -417,6 +420,11 @@ check_header (CamelSExp *sexp,
                                                                how, type, charset);
                                        }
                                        camel_search_words_free (words);
+                               } else if (is_message_id) {
+                                       guint64 message_id;
+
+                                       message_id = camel_folder_search_util_hash_message_id 
(argv[i]->value.string, TRUE);
+                                       truth = camel_message_info_get_message_id (search->priv->current) == 
message_id;
                                } else {
                                        if (message) {
                                                const CamelNameValueArray *headers = NULL;
@@ -2629,3 +2637,44 @@ camel_folder_search_util_compare_date (gint64 datetime1,
 
        return dt1 - dt2;
 }
+
+/**
+ * camel_folder_search_util_hash_message_id:
+ * @message_id: a raw Message-ID header value
+ * @needs_decode: whether the @message_id requires camel_header_msgid_decode() first
+ *
+ * Calculates a hash of the Message-ID header value @message_id.
+ *
+ * Returns: hash of the @message_id, or 0 on any error.
+ *
+ * Since: 3.40
+ **/
+guint64
+camel_folder_search_util_hash_message_id (const gchar *message_id,
+                                         gboolean needs_decode)
+{
+       GChecksum *checksum;
+       CamelSummaryMessageID message_id_struct;
+       gchar *msgid = NULL;
+       guint8 *digest;
+       gsize length;
+
+       if (!message_id)
+               return 0;
+
+       if (needs_decode)
+               msgid = camel_header_msgid_decode (message_id);
+
+       length = g_checksum_type_get_length (G_CHECKSUM_MD5);
+       digest = g_alloca (length);
+
+       checksum = g_checksum_new (G_CHECKSUM_MD5);
+       g_checksum_update (checksum, (guchar *) (msgid ? msgid : message_id), -1);
+       g_checksum_get_digest (checksum, digest, &length);
+       g_checksum_free (checksum);
+
+       memcpy (message_id_struct.id.hash, digest, sizeof (message_id_struct.id.hash));
+       g_free (msgid);
+
+       return message_id_struct.id.id;
+}
diff --git a/src/camel/camel-folder-search.h b/src/camel/camel-folder-search.h
index fc95bf8c1..be6d6f05f 100644
--- a/src/camel/camel-folder-search.h
+++ b/src/camel/camel-folder-search.h
@@ -331,6 +331,9 @@ time_t              camel_folder_search_util_make_time
 gint           camel_folder_search_util_compare_date
                                                (gint64 datetime1,
                                                 gint64 datetime2);
+guint64                camel_folder_search_util_hash_message_id
+                                               (const gchar *message_id,
+                                                gboolean needs_decode);
 G_END_DECLS
 
 #endif /* CAMEL_FOLDER_SEARCH_H */
diff --git a/src/camel/camel-folder-summary.c b/src/camel/camel-folder-summary.c
index 0b33bb5ec..af80a658e 100644
--- a/src/camel/camel-folder-summary.c
+++ b/src/camel/camel-folder-summary.c
@@ -2944,19 +2944,13 @@ static CamelMessageInfo *
 message_info_new_from_headers (CamelFolderSummary *summary,
                               const CamelNameValueArray *headers)
 {
-       const gchar *received, *date, *content, *charset = NULL;
+       const gchar *received, *date, *content, *charset = NULL, *msgid;
        GSList *refs, *irt, *scan;
        gchar *subject, *from, *to, *cc, *mlist;
        CamelContentType *ct = NULL;
        CamelMessageInfo *mi;
-       guint8 *digest;
-       gsize length;
-       gchar *msgid;
        guint count;
 
-       length = g_checksum_type_get_length (G_CHECKSUM_MD5);
-       digest = g_alloca (length);
-
        mi = camel_message_info_new (summary);
 
        camel_message_info_set_abort_notifications (mi, TRUE);
@@ -3008,28 +3002,15 @@ message_info_new_from_headers (CamelFolderSummary *summary,
        if (!camel_message_info_get_date_sent (mi))
                camel_message_info_set_date_sent (mi, (gint64) time (NULL));
 
-       msgid = camel_header_msgid_decode (camel_name_value_array_get_named (headers, 
CAMEL_COMPARE_CASE_INSENSITIVE, "Message-ID"));
-       if (msgid) {
-               GChecksum *checksum;
-               CamelSummaryMessageID message_id;
-
-               checksum = g_checksum_new (G_CHECKSUM_MD5);
-               g_checksum_update (checksum, (guchar *) msgid, -1);
-               g_checksum_get_digest (checksum, digest, &length);
-               g_checksum_free (checksum);
-
-               memcpy (message_id.id.hash, digest, sizeof (message_id.id.hash));
-               g_free (msgid);
-
-               camel_message_info_set_message_id (mi, message_id.id.id);
-       }
+       msgid = camel_name_value_array_get_named (headers, CAMEL_COMPARE_CASE_INSENSITIVE, "Message-ID");
+       if (msgid)
+               camel_message_info_set_message_id (mi, camel_folder_search_util_hash_message_id (msgid, 
TRUE));
 
        /* decode our references and in-reply-to headers */
        refs = camel_header_references_decode (camel_name_value_array_get_named (headers, 
CAMEL_COMPARE_CASE_INSENSITIVE, "References"));
        irt = camel_header_references_decode (camel_name_value_array_get_named (headers, 
CAMEL_COMPARE_CASE_INSENSITIVE, "In-Reply-To"));
        if (refs || irt) {
                GArray *references;
-               CamelSummaryMessageID message_id;
 
                if (irt) {
                        /* The References field is populated from the "References" and/or "In-Reply-To"
@@ -3046,16 +3027,11 @@ message_info_new_from_headers (CamelFolderSummary *summary,
                references = g_array_sized_new (FALSE, FALSE, sizeof (guint64), count);
 
                for (scan = refs; scan != NULL; scan = g_slist_next (scan)) {
-                       GChecksum *checksum;
-
-                       checksum = g_checksum_new (G_CHECKSUM_MD5);
-                       g_checksum_update (checksum, (guchar *) scan->data, -1);
-                       g_checksum_get_digest (checksum, digest, &length);
-                       g_checksum_free (checksum);
+                       guint64 msgid_hash;
 
-                       memcpy (message_id.id.hash, digest, sizeof (message_id.id.hash));
+                       msgid_hash = camel_folder_search_util_hash_message_id (scan->data, FALSE);
 
-                       g_array_append_val (references, message_id.id.id);
+                       g_array_append_val (references, msgid_hash);
                }
                g_slist_free_full (refs, g_free);
 
diff --git a/src/camel/camel-search-sql-sexp.c b/src/camel/camel-search-sql-sexp.c
index 59e99435a..d2bfb66fe 100644
--- a/src/camel/camel-search-sql-sexp.c
+++ b/src/camel/camel-search-sql-sexp.c
@@ -391,6 +391,10 @@ check_header (struct _CamelSExp *f,
 
                /* only a subset of headers are supported .. */
                headername = camel_db_get_column_name (argv[0]->value.string);
+               if (!headername && how == CAMEL_SEARCH_MATCH_EXACT &&
+                   g_ascii_strcasecmp (argv[0]->value.string ? argv[0]->value.string : "", "MESSAGE-ID") == 
0) {
+                       headername = g_strdup ("part");
+               }
                if (!headername) {
                        gboolean *pcontains_unknown_column = (gboolean *) data;
                        *pcontains_unknown_column = TRUE;
@@ -417,7 +421,16 @@ check_header (struct _CamelSExp *f,
                                        value = get_db_safe_string (tstr);
                                        g_free (tstr);
                                } else if (how == CAMEL_SEARCH_MATCH_EXACT) {
-                                       tstr = g_strdup_printf ("%c%s%c", '%', argv[i]->value.string, '%');
+                                       if (g_ascii_strcasecmp (headername, "part") == 0) {
+                                               CamelSummaryMessageID message_id;
+
+                                               message_id.id.id = camel_folder_search_util_hash_message_id 
(argv[i]->value.string, TRUE);
+
+                                               tstr = g_strdup_printf ("%lu %lu %%", (gulong) 
message_id.id.part.hi, (gulong) message_id.id.part.lo);
+                                       } else {
+                                               tstr = g_strdup_printf ("%c%s%c", '%', argv[i]->value.string, 
'%');
+                                       }
+
                                        value = get_db_safe_string (tstr);
                                        g_free (tstr);
                                }


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