aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-folder-search.c
diff options
context:
space:
mode:
authorNot Zed <NotZed@HelixCode.com>2000-10-18 14:11:54 +0800
committerMichael Zucci <zucchi@src.gnome.org>2000-10-18 14:11:54 +0800
commit229f78b929e0a9553b543f596a7643129d80b494 (patch)
tree8b33f2672a07f2431fae5bf2f686a52fb8b2e401 /camel/camel-folder-search.c
parent345f04ccae499e039f1f6f3d21768a2d93ea1c83 (diff)
downloadgsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar
gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar.gz
gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar.bz2
gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar.lz
gsoc2013-evolution-229f78b929e0a9553b543f596a7643129d80b494.tar.xz
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.c133
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();
}
}