aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/ChangeLog11
-rw-r--r--filter/filter-message-search.c122
-rw-r--r--filter/filtertypes.xml79
-rw-r--r--filter/libfilter-i18n.h3
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 <fejj@helixcode.com>
+
+ * 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 <fejj@helixcode.com>
* 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 <e-util/e-sexp.h>
#include <regex.h>
+#include <string.h>
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 },
@@ -71,6 +76,31 @@ header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterM
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;
regex_t regexpat; /* regex patern */
regmatch_t *fltmatch;
gint regerr = 0;
@@ -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 (&regexpat, 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, &regexpat, 0, 0);
- regmsg = g_malloc0 (reglen + 1);
- regerror (regerr, &regexpat, regmsg, reglen);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- "Failed to perform regex search on message body: %s",
- regmsg);
- g_free (regmsg);
- regfree (&regexpat);
+ if (regex) {
+ regerr = regcomp (&regexpat, 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, &regexpat, 0, 0);
+ regmsg = g_malloc0 (reglen + 1);
+ regerror (regerr, &regexpat, regmsg, reglen);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ "Failed to perform regex search on message body: %s",
+ regmsg);
+ g_free (regmsg);
+ regfree (&regexpat);
+ } else {
+ fltmatch = g_new0 (regmatch_t, regexpat.re_nsub);
+
+ if (!regexec (&regexpat, text, regexpat.re_nsub, fltmatch, 0))
+ matched = TRUE;
+
+ g_free (fltmatch);
+ regfree (&regexpat);
+ }
} else {
- fltmatch = g_new0 (regmatch_t, regexpat.re_nsub);
-
- if (!regexec (&regexpat, text, regexpat.re_nsub, fltmatch, 0))
+ if (strstr (text, match))
matched = TRUE;
-
- g_free (fltmatch);
- regfree (&regexpat);
}
+ 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 @@
<filterdescription>
<partset>
<part name="sender">
- <title>Sender</title>
+ <title>Sender</title>
<input type="optionlist" name="sender-type">
<option value="contains">
- <title>contains</title>
- <code>(match-all (header-contains "From" ${sender}))</code>
+ <title>contains</title>
+ <code>
+ (match-all (header-contains "From" ${sender}))
+ </code>
</option>
<option value="not contains">
- <title>does not contain</title>
- <code>(match-all (not (header-contains "From" ${sender})))</code>
+ <title>does not contain</title>
+ <code>
+ (match-all (not (header-contains "From" ${sender})))
+ </code>
+ </option>
+ <option value="matches regex">
+ <title>matches regex</title>
+ <code>
+ (match-all (header-regex "From" ${sender}))
+ </code>
+ </option>
+ <option value="not match regex">
+ <title>does not match regex</title>
+ <code>
+ (match-all (not (header-regex "From" ${sender})))
+ </code>
</option>
</input>
<input type="string" name="sender"/>
@@ -34,6 +50,21 @@
(header-contains "Cc" ${recipient}))))
</code>
</option>
+ <option value="matches regex">
+ <title>matches regex</title>
+ <code>
+ (match-all (or (header-regex "To" ${recipient})
+ (header-regex "Cc" ${recipient})))
+ </code>
+ </option>
+ <option value="not match regex">
+ <title>does not match regex</title>
+ <code>
+ (match-all (not (or
+ (header-regex "To" ${recipient})
+ (header-regex "Cc" ${recipient}))))
+ </code>
+ </option>
</input>
<input type="address" name="recipient"/>
</part>
@@ -53,6 +84,18 @@
(match-all (not (header-contains "Subject" ${subject})))
</code>
</option>
+ <option value="matches regex">
+ <title>matches regex</title>
+ <code>
+ (match-all (header-regex "Subject" ${subject}))
+ </code>
+ </option>
+ <option value="not match regex">
+ <title>does not match regex</title>
+ <code>
+ (match-all (not (header-regex "Subject" ${subject}))
+ </code>
+ </option>
</input>
<input type="string" name="subject"/>
</part>
@@ -73,6 +116,18 @@
(match-all (not (header-contains ${header-field} ${word})))
</code>
</option>
+ <option value="matches regex">
+ <title>matches regex</title>
+ <code>
+ (match-all (header-regex ${header-field} ${word}))
+ </code>
+ </option>
+ <option value="not match regex">
+ <title>does not match regex</title>
+ <code>
+ (match-all (not (header-regex ${header-field} ${word}))
+ </code>
+ </option>
</input>
<input type="string" name="word"/>
</part>
@@ -89,7 +144,19 @@
<option value="not contains">
<title>does not contain</title>
<code>
- (not (body-contains "Subject" ${word}))
+ (not (body-contains ${word}))
+ </code>
+ </option>
+ <option value="matches regex">
+ <title>matches regex</title>
+ <code>
+ (body-regex ${word})
+ </code>
+ </option>
+ <option value="not match regex">
+ <title>does not match regex</title>
+ <code>
+ (not (body-regex ${word}))
</code>
</option>
</input>
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");