* lines. ``line'' must point to a dynamically allocated string; it is
* increased if more space is required to fit the whole line.
*/
-static char *read_rfc822_line (FILE * f, char *line, size_t * linelen)
+char *mutt_read_rfc822_line (FILE * f, char *line, size_t * linelen)
{
char *buf = line;
char ch;
return TYPEVIDEO;
else if (ascii_strcasecmp ("model", s) == 0)
return TYPEMODEL;
+ else if (ascii_strcasecmp ("*", s) == 0)
+ return TYPEANY;
+ else if (ascii_strcasecmp (".*", s) == 0)
+ return TYPEANY;
else
return TYPEOTHER;
}
p->type = digest ? TYPEMESSAGE : TYPETEXT;
p->disposition = DISPINLINE;
- while (*(line = read_rfc822_line (fp, line, &linelen)) != 0) {
+ while (*(line = mutt_read_rfc822_line (fp, line, &linelen)) != 0) {
/* Find the value of the current header */
if ((c = strchr (line, ':'))) {
*c = 0;
void mutt_parse_mime_message (CONTEXT * ctx, HEADER * cur)
{
MESSAGE *msg;
+ int flags = 0;
- if (cur->content->type != TYPEMESSAGE
- && cur->content->type != TYPEMULTIPART)
- return; /* nothing to do */
+ do {
+ if (cur->content->type != TYPEMESSAGE
+ && cur->content->type != TYPEMULTIPART)
+ break; /* nothing to do */
- if (cur->content->parts)
- return; /* The message was parsed earlier. */
+ if (cur->content->parts)
+ break; /* The message was parsed earlier. */
- if ((msg = mx_open_message (ctx, cur->msgno))) {
- mutt_parse_part (msg->fp, cur->content);
+ if ((msg = mx_open_message (ctx, cur->msgno))) {
+ mutt_parse_part (msg->fp, cur->content);
- if (WithCrypto)
- cur->security = crypt_query (cur->content);
+ if (WithCrypto)
+ cur->security = crypt_query (cur->content);
- mx_close_message (&msg);
- }
+ mx_close_message (&msg);
+ }
+ } while (0);
+ mutt_count_body_parts (cur, flags | M_PARTS_RECOUNT);
}
int mutt_parse_rfc822_line (ENVELOPE * e, HEADER * hdr, char *line, char *p,
* bothered me for _years_ */
if (!e->from) {
e->from = rfc822_new_address ();
- e->from->personal = str_dup (line + 6);
+ e->from->personal = str_dup (p);
}
matched = 1;
}
matched = 1;
}
else if (!ascii_strcasecmp (line + 1, "essage-id")) {
- /* We add a new "Message-Id:" when building a message */
+ /* We add a new "Message-ID:" when building a message */
mem_free (&e->message_id);
e->message_id = extract_message_id (p);
matched = 1;
}
while ((loc = ftell (f)),
- *(line = read_rfc822_line (f, line, &linelen)) != 0) {
+ *(line = mutt_read_rfc822_line (f, line, &linelen)) != 0) {
matched = 0;
if ((p = strpbrk (line, ": \t")) == NULL || *p != ':') {
if (hdr) {
hdr->content->hdr_offset = hdr->offset;
hdr->content->offset = ftell (f);
-
- /* do RFC2047 decoding */
- rfc2047_decode_adrlist (e->from);
- rfc2047_decode_adrlist (e->to);
- rfc2047_decode_adrlist (e->cc);
- rfc2047_decode_adrlist (e->bcc);
- rfc2047_decode_adrlist (e->reply_to);
- rfc2047_decode_adrlist (e->mail_followup_to);
- rfc2047_decode_adrlist (e->return_path);
- rfc2047_decode_adrlist (e->sender);
-
- if (e->subject) {
- regmatch_t pmatch[1];
-
- rfc2047_decode (&e->subject);
-
- if (regexec (ReplyRegexp.rx, e->subject, 1, pmatch, 0) == 0)
- e->real_subj = e->subject + pmatch[0].rm_eo;
- else
- e->real_subj = e->subject;
- }
-
+ rfc2047_decode_envelope (e);
/* check for missing or invalid date */
if (hdr->date_sent <= 0) {
- debug_print (1, ("no date found, using received time from msg separator\n"));
+ debug_print (1, ("no date found, using received "
+ "time from msg separator\n"));
hdr->date_sent = hdr->received;
}
}
return p;
}
+
+
+/* Compares mime types to the ok and except lists */
+int count_body_parts_check(LIST **checklist, BODY *b, int dflt) {
+ LIST *type;
+ ATTACH_MATCH *a;
+
+ /* If list is null, use default behavior. */
+ if (! *checklist) {
+ /*return dflt;*/
+ return 0;
+ }
+
+ for (type = *checklist; type; type = type->next) {
+ a = (ATTACH_MATCH *)type->data;
+ debug_print(5, ("cbpc: %s %d/%s ?? %s/%s [%d]... ",
+ dflt ? "[OK] " : "[EXCL] ",
+ b->type, b->subtype, a->major, a->minor, a->major_int));
+ if ((a->major_int == TYPEANY || a->major_int == b->type) &&
+ !regexec(&a->minor_rx, b->subtype, 0, NULL, 0)) {
+ debug_print(5, ("yes\n"));
+ return 1;
+ } else {
+ debug_print(5, ("no\n"));
+ }
+ }
+ return 0;
+}
+
+#define AT_COUNT(why) { shallcount = 1; }
+#define AT_NOCOUNT(why) { shallcount = 0; }
+
+int count_body_parts (BODY *body, int flags) {
+ int count = 0;
+ int shallcount, shallrecurse;
+ BODY *bp;
+
+ if (body == NULL)
+ return 0;
+
+ for (bp = body; bp != NULL; bp = bp->next) {
+ /* Initial disposition is to count and not to recurse this part. */
+ AT_COUNT("default");
+ shallrecurse = 0;
+
+ debug_print(5, ("bp: desc=\"%s\"; fn=\"%s\", type=\"%d/%s\"\n",
+ bp->description ? bp->description : ("none"),
+ bp->filename ? bp->filename :
+ bp->d_filename ? bp->d_filename : "(none)",
+ bp->type, bp->subtype ? bp->subtype : "*"));
+
+ if (bp->type == TYPEMESSAGE) {
+ shallrecurse = 1;
+
+ /* If it's an external body pointer, don't recurse it. */
+ if (!ascii_strcasecmp (bp->subtype, "external-body"))
+ shallrecurse = 0;
+
+ /* Don't count containers if they're top-level. */
+ if (flags & M_PARTS_TOPLEVEL)
+ AT_NOCOUNT("top-level message/*");
+ } else if (bp->type == TYPEMULTIPART) {
+ /* Always recurse multiparts, except multipart/alternative. */
+ shallrecurse = 1;
+ if (!str_casecmp(bp->subtype, "alternative"))
+ shallrecurse = 0;
+
+ /* Don't count containers if they're top-level. */
+ if (flags & M_PARTS_TOPLEVEL)
+ AT_NOCOUNT("top-level multipart");
+ }
+
+ if (bp->disposition == DISPINLINE &&
+ bp->type != TYPEMULTIPART && bp->type != TYPEMESSAGE && bp == body)
+ AT_NOCOUNT("ignore fundamental inlines");
+
+ /* If this body isn't scheduled for enumeration already, don't bother
+ * profiling it further. */
+
+ if (shallcount) {
+ /* Turn off shallcount if message type is not in ok list,
+ * or if it is in except list. Check is done separately for
+ * inlines vs. attachments.
+ */
+
+ if (bp->disposition == DISPATTACH) {
+ if (!count_body_parts_check(&AttachAllow, bp, 1))
+ AT_NOCOUNT("attach not allowed");
+ if (count_body_parts_check(&AttachExclude, bp, 0))
+ AT_NOCOUNT("attach excluded");
+ } else {
+ if (!count_body_parts_check(&InlineAllow, bp, 1))
+ AT_NOCOUNT("inline not allowed");
+ if (count_body_parts_check(&InlineExclude, bp, 0))
+ AT_NOCOUNT("excluded");
+ }
+ }
+
+ if (shallcount)
+ count++;
+ bp->attach_qualifies = shallcount ? 1 : 0;
+
+ debug_print(5, ("cbp: %08x shallcount = %d\n", (unsigned int)bp, shallcount));
+
+ if (shallrecurse) {
+ debug_print(5, ("cbp: %08x pre count = %d\n", (unsigned int)bp, count));
+ bp->attach_count = count_body_parts(bp->parts, flags & ~M_PARTS_TOPLEVEL);
+ count += bp->attach_count;
+ debug_print(5, ("cbp: %08x post count = %d\n", (unsigned int)bp, count));
+ }
+ }
+
+ debug_print(5, ("bp: return %d\n", count < 0 ? 0 : count));
+ return count < 0 ? 0 : count;
+}
+
+int mutt_count_body_parts (HEADER *hdr, int flags) {
+ if (!option (OPTCOUNTATTACH))
+ return (0);
+ if (hdr->attach_valid && !(flags & M_PARTS_RECOUNT))
+ return hdr->attach_total;
+
+ if (AttachAllow || AttachExclude || InlineAllow || InlineExclude)
+ hdr->attach_total = count_body_parts(hdr->content, flags | M_PARTS_TOPLEVEL);
+ else
+ hdr->attach_total = 0;
+
+ hdr->attach_valid = 1;
+ return hdr->attach_total;
+}