From a45cfac852ae0825d5635abc939978f4a192b8a6 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jun 2020 12:59:21 -0700 Subject: [PATCH] Rebuild with newer protobuf and libphonenumber, backport fixes --- ...h-All-condition-doesn-t-show-any-mes.patch | 283 ++++++++++++ ...age-contains-search-broken-in-3.36.3.patch | 435 ++++++++++++++++++ ...rch-Fix-a-memory-leak-when-searching.patch | 30 ++ ...age-contains-search-broken-in-3.36.3.patch | 81 ++++ evolution-data-server.spec | 15 +- 5 files changed, 842 insertions(+), 2 deletions(-) create mode 100644 0001-I-222-Camel-Match-All-condition-doesn-t-show-any-mes.patch create mode 100644 0002-evo-I-982-Message-contains-search-broken-in-3.36.3.patch create mode 100644 0003-camel-folder-search-Fix-a-memory-leak-when-searching.patch create mode 100644 0004-evo-I-982-Message-contains-search-broken-in-3.36.3.patch diff --git a/0001-I-222-Camel-Match-All-condition-doesn-t-show-any-mes.patch b/0001-I-222-Camel-Match-All-condition-doesn-t-show-any-mes.patch new file mode 100644 index 0000000..69487ce --- /dev/null +++ b/0001-I-222-Camel-Match-All-condition-doesn-t-show-any-mes.patch @@ -0,0 +1,283 @@ +From e59414460e833e36585e04260f257fa128f518e0 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Mon, 1 Jun 2020 17:40:41 +0200 +Subject: [PATCH 1/4] I#222 - Camel: Match-All condition doesn't show any + messages + +Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/222 +--- + src/camel/camel-folder-search.c | 8 +-- + src/camel/camel-search-sql-sexp.c | 109 ++++++++++++++++-------------- + 2 files changed, 62 insertions(+), 55 deletions(-) + +diff --git a/src/camel/camel-folder-search.c b/src/camel/camel-folder-search.c +index 33741fd4e..346af67a4 100644 +--- a/src/camel/camel-folder-search.c ++++ b/src/camel/camel-folder-search.c +@@ -2256,10 +2256,10 @@ camel_folder_search_count (CamelFolderSearch *search, + + dd (printf ("sexp is : [%s]\n", expr)); + tmp1 = camel_db_sqlize_string (full_name); +- tmp = g_strdup_printf ("SELECT COUNT (*) FROM %s %s %s", tmp1, sql_query ? "WHERE" : "", sql_query ? sql_query : ""); ++ tmp = g_strdup_printf ("SELECT COUNT (*) FROM %s %s %s", tmp1, (sql_query && *sql_query) ? "WHERE" : "", sql_query ? sql_query : ""); + camel_db_free_sqlized_string (tmp1); + g_free (sql_query); +- dd (printf ("Equivalent sql %s\n", tmp)); ++ dd (printf ("Equivalent sql: \"%s\"\n", tmp)); + + cdb = camel_store_get_db (parent_store); + camel_db_count_message_info (cdb, tmp, &count, &local_error); +@@ -2432,10 +2432,10 @@ camel_folder_search_search (CamelFolderSearch *search, + + dd (printf ("sexp is : [%s]\n", expr)); + tmp1 = camel_db_sqlize_string (full_name); +- tmp = g_strdup_printf ("SELECT uid FROM %s %s %s", tmp1, sql_query ? "WHERE":"", sql_query ? sql_query:""); ++ tmp = g_strdup_printf ("SELECT uid FROM %s %s %s", tmp1, (sql_query && *sql_query) ? "WHERE" : "", sql_query ? sql_query : ""); + camel_db_free_sqlized_string (tmp1); + g_free (sql_query); +- dd (printf ("Equivalent sql %s\n", tmp)); ++ dd (printf ("Equivalent sql: \"%s\"\n", tmp)); + + matches = g_ptr_array_new (); + cdb = camel_store_get_db (parent_store); +diff --git a/src/camel/camel-search-sql-sexp.c b/src/camel/camel-search-sql-sexp.c +index 72489694a..59e99435a 100644 +--- a/src/camel/camel-search-sql-sexp.c ++++ b/src/camel/camel-search-sql-sexp.c +@@ -72,69 +72,75 @@ get_db_safe_string (const gchar *str) + } + + /* Configuration of your sexp expression */ +- + static CamelSExpResult * +-func_and (CamelSExp *f, +- gint argc, +- struct _CamelSExpTerm **argv, +- gpointer data) ++func_and_or (CamelSExp *f, ++ gint argc, ++ struct _CamelSExpTerm **argv, ++ const gchar *term) + { + CamelSExpResult *r, *r1; + GString *string; + gint i; + +- d (printf ("executing and: %d", argc)); ++ string = NULL; + +- string = g_string_new ("( "); + for (i = 0; i < argc; i++) { + r1 = camel_sexp_term_eval (f, argv[i]); + +- if (r1->type != CAMEL_SEXP_RES_STRING) { +- camel_sexp_result_free (f, r1); +- continue; ++ if (r1->type == CAMEL_SEXP_RES_STRING && ++ r1->value.string && *r1->value.string) { ++ if (!string) ++ string = g_string_new ("( "); ++ ++ if (string->len > 2) { ++ g_string_append_c (string, ' '); ++ g_string_append (string, term); ++ g_string_append_c (string, ' '); ++ } ++ ++ g_string_append (string, r1->value.string); + } +- if (r1->value.string && *r1->value.string) +- g_string_append_printf (string, "%s%s", r1->value.string, ((argc > 1) && (i != argc - 1)) ? " AND ":""); ++ + camel_sexp_result_free (f, r1); + } +- g_string_append (string, " )"); ++ + r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING); + +- if (string->len == 4) +- g_string_set_size (string, 0); +- r->value.string = g_string_free (string, FALSE); ++ if (string) { ++ if (string->len == 2) ++ g_string_set_size (string, 0); ++ else ++ g_string_append (string, " )"); ++ ++ r->value.string = g_string_free (string, FALSE); ++ } else { ++ r->value.string = g_strdup (""); ++ } + + return r; + } + ++static CamelSExpResult * ++func_and (CamelSExp *f, ++ gint argc, ++ struct _CamelSExpTerm **argv, ++ gpointer data) ++{ ++ ++ d (printf ("executing and: %d\n", argc)); ++ ++ return func_and_or (f, argc, argv, "AND"); ++} ++ + static CamelSExpResult * + func_or (CamelSExp *f, + gint argc, + struct _CamelSExpTerm **argv, + gpointer data) + { +- CamelSExpResult *r, *r1; +- GString *string; +- gint i; +- +- d (printf ("executing or: %d", argc)); ++ d (printf ("executing or: %d\n", argc)); + +- string = g_string_new ("( "); +- for (i = 0; i < argc; i++) { +- r1 = camel_sexp_term_eval (f, argv[i]); +- +- if (r1->type != CAMEL_SEXP_RES_STRING) { +- camel_sexp_result_free (f, r1); +- continue; +- } +- g_string_append_printf (string, "%s%s", r1->value.string, ((argc > 1) && (i != argc - 1)) ? " OR ":""); +- camel_sexp_result_free (f, r1); +- } +- g_string_append (string, " )"); +- +- r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING); +- r->value.string = g_string_free (string, FALSE); +- return r; ++ return func_and_or (f, argc, argv, "OR"); + } + + static CamelSExpResult * +@@ -145,7 +151,7 @@ func_not (CamelSExp *f, + { + CamelSExpResult *r = NULL, *r1; + +- d (printf ("executing not: %d", argc)); ++ d (printf ("executing not: %d\n", argc)); + r1 = camel_sexp_term_eval (f, argv[0]); + + if (r1->type == CAMEL_SEXP_RES_STRING) { +@@ -153,9 +159,10 @@ func_not (CamelSExp *f, + /* HACK: Fix and handle completed-on better. */ + if (g_strcmp0 (r1->value.string, "( (usertags LIKE '%completed-on 0%' AND usertags LIKE '%completed-on%') )") == 0) + r->value.string = g_strdup ("( (not (usertags LIKE '%completed-on 0%')) AND usertags LIKE '%completed-on%' )"); ++ else if (r1->value.string && *r1->value.string) ++ r->value.string = g_strdup_printf ("(NOT (%s))", r1->value.string); + else +- r->value.string = g_strdup_printf ( +- "(NOT (%s))", r1->value.string); ++ r->value.string = g_strdup (""); + } + camel_sexp_result_free (f, r1); + +@@ -325,7 +332,7 @@ match_all (struct _CamelSExp *f, + { + CamelSExpResult *r; + +- d (printf ("executing match-all: %d", argc)); ++ d (printf ("executing match-all: %d\n", argc)); + if (argc == 0) { + r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING); + r->value.string = g_strdup ("1"); +@@ -350,7 +357,7 @@ match_threads (struct _CamelSExp *f, + gint i; + GString *str = g_string_new ("( "); + +- d (printf ("executing match-threads: %d", argc)); ++ d (printf ("executing match-threads: %d\n", argc)); + + for (i = 1; i < argc; i++) { + r = camel_sexp_term_eval (f, argv[i]); +@@ -434,7 +441,7 @@ header_contains (struct _CamelSExp *f, + struct _CamelSExpResult **argv, + gpointer data) + { +- d (printf ("executing header-contains: %d", argc)); ++ d (printf ("executing header-contains: %d\n", argc)); + + return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_CONTAINS); + } +@@ -445,7 +452,7 @@ header_has_words (struct _CamelSExp *f, + struct _CamelSExpResult **argv, + gpointer data) + { +- d (printf ("executing header-has-word: %d", argc)); ++ d (printf ("executing header-has-word: %d\n", argc)); + + return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_WORD); + } +@@ -456,7 +463,7 @@ header_matches (struct _CamelSExp *f, + struct _CamelSExpResult **argv, + gpointer data) + { +- d (printf ("executing header-matches: %d", argc)); ++ d (printf ("executing header-matches: %d\n", argc)); + + return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_EXACT); + } +@@ -467,7 +474,7 @@ header_starts_with (struct _CamelSExp *f, + struct _CamelSExpResult **argv, + gpointer data) + { +- d (printf ("executing header-starts-with: %d", argc)); ++ d (printf ("executing header-starts-with: %d\n", argc)); + + return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_STARTS); + } +@@ -478,7 +485,7 @@ header_ends_with (struct _CamelSExp *f, + struct _CamelSExpResult **argv, + gpointer data) + { +- d (printf ("executing header-ends-with: %d", argc)); ++ d (printf ("executing header-ends-with: %d\n", argc)); + + return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_ENDS); + } +@@ -492,7 +499,7 @@ header_exists (struct _CamelSExp *f, + CamelSExpResult *r; + gchar *headername; + +- d (printf ("executing header-exists: %d", argc)); ++ d (printf ("executing header-exists: %d\n", argc)); + + headername = camel_db_get_column_name (argv[0]->value.string); + if (!headername) { +@@ -517,7 +524,7 @@ user_tag (struct _CamelSExp *f, + { + CamelSExpResult *r; + +- d (printf ("executing user-tag: %d", argc)); ++ d (printf ("executing user-tag: %d\n", argc)); + + r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING); + /* Hacks no otherway to fix these really :( */ +@@ -541,7 +548,7 @@ user_flag (struct _CamelSExp *f, + CamelSExpResult *r; + gchar *tstr, *qstr; + +- d (printf ("executing user-flag: %d", argc)); ++ d (printf ("executing user-flag: %d\n", argc)); + + r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING); + +@@ -567,7 +574,7 @@ system_flag (struct _CamelSExp *f, + CamelSExpResult *r; + gchar *tstr; + +- d (printf ("executing system-flag: %d", argc)); ++ d (printf ("executing system-flag: %d\n", argc)); + + r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING); + +-- +2.27.0 + diff --git a/0002-evo-I-982-Message-contains-search-broken-in-3.36.3.patch b/0002-evo-I-982-Message-contains-search-broken-in-3.36.3.patch new file mode 100644 index 0000000..489f944 --- /dev/null +++ b/0002-evo-I-982-Message-contains-search-broken-in-3.36.3.patch @@ -0,0 +1,435 @@ +From 16562adadd9e7534852d29b365aaecce0dd43b84 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Thu, 11 Jun 2020 19:07:38 +0200 +Subject: [PATCH 2/4] evo-I#982 - 'Message contains'-search broken in 3.36.3 + +Related to https://gitlab.gnome.org/GNOME/evolution/-/issues/982 +--- + .../providers/imapx/camel-imapx-folder.c | 6 + + .../providers/imapx/camel-imapx-search.c | 223 +++++++++--------- + .../providers/imapx/camel-imapx-search.h | 2 + + 3 files changed, 114 insertions(+), 117 deletions(-) + +diff --git a/src/camel/providers/imapx/camel-imapx-folder.c b/src/camel/providers/imapx/camel-imapx-folder.c +index 0df26f1e9..1ef5750fc 100644 +--- a/src/camel/providers/imapx/camel-imapx-folder.c ++++ b/src/camel/providers/imapx/camel-imapx-folder.c +@@ -347,12 +347,14 @@ imapx_search_by_uids (CamelFolder *folder, + imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search); + + camel_folder_search_set_folder (imapx_folder->search, folder); ++ camel_imapx_search_clear_cached_results (imapx_search); + camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error); + + matches = camel_folder_search_search ( + imapx_folder->search, expression, uids, cancellable, error); + + camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL); ++ camel_imapx_search_clear_cached_results (imapx_search); + + g_mutex_unlock (&imapx_folder->search_lock); + +@@ -376,12 +378,14 @@ imapx_count_by_expression (CamelFolder *folder, + imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search); + + camel_folder_search_set_folder (imapx_folder->search, folder); ++ camel_imapx_search_clear_cached_results (imapx_search); + camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error); + + matches = camel_folder_search_count ( + imapx_folder->search, expression, cancellable, error); + + camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL); ++ camel_imapx_search_clear_cached_results (imapx_search); + + g_mutex_unlock (&imapx_folder->search_lock); + +@@ -405,12 +409,14 @@ imapx_search_by_expression (CamelFolder *folder, + imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search); + + camel_folder_search_set_folder (imapx_folder->search, folder); ++ camel_imapx_search_clear_cached_results (imapx_search); + camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error); + + matches = camel_folder_search_search ( + imapx_folder->search, expression, NULL, cancellable, error); + + camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL); ++ camel_imapx_search_clear_cached_results (imapx_search); + + g_mutex_unlock (&imapx_folder->search_lock); + +diff --git a/src/camel/providers/imapx/camel-imapx-search.c b/src/camel/providers/imapx/camel-imapx-search.c +index 6d68f700e..7c62443b8 100644 +--- a/src/camel/providers/imapx/camel-imapx-search.c ++++ b/src/camel/providers/imapx/camel-imapx-search.c +@@ -29,6 +29,7 @@ struct _CamelIMAPXSearchPrivate { + GWeakRef imapx_store; + gint *local_data_search; /* not NULL, if testing whether all used headers are all locally available */ + ++ GHashTable *cached_results; /* gchar * (search description) ~> GHashTable { gchar * (uid {from string pool}) ~> NULL } */ + GCancellable *cancellable; /* not referenced */ + GError **error; /* not referenced */ + }; +@@ -99,6 +100,7 @@ imapx_search_finalize (GObject *object) + priv = CAMEL_IMAPX_SEARCH (object)->priv; + + g_weak_ref_clear (&priv->imapx_store); ++ g_hash_table_destroy (priv->cached_results); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (camel_imapx_search_parent_class)->finalize (object); +@@ -153,6 +155,43 @@ imapx_search_result_match_none (CamelSExp *sexp, + return result; + } + ++static gchar * ++imapx_search_describe_criteria (const GString *criteria_prefix, ++ const gchar *search_key, ++ const GPtrArray *words) ++{ ++ GString *desc; ++ ++ desc = g_string_sized_new (64); ++ ++ if (criteria_prefix && criteria_prefix->len) ++ g_string_append (desc, criteria_prefix->str); ++ ++ g_string_append_c (desc, '\n'); ++ ++ if (search_key && *search_key) ++ g_string_append (desc, search_key); ++ ++ g_string_append_c (desc, '\n'); ++ ++ if (words && words->len) { ++ guint ii; ++ ++ for (ii = 0; ii < words->len; ii++) { ++ const gchar *word = words->pdata[ii]; ++ ++ if (word) { ++ g_string_append (desc, word); ++ g_string_append_c (desc, '\n'); ++ } ++ } ++ } ++ ++ g_string_append_c (desc, '\n'); ++ ++ return g_string_free (desc, FALSE); ++} ++ + static CamelSExpResult * + imapx_search_process_criteria (CamelSExp *sexp, + CamelFolderSearch *search, +@@ -165,114 +204,89 @@ imapx_search_process_criteria (CamelSExp *sexp, + CamelSExpResult *result; + CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search); + CamelIMAPXMailbox *mailbox; ++ CamelMessageInfo *info; ++ GHashTable *cached_results; ++ gchar *criteria_desc; + GPtrArray *uids = NULL; + GError *local_error = NULL; + +- mailbox = camel_imapx_folder_list_mailbox ( +- CAMEL_IMAPX_FOLDER (camel_folder_search_get_folder (search)), imapx_search->priv->cancellable, &local_error); ++ criteria_desc = imapx_search_describe_criteria (criteria_prefix, search_key, words); ++ cached_results = g_hash_table_lookup (imapx_search->priv->cached_results, criteria_desc); + +- /* Sanity check. */ +- g_return_val_if_fail ( +- ((mailbox != NULL) && (local_error == NULL)) || +- ((mailbox == NULL) && (local_error != NULL)), NULL); ++ if (!cached_results) { ++ mailbox = camel_imapx_folder_list_mailbox ( ++ CAMEL_IMAPX_FOLDER (camel_folder_search_get_folder (search)), imapx_search->priv->cancellable, &local_error); + +- if (mailbox != NULL) { +- CamelIMAPXConnManager *conn_man; ++ /* Sanity check. */ ++ g_return_val_if_fail ( ++ ((mailbox != NULL) && (local_error == NULL)) || ++ ((mailbox == NULL) && (local_error != NULL)), NULL); + +- conn_man = camel_imapx_store_get_conn_manager (imapx_store); +- uids = camel_imapx_conn_manager_uid_search_sync (conn_man, mailbox, criteria_prefix->str, search_key, +- words ? (const gchar * const *) words->pdata : NULL, imapx_search->priv->cancellable, &local_error); ++ if (mailbox != NULL) { ++ CamelIMAPXConnManager *conn_man; + +- g_object_unref (mailbox); +- } ++ conn_man = camel_imapx_store_get_conn_manager (imapx_store); ++ uids = camel_imapx_conn_manager_uid_search_sync (conn_man, mailbox, criteria_prefix ? criteria_prefix->str : "", search_key, ++ words ? (const gchar * const *) words->pdata : NULL, imapx_search->priv->cancellable, &local_error); ++ g_object_unref (mailbox); ++ } + +- /* Sanity check. */ +- g_return_val_if_fail ( +- ((uids != NULL) && (local_error == NULL)) || +- ((uids == NULL) && (local_error != NULL)), NULL); ++ /* Sanity check. */ ++ g_return_val_if_fail ( ++ ((uids != NULL) && (local_error == NULL)) || ++ ((uids == NULL) && (local_error != NULL)), NULL); + +- if (local_error != NULL) { +- g_propagate_error (imapx_search->priv->error, local_error); ++ if (local_error != NULL) { ++ g_propagate_error (imapx_search->priv->error, local_error); + +- /* Make like we've got an empty result */ +- uids = g_ptr_array_new (); ++ /* Make like we've got an empty result */ ++ uids = g_ptr_array_new (); ++ } + } + +- if (camel_folder_search_get_current_message_info (search)) { ++ info = camel_folder_search_get_current_message_info (search); ++ ++ if (info) { + result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL); +- result->value.boolean = (uids && uids->len > 0); ++ result->value.boolean = cached_results ? g_hash_table_contains (cached_results, camel_message_info_get_uid (info)) : (uids && uids->len > 0); + } else { +- result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR); +- result->value.ptrarray = g_ptr_array_ref (uids); +- } ++ if (cached_results) { ++ GHashTableIter iter; ++ gpointer key; + +- g_ptr_array_unref (uids); ++ g_warn_if_fail (uids == NULL); + +- return result; +-} ++ uids = g_ptr_array_sized_new (g_hash_table_size (cached_results)); + +-static CamelSExpResult * +-imapx_search_match_all (CamelSExp *sexp, +- gint argc, +- CamelSExpTerm **argv, +- CamelFolderSearch *search) +-{ +- CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search); +- CamelIMAPXStore *imapx_store; +- CamelSExpResult *result; +- GPtrArray *summary; +- gint local_data_search = 0, *prev_local_data_search, ii; ++ g_hash_table_iter_init (&iter, cached_results); + +- if (argc != 1) +- return imapx_search_result_match_none (sexp, search); +- +- imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search)); +- if (!imapx_store || camel_folder_search_get_current_message_info (search) || !camel_folder_search_get_summary (search)) { +- g_clear_object (&imapx_store); ++ while (g_hash_table_iter_next (&iter, &key, NULL)) { ++ g_ptr_array_add (uids, (gpointer) camel_pstring_strdup (key)); ++ } ++ } + +- /* Chain up to parent's method. */ +- return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)-> +- match_all (sexp, argc, argv, search); ++ result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR); ++ result->value.ptrarray = g_ptr_array_ref (uids); + } + +- /* First try to see whether all used headers are available locally - if +- * they are, then do not use server-side filtering at all. */ +- prev_local_data_search = imapx_search->priv->local_data_search; +- imapx_search->priv->local_data_search = &local_data_search; ++ if (!cached_results) { ++ cached_results = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL); + +- summary = camel_folder_search_get_current_summary (search); ++ if (uids) { ++ guint ii; + +- if (!CAMEL_IS_VEE_FOLDER (camel_folder_search_get_folder (search))) { +- camel_folder_summary_prepare_fetch_all (camel_folder_get_folder_summary (camel_folder_search_get_folder (search)), NULL); +- } +- +- for (ii = 0; ii < summary->len; ii++) { +- camel_folder_search_take_current_message_info (search, camel_folder_summary_get (camel_folder_get_folder_summary (camel_folder_search_get_folder (search)), summary->pdata[ii])); +- if (camel_folder_search_get_current_message_info (search)) { +- result = camel_sexp_term_eval (sexp, argv[0]); +- camel_sexp_result_free (sexp, result); +- camel_folder_search_set_current_message_info (search, NULL); +- break; ++ for (ii = 0; ii < uids->len; ii++) { ++ g_hash_table_insert (cached_results, (gpointer) camel_pstring_strdup (uids->pdata[ii]), NULL); ++ } + } +- } +- imapx_search->priv->local_data_search = prev_local_data_search; +- +- if (local_data_search >= 0) { +- g_clear_object (&imapx_store); + +- /* Chain up to parent's method. */ +- return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)-> +- match_all (sexp, argc, argv, search); ++ g_hash_table_insert (imapx_search->priv->cached_results, criteria_desc, cached_results); ++ } else { ++ g_free (criteria_desc); + } + +- /* let's change the requirements a bit, the parent class expects as a result boolean, +- * but here is expected GPtrArray of matched UIDs */ +- result = camel_sexp_term_eval (sexp, argv[0]); +- +- g_object_unref (imapx_store); +- +- g_return_val_if_fail (result != NULL, result); +- g_return_val_if_fail (result->type == CAMEL_SEXP_RES_ARRAY_PTR, result); ++ if (uids) ++ g_ptr_array_unref (uids); + + return result; + } +@@ -338,7 +352,6 @@ imapx_search_body_contains (CamelSExp *sexp, + CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search); + CamelIMAPXStore *imapx_store; + CamelSExpResult *result; +- GString *criteria; + GPtrArray *words; + gboolean is_gmail; + +@@ -367,23 +380,12 @@ imapx_search_body_contains (CamelSExp *sexp, + + /* Build the IMAP search criteria. */ + +- criteria = g_string_sized_new (128); +- +- if (camel_folder_search_get_current_message_info (search)) { +- const gchar *uid; +- +- /* Limit the search to a single UID. */ +- uid = camel_message_info_get_uid (camel_folder_search_get_current_message_info (search)); +- g_string_append_printf (criteria, "UID %s", uid); +- } +- + words = imapx_search_gather_words (argv, 0, argc); + +- result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, "BODY", words, G_STRFUNC); ++ result = imapx_search_process_criteria (sexp, search, imapx_store, NULL, "BODY", words, G_STRFUNC); + + is_gmail = camel_imapx_store_is_gmail_server (imapx_store); + +- g_string_free (criteria, TRUE); + g_ptr_array_free (words, TRUE); + g_object_unref (imapx_store); + +@@ -470,7 +472,6 @@ imapx_search_header_contains (CamelSExp *sexp, + CamelIMAPXStore *imapx_store; + CamelSExpResult *result; + const gchar *headername, *command = NULL; +- GString *criteria; + gchar *search_key = NULL; + GPtrArray *words; + +@@ -508,16 +509,6 @@ imapx_search_header_contains (CamelSExp *sexp, + + /* Build the IMAP search criteria. */ + +- criteria = g_string_sized_new (128); +- +- if (camel_folder_search_get_current_message_info (search)) { +- const gchar *uid; +- +- /* Limit the search to a single UID. */ +- uid = camel_message_info_get_uid (camel_folder_search_get_current_message_info (search)); +- g_string_append_printf (criteria, "UID %s", uid); +- } +- + if (g_ascii_strcasecmp (headername, "From") == 0) + command = "FROM"; + else if (g_ascii_strcasecmp (headername, "To") == 0) +@@ -534,9 +525,8 @@ imapx_search_header_contains (CamelSExp *sexp, + if (!command) + search_key = g_strdup_printf ("HEADER \"%s\"", headername); + +- result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, command ? command : search_key, words, G_STRFUNC); ++ result = imapx_search_process_criteria (sexp, search, imapx_store, NULL, command ? command : search_key, words, G_STRFUNC); + +- g_string_free (criteria, TRUE); + g_ptr_array_free (words, TRUE); + g_object_unref (imapx_store); + g_free (search_key); +@@ -599,14 +589,6 @@ imapx_search_header_exists (CamelSExp *sexp, + + criteria = g_string_sized_new (128); + +- if (camel_folder_search_get_current_message_info (search)) { +- const gchar *uid; +- +- /* Limit the search to a single UID. */ +- uid = camel_message_info_get_uid (camel_folder_search_get_current_message_info (search)); +- g_string_append_printf (criteria, "UID %s", uid); +- } +- + for (ii = 0; ii < argc; ii++) { + const gchar *headername; + +@@ -623,7 +605,6 @@ imapx_search_header_exists (CamelSExp *sexp, + + result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, NULL, NULL, G_STRFUNC); + +- g_string_free (criteria, TRUE); + g_object_unref (imapx_store); + + return result; +@@ -642,7 +623,6 @@ camel_imapx_search_class_init (CamelIMAPXSearchClass *class) + object_class->finalize = imapx_search_finalize; + + search_class = CAMEL_FOLDER_SEARCH_CLASS (class); +- search_class->match_all = imapx_search_match_all; + search_class->body_contains = imapx_search_body_contains; + search_class->header_contains = imapx_search_header_contains; + search_class->header_exists = imapx_search_header_exists; +@@ -665,6 +645,7 @@ camel_imapx_search_init (CamelIMAPXSearch *search) + { + search->priv = camel_imapx_search_get_instance_private (search); + search->priv->local_data_search = NULL; ++ search->priv->cached_results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy); + + g_weak_ref_init (&search->priv->imapx_store, NULL); + } +@@ -764,6 +745,14 @@ camel_imapx_search_set_store (CamelIMAPXSearch *search, + g_object_notify (G_OBJECT (search), "store"); + } + ++void ++camel_imapx_search_clear_cached_results (CamelIMAPXSearch *search) ++{ ++ g_return_if_fail (CAMEL_IS_IMAPX_SEARCH (search)); ++ ++ g_hash_table_remove_all (search->priv->cached_results); ++} ++ + /** + * camel_imapx_search_set_cancellable_and_error: + * @search: a #CamelIMAPXSearch +diff --git a/src/camel/providers/imapx/camel-imapx-search.h b/src/camel/providers/imapx/camel-imapx-search.h +index 98959a5b0..75d816941 100644 +--- a/src/camel/providers/imapx/camel-imapx-search.h ++++ b/src/camel/providers/imapx/camel-imapx-search.h +@@ -75,6 +75,8 @@ CamelIMAPXStore * + camel_imapx_search_ref_store (CamelIMAPXSearch *search); + void camel_imapx_search_set_store (CamelIMAPXSearch *search, + CamelIMAPXStore *imapx_store); ++void camel_imapx_search_clear_cached_results ++ (CamelIMAPXSearch *search); + void camel_imapx_search_set_cancellable_and_error + (CamelIMAPXSearch *search, + GCancellable *cancellable, +-- +2.27.0 + diff --git a/0003-camel-folder-search-Fix-a-memory-leak-when-searching.patch b/0003-camel-folder-search-Fix-a-memory-leak-when-searching.patch new file mode 100644 index 0000000..48c0766 --- /dev/null +++ b/0003-camel-folder-search-Fix-a-memory-leak-when-searching.patch @@ -0,0 +1,30 @@ +From c951d611578b17ced604e18ec22c3d79d938dd2b Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Mon, 15 Jun 2020 14:25:34 +0200 +Subject: [PATCH 3/4] camel-folder-search: Fix a memory leak when searching + message body + +--- + src/camel/camel-folder-search.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/camel/camel-folder-search.c b/src/camel/camel-folder-search.c +index 346af67a4..858ff79f4 100644 +--- a/src/camel/camel-folder-search.c ++++ b/src/camel/camel-folder-search.c +@@ -617,8 +617,10 @@ match_words_1message (CamelDataWrapper *object, + if (camel_ustrstrcase ((const gchar *) byte_array->data, words->words[i]->word) != NULL) { + *mask |= (1 << i); + /* shortcut a match */ +- if (*mask == (1 << (words->len)) - 1) +- return TRUE; ++ if (*mask == (1 << (words->len)) - 1) { ++ truth = TRUE; ++ break; ++ } + } + } + +-- +2.27.0 + diff --git a/0004-evo-I-982-Message-contains-search-broken-in-3.36.3.patch b/0004-evo-I-982-Message-contains-search-broken-in-3.36.3.patch new file mode 100644 index 0000000..c7c8b40 --- /dev/null +++ b/0004-evo-I-982-Message-contains-search-broken-in-3.36.3.patch @@ -0,0 +1,81 @@ +From 70c6f2e2b204714ecb4d920eb0b10d8f54dc5e7d Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Mon, 15 Jun 2020 15:15:58 +0200 +Subject: [PATCH 4/4] evo-I#982 - 'Message contains'-search broken in 3.36.3 ][ + +Fix incorrect result, where the first call, which did the server-side +call, could return currently processed message as matching, even when +it did not match the search criteria. + +Related to https://gitlab.gnome.org/GNOME/evolution/-/issues/982 +--- + .../providers/imapx/camel-imapx-search.c | 38 +++++++++---------- + 1 file changed, 18 insertions(+), 20 deletions(-) + +diff --git a/src/camel/providers/imapx/camel-imapx-search.c b/src/camel/providers/imapx/camel-imapx-search.c +index 7c62443b8..2a34b389c 100644 +--- a/src/camel/providers/imapx/camel-imapx-search.c ++++ b/src/camel/providers/imapx/camel-imapx-search.c +@@ -244,18 +244,32 @@ imapx_search_process_criteria (CamelSExp *sexp, + } + } + ++ if (!cached_results) { ++ cached_results = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL); ++ ++ if (uids) { ++ guint ii; ++ ++ for (ii = 0; ii < uids->len; ii++) { ++ g_hash_table_insert (cached_results, (gpointer) camel_pstring_strdup (uids->pdata[ii]), NULL); ++ } ++ } ++ ++ g_hash_table_insert (imapx_search->priv->cached_results, criteria_desc, cached_results); ++ } else { ++ g_free (criteria_desc); ++ } ++ + info = camel_folder_search_get_current_message_info (search); + + if (info) { + result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL); +- result->value.boolean = cached_results ? g_hash_table_contains (cached_results, camel_message_info_get_uid (info)) : (uids && uids->len > 0); ++ result->value.boolean = g_hash_table_contains (cached_results, camel_message_info_get_uid (info)); + } else { +- if (cached_results) { ++ if (!uids) { + GHashTableIter iter; + gpointer key; + +- g_warn_if_fail (uids == NULL); +- + uids = g_ptr_array_sized_new (g_hash_table_size (cached_results)); + + g_hash_table_iter_init (&iter, cached_results); +@@ -269,22 +283,6 @@ imapx_search_process_criteria (CamelSExp *sexp, + result->value.ptrarray = g_ptr_array_ref (uids); + } + +- if (!cached_results) { +- cached_results = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL); +- +- if (uids) { +- guint ii; +- +- for (ii = 0; ii < uids->len; ii++) { +- g_hash_table_insert (cached_results, (gpointer) camel_pstring_strdup (uids->pdata[ii]), NULL); +- } +- } +- +- g_hash_table_insert (imapx_search->priv->cached_results, criteria_desc, cached_results); +- } else { +- g_free (criteria_desc); +- } +- + if (uids) + g_ptr_array_unref (uids); + +-- +2.27.0 + diff --git a/evolution-data-server.spec b/evolution-data-server.spec index 596dd01..c4fd30a 100644 --- a/evolution-data-server.spec +++ b/evolution-data-server.spec @@ -38,12 +38,19 @@ Name: evolution-data-server Version: 3.37.2 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Backend data server for Evolution License: LGPLv2+ URL: https://wiki.gnome.org/Apps/Evolution Source: http://download.gnome.org/sources/%{name}/3.37/%{name}-%{version}.tar.xz +# Various bugfixes backported from upstream mainline +Patch0001: 0001-I-222-Camel-Match-All-condition-doesn-t-show-any-mes.patch +Patch0002: 0002-evo-I-982-Message-contains-search-broken-in-3.36.3.patch +Patch0003: 0003-camel-folder-search-Fix-a-memory-leak-when-searching.patch +Patch0004: 0004-evo-I-982-Message-contains-search-broken-in-3.36.3.patch + + Provides: evolution-webcal = %{version} Obsoletes: evolution-webcal < 2.24.0 @@ -176,7 +183,7 @@ The %{name}-tests package contains tests that can be used to verify the functionality of the installed %{name} package. %prep -%setup -q +%autosetup -p1 %build @@ -474,6 +481,10 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_datadir}/installed-tests %changelog +* Tue Jun 23 2020 Adam Williamson - 3.37.2-2 +- Rebuild with newer protobuf and libphonenumber +- Backport several fixes for annoying bugs from mainline + * Fri May 29 2020 Milan Crha - 3.37.2-1 - Update to 3.37.2