[evolution-data-server] Bug #391472 - Add ability to match headers by words



commit e3da65f2d5537d8d60e4d7009f03335552f1788f
Author: Milan Crha <mcrha redhat com>
Date:   Tue Feb 7 18:41:12 2012 +0100

    Bug #391472 - Add ability to match headers by words

 camel/camel-filter-search.c   |   11 +++++++
 camel/camel-folder-search.c   |   12 +++++++-
 camel/camel-search-private.c  |   61 +++++++++++++++++++++++++++++++++++++++++
 camel/camel-search-private.h  |    1 +
 camel/camel-search-sql-sexp.c |   14 +++++++++-
 5 files changed, 97 insertions(+), 2 deletions(-)
---
diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c
index 0e55982..668fb2f 100644
--- a/camel/camel-filter-search.c
+++ b/camel/camel-filter-search.c
@@ -70,6 +70,7 @@ typedef struct {
 
 /* CamelSExp callbacks */
 static CamelSExpResult *header_contains (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms);
+static CamelSExpResult *header_has_words (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms);
 static CamelSExpResult *header_matches (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms);
 static CamelSExpResult *header_starts_with (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms);
 static CamelSExpResult *header_ends_with (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms);
@@ -103,6 +104,7 @@ static struct {
 	{ "body-contains",      (CamelSExpFunc) body_contains,      0 },
 	{ "body-regex",         (CamelSExpFunc) body_regex,         0 },
 	{ "header-contains",    (CamelSExpFunc) header_contains,    0 },
+	{ "header-has-words",   (CamelSExpFunc) header_has_words,   0 },
 	{ "header-matches",     (CamelSExpFunc) header_matches,     0 },
 	{ "header-starts-with", (CamelSExpFunc) header_starts_with, 0 },
 	{ "header-ends-with",   (CamelSExpFunc) header_ends_with,   0 },
@@ -270,6 +272,15 @@ header_contains (struct _CamelSExp *f,
 }
 
 static CamelSExpResult *
+header_has_words (struct _CamelSExp *f,
+		  gint argc,
+		  struct _CamelSExpResult **argv,
+		  FilterMessageSearch *fms)
+{
+	return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_WORD);
+}
+
+static CamelSExpResult *
 header_matches (struct _CamelSExp *f,
                 gint argc,
                 struct _CamelSExpResult **argv,
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c
index 973130a..4fa136f 100644
--- a/camel/camel-folder-search.c
+++ b/camel/camel-folder-search.c
@@ -573,7 +573,17 @@ static gboolean
 do_search_in_memory (const gchar *expr)
 {
 	/* if the expression contains any of these tokens, then perform a memory search, instead of the SQL one */
-	const gchar *in_memory_tokens[] = { "body-contains", "body-regex", "match-threads", "message-location", "header-soundex", "header-regex", "header-full-regex", "header-contains", NULL };
+	const gchar *in_memory_tokens[] = {
+		"body-contains",
+		"body-regex",
+		"match-threads",
+		"message-location",
+		"header-soundex",
+		"header-regex",
+		"header-full-regex",
+		"header-contains",
+		"header-has-words",
+		NULL };
 	gint i;
 
 	if (!expr)
diff --git a/camel/camel-search-private.c b/camel/camel-search-private.c
index d196326..645a5a7 100644
--- a/camel/camel-search-private.c
+++ b/camel/camel-search-private.c
@@ -294,6 +294,65 @@ camel_ustrcasecmp (const gchar *ps1,
 	return 0;
 }
 
+static gchar *
+depunct_string (const gchar *str)
+{
+	gchar *res;
+	gint ii;
+
+	g_return_val_if_fail (str != NULL, NULL);
+
+	res = g_strdup (str);
+	for (ii = 0; res[ii]; ii++) {
+		if (ispunct (res[ii]))
+			res[ii] = ' ';
+	}
+
+	return res;
+}
+
+static gboolean
+camel_uwordcase (const gchar *haystack,
+		 const gchar *needle)
+{
+	struct _camel_search_words *hwords, *nwords;
+	gchar *copy_haystack, *copy_needle;
+	gboolean found_all;
+	gint ii, jj;
+
+	g_return_val_if_fail (haystack != NULL, FALSE);
+	g_return_val_if_fail (needle != NULL, FALSE);
+
+	if (!*needle)
+		return TRUE;
+	if (!*haystack)
+		return FALSE;
+
+	copy_haystack = depunct_string (haystack);
+	copy_needle = depunct_string (needle);
+	hwords = camel_search_words_split ((const guchar *) copy_haystack);
+	nwords = camel_search_words_split ((const guchar *) copy_needle);
+	g_free (copy_haystack);
+	g_free (copy_needle);
+
+	found_all = TRUE;
+	for (ii = 0; ii < nwords->len && found_all; ii++) {
+		found_all = FALSE;
+
+		for (jj = 0; jj < hwords->len; jj++) {
+			if (camel_ustrcasecmp (hwords->words[jj]->word, nwords->words[ii]->word) == 0) {
+				found_all = TRUE;
+				break;
+			}
+		}
+	}
+
+	camel_search_words_free (hwords);
+	camel_search_words_free (nwords);
+
+	return found_all;
+}
+
 static gint
 camel_ustrncasecmp (const gchar *ps1,
                     const gchar *ps2,
@@ -353,6 +412,8 @@ header_match (const gchar *value,
 		return camel_ustrcasecmp (value, match) == 0;
 	case CAMEL_SEARCH_MATCH_CONTAINS:
 		return camel_ustrstrcase (value, match) != NULL;
+	case CAMEL_SEARCH_MATCH_WORD:
+		return camel_uwordcase (value, match);
 	case CAMEL_SEARCH_MATCH_STARTS:
 		return camel_ustrncasecmp (value, match, mlen) == 0;
 	case CAMEL_SEARCH_MATCH_ENDS:
diff --git a/camel/camel-search-private.h b/camel/camel-search-private.h
index a6e4b81..8302ff9 100644
--- a/camel/camel-search-private.h
+++ b/camel/camel-search-private.h
@@ -41,6 +41,7 @@ typedef enum {
 typedef enum {
 	CAMEL_SEARCH_MATCH_EXACT,
 	CAMEL_SEARCH_MATCH_CONTAINS,
+	CAMEL_SEARCH_MATCH_WORD,
 	CAMEL_SEARCH_MATCH_STARTS,
 	CAMEL_SEARCH_MATCH_ENDS,
 	CAMEL_SEARCH_MATCH_SOUNDEX
diff --git a/camel/camel-search-sql-sexp.c b/camel/camel-search-sql-sexp.c
index aac19a2..07f6146 100644
--- a/camel/camel-search-sql-sexp.c
+++ b/camel/camel-search-sql-sexp.c
@@ -384,7 +384,7 @@ check_header (struct _CamelSExp *f,
 				gchar *value = NULL, *tstr = NULL;
 				if (argv[i]->value.string[0] == 0)
 					continue;
-				if (how == CAMEL_SEARCH_MATCH_CONTAINS) {
+				if (how == CAMEL_SEARCH_MATCH_CONTAINS || how == CAMEL_SEARCH_MATCH_WORD) {
 					tstr = g_strdup_printf ("%c%s%c", '%', argv[i]->value.string, '%');
 					value = get_db_safe_string (tstr);
 					g_free (tstr);
@@ -427,6 +427,17 @@ header_contains (struct _CamelSExp *f,
 }
 
 static CamelSExpResult *
+header_has_words (struct _CamelSExp *f,
+                  gint argc,
+                  struct _CamelSExpResult **argv,
+                  gpointer data)
+{
+	d(printf("executing header-has-word: %d", argc));
+
+	return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_WORD);
+}
+
+static CamelSExpResult *
 header_matches (struct _CamelSExp *f,
                 gint argc,
                 struct _CamelSExpResult **argv,
@@ -675,6 +686,7 @@ static struct {
 	{ "match-threads", (CamelSExpFunc)match_threads, 1 },
 /*	{ "body-contains", body_contains}, */ /* We don't store body on the db. */
 	{ "header-contains", header_contains, 0},
+	{ "header-has-words", header_has_words, 0},
 	{ "header-matches", header_matches, 0},
 	{ "header-starts-with", header_starts_with, 0},
 	{ "header-ends-with", header_ends_with, 0},



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