2 * $Id: pattern.h 942 2008-03-04 18:21:33Z hubert@u.washington.edu $
4 * ========================================================================
5 * Copyright 2013-2022 Eduardo Chappa
6 * Copyright 2006-2008 University of Washington
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * ========================================================================
17 #ifndef PITH_PATTERN_INCLUDED
18 #define PITH_PATTERN_INCLUDED
21 #include "../pith/msgno.h"
22 #include "../pith/sorttype.h"
23 #include "../pith/string.h"
24 #include "../pith/indxtype.h"
28 * This structure is used to contain strings which are matched against
29 * header fields. The match is a simple substring match. The match is
30 * an OR of all the patterns in the PATTERN_S list. That is,
31 * substring1_matches OR substring2_matches OR substring3_matches.
32 * If not is set in the _head_ of the PATTERN_S, it is a NOT of the
33 * whole pattern, that is,
34 * NOT (substring1_matches OR substring2_matches OR substring3_matches).
35 * The not variable is not meaningful except in the head member of the
38 typedef struct pattern_s
{
39 int not; /* NOT of whole pattern */
41 struct pattern_s
*next
;
45 * List of these is a list of arbitrary freetext headers and patterns.
46 * This may be part of a pattern group.
47 * The isemptyval bit is to keep track of the difference between an arb
48 * header with no value set and one with the empty value "" set. For the
49 * other builtin headers this difference is kept track of by whether or
50 * not the header is in the config file at all or not. Here we want to
51 * be able to add a header to the config file without necessarily giving
54 typedef struct arbhdr_s
{
58 struct arbhdr_s
*next
;
62 * A list of intervals of integers.
64 typedef struct intvl_s
{
70 * A Pattern group gives characteristics of an envelope to match against. Any of
71 * the characteristics (to, from, ...) which is non-null must match for the
72 * whole thing to be considered a match. That is, it is an AND of all the
75 typedef struct patgrp_s
{
77 char *comment
; /* for user, not used for anything */
90 STRLIST_S
*charsets_list
; /* used for efficiency, computed from charset */
91 ARBHDR_S
*arbhdr
; /* list of arbitrary hdrnames and patterns */
92 int fldr_type
; /* see FLDR_* below */
93 PATTERN_S
*folder
; /* folder if type FLDR_SPECIFIC */
94 int inabook
; /* see IAB_* below */
99 INTVL_S
*age
; /* ages are in days */
102 int age_uses_sentdate
; /* on or off */
106 long cat_lim
; /* -1 no limit 0 only headers */
107 int bogus
; /* patgrp contains unknown stuff */
108 int stat_new
, /* msg status is New (Unseen) */
109 stat_rec
, /* msg status is Recent */
110 stat_del
, /* msg status is Deleted */
111 stat_imp
, /* msg is flagged Important */
112 stat_ans
, /* msg is flagged Answered */
113 stat_8bitsubj
, /* subject contains 8bit chars */
114 stat_bom
, /* this is first pine run of the month */
115 stat_boy
; /* this is first pine run of the year */
121 #define FLDR_SPECIFIC 3
123 #define FLDR_DEFL FLDR_EMAIL
126 #define IAB_EITHER 0x0 /* don't care if in or not */
128 #define IAB_TYPE_MASK 0xf
129 #define IAB_YES 0x1 /* addresses in any abook */
130 #define IAB_NO 0x2 /* " not " */
131 #define IAB_SPEC_YES 0x3 /* addresses in specific abooks */
132 #define IAB_SPEC_NO 0x4
135 * Warning about reply-to. We're using the c-client envelope reply-to which
136 * means if there isn't a real reply-to it uses the From!
138 #define IAB_ADDR_MASK 0xff0
139 #define IAB_FROM 0x10 /* from address included in list */
140 #define IAB_REPLYTO 0x20 /* reply-to address included in list */
141 #define IAB_SENDER 0x40 /* sender address included in list */
142 #define IAB_TO 0x80 /* to address included in list */
143 #define IAB_CC 0x100 /* cc address included in list */
145 #define IAB_DEFL IAB_EITHER
148 #define FILTER_STATE 0
149 #define FILTER_KILL 1
150 #define FILTER_FOLDER 2
153 * For the Status parts of a PATGRP_S. For example, stat_del is Deleted
154 * status. User sets EITHER means they don't care, it always matches.
155 * YES means it must be deleted to match. NO means it must not be deleted.
157 #define PAT_STAT_EITHER 0 /* we don't care which, yes or no */
158 #define PAT_STAT_YES 1 /* yes, this status is true */
159 #define PAT_STAT_NO 2 /* no, this status is not true */
162 * For the State setting part of a filter action
164 #define ACT_STAT_LEAVE 0 /* leave msg state alone */
165 #define ACT_STAT_SET 1 /* set this part of msg state */
166 #define ACT_STAT_CLEAR 2 /* clear this part of msg state */
168 typedef struct action_s
{
169 unsigned is_a_role
:1; /* this is a role action */
170 unsigned is_a_incol
:1; /* this is an index color action */
171 unsigned is_a_score
:1; /* this is a score setting action */
172 unsigned is_a_filter
:1; /* this is a filter action */
173 unsigned is_a_other
:1; /* this is a miscellaneous action */
174 unsigned is_a_srch
:1; /* this is for Select cmd, no action */
175 unsigned bogus
:1; /* action contains unknown stuff */
176 unsigned been_here_before
:1; /* inheritance loop prevention */
177 /* --- These are for roles --- */
178 ADDRESS
*from
; /* value to set for From */
179 ADDRESS
*replyto
; /* value to set for Reply-To */
180 char **cstm
; /* custom headers */
181 char **smtp
; /* custom SMTP server for this role */
182 char **nntp
; /* custom NNTP server for this role */
183 char *fcc
; /* value to set for Fcc */
184 char *litsig
; /* value to set Literal Signature */
185 char *sig
; /* value to set for Sig File */
186 char *template; /* value to set for Template */
187 char *nick
; /* value to set for Nickname */
188 int repl_type
; /* see ROLE_REPL_* below */
189 int forw_type
; /* see ROLE_FORW_* below */
190 int comp_type
; /* see ROLE_COMP_* below */
191 char *inherit_nick
; /* pattern we inherit actions from */
192 /* --- This is for indexcoloring --- */
193 COLOR_PAIR
*incol
; /* colors for index line */
194 /* --- This is for scoring --- */
196 HEADER_TOK_S
*scorevalhdrtok
;
197 /* --- These are for filtering --- */
199 long state_setting_bits
;
200 PATTERN_S
*keyword_set
; /* set these keywords */
201 PATTERN_S
*keyword_clr
; /* clear these keywords */
202 PATTERN_S
*folder
; /* folders to recv. filtered mail */
203 int move_only_if_not_deleted
; /* on or off */
204 int non_terminating
; /* on or off */
205 /* --- These are for other --- */
206 /* sort order of folder */
207 unsigned sort_is_set
:1;
208 SortOrder sortorder
; /* sorting order */
209 int revsort
; /* whether or not to reverse sort */
210 /* Index format of folder */
212 unsigned startup_rule
;
215 /* flags for first_pattern..., set_role_from_msg, and confirm_role() */
216 #define PAT_CLOSED 0x00000000 /* closed */
217 #define PAT_OPENED 0x00000001 /* opened successfully */
218 #define PAT_OPEN_FAILED 0x00000002
219 #define PAT_USE_CURRENT 0x00000010 /* use current_val to set up pattern */
220 #define PAT_USE_CHANGED 0x00000020 /* use changed_val to set up pattern */
221 #define PAT_USE_MAIN 0x00000040 /* use main_user_val */
222 #define PAT_USE_POST 0x00000080 /* use post_user_val */
223 #define ROLE_COMPOSE 0x00000100 /* roles with compose value != NO */
224 #define ROLE_REPLY 0x00000200 /* roles with reply value != NO */
225 #define ROLE_FORWARD 0x00000400 /* roles with forward value != NO */
226 #define ROLE_INCOL 0x00000800 /* patterns with non-Normal colors */
227 #define ROLE_SCORE 0x00001000 /* patterns with non-zero scorevals */
228 #define ROLE_DO_ROLES 0x00010000 /* role patterns */
229 #define ROLE_DO_INCOLS 0x00020000 /* index line color patterns */
230 #define ROLE_DO_SCORES 0x00040000 /* set score patterns */
231 #define ROLE_DO_FILTER 0x00080000 /* filter patterns */
232 #define ROLE_DO_OTHER 0x00100000 /* miscellaneous patterns */
233 #define ROLE_DO_SRCH 0x00200000 /* index line color patterns */
234 #define ROLE_OLD_PAT 0x00400000 /* old patterns variable */
235 #define ROLE_OLD_FILT 0x00800000 /* old patterns-filters variable */
236 #define ROLE_OLD_SCORE 0x01000000 /* old patterns-scores variable */
237 #define ROLE_CHANGES 0x02000000 /* start editing with changes
238 already registered */
240 #define PAT_OPEN_MASK 0x0000000f
241 #define PAT_USE_MASK 0x000000f0
242 #define ROLE_MASK 0x00ffff00
244 #define ROLE_REPL_NO 0 /* never use for reply */
245 #define ROLE_REPL_YES 1 /* use for reply with confirmation */
246 #define ROLE_REPL_NOCONF 2 /* use for reply without confirmation */
247 #define ROLE_FORW_NO 0 /* ... forward ... */
248 #define ROLE_FORW_YES 1
249 #define ROLE_FORW_NOCONF 2
250 #define ROLE_COMP_NO 0 /* ... compose ... */
251 #define ROLE_COMP_YES 1
252 #define ROLE_COMP_NOCONF 2
254 #define ROLE_REPL_DEFL ROLE_REPL_YES /* default reply value */
255 #define ROLE_FORW_DEFL ROLE_FORW_YES /* default forward value */
256 #define ROLE_COMP_DEFL ROLE_COMP_NO /* default compose value */
257 #define ROLE_NOTAROLE_DEFL ROLE_COMP_NO
259 #define INTVL_INF (2147483646L)
260 #define INTVL_UNDEF (INTVL_INF + 1L)
261 #define SCORE_UNDEF INTVL_UNDEF
262 #define SCORE_MIN (-100)
263 #define SCORE_MAX (100)
264 #define SCOREUSE_GET 0x000
265 #define SCOREUSE_INVALID 0x001 /* will recalculate scores_in_use next time */
266 #define SCOREUSE_ROLES 0x010 /* scores are used for roles */
267 #define SCOREUSE_INCOLS 0x020 /* scores are used for index line colors */
268 #define SCOREUSE_FILTERS 0x040 /* scores are used for filters */
269 #define SCOREUSE_OTHER 0x080 /* scores are used for miscellaneous stuff */
270 #define SCOREUSE_INDEX 0x100 /* scores are used in index-format */
271 #define SCOREUSE_STATEDEP 0x200 /* scores depend on message state */
274 * A message is compared with a pattern group to see if it matches.
275 * If it does match, then there are actions which are taken.
277 typedef struct pat_s
{
280 struct pat_line_s
*patline
; /* pat_line that goes with this pat */
287 typedef enum {TypeNotSet
= 0, Literal
, File
, Inherit
} PAT_TYPE
;
290 * There's one of these for each line in the pinerc variable.
291 * Normal type=Literal patterns have a patline with both first and last
292 * pointing to the pattern. Type File has one patline for the file and first
293 * and last point to the first and last patterns in the file.
294 * The patterns aren't linked into one giant list, the patlines are.
295 * To traverse all the patterns you have to go through the patline list
296 * and then for each patline go from first to last through the patterns.
297 * That's what next_pattern and friends do.
299 typedef struct pat_line_s
{
301 PAT_S
*first
; /* 1st pattern in list belonging to this line */
303 char *filename
; /* If type File, the filename */
306 unsigned dirty
:1; /* needs to be written back to storage */
307 struct pat_line_s
*next
;
308 struct pat_line_s
*prev
;
311 typedef struct pat_handle
{
312 PAT_LINE_S
*patlinehead
; /* list of in-core, parsed pat lines */
313 unsigned dirtypinerc
:1; /* needs to be written */
316 typedef struct pat_state
{
319 PAT_LINE_S
*patlinecurrent
;
320 PAT_S
*patcurrent
; /* current pat within patline */
323 #define PATTERN_MAGIC "P#Pats"
324 #define PATTERN_FILE_VERS "01"
328 * This is a little dangerous. We're passing flags to match_pattern and
329 * peeling some of them off for our own use while passing the rest on
330 * to mail_search_full. So we need to define ours so they don't overlap
331 * with the c-client flags that can be passed to mail_search_full.
332 * We could formalize it with mrc.
334 #define MP_IN_CCLIENT_CB 0x10000 /* we're in a c-client callback! */
335 #define MP_NOT 0x20000 /* use ! of patgrp for search */
338 /* match_pattern_folder_specific flags */
339 #define FOR_PATTERN 0x01
340 #define FOR_FILTER 0x02
341 #define FOR_OPTIONSCREEN 0x04
344 extern PAT_HANDLE
**cur_pat_h
;
347 /* exported prototypes */
348 void role_process_filters(void);
349 int add_to_pattern(PAT_S
*, long);
350 char *add_pat_escapes(char *);
351 char *remove_pat_escapes(char *);
352 char *add_roletake_escapes(char *);
353 char *add_comma_escapes(char *);
354 void set_pathandle(long);
355 void close_every_pattern(void);
356 void close_patterns(long);
357 int nonempty_patterns(long, PAT_STATE
*);
358 int any_patterns(long, PAT_STATE
*);
359 int edit_pattern(PAT_S
*, int, long);
360 int add_pattern(PAT_S
*, long);
361 int delete_pattern(int, long);
362 int shuffle_pattern(int, int, long);
363 PAT_LINE_S
*parse_pat_file(char *);
364 INTVL_S
*parse_intvl(char *);
365 char *stringform_of_intvl(INTVL_S
*);
366 char *hdrtok_to_stringform(HEADER_TOK_S
*);
367 HEADER_TOK_S
*stringform_to_hdrtok(char *);
368 char *hdrtok_to_config(HEADER_TOK_S
*);
369 HEADER_TOK_S
*config_to_hdrtok(char *);
370 int scores_are_used(int);
371 int patgrp_depends_on_state(PATGRP_S
*);
372 int patgrp_depends_on_active_state(PATGRP_S
*);
373 PATTERN_S
*parse_pattern(char *, char *, int);
374 PATTERN_S
*string_to_pattern(char *);
375 char *pattern_to_string(PATTERN_S
*);
376 char *pattern_to_config(PATTERN_S
*);
377 PATTERN_S
*config_to_pattern(char *);
378 PATTERN_S
*editlist_to_pattern(char **);
379 char **pattern_to_editlist(PATTERN_S
*);
380 PATGRP_S
*nick_to_patgrp(char *, int);
381 PAT_S
*first_pattern(PAT_STATE
*);
382 PAT_S
*last_pattern(PAT_STATE
*);
383 PAT_S
*prev_pattern(PAT_STATE
*);
384 PAT_S
*next_pattern(PAT_STATE
*);
385 int write_patterns(long);
386 void convert_statebits_to_vals(long, int *, int *, int *, int *);
387 int match_pattern(PATGRP_S
*, MAILSTREAM
*, SEARCHSET
*,char *,
388 long (*)(MAILSTREAM
*, long), long);
389 void find_8bitsubj_in_messages(MAILSTREAM
*, SEARCHSET
*, int, int);
390 void find_charsets_in_messages(MAILSTREAM
*, SEARCHSET
*, PATGRP_S
*, int);
391 int compare_strlists_for_match(STRLIST_S
*, STRLIST_S
*);
392 int match_pattern_folder(PATGRP_S
*, MAILSTREAM
*);
393 int match_pattern_folder_specific(PATTERN_S
*, MAILSTREAM
*, int);
394 SEARCHPGM
*match_pattern_srchpgm(PATGRP_S
*, MAILSTREAM
*, SEARCHSET
*);
395 void calc_extra_hdrs(void);
396 char *get_extra_hdrs(void);
397 void free_extra_hdrs(void);
398 void free_pat(PAT_S
**);
399 void free_pattern(PATTERN_S
**);
400 void free_action(ACTION_S
**);
401 PAT_S
*copy_pat(PAT_S
*);
402 PATGRP_S
*copy_patgrp(PATGRP_S
*);
403 ACTION_S
*copy_action(ACTION_S
*);
404 ACTION_S
*combine_inherited_role(ACTION_S
*);
405 void mail_expunge_prefilter(MAILSTREAM
*, int);
406 void process_filter_patterns(MAILSTREAM
*, MSGNO_S
*, long);
407 void reprocess_filter_patterns(MAILSTREAM
*, MSGNO_S
*, int);
408 int trivial_patgrp(PATGRP_S
*);
409 void free_patgrp(PATGRP_S
**);
410 void free_patline(PAT_LINE_S
**patline
);
411 int some_filter_depends_on_active_state(void);
412 void delete_filtered_msgs(MAILSTREAM
*);
413 void free_intvl(INTVL_S
**);
414 void free_arbhdr(ARBHDR_S
**);
417 #endif /* PITH_PATTERN_INCLUDED */