aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog41
-rw-r--r--camel/camel-filter-driver.c107
-rw-r--r--camel/camel-filter-search.c85
-rw-r--r--camel/camel-filter-search.h7
-rw-r--r--camel/providers/local/camel-local-folder.c12
5 files changed, 206 insertions, 46 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index d887f6a785..c4c35dbc78 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,44 @@
+2002-01-09 Jeffrey Stedfast <fejj@ximian.com>
+
+ * providers/local/camel-mbox-folder.c (camel_mbox_folder_new): If
+ the mbox file is a symlink, follow the symlink and get the One
+ True Path so that we can rewrite the mbox later without worrying
+ about clobbering the symlink.
+
+2002-01-08 Jeffrey Stedfast <fejj@ximian.com>
+
+ * camel-filter-search.c (TODO): There are a few sexp callbacks
+ that could be modified to use fms->info rather than using a
+ message object (like date and possibly mlist stuff) but *only* if
+ the date exists on the CamelMessageInfo object (since it may be
+ blank except for message flags).
+ (camel_filter_search_get_message): New internal convenience
+ function to make sure that the FilterMessageSearch has loaded the
+ message (and to load the message if this isn't the case).
+ (check_header): Call camel_filter_search_get_message().
+ (header_exists): Same.
+ (header_regex): Here too.
+ (header_full_regex): And here.
+ (body_contains): Again here.
+ (body_regex): Here too.
+ (get_sent_date): Here also.
+ (get_received_date): Same.
+ (get_source): Here if we need to.
+ (camel_filter_search_match): Now takes a callback function/data
+ pair for on-demand message loading so that we don't necessarily
+ have to load the message if the defined filter rules don't require
+ it.
+
+ * camel-filter-driver.c (camel_filter_driver_filter_folder): Don't
+ bother fetching the message here, let
+ camel_filter_driver_filter_message() worry about this.
+ (get_message_cb): New utility callback to fetch a message.
+ (camel_filter_driver_filter_message): Only fetch the message if we
+ absolutely need it to get a CamelMessageInfo. Instead of passing a
+ message object to camel_filter_search_match(), pass get_message_cb
+ and some user_data so that the matching code can fetch the message
+ on demand.
+
2002-01-07 Jeffrey Stedfast <fejj@ximian.com>
* camel-folder.c (filter_filter): Flush the only-once actions.
diff --git a/camel/camel-filter-driver.c b/camel/camel-filter-driver.c
index 9a05b91b2c..c9720b621f 100644
--- a/camel/camel-filter-driver.c
+++ b/camel/camel-filter-driver.c
@@ -791,7 +791,7 @@ camel_filter_driver_flush (CamelFilterDriver *driver, CamelException *ex)
data.driver = driver;
data.ex = ex;
- g_hash_table_foreach_remove (p->only_once, run_only_once, &data);
+ g_hash_table_foreach_remove (p->only_once, (GHRFunc) run_only_once, &data);
}
/**
@@ -917,14 +917,13 @@ camel_filter_driver_filter_folder (CamelFilterDriver *driver, CamelFolder *folde
GPtrArray *uids, gboolean remove, CamelException *ex)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
- int i;
- int freeuids = FALSE;
- CamelMimeMessage *message;
+ gboolean freeuids = FALSE;
CamelMessageInfo *info;
char *source_url, *service_url;
const char *folder_name;
int status = 0;
int need_sep = 0;
+ int i;
service_url = camel_service_get_url (CAMEL_SERVICE (camel_folder_get_parent_store (folder)));
folder_name = camel_folder_get_full_name (folder);
@@ -934,9 +933,8 @@ camel_filter_driver_filter_folder (CamelFilterDriver *driver, CamelFolder *folde
if (service_url && *service_url && !need_sep) {
need_sep = (service_url[strlen (service_url)-1] != '/');
}
- source_url = g_strdup_printf ("%s%s%s",
- service_url,
- need_sep ? "/" : "",
+
+ source_url = g_strdup_printf ("%s%s%s", service_url, need_sep ? "/" : "",
folder_name);
g_free (service_url);
@@ -951,20 +949,12 @@ camel_filter_driver_filter_folder (CamelFilterDriver *driver, CamelFolder *folde
report_status (driver, CAMEL_FILTER_STATUS_START, pc, _("Getting message %d of %d"), i+1,
uids->len);
- message = camel_folder_get_message (folder, uids->pdata[i], ex);
- if (!message || camel_exception_is_set (ex)) {
- report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed at message %d of %d"),
- i+1, uids->len);
- status = -1;
- break;
- }
-
if (camel_folder_has_summary_capability (folder))
info = camel_folder_get_message_info (folder, uids->pdata[i]);
else
info = NULL;
- status = camel_filter_driver_filter_message (driver, message, info, uids->pdata[i],
+ status = camel_filter_driver_filter_message (driver, NULL, info, uids->pdata[i],
folder, source_url, source_url, ex);
if (camel_folder_has_summary_capability (folder))
@@ -983,8 +973,6 @@ camel_filter_driver_filter_folder (CamelFilterDriver *driver, CamelFolder *folde
if (cache)
camel_uid_cache_save_uid (cache, uids->pdata[i]);
-
- camel_object_unref (CAMEL_OBJECT (message));
}
if (freeuids)
@@ -1004,10 +992,44 @@ camel_filter_driver_filter_folder (CamelFilterDriver *driver, CamelFolder *folde
}
+struct _get_message {
+ struct _CamelFilterDriverPrivate *p;
+ const char *source_url;
+};
+
+
+static CamelMimeMessage *
+get_message_cb (void *data, CamelException *ex)
+{
+ struct _get_message *msgdata = data;
+ struct _CamelFilterDriverPrivate *p = msgdata->p;
+ const char *source_url = msgdata->source_url;
+ CamelMimeMessage *message;
+
+ if (p->message) {
+ message = p->message;
+ camel_object_ref (CAMEL_OBJECT (message));
+ } else {
+ const char *uid;
+
+ if (p->uid)
+ uid = p->uid;
+ else
+ uid = camel_message_info_uid (p->info);
+
+ message = camel_folder_get_message (p->source, uid, ex);
+ }
+
+ if (source_url && camel_mime_message_get_source (message) == NULL)
+ camel_mime_message_set_source (message, source_url);
+
+ return message;
+}
+
/**
* camel_filter_driver_filter_message:
* @driver: CamelFilterDriver
- * @message: message to filter
+ * @message: message to filter or NULL
* @info: message info or NULL
* @uid: message uid or NULL
* @source: source folder or NULL
@@ -1039,14 +1061,34 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver, CamelMimeMessage
ESExpResult *r;
int result;
+ /* FIXME: make me into a g_return_if_fail/g_assert or whatever... */
+ if (message == NULL && (source == NULL || uid == NULL)) {
+ g_warning ("there is no way to fetch the message using the information provided...");
+ return -1;
+ }
+
if (info == NULL) {
- struct _header_raw *h = CAMEL_MIME_PART (message)->headers;
+ struct _header_raw *h;
+
+ if (message) {
+ camel_object_ref (CAMEL_OBJECT (message));
+ } else {
+ message = camel_folder_get_message (source, uid, ex);
+ if (!message)
+ return -1;
+ }
+ h = CAMEL_MIME_PART (message)->headers;
info = camel_message_info_new_from_header (h);
freeinfo = TRUE;
} else {
if (info->flags & CAMEL_MESSAGE_DELETED)
return 0;
+
+ uid = camel_message_info_uid (info);
+
+ if (message)
+ camel_object_ref (CAMEL_OBJECT (message));
}
p->ex = ex;
@@ -1058,15 +1100,20 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver, CamelMimeMessage
p->uid = uid;
p->source = source;
- if (original_source_url && camel_mime_message_get_source (message) == NULL)
+ if (message && original_source_url && camel_mime_message_get_source (message) == NULL)
camel_mime_message_set_source (message, original_source_url);
- node = (struct _filter_rule *)p->rules.head;
+ node = (struct _filter_rule *) p->rules.head;
result = CAMEL_SEARCH_NOMATCH;
while (node->next && !p->terminated) {
+ struct _get_message data;
+
d(fprintf (stderr, "applying rule %s\naction %s\n", node->match, node->action));
- result = camel_filter_search_match (p->message, p->info,
+ data.p = p;
+ data.source_url = original_source_url;
+
+ result = camel_filter_search_match (get_message_cb, &data, p->info,
original_source_url ? original_source_url : source_url,
node->match, p->ex);
@@ -1119,19 +1166,31 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver, CamelMimeMessage
camel_folder_copy_messages_to (p->source, uids, p->defaultfolder, p->ex);
g_ptr_array_free (uids, TRUE);
} else {
+ if (p->message == NULL) {
+ p->message = camel_folder_get_message (source, uid, ex);
+ if (!p->message)
+ goto error;
+ }
+
camel_folder_append_message (p->defaultfolder, p->message, p->info, p->ex);
}
}
+ if (p->message)
+ camel_object_unref (CAMEL_OBJECT (p->message));
+
if (freeinfo)
camel_message_info_free (info);
return 0;
-error:
+ error:
if (filtered)
camel_filter_driver_log (driver, FILTER_LOG_END, NULL);
+ if (p->message)
+ camel_object_unref (CAMEL_OBJECT (p->message));
+
if (freeinfo)
camel_message_info_free (info);
diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c
index 430f614349..c888887edd 100644
--- a/camel/camel-filter-search.c
+++ b/camel/camel-filter-search.c
@@ -54,6 +54,8 @@
#define d(x)
typedef struct {
+ CamelFilterSearchGetMessageFunc get_message;
+ void *get_message_data;
CamelMimeMessage *message;
CamelMessageInfo *info;
const char *source;
@@ -111,6 +113,21 @@ static struct {
{ "get-size", (ESExpFunc *) get_size, 0 },
};
+
+static CamelMimeMessage *
+camel_filter_search_get_message (FilterMessageSearch *fms, struct _ESExp *sexp)
+{
+ if (fms->message)
+ return fms->message;
+
+ fms->message = fms->get_message (fms->get_message_data, fms->ex);
+
+ if (fms->message == NULL)
+ e_sexp_fatal_error (sexp, _("Failed to retrieve message"));
+
+ return fms->message;
+}
+
static ESExpResult *
check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms, camel_search_match_t how)
{
@@ -124,21 +141,24 @@ check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMess
camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED;
CamelContentType *ct;
const char *charset = NULL;
-
+
if (strcasecmp(name, "x-camel-mlist") == 0) {
header = camel_message_info_mlist(fms->info);
type = CAMEL_SEARCH_TYPE_MLIST;
} else {
- header = camel_medium_get_header(CAMEL_MEDIUM(fms->message), argv[0]->value.string);
+ CamelMimeMessage *message = camel_filter_search_get_message (fms, f);
+
+ header = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string);
+ /* FIXME: what about Resent-To, Resent-Cc and Resent-From? */
if (strcasecmp("to", name) == 0 || strcasecmp("cc", name) == 0 || strcasecmp("from", name) == 0)
type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
else {
- ct = camel_mime_part_get_content_type(CAMEL_MIME_PART(fms->message));
+ ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (message));
if (ct)
charset = e_iconv_charset_name(header_content_type_param(ct, "charset"));
}
}
-
+
if (header) {
for (i=1; i<argc && !matched; i++) {
if (argv[i]->type == ESEXP_RES_STRING)
@@ -187,13 +207,16 @@ header_soundex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMe
static ESExpResult *
header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
+ CamelMimeMessage *message;
gboolean matched = FALSE;
ESExpResult *r;
int i;
+ message = camel_filter_search_get_message (fms, f);
+
for (i = 0; i < argc && !matched; i++) {
if (argv[i]->type == ESEXP_RES_STRING)
- matched = camel_medium_get_header (CAMEL_MEDIUM (fms->message), argv[i]->value.string) != NULL;
+ matched = camel_medium_get_header (CAMEL_MEDIUM (message), argv[i]->value.string) != NULL;
}
r = e_sexp_result_new (f, ESEXP_RES_BOOL);
@@ -206,11 +229,14 @@ static ESExpResult *
header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
+ CamelMimeMessage *message;
regex_t pattern;
const char *contents;
+ message = camel_filter_search_get_message (fms, f);
+
if (argc > 1 && argv[0]->type == ESEXP_RES_STRING
- && (contents = camel_medium_get_header (CAMEL_MEDIUM (fms->message), argv[0]->value.string))
+ && (contents = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string))
&& camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, fms->ex) == 0) {
r->value.bool = regexec (&pattern, contents, 0, NULL, 0) == 0;
regfree (&pattern);
@@ -250,12 +276,14 @@ static ESExpResult *
header_full_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
+ CamelMimeMessage *message;
regex_t pattern;
char *contents;
if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_NEWLINE,
argc, argv, fms->ex) == 0) {
- contents = get_full_header (fms->message);
+ message = camel_filter_search_get_message (fms, f);
+ contents = get_full_header (message);
r->value.bool = regexec (&pattern, contents, 0, NULL, 0) == 0;
g_free (contents);
regfree (&pattern);
@@ -284,10 +312,12 @@ static ESExpResult *
body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
+ CamelMimeMessage *message;
regex_t pattern;
if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_ICASE, argc, argv, fms->ex) == 0) {
- r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *)fms->message, &pattern);
+ message = camel_filter_search_get_message (fms, f);
+ r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *) message, &pattern);
regfree (&pattern);
} else
r->value.bool = FALSE;
@@ -299,11 +329,13 @@ static ESExpResult *
body_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ CamelMimeMessage *message;
regex_t pattern;
if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_NEWLINE,
argc, argv, fms->ex) == 0) {
- r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *)fms->message, &pattern);
+ message = camel_filter_search_get_message (fms, f);
+ r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *) message, &pattern);
regfree (&pattern);
} else
r->value.bool = FALSE;
@@ -365,10 +397,12 @@ user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageS
static ESExpResult *
get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
+ CamelMimeMessage *message;
ESExpResult *r;
+ message = camel_filter_search_get_message (fms, f);
r = e_sexp_result_new (f, ESEXP_RES_INT);
- r->value.number = camel_mime_message_get_date (fms->message, NULL);
+ r->value.number = camel_mime_message_get_date (message, NULL);
return r;
}
@@ -376,10 +410,12 @@ get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMes
static ESExpResult *
get_received_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
+ CamelMimeMessage *message;
ESExpResult *r;
+ message = camel_filter_search_get_message (fms, f);
r = e_sexp_result_new (f, ESEXP_RES_INT);
- r->value.number = camel_mime_message_get_date_received (fms->message, NULL);
+ r->value.number = camel_mime_message_get_date_received (message, NULL);
return r;
}
@@ -415,6 +451,7 @@ get_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessage
static ESExpResult *
get_source (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
+ CamelMimeMessage *message;
ESExpResult *r;
char *src = NULL;
char *tmp;
@@ -428,17 +465,18 @@ get_source (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessag
camel_url_free (url);
}
} else {
- src = g_strdup (camel_mime_message_get_source (fms->message));
+ message = camel_filter_search_get_message (fms, f);
+ src = g_strdup (camel_mime_message_get_source (message));
}
/* This is an abusive hack */
- if ( src && (tmp = strstr (src, "://")) ) {
+ if (src && (tmp = strstr (src, "://"))) {
tmp += 3;
tmp = strchr (tmp, '/');
if (tmp)
*tmp = '\0';
}
-
+
if (src) {
r = e_sexp_result_new (f, ESEXP_RES_STRING);
r->value.string = src;
@@ -473,8 +511,9 @@ get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageS
* Returns one of CAMEL_SEARCH_MATCHED, CAMEL_SEARCH_NOMATCH, or CAMEL_SEARCH_ERROR.
**/
int
-camel_filter_search_match (CamelMimeMessage *message, CamelMessageInfo *info,
- const char *source, const char *expression, CamelException *ex)
+camel_filter_search_match (CamelFilterSearchGetMessageFunc get_message, void *data,
+ CamelMessageInfo *info, const char *source,
+ const char *expression, CamelException *ex)
{
FilterMessageSearch fms;
ESExp *sexp;
@@ -482,7 +521,9 @@ camel_filter_search_match (CamelMimeMessage *message, CamelMessageInfo *info,
gboolean retval;
int i;
- fms.message = message;
+ fms.get_message = get_message;
+ fms.get_message_data = data;
+ fms.message = NULL;
fms.info = info;
fms.source = source;
fms.ex = ex;
@@ -503,6 +544,7 @@ camel_filter_search_match (CamelMimeMessage *message, CamelMessageInfo *info,
e_sexp_error (sexp), expression);
goto error;
}
+
result = e_sexp_eval (sexp);
if (result == NULL) {
if (!camel_exception_is_set (ex))
@@ -519,9 +561,16 @@ camel_filter_search_match (CamelMimeMessage *message, CamelMessageInfo *info,
e_sexp_result_free (sexp, result);
e_sexp_unref (sexp);
+ if (fms.message)
+ camel_object_unref (CAMEL_OBJECT (fms.message));
+
return retval;
-error:
+ error:
+ if (fms.message)
+ camel_object_unref (CAMEL_OBJECT (fms.message));
+
e_sexp_unref (sexp);
+
return CAMEL_SEARCH_ERROR;
}
diff --git a/camel/camel-filter-search.h b/camel/camel-filter-search.h
index 1010603b2b..d54c3c03b7 100644
--- a/camel/camel-filter-search.h
+++ b/camel/camel-filter-search.h
@@ -40,8 +40,11 @@ enum {
CAMEL_SEARCH_MATCHED = 1,
};
-int camel_filter_search_match (CamelMimeMessage *message, CamelMessageInfo *info,
- const char *source, const char *expression, CamelException *ex);
+typedef CamelMimeMessage * (*CamelFilterSearchGetMessageFunc) (void *data, CamelException *ex);
+
+int camel_filter_search_match (CamelFilterSearchGetMessageFunc get_message, void *data,
+ CamelMessageInfo *info, const char *source,
+ const char *expression, CamelException *ex);
#ifdef __cplusplus
}
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index 0a4d581bdf..b6d6ef8ab2 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -24,6 +24,7 @@
#endif
#include <stdlib.h>
+#include <limits.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
@@ -172,6 +173,7 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con
CamelFolderInfo *fi;
CamelFolder *folder;
const char *root_dir_path, *name;
+ char folder_path[PATH_MAX];
struct stat st;
int forceindex;
@@ -191,13 +193,19 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con
lf->folder_path = g_strdup_printf("%s/%s", root_dir_path, full_name);
lf->summary_path = g_strdup_printf("%s/%s.ev-summary", root_dir_path, full_name);
lf->index_path = g_strdup_printf("%s/%s.ibex", root_dir_path, full_name);
-
+
+ /* follow any symlinks to the mailbox */
+ if (lstat (lf->folder_path, &st) != -1 && S_ISLNK (st.st_mode) &&
+ realpath (lf->folder_path, folder_path) != NULL) {
+ g_free (lf->folder_path);
+ lf->folder_path = g_strdup (folder_path);
+ }
+
lf->changes = camel_folder_change_info_new();
/* if we have no index file, force it */
forceindex = stat(lf->index_path, &st) == -1;
if (flags & CAMEL_STORE_FOLDER_BODY_INDEX) {
-
lf->index = ibex_open(lf->index_path, O_CREAT | O_RDWR, 0600);
if (lf->index == NULL) {
/* yes, this isn't fatal at all */