NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
mutt_parse.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include "mutt/lib.h"
33 #include "email/lib.h"
34 #include "mutt_parse.h"
35 #include "ncrypt/lib.h"
36 #include "mutt_globals.h"
37 #include "mx.h"
38 
43 
49 void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
50 {
51  do
52  {
53  if ((e->body->type != TYPE_MESSAGE) && (e->body->type != TYPE_MULTIPART))
54  break; /* nothing to do */
55 
56  if (e->body->parts)
57  break; /* The message was parsed earlier. */
58 
59  struct Message *msg = mx_msg_open(m, e->msgno);
60  if (msg)
61  {
62  mutt_parse_part(msg->fp, e->body);
63 
64  if (WithCrypto)
65  e->security = crypt_query(e->body);
66 
67  mx_msg_close(m, &msg);
68  }
69  } while (false);
70 
71  e->attach_valid = false;
72 }
73 
81 static bool count_body_parts_check(struct ListHead *checklist, struct Body *b, bool dflt)
82 {
83  struct AttachMatch *a = NULL;
84 
85  /* If list is null, use default behavior. */
86  if (!checklist || STAILQ_EMPTY(checklist))
87  {
88  return false;
89  }
90 
91  struct ListNode *np = NULL;
92  STAILQ_FOREACH(np, checklist, entries)
93  {
94  a = (struct AttachMatch *) np->data;
95  mutt_debug(LL_DEBUG3, "%s %d/%s ?? %s/%s [%d]... ", dflt ? "[OK] " : "[EXCL] ",
96  b->type, b->subtype ? b->subtype : "*", a->major, a->minor, a->major_int);
97  if (((a->major_int == TYPE_ANY) || (a->major_int == b->type)) &&
98  (!b->subtype || (regexec(&a->minor_regex, b->subtype, 0, NULL, 0) == 0)))
99  {
100  mutt_debug(LL_DEBUG3, "yes\n");
101  return true;
102  }
103  else
104  {
105  mutt_debug(LL_DEBUG3, "no\n");
106  }
107  }
108 
109  return false;
110 }
111 
117 static int count_body_parts(struct Body *body)
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 :
133  bp->d_filename ? bp->d_filename :
134  "(none)",
135  bp->type, bp->subtype ? bp->subtype : "*");
136 
137  if (bp->type == TYPE_MESSAGE)
138  {
139  shallrecurse = true;
140 
141  /* If it's an external body pointer, don't recurse it. */
142  if (mutt_istr_equal(bp->subtype, "external-body"))
143  shallrecurse = false;
144  }
145  else if (bp->type == TYPE_MULTIPART)
146  {
147  /* Always recurse multiparts, except multipart/alternative. */
148  shallrecurse = true;
149  if (mutt_istr_equal(bp->subtype, "alternative"))
150  shallrecurse = C_CountAlternatives;
151  }
152 
153  if ((bp->disposition == DISP_INLINE) && (bp->type != TYPE_MULTIPART) &&
154  (bp->type != TYPE_MESSAGE) && (bp == body))
155  {
156  shallcount = false; /* ignore fundamental inlines */
157  }
158 
159  /* If this body isn't scheduled for enumeration already, don't bother
160  * profiling it further. */
161  if (shallcount)
162  {
163  /* Turn off shallcount if message type is not in ok list,
164  * or if it is in except list. Check is done separately for
165  * inlines vs. attachments. */
166 
167  if (bp->disposition == DISP_ATTACH)
168  {
169  if (!count_body_parts_check(&AttachAllow, bp, true))
170  shallcount = false; /* attach not allowed */
171  if (count_body_parts_check(&AttachExclude, bp, false))
172  shallcount = false; /* attach excluded */
173  }
174  else
175  {
176  if (!count_body_parts_check(&InlineAllow, bp, true))
177  shallcount = false; /* inline not allowed */
178  if (count_body_parts_check(&InlineExclude, bp, false))
179  shallcount = false; /* excluded */
180  }
181  }
182 
183  if (shallcount)
184  count++;
185  bp->attach_qualifies = shallcount;
186 
187  mutt_debug(LL_DEBUG3, "%p shallcount = %d\n", (void *) bp, shallcount);
188 
189  if (shallrecurse)
190  {
191  mutt_debug(LL_DEBUG3, "%p pre count = %d\n", (void *) bp, count);
192  bp->attach_count = count_body_parts(bp->parts);
193  count += bp->attach_count;
194  mutt_debug(LL_DEBUG3, "%p post count = %d\n", (void *) bp, count);
195  }
196  }
197 
198  mutt_debug(LL_DEBUG3, "return %d\n", (count < 0) ? 0 : count);
199  return (count < 0) ? 0 : count;
200 }
201 
208 int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
209 {
210  bool keep_parts = false;
211 
212  if (e->attach_valid)
213  return e->attach_total;
214 
215  if (e->body->parts)
216  keep_parts = true;
217  else
219 
222  {
224  }
225  else
226  e->attach_total = 0;
227 
228  e->attach_valid = true;
229 
230  if (!keep_parts)
231  mutt_body_free(&e->body->parts);
232 
233  return e->attach_total;
234 }
235 
244 {
245  if (!ptr || !*ptr)
246  return;
247 
248  struct AttachMatch *am = *ptr;
249  regfree(&am->minor_regex);
250  FREE(&am->major);
251  FREE(ptr);
252 }
AttachMatch
An attachment matching a regex for attachment counter.
Definition: mutt_parse.h:34
Email::msgno
int msgno
Number displayed to the user.
Definition: email.h:87
InlineAllow
struct ListHead InlineAllow
List of inline types to counted.
Definition: mutt_parse.c:41
Mailbox
A mailbox.
Definition: mailbox.h:81
ListNode
A List node for strings.
Definition: list.h:34
LL_DEBUG3
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
Body::next
struct Body * next
next attachment in the list
Definition: body.h:53
Body
The body of an email.
Definition: body.h:34
mutt_parse_part
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1659
mutt_parse.h
mutt_globals.h
FREE
#define FREE(x)
Definition: memory.h:40
DISP_ATTACH
@ DISP_ATTACH
Content is attached.
Definition: mime.h:63
LL_DEBUG5
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
STAILQ_EMPTY
#define STAILQ_EMPTY(head)
Definition: queue.h:345
mutt_body_free
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
Body::subtype
char * subtype
content-type subtype
Definition: body.h:37
count_body_parts_check
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:81
STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
mutt_parse_mime_message
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:49
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
crypt_query
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:687
lib.h
mutt_count_body_parts
int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
Count the MIME Body parts.
Definition: mutt_parse.c:208
InlineExclude
struct ListHead InlineExclude
List of inline types to ignore.
Definition: mutt_parse.c:42
C_CountAlternatives
WHERE bool C_CountAlternatives
Config: Recurse inside multipart/alternatives while counting attachments.
Definition: mutt_globals.h:144
TYPE_ANY
@ TYPE_ANY
Type: '*' or '.*'.
Definition: mime.h:40
Body::parts
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
TYPE_MESSAGE
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
mutt_attachmatch_free
void mutt_attachmatch_free(struct AttachMatch **ptr)
Free an AttachMatch - Implements list_free_t.
Definition: mutt_parse.c:243
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
AttachMatch::major_int
enum ContentType major_int
Definition: mutt_parse.h:37
Email::attach_total
short attach_total
Number of qualifying attachments in message, if attach_valid.
Definition: email.h:97
Message::fp
FILE * fp
pointer to the message data
Definition: mx.h:96
Email::security
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:39
WithCrypto
#define WithCrypto
Definition: lib.h:123
lib.h
lib.h
STAILQ_HEAD_INITIALIZER
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
DISP_INLINE
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
Body::type
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
ListNode::data
char * data
String.
Definition: list.h:36
Email::attach_valid
bool attach_valid
true when the attachment count is valid
Definition: email.h:70
AttachMatch::minor_regex
regex_t minor_regex
Definition: mutt_parse.h:39
AttachMatch::major
const char * major
Definition: mutt_parse.h:36
mx.h
mx_msg_close
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1204
TYPE_MULTIPART
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
Email
The envelope/body of an email.
Definition: email.h:37
count_body_parts
static int count_body_parts(struct Body *body)
Count the MIME Body parts.
Definition: mutt_parse.c:117
AttachMatch::minor
const char * minor
Definition: mutt_parse.h:38
AttachAllow
struct ListHead AttachAllow
List of attachment types to be counted.
Definition: mutt_parse.c:39
Message
A local copy of an email.
Definition: mx.h:94
Email::body
struct Body * body
List of MIME parts.
Definition: email.h:91
mx_msg_open
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1158
AttachExclude
struct ListHead AttachExclude
List of attachment types to be ignored.
Definition: mutt_parse.c:40