NeoMutt  2018-07-16 +2481-68dcde
Teaching an old dog new tricks
DOXYGEN
mutt_parse.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <regex.h>
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include "mutt/mutt.h"
34 #include "email/lib.h"
35 #include "mutt.h"
36 #include "mutt_parse.h"
37 #include "globals.h"
38 #include "mx.h"
39 #include "ncrypt/ncrypt.h"
40 
41 #define MUTT_PARTS_TOPLEVEL (1 << 0) /* is the top-level part */
42 
48 void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
49 {
50  do
51  {
52  if ((e->content->type != TYPE_MESSAGE) && (e->content->type != TYPE_MULTIPART))
53  break; /* nothing to do */
54 
55  if (e->content->parts)
56  break; /* The message was parsed earlier. */
57 
58  struct Message *msg = mx_msg_open(m, e->msgno);
59  if (msg)
60  {
61  mutt_parse_part(msg->fp, e->content);
62 
63  if (WithCrypto)
64  e->security = crypt_query(e->content);
65 
66  mx_msg_close(m, &msg);
67  }
68  } while (false);
69 
70  e->attach_valid = false;
71 }
72 
80 static bool count_body_parts_check(struct ListHead *checklist, struct Body *b, bool dflt)
81 {
82  struct AttachMatch *a = NULL;
83 
84  /* If list is null, use default behavior. */
85  if (!checklist || STAILQ_EMPTY(checklist))
86  {
87  return false;
88  }
89 
90  struct ListNode *np = NULL;
91  STAILQ_FOREACH(np, checklist, entries)
92  {
93  a = (struct AttachMatch *) np->data;
94  mutt_debug(LL_DEBUG3, "%s %d/%s ?? %s/%s [%d]... ", dflt ? "[OK] " : "[EXCL] ",
95  b->type, b->subtype ? b->subtype : "*", a->major, a->minor, a->major_int);
96  if (((a->major_int == TYPE_ANY) || (a->major_int == b->type)) &&
97  (!b->subtype || !regexec(&a->minor_regex, b->subtype, 0, NULL, 0)))
98  {
99  mutt_debug(LL_DEBUG3, "yes\n");
100  return true;
101  }
102  else
103  {
104  mutt_debug(LL_DEBUG3, "no\n");
105  }
106  }
107 
108  return false;
109 }
110 
117 static int count_body_parts(struct Body *body, int flags)
118 {
119  if (!body)
120  return 0;
121 
122  int count = 0;
123 
124  for (struct Body *bp = body; bp; bp = bp->next)
125  {
126  /* Initial disposition is to count and not to recurse this part. */
127  bool shallcount = true; /* default */
128  bool shallrecurse = false;
129 
130  mutt_debug(LL_DEBUG5, "desc=\"%s\"; fn=\"%s\", type=\"%d/%s\"\n",
131  bp->description ? bp->description : ("none"),
132  bp->filename ? bp->filename : bp->d_filename ? bp->d_filename : "(none)",
133  bp->type, bp->subtype ? bp->subtype : "*");
134 
135  if (bp->type == TYPE_MESSAGE)
136  {
137  shallrecurse = true;
138 
139  /* If it's an external body pointer, don't recurse it. */
140  if (mutt_str_strcasecmp(bp->subtype, "external-body") == 0)
141  shallrecurse = false;
142 
143  /* Don't count containers if they're top-level. */
144  if (flags & MUTT_PARTS_TOPLEVEL)
145  shallcount = false; // top-level message/*
146  }
147  else if (bp->type == TYPE_MULTIPART)
148  {
149  /* Always recurse multiparts, except multipart/alternative. */
150  shallrecurse = true;
151  if (mutt_str_strcasecmp(bp->subtype, "alternative") == 0)
152  shallrecurse = false;
153 
154  /* Don't count containers if they're top-level. */
155  if (flags & MUTT_PARTS_TOPLEVEL)
156  shallcount = false; /* top-level multipart */
157  }
158 
159  if ((bp->disposition == DISP_INLINE) && (bp->type != TYPE_MULTIPART) &&
160  (bp->type != TYPE_MESSAGE) && (bp == body))
161  {
162  shallcount = false; /* ignore fundamental inlines */
163  }
164 
165  /* If this body isn't scheduled for enumeration already, don't bother
166  * profiling it further. */
167  if (shallcount)
168  {
169  /* Turn off shallcount if message type is not in ok list,
170  * or if it is in except list. Check is done separately for
171  * inlines vs. attachments. */
172 
173  if (bp->disposition == DISP_ATTACH)
174  {
175  if (!count_body_parts_check(&AttachAllow, bp, true))
176  shallcount = false; /* attach not allowed */
177  if (count_body_parts_check(&AttachExclude, bp, false))
178  shallcount = false; /* attach excluded */
179  }
180  else
181  {
182  if (!count_body_parts_check(&InlineAllow, bp, true))
183  shallcount = false; /* inline not allowed */
184  if (count_body_parts_check(&InlineExclude, bp, false))
185  shallcount = false; /* excluded */
186  }
187  }
188 
189  if (shallcount)
190  count++;
191  bp->attach_qualifies = shallcount;
192 
193  mutt_debug(LL_DEBUG3, "%p shallcount = %d\n", (void *) bp, shallcount);
194 
195  if (shallrecurse)
196  {
197  mutt_debug(LL_DEBUG3, "%p pre count = %d\n", (void *) bp, count);
198  bp->attach_count = count_body_parts(bp->parts, flags & ~MUTT_PARTS_TOPLEVEL);
199  count += bp->attach_count;
200  mutt_debug(LL_DEBUG3, "%p post count = %d\n", (void *) bp, count);
201  }
202  }
203 
204  mutt_debug(LL_DEBUG3, "return %d\n", (count < 0) ? 0 : count);
205  return (count < 0) ? 0 : count;
206 }
207 
214 int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
215 {
216  bool keep_parts = false;
217 
218  if (e->attach_valid)
219  return e->attach_total;
220 
221  if (e->content->parts)
222  keep_parts = true;
223  else
225 
226  if (!STAILQ_EMPTY(&AttachAllow) || !STAILQ_EMPTY(&AttachExclude) ||
227  !STAILQ_EMPTY(&InlineAllow) || !STAILQ_EMPTY(&InlineExclude))
228  {
230  }
231  else
232  e->attach_total = 0;
233 
234  e->attach_valid = true;
235 
236  if (!keep_parts)
238 
239  return e->attach_total;
240 }
static bool count_body_parts_check(struct ListHead *checklist, struct Body *b, bool dflt)
Compares mime types to the ok and except lists.
Definition: mutt_parse.c:80
Miscellaneous email parsing routines.
The envelope/body of an email.
Definition: email.h:39
Structs that make up an email.
struct Body * content
List of MIME parts.
Definition: email.h:92
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:48
enum ContentType major_int
Definition: mutt.h:134
#define MUTT_PARTS_TOPLEVEL
Definition: mutt_parse.c:41
struct Body * next
next attachment in the list
Definition: body.h:53
Type: &#39;*&#39; or &#39;.*&#39;.
Definition: mime.h:40
The body of an email.
Definition: body.h:34
Hundreds of global variables to back the user variables.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1087
API for mailboxes.
Content is attached.
Definition: mime.h:63
const char * major
Definition: mutt.h:133
short attach_total
Number of qualifying attachments in message, if attach_valid.
Definition: email.h:98
char * subtype
content-type subtype
Definition: body.h:37
static int count_body_parts(struct Body *body, int flags)
Count the MIME Body parts.
Definition: mutt_parse.c:117
A local copy of an email.
Definition: mx.h:81
A mailbox.
Definition: mailbox.h:92
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
bool attach_valid
true when the attachment count is valid
Definition: email.h:72
API for encryption/signing of emails.
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:41
unsigned int type
content-type primary type
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1398
char * data
String.
Definition: list.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
regex_t minor_regex
Definition: mutt.h:136
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
FILE * fp
pointer to the message data
Definition: mx.h:83
#define STAILQ_EMPTY(head)
Definition: queue.h:346
int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
Count the MIME Body parts.
Definition: mutt_parse.c:214
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
An attachment matching a regex.
Definition: mutt.h:131
Log at debug level 5.
Definition: logging.h:60
A List node for strings.
Definition: list.h:33
Content is inline.
Definition: mime.h:62
const char * minor
Definition: mutt.h:135
#define WithCrypto
Definition: ncrypt.h:160
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:696
Convenience wrapper for the library headers.
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1039
Log at debug level 3.
Definition: logging.h:58
int msgno
Number displayed to the user.
Definition: email.h:88