diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-10-18 14:11:54 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-10-18 14:11:54 +0800 |
commit | 229f78b929e0a9553b543f596a7643129d80b494 (patch) | |
tree | 8b33f2672a07f2431fae5bf2f686a52fb8b2e401 /camel/camel-folder-search.c | |
parent | 345f04ccae499e039f1f6f3d21768a2d93ea1c83 (diff) | |
download | gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar.gz gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar.zst gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.zip |
No, we must not encode the headers here. These interfaces ARE raw
2000-10-18 Not Zed <NotZed@HelixCode.com>
* camel-mime-part.c (add_header): No, we must not encode the
headers here. These interfaces ARE raw interfaces as they are
defined in camel_medium. Also removed a bogus/meaningless FIXME.
(set_header): Likewise here, we must not.
(process_header): Removed another bogus comment.
* camel-object.c (shared_is_of_type): Comment out the spitting of
a big warning when we're trying to determine types from code.
* providers/mbox/camel-mbox-summary.c
(message_info_new_from_parser): Only call ibex funcitons if we
have an index.
* providers/mh/camel-mh-summary.c (camel_mh_summary_add): Only
call ibex functions if we have an index.
(remove_summary): Likewise.
(camel_mh_summary_check): Likewise.
* providers/nntp/camel-nntp-store.c (nntp_store_get_folder):
get_folder -> flags argument.
* providers/vee/camel-vee-store.c (vee_get_folder): create->flags.
* providers/pop3/camel-pop3-store.c (get_folder): Changed create
-> flags.
* providers/imap/camel-imap-store.c (get_folder): Added flags
argument.
* providers/mh/camel-mh-folder.c (camel_mh_folder_new): Added
flags argument, and fixed code appropriately.
* providers/mh/camel-mh-store.c (get_folder): Added flags argument.
* camel-folder-search.c (message_body_contains): Perform a regex
match on the contents of messages. This wont quite work yet as
message contents are encoded when written to a stream.
(build_match_regex): Converts a number of strings into a regex
matching pattern, escaping special chars.
(match_message): match a single message from a folder, by uid.
Slow.
(search_body_contains): Changed to support matching where no index
is supplied. Matches are performed by retrieving message
contents, etc.
() WTF? camel should not be including any widget headers.
* providers/mbox/camel-mbox-folder.c (camel_mbox_folder_new):
Added flags argument.
(mbox_refresh_info): Changed into a NOP, the refresh info code
moved into the new function.
(camel_mbox_folder_new): If we have an index requested, build one,
otherwise, remove an old one, or just dont do anything.
* providers/mbox/camel-mbox-store.c (get_folder): Changed create
to flags, changed code to suit.
* camel-store.c (camel_store_get_folder): Changed create to flags.
(get_folder_internal): And here.
(get_folder): And here too.
* camel-store.h (camel_store_get_folder): Change the create
argument to be a flags argument.
svn path=/trunk/; revision=5978
Diffstat (limited to 'camel/camel-folder-search.c')
-rw-r--r-- | camel/camel-folder-search.c | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index 7c1f117ea4..6687067d13 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -26,11 +26,19 @@ #include <stdio.h> #include <string.h> #include <glib.h> +#include <regex.h> #include <gal/widgets/e-unicode.h> #include "camel-folder-search.h" #include "string-utils.h" +#include "camel-exception.h" +#include "camel-medium.h" +#include "camel-multipart.h" +#include "camel-mime-message.h" +#include "gmime-content-field.h" +#include "camel-stream-mem.h" + #define d(x) x #define r(x) x @@ -436,11 +444,112 @@ g_lib_sux_htor(char *key, int value, struct _glib_sux_donkeys *fuckup) g_ptr_array_add(fuckup->uids, key); } +/* performs a 'slow' content-based match */ +static gboolean +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)); + + 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;i<parts && truth==FALSE;i++) { + CamelDataWrapper *part = (CamelDataWrapper *)camel_multipart_get_part(CAMEL_MULTIPART(containee), i); + if (part) { + truth = message_body_contains(part, pattern); + } + } + } else if (CAMEL_IS_MIME_MESSAGE(containee)) { + /* for messages we only look at its contents */ + truth = message_body_contains((CamelDataWrapper *)containee, pattern); + } else if (gmime_content_field_is_type(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); + } + return truth; +} + +/* builds the regex into pattern */ +static int +build_match_regex(regex_t *pattern, int argc, struct _ESExpResult **argv) +{ + GString *match = g_string_new(""); + int c, i, count=0, err; + char *word; + + /* 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;i<argc;i++) { + if (argv[i]->type == ESEXP_RES_STRING) { + if (count > 0) + g_string_append_c(match, '|'); + /* escape any special chars (not sure if this list is complete) */ + word = argv[i]->value.string; + while ((c = *word++)) { + if (strchr("*\\.()[]^$+", c) != NULL) { + g_string_append_c(match, '\\'); + } + g_string_append_c(match, c); + } + count++; + } else { + g_warning("Invalid type passed to body-contains match function"); + } + } + if (argc>1) + g_string_append_c(match, ')'); + err = regcomp(pattern, match->str, REG_EXTENDED|REG_ICASE|REG_NOSUB); + if (err != 0) { + char buffer[1024]; /* dont really care if its longer than this ... */ + + regerror(err, pattern, buffer, 1023); + g_warning("Internal error with search pattern: %s: %s", match->str, buffer); + regfree(pattern); + } + d(printf("Built regex: '%s'\n", match->str)); + g_string_free(match, TRUE); + return err; +} + +static int +match_message(CamelFolder *folder, const char *uid, regex_t *pattern) +{ + CamelMimeMessage *msg; + int truth = FALSE; + CamelException *ex; + + ex = camel_exception_new(); + msg = camel_folder_get_message(folder, uid, ex); + if (!camel_exception_is_set(ex) && msg!=NULL) { + truth = message_body_contains((CamelDataWrapper *)msg, pattern); + camel_object_unref((CamelObject *)msg); + } + camel_exception_free(ex); + return truth; +} + static ESExpResult * search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) { ESExpResult *r; int i, j; + regex_t pattern; if (search->current) { int truth = FALSE; @@ -454,8 +563,14 @@ search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, Cam g_warning("Invalid type passed to body-contains match function"); } } + } else if (search->folder) { + /* we do a 'slow' direct search */ + if (build_match_regex(&pattern, argc, argv) == 0) { + truth = match_message(search->folder, search->current->uid, &pattern); + regfree(&pattern); + } } else { - g_warning("Cannot perform indexed body query with no index"); + g_warning("Cannot perform indexed body query with no index or folder set"); } r->value.bool = truth; } else { @@ -487,7 +602,23 @@ search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, Cam r->value.ptrarray = lambdafoo.uids; g_hash_table_destroy(ht); } + } else if (search->folder) { + /* do a slow search */ + r->value.ptrarray = g_ptr_array_new(); + if (build_match_regex(&pattern, argc, argv) == 0) { + if (search->summary) { + for (i=0;i<search->summary->len;i++) { + CamelMessageInfo *info = g_ptr_array_index(search->summary, i); + + if (match_message(search->folder, info->uid, &pattern)) + g_ptr_array_add(r->value.ptrarray, info->uid); + } + } /* else? we could always get the summary from the folder, but then + we need to free it later somehow */ + regfree(&pattern); + } } else { + g_warning("Cannot perform indexed body query with no index or folder set"); r->value.ptrarray = g_ptr_array_new(); } } |