1 /**
2  * @file
3  * Match patterns to emails
4  *
5  * @authors
6  * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
7  * Copyright (C) 2019 Pietro Cerutti <gahr@gahr.ch>
8  *
9  * @copyright
10  * This program is free software: you can redistribute it and/or modify it under
11  * the terms of the GNU General Public License as published by the Free Software
12  * Foundation, either version 2 of the License, or (at your option) any later
13  * version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 /**
25  * @page lib_pattern Pattern
26  *
27  * Match patterns to emails
28  *
29  * | File                 | Description                 |
30  * | :------------------- | :-------------------------- |
31  * | pattern/compile.c    | @subpage pattern_compile    |
32  * | pattern/config.c     | @subpage pattern_config     |
33  * | pattern/dlgpattern.c | @subpage pattern_dlgpattern |
34  * | pattern/exec.c       | @subpage pattern_exec       |
35  * | pattern/flags.c      | @subpage pattern_flags      |
36  * | pattern/pattern.c    | @subpage pattern_pattern    |
37  */
38 
39 #ifndef MUTT_PATTERN_LIB_H
40 #define MUTT_PATTERN_LIB_H
41 
42 #include "config.h"
43 #include <stddef.h>
44 #include <stdbool.h>
45 #include <stdint.h>
46 #include "mutt/lib.h"
47 #include "mutt.h"
48 
49 struct AliasMenuData;
50 struct AliasView;
51 struct Context;
52 struct Email;
53 struct Envelope;
54 struct Mailbox;
55 struct Menu;
56 
57 #define MUTT_ALIAS_SIMPLESEARCH "~f %s | ~t %s | ~c %s"
58 
59 typedef uint8_t PatternCompFlags;           ///< Flags for mutt_pattern_comp(), e.g. #MUTT_PC_FULL_MSG
60 #define MUTT_PC_NO_FLAGS                0   ///< No flags are set
61 #define MUTT_PC_FULL_MSG          (1 << 0)  ///< Enable body and header matching
62 #define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)  ///< Enable runtime date range evaluation
63 #define MUTT_PC_SEND_MODE_SEARCH  (1 << 2)  ///< Allow send-mode body searching
64 
65 /**
66  * struct Pattern - A simple (non-regex) pattern
67  */
68 struct Pattern
69 {
70   short op;                      ///< Operation, e.g. MUTT_PAT_SCORE
71   bool pat_not      : 1;         ///< Pattern should be inverted (not)
72   bool all_addr     : 1;         ///< All Addresses in the list must match
73   bool string_match : 1;         ///< Check a string for a match
74   bool group_match  : 1;         ///< Check a group of Addresses
75   bool ign_case     : 1;         ///< Ignore case for local string_match searches
76   bool is_alias     : 1;         ///< Is there an alias for this Address?
77   bool dynamic      : 1;         ///< Evaluate date ranges at run time
78   bool sendmode     : 1;         ///< Evaluate searches in send-mode
79   bool is_multi     : 1;         ///< Multiple case (only for ~I pattern now)
80   int min;                       ///< Minimum for range checks
81   int max;                       ///< Maximum for range checks
82   struct PatternList *child;     ///< Arguments to logical operation
83   union {
84     regex_t *regex;              ///< Compiled regex, for non-pattern matching
85     struct Group *group;         ///< Address group if group_match is set
86     char *str;                   ///< String, if string_match is set
87     struct ListHead multi_cases; ///< Multiple strings for ~I pattern
88   } p;
89   SLIST_ENTRY(Pattern) entries;  ///< Linked list
90 };
91 SLIST_HEAD(PatternList, Pattern);
92 
93 typedef uint8_t PatternExecFlags;         ///< Flags for mutt_pattern_exec(), e.g. #MUTT_MATCH_FULL_ADDRESS
94 #define MUTT_PAT_EXEC_NO_FLAGS         0  ///< No flags are set
95 #define MUTT_MATCH_FULL_ADDRESS  (1 << 0) ///< Match the full address
96 
97 /**
98  * struct PatternCache - Cache commonly-used patterns
99  *
100  * This is used when a message is repeatedly pattern matched against.
101  * e.g. for color, scoring, hooks.  It caches a few of the potentially slow
102  * operations.
103  * Each entry has a value of 0 = unset, 1 = false, 2 = true
104  */
105 struct PatternCache
106 {
107   int list_all;       ///< ^~l
108   int list_one;       ///<  ~l
109   int sub_all;        ///< ^~u
110   int sub_one;        ///<  ~u
111   int pers_recip_all; ///< ^~p
112   int pers_recip_one; ///<  ~p
113   int pers_from_all;  ///< ^~P
114   int pers_from_one;  ///<  ~P
115 };
116 
117 /**
118  * enum PatternType - Types of pattern to match
119  *
120  * @note This enum piggy-backs on top of #MessageType
121  *
122  * @sa mutt_pattern_comp(), mutt_pattern_exec()
123  */
124 enum PatternType
125 {
126   MUTT_PAT_AND = MUTT_MT_MAX, ///< Both patterns must match
127   MUTT_PAT_OR,                ///< Either pattern can match
128   MUTT_PAT_THREAD,            ///< Pattern matches email thread
129   MUTT_PAT_PARENT,            ///< Pattern matches parent
130   MUTT_PAT_CHILDREN,          ///< Pattern matches a child email
131   MUTT_PAT_TO,                ///< Pattern matches 'To:' field
132   MUTT_PAT_CC,                ///< Pattern matches 'Cc:' field
133   MUTT_PAT_COLLAPSED,         ///< Thread is collapsed
134   MUTT_PAT_SUBJECT,           ///< Pattern matches 'Subject:' field
135   MUTT_PAT_FROM,              ///< Pattern matches 'From:' field
136   MUTT_PAT_DATE,              ///< Pattern matches 'Date:' field
137   MUTT_PAT_DATE_RECEIVED,     ///< Pattern matches date received
138   MUTT_PAT_DUPLICATED,        ///< Duplicate message
139   MUTT_PAT_UNREFERENCED,      ///< Message is unreferenced in the thread
140   MUTT_PAT_BROKEN,            ///< Message is part of a broken thread
141   MUTT_PAT_ID,                ///< Pattern matches email's Message-Id
142   MUTT_PAT_ID_EXTERNAL,       ///< Message-Id is among results from an external query
143   MUTT_PAT_BODY,              ///< Pattern matches email's body
144   MUTT_PAT_HEADER,            ///< Pattern matches email's header
145   MUTT_PAT_HORMEL,            ///< Pattern matches email's spam score
146   MUTT_PAT_WHOLE_MSG,         ///< Pattern matches raw email text
147   MUTT_PAT_SENDER,            ///< Pattern matches sender
148   MUTT_PAT_MESSAGE,           ///< Pattern matches message number
149   MUTT_PAT_SCORE,             ///< Pattern matches email's score
150   MUTT_PAT_SIZE,              ///< Pattern matches email's size
151   MUTT_PAT_REFERENCE,         ///< Pattern matches 'References:' or 'In-Reply-To:' field
152   MUTT_PAT_RECIPIENT,         ///< User is a recipient of the email
153   MUTT_PAT_LIST,              ///< Email is on mailing list
154   MUTT_PAT_SUBSCRIBED_LIST,   ///< Email is on subscribed mailing list
155   MUTT_PAT_PERSONAL_RECIP,    ///< Email is addressed to the user
156   MUTT_PAT_PERSONAL_FROM,     ///< Email is from the user
157   MUTT_PAT_ADDRESS,           ///< Pattern matches any address field
158   MUTT_PAT_CRYPT_SIGN,        ///< Message is signed
159   MUTT_PAT_CRYPT_VERIFIED,    ///< Message is crypographically verified
160   MUTT_PAT_CRYPT_ENCRYPT,     ///< Message is encrypted
161   MUTT_PAT_PGP_KEY,           ///< Message has PGP key
162   MUTT_PAT_XLABEL,            ///< Pattern matches keyword/label
163   MUTT_PAT_SERVERSEARCH,      ///< Server-side pattern matches
164   MUTT_PAT_DRIVER_TAGS,       ///< Pattern matches message tags
165   MUTT_PAT_MIMEATTACH,        ///< Pattern matches number of attachments
166   MUTT_PAT_MIMETYPE,          ///< Pattern matches MIME type
167 #ifdef USE_NNTP
168   MUTT_PAT_NEWSGROUPS,        ///< Pattern matches newsgroup
169 #endif
170   MUTT_PAT_MAX,
171 };
172 
173 bool mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m,
174                        struct Email *e, struct PatternCache *cache);
175 bool mutt_pattern_alias_exec(struct Pattern *pat, PatternExecFlags flags,
176                              struct AliasView *av, struct PatternCache *cache);
177 
178 struct PatternList *mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err);
179 void mutt_check_simple(struct Buffer *s, const char *simple);
180 void mutt_pattern_free(struct PatternList **pat);
181 bool dlg_select_pattern(char *buf, size_t buflen);
182 
183 int mutt_which_case(const char *s);
184 int mutt_is_list_recipient(bool all_addr, struct Envelope *e);
185 int mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *e);
186 int mutt_pattern_func(struct Context *ctx, int op, char *prompt);
187 int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu);
188 int mutt_search_command(struct Mailbox *m, struct Menu *menu, int cur, int op);
189 int mutt_search_alias_command(struct Menu *menu, int cur, int op);
190 
191 bool mutt_limit_current_thread(struct Context *ctx, struct Email *e);
192 
193 #endif /* MUTT_PATTERN_LIB_H */
194