NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
exec.c
Go to the documentation of this file.
1
30#include "config.h"
31#include <assert.h>
32#include <stdarg.h>
33#include <stdbool.h>
34#include <stdio.h>
35#include <string.h>
36#include <unistd.h>
37#include "private.h"
38#include "mutt/lib.h"
39#include "address/lib.h"
40#include "config/lib.h"
41#include "email/lib.h"
42#include "core/lib.h"
43#include "alias/alias.h" // IWYU pragma: keep
44#include "alias/gui.h" // IWYU pragma: keep
45#include "alias/lib.h"
46#include "mutt.h"
47#include "lib.h"
48#include "attach/lib.h"
49#include "ncrypt/lib.h"
50#include "send/lib.h"
51#include "copy.h"
52#include "handler.h"
53#include "maillist.h"
54#include "muttlib.h"
55#include "mx.h"
56#ifndef USE_FMEMOPEN
57#include <sys/stat.h>
58#endif
59
60static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags,
61 struct Mailbox *m, struct Email *e,
62 struct Message *msg, struct PatternCache *cache);
63
71static bool patmatch(const struct Pattern *pat, const char *buf)
72{
73 if (pat->is_multi)
74 return (mutt_list_find(&pat->p.multi_cases, buf) != NULL);
75 if (pat->string_match)
76 return pat->ign_case ? mutt_istr_find(buf, pat->p.str) : strstr(buf, pat->p.str);
77 if (pat->group_match)
78 return mutt_group_match(pat->p.group, buf);
79 return (regexec(pat->p.regex, buf, 0, NULL, 0) == 0);
80}
81
87{
88 const struct PatternFlags *entry = lookup_op(op);
89 if (entry)
90 {
91 /* L10N: One of the crypt pattern operators: ~g, ~G, ~k, ~V
92 was invoked when NeoMutt was compiled without crypto support.
93 %c is the pattern character, i.e. "g". */
94 mutt_error(_("Pattern operator '~%c' is disabled"), entry->tag);
95 }
96 else
97 {
98 /* L10N: An unknown pattern operator was somehow invoked.
99 This shouldn't be possible unless there is a bug. */
100 mutt_error(_("error: unknown op %d (report this error)"), op);
101 }
102}
103
112static bool msg_search(struct Pattern *pat, struct Email *e, struct Message *msg)
113{
114 assert(msg);
115
116 bool match = false;
117
118 FILE *fp = NULL;
119 long len = 0;
120#ifdef USE_FMEMOPEN
121 char *temp = NULL;
122 size_t tempsize = 0;
123#else
124 struct stat st = { 0 };
125#endif
126
127 const bool needs_head = (pat->op == MUTT_PAT_HEADER) || (pat->op == MUTT_PAT_WHOLE_MSG);
128 const bool needs_body = (pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_WHOLE_MSG);
129 const bool c_thorough_search = cs_subset_bool(NeoMutt->sub, "thorough_search");
130 if (c_thorough_search)
131 {
132 /* decode the header / body */
133 struct State s = { 0 };
134 s.fp_in = msg->fp;
136#ifdef USE_FMEMOPEN
137 s.fp_out = open_memstream(&temp, &tempsize);
138 if (!s.fp_out)
139 {
140 mutt_perror(_("Error opening 'memory stream'"));
141 return false;
142 }
143#else
145 if (!s.fp_out)
146 {
147 mutt_perror(_("Can't create temporary file"));
148 return false;
149 }
150#endif
151
152 if (needs_head)
153 {
154 mutt_copy_header(msg->fp, e, s.fp_out, CH_FROM | CH_DECODE, NULL, 0);
155 }
156
157 if (needs_body)
158 {
160
161 if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) &&
163 {
164 if (s.fp_out)
165 {
167#ifdef USE_FMEMOPEN
168 FREE(&temp);
169#endif
170 }
171 return false;
172 }
173
174 if (!mutt_file_seek(msg->fp, e->offset, SEEK_SET))
175 {
176 return false;
177 }
178 mutt_body_handler(e->body, &s);
179 }
180
181#ifdef USE_FMEMOPEN
183 len = tempsize;
184
185 if (tempsize != 0)
186 {
187 fp = fmemopen(temp, tempsize, "r");
188 if (!fp)
189 {
190 mutt_perror(_("Error re-opening 'memory stream'"));
191 FREE(&temp);
192 return false;
193 }
194 }
195 else
196 { /* fmemopen can't handle empty buffers */
197 fp = mutt_file_fopen("/dev/null", "r");
198 if (!fp)
199 {
200 mutt_perror(_("Error opening /dev/null"));
201 return false;
202 }
203 }
204#else
205 fp = s.fp_out;
206 fflush(fp);
207 if (!mutt_file_seek(fp, 0, SEEK_SET) || fstat(fileno(fp), &st))
208 {
209 mutt_perror(_("Error checking length of temporary file"));
210 mutt_file_fclose(&fp);
211 return false;
212 }
213 len = (long) st.st_size;
214#endif
215 }
216 else
217 {
218 /* raw header / body */
219 fp = msg->fp;
220 if (needs_head)
221 {
222 if (!mutt_file_seek(fp, e->offset, SEEK_SET))
223 {
224 return false;
225 }
226 len = e->body->offset - e->offset;
227 }
228 if (needs_body)
229 {
230 if (pat->op == MUTT_PAT_BODY)
231 {
232 if (!mutt_file_seek(fp, e->body->offset, SEEK_SET))
233 {
234 return false;
235 }
236 }
237 len += e->body->length;
238 }
239 }
240
241 size_t blen = 256;
242 char *buf = mutt_mem_malloc(blen);
243
244 /* search the file "fp" */
245 while (len > 0)
246 {
247 if (pat->op == MUTT_PAT_HEADER)
248 {
249 buf = mutt_rfc822_read_line(fp, buf, &blen);
250 if (*buf == '\0')
251 break;
252 }
253 else if (!fgets(buf, blen - 1, fp))
254 break; /* don't loop forever */
255 if (patmatch(pat, buf))
256 {
257 match = true;
258 break;
259 }
260 len -= mutt_str_len(buf);
261 }
262
263 FREE(&buf);
264
265 if (c_thorough_search)
266 mutt_file_fclose(&fp);
267
268#ifdef USE_FMEMOPEN
269 FREE(&temp);
270#endif
271
272 return match;
273}
274
285static bool perform_and(struct PatternList *pat, PatternExecFlags flags,
286 struct Mailbox *m, struct Email *e, struct Message *msg,
287 struct PatternCache *cache)
288{
289 struct Pattern *p = NULL;
290
291 SLIST_FOREACH(p, pat, entries)
292 {
293 if (!pattern_exec(p, flags, m, e, msg, cache))
294 {
295 return false;
296 }
297 }
298 return true;
299}
300
309static bool perform_alias_and(struct PatternList *pat, PatternExecFlags flags,
310 struct AliasView *av, struct PatternCache *cache)
311{
312 struct Pattern *p = NULL;
313
314 SLIST_FOREACH(p, pat, entries)
315 {
316 if (!mutt_pattern_alias_exec(p, flags, av, cache))
317 {
318 return false;
319 }
320 }
321 return true;
322}
323
334static int perform_or(struct PatternList *pat, PatternExecFlags flags,
335 struct Mailbox *m, struct Email *e, struct Message *msg,
336 struct PatternCache *cache)
337{
338 struct Pattern *p = NULL;
339
340 SLIST_FOREACH(p, pat, entries)
341 {
342 if (pattern_exec(p, flags, m, e, msg, cache))
343 {
344 return true;
345 }
346 }
347 return false;
348}
349
358static int perform_alias_or(struct PatternList *pat, PatternExecFlags flags,
359 struct AliasView *av, struct PatternCache *cache)
360{
361 struct Pattern *p = NULL;
362
363 SLIST_FOREACH(p, pat, entries)
364 {
365 if (mutt_pattern_alias_exec(p, flags, av, cache))
366 {
367 return true;
368 }
369 }
370 return false;
371}
372
383static int match_addrlist(struct Pattern *pat, bool match_personal, int n, ...)
384{
385 va_list ap;
386
387 va_start(ap, n);
388 for (; n; n--)
389 {
390 struct AddressList *al = va_arg(ap, struct AddressList *);
391 struct Address *a = NULL;
392 TAILQ_FOREACH(a, al, entries)
393 {
394 if (pat->all_addr ^ ((!pat->is_alias || alias_reverse_lookup(a)) &&
395 ((a->mailbox && patmatch(pat, a->mailbox)) ||
396 (match_personal && a->personal && patmatch(pat, a->personal)))))
397 {
398 va_end(ap);
399 return !pat->all_addr; /* Found match, or non-match if all_addr */
400 }
401 }
402 }
403 va_end(ap);
404 return pat->all_addr; /* No matches, or all matches if all_addr */
405}
406
413static bool match_reference(struct Pattern *pat, struct ListHead *refs)
414{
415 struct ListNode *np = NULL;
416 STAILQ_FOREACH(np, refs, entries)
417 {
418 if (patmatch(pat, np->data))
419 return true;
420 }
421 return false;
422}
423
435static bool mutt_is_predicate_recipient(bool all_addr, struct Envelope *env, addr_predicate_t p)
436{
437 struct AddressList *als[] = { &env->to, &env->cc };
438 for (size_t i = 0; i < mutt_array_size(als); ++i)
439 {
440 struct AddressList *al = als[i];
441 struct Address *a = NULL;
442 TAILQ_FOREACH(a, al, entries)
443 {
444 if (all_addr ^ p(a))
445 return !all_addr;
446 }
447 }
448 return all_addr;
449}
450
459bool mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *env)
460{
462}
463
472bool mutt_is_list_recipient(bool all_addr, struct Envelope *env)
473{
474 return mutt_is_predicate_recipient(all_addr, env, &mutt_is_mail_list);
475}
476
486static int match_user(int all_addr, struct AddressList *al1, struct AddressList *al2)
487{
488 struct Address *a = NULL;
489 if (al1)
490 {
491 TAILQ_FOREACH(a, al1, entries)
492 {
493 if (all_addr ^ mutt_addr_is_user(a))
494 return !all_addr;
495 }
496 }
497
498 if (al2)
499 {
500 TAILQ_FOREACH(a, al2, entries)
501 {
502 if (all_addr ^ mutt_addr_is_user(a))
503 return !all_addr;
504 }
505 }
506 return all_addr;
507}
508
522static int match_threadcomplete(struct PatternList *pat, PatternExecFlags flags,
523 struct Mailbox *m, struct MuttThread *t,
524 int left, int up, int right, int down)
525{
526 if (!t)
527 return 0;
528
529 int a;
530 struct Email *e = t->message;
531 if (e)
532 if (mutt_pattern_exec(SLIST_FIRST(pat), flags, m, e, NULL))
533 return 1;
534
535 if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
536 return a;
537 if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
538 {
539 return a;
540 }
541 if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
542 {
543 return a;
544 }
545 if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
546 return a;
547 return 0;
548}
549
560static int match_threadparent(struct PatternList *pat, PatternExecFlags flags,
561 struct Mailbox *m, struct MuttThread *t)
562{
563 if (!t || !t->parent || !t->parent->message)
564 return 0;
565
566 return mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->parent->message, NULL);
567}
568
579static int match_threadchildren(struct PatternList *pat, PatternExecFlags flags,
580 struct Mailbox *m, struct MuttThread *t)
581{
582 if (!t || !t->child)
583 return 0;
584
585 for (t = t->child; t; t = t->next)
586 if (t->message && mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->message, NULL))
587 return 1;
588
589 return 0;
590}
591
599static bool match_content_type(const struct Pattern *pat, struct Body *b)
600{
601 if (!b)
602 return false;
603
604 char buf[256] = { 0 };
605 snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
606
607 if (patmatch(pat, buf))
608 return true;
609 if (match_content_type(pat, b->parts))
610 return true;
611 if (match_content_type(pat, b->next))
612 return true;
613 return false;
614}
615
624static bool match_mime_content_type(const struct Pattern *pat, struct Email *e, FILE *fp)
625{
627 return match_content_type(pat, e->body);
628}
629
636static bool match_update_dynamic_date(struct Pattern *pat)
637{
638 struct Buffer *err = mutt_buffer_pool_get();
639
640 bool rc = eval_date_minmax(pat, pat->p.str, err);
642
643 return rc;
644}
645
653static void set_pattern_cache_value(int *cache_entry, int value)
654{
655 *cache_entry = (value != 0) ? 2 : 1;
656}
657
664static bool get_pattern_cache_value(int cache_entry)
665{
666 return cache_entry == 2;
667}
668
674static int is_pattern_cache_set(int cache_entry)
675{
676 return cache_entry != 0;
677}
678
687static int msg_search_sendmode(struct Email *e, struct Pattern *pat)
688{
689 bool match = false;
690 char *buf = NULL;
691 size_t blen = 0;
692 FILE *fp = NULL;
693
694 if ((pat->op == MUTT_PAT_HEADER) || (pat->op == MUTT_PAT_WHOLE_MSG))
695 {
696 struct Buffer *tempfile = mutt_buffer_pool_get();
697 mutt_buffer_mktemp(tempfile);
698 fp = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
699 if (!fp)
700 {
702 mutt_buffer_pool_release(&tempfile);
703 return 0;
704 }
705
707 false, false, NeoMutt->sub);
708 fflush(fp);
709 if (mutt_file_seek(fp, 0, SEEK_SET))
710 {
711 while ((buf = mutt_file_read_line(buf, &blen, fp, NULL, MUTT_RL_NO_FLAGS)) != NULL)
712 {
713 if (patmatch(pat, buf) == 0)
714 {
715 match = true;
716 break;
717 }
718 }
719 }
720
721 FREE(&buf);
722 mutt_file_fclose(&fp);
723 unlink(mutt_buffer_string(tempfile));
724 mutt_buffer_pool_release(&tempfile);
725
726 if (match)
727 return match;
728 }
729
730 if ((pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_WHOLE_MSG))
731 {
732 fp = mutt_file_fopen(e->body->filename, "r");
733 if (!fp)
734 {
736 return 0;
737 }
738
739 while ((buf = mutt_file_read_line(buf, &blen, fp, NULL, MUTT_RL_NO_FLAGS)) != NULL)
740 {
741 if (patmatch(pat, buf) == 0)
742 {
743 match = true;
744 break;
745 }
746 }
747
748 FREE(&buf);
749 mutt_file_fclose(&fp);
750 }
751
752 return match;
753}
754
762static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
763{
764 if ((pat->op == MUTT_PAT_MIMETYPE) || (pat->op == MUTT_PAT_MIMEATTACH))
765 {
766 return true;
767 }
768
769 if ((pat->op == MUTT_PAT_WHOLE_MSG) || (pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_HEADER))
770 {
771#ifdef USE_IMAP
772 return !((m->type == MUTT_IMAP) && pat->string_match);
773#else
774 return true;
775#endif
776 }
777
778 if ((pat->op == MUTT_PAT_AND) || (pat->op == MUTT_PAT_OR))
779 {
780 struct Pattern *p = NULL;
781 SLIST_FOREACH(p, pat->child, entries)
782 {
783 if (pattern_needs_msg(m, p))
784 {
785 return true;
786 }
787 }
788 }
789
790 return false;
791}
792
808static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags,
809 struct Mailbox *m, struct Email *e,
810 struct Message *msg, struct PatternCache *cache)
811{
812 switch (pat->op)
813 {
814 case MUTT_PAT_AND:
815 return pat->pat_not ^ (perform_and(pat->child, flags, m, e, msg, cache) > 0);
816 case MUTT_PAT_OR:
817 return pat->pat_not ^ (perform_or(pat->child, flags, m, e, msg, cache) > 0);
818 case MUTT_PAT_THREAD:
819 return pat->pat_not ^
820 match_threadcomplete(pat->child, flags, m, e->thread, 1, 1, 1, 1);
821 case MUTT_PAT_PARENT:
822 return pat->pat_not ^ match_threadparent(pat->child, flags, m, e->thread);
824 return pat->pat_not ^ match_threadchildren(pat->child, flags, m, e->thread);
825 case MUTT_ALL:
826 return !pat->pat_not;
827 case MUTT_EXPIRED:
828 return pat->pat_not ^ e->expired;
829 case MUTT_SUPERSEDED:
830 return pat->pat_not ^ e->superseded;
831 case MUTT_FLAG:
832 return pat->pat_not ^ e->flagged;
833 case MUTT_TAG:
834 return pat->pat_not ^ e->tagged;
835 case MUTT_NEW:
836 return pat->pat_not ? e->old || e->read : !(e->old || e->read);
837 case MUTT_UNREAD:
838 return pat->pat_not ? e->read : !e->read;
839 case MUTT_REPLIED:
840 return pat->pat_not ^ e->replied;
841 case MUTT_OLD:
842 return pat->pat_not ? (!e->old || e->read) : (e->old && !e->read);
843 case MUTT_READ:
844 return pat->pat_not ^ e->read;
845 case MUTT_DELETED:
846 return pat->pat_not ^ e->deleted;
847 case MUTT_PAT_MESSAGE:
848 return pat->pat_not ^ ((EMSG(e) >= pat->min) && (EMSG(e) <= pat->max));
849 case MUTT_PAT_DATE:
850 if (pat->dynamic)
852 return pat->pat_not ^ ((e->date_sent >= pat->min) && (e->date_sent <= pat->max));
854 if (pat->dynamic)
856 return pat->pat_not ^ ((e->received >= pat->min) && (e->received <= pat->max));
857 case MUTT_PAT_BODY:
858 case MUTT_PAT_HEADER:
860 if (pat->sendmode)
861 {
862 if (!e->body || !e->body->filename)
863 return false;
864 return pat->pat_not ^ msg_search_sendmode(e, pat);
865 }
866 /* m can be NULL in certain cases, such as when replying to a message
867 * from the attachment menu and the user has a reply-hook using "~e".
868 * This is also the case when message scoring. */
869 if (!m)
870 return false;
871#ifdef USE_IMAP
872 /* IMAP search sets e->matched at search compile time */
873 if ((m->type == MUTT_IMAP) && pat->string_match)
874 return e->matched;
875#endif
876 return pat->pat_not ^ msg_search(pat, e, msg);
878#ifdef USE_IMAP
879 if (!m)
880 return false;
881 if (m->type == MUTT_IMAP)
882 {
883 return (pat->string_match) ? e->matched : false;
884 }
885#endif
886 mutt_error(_("error: server custom search only supported with IMAP"));
887 return false;
888 case MUTT_PAT_SENDER:
889 if (!e->env)
890 return false;
891 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
892 1, &e->env->sender);
893 case MUTT_PAT_FROM:
894 if (!e->env)
895 return false;
896 return pat->pat_not ^
897 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->from);
898 case MUTT_PAT_TO:
899 if (!e->env)
900 return false;
901 return pat->pat_not ^
902 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->to);
903 case MUTT_PAT_CC:
904 if (!e->env)
905 return false;
906 return pat->pat_not ^
907 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->cc);
908 case MUTT_PAT_SUBJECT:
909 if (!e->env)
910 return false;
911 return pat->pat_not ^ (e->env->subject && patmatch(pat, e->env->subject));
912 case MUTT_PAT_ID:
914 if (!e->env)
915 return false;
916 return pat->pat_not ^ (e->env->message_id && patmatch(pat, e->env->message_id));
917 case MUTT_PAT_SCORE:
918 return pat->pat_not ^ (e->score >= pat->min &&
919 (pat->max == MUTT_MAXRANGE || e->score <= pat->max));
920 case MUTT_PAT_SIZE:
921 return pat->pat_not ^ (e->body->length >= pat->min &&
922 (pat->max == MUTT_MAXRANGE || e->body->length <= pat->max));
924 if (!e->env)
925 return false;
926 return pat->pat_not ^ (match_reference(pat, &e->env->references) ||
927 match_reference(pat, &e->env->in_reply_to));
928 case MUTT_PAT_ADDRESS:
929 if (!e->env)
930 return false;
931 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
932 4, &e->env->from, &e->env->sender,
933 &e->env->to, &e->env->cc);
935 if (!e->env)
936 return false;
937 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
938 2, &e->env->to, &e->env->cc);
939 case MUTT_PAT_LIST: /* known list, subscribed or not */
940 {
941 if (!e->env)
942 return false;
943
944 bool result;
945 if (cache)
946 {
947 int *cache_entry = pat->all_addr ? &cache->list_all : &cache->list_one;
948 if (!is_pattern_cache_set(*cache_entry))
949 {
950 set_pattern_cache_value(cache_entry,
952 }
953 result = get_pattern_cache_value(*cache_entry);
954 }
955 else
956 result = mutt_is_list_recipient(pat->all_addr, e->env);
957 return pat->pat_not ^ result;
958 }
960 {
961 if (!e->env)
962 return false;
963
964 bool result;
965 if (cache)
966 {
967 int *cache_entry = pat->all_addr ? &cache->sub_all : &cache->sub_one;
968 if (!is_pattern_cache_set(*cache_entry))
969 {
970 set_pattern_cache_value(cache_entry,
972 }
973 result = get_pattern_cache_value(*cache_entry);
974 }
975 else
977 return pat->pat_not ^ result;
978 }
980 {
981 if (!e->env)
982 return false;
983
984 bool result;
985 if (cache)
986 {
987 int *cache_entry = pat->all_addr ? &cache->pers_recip_all : &cache->pers_recip_one;
988 if (!is_pattern_cache_set(*cache_entry))
989 {
990 set_pattern_cache_value(cache_entry,
991 match_user(pat->all_addr, &e->env->to, &e->env->cc));
992 }
993 result = get_pattern_cache_value(*cache_entry);
994 }
995 else
996 result = match_user(pat->all_addr, &e->env->to, &e->env->cc);
997 return pat->pat_not ^ result;
998 }
1000 {
1001 if (!e->env)
1002 return false;
1003
1004 bool result;
1005 if (cache)
1006 {
1007 int *cache_entry = pat->all_addr ? &cache->pers_from_all : &cache->pers_from_one;
1008 if (!is_pattern_cache_set(*cache_entry))
1009 {
1010 set_pattern_cache_value(cache_entry,
1011 match_user(pat->all_addr, &e->env->from, NULL));
1012 }
1013 result = get_pattern_cache_value(*cache_entry);
1014 }
1015 else
1016 result = match_user(pat->all_addr, &e->env->from, NULL);
1017 return pat->pat_not ^ result;
1018 }
1019 case MUTT_PAT_COLLAPSED:
1020 return pat->pat_not ^ (e->collapsed && e->num_hidden > 1);
1022 if (!WithCrypto)
1023 {
1025 return false;
1026 }
1027 return pat->pat_not ^ ((e->security & SEC_SIGN) ? 1 : 0);
1029 if (!WithCrypto)
1030 {
1032 return false;
1033 }
1034 return pat->pat_not ^ ((e->security & SEC_GOODSIGN) ? 1 : 0);
1036 if (!WithCrypto)
1037 {
1039 return false;
1040 }
1041 return pat->pat_not ^ ((e->security & SEC_ENCRYPT) ? 1 : 0);
1042 case MUTT_PAT_PGP_KEY:
1043 if (!(WithCrypto & APPLICATION_PGP))
1044 {
1046 return false;
1047 }
1048 return pat->pat_not ^ ((e->security & PGP_KEY) == PGP_KEY);
1049 case MUTT_PAT_XLABEL:
1050 if (!e->env)
1051 return false;
1052 return pat->pat_not ^ (e->env->x_label && patmatch(pat, e->env->x_label));
1054 {
1055 char *tags = driver_tags_get(&e->tags);
1056 const bool rc = (pat->pat_not ^ (tags && patmatch(pat, tags)));
1057 FREE(&tags);
1058 return rc;
1059 }
1060 case MUTT_PAT_HORMEL:
1061 if (!e->env)
1062 return false;
1063 return pat->pat_not ^ (e->env->spam.data && patmatch(pat, e->env->spam.data));
1065 return pat->pat_not ^ (e->thread && e->thread->duplicate_thread);
1067 if (!m)
1068 return false;
1069 {
1070 int count = mutt_count_body_parts(m, e, msg->fp);
1071 return pat->pat_not ^ (count >= pat->min &&
1072 (pat->max == MUTT_MAXRANGE || count <= pat->max));
1073 }
1074 case MUTT_PAT_MIMETYPE:
1075 if (!m)
1076 return false;
1077 return pat->pat_not ^ match_mime_content_type(pat, e, msg->fp);
1079 return pat->pat_not ^ (e->thread && !e->thread->child);
1080 case MUTT_PAT_BROKEN:
1081 return pat->pat_not ^ (e->thread && e->thread->fake_thread);
1082#ifdef USE_NNTP
1084 if (!e->env)
1085 return false;
1086 return pat->pat_not ^ (e->env->newsgroups && patmatch(pat, e->env->newsgroups));
1087#endif
1088 }
1089 mutt_error(_("error: unknown op %d (report this error)"), pat->op);
1090 return false;
1091}
1092
1108 struct Mailbox *m, struct Email *e, struct PatternCache *cache)
1109{
1110 const bool needs_msg = pattern_needs_msg(m, pat);
1111 struct Message *msg = needs_msg ? mx_msg_open(m, e->msgno) : NULL;
1112 if (needs_msg && !msg)
1113 {
1114 return false;
1115 }
1116 const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1117 mx_msg_close(m, &msg);
1118 return matched;
1119}
1120
1135 struct AliasView *av, struct PatternCache *cache)
1136{
1137 switch (pat->op)
1138 {
1139 case MUTT_PAT_FROM: /* alias */
1140 if (!av->alias)
1141 return false;
1142 return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1143 case MUTT_PAT_CC: /* comment */
1144 if (!av->alias)
1145 return false;
1146 return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1147 case MUTT_PAT_TO: /* alias address list */
1148 if (!av->alias)
1149 return false;
1150 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1151 1, &av->alias->addr);
1152 case MUTT_PAT_AND:
1153 return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1154 case MUTT_PAT_OR:
1155 return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1156 }
1157
1158 return false;
1159}
bool(* addr_predicate_t)(const struct Address *a)
Definition: address.h:73
Email Address Handling.
Email Aliases.
struct Address * alias_reverse_lookup(const struct Address *addr)
Does the user have an alias for the given address.
Definition: reverse.c:105
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:574
Representation of a single alias to an email address.
GUI display the mailboxes in a side panel.
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:591
int mutt_count_body_parts(const struct Mailbox *m, struct Email *e, FILE *fp)
Count the MIME Body parts.
Definition: attachments.c:251
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
Definition: compile.c:500
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c:414
Duplicate the structure of an entire email.
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:54
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:56
Convenience wrapper for the core headers.
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
Structs that make up an email.
static int match_user(int all_addr, struct AddressList *al1, struct AddressList *al2)
Matches the user's email Address.
Definition: exec.c:486
static bool msg_search(struct Pattern *pat, struct Email *e, struct Message *msg)
Search an email.
Definition: exec.c:112
static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
Check whether a pattern needs a full message.
Definition: exec.c:762
static int match_threadcomplete(struct PatternList *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t, int left, int up, int right, int down)
Match a Pattern against an email thread.
Definition: exec.c:522
bool mutt_pattern_alias_exec(struct Pattern *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Match a pattern against an alias.
Definition: exec.c:1134
static void print_crypt_pattern_op_error(int op)
Print an error for a disabled crypto pattern.
Definition: exec.c:86
static int match_threadparent(struct PatternList *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t)
Match Pattern against an email's parent.
Definition: exec.c:560
static bool match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment's Content-Type.
Definition: exec.c:599
static bool perform_alias_and(struct PatternList *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Perform a logical AND on a set of Patterns.
Definition: exec.c:309
static bool match_mime_content_type(const struct Pattern *pat, struct Email *e, FILE *fp)
Match a Pattern against an email's Content-Type.
Definition: exec.c:624
static int match_threadchildren(struct PatternList *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t)
Match Pattern against an email's children.
Definition: exec.c:579
static bool match_reference(struct Pattern *pat, struct ListHead *refs)
Match references against a Pattern.
Definition: exec.c:413
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:383
static bool mutt_is_predicate_recipient(bool all_addr, struct Envelope *env, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition: exec.c:435
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: exec.c:71
static int is_pattern_cache_set(int cache_entry)
Is a given Pattern cached?
Definition: exec.c:674
static int perform_alias_or(struct PatternList *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Perform a logical OR on a set of Patterns.
Definition: exec.c:358
bool mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *env)
Matches subscribed mailing lists.
Definition: exec.c:459
static int perform_or(struct PatternList *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct Message *msg, struct PatternCache *cache)
Perform a logical OR on a set of Patterns.
Definition: exec.c:334
bool mutt_is_list_recipient(bool all_addr, struct Envelope *env)
Matches known mailing lists.
Definition: exec.c:472
static bool match_update_dynamic_date(struct Pattern *pat)
Update a dynamic date pattern.
Definition: exec.c:636
static bool perform_and(struct PatternList *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct Message *msg, struct PatternCache *cache)
Perform a logical AND on a set of Patterns.
Definition: exec.c:285
static bool get_pattern_cache_value(int cache_entry)
Get pattern cache value.
Definition: exec.c:664
static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct Message *msg, struct PatternCache *cache)
Match a pattern against an email header.
Definition: exec.c:808
static void set_pattern_cache_value(int *cache_entry, int value)
Sets a value in the PatternCache cache entry.
Definition: exec.c:653
bool mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: exec.c:1107
static int msg_search_sendmode(struct Email *e, struct Pattern *pat)
Search in send-mode.
Definition: exec.c:687
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define mutt_file_mkstemp()
Definition: file.h:112
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:369
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:44
bool mutt_is_subscribed_list(const struct Address *addr)
Is this the email address of a user-subscribed mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:56
#define mutt_error(...)
Definition: logging.h:87
#define mutt_perror(...)
Definition: logging.h:88
Shared code for the Alias and Query Dialogs.
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
Decide how to display email content.
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:572
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition: header.h:42
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:102
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
Handle mailing lists.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
#define mutt_array_size(x)
Definition: memory.h:36
#define TYPE(body)
Definition: mime.h:89
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:592
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
Many unsorted constants and some structs.
@ MUTT_ALL
All messages.
Definition: mutt.h:88
@ MUTT_SUPERSEDED
Superseded messages.
Definition: mutt.h:104
@ MUTT_EXPIRED
Expired messages.
Definition: mutt.h:103
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:93
@ MUTT_OLD
Old messages.
Definition: mutt.h:91
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:100
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:99
@ MUTT_DELETED
Deleted messages.
Definition: mutt.h:98
@ MUTT_NEW
New messages.
Definition: mutt.h:90
@ MUTT_UNREAD
Unread messages.
Definition: mutt.h:94
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:92
Some miscellaneous functions.
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1193
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1147
API for mailboxes.
API for encryption/signing of emails.
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:80
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define PGP_KEY
Definition: lib.h:99
#define WithCrypto
Definition: lib.h:116
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
char * mutt_rfc822_read_line(FILE *fp, char *line, size_t *linelen)
Read a header line from a file.
Definition: parse.c:1083
const struct PatternFlags * lookup_op(int op)
Lookup the Pattern Flags for an op.
Definition: flags.c:210
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition: lib.h:148
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition: lib.h:150
@ MUTT_PAT_BROKEN
Message is part of a broken thread.
Definition: lib.h:144
@ MUTT_PAT_ID_EXTERNAL
Message-Id is among results from an external query.
Definition: lib.h:146
@ MUTT_PAT_OR
Either pattern can match.
Definition: lib.h:131
@ MUTT_PAT_CHILDREN
Pattern matches a child email.
Definition: lib.h:134
@ MUTT_PAT_PARENT
Pattern matches parent.
Definition: lib.h:133
@ MUTT_PAT_REFERENCE
Pattern matches 'References:' or 'In-Reply-To:' field.
Definition: lib.h:155
@ MUTT_PAT_FROM
Pattern matches 'From:' field.
Definition: lib.h:139
@ MUTT_PAT_DRIVER_TAGS
Pattern matches message tags.
Definition: lib.h:168
@ MUTT_PAT_COLLAPSED
Thread is collapsed.
Definition: lib.h:137
@ MUTT_PAT_CRYPT_VERIFIED
Message is crypographically verified.
Definition: lib.h:163
@ MUTT_PAT_HORMEL
Pattern matches email's spam score.
Definition: lib.h:149
@ MUTT_PAT_SUBJECT
Pattern matches 'Subject:' field.
Definition: lib.h:138
@ MUTT_PAT_LIST
Email is on mailing list.
Definition: lib.h:157
@ MUTT_PAT_NEWSGROUPS
Pattern matches newsgroup.
Definition: lib.h:172
@ MUTT_PAT_PERSONAL_RECIP
Email is addressed to the user.
Definition: lib.h:159
@ MUTT_PAT_CC
Pattern matches 'Cc:' field.
Definition: lib.h:136
@ MUTT_PAT_SUBSCRIBED_LIST
Email is on subscribed mailing list.
Definition: lib.h:158
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition: lib.h:167
@ MUTT_PAT_RECIPIENT
User is a recipient of the email.
Definition: lib.h:156
@ MUTT_PAT_CRYPT_ENCRYPT
Message is encrypted.
Definition: lib.h:164
@ MUTT_PAT_UNREFERENCED
Message is unreferenced in the thread.
Definition: lib.h:143
@ MUTT_PAT_CRYPT_SIGN
Message is signed.
Definition: lib.h:162
@ MUTT_PAT_MESSAGE
Pattern matches message number.
Definition: lib.h:152
@ MUTT_PAT_AND
Both patterns must match.
Definition: lib.h:130
@ MUTT_PAT_DATE
Pattern matches 'Date:' field.
Definition: lib.h:140
@ MUTT_PAT_XLABEL
Pattern matches keyword/label.
Definition: lib.h:166
@ MUTT_PAT_SCORE
Pattern matches email's score.
Definition: lib.h:153
@ MUTT_PAT_MIMEATTACH
Pattern matches number of attachments.
Definition: lib.h:169
@ MUTT_PAT_DUPLICATED
Duplicate message.
Definition: lib.h:142
@ MUTT_PAT_PERSONAL_FROM
Email is from the user.
Definition: lib.h:160
@ MUTT_PAT_TO
Pattern matches 'To:' field.
Definition: lib.h:135
@ MUTT_PAT_SENDER
Pattern matches sender.
Definition: lib.h:151
@ MUTT_PAT_DATE_RECEIVED
Pattern matches date received.
Definition: lib.h:141
@ MUTT_PAT_ADDRESS
Pattern matches any address field.
Definition: lib.h:161
@ MUTT_PAT_MIMETYPE
Pattern matches MIME type.
Definition: lib.h:170
@ MUTT_PAT_PGP_KEY
Message has PGP key.
Definition: lib.h:165
@ MUTT_PAT_ID
Pattern matches email's Message-Id.
Definition: lib.h:145
@ MUTT_PAT_THREAD
Pattern matches email thread.
Definition: lib.h:132
@ MUTT_PAT_SIZE
Pattern matches email's size.
Definition: lib.h:154
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition: lib.h:147
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:99
uint8_t PatternExecFlags
Flags for mutt_pattern_exec(), e.g. MUTT_MATCH_FULL_ADDRESS.
Definition: lib.h:97
#define MUTT_MAXRANGE
Definition: private.h:129
#define EMSG(e)
Definition: private.h:127
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define SLIST_FIRST(head)
Definition: queue.h:229
Convenience wrapper for the send headers.
GUI display the mailboxes in a side panel.
Key value store.
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * personal
Real name of address.
Definition: address.h:37
GUI data wrapping an Alias.
Definition: gui.h:36
struct Alias * alias
Alias.
Definition: gui.h:44
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
struct Body * next
next attachment in the list
Definition: body.h:71
char * subtype
content-type subtype
Definition: body.h:60
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
The envelope/body of an email.
Definition: email.h:37
bool read
Email is read.
Definition: email.h:48
bool matched
Search matches this Email.
Definition: email.h:102
struct Envelope * env
Envelope information.
Definition: email.h:66
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct Body * body
List of MIME parts.
Definition: email.h:67
bool old
Email is seen, but unread.
Definition: email.h:47
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:122
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:69
bool flagged
Marked important?
Definition: email.h:45
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:58
bool replied
Email has been replied to.
Definition: email.h:49
bool expired
Already expired?
Definition: email.h:44
struct TagList tags
For drivers that support server tagging.
Definition: email.h:70
int score
Message score.
Definition: email.h:113
int msgno
Number displayed to the user.
Definition: email.h:111
bool deleted
Email is deleted.
Definition: email.h:76
bool tagged
Email is tagged.
Definition: email.h:107
bool superseded
Got superseded?
Definition: email.h:50
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:59
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
The header of an Email.
Definition: envelope.h:57
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
char * message_id
Message ID.
Definition: envelope.h:73
char * newsgroups
List of newsgroups.
Definition: envelope.h:79
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList sender
Email's sender.
Definition: envelope.h:63
struct ListHead references
message references (in reverse order)
Definition: envelope.h:85
struct Buffer spam
Spam header.
Definition: envelope.h:84
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:86
char * subject
Email's subject.
Definition: envelope.h:70
char * x_label
X-Label.
Definition: envelope.h:76
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
A mailbox.
Definition: mailbox.h:79
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
struct Message::@0 flags
Flags for the Message.
An Email conversation.
Definition: thread.h:35
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
bool fake_thread
Emails grouped by Subject.
Definition: thread.h:36
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
bool duplicate_thread
Duplicated Email in Thread.
Definition: thread.h:37
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Cache commonly-used patterns.
Definition: lib.h:110
int pers_recip_all
^~p
Definition: lib.h:115
int list_one
~l
Definition: lib.h:112
int pers_from_one
~P
Definition: lib.h:118
int list_all
^~l
Definition: lib.h:111
int sub_all
^~u
Definition: lib.h:113
int pers_recip_one
~p
Definition: lib.h:116
int pers_from_all
^~P
Definition: lib.h:117
int sub_one
~u
Definition: lib.h:114
Mapping between user character and internal constant.
Definition: private.h:60
int tag
Character used to represent this operation, e.g. 'A' for '~A'.
Definition: private.h:61
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition: private.h:62
A simple (non-regex) pattern.
Definition: lib.h:70
bool group_match
Check a group of Addresses.
Definition: lib.h:75
union Pattern::@1 p
bool all_addr
All Addresses in the list must match.
Definition: lib.h:73
struct Group * group
Address group if group_match is set.
Definition: lib.h:86
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:83
long min
Minimum for range checks.
Definition: lib.h:81
bool string_match
Check a string for a match.
Definition: lib.h:74
regex_t * regex
Compiled regex, for non-pattern matching.
Definition: lib.h:85
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition: lib.h:88
char * str
String, if string_match is set.
Definition: lib.h:87
bool is_alias
Is there an alias for this Address?
Definition: lib.h:77
bool ign_case
Ignore case for local string_match searches.
Definition: lib.h:76
long max
Maximum for range checks.
Definition: lib.h:82
bool dynamic
Evaluate date ranges at run time.
Definition: lib.h:78
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:71
bool sendmode
Evaluate searches in send-mode.
Definition: lib.h:79
bool is_multi
Multiple case (only for ~I pattern now)
Definition: lib.h:80
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:72
Keep track when processing files.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
FILE * fp_out
File to write to.
Definition: state.h:48
FILE * fp_in
File to read from.
Definition: state.h:47
char * driver_tags_get(struct TagList *list)
Get tags.
Definition: tags.c:145