diff options
-rw-r--r-- | camel/ChangeLog | 7 | ||||
-rw-r--r-- | camel/camel-folder-search.c | 252 | ||||
-rw-r--r-- | camel/camel-folder-search.h | 14 |
3 files changed, 271 insertions, 2 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index ee91389bd5..c5f5a534fe 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,10 @@ +2000-01-03 Jeffrey Stedfast <fejj@helixcode.com> + + * camel-folder-search.c (search_header_matches): Implemented. + (search_header_exists): Implemented. + (search_header_starts_with): Implemented. + (search_header_ends_with): Implemented. + 2001-01-03 Christopher James Lahey <clahey@helixcode.com> * providers/imap/camel-imap-folder.c (camel_imap_folder_new): diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index 97fcf6557a..bc9e13cb34 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <string.h> +#include <ctype.h> #include <glib.h> #include <sys/types.h> #include <regex.h> @@ -50,6 +51,10 @@ struct _CamelFolderSearchPrivate { #define _PRIVATE(o) (((CamelFolderSearch *)(o))->priv) static ESExpResult *search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); +static ESExpResult *search_header_matches(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); +static ESExpResult *search_header_starts_with(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); +static ESExpResult *search_header_ends_with(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); +static ESExpResult *search_header_exists(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); static ESExpResult *search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *search); static ESExpResult *search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); static ESExpResult *search_user_flag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); @@ -75,6 +80,10 @@ camel_folder_search_class_init (CamelFolderSearchClass *klass) klass->match_all = search_match_all; klass->body_contains = search_body_contains; klass->header_contains = search_header_contains; + klass->header_matches = search_header_matches; + klass->header_starts_with = search_header_starts_with; + klass->header_ends_with = search_header_ends_with; + klass->header_exists = search_header_exists; klass->user_tag = search_user_tag; klass->user_flag = search_user_flag; klass->system_flag = search_system_flag; @@ -168,6 +177,10 @@ struct { { "match-all", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, match_all), 3 }, { "body-contains", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, body_contains), 1 }, { "header-contains", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_contains), 1 }, + { "header-matches", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_matches), 1 }, + { "header-starts-with", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_starts_with), 1 }, + { "header-ends-with", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_ends_with), 1 }, + { "header-exists", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_exists), 1 }, { "user-tag", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, user_tag), 1 }, { "user-flag", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, user_flag), 1 }, { "system-flag", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, system_flag), 1 }, @@ -521,7 +534,9 @@ search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, C for (i=1;i<argc && !truth;i++) { if (argv[i]->type == ESEXP_RES_STRING && e_utf8_strstrcase (header, argv[i]->value.string)) { - r(printf("%s got a match with %s of %s\n", camel_message_info_uid(search->current), header, argv[i]->value.string)); + r(printf("%s got a match with %s of %s\n", + camel_message_info_uid(search->current), + header, argv[i]->value.string)); truth = TRUE; break; } @@ -536,6 +551,241 @@ search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, C return r; } +static ESExpResult * +search_header_matches(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) +{ + ESExpResult *r; + + r(printf ("executing header-matches\n")); + + if (search->current && argc == 2) { + char *headername; + const char *header = NULL; + char strbuf[32]; + gboolean truth = FALSE; + + /* only a subset of headers are supported .. */ + headername = argv[0]->value.string; + if (!strcasecmp (headername, "subject")) { + header = camel_message_info_subject (search->current); + } else if (!strcasecmp (headername, "date")) { + /* FIXME: not a very useful form of the date */ + sprintf (strbuf, "%d", (int)search->current->date_sent); + header = strbuf; + } else if (!strcasecmp (headername, "from")) { + header = camel_message_info_from (search->current); + } else if (!strcasecmp (headername, "to")) { + header = camel_message_info_to (search->current); + } else if (!strcasecmp (headername, "cc")) { + header = camel_message_info_cc (search->current); + } else { + g_warning ("Performing query on unknown header: %s", headername); + } + + if (header && argv[1]->type == ESEXP_RES_STRING) { + /* danw says to use search-engine style matching... + * This means that if the search match string is + * lowercase then compare case-insensitive else + * compare case-sensitive. */ + gboolean is_lowercase = TRUE; + char *match = argv[1]->value.string; + char *c; + + /* remove any leading white space... */ + for ( ; *header && isspace (*header); header++); + + for (c = match; *c; c++) { + if (isalpha (*c) && isupper (*c)) { + is_lowercase = FALSE; + break; + } + } + + if (is_lowercase) { + if (!g_strcasecmp (header, match)) + truth = TRUE; + } else { + if (!strcmp (header, match)) + truth = TRUE; + } + } + + r = e_sexp_result_new (ESEXP_RES_BOOL); + r->value.bool = truth; + } else { + r = e_sexp_result_new (ESEXP_RES_ARRAY_PTR); + r->value.ptrarray = g_ptr_array_new (); + } + + return r; +} + +static ESExpResult * +search_header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) +{ + ESExpResult *r; + + r(printf ("executing header-starts-with\n")); + + if (search->current && argc == 2) { + char *headername, *match; + const char *header = NULL; + char strbuf[32]; + gboolean truth = FALSE; + + /* only a subset of headers are supported .. */ + headername = argv[0]->value.string; + if (!strcasecmp (headername, "subject")) { + header = camel_message_info_subject (search->current); + } else if (!strcasecmp (headername, "date")) { + /* FIXME: not a very useful form of the date */ + sprintf (strbuf, "%d", (int)search->current->date_sent); + header = strbuf; + } else if (!strcasecmp (headername, "from")) { + header = camel_message_info_from (search->current); + } else if (!strcasecmp (headername, "to")) { + header = camel_message_info_to (search->current); + } else if (!strcasecmp (headername, "cc")) { + header = camel_message_info_cc (search->current); + } else { + g_warning ("Performing query on unknown header: %s", headername); + } + + match = argv[1]->value.string; + + if (header && strlen (header) >= strlen (match)) { + /* danw says to use search-engine style matching... + * This means that if the search match string is + * lowercase then compare case-insensitive else + * compare case-sensitive. */ + gboolean is_lowercase = TRUE; + char *c; + + /* remove any leading white space... */ + for ( ; *header && isspace (*header); header++); + + for (c = match; *c; c++) { + if (isalpha (*c) && isupper (*c)) { + is_lowercase = FALSE; + break; + } + } + + if (is_lowercase) { + if (!g_strncasecmp (header, match, strlen (match))) + truth = TRUE; + } else { + if (!strncmp (header, match, strlen (match))) + truth = TRUE; + } + } + + r = e_sexp_result_new (ESEXP_RES_BOOL); + r->value.bool = truth; + } else { + r = e_sexp_result_new (ESEXP_RES_ARRAY_PTR); + r->value.ptrarray = g_ptr_array_new (); + } + + return r; +} + +static ESExpResult * +search_header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) +{ + ESExpResult *r; + + r(printf ("executing header-ends-with\n")); + + if (search->current && argc == 2) { + char *headername, *match; + const char *header = NULL; + char strbuf[32]; + gboolean truth = FALSE; + + /* only a subset of headers are supported .. */ + headername = argv[0]->value.string; + if (!strcasecmp (headername, "subject")) { + header = camel_message_info_subject (search->current); + } else if (!strcasecmp (headername, "date")) { + /* FIXME: not a very useful form of the date */ + sprintf (strbuf, "%d", (int)search->current->date_sent); + header = strbuf; + } else if (!strcasecmp (headername, "from")) { + header = camel_message_info_from (search->current); + } else if (!strcasecmp (headername, "to")) { + header = camel_message_info_to (search->current); + } else if (!strcasecmp (headername, "cc")) { + header = camel_message_info_cc (search->current); + } else { + g_warning ("Performing query on unknown header: %s", headername); + } + + match = argv[1]->value.string; + + if (header && strlen (header) >= strlen (match)) { + /* danw says to use search-engine style matching... + * This means that if the search match string is + * lowercase then compare case-insensitive else + * compare case-sensitive. */ + gboolean is_lowercase = TRUE; + char *c, *end; + + /* remove any leading white space... */ + for ( ; *header && isspace (*header); header++); + + for (c = match; *c; c++) { + if (isalpha (*c) && isupper (*c)) { + is_lowercase = FALSE; + break; + } + } + + end = (char *) header + strlen (header) - strlen (match); + + if (is_lowercase) { + if (!g_strncasecmp (header, match, strlen (match))) + truth = TRUE; + } else { + if (!strncmp (header, match, strlen (match))) + truth = TRUE; + } + } + + r = e_sexp_result_new (ESEXP_RES_BOOL); + r->value.bool = truth; + } else { + r = e_sexp_result_new (ESEXP_RES_ARRAY_PTR); + r->value.ptrarray = g_ptr_array_new (); + } + + return r; +} + +static ESExpResult * +search_header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) +{ + ESExpResult *r; + + r(printf ("executing header-exists\n")); + + if (search->current) { + const gchar *value = NULL; + + if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) + value = camel_medium_get_header (CAMEL_MEDIUM (search->current), + argv[0]->value.string); + + r = e_sexp_result_new (ESEXP_RES_BOOL); + r->value.bool = value ? TRUE : FALSE; + } else { + r = e_sexp_result_new (ESEXP_RES_ARRAY_PTR); + r->value.ptrarray = g_ptr_array_new (); + } + + return r; +} + /* this is just to OR results together */ struct _glib_sux_donkeys { int count; diff --git a/camel/camel-folder-search.h b/camel/camel-folder-search.h index df3c7f5da6..ff24950e53 100644 --- a/camel/camel-folder-search.h +++ b/camel/camel-folder-search.h @@ -72,7 +72,19 @@ struct _CamelFolderSearchClass { /* (header-contains "headername" "string1" ...) List of matches, or true if in single-message mode */ ESExpResult * (*header_contains)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); - + + /* (header-matches "headername" "string") */ + ESExpResult * (*header_matches)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); + + /* (header-starts-with "headername" "string") */ + ESExpResult * (*header_starts_with)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); + + /* (header-ends-with "headername" "string") */ + ESExpResult * (*header_ends_with)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); + + /* (header-exists "headername") */ + ESExpResult * (*header_exists)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); + /* (user-flag "flagname" "flagname" ...) If one of user-flag set */ ESExpResult * (*user_flag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); |