+2006-08-30 [colin] 2.4.0cvs114
+
+ * src/procmsg.c
+ * src/procmsg.h
+ Provide a way to filter a list of
+ messages in an optimised manner, and
+ add a list-filtering hook
+ * src/folder.c
+ * src/inc.c
+ * src/mbox.c
+ Use the list filtering
+ * src/plugins/bogofilter/bogofilter.c
+ Use the list-filtering hook
+ Use -b (bulk) mode for more speed
+ when learning and filtering
+ * src/etpan/imap-thread.c
+ Make log output shorter in UID SEARCH
+
+
2006-08-30 [colin] 2.4.0cvs113
* src/plugins/bogofilter/bogofilter.c
( cvs diff -u -r 1.207.2.113 -r 1.207.2.114 src/folderview.c; cvs diff -u -r 1.83.2.82 -r 1.83.2.83 src/mimeview.c; cvs diff -u -r 1.20.2.14 -r 1.20.2.15 src/mimeview.h; cvs diff -u -r 1.395.2.236 -r 1.395.2.237 src/summaryview.c; cvs diff -u -r 1.96.2.141 -r 1.96.2.142 src/textview.c; cvs diff -u -r 1.5.2.39 -r 1.5.2.40 src/gtk/gtkutils.c; cvs diff -u -r 1.4.2.24 -r 1.4.2.25 src/gtk/gtkutils.h; ) > 2.4.0cvs111.patchset
( cvs diff -u -r 1.16.2.38 -r 1.16.2.39 src/msgcache.c; ) > 2.4.0cvs112.patchset
( cvs diff -u -r 1.1.2.4 -r 1.1.2.5 src/plugins/bogofilter/bogofilter.c; ) > 2.4.0cvs113.patchset
+( cvs diff -u -r 1.213.2.111 -r 1.213.2.112 src/folder.c; cvs diff -u -r 1.149.2.55 -r 1.149.2.56 src/inc.c; cvs diff -u -r 1.28.2.24 -r 1.28.2.25 src/mbox.c; cvs diff -u -r 1.150.2.76 -r 1.150.2.77 src/procmsg.c; cvs diff -u -r 1.60.2.34 -r 1.60.2.35 src/procmsg.h; cvs diff -u -r 1.1.4.47 -r 1.1.4.48 src/etpan/imap-thread.c; cvs diff -u -r 1.1.2.5 -r 1.1.2.6 src/plugins/bogofilter/bogofilter.c; ) > 2.4.0cvs114.patchset
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=113
+EXTRA_VERSION=114
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
free(buf);
}
+void imap_logger_uid(int direction, const char * str, size_t size)
+{
+ gchar *buf;
+ gchar **lines;
+ int i = 0;
+
+ buf = malloc(size+1);
+ memset(buf, 0, size+1);
+ strncpy(buf, str, size);
+ buf[size] = '\0';
+ if (!strncmp(buf, "<<<<<<<", 7)
+ || !strncmp(buf, ">>>>>>>", 7)) {
+ free(buf);
+ return;
+ }
+ while (strstr(buf, "\r"))
+ *strstr(buf, "\r") = ' ';
+ while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
+ buf[strlen(buf)-1] = '\0';
+
+ lines = g_strsplit(buf, "\n", -1);
+
+ if (direction == 0 && size > 64) {
+ gchar tmp[32];
+ strncpy2(tmp, lines[0], 31);
+ log_print("IMAP4%c %s[... - %zd bytes more]\n", direction?'>':'<', tmp,
+ size-32);
+ } else {
+ while (lines[i] && *lines[i]) {
+ log_print("IMAP4%c %s\n", direction?'>':'<', lines[i]);
+ i++;
+ }
+ }
+ g_strfreev(lines);
+ free(buf);
+}
+
void imap_logger_append(int direction, const char * str, size_t size)
{
gchar *buf;
result->error = -1;
result->search_result = NULL;
} else {
+ mailstream_logger = imap_logger_uid;
+
r = mailimap_uid_search(param->imap, NULL, key, &search_result);
+ mailstream_logger = imap_logger_cmd;
+
/* free the key (with the imapset) */
mailimap_search_key_free(key);
folder_item_update_freeze();
if (newmsg_list != NULL) {
GSList *elem, *to_filter = NULL;
- int total = g_slist_length(newmsg_list), cur = 0;
-
- if ((filtering == TRUE) &&
- (item->stype == F_INBOX) &&
- (item->folder->account != NULL) &&
- (item->folder->account->filter_on_recv))
- statusbar_print_all(_("Filtering messages...\n"));
+ gboolean do_filter = (filtering == TRUE) &&
+ (item->stype == F_INBOX) &&
+ (item->folder->account != NULL) &&
+ (item->folder->account->filter_on_recv);
for (elem = newmsg_list; elem != NULL; elem = g_slist_next(elem)) {
MsgInfo *msginfo = (MsgInfo *) elem->data;
- statusbar_progress_all(cur++,total, 10);
-
msgcache_add_msg(item->cache, msginfo);
- if ((filtering == TRUE) &&
- (item->stype == F_INBOX) &&
- (item->folder->account != NULL) &&
- (item->folder->account->filter_on_recv) &&
- procmsg_msginfo_filter(msginfo, item->folder->account))
- to_filter = g_slist_prepend(to_filter, msginfo);
- else {
+ if (!do_filter) {
exists_list = g_slist_prepend(exists_list, msginfo);
-
+
if(prefs_common.thread_by_subject &&
MSG_IS_IGNORE_THREAD(msginfo->flags) &&
!subject_table_lookup(subject_table, msginfo->subject)) {
subject_table_insert(subject_table, msginfo->subject, msginfo);
- }
+ }
}
}
- filtering_move_and_copy_msgs(to_filter);
- for (elem = to_filter; elem; elem = g_slist_next(elem)) {
- MsgInfo *msginfo = (MsgInfo *)elem->data;
- procmsg_msginfo_free(msginfo);
- }
- g_slist_free(to_filter);
+ if (do_filter) {
+ GSList *unfiltered;
+ procmsg_msglist_filter(newmsg_list, item->folder->account,
+ &to_filter, &unfiltered,
+ TRUE);
+
+ if (to_filter != NULL) {
+ filtering_move_and_copy_msgs(to_filter);
+ for (elem = to_filter; elem; elem = g_slist_next(elem)) {
+ MsgInfo *msginfo = (MsgInfo *)elem->data;
+ procmsg_msginfo_free(msginfo);
+ }
+ g_slist_free(to_filter);
+ }
+ if (unfiltered != NULL) {
+ for (elem = unfiltered; elem; elem = g_slist_next(elem)) {
+ MsgInfo *msginfo = (MsgInfo *)elem->data;
+ exists_list = g_slist_prepend(exists_list, msginfo);
+
+ if(prefs_common.thread_by_subject &&
+ MSG_IS_IGNORE_THREAD(msginfo->flags) &&
+ !subject_table_lookup(subject_table, msginfo->subject)) {
+ subject_table_insert(subject_table, msginfo->subject, msginfo);
+ }
+ }
+ g_slist_free(unfiltered);
+ }
+ }
+
g_slist_free(newmsg_list);
- statusbar_progress_all(0,0,0);
- statusbar_pop_all();
update_flags |= F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT;
}
gchar *msg;
gchar *fin_msg;
FolderItem *processing, *inbox;
- MsgInfo *msginfo;
GSList *msglist, *msglist_element;
gboolean cancelled = FALSE;
}
for (; inc_dialog->queue_list != NULL && !cancelled; inc_dialog->cur_row++) {
- int cur = 1, total = 0;
session = inc_dialog->queue_list->data;
pop3_session = POP3_SESSION(session->session);
+ GSList *filtered, *unfiltered;
if (pop3_session->pass == NULL) {
SET_PIXMAP_AND_TEXT(okpix, _("Cancelled"));
/* process messages */
folder_item_update_freeze();
- if (pop3_session->ac_prefs->filter_on_recv)
- statusbar_print_all(_("Filtering messages...\n"));
- total = g_slist_length(msglist);
-
- for(msglist_element = msglist; msglist_element != NULL;
- msglist_element = msglist_element->next) {
- gchar *filename;
- msginfo = (MsgInfo *) msglist_element->data;
- filename = folder_item_fetch_msg(processing, msginfo->msgnum);
- g_free(filename);
+
+ procmsg_msglist_filter(msglist, pop3_session->ac_prefs,
+ &filtered, &unfiltered,
+ pop3_session->ac_prefs->filter_on_recv);
- if (pop3_session->ac_prefs->filter_on_recv)
- statusbar_progress_all(cur++,total, prefs_common.statusbar_update_step);
+ if (filtered != NULL)
+ filtering_move_and_copy_msgs(filtered);
+ if (unfiltered != NULL)
+ folder_item_move_msgs(inbox, unfiltered);
- if (!pop3_session->ac_prefs->filter_on_recv ||
- !procmsg_msginfo_filter(msginfo, pop3_session->ac_prefs))
- folder_item_move_msg(inbox, msginfo);
- }
- filtering_move_and_copy_msgs(msglist);
for(msglist_element = msglist; msglist_element != NULL;
msglist_element = msglist_element->next) {
MsgInfo *msginfo = (MsgInfo *)msglist_element->data;
}
folder_item_update_thaw();
- statusbar_progress_all(0,0,0);
- statusbar_pop_all();
-
g_slist_free(msglist);
+ g_slist_free(filtered);
+ g_slist_free(unfiltered);
statusbar_pop_all();
gint lines;
MsgInfo *msginfo;
gboolean more;
- GSList *to_filter = NULL, *to_drop = NULL, *cur, *to_add = NULL;
+ GSList *to_filter = NULL, *filtered = NULL, *unfiltered = NULL, *cur, *to_add = NULL;
gboolean printed = FALSE;
FolderItem *dropfolder;
return -1;
}
msginfo = folder_item_get_msginfo(dropfolder, msgnum);
- if (!procmsg_msginfo_filter(msginfo, NULL))
- to_drop = g_slist_prepend(to_drop, msginfo);
- else
- to_filter = g_slist_prepend(to_filter, msginfo);
+ to_filter = g_slist_prepend(to_filter, msginfo);
} else {
MsgFileInfo *finfo = g_new0(MsgFileInfo, 1);
finfo->file = tmp_file;
statusbar_pop_all();
if (apply_filter) {
- to_drop = g_slist_reverse(to_drop);
- folder_item_move_msgs(dest, to_drop);
- for (cur = to_drop; cur; cur = g_slist_next(cur)) {
+ procmsg_msglist_filter(to_filter, NULL, &filtered, &unfiltered, TRUE);
+ unfiltered = g_slist_reverse(unfiltered);
+ folder_item_move_msgs(dest, unfiltered);
+ for (cur = unfiltered; cur; cur = g_slist_next(cur)) {
MsgInfo *info = (MsgInfo *)cur->data;
procmsg_msginfo_free(info);
}
- to_filter = g_slist_reverse(to_filter);
- filtering_move_and_copy_msgs(to_filter);
- for (cur = to_filter; cur; cur = g_slist_next(cur)) {
+ filtered = g_slist_reverse(filtered);
+ filtering_move_and_copy_msgs(filtered);
+ for (cur = filtered; cur; cur = g_slist_next(cur)) {
MsgInfo *info = (MsgInfo *)cur->data;
procmsg_msginfo_free(info);
}
- g_slist_free(to_drop);
+ g_slist_free(unfiltered);
+ g_slist_free(filtered);
g_slist_free(to_filter);
} else if (to_add) {
folder_item_add_msgs(dropfolder, to_add, TRUE);
#include <pwd.h>
#endif
-enum {
- CHILD_RUNNING = 1 << 0,
- TIMEOUT_RUNNING = 1 << 1,
-};
+#define MAILS_PER_BATCH 20
static guint hook_id = -1;
static MessageCallback message_callback;
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
};
+/*
+ * Helper function for spawn_with_input() - write an entire
+ * string to a fd.
+ */
+static gboolean
+write_all (int fd,
+ const char *buf,
+ gsize to_write)
+{
+ while (to_write > 0)
+ {
+ gssize count = write (fd, buf, to_write);
+ if (count < 0)
+ {
+ if (errno != EINTR)
+ return FALSE;
+ }
+ else
+ {
+ to_write -= count;
+ buf += count;
+ }
+ }
+
+ return TRUE;
+}
+
static gboolean mail_filtering_hook(gpointer source, gpointer data)
{
MailFilteringData *mail_filtering_data = (MailFilteringData *) source;
MsgInfo *msginfo = mail_filtering_data->msginfo;
- gboolean is_spam = FALSE;
+ GSList *msglist = mail_filtering_data->msglist;
+ GSList *cur = NULL;
static gboolean warned_error = FALSE;
gchar *file = NULL, *cmd = NULL;
- int status = 3;
+ int status = 0;
gchar *bogo_exec = (config.bogopath && *config.bogopath) ? config.bogopath:"bogofilter";
+ int total = 0, curnum = 0;
+ GSList *spams = NULL;
+ gchar buf[BUFSIZ];
+
+ gchar *bogo_args[4];
+ GPid bogo_pid;
+ gint bogo_stdin, bogo_stdout;
+ GError *error = NULL;
+ gboolean bogo_forked;
if (!config.process_emails) {
return FALSE;
}
- debug_print("Filtering message %d\n", msginfo->msgnum);
+
+ if (msglist == NULL && msginfo != NULL) {
+ g_warning("wrong call to bogofilter mail_filtering_hook");
+ return FALSE;
+ }
+
+ total = g_slist_length(msglist);
if (message_callback != NULL)
- message_callback(_("Bogofilter: filtering message..."), 0, 0);
+ message_callback(_("Bogofilter: filtering messages..."), total, 0);
- file = procmsg_get_message_file(msginfo);
+ cmd = g_strdup_printf("%s -T -b", bogo_exec);
- if (file)
- cmd = g_strdup_printf("%s -I %s", bogo_exec, file);
-
- if (cmd)
- status = system(cmd);
-
- if (status == -1)
- status = 3;
- else
- status = WEXITSTATUS(status);
-
- g_free(cmd);
- g_free(file);
- debug_print("bogofilter status %d\n", status);
- is_spam = (status == 0);
-
- if (is_spam) {
- debug_print("message is spam\n");
- procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0);
- if (config.receive_spam) {
- FolderItem *save_folder;
-
- if ((!config.save_folder) ||
- (config.save_folder[0] == '\0') ||
- ((save_folder = folder_find_item_from_identifier(config.save_folder)) == NULL))
- save_folder = folder_get_default_trash();
-
- procmsg_msginfo_unset_flags(msginfo, ~0, 0);
- procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0);
- folder_item_move_msg(save_folder, msginfo);
- } else {
- folder_item_remove_msg(msginfo->folder, msginfo->msgnum);
- }
+ bogo_args[0] = bogo_exec;
+ bogo_args[1] = "-T";
+ bogo_args[2] = "-b";
+ bogo_args[3] = NULL;
- return TRUE;
+ bogo_forked = g_spawn_async_with_pipes(
+ NULL, bogo_args,NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &bogo_pid, &bogo_stdin,
+ &bogo_stdout, NULL, &error);
+
+ if (bogo_forked == FALSE) {
+ g_warning("%s\n", error ? error->message:"ERROR???");
+ g_error_free(error);
+ error = NULL;
+ status = -1;
} else {
- debug_print("message is ham\n");
- procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+ for (cur = msglist; cur; cur = cur->next) {
+ msginfo = (MsgInfo *)cur->data;
+ debug_print("Filtering message %d (%d/%d)\n", msginfo->msgnum, curnum, total);
+
+ if (message_callback != NULL)
+ message_callback(NULL, total, curnum++);
+
+ file = procmsg_get_message_file(msginfo);
+
+ if (file) {
+ gchar *tmp = g_strdup_printf("%s\n",file);
+ write_all(bogo_stdin, tmp, strlen(tmp));
+ g_free(tmp);
+ memset(buf, 0, sizeof(buf));
+ if (read(bogo_stdout, buf, sizeof(buf)-1) < 0) {
+ printf("ERROR 2\n");
+ } else {
+ gchar **parts = NULL;
+ if (strchr(buf, '/')) {
+ tmp = strrchr(buf, '/')+1;
+ } else {
+ tmp = buf;
+ }
+ parts = g_strsplit(tmp, " ", 0);
+ debug_print("read %s\n", buf);
+ if (parts && parts[0] && parts[1] && *parts[1] == 'S') {
+ debug_print("message %d is spam\n", msginfo->msgnum);
+ procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0);
+ if (config.receive_spam) {
+ procmsg_msginfo_unset_flags(msginfo, ~0, 0);
+ procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0);
+ spams = g_slist_prepend(spams, msginfo);
+ } else {
+ folder_item_remove_msg(msginfo->folder, msginfo->msgnum);
+ }
+ mail_filtering_data->filtered = g_slist_prepend(
+ mail_filtering_data->filtered, msginfo);
+ } else {
+ debug_print("message %d is ham\n", msginfo->msgnum);
+ procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+ mail_filtering_data->unfiltered = g_slist_prepend(
+ mail_filtering_data->unfiltered, msginfo);
+ }
+ g_strfreev(parts);
+ }
+ g_free(file);
+ } else {
+ mail_filtering_data->unfiltered = g_slist_prepend(
+ mail_filtering_data->unfiltered, msginfo);
+ }
+ }
}
- if (status == 3) { /* I/O or other errors */
- gchar *msg = _("The Bogofilter plugin couldn't filter "
+ if (status != -1) {
+ close(bogo_stdout);
+ close(bogo_stdin);
+ waitpid(bogo_pid, &status, 0);
+ if (!WIFEXITED(status))
+ status = -1;
+ else
+ status = WEXITSTATUS(status);
+ }
+
+ if (status < 0 || status > 2) { /* I/O or other errors */
+ gchar *msg = NULL;
+
+ if (status == 3)
+ msg = g_strdup_printf(_("The Bogofilter plugin couldn't filter "
"a message. The probable cause of the "
"error is that it didn't learn from any mail.\n"
"Use \"/Mark/Mark as spam\" and \"/Mark/Mark as "
"ham\" to train Bogofilter with a few hundred "
- "spam and ham messages.");
+ "spam and ham messages."));
+ else
+ msg = g_strdup_printf(_("The Bogofilter plugin couldn't filter "
+ "a message. the command `%s` couldn't be run."), cmd);
if (!prefs_common.no_recv_err_panel) {
if (!warned_error) {
alertpanel_error(msg);
log_error(tmp);
g_free(tmp);
}
+ g_free(msg);
}
+ if (status < 0 || status > 2) {
+ g_slist_free(mail_filtering_data->filtered);
+ g_slist_free(mail_filtering_data->unfiltered);
+ g_slist_free(spams);
+ mail_filtering_data->filtered = NULL;
+ mail_filtering_data->unfiltered = NULL;
+ } else if (config.receive_spam && spams) {
+ FolderItem *save_folder;
+
+ if ((!config.save_folder) ||
+ (config.save_folder[0] == '\0') ||
+ ((save_folder = folder_find_item_from_identifier(config.save_folder)) == NULL))
+ save_folder = folder_get_default_trash();
+
+ folder_item_move_msgs(save_folder, spams);
+ }
+
+ if (message_callback != NULL)
+ message_callback(NULL, 0, 0);
+ mail_filtering_data->filtered = g_slist_reverse(
+ mail_filtering_data->filtered);
+ mail_filtering_data->unfiltered = g_slist_reverse(
+ mail_filtering_data->unfiltered);
return FALSE;
}
message_callback(NULL, total, done);
}
} else if (some_correction || some_no_correction) {
- int count = 0;
- gchar *file_list = NULL;
cur = msglist;
- while (cur && status == 0) {
+ gchar *bogo_args[4];
+ GPid bogo_pid;
+ gint bogo_stdin;
+ GError *error = NULL;
+ gboolean bogo_forked;
+
+ bogo_args[0] = (gchar *)bogo_exec;
+ if (some_correction && !some_no_correction)
+ bogo_args[1] = "-Sn";
+ else if (some_no_correction && !some_correction)
+ bogo_args[1] = spam ? "-s":"-n";
+ bogo_args[2] = "-b";
+ bogo_args[3] = NULL;
+
+ bogo_forked = g_spawn_async_with_pipes(
+ NULL, bogo_args,NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &bogo_pid, &bogo_stdin,
+ NULL, NULL, &error);
+
+ while (bogo_forked && cur) {
gchar *tmp = NULL;
info = (MsgInfo *)cur->data;
file = procmsg_get_message_file(info);
if (file) {
- tmp = g_strdup_printf("%s%s'%s'",
- file_list?file_list:"",
- file_list?" ":"",
+ tmp = g_strdup_printf("%s\n",
file);
- g_free(file_list);
- file_list = tmp;
+ write_all(bogo_stdin, tmp, strlen(tmp));
+ g_free(tmp);
}
g_free(file);
- count ++;
done++;
- if (count > 10 || cur->next == NULL) {
- /* flush */
- if (some_correction && !some_no_correction)
- cmd = g_strdup_printf("%s -Sn -B %s", bogo_exec, file_list);
- else if (some_no_correction && !some_correction)
- cmd = g_strdup_printf("%s -%c -B %s", bogo_exec, spam?'s':'n', file_list);
- else
- g_warning("duuh bogofilter plugin shouldn't be there!\n");
- if ((status = execute_command_line(cmd, FALSE)) != 0)
- alertpanel_error(_("Learning failed; `%s` returned with status %d."),
- cmd, status);
- count = 0;
- g_free(cmd);
- g_free(file_list);
- file_list = NULL;
- }
if (message_callback != NULL)
message_callback(NULL, total, done);
cur = cur->next;
}
- g_free(file_list);
+ if (bogo_forked) {
+ close(bogo_stdin);
+ waitpid(bogo_pid, &status, 0);
+ if (!WIFEXITED(status))
+ status = -1;
+ else
+ status = WEXITSTATUS(status);
+ }
+ if (!bogo_forked || status != 0) {
+ alertpanel_error(_("Learning failed; `%s` returned with error:\n%s"),
+ cmd, error ? error->message:_("Unknown error"));
+ if (error)
+ g_error_free(error);
+ }
+
}
if (message_callback != NULL)
void bogofilter_register_hook(void)
{
- hook_id = hooks_register_hook(MAIL_FILTERING_HOOKLIST, mail_filtering_hook, NULL);
+ hook_id = hooks_register_hook(MAIL_LISTFILTERING_HOOKLIST, mail_filtering_hook, NULL);
if (hook_id == -1) {
g_warning("Failed to register mail filtering hook");
config.process_emails = FALSE;
void bogofilter_unregister_hook(void)
{
if (hook_id != -1) {
- hooks_unregister_hook(MAIL_FILTERING_HOOKLIST, hook_id);
+ hooks_unregister_hook(MAIL_LISTFILTERING_HOOKLIST, hook_id);
}
}
MailFilteringData mail_filtering_data;
mail_filtering_data.msginfo = msginfo;
+ mail_filtering_data.msglist = NULL;
+ mail_filtering_data.filtered = NULL;
+ mail_filtering_data.unfiltered = NULL;
if (hooks_invoke(MAIL_FILTERING_HOOKLIST, &mail_filtering_data)) {
return TRUE;
}
return FALSE;
}
+void procmsg_msglist_filter(GSList *list, PrefsAccount *ac,
+ GSList **filtered, GSList **unfiltered,
+ gboolean do_filter)
+{
+ GSList *cur, *to_do = NULL;
+ gint total = 0, curnum = 0;
+ MailFilteringData mail_filtering_data;
+
+ g_return_if_fail(filtered != NULL);
+ g_return_if_fail(unfiltered != NULL);
+
+ *filtered = NULL;
+ *unfiltered = NULL;
+
+ if (list == NULL)
+ return;
+
+ total = g_slist_length(list);
+
+ if (!do_filter) {
+ *filtered = NULL;
+ *unfiltered = g_slist_copy(list);
+ return;
+ }
+
+ statusbar_print_all(_("Filtering messages...\n"));
+
+ mail_filtering_data.msginfo = NULL;
+ mail_filtering_data.msglist = list;
+ mail_filtering_data.filtered = NULL;
+ mail_filtering_data.unfiltered = NULL;
+
+ hooks_invoke(MAIL_LISTFILTERING_HOOKLIST, &mail_filtering_data);
+
+ if (mail_filtering_data.filtered == NULL &&
+ mail_filtering_data.unfiltered == NULL) {
+ /* nothing happened */
+ debug_print(MAIL_LISTFILTERING_HOOKLIST " did nothing. filtering whole list normally.\n");
+ to_do = list;
+ }
+ if (mail_filtering_data.filtered != NULL) {
+ /* keep track of what's been filtered by the hooks */
+ debug_print(MAIL_LISTFILTERING_HOOKLIST " filtered some stuff. total %d filtered %d unfilt %d.\n",
+ g_slist_length(list),
+ g_slist_length(mail_filtering_data.filtered),
+ g_slist_length(mail_filtering_data.unfiltered));
+
+ *filtered = g_slist_copy(mail_filtering_data.filtered);
+ }
+ if (mail_filtering_data.unfiltered != NULL) {
+ /* what the hooks didn't handle will go in filtered or
+ * unfiltered in the next loop */
+ debug_print(MAIL_LISTFILTERING_HOOKLIST " left unfiltered stuff. total %d filtered %d unfilt %d.\n",
+ g_slist_length(list),
+ g_slist_length(mail_filtering_data.filtered),
+ g_slist_length(mail_filtering_data.unfiltered));
+ to_do = mail_filtering_data.unfiltered;
+ }
+
+ for (cur = to_do; cur; cur = cur->next) {
+ MsgInfo *info = (MsgInfo *)cur->data;
+ if (procmsg_msginfo_filter(info, ac))
+ *filtered = g_slist_prepend(*filtered, info);
+ else
+ *unfiltered = g_slist_prepend(*unfiltered, info);
+ statusbar_progress_all(curnum++, total, prefs_common.statusbar_update_step);
+ }
+
+ g_slist_free(mail_filtering_data.filtered);
+ g_slist_free(mail_filtering_data.unfiltered);
+
+ *filtered = g_slist_reverse(*filtered);
+ *unfiltered = g_slist_reverse(*unfiltered);
+
+ statusbar_progress_all(0,0,0);
+ statusbar_pop_all();
+}
+
MsgInfo *procmsg_msginfo_new_from_mimeinfo(MsgInfo *src_msginfo, MimeInfo *mimeinfo)
{
MsgInfo *tmp_msginfo = NULL;
#define MSGINFO_UPDATE_HOOKLIST "msginfo_update"
#define MAIL_FILTERING_HOOKLIST "mail_filtering_hooklist"
+#define MAIL_LISTFILTERING_HOOKLIST "mail_listfiltering_hooklist"
#define MAIL_POSTFILTERING_HOOKLIST "mail_postfiltering_hooklist"
typedef enum {
struct _MailFilteringData
{
MsgInfo *msginfo;
+ GSList *msglist;
+ GSList *filtered;
+ GSList *unfiltered;
};
GHashTable *procmsg_msg_hash_table_create (GSList *mlist);
gboolean newly_marked);
void procmsg_msginfo_set_to_folder (MsgInfo *msginfo,
FolderItem *to_folder);
-gboolean procmsg_msginfo_filter (MsgInfo *msginfo,
- PrefsAccount *ac_prefs);
+gboolean procmsg_msginfo_filter (MsgInfo *msginfo,
+ PrefsAccount *ac_prefs);
+void procmsg_msglist_filter (GSList *list,
+ PrefsAccount *ac,
+ GSList **filtered,
+ GSList **unfiltered,
+ gboolean do_filter);
+
MsgInfo *procmsg_msginfo_new_from_mimeinfo
(MsgInfo *src_msginfo,
MimeInfo *mimeinfo);