NeoMutt  2021-10-22-8-g9cb437
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 
60 static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags,
61  struct Mailbox *m, struct Email *e,
62  struct Message *msg, struct PatternCache *cache);
63 
71 static 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 ? strcasestr(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 
86 static void print_crypt_pattern_op_error(int op)
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 
112 static 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 =
130  cs_subset_bool(NeoMutt->sub, "thorough_search");
131  if (c_thorough_search)
132  {
133  /* decode the header / body */
134  struct State s = { 0 };
135  s.fp_in = msg->fp;
136  s.flags = MUTT_CHARCONV;
137 #ifdef USE_FMEMOPEN
138  s.fp_out = open_memstream(&temp, &tempsize);
139  if (!s.fp_out)
140  {
141  mutt_perror(_("Error opening 'memory stream'"));
142  return false;
143  }
144 #else
146  if (!s.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, s.fp_out, CH_FROM | CH_DECODE, NULL, 0);
156  }
157 
158  if (needs_body)
159  {
160  mutt_parse_mime_message(e, msg->fp);
161 
162  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) &&
164  {
165  if (s.fp_out)
166  {
168 #ifdef USE_FMEMOPEN
169  FREE(&temp);
170 #endif
171  }
172  return false;
173  }
174 
175  fseeko(msg->fp, e->offset, SEEK_SET);
176  mutt_body_handler(e->body, &s);
177  }
178 
179 #ifdef USE_FMEMOPEN
181  len = tempsize;
182 
183  if (tempsize != 0)
184  {
185  fp = fmemopen(temp, tempsize, "r");
186  if (!fp)
187  {
188  mutt_perror(_("Error re-opening 'memory stream'"));
189  FREE(&temp);
190  return false;
191  }
192  }
193  else
194  { /* fmemopen can't handle empty buffers */
195  fp = mutt_file_fopen("/dev/null", "r");
196  if (!fp)
197  {
198  mutt_perror(_("Error opening /dev/null"));
199  return false;
200  }
201  }
202 #else
203  fp = s.fp_out;
204  fflush(fp);
205  fseek(fp, 0, SEEK_SET);
206  if (fstat(fileno(fp), &st))
207  {
208  mutt_perror(_("Error checking length of temporary file"));
209  mutt_file_fclose(&fp);
210  return false;
211  }
212  len = (long) st.st_size;
213 #endif
214  }
215  else
216  {
217  /* raw header / body */
218  fp = msg->fp;
219  if (needs_head)
220  {
221  fseeko(fp, e->offset, SEEK_SET);
222  len = e->body->offset - e->offset;
223  }
224  if (needs_body)
225  {
226  if (pat->op == MUTT_PAT_BODY)
227  {
228  fseeko(fp, e->body->offset, SEEK_SET);
229  }
230  len += e->body->length;
231  }
232  }
233 
234  size_t blen = 256;
235  char *buf = mutt_mem_malloc(blen);
236 
237  /* search the file "fp" */
238  while (len > 0)
239  {
240  if (pat->op == MUTT_PAT_HEADER)
241  {
242  buf = mutt_rfc822_read_line(fp, buf, &blen);
243  if (*buf == '\0')
244  break;
245  }
246  else if (!fgets(buf, blen - 1, fp))
247  break; /* don't loop forever */
248  if (patmatch(pat, buf))
249  {
250  match = true;
251  break;
252  }
253  len -= mutt_str_len(buf);
254  }
255 
256  FREE(&buf);
257 
258  if (c_thorough_search)
259  mutt_file_fclose(&fp);
260 
261 #ifdef USE_FMEMOPEN
262  FREE(&temp);
263 #endif
264 
265  return match;
266 }
267 
278 static bool perform_and(struct PatternList *pat, PatternExecFlags flags,
279  struct Mailbox *m, struct Email *e, struct Message *msg,
280  struct PatternCache *cache)
281 {
282  struct Pattern *p = NULL;
283 
284  SLIST_FOREACH(p, pat, entries)
285  {
286  if (!pattern_exec(p, flags, m, e, msg, cache))
287  {
288  return false;
289  }
290  }
291  return true;
292 }
293 
302 static bool perform_alias_and(struct PatternList *pat, PatternExecFlags flags,
303  struct AliasView *av, struct PatternCache *cache)
304 {
305  struct Pattern *p = NULL;
306 
307  SLIST_FOREACH(p, pat, entries)
308  {
309  if (!mutt_pattern_alias_exec(p, flags, av, cache))
310  {
311  return false;
312  }
313  }
314  return true;
315 }
316 
327 static int perform_or(struct PatternList *pat, PatternExecFlags flags,
328  struct Mailbox *m, struct Email *e, struct Message *msg,
329  struct PatternCache *cache)
330 {
331  struct Pattern *p = NULL;
332 
333  SLIST_FOREACH(p, pat, entries)
334  {
335  if (pattern_exec(p, flags, m, e, msg, cache))
336  {
337  return true;
338  }
339  }
340  return false;
341 }
342 
351 static int perform_alias_or(struct PatternList *pat, PatternExecFlags flags,
352  struct AliasView *av, struct PatternCache *cache)
353 {
354  struct Pattern *p = NULL;
355 
356  SLIST_FOREACH(p, pat, entries)
357  {
358  if (mutt_pattern_alias_exec(p, flags, av, cache))
359  {
360  return true;
361  }
362  }
363  return false;
364 }
365 
376 static int match_addrlist(struct Pattern *pat, bool match_personal, int n, ...)
377 {
378  va_list ap;
379 
380  va_start(ap, n);
381  for (; n; n--)
382  {
383  struct AddressList *al = va_arg(ap, struct AddressList *);
384  struct Address *a = NULL;
385  TAILQ_FOREACH(a, al, entries)
386  {
387  if (pat->all_addr ^ ((!pat->is_alias || alias_reverse_lookup(a)) &&
388  ((a->mailbox && patmatch(pat, a->mailbox)) ||
389  (match_personal && a->personal && patmatch(pat, a->personal)))))
390  {
391  va_end(ap);
392  return !pat->all_addr; /* Found match, or non-match if all_addr */
393  }
394  }
395  }
396  va_end(ap);
397  return pat->all_addr; /* No matches, or all matches if all_addr */
398 }
399 
406 static bool match_reference(struct Pattern *pat, struct ListHead *refs)
407 {
408  struct ListNode *np = NULL;
409  STAILQ_FOREACH(np, refs, entries)
410  {
411  if (patmatch(pat, np->data))
412  return true;
413  }
414  return false;
415 }
416 
428 static int mutt_is_predicate_recipient(bool all_addr, struct Envelope *e, addr_predicate_t p)
429 {
430  struct AddressList *als[] = { &e->to, &e->cc };
431  for (size_t i = 0; i < mutt_array_size(als); ++i)
432  {
433  struct AddressList *al = als[i];
434  struct Address *a = NULL;
435  TAILQ_FOREACH(a, al, entries)
436  {
437  if (all_addr ^ p(a))
438  return !all_addr;
439  }
440  }
441  return all_addr;
442 }
443 
452 int mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *e)
453 {
455 }
456 
465 int mutt_is_list_recipient(bool all_addr, struct Envelope *e)
466 {
467  return mutt_is_predicate_recipient(all_addr, e, &mutt_is_mail_list);
468 }
469 
479 static int match_user(int all_addr, struct AddressList *al1, struct AddressList *al2)
480 {
481  struct Address *a = NULL;
482  if (al1)
483  {
484  TAILQ_FOREACH(a, al1, entries)
485  {
486  if (all_addr ^ mutt_addr_is_user(a))
487  return !all_addr;
488  }
489  }
490 
491  if (al2)
492  {
493  TAILQ_FOREACH(a, al2, entries)
494  {
495  if (all_addr ^ mutt_addr_is_user(a))
496  return !all_addr;
497  }
498  }
499  return all_addr;
500 }
501 
515 static int match_threadcomplete(struct PatternList *pat, PatternExecFlags flags,
516  struct Mailbox *m, struct MuttThread *t,
517  int left, int up, int right, int down)
518 {
519  if (!t)
520  return 0;
521 
522  int a;
523  struct Email *e = t->message;
524  if (e)
525  if (mutt_pattern_exec(SLIST_FIRST(pat), flags, m, e, NULL))
526  return 1;
527 
528  if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
529  return a;
530  if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
531  {
532  return a;
533  }
534  if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
535  {
536  return a;
537  }
538  if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
539  return a;
540  return 0;
541 }
542 
553 static int match_threadparent(struct PatternList *pat, PatternExecFlags flags,
554  struct Mailbox *m, struct MuttThread *t)
555 {
556  if (!t || !t->parent || !t->parent->message)
557  return 0;
558 
559  return mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->parent->message, NULL);
560 }
561 
572 static int match_threadchildren(struct PatternList *pat, PatternExecFlags flags,
573  struct Mailbox *m, struct MuttThread *t)
574 {
575  if (!t || !t->child)
576  return 0;
577 
578  for (t = t->child; t; t = t->next)
579  if (t->message && mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->message, NULL))
580  return 1;
581 
582  return 0;
583 }
584 
592 static bool match_content_type(const struct Pattern *pat, struct Body *b)
593 {
594  if (!b)
595  return false;
596 
597  char buf[256];
598  snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
599 
600  if (patmatch(pat, buf))
601  return true;
602  if (match_content_type(pat, b->parts))
603  return true;
604  if (match_content_type(pat, b->next))
605  return true;
606  return false;
607 }
608 
617 static bool match_mime_content_type(const struct Pattern *pat, struct Email *e, FILE *fp)
618 {
620  return match_content_type(pat, e->body);
621 }
622 
629 static bool match_update_dynamic_date(struct Pattern *pat)
630 {
631  struct Buffer *err = mutt_buffer_pool_get();
632 
633  bool rc = eval_date_minmax(pat, pat->p.str, err);
635 
636  return rc;
637 }
638 
646 static void set_pattern_cache_value(int *cache_entry, int value)
647 {
648  *cache_entry = (value != 0) ? 2 : 1;
649 }
650 
657 static int get_pattern_cache_value(int cache_entry)
658 {
659  return cache_entry == 2;
660 }
661 
667 static int is_pattern_cache_set(int cache_entry)
668 {
669  return cache_entry != 0;
670 }
671 
680 static int msg_search_sendmode(struct Email *e, struct Pattern *pat)
681 {
682  bool match = false;
683  char *buf = NULL;
684  size_t blen = 0;
685  FILE *fp = NULL;
686 
687  if ((pat->op == MUTT_PAT_HEADER) || (pat->op == MUTT_PAT_WHOLE_MSG))
688  {
689  struct Buffer *tempfile = mutt_buffer_pool_get();
690  mutt_buffer_mktemp(tempfile);
691  fp = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
692  if (!fp)
693  {
694  mutt_perror(mutt_buffer_string(tempfile));
695  mutt_buffer_pool_release(&tempfile);
696  return 0;
697  }
698 
700  false, false, NeoMutt->sub);
701  fflush(fp);
702  fseek(fp, 0, 0);
703 
704  while ((buf = mutt_file_read_line(buf, &blen, fp, NULL, MUTT_RL_NO_FLAGS)) != NULL)
705  {
706  if (patmatch(pat, buf) == 0)
707  {
708  match = true;
709  break;
710  }
711  }
712 
713  FREE(&buf);
714  mutt_file_fclose(&fp);
715  unlink(mutt_buffer_string(tempfile));
716  mutt_buffer_pool_release(&tempfile);
717 
718  if (match)
719  return match;
720  }
721 
722  if ((pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_WHOLE_MSG))
723  {
724  fp = mutt_file_fopen(e->body->filename, "r");
725  if (!fp)
726  {
728  return 0;
729  }
730 
731  while ((buf = mutt_file_read_line(buf, &blen, fp, NULL, MUTT_RL_NO_FLAGS)) != NULL)
732  {
733  if (patmatch(pat, buf) == 0)
734  {
735  match = true;
736  break;
737  }
738  }
739 
740  FREE(&buf);
741  mutt_file_fclose(&fp);
742  }
743 
744  return match;
745 }
746 
754 static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
755 {
756  if ((pat->op == MUTT_PAT_MIMETYPE) || (pat->op == MUTT_PAT_MIMEATTACH))
757  {
758  return true;
759  }
760 
761  if ((pat->op == MUTT_PAT_WHOLE_MSG) || (pat->op == MUTT_PAT_BODY) || (pat->op == MUTT_PAT_HEADER))
762  {
763 #ifdef USE_IMAP
764  return !((m->type == MUTT_IMAP) && pat->string_match);
765 #else
766  return true;
767 #endif
768  }
769 
770  if ((pat->op == MUTT_PAT_AND) || (pat->op == MUTT_PAT_OR))
771  {
772  struct Pattern *p = NULL;
773  SLIST_FOREACH(p, pat->child, entries)
774  {
775  if (pattern_needs_msg(m, p))
776  {
777  return true;
778  }
779  }
780  }
781 
782  return false;
783 }
784 
800 static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags,
801  struct Mailbox *m, struct Email *e,
802  struct Message *msg, struct PatternCache *cache)
803 {
804  switch (pat->op)
805  {
806  case MUTT_PAT_AND:
807  return pat->pat_not ^ (perform_and(pat->child, flags, m, e, msg, cache) > 0);
808  case MUTT_PAT_OR:
809  return pat->pat_not ^ (perform_or(pat->child, flags, m, e, msg, cache) > 0);
810  case MUTT_PAT_THREAD:
811  return pat->pat_not ^
812  match_threadcomplete(pat->child, flags, m, e->thread, 1, 1, 1, 1);
813  case MUTT_PAT_PARENT:
814  return pat->pat_not ^ match_threadparent(pat->child, flags, m, e->thread);
815  case MUTT_PAT_CHILDREN:
816  return pat->pat_not ^ match_threadchildren(pat->child, flags, m, e->thread);
817  case MUTT_ALL:
818  return !pat->pat_not;
819  case MUTT_EXPIRED:
820  return pat->pat_not ^ e->expired;
821  case MUTT_SUPERSEDED:
822  return pat->pat_not ^ e->superseded;
823  case MUTT_FLAG:
824  return pat->pat_not ^ e->flagged;
825  case MUTT_TAG:
826  return pat->pat_not ^ e->tagged;
827  case MUTT_NEW:
828  return pat->pat_not ? e->old || e->read : !(e->old || e->read);
829  case MUTT_UNREAD:
830  return pat->pat_not ? e->read : !e->read;
831  case MUTT_REPLIED:
832  return pat->pat_not ^ e->replied;
833  case MUTT_OLD:
834  return pat->pat_not ? (!e->old || e->read) : (e->old && !e->read);
835  case MUTT_READ:
836  return pat->pat_not ^ e->read;
837  case MUTT_DELETED:
838  return pat->pat_not ^ e->deleted;
839  case MUTT_PAT_MESSAGE:
840  return pat->pat_not ^ ((EMSG(e) >= pat->min) && (EMSG(e) <= pat->max));
841  case MUTT_PAT_DATE:
842  if (pat->dynamic)
844  return pat->pat_not ^ (e->date_sent >= pat->min && e->date_sent <= pat->max);
846  if (pat->dynamic)
848  return pat->pat_not ^ (e->received >= pat->min && e->received <= pat->max);
849  case MUTT_PAT_BODY:
850  case MUTT_PAT_HEADER:
851  case MUTT_PAT_WHOLE_MSG:
852  if (pat->sendmode)
853  {
854  if (!e->body || !e->body->filename)
855  return false;
856  return pat->pat_not ^ msg_search_sendmode(e, pat);
857  }
858  /* m can be NULL in certain cases, such as when replying to a message
859  * from the attachment menu and the user has a reply-hook using "~e".
860  * This is also the case when message scoring. */
861  if (!m)
862  return false;
863 #ifdef USE_IMAP
864  /* IMAP search sets e->matched at search compile time */
865  if ((m->type == MUTT_IMAP) && pat->string_match)
866  return e->matched;
867 #endif
868  return pat->pat_not ^ msg_search(pat, e, msg);
870 #ifdef USE_IMAP
871  if (!m)
872  return false;
873  if (m->type == MUTT_IMAP)
874  {
875  return (pat->string_match) ? e->matched : false;
876  }
877 #endif
878  mutt_error(_("error: server custom search only supported with IMAP"));
879  return false;
880  case MUTT_PAT_SENDER:
881  if (!e->env)
882  return false;
883  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
884  1, &e->env->sender);
885  case MUTT_PAT_FROM:
886  if (!e->env)
887  return false;
888  return pat->pat_not ^
889  match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->from);
890  case MUTT_PAT_TO:
891  if (!e->env)
892  return false;
893  return pat->pat_not ^
894  match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->to);
895  case MUTT_PAT_CC:
896  if (!e->env)
897  return false;
898  return pat->pat_not ^
899  match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->cc);
900  case MUTT_PAT_SUBJECT:
901  if (!e->env)
902  return false;
903  return pat->pat_not ^ (e->env->subject && patmatch(pat, e->env->subject));
904  case MUTT_PAT_ID:
906  if (!e->env)
907  return false;
908  return pat->pat_not ^ (e->env->message_id && patmatch(pat, e->env->message_id));
909  case MUTT_PAT_SCORE:
910  return pat->pat_not ^ (e->score >= pat->min &&
911  (pat->max == MUTT_MAXRANGE || e->score <= pat->max));
912  case MUTT_PAT_SIZE:
913  return pat->pat_not ^ (e->body->length >= pat->min &&
914  (pat->max == MUTT_MAXRANGE || e->body->length <= pat->max));
915  case MUTT_PAT_REFERENCE:
916  if (!e->env)
917  return false;
918  return pat->pat_not ^ (match_reference(pat, &e->env->references) ||
919  match_reference(pat, &e->env->in_reply_to));
920  case MUTT_PAT_ADDRESS:
921  if (!e->env)
922  return false;
923  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
924  4, &e->env->from, &e->env->sender,
925  &e->env->to, &e->env->cc);
926  case MUTT_PAT_RECIPIENT:
927  if (!e->env)
928  return false;
929  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
930  2, &e->env->to, &e->env->cc);
931  case MUTT_PAT_LIST: /* known list, subscribed or not */
932  {
933  if (!e->env)
934  return false;
935 
936  int result;
937  if (cache)
938  {
939  int *cache_entry = pat->all_addr ? &cache->list_all : &cache->list_one;
940  if (!is_pattern_cache_set(*cache_entry))
941  {
942  set_pattern_cache_value(cache_entry,
944  }
945  result = get_pattern_cache_value(*cache_entry);
946  }
947  else
948  result = mutt_is_list_recipient(pat->all_addr, e->env);
949  return pat->pat_not ^ result;
950  }
952  {
953  if (!e->env)
954  return false;
955 
956  int result;
957  if (cache)
958  {
959  int *cache_entry = pat->all_addr ? &cache->sub_all : &cache->sub_one;
960  if (!is_pattern_cache_set(*cache_entry))
961  {
963  cache_entry, mutt_is_subscribed_list_recipient(pat->all_addr, e->env));
964  }
965  result = get_pattern_cache_value(*cache_entry);
966  }
967  else
969  return pat->pat_not ^ result;
970  }
972  {
973  if (!e->env)
974  return false;
975 
976  int result;
977  if (cache)
978  {
979  int *cache_entry = pat->all_addr ? &cache->pers_recip_all : &cache->pers_recip_one;
980  if (!is_pattern_cache_set(*cache_entry))
981  {
983  cache_entry, match_user(pat->all_addr, &e->env->to, &e->env->cc));
984  }
985  result = get_pattern_cache_value(*cache_entry);
986  }
987  else
988  result = match_user(pat->all_addr, &e->env->to, &e->env->cc);
989  return pat->pat_not ^ result;
990  }
992  {
993  if (!e->env)
994  return false;
995 
996  int result;
997  if (cache)
998  {
999  int *cache_entry = pat->all_addr ? &cache->pers_from_all : &cache->pers_from_one;
1000  if (!is_pattern_cache_set(*cache_entry))
1001  {
1002  set_pattern_cache_value(cache_entry,
1003  match_user(pat->all_addr, &e->env->from, NULL));
1004  }
1005  result = get_pattern_cache_value(*cache_entry);
1006  }
1007  else
1008  result = match_user(pat->all_addr, &e->env->from, NULL);
1009  return pat->pat_not ^ result;
1010  }
1011  case MUTT_PAT_COLLAPSED:
1012  return pat->pat_not ^ (e->collapsed && e->num_hidden > 1);
1013  case MUTT_PAT_CRYPT_SIGN:
1014  if (!WithCrypto)
1015  {
1017  return false;
1018  }
1019  return pat->pat_not ^ ((e->security & SEC_SIGN) ? 1 : 0);
1021  if (!WithCrypto)
1022  {
1024  return false;
1025  }
1026  return pat->pat_not ^ ((e->security & SEC_GOODSIGN) ? 1 : 0);
1028  if (!WithCrypto)
1029  {
1031  return false;
1032  }
1033  return pat->pat_not ^ ((e->security & SEC_ENCRYPT) ? 1 : 0);
1034  case MUTT_PAT_PGP_KEY:
1035  if (!(WithCrypto & APPLICATION_PGP))
1036  {
1038  return false;
1039  }
1040  return pat->pat_not ^ ((e->security & PGP_KEY) == PGP_KEY);
1041  case MUTT_PAT_XLABEL:
1042  if (!e->env)
1043  return false;
1044  return pat->pat_not ^ (e->env->x_label && patmatch(pat, e->env->x_label));
1045  case MUTT_PAT_DRIVER_TAGS:
1046  {
1047  char *tags = driver_tags_get(&e->tags);
1048  const bool rc = (pat->pat_not ^ (tags && patmatch(pat, tags)));
1049  FREE(&tags);
1050  return rc;
1051  }
1052  case MUTT_PAT_HORMEL:
1053  if (!e->env)
1054  return false;
1055  return pat->pat_not ^ (e->env->spam.data && patmatch(pat, e->env->spam.data));
1056  case MUTT_PAT_DUPLICATED:
1057  return pat->pat_not ^ (e->thread && e->thread->duplicate_thread);
1058  case MUTT_PAT_MIMEATTACH:
1059  if (!m)
1060  return false;
1061  {
1062  int count = mutt_count_body_parts(m, e, msg->fp);
1063  return pat->pat_not ^ (count >= pat->min &&
1064  (pat->max == MUTT_MAXRANGE || count <= pat->max));
1065  }
1066  case MUTT_PAT_MIMETYPE:
1067  if (!m)
1068  return false;
1069  return pat->pat_not ^ match_mime_content_type(pat, e, msg->fp);
1070  case MUTT_PAT_UNREFERENCED:
1071  return pat->pat_not ^ (e->thread && !e->thread->child);
1072  case MUTT_PAT_BROKEN:
1073  return pat->pat_not ^ (e->thread && e->thread->fake_thread);
1074 #ifdef USE_NNTP
1075  case MUTT_PAT_NEWSGROUPS:
1076  if (!e->env)
1077  return false;
1078  return pat->pat_not ^ (e->env->newsgroups && patmatch(pat, e->env->newsgroups));
1079 #endif
1080  }
1081  mutt_error(_("error: unknown op %d (report this error)"), pat->op);
1082  return false;
1083 }
1084 
1100  struct Mailbox *m, struct Email *e, struct PatternCache *cache)
1101 {
1102  const bool needs_msg = pattern_needs_msg(m, pat);
1103  struct Message *msg = needs_msg ? mx_msg_open(m, e->msgno) : NULL;
1104  if (needs_msg && !msg)
1105  {
1106  return false;
1107  }
1108  const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1109  mx_msg_close(m, &msg);
1110  return matched;
1111 }
1112 
1127  struct AliasView *av, struct PatternCache *cache)
1128 {
1129  switch (pat->op)
1130  {
1131  case MUTT_PAT_FROM: /* alias */
1132  if (!av->alias)
1133  return false;
1134  return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1135  case MUTT_PAT_CC: /* comment */
1136  if (!av->alias)
1137  return false;
1138  return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1139  case MUTT_PAT_TO: /* alias address list */
1140  if (!av->alias)
1141  return false;
1142  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1143  1, &av->alias->addr);
1144  case MUTT_PAT_AND:
1145  return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1146  case MUTT_PAT_OR:
1147  return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1148  }
1149 
1150  return false;
1151 }
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:562
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:593
int mutt_count_body_parts(struct Mailbox *m, struct Email *e, FILE *fp)
Count the MIME Body parts.
Definition: attachments.c:253
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:499
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:423
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:135
Structs that make up an email.
static int mutt_is_predicate_recipient(bool all_addr, struct Envelope *e, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition: exec.c:428
static int get_pattern_cache_value(int cache_entry)
Get pattern cache value.
Definition: exec.c:657
static int match_user(int all_addr, struct AddressList *al1, struct AddressList *al2)
Matches the user's email Address.
Definition: exec.c:479
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:754
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:515
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:1126
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:553
static bool match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment's Content-Type.
Definition: exec.c:592
int mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *e)
Matches subscribed mailing lists.
Definition: exec.c:452
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:302
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:617
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:572
static bool match_reference(struct Pattern *pat, struct ListHead *refs)
Match references against a Pattern.
Definition: exec.c:406
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:376
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:667
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:351
int mutt_is_list_recipient(bool all_addr, struct Envelope *e)
Matches known mailing lists.
Definition: exec.c:465
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:327
static bool match_update_dynamic_date(struct Pattern *pat)
Update a dynamic date pattern.
Definition: exec.c:629
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:278
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:800
static void set_pattern_cache_value(int *cache_entry, int value)
Sets a value in the PatternCache cache entry.
Definition: exec.c:646
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:1099
static int msg_search_sendmode(struct Email *e, struct Pattern *pat)
Search in send-mode.
Definition: exec.c:680
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
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:671
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
#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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
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:53
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:40
#define mutt_array_size(x)
Definition: memory.h:33
#define TYPE(body)
Definition: mime.h:89
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
Many unsorted constants and some structs.
@ MUTT_ALL
All messages.
Definition: mutt.h:87
@ MUTT_SUPERSEDED
Superseded messages.
Definition: mutt.h:103
@ MUTT_EXPIRED
Expired messages.
Definition: mutt.h:102
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:92
@ MUTT_OLD
Old messages.
Definition: mutt.h:90
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:99
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:98
@ MUTT_DELETED
Deleted messages.
Definition: mutt.h:97
@ MUTT_NEW
New messages.
Definition: mutt.h:89
@ MUTT_UNREAD
Unread messages.
Definition: mutt.h:93
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:91
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:1189
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1143
API for mailboxes.
API for encryption/signing of emails.
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:77
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
#define PGP_KEY
Definition: lib.h:96
#define WithCrypto
Definition: lib.h:113
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
char * mutt_rfc822_read_line(FILE *fp, char *line, size_t *linelen)
Read a header line from a file.
Definition: parse.c:1093
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:144
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition: lib.h:146
@ MUTT_PAT_BROKEN
Message is part of a broken thread.
Definition: lib.h:140
@ MUTT_PAT_ID_EXTERNAL
Message-Id is among results from an external query.
Definition: lib.h:142
@ MUTT_PAT_OR
Either pattern can match.
Definition: lib.h:127
@ MUTT_PAT_CHILDREN
Pattern matches a child email.
Definition: lib.h:130
@ MUTT_PAT_PARENT
Pattern matches parent.
Definition: lib.h:129
@ MUTT_PAT_REFERENCE
Pattern matches 'References:' or 'In-Reply-To:' field.
Definition: lib.h:151
@ MUTT_PAT_FROM
Pattern matches 'From:' field.
Definition: lib.h:135
@ MUTT_PAT_DRIVER_TAGS
Pattern matches message tags.
Definition: lib.h:164
@ MUTT_PAT_COLLAPSED
Thread is collapsed.
Definition: lib.h:133
@ MUTT_PAT_CRYPT_VERIFIED
Message is crypographically verified.
Definition: lib.h:159
@ MUTT_PAT_HORMEL
Pattern matches email's spam score.
Definition: lib.h:145
@ MUTT_PAT_SUBJECT
Pattern matches 'Subject:' field.
Definition: lib.h:134
@ MUTT_PAT_LIST
Email is on mailing list.
Definition: lib.h:153
@ MUTT_PAT_NEWSGROUPS
Pattern matches newsgroup.
Definition: lib.h:168
@ MUTT_PAT_PERSONAL_RECIP
Email is addressed to the user.
Definition: lib.h:155
@ MUTT_PAT_CC
Pattern matches 'Cc:' field.
Definition: lib.h:132
@ MUTT_PAT_SUBSCRIBED_LIST
Email is on subscribed mailing list.
Definition: lib.h:154
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition: lib.h:163
@ MUTT_PAT_RECIPIENT
User is a recipient of the email.
Definition: lib.h:152
@ MUTT_PAT_CRYPT_ENCRYPT
Message is encrypted.
Definition: lib.h:160
@ MUTT_PAT_UNREFERENCED
Message is unreferenced in the thread.
Definition: lib.h:139
@ MUTT_PAT_CRYPT_SIGN
Message is signed.
Definition: lib.h:158
@ MUTT_PAT_MESSAGE
Pattern matches message number.
Definition: lib.h:148
@ MUTT_PAT_AND
Both patterns must match.
Definition: lib.h:126
@ MUTT_PAT_DATE
Pattern matches 'Date:' field.
Definition: lib.h:136
@ MUTT_PAT_XLABEL
Pattern matches keyword/label.
Definition: lib.h:162
@ MUTT_PAT_SCORE
Pattern matches email's score.
Definition: lib.h:149
@ MUTT_PAT_MIMEATTACH
Pattern matches number of attachments.
Definition: lib.h:165
@ MUTT_PAT_DUPLICATED
Duplicate message.
Definition: lib.h:138
@ MUTT_PAT_PERSONAL_FROM
Email is from the user.
Definition: lib.h:156
@ MUTT_PAT_TO
Pattern matches 'To:' field.
Definition: lib.h:131
@ MUTT_PAT_SENDER
Pattern matches sender.
Definition: lib.h:147
@ MUTT_PAT_DATE_RECEIVED
Pattern matches date received.
Definition: lib.h:137
@ MUTT_PAT_ADDRESS
Pattern matches any address field.
Definition: lib.h:157
@ MUTT_PAT_MIMETYPE
Pattern matches MIME type.
Definition: lib.h:166
@ MUTT_PAT_PGP_KEY
Message has PGP key.
Definition: lib.h:161
@ MUTT_PAT_ID
Pattern matches email's Message-Id.
Definition: lib.h:141
@ MUTT_PAT_THREAD
Pattern matches email thread.
Definition: lib.h:128
@ MUTT_PAT_SIZE
Pattern matches email's size.
Definition: lib.h:150
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition: lib.h:143
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:95
uint8_t PatternExecFlags
Flags for mutt_pattern_exec(), e.g. MUTT_MATCH_FULL_ADDRESS.
Definition: lib.h:93
#define MUTT_MAXRANGE
Definition: private.h:119
#define EMSG(e)
Definition: private.h:117
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.
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
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:35
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:71
LOFF_T offset
offset where the actual data begins
Definition: body.h:51
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
struct Body * next
next attachment in the list
Definition: body.h:70
char * subtype
content-type subtype
Definition: body.h:59
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:57
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:55
struct AddressList to
Email's 'To' list.
Definition: envelope.h:58
char * message_id
Message ID.
Definition: envelope.h:71
char * newsgroups
List of newsgroups.
Definition: envelope.h:77
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:59
struct AddressList sender
Email's sender.
Definition: envelope.h:61
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
char * subject
Email's subject.
Definition: envelope.h:68
char * x_label
X-Label.
Definition: envelope.h:74
struct AddressList from
Email's 'From' list.
Definition: envelope.h:57
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
A mailbox.
Definition: mailbox.h:82
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
A local copy of an email.
Definition: mxapi.h:42
FILE * fp
pointer to the message data
Definition: mxapi.h:43
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:106
int pers_recip_all
^~p
Definition: lib.h:111
int list_one
~l
Definition: lib.h:108
int pers_from_one
~P
Definition: lib.h:114
int list_all
^~l
Definition: lib.h:107
int sub_all
^~u
Definition: lib.h:109
int pers_recip_one
~p
Definition: lib.h:112
int pers_from_all
^~P
Definition: lib.h:113
int sub_one
~u
Definition: lib.h:110
Mapping between user character and internal constant.
Definition: private.h:50
int tag
Character used to represent this operation, e.g. 'A' for '~A'.
Definition: private.h:51
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition: private.h:52
A simple (non-regex) pattern.
Definition: lib.h:69
bool group_match
Check a group of Addresses.
Definition: lib.h:74
union Pattern::@1 p
int max
Maximum for range checks.
Definition: lib.h:81
bool all_addr
All Addresses in the list must match.
Definition: lib.h:72
struct Group * group
Address group if group_match is set.
Definition: lib.h:85
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:82
bool string_match
Check a string for a match.
Definition: lib.h:73
regex_t * regex
Compiled regex, for non-pattern matching.
Definition: lib.h:84
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition: lib.h:87
char * str
String, if string_match is set.
Definition: lib.h:86
bool is_alias
Is there an alias for this Address?
Definition: lib.h:76
bool ign_case
Ignore case for local string_match searches.
Definition: lib.h:75
bool dynamic
Evaluate date ranges at run time.
Definition: lib.h:77
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:70
bool sendmode
Evaluate searches in send-mode.
Definition: lib.h:78
bool is_multi
Multiple case (only for ~I pattern now)
Definition: lib.h:79
int min
Minimum for range checks.
Definition: lib.h:80
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:71
Keep track when processing files.
Definition: state.h:45
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
char * driver_tags_get(struct TagList *list)
Get tags.
Definition: tags.c:145