diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-10-12 21:53:50 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-10-12 21:53:50 +0800 |
commit | c308f5eeef858ef813205af508e8ef94a8208d62 (patch) | |
tree | f2bad01816b88533321c63e809c0d609549b8f74 /filter/filter-driver.c | |
parent | 80237e0c26dd375b0269dc2099d49fc3cd50a4f2 (diff) | |
download | gsoc2013-evolution-c308f5eeef858ef813205af508e8ef94a8208d62.tar.gz gsoc2013-evolution-c308f5eeef858ef813205af508e8ef94a8208d62.tar.zst gsoc2013-evolution-c308f5eeef858ef813205af508e8ef94a8208d62.zip |
Report the percentage of file complete for the filter.
2000-10-11 Not Zed <NotZed@HelixCode.com>
* filter-driver.c (filter_driver_filter_mbox): Report the
percentage of file complete for the filter.
2000-10-10 Not Zed <NotZed@HelixCode.com>
* filter-driver.c (filter_driver_run): Why on earth does this code
ref all these objects for? This is not right at all.
(filter_driver_run): Changed source type to a string.
(filter_driver_run): REmove the very weird exception copying
stuff - just ref it instead.
(do_score):
(do_colour):
(do_stop):
(do_copy):
(mark_forward):
(do_delete): Removed bogus 'terminated' testing. This is NOT
NEEDED HERE. It is tested after every rule/action, and
termination only makes sense at that point.
(filter_driver_filter_message): new funciton (renamed), filter
only a message.
(filter_driver_filter_mbox): Filter a whole mbox.
(filter_driver_run): If we aren't given an info, create a simple
one based on the message headers.
(filter_driver_filter_message): Renamed from filter_driver_run().
(filter_driver_set_status_func): Set the status callback function.
(filter_driver_set_default_folder): Set the default folder for
filtering.
(report_status): Internal function to report the status of a given
event.
(do_copy): Removed a pointless cache lookup - duh, we do it in
open_folder anyway (infact, we do it in camel too!!).
(filter_driver_filter_message): Removed pointless re-refing of
arguments. Why would anyone think this could be any use at all?
(filter_driver_filter_folder): New function to filter a whole
folder.
* filter-editor.c (rule_add): api fixes.
(rule_edit):
(rule_up):
(rule_down):
(set_sensitive): This didn't take into account the source, now it
does.
(select_source): Fix for api changes. Changed the rather generic
'number' argument to be 'source', and a string.
(filter_editor_construct): Changed the 'number' to 'source', and
set the string appropriately. Added a warning for one case where
the glade file is out of sync.
* score-editor.c (score_editor_construct):
(rule_edit):
(rule_delete):
(rule_up):
(rule_down):
(set_sensitive): api fixes.
* vfolder-editor.c (set_sensitive): Api fixes.
(vfolder_editor_construct):
(rule_edit):
(vfolder_editor_construct):
* rule-context.h (RCNextRuleFunc): Added a source argument.
* rule-context.c (rule_context_next_rule): Added source argument.
(rule_context_find_rule): Added source argument.
(rule_context_get_rank_rule): Added source argument.
(rule_context_get_rank_rule_with_source): Removed.
(save): Fixed for changes to RCNextRuleFunc prototype.
* filter-rule.h: Changed the source to be a string, removed the
filter_source_t type.
* filter-rule.c (filter_rule_set_source): New function to set the
source of a rule. What idiot ran this code through indent?
(filter_rule_find_list): Added a source argument.
(filter_rule_next_list): Added a source argument.
(get_widget): Fixed the wording. You dont remove search parts,
you can only remove the last one. Why you even need to mention
they are search 'criteria' is beyond me. Whoever added the
scrolled window needs to be shot, its the single most awful GUI
feature ever invented (ranks with the close button next to
maximise).
(xml_encode): Save source as a string (if present).
(xml_decode): Likewise for loading & fixed a small memleak.
(filter_rule_finalise): Free source.
svn path=/trunk/; revision=5884
Diffstat (limited to 'filter/filter-driver.c')
-rw-r--r-- | filter/filter-driver.c | 379 |
1 files changed, 258 insertions, 121 deletions
diff --git a/filter/filter-driver.c b/filter/filter-driver.c index a7737d7be3..2e6c797ab6 100644 --- a/filter/filter-driver.c +++ b/filter/filter-driver.c @@ -44,7 +44,11 @@ struct _FilterDriverPrivate { GHashTable *globals; /* global variables */ - + + CamelFolder *defaultfolder; /* defualt folder */ + FDStatusFunc *statusfunc; /* status callback */ + void *statusdata; /* status callback data */ + FilterContext *context; /* for callback */ @@ -61,7 +65,7 @@ struct _FilterDriverPrivate { CamelMimeMessage *message; /* input message */ CamelMessageInfo *info; /* message summary info */ - + FILE *logfile; /* log file */ CamelException *ex; @@ -164,9 +168,6 @@ filter_driver_init (FilterDriver *obj) p->globals = g_hash_table_new (g_str_hash, g_str_equal); p->folders = g_hash_table_new (g_str_hash, g_str_equal); - - /* Will get set in filter_driver_run */ - p->ex = NULL; } static void @@ -190,6 +191,9 @@ filter_driver_finalise (GtkObject *obj) g_hash_table_destroy (p->globals); gtk_object_unref (GTK_OBJECT (p->eval)); + + if (p->defaultfolder) + camel_object_unref((CamelObject *)p->defaultfolder); g_free (p); @@ -224,6 +228,43 @@ filter_driver_new (FilterContext *context, FilterGetFolderFunc get_folder, void } +void +filter_driver_set_status_func(FilterDriver *d, FDStatusFunc *func, void *data) +{ + struct _FilterDriverPrivate *p = _PRIVATE (d); + + p->statusfunc = func; + p->statusdata = data; +} + +void +filter_driver_set_default_folder(FilterDriver *d, CamelFolder *def) +{ + struct _FilterDriverPrivate *p = _PRIVATE (d); + + if (p->defaultfolder) + camel_object_unref((CamelObject *)p->defaultfolder); + p->defaultfolder = def; + if (p->defaultfolder) + camel_object_ref((CamelObject *)p->defaultfolder); +} + +static void +report_status(FilterDriver *driver, enum filter_status_t status, const char *desc, ...) +{ + struct _FilterDriverPrivate *p = _PRIVATE (driver); + va_list ap; + char *str; + + if (p->statusfunc) { + va_start(ap, desc); + str = g_strdup_vprintf(desc, ap); + p->statusfunc(driver, status, str, p->message, p->statusdata); + g_free(str); + } +} + + #if 0 void filter_driver_set_global (FilterDriver *d, const char *name, const char *value) @@ -245,27 +286,21 @@ do_delete (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver { struct _FilterDriverPrivate *p = _PRIVATE (driver); - if (!p->terminated) { - d(fprintf (stderr, "doing delete\n")); - p->deleted = TRUE; - if (p->logfile) - fprintf (p->logfile, "Action = Deleted\n"); - } - + d(fprintf (stderr, "doing delete\n")); + p->deleted = TRUE; + report_status(driver, FILTER_STATUS_ACTION, "Delete"); + return NULL; } static ESExpResult * mark_forward (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *driver) { - struct _FilterDriverPrivate *p = _PRIVATE (driver); + /*struct _FilterDriverPrivate *p = _PRIVATE (driver);*/ - if (!p->terminated) { - d(fprintf (stderr, "marking message for forwarding\n")); - /* FIXME: do stuff here */ - if (p->logfile) - fprintf (p->logfile, "Action = Forwarded\n"); - } + d(fprintf (stderr, "marking message for forwarding\n")); + /* FIXME: do stuff here */ + report_status(driver, FILTER_STATUS_ACTION, "Forward"); return NULL; } @@ -276,28 +311,22 @@ do_copy (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *d struct _FilterDriverPrivate *p = _PRIVATE (driver); int i; - if (!p->terminated) { - d(fprintf (stderr, "copying message...\n")); - p->copied = TRUE; - for (i = 0; i < argc; i++) { - if (argv[i]->type == ESEXP_RES_STRING) { + d(fprintf (stderr, "copying message...\n")); + p->copied = TRUE; + for (i = 0; i < argc; i++) { + if (argv[i]->type == ESEXP_RES_STRING) { /* open folders we intent to copy to */ - char *folder = argv[i]->value.string; - CamelFolder *outbox; - - outbox = g_hash_table_lookup (p->folders, folder); - if (!outbox) { - outbox = open_folder (driver, folder); - if (!outbox) - continue; - } - - mail_tool_camel_lock_up (); - camel_folder_append_message (outbox, p->message, p->info, p->ex); - if (p->logfile) - fprintf (p->logfile, "Action = Copied to folder %s\n", outbox->full_name); - mail_tool_camel_lock_down (); - } + char *folder = argv[i]->value.string; + CamelFolder *outbox; + + outbox = open_folder (driver, folder); + if (!outbox) + continue; + + mail_tool_camel_lock_up (); + camel_folder_append_message (outbox, p->message, p->info, p->ex); + report_status(driver, FILTER_STATUS_ACTION, "Copy to folder %s", outbox->full_name); + mail_tool_camel_lock_down (); } } @@ -309,10 +338,9 @@ do_stop (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *d { struct _FilterDriverPrivate *p = _PRIVATE (driver); - if (!p->terminated) { - d(fprintf (stderr, "terminating message processing\n")); - p->terminated = TRUE; - } + report_status(driver, FILTER_STATUS_ACTION, "Stopped processing"); + d(fprintf (stderr, "terminating message processing\n")); + p->terminated = TRUE; return NULL; } @@ -322,13 +350,10 @@ do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver { struct _FilterDriverPrivate *p = _PRIVATE (driver); - if (!p->terminated) { - d(fprintf (stderr, "setting colour tag\n")); - if (argc > 0 && argv[0]->type == ESEXP_RES_STRING) { - camel_tag_set (&p->info->user_tags, "colour", argv[0]->value.string); - if (p->logfile) - fprintf (p->logfile, "Action = Set color to %s\n", argv[0]->value.string); - } + d(fprintf (stderr, "setting colour tag\n")); + if (argc > 0 && argv[0]->type == ESEXP_RES_STRING) { + camel_tag_set (&p->info->user_tags, "colour", argv[0]->value.string); + report_status(driver, FILTER_STATUS_ACTION, "Set colour to %s", argv[0]->value.string); } return NULL; @@ -339,17 +364,14 @@ do_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver * { struct _FilterDriverPrivate *p = _PRIVATE (driver); - if (!p->terminated) { - d(fprintf (stderr, "setting score tag\n")); - if (argc > 0 && argv[0]->type == ESEXP_RES_INT) { - char *value; - - value = g_strdup_printf ("%d", argv[0]->value.number); - camel_tag_set (&p->info->user_tags, "score", value); - if (p->logfile) - fprintf (p->logfile, "Action = Set score to %d\n", argv[0]->value.number); - g_free (value); - } + d(fprintf (stderr, "setting score tag\n")); + if (argc > 0 && argv[0]->type == ESEXP_RES_INT) { + char *value; + + value = g_strdup_printf ("%d", argv[0]->value.number); + camel_tag_set (&p->info->user_tags, "score", value); + report_status(driver, FILTER_STATUS_ACTION, "Set score to %d", argv[0]->value.number); + g_free (value); } return NULL; @@ -415,43 +437,177 @@ free_key (gpointer key, gpointer value, gpointer user_data) } #endif + +void +filter_driver_status_log(FilterDriver *driver, enum filter_status_t status, const char *desc, CamelMimeMessage *msg, void *data) +{ + FILE *out = data; + + switch(status) { + case FILTER_STATUS_END: { + /* write log header */ + time_t t; + char date[50]; + + time(&t); + strftime(date, 49, "%a, %d %b %Y %H:%M:%S", localtime(&t)); + fprintf(out, " - Applied filter \"%s\" to message from %s - \"%s\" at %s\n", + desc, msg?camel_mime_message_get_from(msg):"unknown", + msg?camel_mime_message_get_subject(msg):"", date); + break; + } + case FILTER_STATUS_START: + fprintf(out, "\n"); + break; + case FILTER_STATUS_ACTION: + fprintf(out, "Action: %s\n", desc); + break; + default: + /* nothing else is loggable */ + break; + } +} + + +/* will filter only an mbox - is more efficient as it doesn't need to open the folder through camel directly */ +void +filter_driver_filter_mbox(FilterDriver *driver, const char *mbox, const char *source, CamelException *ex) +{ + CamelMimeParser *mp =NULL; + int fd = -1; + int i = 0; + struct stat st; + + fd = open(mbox, O_RDONLY); + if (fd == -1) { + camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM, "Unable to open spool folder"); + goto fail; + } + /* to get the filesize */ + fstat(fd, &st); + + mp = camel_mime_parser_new(); + camel_mime_parser_scan_from(mp, TRUE); + if (camel_mime_parser_init_with_fd(mp, fd) == -1) { + camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM, "Unable to process spool folder"); + goto fail; + } + fd = -1; + while (camel_mime_parser_step(mp, 0, 0) == HSCAN_FROM) { + CamelMimeMessage *msg; + int pc; + + pc = camel_mime_parser_tell(mp) * 100 / st.st_size; + report_status(driver, FILTER_STATUS_START, "Getting message %d (%d%% of file)", i, pc); + + msg = camel_mime_message_new(); + if (camel_mime_part_construct_from_parser((CamelMimePart *)msg, mp) == -1) { + report_status(driver, FILTER_STATUS_END, "Failed message %d", i); + camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM, "Cannot open message"); + camel_object_unref((CamelObject *)msg); + goto fail; + } + + filter_driver_filter_message(driver, msg, NULL, source, ex); + camel_object_unref((CamelObject *)msg); + if (camel_exception_is_set(ex)) { + report_status(driver, FILTER_STATUS_END, "Failed message %d", i); + goto fail; + } + + report_status(driver, FILTER_STATUS_END, "Finished message %d", i); + i++; + + /* skip over the FROM_END state */ + camel_mime_parser_step(mp, 0, 0); + } +fail: + if (fd != -1) + close(fd); + if (mp) + camel_object_unref((CamelObject *)mp); +} + +/* will filter a folder */ +void +filter_driver_filter_folder(FilterDriver *driver, CamelFolder *folder, const char *source, GPtrArray *uids, gboolean remove, CamelException *ex) +{ + int i; + int freeuids = FALSE; + CamelMimeMessage *message; + const CamelMessageInfo *info; + + if (uids == NULL) { + uids = camel_folder_get_uids(folder); + freeuids = TRUE; + } + + for (i=0;i<uids->len;i++) { + + report_status(driver, FILTER_STATUS_START, "Getting message %d of %d", i, uids->len); + + message = camel_folder_get_message (folder, uids->pdata[i], ex); + if (camel_exception_is_set (ex)) { + report_status(driver, FILTER_STATUS_END, "Failed at message %d of %d", i, uids->len); + break; + } + + if (camel_folder_has_summary_capability (folder)) + info = camel_folder_get_message_info (folder, uids->pdata[i]); + else + info = NULL; + + filter_driver_filter_message(driver, message, (CamelMessageInfo *)info, source, ex); + if (camel_exception_is_set (ex)) { + report_status(driver, FILTER_STATUS_END, "Failed at message %d of %d", i, uids->len); + break; + } + + if (remove) + camel_folder_set_message_flags (folder, uids->pdata[i], CAMEL_MESSAGE_DELETED,CAMEL_MESSAGE_DELETED); + + camel_object_unref (CAMEL_OBJECT (message)); + } + + if (freeuids) + camel_folder_free_uids(folder, uids); +} + gboolean -filter_driver_run (FilterDriver *driver, CamelMimeMessage *message, CamelMessageInfo *info, - CamelFolder *inbox, enum _filter_source_t sourcetype, - FILE *logfile, CamelException *ex) +filter_driver_filter_message (FilterDriver *driver, CamelMimeMessage *message, CamelMessageInfo *info, + const char *source, CamelException *ex) { struct _FilterDriverPrivate *p = _PRIVATE (driver); ESExpResult *r; GString *fsearch, *faction; FilterFilter *rule; - - gtk_object_ref (GTK_OBJECT (driver)); - camel_object_ref (CAMEL_OBJECT (message)); - - if (inbox) - camel_object_ref (CAMEL_OBJECT (inbox)); - - p->ex = camel_exception_new (); + int freeinfo = FALSE; + + if (info == NULL) { + struct _header_raw *h = CAMEL_MIME_PART(message)->headers; + + info = g_malloc0(sizeof(*info)); + freeinfo = TRUE; + info->subject = camel_folder_summary_format_string(h, "subject"); + info->from = camel_folder_summary_format_address(h, "from"); + info->to = camel_folder_summary_format_address(h, "to"); + info->cc = camel_folder_summary_format_address(h, "cc"); + } + + p->ex = ex; p->terminated = FALSE; p->deleted = FALSE; p->copied = FALSE; p->message = message; p->info = info; - p->logfile = logfile; fsearch = g_string_new (""); faction = g_string_new (""); rule = NULL; - while ((rule = (FilterFilter *)rule_context_next_rule ((RuleContext *)p->context, (FilterRule *)rule))) { + while ((rule = (FilterFilter *)rule_context_next_rule ((RuleContext *)p->context, (FilterRule *)rule, source))) { gboolean matched; - if (((FilterRule *)rule)->source != sourcetype) { - d(fprintf (stderr, "skipping rule %s - wrong source type (%d %d)\n", ((FilterRule *)rule)->name, - ((FilterRule *)rule)->source, sourcetype)); - continue; - } - g_string_truncate (fsearch, 0); g_string_truncate (faction, 0); @@ -464,59 +620,40 @@ filter_driver_run (FilterDriver *driver, CamelMimeMessage *message, CamelMessage matched = filter_message_search (p->message, p->info, fsearch->str, p->ex); mail_tool_camel_lock_down (); - if (!matched) - continue; - + if (matched) { #ifndef NO_WARNINGS #warning "Must check expression parsed and executed properly?" #endif - if (logfile) { - /* write log header */ - time_t t; - char date[50]; - - time (&t); - strftime (date, 49, "%a, %d %b %Y %H:%M:%S", localtime (&t)); - fprintf (logfile, "Applied filter \"%s\" to message from %s - \"%s\" at %s\n", - fsearch->str, camel_mime_message_get_from (message), - camel_mime_message_get_subject (message), date); - } - - /* perform necessary filtering actions */ - e_sexp_input_text (p->eval, faction->str, strlen (faction->str)); - e_sexp_parse (p->eval); - r = e_sexp_eval (p->eval); - e_sexp_result_free (r); - - if (logfile) { - /* spacer between filters */ - fprintf (logfile, "\n"); + /* perform necessary filtering actions */ + e_sexp_input_text (p->eval, faction->str, strlen (faction->str)); + e_sexp_parse (p->eval); + r = e_sexp_eval (p->eval); + e_sexp_result_free (r); + if (p->terminated) + break; } - - if (p->terminated) - break; } g_string_free (fsearch, TRUE); g_string_free (faction, TRUE); - if (!p->deleted && !p->copied && inbox) { + if (!p->deleted && !p->copied && p->defaultfolder) { /* copy it to the default inbox */ + report_status(driver, FILTER_STATUS_ACTION, "Copy to default folder"); mail_tool_camel_lock_up (); - camel_folder_append_message (inbox, p->message, p->info, p->ex); + camel_folder_append_message (p->defaultfolder, p->message, p->info, p->ex); mail_tool_camel_lock_down (); } - - /* transfer the exception over to the parents exception */ - if (camel_exception_is_set (p->ex)) - camel_exception_xfer (ex, p->ex); - camel_exception_free (p->ex); - - camel_object_unref (CAMEL_OBJECT (message)); - if (inbox) - camel_object_unref (CAMEL_OBJECT (inbox)); - - gtk_object_unref (GTK_OBJECT (driver)); + + if (freeinfo) { + camel_flag_list_free(&info->user_flags); + camel_tag_list_free(&info->user_tags); + g_free(info->subject); + g_free(info->from); + g_free(info->to); + g_free(info->cc); + g_free(info); + } return p->copied; } |