10 #include "procheader.h"
12 #include "filtering.h"
16 #define PREFSBUFSIZE 1024
18 GSList * prefs_filtering = NULL;
20 FilteringAction * filteringaction_new(int type, int account_id,
23 FilteringAction * action;
25 action = g_new0(FilteringAction, 1);
28 action->account_id = account_id;
30 action->destination = g_strdup(destination);
35 void filteringaction_free(FilteringAction * action)
37 if (action->destination)
38 g_free(action->destination);
42 FilteringAction * filteringaction_parse(gchar ** str)
44 FilteringAction * action;
46 gchar * destination = NULL;
52 key = matcher_parse_keyword(&tmp);
55 case MATCHING_ACTION_MOVE:
56 destination = matcher_parse_str(&tmp);
62 case MATCHING_ACTION_COPY:
63 destination = matcher_parse_str(&tmp);
69 case MATCHING_ACTION_DELETE:
71 case MATCHING_ACTION_MARK:
73 case MATCHING_ACTION_MARK_AS_READ:
75 case MATCHING_ACTION_UNMARK:
77 case MATCHING_ACTION_MARK_AS_UNREAD:
79 case MATCHING_ACTION_FORWARD:
80 account_id = matcher_parse_number(&tmp);
86 destination = matcher_parse_str(&tmp);
93 case MATCHING_ACTION_FORWARD_AS_ATTACHMENT:
94 account_id = matcher_parse_number(&tmp);
100 destination = matcher_parse_str(&tmp);
113 action = filteringaction_new(key, account_id, destination);
118 FilteringProp * filteringprop_parse(gchar ** str)
122 FilteringProp * filtering;
123 MatcherList * matchers;
124 FilteringAction * action;
128 matchers = matcherlist_parse(&tmp);
135 matcherlist_free(matchers);
140 action = filteringaction_parse(&tmp);
142 matcherlist_free(matchers);
147 filtering = filteringprop_new(matchers, action);
154 FilteringProp * filteringprop_new(MatcherList * matchers,
155 FilteringAction * action)
157 FilteringProp * filtering;
159 filtering = g_new0(FilteringProp, 1);
160 filtering->matchers = matchers;
161 filtering->action = action;
166 void filteringprop_free(FilteringProp * prop)
168 matcherlist_free(prop->matchers);
169 filteringaction_free(prop->action);
173 static gboolean filteringaction_update_mark(MsgInfo * info)
178 dest_path = folder_item_get_path(info->folder);
179 if (!is_dir_exist(dest_path))
180 make_dir_hier(dest_path);
182 if (dest_path == NULL) {
183 g_warning(_("Can't open mark file.\n"));
187 if ((fp = procmsg_open_mark_file(dest_path, TRUE))
189 g_warning(_("Can't open mark file.\n"));
193 procmsg_write_flags(info, fp);
199 fitleringaction_apply
200 runs the action on one MsgInfo
201 return value : return TRUE if the action could be applied
204 static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info,
205 GHashTable *folder_table)
207 FolderItem * dest_folder;
210 PrefsAccount * account;
212 switch(action->type) {
213 case MATCHING_ACTION_MOVE:
214 dest_folder = folder_find_item_from_path(action->destination);
218 if (folder_item_move_msg(dest_folder, info) == -1)
222 filteringaction_update_mark(info);
224 val = GPOINTER_TO_INT(g_hash_table_lookup
225 (folder_table, dest_folder));
227 folder_item_scan(dest_folder);
228 g_hash_table_insert(folder_table, dest_folder,
231 val = GPOINTER_TO_INT(g_hash_table_lookup
232 (folder_table, info->folder));
234 folder_item_scan(info->folder);
235 g_hash_table_insert(folder_table, info->folder,
241 case MATCHING_ACTION_COPY:
242 dest_folder = folder_find_item_from_path(action->destination);
246 if (folder_item_copy_msg(dest_folder, info) == -1)
249 val = GPOINTER_TO_INT(g_hash_table_lookup
250 (folder_table, dest_folder));
252 folder_item_scan(dest_folder);
253 g_hash_table_insert(folder_table, dest_folder,
259 case MATCHING_ACTION_DELETE:
260 if (folder_item_remove_msg(info->folder, info->msgnum) == -1)
264 filteringaction_update_mark(info);
268 case MATCHING_ACTION_MARK:
269 MSG_SET_FLAGS(info->flags, MSG_MARKED);
270 filteringaction_update_mark(info);
274 case MATCHING_ACTION_UNMARK:
275 MSG_UNSET_FLAGS(info->flags, MSG_MARKED);
276 filteringaction_update_mark(info);
280 case MATCHING_ACTION_MARK_AS_READ:
281 MSG_UNSET_FLAGS(info->flags, MSG_UNREAD | MSG_NEW);
282 filteringaction_update_mark(info);
286 case MATCHING_ACTION_MARK_AS_UNREAD:
287 MSG_SET_FLAGS(info->flags, MSG_UNREAD | MSG_NEW);
288 filteringaction_update_mark(info);
292 case MATCHING_ACTION_FORWARD:
294 account = account_find_from_id(action->account_id);
295 compose = compose_forward(account, info, FALSE);
296 if (compose->account->protocol == A_NNTP)
297 compose_entry_append(compose, action->destination,
300 compose_entry_append(compose, action->destination,
303 val = compose_send(compose);
305 gtk_widget_destroy(compose->window);
309 gtk_widget_destroy(compose->window);
312 case MATCHING_ACTION_FORWARD_AS_ATTACHMENT:
314 account = account_find_from_id(action->account_id);
315 compose = compose_forward(account, info, TRUE);
316 if (compose->account->protocol == A_NNTP)
317 compose_entry_append(compose, action->destination,
320 compose_entry_append(compose, action->destination,
323 val = compose_send(compose);
325 gtk_widget_destroy(compose->window);
329 gtk_widget_destroy(compose->window);
339 runs the action on one MsgInfo if it matches the criterium
340 return value : return TRUE if the action doesn't allow more actions
343 static gboolean filteringprop_apply(FilteringProp * filtering, MsgInfo * info,
344 GHashTable *folder_table)
346 if (matcherlist_match(filtering->matchers, info)) {
352 result = filteringaction_apply(filtering->action, info,
355 filteringaction_to_string(filtering->action);
357 g_warning(_("action %s could not be applied"),
361 debug_print(_("message %i %s..."),
362 info->msgnum, action_str);
367 switch(filtering->action->type) {
368 case MATCHING_ACTION_MOVE:
369 case MATCHING_ACTION_DELETE:
371 case MATCHING_ACTION_COPY:
372 case MATCHING_ACTION_MARK:
373 case MATCHING_ACTION_MARK_AS_READ:
374 case MATCHING_ACTION_UNMARK:
375 case MATCHING_ACTION_MARK_AS_UNREAD:
376 case MATCHING_ACTION_FORWARD:
377 case MATCHING_ACTION_FORWARD_AS_ATTACHMENT:
387 void filter_msginfo(GSList * filtering_list, MsgInfo * info,
388 GHashTable *folder_table)
393 g_warning(_("msginfo is not set"));
397 for(l = filtering_list ; l != NULL ; l = g_slist_next(l)) {
398 FilteringProp * filtering = (FilteringProp *) l->data;
400 if (filteringprop_apply(filtering, info, folder_table))
405 void filter_message(GSList * filtering_list, FolderItem * item,
406 gint msgnum, GHashTable *folder_table)
412 g_warning(_("folderitem not set"));
416 filename = folder_item_fetch_msg(item, msgnum);
418 if (filename == NULL) {
419 g_warning(_("filename is not set"));
423 msginfo = procheader_parse(filename, 0, TRUE);
427 if (msginfo == NULL) {
428 g_warning(_("could not get info for %s"), filename);
432 msginfo->folder = item;
433 msginfo->msgnum = msgnum;
435 filter_msginfo(filtering_list, msginfo, folder_table);
438 void prefs_filtering_read_config(void)
442 gchar buf[PREFSBUFSIZE];
444 debug_print(_("Reading filtering configuration...\n"));
446 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
448 if ((fp = fopen(rcpath, "r")) == NULL) {
449 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
451 prefs_filtering = NULL;
456 /* remove all filtering */
457 while (prefs_filtering != NULL) {
458 FilteringProp * filtering =
459 (FilteringProp *) prefs_filtering->data;
460 filteringprop_free(filtering);
461 prefs_filtering = g_slist_remove(prefs_filtering, filtering);
464 while (fgets(buf, sizeof(buf), fp) != NULL) {
465 FilteringProp * filtering;
470 if ((*buf != '#') && (*buf != '\0')) {
472 filtering = filteringprop_parse(&tmp);
475 g_slist_append(prefs_filtering,
480 g_warning(_("syntax error : %s\n"), buf);
488 gchar * filteringaction_to_string(FilteringAction * action)
492 gchar * account_id_str;
495 command_str = get_matchparser_tab_str(action->type);
497 if (command_str == NULL)
500 switch(action->type) {
501 case MATCHING_ACTION_MOVE:
502 case MATCHING_ACTION_COPY:
503 return g_strconcat(command_str, " \"", action->destination,
506 case MATCHING_ACTION_DELETE:
507 case MATCHING_ACTION_MARK:
508 case MATCHING_ACTION_UNMARK:
509 case MATCHING_ACTION_MARK_AS_READ:
510 case MATCHING_ACTION_MARK_AS_UNREAD:
511 return g_strdup(command_str);
514 case MATCHING_ACTION_FORWARD:
515 case MATCHING_ACTION_FORWARD_AS_ATTACHMENT:
516 account_id_str = itos(action->account_id);
517 return g_strconcat(command_str, " ", account_id_str,
518 " \"", action->destination, "\"", NULL);
525 gchar * filteringprop_to_string(FilteringProp * prop)
529 gchar * filtering_str;
531 action_str = filteringaction_to_string(prop->action);
533 if (action_str == NULL)
536 list_str = matcherlist_to_string(prop->matchers);
538 if (list_str == NULL) {
543 filtering_str = g_strconcat(list_str, " ", action_str, NULL);
547 return filtering_str;
550 void prefs_filtering_write_config(void)
555 FilteringProp * prop;
557 debug_print(_("Writing filtering configuration...\n"));
559 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, FILTERING_RC, NULL);
561 if ((pfile = prefs_write_open(rcpath)) == NULL) {
562 g_warning(_("failed to write configuration to file\n"));
567 for (cur = prefs_filtering; cur != NULL; cur = cur->next) {
568 gchar *filtering_str;
570 prop = (FilteringProp *) cur->data;
571 filtering_str = filteringprop_to_string(prop);
572 if (fputs(filtering_str, pfile->fp) == EOF ||
573 fputc('\n', pfile->fp) == EOF) {
574 FILE_OP_ERROR(rcpath, "fputs || fputc");
575 prefs_write_close_revert(pfile);
577 g_free(filtering_str);
580 g_free(filtering_str);
585 if (prefs_write_close(pfile) < 0) {
586 g_warning(_("failed to write configuration to file\n"));