NeoMutt  2024-04-25-100-gcb3684
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
exec.c
Go to the documentation of this file.
1
33#include "config.h"
34#include <stdarg.h> // IWYU pragma: keep
35#include <stdbool.h>
36#include <stdio.h>
37#include <string.h>
38#include <unistd.h>
39#include "private.h"
40#include "mutt/lib.h"
41#include "address/lib.h"
42#include "config/lib.h"
43#include "email/lib.h"
44#include "core/lib.h"
45#include "alias/alias.h" // IWYU pragma: keep
46#include "alias/gui.h" // IWYU pragma: keep
47#include "alias/lib.h"
48#include "mutt.h"
49#include "lib.h"
50#include "attach/lib.h"
51#include "ncrypt/lib.h"
52#include "send/lib.h"
53#include "copy.h"
54#include "handler.h"
55#include "maillist.h"
56#include "mx.h"
57#ifndef USE_FMEMOPEN
58#include <sys/stat.h>
59#endif
60
61static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags,
62 struct Mailbox *m, struct Email *e,
63 struct Message *msg, struct PatternCache *cache);
64
72static bool patmatch(const struct Pattern *pat, const char *buf)
73{
74 if (pat->is_multi)
75 return (mutt_list_find(&pat->p.multi_cases, buf) != NULL);
76 if (pat->string_match)
77 return pat->ign_case ? mutt_istr_find(buf, pat->p.str) : strstr(buf, pat->p.str);
78 if (pat->group_match)
79 return mutt_group_match(pat->p.group, buf);
80 return (regexec(pat->p.regex, buf, 0, NULL, 0) == 0);
81}
82
88{
89 const struct PatternFlags *entry = lookup_op(op);
90 if (entry)
91 {
92 /* L10N: One of the crypt pattern operators: ~g, ~G, ~k, ~V
93 was invoked when NeoMutt was compiled without crypto support.
94 %c is the pattern character, i.e. "g". */
95 mutt_error(_("Pattern operator '~%c' is disabled"), entry->tag);
96 }
97 else
98 {
99 /* L10N: An unknown pattern operator was somehow invoked.
100 This shouldn't be possible unless there is a bug. */
101 mutt_error(_("error: unknown op %d (report this error)"), op);
102 }
103}
104
113static bool msg_search(struct Pattern *pat, struct Email *e, struct Message *msg)
114{
115 ASSERT(msg);
116
117 bool match = false;
118
119 FILE *fp = NULL;
120 long len = 0;
121#ifdef USE_FMEMOPEN
122 char *temp = NULL;
123 size_t tempsize = 0;
124#else
125 struct stat st = { 0 };
126#endif
127
128 const bool needs_head = (pat->op == MUTT_PAT_HEADER) || (pat->op == MUTT_PAT_WHOLE_MSG);
129 const bool needs_body = (pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_WHOLE_MSG);
130 const bool c_thorough_search = cs_subset_bool(NeoMutt->sub, "thorough_search");
131 if (c_thorough_search)
132 {
133 /* decode the header / body */
134 struct State state = { 0 };
135 state.fp_in = msg->fp;
136 state.flags = STATE_CHARCONV;
137#ifdef USE_FMEMOPEN
138 state.fp_out = open_memstream(&temp, &tempsize);
139 if (!state.fp_out)
140 {
141 mutt_perror(_("Error opening 'memory stream'"));
142 return false;
143 }
144#else
145 state.fp_out = mutt_file_mkstemp();
146 if (!state.fp_out)
147 {
148 mutt_perror(_("Can't create temporary file"));
149 return false;
150 }
151#endif
152
153 if (needs_head)
154 {
155 mutt_copy_header(msg->fp, e, state.fp_out, CH_FROM | CH_DECODE, NULL, 0);
156 }
157
158 if (needs_body)
159 {
161
162 if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) &&
164 {
165 if (state.fp_out)
166 {
167 mutt_file_fclose(&state.fp_out);
168#ifdef USE_FMEMOPEN
169 FREE(&temp);
170#endif
171 }
172 return false;
173 }
174
175 if (!mutt_file_seek(msg->fp, e->offset, SEEK_SET))
176 {
177#ifdef USE_FMEMOPEN
178 FREE(&temp);
179#endif
180 return false;
181 }
182 mutt_body_handler(e->body, &state);
183 }
184
185#ifdef USE_FMEMOPEN
186 mutt_file_fclose(&state.fp_out);
187 len = tempsize;
188
189 if (tempsize != 0)
190 {
191 fp = fmemopen(temp, tempsize, "r");
192 if (!fp)
193 {
194 mutt_perror(_("Error re-opening 'memory stream'"));
195 FREE(&temp);
196 return false;
197 }
198 }
199 else
200 { /* fmemopen can't handle empty buffers */
201 fp = mutt_file_fopen("/dev/null", "r");
202 if (!fp)
203 {
204 mutt_perror(_("Error opening /dev/null"));
205 FREE(&temp);
206 return false;
207 }
208 }
209#else
210 fp = state.fp_out;
211 fflush(fp);
212 if (!mutt_file_seek(fp, 0, SEEK_SET) || fstat(fileno(fp), &st))
213 {
214 mutt_perror(_("Error checking length of temporary file"));
215 mutt_file_fclose(&fp);
216 return false;
217 }
218 len = (long) st.st_size;
219#endif
220 }
221 else
222 {
223 /* raw header / body */
224 fp = msg->fp;
225 if (needs_head)
226 {
227 if (!mutt_file_seek(fp, e->offset, SEEK_SET))
228 {
229 return false;
230 }
231 len = e->body->offset - e->offset;
232 }
233 if (needs_body)
234 {
235 if (pat->op == MUTT_PAT_BODY)
236 {
237 if (!mutt_file_seek(fp, e->body->offset, SEEK_SET))
238 {
239 return false;
240 }
241 }
242 len += e->body->length;
243 }
244 }
245
246 /* search the file "fp" */
247 if (pat->op == MUTT_PAT_HEADER)
248 {
249 struct Buffer *buf = buf_pool_get();
250 while (len > 0)
251 {
252 if (mutt_rfc822_read_line(fp, buf) == 0)
253 {
254 break;
255 }
256 len -= buf_len(buf);
257 if (patmatch(pat, buf_string(buf)))
258 {
259 match = true;
260 break;
261 }
262 }
263 buf_pool_release(&buf);
264 }
265 else
266 {
267 char buf[1024] = { 0 };
268 while (len > 0)
269 {
270 if (!fgets(buf, sizeof(buf), fp))
271 {
272 break; /* don't loop forever */
273 }
274 len -= mutt_str_len(buf);
275 if (patmatch(pat, buf))
276 {
277 match = true;
278 break;
279 }
280 }
281 }
282
283 if (c_thorough_search)
284 mutt_file_fclose(&fp);
285
286#ifdef USE_FMEMOPEN
287 FREE(&temp);
288#endif
289
290 return match;
291}
292
303static bool perform_and(struct PatternList *pat, PatternExecFlags flags,
304 struct Mailbox *m, struct Email *e, struct Message *msg,
305 struct PatternCache *cache)
306{
307 struct Pattern *p = NULL;
308
309 SLIST_FOREACH(p, pat, entries)
310 {
311 if (!pattern_exec(p, flags, m, e, msg, cache))
312 {
313 return false;
314 }
315 }
316 return true;
317}
318
327static bool perform_alias_and(struct PatternList *pat, PatternExecFlags flags,
328 struct AliasView *av, struct PatternCache *cache)
329{
330 struct Pattern *p = NULL;
331
332 SLIST_FOREACH(p, pat, entries)
333 {
334 if (!mutt_pattern_alias_exec(p, flags, av, cache))
335 {
336 return false;
337 }
338 }
339 return true;
340}
341
352static int perform_or(struct PatternList *pat, PatternExecFlags flags,
353 struct Mailbox *m, struct Email *e, struct Message *msg,
354 struct PatternCache *cache)
355{
356 struct Pattern *p = NULL;
357
358 SLIST_FOREACH(p, pat, entries)
359 {
360 if (pattern_exec(p, flags, m, e, msg, cache))
361 {
362 return true;
363 }
364 }
365 return false;
366}
367
376static int perform_alias_or(struct PatternList *pat, PatternExecFlags flags,
377 struct AliasView *av, struct PatternCache *cache)
378{
379 struct Pattern *p = NULL;
380
381 SLIST_FOREACH(p, pat, entries)
382 {
383 if (mutt_pattern_alias_exec(p, flags, av, cache))
384 {
385 return true;
386 }
387 }
388 return false;
389}
390
401static int match_addrlist(struct Pattern *pat, bool match_personal, int n, ...)
402{
403 va_list ap;
404
405 va_start(ap, n);
406 while (n-- > 0)
407 {
408 struct AddressList *al = va_arg(ap, struct AddressList *);
409 struct Address *a = NULL;
410 TAILQ_FOREACH(a, al, entries)
411 {
412 if (pat->all_addr ^
413 ((!pat->is_alias || alias_reverse_lookup(a)) &&
414 ((a->mailbox && patmatch(pat, buf_string(a->mailbox))) ||
415 (match_personal && a->personal && patmatch(pat, buf_string(a->personal))))))
416 {
417 va_end(ap);
418 return !pat->all_addr; /* Found match, or non-match if all_addr */
419 }
420 }
421 }
422 va_end(ap);
423 return pat->all_addr; /* No matches, or all matches if all_addr */
424}
425
432static bool match_reference(struct Pattern *pat, struct ListHead *refs)
433{
434 struct ListNode *np = NULL;
435 STAILQ_FOREACH(np, refs, entries)
436 {
437 if (patmatch(pat, np->data))
438 return true;
439 }
440 return false;
441}
442
454static bool mutt_is_predicate_recipient(bool all_addr, struct Envelope *env, addr_predicate_t p)
455{
456 struct AddressList *als[] = { &env->to, &env->cc };
457 for (size_t i = 0; i < mutt_array_size(als); ++i)
458 {
459 struct AddressList *al = als[i];
460 struct Address *a = NULL;
461 TAILQ_FOREACH(a, al, entries)
462 {
463 if (all_addr ^ p(a))
464 return !all_addr;
465 }
466 }
467 return all_addr;
468}
469
478bool mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *env)
479{
481}
482
491bool mutt_is_list_recipient(bool all_addr, struct Envelope *env)
492{
493 return mutt_is_predicate_recipient(all_addr, env, &mutt_is_mail_list);
494}
495
505static int match_user(bool all_addr, int n, ...)
506{
507 va_list ap;
508
509 va_start(ap, n);
510 while (n-- > 0)
511 {
512 struct AddressList *al = va_arg(ap, struct AddressList *);
513 struct Address *a = NULL;
514 TAILQ_FOREACH(a, al, entries)
515 {
516 if (all_addr ^ mutt_addr_is_user(a))
517 {
518 va_end(ap);
519 return !all_addr;
520 }
521 }
522 }
523 va_end(ap);
524 return all_addr;
525}
526
540static int match_threadcomplete(struct PatternList *pat, PatternExecFlags flags,
541 struct Mailbox *m, struct MuttThread *t,
542 int left, int up, int right, int down)
543{
544 if (!t)
545 return 0;
546
547 int a;
548 struct Email *e = t->message;
549 if (e)
550 if (mutt_pattern_exec(SLIST_FIRST(pat), flags, m, e, NULL))
551 return 1;
552
553 if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
554 return a;
555 if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
556 {
557 return a;
558 }
559 if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
560 {
561 return a;
562 }
563 if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
564 return a;
565 return 0;
566}
567
578static int match_threadparent(struct PatternList *pat, PatternExecFlags flags,
579 struct Mailbox *m, struct MuttThread *t)
580{
581 if (!t || !t->parent || !t->parent->message)
582 return 0;
583
584 return mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->parent->message, NULL);
585}
586
597static int match_threadchildren(struct PatternList *pat, PatternExecFlags flags,
598 struct Mailbox *m, struct MuttThread *t)
599{
600 if (!t || !t->child)
601 return 0;
602
603 for (t = t->child; t; t = t->next)
604 if (t->message && mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->message, NULL))
605 return 1;
606
607 return 0;
608}
609
617static bool match_content_type(const struct Pattern *pat, struct Body *b)
618{
619 if (!b)
620 return false;
621
622 char buf[256] = { 0 };
623 snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
624
625 if (patmatch(pat, buf))
626 return true;
627 if (match_content_type(pat, b->parts))
628 return true;
629 if (match_content_type(pat, b->next))
630 return true;
631 return false;
632}
633
642static bool match_mime_content_type(const struct Pattern *pat, struct Email *e, FILE *fp)
643{
645 return match_content_type(pat, e->body);
646}
647
654static bool match_update_dynamic_date(struct Pattern *pat)
655{
656 struct Buffer *err = buf_pool_get();
657
658 bool rc = eval_date_minmax(pat, pat->p.str, err);
659 buf_pool_release(&err);
660
661 return rc;
662}
663
671static void set_pattern_cache_value(int *cache_entry, int value)
672{
673 *cache_entry = (value != 0) ? 2 : 1;
674}
675
682static bool get_pattern_cache_value(int cache_entry)
683{
684 return cache_entry == 2;
685}
686
692static int is_pattern_cache_set(int cache_entry)
693{
694 return cache_entry != 0;
695}
696
705static int msg_search_sendmode(struct Email *e, struct Pattern *pat)
706{
707 bool match = false;
708 char *buf = NULL;
709 size_t blen = 0;
710 FILE *fp = NULL;
711
712 if ((pat->op == MUTT_PAT_HEADER) || (pat->op == MUTT_PAT_WHOLE_MSG))
713 {
714 struct Buffer *tempfile = buf_pool_get();
715 buf_mktemp(tempfile);
716 fp = mutt_file_fopen(buf_string(tempfile), "w+");
717 if (!fp)
718 {
719 mutt_perror("%s", buf_string(tempfile));
720 buf_pool_release(&tempfile);
721 return 0;
722 }
723
725 false, false, NeoMutt->sub);
726 fflush(fp);
727 if (mutt_file_seek(fp, 0, SEEK_SET))
728 {
729 while ((buf = mutt_file_read_line(buf, &blen, fp, NULL, MUTT_RL_NO_FLAGS)) != NULL)
730 {
731 if (patmatch(pat, buf) == 0)
732 {
733 match = true;
734 break;
735 }
736 }
737 }
738
739 FREE(&buf);
740 mutt_file_fclose(&fp);
741 unlink(buf_string(tempfile));
742 buf_pool_release(&tempfile);
743
744 if (match)
745 return match;
746 }
747
748 if ((pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_WHOLE_MSG))
749 {
750 fp = mutt_file_fopen(e->body->filename, "r");
751 if (!fp)
752 {
753 mutt_perror("%s", e->body->filename);
754 return 0;
755 }
756
757 while ((buf = mutt_file_read_line(buf, &blen, fp, NULL, MUTT_RL_NO_FLAGS)) != NULL)
758 {
759 if (patmatch(pat, buf) == 0)
760 {
761 match = true;
762 break;
763 }
764 }
765
766 FREE(&buf);
767 mutt_file_fclose(&fp);
768 }
769
770 return match;
771}
772
780static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
781{
782 if ((pat->op == MUTT_PAT_MIMETYPE) || (pat->op == MUTT_PAT_MIMEATTACH))
783 {
784 return true;
785 }
786
787 if ((pat->op == MUTT_PAT_WHOLE_MSG) || (pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_HEADER))
788 {
789 return !((m->type == MUTT_IMAP) && pat->string_match);
790 }
791
792 if ((pat->op == MUTT_PAT_AND) || (pat->op == MUTT_PAT_OR))
793 {
794 struct Pattern *p = NULL;
795 SLIST_FOREACH(p, pat->child, entries)
796 {
797 if (pattern_needs_msg(m, p))
798 {
799 return true;
800 }
801 }
802 }
803
804 return false;
805}
806
822static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags,
823 struct Mailbox *m, struct Email *e,
824 struct Message *msg, struct PatternCache *cache)
825{
826 switch (pat->op)
827 {
828 case MUTT_PAT_AND:
829 return pat->pat_not ^ (perform_and(pat->child, flags, m, e, msg, cache) > 0);
830 case MUTT_PAT_OR:
831 return pat->pat_not ^ (perform_or(pat->child, flags, m, e, msg, cache) > 0);
832 case MUTT_PAT_THREAD:
833 return pat->pat_not ^
834 match_threadcomplete(pat->child, flags, m, e->thread, 1, 1, 1, 1);
835 case MUTT_PAT_PARENT:
836 return pat->pat_not ^ match_threadparent(pat->child, flags, m, e->thread);
838 return pat->pat_not ^ match_threadchildren(pat->child, flags, m, e->thread);
839 case MUTT_ALL:
840 return !pat->pat_not;
841 case MUTT_EXPIRED:
842 return pat->pat_not ^ e->expired;
843 case MUTT_SUPERSEDED:
844 return pat->pat_not ^ e->superseded;
845 case MUTT_FLAG:
846 return pat->pat_not ^ e->flagged;
847 case MUTT_TAG:
848 return pat->pat_not ^ e->tagged;
849 case MUTT_NEW:
850 return pat->pat_not ? e->old || e->read : !(e->old || e->read);
851 case MUTT_UNREAD:
852 return pat->pat_not ? e->read : !e->read;
853 case MUTT_REPLIED:
854 return pat->pat_not ^ e->replied;
855 case MUTT_OLD:
856 return pat->pat_not ? (!e->old || e->read) : (e->old && !e->read);
857 case MUTT_READ:
858 return pat->pat_not ^ e->read;
859 case MUTT_DELETED:
860 return pat->pat_not ^ e->deleted;
861 case MUTT_PAT_MESSAGE:
862 return pat->pat_not ^
863 ((email_msgno(e) >= pat->min) && (email_msgno(e) <= pat->max));
864 case MUTT_PAT_DATE:
865 if (pat->dynamic)
867 return pat->pat_not ^ ((e->date_sent >= pat->min) && (e->date_sent <= pat->max));
869 if (pat->dynamic)
871 return pat->pat_not ^ ((e->received >= pat->min) && (e->received <= pat->max));
872 case MUTT_PAT_BODY:
873 case MUTT_PAT_HEADER:
875 if (pat->sendmode)
876 {
877 if (!e->body || !e->body->filename)
878 return false;
879 return pat->pat_not ^ msg_search_sendmode(e, pat);
880 }
881 /* m can be NULL in certain cases, such as when replying to a message
882 * from the attachment menu and the user has a reply-hook using "~e".
883 * This is also the case when message scoring. */
884 if (!m)
885 return false;
886 /* IMAP search sets e->matched at search compile time */
887 if ((m->type == MUTT_IMAP) && pat->string_match)
888 return e->matched;
889 return pat->pat_not ^ msg_search(pat, e, msg);
891 if (!m)
892 return false;
893 if (m->type == MUTT_IMAP)
894 {
895 return (pat->string_match) ? e->matched : false;
896 }
897 mutt_error(_("error: server custom search only supported with IMAP"));
898 return false;
899 case MUTT_PAT_SENDER:
900 if (!e->env)
901 return false;
902 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
903 1, &e->env->sender);
904 case MUTT_PAT_FROM:
905 if (!e->env)
906 return false;
907 return pat->pat_not ^
908 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->from);
909 case MUTT_PAT_TO:
910 if (!e->env)
911 return false;
912 return pat->pat_not ^
913 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->to);
914 case MUTT_PAT_CC:
915 if (!e->env)
916 return false;
917 return pat->pat_not ^
918 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->cc);
919 case MUTT_PAT_BCC:
920 if (!e->env)
921 return false;
922 return pat->pat_not ^
923 match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->bcc);
924 case MUTT_PAT_SUBJECT:
925 if (!e->env)
926 return false;
927 return pat->pat_not ^ (e->env->subject && patmatch(pat, e->env->subject));
928 case MUTT_PAT_ID:
930 if (!e->env)
931 return false;
932 return pat->pat_not ^ (e->env->message_id && patmatch(pat, e->env->message_id));
933 case MUTT_PAT_SCORE:
934 return pat->pat_not ^ (e->score >= pat->min &&
935 (pat->max == MUTT_MAXRANGE || e->score <= pat->max));
936 case MUTT_PAT_SIZE:
937 return pat->pat_not ^ (e->body->length >= pat->min &&
938 (pat->max == MUTT_MAXRANGE || e->body->length <= pat->max));
940 if (!e->env)
941 return false;
942 return pat->pat_not ^ (match_reference(pat, &e->env->references) ||
943 match_reference(pat, &e->env->in_reply_to));
944 case MUTT_PAT_ADDRESS:
945 if (!e->env)
946 return false;
947 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
948 5, &e->env->from, &e->env->sender,
949 &e->env->to, &e->env->cc, &e->env->bcc);
951 if (!e->env)
952 return false;
953 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 3,
954 &e->env->to, &e->env->cc, &e->env->bcc);
955 case MUTT_PAT_LIST: /* known list, subscribed or not */
956 {
957 if (!e->env)
958 return false;
959
960 bool result;
961 if (cache)
962 {
963 int *cache_entry = pat->all_addr ? &cache->list_all : &cache->list_one;
964 if (!is_pattern_cache_set(*cache_entry))
965 {
966 set_pattern_cache_value(cache_entry,
968 }
969 result = get_pattern_cache_value(*cache_entry);
970 }
971 else
972 {
973 result = mutt_is_list_recipient(pat->all_addr, e->env);
974 }
975 return pat->pat_not ^ result;
976 }
978 {
979 if (!e->env)
980 return false;
981
982 bool result;
983 if (cache)
984 {
985 int *cache_entry = pat->all_addr ? &cache->sub_all : &cache->sub_one;
986 if (!is_pattern_cache_set(*cache_entry))
987 {
988 set_pattern_cache_value(cache_entry,
990 }
991 result = get_pattern_cache_value(*cache_entry);
992 }
993 else
994 {
996 }
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_recip_all : &cache->pers_recip_one;
1008 if (!is_pattern_cache_set(*cache_entry))
1009 {
1010 set_pattern_cache_value(cache_entry,
1011 match_user(pat->all_addr, 3, &e->env->to,
1012 &e->env->cc, &e->env->bcc));
1013 }
1014 result = get_pattern_cache_value(*cache_entry);
1015 }
1016 else
1017 {
1018 result = match_user(pat->all_addr, 3, &e->env->to, &e->env->cc, &e->env->bcc);
1019 }
1020 return pat->pat_not ^ result;
1021 }
1023 {
1024 if (!e->env)
1025 return false;
1026
1027 bool result;
1028 if (cache)
1029 {
1030 int *cache_entry = pat->all_addr ? &cache->pers_from_all : &cache->pers_from_one;
1031 if (!is_pattern_cache_set(*cache_entry))
1032 {
1033 set_pattern_cache_value(cache_entry,
1034 match_user(pat->all_addr, 1, &e->env->from));
1035 }
1036 result = get_pattern_cache_value(*cache_entry);
1037 }
1038 else
1039 {
1040 result = match_user(pat->all_addr, 1, &e->env->from);
1041 }
1042 return pat->pat_not ^ result;
1043 }
1044 case MUTT_PAT_COLLAPSED:
1045 return pat->pat_not ^ (e->collapsed && e->num_hidden > 1);
1047 if (!WithCrypto)
1048 {
1050 return false;
1051 }
1052 return pat->pat_not ^ ((e->security & SEC_SIGN) ? 1 : 0);
1054 if (!WithCrypto)
1055 {
1057 return false;
1058 }
1059 return pat->pat_not ^ ((e->security & SEC_GOODSIGN) ? 1 : 0);
1061 if (!WithCrypto)
1062 {
1064 return false;
1065 }
1066 return pat->pat_not ^ ((e->security & SEC_ENCRYPT) ? 1 : 0);
1067 case MUTT_PAT_PGP_KEY:
1068 if (!(WithCrypto & APPLICATION_PGP))
1069 {
1071 return false;
1072 }
1073 return pat->pat_not ^ ((e->security & PGP_KEY) == PGP_KEY);
1074 case MUTT_PAT_XLABEL:
1075 if (!e->env)
1076 return false;
1077 return pat->pat_not ^ (e->env->x_label && patmatch(pat, e->env->x_label));
1079 {
1080 struct Buffer *tags = buf_pool_get();
1082 const bool rc = (pat->pat_not ^
1083 (!buf_is_empty(tags) && patmatch(pat, buf_string(tags))));
1084 buf_pool_release(&tags);
1085 return rc;
1086 }
1087 case MUTT_PAT_HORMEL:
1088 if (!e->env)
1089 return false;
1090 return pat->pat_not ^ (e->env->spam.data && patmatch(pat, e->env->spam.data));
1092 return pat->pat_not ^ (e->thread && e->thread->duplicate_thread);
1094 if (!m)
1095 return false;
1096 {
1097 int count = mutt_count_body_parts(m, e, msg->fp);
1098 return pat->pat_not ^ (count >= pat->min &&
1099 (pat->max == MUTT_MAXRANGE || count <= pat->max));
1100 }
1101 case MUTT_PAT_MIMETYPE:
1102 if (!m)
1103 return false;
1104 return pat->pat_not ^ match_mime_content_type(pat, e, msg->fp);
1106 return pat->pat_not ^ (e->thread && !e->thread->child);
1107 case MUTT_PAT_BROKEN:
1108 return pat->pat_not ^ (e->thread && e->thread->fake_thread);
1110 if (!e->env)
1111 return false;
1112 return pat->pat_not ^ (e->env->newsgroups && patmatch(pat, e->env->newsgroups));
1113 }
1114 mutt_error(_("error: unknown op %d (report this error)"), pat->op);
1115 return false;
1116}
1117
1133 struct Mailbox *m, struct Email *e, struct PatternCache *cache)
1134{
1135 const bool needs_msg = pattern_needs_msg(m, pat);
1136 struct Message *msg = needs_msg ? mx_msg_open(m, e) : NULL;
1137 if (needs_msg && !msg)
1138 {
1139 return false;
1140 }
1141 const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1142 mx_msg_close(m, &msg);
1143 return matched;
1144}
1145
1160 struct AliasView *av, struct PatternCache *cache)
1161{
1162 switch (pat->op)
1163 {
1164 case MUTT_PAT_FROM: /* alias */
1165 if (!av->alias)
1166 return false;
1167 return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1168 case MUTT_PAT_CC: /* comment */
1169 if (!av->alias)
1170 return false;
1171 return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1172 case MUTT_PAT_TO: /* alias address list */
1173 if (!av->alias)
1174 return false;
1175 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1176 1, &av->alias->addr);
1178 {
1179 if (!av->alias)
1180 return false;
1181
1182 struct Buffer *tags = buf_pool_get();
1183 alias_tags_to_buffer(&av->alias->tags, tags);
1184
1185 bool rc = false;
1186 if (!buf_is_empty(tags))
1187 {
1188 rc = (pat->pat_not ^ (patmatch(pat, buf_string(tags))));
1189 }
1190
1191 buf_pool_release(&tags);
1192 return rc;
1193 }
1194
1195 case MUTT_PAT_AND:
1196 return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1197 case MUTT_PAT_OR:
1198 return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1199 }
1200
1201 return false;
1202}
Email Address Handling.
bool(* addr_predicate_t)(const struct Address *a)
Definition: address.h:56
void alias_tags_to_buffer(struct TagList *tl, struct Buffer *buf)
Write a comma-separated list of tags to a Buffer.
Definition: commands.c:49
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:600
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:597
int mutt_count_body_parts(const struct Mailbox *m, struct Email *e, FILE *fp)
Count the MIME Body parts.
Definition: attachments.c:252
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
Definition: compile.c:496
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
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:425
Duplicate the structure of an entire email.
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:56
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:58
Convenience wrapper for the core headers.
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:132
Structs that make up an email.
size_t mutt_rfc822_read_line(FILE *fp, struct Buffer *buf)
Read a header line from a file.
Definition: parse.c:1125
static bool msg_search(struct Pattern *pat, struct Email *e, struct Message *msg)
Search an email.
Definition: exec.c:113
static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
Check whether a pattern needs a full message.
Definition: exec.c:780
static int match_user(bool all_addr, int n,...)
Matches the user's email Address.
Definition: exec.c:505
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:540
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:1159
static void print_crypt_pattern_op_error(int op)
Print an error for a disabled crypto pattern.
Definition: exec.c:87
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:578
static bool match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment's Content-Type.
Definition: exec.c:617
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:327
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:642
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:597
static bool match_reference(struct Pattern *pat, struct ListHead *refs)
Match references against a Pattern.
Definition: exec.c:432
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:401
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:454
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: exec.c:72
static int is_pattern_cache_set(int cache_entry)
Is a given Pattern cached?
Definition: exec.c:692
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:376
bool mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *env)
Matches subscribed mailing lists.
Definition: exec.c:478
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:352
bool mutt_is_list_recipient(bool all_addr, struct Envelope *env)
Matches known mailing lists.
Definition: exec.c:491
static bool match_update_dynamic_date(struct Pattern *pat)
Update a dynamic date pattern.
Definition: exec.c:654
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:303
static bool get_pattern_cache_value(int cache_entry)
Get pattern cache value.
Definition: exec.c:682
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:822
static void set_pattern_cache_value(int *cache_entry, int value)
Sets a value in the PatternCache cache entry.
Definition: exec.c:671
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:1132
static int msg_search_sendmode(struct Email *e, struct Pattern *pat)
Search in send-mode.
Definition: exec.c:705
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:808
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:778
#define mutt_file_fclose(FP)
Definition: file.h:149
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:148
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:370
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:45
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:57
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_perror(...)
Definition: logging2.h:93
Shared code for the Alias and Query Dialogs.
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1631
Decide how to display email content.
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *b, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:577
@ 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:103
Handle mailing lists.
#define FREE(x)
Definition: memory.h:45
#define mutt_array_size(x)
Definition: memory.h:38
#define TYPE(body)
Definition: mime.h:89
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
#define STATE_CHARCONV
Do character set conversions.
Definition: state.h:37
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:521
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
Many unsorted constants and some structs.
@ MUTT_ALL
All messages.
Definition: mutt.h:68
@ MUTT_SUPERSEDED
Superseded messages.
Definition: mutt.h:84
@ MUTT_EXPIRED
Expired messages.
Definition: mutt.h:83
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:73
@ MUTT_OLD
Old messages.
Definition: mutt.h:71
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:80
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:79
@ MUTT_DELETED
Deleted messages.
Definition: mutt.h:78
@ MUTT_NEW
New messages.
Definition: mutt.h:70
@ MUTT_UNREAD
Unread messages.
Definition: mutt.h:74
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:72
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1180
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1134
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
const struct PatternFlags * lookup_op(int op)
Lookup the Pattern Flags for an op.
Definition: flags.c:211
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition: lib.h:156
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition: lib.h:158
@ MUTT_PAT_BROKEN
Message is part of a broken thread.
Definition: lib.h:152
@ MUTT_PAT_ID_EXTERNAL
Message-Id is among results from an external query.
Definition: lib.h:154
@ MUTT_PAT_OR
Either pattern can match.
Definition: lib.h:138
@ MUTT_PAT_CHILDREN
Pattern matches a child email.
Definition: lib.h:141
@ MUTT_PAT_PARENT
Pattern matches parent.
Definition: lib.h:140
@ MUTT_PAT_REFERENCE
Pattern matches 'References:' or 'In-Reply-To:' field.
Definition: lib.h:163
@ MUTT_PAT_FROM
Pattern matches 'From:' field.
Definition: lib.h:147
@ MUTT_PAT_DRIVER_TAGS
Pattern matches message tags.
Definition: lib.h:176
@ MUTT_PAT_COLLAPSED
Thread is collapsed.
Definition: lib.h:145
@ MUTT_PAT_CRYPT_VERIFIED
Message is crypographically verified.
Definition: lib.h:171
@ MUTT_PAT_HORMEL
Pattern matches email's spam score.
Definition: lib.h:157
@ MUTT_PAT_SUBJECT
Pattern matches 'Subject:' field.
Definition: lib.h:146
@ MUTT_PAT_LIST
Email is on mailing list.
Definition: lib.h:165
@ MUTT_PAT_NEWSGROUPS
Pattern matches newsgroup.
Definition: lib.h:179
@ MUTT_PAT_PERSONAL_RECIP
Email is addressed to the user.
Definition: lib.h:167
@ MUTT_PAT_CC
Pattern matches 'Cc:' field.
Definition: lib.h:143
@ MUTT_PAT_SUBSCRIBED_LIST
Email is on subscribed mailing list.
Definition: lib.h:166
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition: lib.h:175
@ MUTT_PAT_RECIPIENT
User is a recipient of the email.
Definition: lib.h:164
@ MUTT_PAT_CRYPT_ENCRYPT
Message is encrypted.
Definition: lib.h:172
@ MUTT_PAT_UNREFERENCED
Message is unreferenced in the thread.
Definition: lib.h:151
@ MUTT_PAT_CRYPT_SIGN
Message is signed.
Definition: lib.h:170
@ MUTT_PAT_MESSAGE
Pattern matches message number.
Definition: lib.h:160
@ MUTT_PAT_AND
Both patterns must match.
Definition: lib.h:137
@ MUTT_PAT_DATE
Pattern matches 'Date:' field.
Definition: lib.h:148
@ MUTT_PAT_XLABEL
Pattern matches keyword/label.
Definition: lib.h:174
@ MUTT_PAT_SCORE
Pattern matches email's score.
Definition: lib.h:161
@ MUTT_PAT_MIMEATTACH
Pattern matches number of attachments.
Definition: lib.h:177
@ MUTT_PAT_DUPLICATED
Duplicate message.
Definition: lib.h:150
@ MUTT_PAT_PERSONAL_FROM
Email is from the user.
Definition: lib.h:168
@ MUTT_PAT_TO
Pattern matches 'To:' field.
Definition: lib.h:142
@ MUTT_PAT_BCC
Pattern matches 'Bcc:' field.
Definition: lib.h:144
@ MUTT_PAT_SENDER
Pattern matches sender.
Definition: lib.h:159
@ MUTT_PAT_DATE_RECEIVED
Pattern matches date received.
Definition: lib.h:149
@ MUTT_PAT_ADDRESS
Pattern matches any address field.
Definition: lib.h:169
@ MUTT_PAT_MIMETYPE
Pattern matches MIME type.
Definition: lib.h:178
@ MUTT_PAT_PGP_KEY
Message has PGP key.
Definition: lib.h:173
@ MUTT_PAT_ID
Pattern matches email's Message-Id.
Definition: lib.h:153
@ MUTT_PAT_THREAD
Pattern matches email thread.
Definition: lib.h:139
@ MUTT_PAT_SIZE
Pattern matches email's size.
Definition: lib.h:162
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition: lib.h:155
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:106
uint8_t PatternExecFlags
Flags for mutt_pattern_exec(), e.g. MUTT_MATCH_FULL_ADDRESS.
Definition: lib.h:104
#define MUTT_MAXRANGE
Definition: private.h:152
static int email_msgno(struct Email *e)
Helper to get the Email's message number.
Definition: private.h:147
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#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.
#define ASSERT(COND)
Definition: signal2.h:58
Key value store.
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
GUI data wrapping an Alias.
Definition: gui.h:38
struct Alias * alias
Alias.
Definition: gui.h:46
struct TagList tags
Tags.
Definition: alias.h:39
char * comment
Free-form comment string.
Definition: alias.h:38
char * name
Short name.
Definition: alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:37
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:73
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:72
char * subtype
content-type subtype
Definition: body.h:61
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:59
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
The envelope/body of an email.
Definition: email.h:39
bool read
Email is read.
Definition: email.h:50
bool matched
Search matches this Email.
Definition: email.h:102
struct Envelope * env
Envelope information.
Definition: email.h:68
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:43
struct Body * body
List of MIME parts.
Definition: email.h:69
bool old
Email is seen, but unread.
Definition: email.h:49
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:123
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:71
bool flagged
Marked important?
Definition: email.h:47
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:60
bool replied
Email has been replied to.
Definition: email.h:51
bool expired
Already expired?
Definition: email.h:46
struct TagList tags
For drivers that support server tagging.
Definition: email.h:72
int score
Message score.
Definition: email.h:113
bool deleted
Email is deleted.
Definition: email.h:78
bool tagged
Email is tagged.
Definition: email.h:107
bool superseded
Got superseded?
Definition: email.h:52
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:61
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
The header of an Email.
Definition: envelope.h:57
char *const subject
Email's subject.
Definition: envelope.h:70
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:78
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:83
struct Buffer spam
Spam header.
Definition: envelope.h:82
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
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:37
char * data
String.
Definition: list.h:38
A mailbox.
Definition: mailbox.h:79
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
A local copy of an email.
Definition: message.h:34
FILE * fp
pointer to the message data
Definition: message.h:35
struct Message::@0 flags
Flags for the Message.
An Email conversation.
Definition: thread.h:34
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:44
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:47
bool fake_thread
Emails grouped by Subject.
Definition: thread.h:38
struct MuttThread * child
Child of this Thread.
Definition: thread.h:45
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:46
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
Cache commonly-used patterns.
Definition: lib.h:117
int pers_recip_all
^~p
Definition: lib.h:122
int list_one
~l
Definition: lib.h:119
int pers_from_one
~P
Definition: lib.h:125
int list_all
^~l
Definition: lib.h:118
int sub_all
^~u
Definition: lib.h:120
int pers_recip_one
~p
Definition: lib.h:123
int pers_from_all
^~P
Definition: lib.h:124
int sub_one
~u
Definition: lib.h:121
Mapping between user character and internal constant.
Definition: private.h:75
int tag
Character used to represent this operation, e.g. 'A' for '~A'.
Definition: private.h:76
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition: private.h:77
A simple (non-regex) pattern.
Definition: lib.h:77
bool group_match
Check a group of Addresses.
Definition: lib.h:82
union Pattern::@1 p
bool all_addr
All Addresses in the list must match.
Definition: lib.h:80
struct Group * group
Address group if group_match is set.
Definition: lib.h:93
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:90
long min
Minimum for range checks.
Definition: lib.h:88
bool string_match
Check a string for a match.
Definition: lib.h:81
regex_t * regex
Compiled regex, for non-pattern matching.
Definition: lib.h:92
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition: lib.h:95
char * str
String, if string_match is set.
Definition: lib.h:94
bool is_alias
Is there an alias for this Address?
Definition: lib.h:84
bool ign_case
Ignore case for local string_match searches.
Definition: lib.h:83
long max
Maximum for range checks.
Definition: lib.h:89
bool dynamic
Evaluate date ranges at run time.
Definition: lib.h:85
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:78
bool sendmode
Evaluate searches in send-mode.
Definition: lib.h:86
bool is_multi
Multiple case (only for ~I pattern now)
Definition: lib.h:87
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:79
Keep track when processing files.
Definition: state.h:48
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition: state.h:52
FILE * fp_out
File to write to.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:49
void driver_tags_get_with_hidden(struct TagList *tl, struct Buffer *tags)
Get all tags, also hidden ones, separated by space.
Definition: tags.c:174
#define buf_mktemp(buf)
Definition: tmp.h:33
#define mutt_file_mkstemp()
Definition: tmp.h:36