From 1c81f56fdefa6412bd1f3ae5f36ad3f872e25ce7 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Wed, 25 Oct 2000 21:29:11 +0000 Subject: Added option menu items to allow searching based on regular expressions. 2000-10-25 Jeffrey Stedfast * filtertypes.xml: Added option menu items to allow searching based on regular expressions. * filter-message-search.c (body_regex): New callback to match text in the body using regex. (body_contains): Modified to only match using strstr. (header_regex): New callback to match headers using regex. (header_contains): Modified to only match using strstr. svn path=/trunk/; revision=6177 --- filter/ChangeLog | 11 ++++ filter/filter-message-search.c | 122 ++++++++++++++++++++++++++++++++--------- filter/filtertypes.xml | 79 ++++++++++++++++++++++++-- filter/libfilter-i18n.h | 3 +- 4 files changed, 183 insertions(+), 32 deletions(-) diff --git a/filter/ChangeLog b/filter/ChangeLog index 5a0052a97d..b35fc305f2 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,3 +1,14 @@ +2000-10-25 Jeffrey Stedfast + + * filtertypes.xml: Added option menu items to allow searching + based on regular expressions. + + * filter-message-search.c (body_regex): New callback to match text + in the body using regex. + (body_contains): Modified to only match using strstr. + (header_regex): New callback to match headers using regex. + (header_contains): Modified to only match using strstr. + 2000-10-24 Jeffrey Stedfast * filtertypes.xml: Take out the reference to "Source". diff --git a/filter/filter-message-search.c b/filter/filter-message-search.c index 8b90e273e6..a227af41c0 100644 --- a/filter/filter-message-search.c +++ b/filter/filter-message-search.c @@ -23,6 +23,7 @@ #include "filter-message-search.h" #include #include +#include typedef struct { CamelMimeMessage *message; @@ -33,8 +34,10 @@ typedef struct { /* ESExp callbacks */ static ESExpResult *header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); +static ESExpResult *header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); static ESExpResult *match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSearch *fms); static ESExpResult *body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); +static ESExpResult *body_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); static ESExpResult *user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); static ESExpResult *user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); static ESExpResult *get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms); @@ -52,7 +55,9 @@ static struct { } symbols[] = { { "match-all", (ESExpFunc *) match_all, 0 }, { "body-contains", (ESExpFunc *) body_contains, 0 }, + { "body-regex", (ESExpFunc *) body_regex, 0 }, { "header-contains", (ESExpFunc *) header_contains, 0 }, + { "header-regex", (ESExpFunc *) header_regex, 0 }, { "user-tag", (ESExpFunc *) user_tag, 0 }, { "user-flag", (ESExpFunc *) user_flag, 0 }, { "get-sent-date", (ESExpFunc *) get_sent_date, 0 }, @@ -68,6 +73,31 @@ header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterM gboolean matched = FALSE; ESExpResult *r; + if (argc == 2) { + char *header = (argv[0])->value.string; + char *match = (argv[1])->value.string; + const char *contents; + + contents = camel_medium_get_header (CAMEL_MEDIUM (fms->message), header); + + if (contents) { + if (strstr (contents, match)) + matched = TRUE; + } + } + + r = e_sexp_result_new (ESEXP_RES_BOOL); + r->value.bool = matched; + + return r; +} + +static ESExpResult * +header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) +{ + gboolean matched = FALSE; + ESExpResult *r; + if (argc == 2) { char *header = (argv[0])->value.string; char *match = (argv[1])->value.string; @@ -127,7 +157,7 @@ match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSe } static gboolean -mime_part_matches (CamelMimePart *mime_part, const char *match, CamelException *ex) +mime_part_matches (CamelMimePart *mime_part, const char *match, gboolean regex, CamelException *ex) { CamelStream *stream; GByteArray *array; @@ -142,38 +172,46 @@ mime_part_matches (CamelMimePart *mime_part, const char *match, CamelException * array = g_byte_array_new (); stream = camel_stream_mem_new_with_byte_array (array); camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_part), stream); - camel_stream_reset (stream); + camel_object_unref (CAMEL_OBJECT (stream)); + g_byte_array_append (array, "", 1); text = array->data; - regerr = regcomp (®expat, match, REG_EXTENDED | REG_NEWLINE | REG_ICASE); - if (regerr) { - /* regerror gets called twice to get the full error string - length to do proper posix error reporting */ - reglen = regerror (regerr, ®expat, 0, 0); - regmsg = g_malloc0 (reglen + 1); - regerror (regerr, ®expat, regmsg, reglen); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - "Failed to perform regex search on message body: %s", - regmsg); - g_free (regmsg); - regfree (®expat); + if (regex) { + regerr = regcomp (®expat, match, REG_EXTENDED | REG_NEWLINE | REG_ICASE); + if (regerr) { + /* regerror gets called twice to get the full error string + length to do proper posix error reporting */ + reglen = regerror (regerr, ®expat, 0, 0); + regmsg = g_malloc0 (reglen + 1); + regerror (regerr, ®expat, regmsg, reglen); + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Failed to perform regex search on message body: %s", + regmsg); + g_free (regmsg); + regfree (®expat); + } else { + fltmatch = g_new0 (regmatch_t, regexpat.re_nsub); + + if (!regexec (®expat, text, regexpat.re_nsub, fltmatch, 0)) + matched = TRUE; + + g_free (fltmatch); + regfree (®expat); + } } else { - fltmatch = g_new0 (regmatch_t, regexpat.re_nsub); - - if (!regexec (®expat, text, regexpat.re_nsub, fltmatch, 0)) + if (strstr (text, match)) matched = TRUE; - - g_free (fltmatch); - regfree (®expat); } + g_byte_array_free (array, TRUE); + return matched; } static gboolean -handle_multipart (CamelMultipart *multipart, const char *match, CamelException *ex) +handle_multipart (CamelMultipart *multipart, const char *match, gboolean regex, CamelException *ex) { gboolean matched = FALSE; int i, nparts; @@ -189,7 +227,7 @@ handle_multipart (CamelMultipart *multipart, const char *match, CamelException * if (gmime_content_field_is_type (content, "text", "*")) { /* we only want to match text parts */ - matched = mime_part_matches (mime_part, match, ex); + matched = mime_part_matches (mime_part, match, regex, ex); if (camel_exception_is_set (ex)) break; @@ -200,7 +238,7 @@ handle_multipart (CamelMultipart *multipart, const char *match, CamelException * wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); mpart = CAMEL_MULTIPART (wrapper); - matched = handle_multipart (mpart, match, ex); + matched = handle_multipart (mpart, match, regex, ex); if (camel_exception_is_set (ex)) break; @@ -231,10 +269,44 @@ body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMes wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (fms->message))); multipart = CAMEL_MULTIPART (wrapper); - matched = handle_multipart (multipart, match, fms->ex); + matched = handle_multipart (multipart, match, FALSE, fms->ex); + } else { + /* single-part message so just search the entire message */ + matched = mime_part_matches (CAMEL_MIME_PART (fms->message), match, FALSE, fms->ex); + } + } + + r = e_sexp_result_new (ESEXP_RES_BOOL); + r->value.bool = matched; + + return r; +} + +static ESExpResult * +body_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms) +{ + gboolean matched = FALSE; + ESExpResult *r; + + if (argc > 0) { + GMimeContentField *content; + char *match; + + match = (*argv)->value.string; + + content = camel_mime_part_get_content_type (CAMEL_MIME_PART (fms->message)); + + if (gmime_content_field_is_type (content, "multipart", "*")) { + CamelDataWrapper *wrapper; + CamelMultipart *multipart; + + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (fms->message))); + multipart = CAMEL_MULTIPART (wrapper); + + matched = handle_multipart (multipart, match, TRUE, fms->ex); } else { /* single-part message so just search the entire message */ - matched = mime_part_matches (CAMEL_MIME_PART (fms->message), match, fms->ex); + matched = mime_part_matches (CAMEL_MIME_PART (fms->message), match, TRUE, fms->ex); } } diff --git a/filter/filtertypes.xml b/filter/filtertypes.xml index 930db4fc2a..6417ef261c 100644 --- a/filter/filtertypes.xml +++ b/filter/filtertypes.xml @@ -2,15 +2,31 @@ - Sender + Sender + + @@ -34,6 +50,21 @@ (header-contains "Cc" ${recipient})))) + + @@ -53,6 +84,18 @@ (match-all (not (header-contains "Subject" ${subject}))) + + @@ -73,6 +116,18 @@ (match-all (not (header-contains ${header-field} ${word}))) + + @@ -89,7 +144,19 @@ + + diff --git a/filter/libfilter-i18n.h b/filter/libfilter-i18n.h index 25391215ad..c998d4ba0e 100644 --- a/filter/libfilter-i18n.h +++ b/filter/libfilter-i18n.h @@ -14,7 +14,6 @@ char *s = N_("Move to Folder"); char *s = N_("Priority"); char *s = N_("Recipients"); char *s = N_("Sender"); -char *s = N_("Source"); char *s = N_("Specific header"); char *s = N_("Stop Processing"); char *s = N_("Subject"); @@ -22,10 +21,12 @@ char *s = N_("after"); char *s = N_("before"); char *s = N_("contains"); char *s = N_("does not contain"); +char *s = N_("does not match regex"); char *s = N_("is greater than"); char *s = N_("is less than"); char *s = N_("is not"); char *s = N_("is"); +char *s = N_("matches regex"); char *s = N_("on or after"); char *s = N_("on or before"); char *s = N_("was after"); -- cgit v1.2.3