From a039733f7047d870fa4e8fe9425f8b76b4e15d41 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 7 Aug 2001 19:55:34 +0000 Subject: New function to do danw's address "is" comparison (as specified in bug 2001-08-07 Jeffrey Stedfast * camel-filter-search.c (address_matches_exactly): New function to do danw's address "is" comparison (as specified in bug #5886. (check_header): Special-case address-type headers when we are doing an exact match to use the address_matches_exactly function. svn path=/trunk/; revision=11738 --- camel/ChangeLog | 7 +++ camel/camel-filter-search.c | 132 ++++++++++++++++++++++++++-------------- camel/camel-search-private.c | 141 ++++++++++++++++++++++--------------------- 3 files changed, 167 insertions(+), 113 deletions(-) (limited to 'camel') diff --git a/camel/ChangeLog b/camel/ChangeLog index 2f331d6696..42a7859eea 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,10 @@ +2001-08-07 Jeffrey Stedfast + + * camel-filter-search.c (address_matches_exactly): New function to + do danw's address "is" comparison (as specified in bug #5886. + (check_header): Special-case address-type headers when we are + doing an exact match to use the address_matches_exactly function. + 2001-08-06 Jeffrey Stedfast * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c index b4651f67fc..527e7cc0c1 100644 --- a/camel/camel-filter-search.c +++ b/camel/camel-filter-search.c @@ -104,8 +104,44 @@ static struct { { "get-size", (ESExpFunc *) get_size, 0 }, }; +static gboolean +address_matches_exactly (const char *header, const char *string) +{ + CamelInternetAddress *cia; + GCompareFunc compare; + const char *p; + + for (p = string; *p; p++) + if (isupper ((unsigned) *p)) + break; + + if (*p) + compare = (GCompareFunc) strcmp; + else + compare = (GCompareFunc) g_strcasecmp; + + /* the simple case? */ + if (!compare (header, string)) + return TRUE; + + cia = camel_internet_address_new (); + if (camel_address_decode (CAMEL_ADDRESS (cia), header) == 1) { + const char *name, *addr; + + camel_internet_address_get (cia, 0, &name, &addr); + if (!compare (name, string)) + return TRUE; + + if (!compare (addr, string)) + return TRUE; + } + camel_object_unref (CAMEL_OBJECT (cia)); + + return FALSE; +} + static ESExpResult * -check_header(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms, camel_search_match_t how) +check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms, camel_search_match_t how) { gboolean matched = FALSE; ESExpResult *r; @@ -114,24 +150,29 @@ check_header(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessa if (argc > 1 && argv[0]->type == ESEXP_RES_STRING) { char *name = argv[0]->value.string; const char *header; - - if (strcasecmp(name, "x-camel-mlist") == 0) - header = camel_message_info_mlist(fms->info); + + if (g_strcasecmp (name, "x-camel-mlist") == 0) + header = camel_message_info_mlist (fms->info); else header = camel_medium_get_header (CAMEL_MEDIUM (fms->message), argv[0]->value.string); - + if (header) { - for (i=1;itype == ESEXP_RES_STRING - && camel_search_header_match(header, argv[i]->value.string, how)) { - matched = TRUE; + for (i = 1; i < argc && !matched; i++) { + if (argv[i]->type == ESEXP_RES_STRING) { + if (how == CAMEL_SEARCH_MATCH_EXACT + && (!g_strcasecmp (name, "To") + || !g_strcasecmp (name, "Cc") + || !g_strcasecmp (name, "From"))) + matched = address_matches_exactly (header, argv[i]->value.string); + else + matched = camel_search_header_match (header, argv[i]->value.string, how); break; } } } } - r = e_sexp_result_new(f, ESEXP_RES_BOOL); + r = e_sexp_result_new (f, ESEXP_RES_BOOL); r->value.bool = matched; return r; @@ -140,32 +181,32 @@ check_header(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessa static ESExpResult * header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - return check_header(f, argc, argv, fms, CAMEL_SEARCH_MATCH_CONTAINS); + return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_CONTAINS); } static ESExpResult * header_matches (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - return check_header(f, argc, argv, fms, CAMEL_SEARCH_MATCH_EXACT); + return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_EXACT); } static ESExpResult * header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - return check_header(f, argc, argv, fms, CAMEL_SEARCH_MATCH_STARTS); + return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_STARTS); } static ESExpResult * header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - return check_header(f, argc, argv, fms, CAMEL_SEARCH_MATCH_ENDS); + return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_ENDS); } static ESExpResult * header_soundex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - return check_header(f, argc, argv, fms, CAMEL_SEARCH_MATCH_SOUNDEX); + return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_SOUNDEX); } static ESExpResult * @@ -174,13 +215,13 @@ header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMes gboolean matched = FALSE; ESExpResult *r; int i; - - for (i=0;itype == ESEXP_RES_STRING) matched = camel_medium_get_header (CAMEL_MEDIUM (fms->message), argv[i]->value.string) != NULL; } - r = e_sexp_result_new(f, ESEXP_RES_BOOL); + r = e_sexp_result_new (f, ESEXP_RES_BOOL); r->value.bool = matched; return r; @@ -189,16 +230,17 @@ header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMes static ESExpResult * header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL); + ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL); regex_t pattern; const char *contents; - - if (argc>1 - && argv[0]->type == ESEXP_RES_STRING + + if (argc > 1 && argv[0]->type == ESEXP_RES_STRING && (contents = camel_medium_get_header (CAMEL_MEDIUM (fms->message), argv[0]->value.string)) - && camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, fms->ex) == 0) { - r->value.bool = regexec(&pattern, contents, 0, NULL, 0) == 0; - regfree(&pattern); + && camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_REGEX | + CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, + fms->ex) == 0) { + r->value.bool = regexec (&pattern, contents, 0, NULL, 0) == 0; + regfree (&pattern); } else r->value.bool = FALSE; @@ -215,12 +257,12 @@ get_full_header (CamelMimeMessage *message) for (h = mp->headers; h; h = h->next) { if (h->value != NULL) { - g_string_append(str, h->name); - if (isspace(h->value[0])) - g_string_append(str, ":"); + g_string_append (str, h->name); + if (isspace (h->value[0])) + g_string_append (str, ":"); else - g_string_append(str, ": "); - g_string_append(str, h->value); + g_string_append (str, ": "); + g_string_append (str, h->value); } } @@ -233,15 +275,16 @@ get_full_header (CamelMimeMessage *message) static ESExpResult * header_full_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL); + ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL); regex_t pattern; char *contents; - if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, fms->ex) == 0) { + if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_REGEX | + CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, fms->ex) == 0) { contents = get_full_header (fms->message); - r->value.bool = regexec(&pattern, contents, 0, NULL, 0) == 0; - g_free(contents); - regfree(&pattern); + r->value.bool = regexec (&pattern, contents, 0, NULL, 0) == 0; + g_free (contents); + regfree (&pattern); } else r->value.bool = FALSE; @@ -266,12 +309,12 @@ match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSe static ESExpResult * body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) { - ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL); + ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL); regex_t pattern; - - if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_ICASE, argc, argv, fms->ex) == 0) { - r->value.bool = camel_search_message_body_contains((CamelDataWrapper *)fms->message, &pattern); - regfree(&pattern); + + if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_ICASE, argc, argv, fms->ex) == 0) { + r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *)fms->message, &pattern); + regfree (&pattern); } else r->value.bool = FALSE; @@ -283,10 +326,11 @@ body_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessag { ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL); regex_t pattern; - - if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_REGEX, argc, argv, fms->ex) == 0) { - r->value.bool = camel_search_message_body_contains((CamelDataWrapper *)fms->message, &pattern); - regfree(&pattern); + + if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_ICASE | + CAMEL_SEARCH_MATCH_REGEX, argc, argv, fms->ex) == 0) { + r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *)fms->message, &pattern); + regfree (&pattern); } else r->value.bool = FALSE; diff --git a/camel/camel-search-private.c b/camel/camel-search-private.c index 164f4d2b60..65e5ede3f0 100644 --- a/camel/camel-search-private.c +++ b/camel/camel-search-private.c @@ -63,58 +63,59 @@ camel_search_build_match_regex (regex_t *pattern, camel_search_flags_t type, int int c, i, count=0, err; char *word; int flags; - + /* build a regex pattern we can use to match the words, we OR them together */ if (argc>1) - g_string_append_c(match, '('); - for (i=0;itype == ESEXP_RES_STRING) { if (count > 0) - g_string_append_c(match, '|'); - + g_string_append_c (match, '|'); + word = argv[i]->value.string; if (type & CAMEL_SEARCH_MATCH_REGEX) { /* no need to escape because this should already be a valid regex */ - g_string_append(match, word); + g_string_append (match, word); } else { /* escape any special chars (not sure if this list is complete) */ if (type & CAMEL_SEARCH_MATCH_START) - g_string_append_c(match, '^'); + g_string_append_c (match, '^'); while ((c = *word++)) { - if (strchr("*\\.()[]^$+", c) != NULL) { - g_string_append_c(match, '\\'); + if (strchr ("*\\.()[]^$+", c) != NULL) { + g_string_append_c (match, '\\'); } - g_string_append_c(match, c); + g_string_append_c (match, c); } if (type & CAMEL_SEARCH_MATCH_END) - g_string_append_c(match, '^'); + g_string_append_c (match, '^'); } count++; } else { g_warning("Invalid type passed to body-contains match function"); } } - if (argc>1) - g_string_append_c(match, ')'); + if (argc > 1) + g_string_append_c (match, ')'); flags = REG_EXTENDED|REG_NOSUB; if (type & CAMEL_SEARCH_MATCH_ICASE) flags |= REG_ICASE; - err = regcomp(pattern, match->str, flags); + err = regcomp (pattern, match->str, flags); if (err != 0) { /* regerror gets called twice to get the full error string length to do proper posix error reporting */ - int len = regerror(err, pattern, 0, 0); - char *buffer = g_malloc0(len + 1); - - regerror(err, pattern, buffer, len); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Regular expression compilation failed: %s: %s"), - match->str, buffer); - - regfree(pattern); + int len = regerror (err, pattern, 0, 0); + char *buffer = g_malloc0 (len + 1); + + regerror (err, pattern, buffer, len); + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Regular expression compilation failed: %s: %s"), + match->str, buffer); + + regfree (pattern); } d(printf("Built regex: '%s'\n", match->str)); - g_string_free(match, TRUE); + g_string_free (match, TRUE); + return err; } @@ -158,36 +159,36 @@ soundexify (const gchar *sound, gchar code[5]) } static gboolean -header_soundex(const char *header, const char *match) +header_soundex (const char *header, const char *match) { char mcode[5], hcode[5]; const char *p; char c; GString *word; int truth = FALSE; - - soundexify(match, mcode); - + + soundexify (match, mcode); + /* split the header into words, and soundexify and compare each one */ /* FIXME: Should this convert to utf8, and split based on that, and what not? soundex only makes sense for us-ascii though ... */ - + word = g_string_new(""); p = header; do { c = *p++; - if (c == 0 || isspace(c)) { + if (c == 0 || isspace (c)) { if (word->len > 0) { - soundexify(word->str, hcode); - if (strcmp(hcode, mcode) == 0) + soundexify (word->str, hcode); + if (strcmp (hcode, mcode) == 0) truth = TRUE; } - g_string_truncate(word, 0); - } else if (isalpha(c)) - g_string_append_c(word, c); + g_string_truncate (word, 0); + } else if (isalpha (c)) + g_string_append_c (word, c); } while (c && !truth); - g_string_free(word, TRUE); - + g_string_free (word, TRUE); + return truth; } @@ -214,10 +215,10 @@ camel_ustrstrcase (const char *haystack, const char *needle) g_return_val_if_fail (haystack != NULL, NULL); g_return_val_if_fail (needle != NULL, NULL); - - if (strlen(needle) == 0) + + if (strlen (needle) == 0) return haystack; - if (strlen(haystack) == 0) + if (strlen (haystack) == 0) return NULL; puni = nuni = alloca (sizeof (gunichar) * strlen (needle)); @@ -342,7 +343,7 @@ camel_search_header_match (const char *value, const char *match, camel_search_ma { const char *p; int vlen, mlen; - + while (*value && isspace (*value)) value++; @@ -358,12 +359,12 @@ camel_search_header_match (const char *value, const char *match, camel_search_ma otherwise not */ p = match; while (*p) { - if (isupper(*p)) { - switch(how) { + if (isupper (*p)) { + switch (how) { case CAMEL_SEARCH_MATCH_EXACT: - return strcmp(value, match) == 0; + return strcmp (value, match) == 0; case CAMEL_SEARCH_MATCH_CONTAINS: - return strstr(value, match) != NULL; + return strstr (value, match) != NULL; case CAMEL_SEARCH_MATCH_STARTS: return strncmp (value, match, mlen) == 0; case CAMEL_SEARCH_MATCH_ENDS: @@ -375,11 +376,12 @@ camel_search_header_match (const char *value, const char *match, camel_search_ma } p++; } - switch(how) { + + switch (how) { case CAMEL_SEARCH_MATCH_EXACT: - return camel_ustrcasecmp(value, match) == 0; + return camel_ustrcasecmp (value, match) == 0; case CAMEL_SEARCH_MATCH_CONTAINS: - return camel_ustrstrcase(value, match) != NULL; + return camel_ustrstrcase (value, match) != NULL; case CAMEL_SEARCH_MATCH_STARTS: return camel_ustrncasecmp (value, match, mlen) == 0; case CAMEL_SEARCH_MATCH_ENDS: @@ -387,47 +389,48 @@ camel_search_header_match (const char *value, const char *match, camel_search_ma default: break; } - + return FALSE; } /* performs a 'slow' content-based match */ /* there is also an identical copy of this in camel-filter-search.c */ gboolean -camel_search_message_body_contains(CamelDataWrapper *object, regex_t *pattern) +camel_search_message_body_contains (CamelDataWrapper *object, regex_t *pattern) { CamelDataWrapper *containee; int truth = FALSE; int parts, i; - - containee = camel_medium_get_content_object(CAMEL_MEDIUM(object)); - + + containee = camel_medium_get_content_object (CAMEL_MEDIUM (object)); + if (containee == NULL) return FALSE; - + /* TODO: I find it odd that get_part and get_content_object do not add a reference, probably need fixing for multithreading */ - + /* using the object types is more accurate than using the mime/types */ - if (CAMEL_IS_MULTIPART(containee)) { - parts = camel_multipart_get_number(CAMEL_MULTIPART(containee)); - for (i=0;imime_type, "text", "*")) { + truth = camel_search_message_body_contains ((CamelDataWrapper *)containee, pattern); + } else if (header_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "text", "*")) { /* for all other text parts, we look inside, otherwise we dont care */ - CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new(); - - camel_data_wrapper_write_to_stream(containee, (CamelStream *)mem); - camel_stream_write((CamelStream *)mem, "", 1); - truth = regexec(pattern, mem->buffer->data, 0, NULL, 0) == 0; - camel_object_unref((CamelObject *)mem); + CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new (); + + camel_data_wrapper_write_to_stream (containee, CAMEL_STREAM (mem)); + camel_stream_write (CAMEL_STREAM (mem), "", 1); + truth = regexec (pattern, mem->buffer->data, 0, NULL, 0) == 0; + camel_object_unref (CAMEL_OBJECT (mem)); } + return truth; } -- cgit v1.2.3