1 /* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ 2 /* Balsa E-Mail Client 3 * 4 * Copyright (C) 1997-2013 Stuart Parmenter and others, 5 * See the file AUTHORS for a list. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 /* 23 * filter.h 24 * 25 * Header for libfilter, the mail filtering porting of balsa 26 * 27 * Authors: Joel Becker - Emmanuel Allaud 28 */ 29 30 #ifndef __FILTER_H__ 31 #define __FILTER_H__ 32 33 #include <glib.h> 34 35 #include <time.h> 36 #include "libbalsa.h" 37 38 typedef struct _LibBalsaConditionRegex LibBalsaConditionRegex; 39 40 /* Conditions definition : 41 * a condition is the basic component of a filter 42 * It can be of type (mimic the old filter types) : 43 * - CONDITION_STRING : matches when a string is contained in 44 * one of the specified fields 45 * - CONDITION_REGEX : matches when one of the reg exs matches on one 46 * of the specified fields 47 * - CONDITION_EXEC : matches when the execution of the given command 48 * with parameters (FIXME : what are they???, see proposition for filter command) returns 1 49 * 50 * A condition has attributes : 51 * - fields : a gint specifying on which fields to apply the condition 52 * - negate : a gboolean to negate (logical not) the condition 53 */ 54 55 /* condition match types */ 56 57 typedef enum { 58 CONDITION_NONE, 59 CONDITION_STRING, /* */ 60 CONDITION_REGEX, 61 CONDITION_DATE, 62 CONDITION_FLAG, 63 CONDITION_AND, /* Condition has a list of subconditions and 64 * matches if all the subconditions match. */ 65 CONDITION_OR /* Condition has a list of subconditions and 66 * matches if any subcondition matches. */ 67 } ConditionMatchType; 68 69 struct _LibBalsaCondition { 70 gint ref_count; 71 gboolean negate; /* negate the result of the condition. */ 72 ConditionMatchType type; 73 74 /* The match type fields */ 75 union _match { 76 /* CONDITION_STRING */ 77 struct { 78 unsigned fields; /* Contains the header list for 79 * that this search should look in. */ 80 gchar * string; 81 gchar * user_header; /* This is !=NULL and gives the name 82 * of the user header against which 83 * we make the match if fields 84 * includes 85 * CONDITION_MATCH_US_HEAD. */ 86 } string; 87 /* CONDITION_REGEX */ 88 struct { 89 unsigned fields; /* Contains the header list for 90 * that this search should look in. */ 91 /* GSList * regexs; */ 92 } regex; 93 /* CONDITION_DATE */ 94 struct { 95 time_t date_low,date_high; /* for CONDITION_DATE */ 96 /* (date_high==0=>no high limit) */ 97 } date; 98 /* CONDITION_FLAG */ 99 LibBalsaMessageFlag flags; 100 101 /* CONDITION_AND and CONDITION_OR */ 102 struct { 103 LibBalsaCondition *left, *right; 104 } andor; 105 } match; 106 }; 107 108 LibBalsaCondition* libbalsa_condition_new_from_string(gchar **string); 109 gchar* libbalsa_condition_to_string(LibBalsaCondition *cond); 110 gchar* libbalsa_condition_to_string_user(LibBalsaCondition *cond); 111 112 LibBalsaCondition* libbalsa_condition_new_flag_enum(gboolean negated, 113 LibBalsaMessageFlag flgs); 114 115 LibBalsaCondition* libbalsa_condition_new_string(gboolean negated, 116 unsigned headers, 117 gchar *str, 118 gchar *user_header); 119 LibBalsaCondition* libbalsa_condition_new_date(gboolean negated, 120 time_t *from, time_t *to); 121 LibBalsaCondition* libbalsa_condition_new_bool_ptr(gboolean negated, 122 ConditionMatchType cmt, 123 LibBalsaCondition *left, 124 LibBalsaCondition *right); 125 LibBalsaCondition* libbalsa_condition_ref(LibBalsaCondition* cnd); 126 void libbalsa_condition_unref(LibBalsaCondition*); 127 128 129 typedef enum { 130 FILTER_NOOP, 131 FILTER_OP_OR, 132 FILTER_OP_AND /* Must be the last one */ 133 } FilterOpType; 134 135 /* Filter definition : 136 * a filter is defined by 137 * - a list of conditions and a gint conditions_op 138 * specifying the logical op to apply on the result of the condition match 139 * - an action to perform on match : move, copy, print or trash the 140 * matching message, emit a sound, popup a text, execute a command 141 */ 142 143 typedef enum { 144 FILTER_NOTHING, 145 FILTER_COPY, 146 FILTER_MOVE, 147 FILTER_PRINT, 148 FILTER_RUN, 149 FILTER_TRASH, 150 FILTER_COLOR, 151 FILTER_N_TYPES 152 } FilterActionType; 153 154 /* 155 * filter error codes 156 * (not an enum cause they *have* to match filter_errlist) 157 */ 158 159 #define FILTER_NOERR 0 160 #define FILTER_EFILESYN 1 161 #define FILTER_ENOMEM 2 162 #define FILTER_EREGSYN 3 163 #define FILTER_EINVALID 4 164 165 /* 166 * Filter errors set the variable filter_errno (like errno) 167 * See policy to use it in filter-error.c 168 */ 169 extern gint filter_errno; 170 171 typedef struct _LibBalsaFilter { 172 173 gchar *name; 174 gint flags; 175 176 LibBalsaCondition *condition; /* A codition, possibly a composite 177 * one. */ 178 179 /* The notification fields : NULL signifies no notification */ 180 gchar * sound; 181 gchar * popup_text; 182 183 /* The action */ 184 FilterActionType action; 185 /* action_string depends on action : 186 * - if action is FILTER_MOVE, or FILTER_COPY, action_string is 187 * the URL (this is mandatory because it determines UNIQUELY 188 * the mailbox, unlike the name) of the mailbox to move/copy 189 * the matching message 190 * - if action is FILTER_RUN, action_string is the command to run 191 * for now this is the way to specify parameters (replaced by 192 * pieces of the matching message) for the running command, 193 * proposition : %f,%t,%c,%s are replaced by the corresponding 194 * header (from,to,cc,subject) field of the matching message on 195 * the command line with enclosing quotes if necessary, e.g. : 196 * command_to_run %t %s -----> command_to_run manu@wanadoo.fr 197 * "about filters" If you want the body, we must find a way to 198 * pipe it to the std input of the command (FIXME what do we do 199 * for different parts, attachments and so on?) 200 * - if action is FILTER_TRASH it's NULL 201 * - FIXME if action is FILTER_PRINT it could be the print command ? 202 */ 203 gchar * action_string; 204 } LibBalsaFilter; 205 206 /* 207 * Exported filter functions A lot are, to have a fine-grained API so 208 * we can use filter engine for a lot of different purpose : search 209 * functions, virtual folders..., not only filtering 210 */ 211 212 void libbalsa_condition_regex_set(LibBalsaConditionRegex * reg, gchar *str); 213 /* returns pointer to internal data, treat with caution! */ 214 const gchar* libbalsa_condition_regex_get(LibBalsaConditionRegex * reg); 215 216 void libbalsa_condition_prepend_regex(LibBalsaCondition* cond, 217 LibBalsaConditionRegex *new_reg); 218 219 /** libbalsa_condition_matches() checks whether given message matches the 220 * condition. */ 221 gboolean libbalsa_condition_matches(LibBalsaCondition* cond, 222 LibBalsaMessage* message); 223 224 /* Filtering functions */ 225 /* FIXME : perhaps I should try to use multithreading -> but we must 226 therefore use lock very well */ 227 /* prepare_filters_to_run will test all filters for correctness, 228 compile regexs if needed 229 * Return 230 * - TRUE on success (all filters are valid, ready to be applied) 231 * - FALSE if there are invalid filters 232 */ 233 234 gint filters_prepare_to_run(GSList * filters); 235 236 /* Apply the filter action to the list of messages. 237 * It returns TRUE if the trash bin has been filled with something 238 * this is used to call enable_empty_trash after 239 */ 240 241 gboolean libbalsa_filter_mailbox_messages(LibBalsaFilter * filt, 242 LibBalsaMailbox * mailbox, 243 GArray * msgnos); 244 245 /* 246 * libbalsa_filter_get_by_name() 247 * search in the filter list the filter of name fname or NULL if unfound 248 */ 249 250 LibBalsaFilter* libbalsa_filter_get_by_name(const gchar* fname); 251 252 /* 253 * Dialog calls 254 */ 255 /* filters_edit_dialog launches (guess what :) the filters edit dialog box 256 * to modify the list of all filters 257 */ 258 void filters_edit_dialog(void); 259 260 /* filter_run_dialog edits and runs the list of filters of the mailbox 261 */ 262 void filters_run_dialog(LibBalsaMailbox *mbox); 263 264 /* filter_export_dialog to export filters as sieve scripts 265 */ 266 267 void 268 filters_export_dialog(void); 269 270 void libbalsa_filters_set_trash(LibBalsaMailbox* new_trash); 271 typedef LibBalsaMailbox* (*UrlToMailboxMapper)(const gchar* url); 272 void libbalsa_filters_set_url_mapper(UrlToMailboxMapper u2mm); 273 void libbalsa_filters_set_filter_list(GSList** list); 274 275 /* 276 * Error calls 277 */ 278 gchar *filter_strerror(gint filter_errnum); 279 void filter_perror(const gchar * s); 280 281 /* Test */ 282 gboolean libbalsa_condition_can_match(LibBalsaCondition * cond, 283 LibBalsaMessage * message); 284 gboolean libbalsa_condition_is_flag_only(LibBalsaCondition * cond, 285 LibBalsaMailbox * mailbox, 286 guint msgno, gboolean * match); 287 288 /* Compatibility */ 289 LibBalsaCondition *libbalsa_condition_new_2_0(const gchar * 290 filter_section_name, 291 ConditionMatchType cmt); 292 293 #endif /* __FILTER_H__ */ 294