aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/ChangeLog13
-rw-r--r--filter/filter-message-search.c89
-rw-r--r--filter/filtertypes.xml51
-rw-r--r--filter/libfilter-i18n.h2
4 files changed, 149 insertions, 6 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog
index f4bb2470bc..72b07bc94e 100644
--- a/filter/ChangeLog
+++ b/filter/ChangeLog
@@ -1,5 +1,18 @@
2000-10-31 Jeffrey Stedfast <fejj@helixcode.com>
+ * filtertypes.xml: Updated to allow the user to select "sounds
+ like" or "does not sound like" (uses header-soundex).
+
+ * filter-message-search.c (header_matches): Oops. Should be using
+ !g_strncasecmp. This should fix it so this filter match works
+ right.
+ (header_starts_with): Same.
+ (header_ends_with): Same.
+ (header_soundex): New filter callback for soundex matching (yes,
+ it's probably a bloated feature but hey, it was fun to code)
+
+2000-10-31 Jeffrey Stedfast <fejj@helixcode.com>
+
* filter-folder.c (validate): Override the default validate
function to only return TRUE if a folder has been selected.
diff --git a/filter/filter-message-search.c b/filter/filter-message-search.c
index 81955671d1..2e09489843 100644
--- a/filter/filter-message-search.c
+++ b/filter/filter-message-search.c
@@ -39,6 +39,7 @@ static ESExpResult *header_matches (struct _ESExp *f, int argc, struct _ESExpRes
static ESExpResult *header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *header_soundex (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);
@@ -66,6 +67,7 @@ static struct {
{ "header-starts-with", (ESExpFunc *) header_starts_with, 0 },
{ "header-ends-with", (ESExpFunc *) header_ends_with, 0 },
{ "header-exists", (ESExpFunc *) header_exists, 0 },
+ { "header-soundex", (ESExpFunc *) header_soundex, 0 },
{ "header-regex", (ESExpFunc *) header_regex, 0 },
{ "user-tag", (ESExpFunc *) user_tag, 0 },
{ "user-flag", (ESExpFunc *) user_flag, 0 },
@@ -130,10 +132,10 @@ header_matches (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMe
}
if (is_lowercase) {
- if (g_strcasecmp (contents, match))
+ if (!g_strcasecmp (contents, match))
matched = TRUE;
} else {
- if (strcmp (contents, match))
+ if (!strcmp (contents, match))
matched = TRUE;
}
}
@@ -174,10 +176,10 @@ header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, Filt
}
if (is_lowercase) {
- if (g_strncasecmp (contents, match, strlen (match)))
+ if (!g_strncasecmp (contents, match, strlen (match)))
matched = TRUE;
} else {
- if (strncmp (contents, match, strlen (match)))
+ if (!strncmp (contents, match, strlen (match)))
matched = TRUE;
}
}
@@ -220,10 +222,10 @@ header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, Filter
end = (char *) contents + strlen (contents) - strlen (match);
if (is_lowercase) {
- if (g_strcasecmp (end, match))
+ if (!g_strcasecmp (end, match))
matched = TRUE;
} else {
- if (strcmp (end, match))
+ if (!strcmp (end, match))
matched = TRUE;
}
}
@@ -257,6 +259,81 @@ header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMes
return r;
}
+static unsigned char soundex_table[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 49, 50, 51, 0, 49, 50, 0, 0, 50, 50, 52, 53, 53, 0,
+ 49, 50, 54, 50, 51, 0, 49, 0, 50, 0, 50, 0, 0, 0, 0, 0,
+ 0, 0, 49, 50, 51, 0, 49, 50, 0, 0, 50, 50, 52, 53, 53, 0,
+ 49, 50, 54, 50, 51, 0, 49, 0, 50, 0, 50, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void
+soundexify (const gchar *sound, gchar code[5])
+{
+ guchar *c, last = '\0';
+ gint n;
+
+ for (c = (guchar *) sound; *c && !isalpha (*c); c++);
+ code[0] = toupper (*c);
+ memset (code + 1, '0', 3);
+ for (n = 1; *c && n < 5; c++) {
+ guchar ch = soundex_table[*c];
+
+ if (ch && ch != last) {
+ code[n++] = ch;
+ last = ch;
+ }
+ }
+ code[4] = '\0';
+}
+
+static gint
+soundexcmp (const gchar *sound1, const gchar *sound2)
+{
+ gchar code1[5], code2[5];
+
+ soundexify (sound1, code1);
+ soundexify (sound2, code2);
+
+ return strcmp (code1, code2);
+}
+
+static ESExpResult *
+header_soundex (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;
+ const char *contents;
+
+ contents = camel_medium_get_header (CAMEL_MEDIUM (fms->message), header);
+
+ if (contents) {
+ if (!soundexcmp (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)
{
diff --git a/filter/filtertypes.xml b/filter/filtertypes.xml
index 9b6946c030..3fa396f57b 100644
--- a/filter/filtertypes.xml
+++ b/filter/filtertypes.xml
@@ -52,6 +52,18 @@
(match-all (not (header-ends-with "From" ${sender})))
</code>
</option>
+ <option value="matches soundex">
+ <title>sounds like</title>
+ <code>
+ (match-all (header-soundex "From" ${sender}))
+ </code>
+ </option>
+ <option value="not match soundex">
+ <title>does not sound like</title>
+ <code>
+ (match-all (not (header-soundex "From" ${sender})))
+ </code>
+ </option>
<option value="matches regex">
<title>matches regex</title>
<code>
@@ -131,6 +143,21 @@
(header-ends-with "Cc" ${recipient}))))
</code>
</option>
+ <option value="matches soundex">
+ <title>sounds like</title>
+ <code>
+ (match-all (or (header-soundex "To" ${recipient})
+ (header-soundex "Cc" ${recipient})))
+ </code>
+ </option>
+ <option value="not match soundex">
+ <title>does not sound like</title>
+ <code>
+ (match-all (not (or
+ (header-soundex "To" ${recipient})
+ (header-soundex "Cc" ${recipient}))))
+ </code>
+ </option>
<option value="matches regex">
<title>matches regex</title>
<code>
@@ -201,6 +228,18 @@
(match-all (not (header-ends-with "Subject" ${subject}))
</code>
</option>
+ <option value="matches soundex">
+ <title>sounds like</title>
+ <code>
+ (match-all (header-soundex "Subject" ${subject}))
+ </code>
+ </option>
+ <option value="not match soundex">
+ <title>does not sound like</title>
+ <code>
+ (match-all (not (header-soundex "Subject" ${subject})))
+ </code>
+ </option>
<option value="matches regex">
<title>matches regex</title>
<code>
@@ -281,6 +320,18 @@
(match-all (not (header-exists ${header-field}))
</code>
</option>
+ <option value="matches soundex">
+ <title>sounds like</title>
+ <code>
+ (match-all (header-soundex ${header-field} ${word}))
+ </code>
+ </option>
+ <option value="not match soundex">
+ <title>does not sound like</title>
+ <code>
+ (match-all (not (header-soundex ${header-field} ${word})))
+ </code>
+ </option>
<option value="matches regex">
<title>matches regex</title>
<code>
diff --git a/filter/libfilter-i18n.h b/filter/libfilter-i18n.h
index 3cac52183b..c725cb7bae 100644
--- a/filter/libfilter-i18n.h
+++ b/filter/libfilter-i18n.h
@@ -31,6 +31,7 @@ char *s = N_("does not contain");
char *s = N_("does not end with");
char *s = N_("does not exist");
char *s = N_("does not match regex");
+char *s = N_("does not sound like");
char *s = N_("does not start with");
char *s = N_("ends with");
char *s = N_("exists");
@@ -41,6 +42,7 @@ char *s = N_("is");
char *s = N_("matches regex");
char *s = N_("on or after");
char *s = N_("on or before");
+char *s = N_("sounds like");
char *s = N_("starts with");
char *s = N_("was after");
char *s = N_("was before");