From: Ken Hornstein Date: Fri, 8 Feb 2013 20:46:31 +0000 (-0500) Subject: Make burst(1) be able to burst MIME-formatted messages with message/rfc822 X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/a1829d0ea1260a9e361191054d84242a9b7f0f15?hp=d54945fa60a6c72e49705cfdd692710720c22392 Make burst(1) be able to burst MIME-formatted messages with message/rfc822 parts in them. --- diff --git a/Makefile.am b/Makefile.am index 0208910d..4e838984 100644 --- a/Makefile.am +++ b/Makefile.am @@ -267,7 +267,8 @@ uip_ali_SOURCES = uip/ali.c uip/aliasbr.c uip_anno_SOURCES = uip/anno.c uip/annosbr.c -uip_burst_SOURCES = uip/burst.c +uip_burst_SOURCES = uip/burst.c uip/mhparse.c uip/mhmisc.c uip/mhfree.c \ + uip/mhcachesbr.c uip/md5.c uip_comp_SOURCES = uip/comp.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c diff --git a/docs/pending-release-notes b/docs/pending-release-notes index a6ae19c5..9624ac6c 100644 --- a/docs/pending-release-notes +++ b/docs/pending-release-notes @@ -36,7 +36,8 @@ NEW FEATURES if the user does not configure an editor entry in their profile. - The format engine (mh_format(5)) now properly accounts for multibyte characters when accounting for column widths. - +- burst(1) now can burst MIME-formatted digests (messages that contain + message/rfc822 parts instead of messages formatted with RFC 934). ---------------------------- OBSOLETE/DEPRECATED FEATURES diff --git a/man/burst.man b/man/burst.man index 526870ca..2ef0975c 100644 --- a/man/burst.man +++ b/man/burst.man @@ -11,6 +11,8 @@ burst \- explode digests into messages .RI [ +folder ] .RI [ msgs ] .RB [ \-inplace " | " \-noinplace ] +.RB [ \-mime " | " \-nomime ] +.RB [ \-automime ] .RB [ \-quiet " | " \-noquiet ] .RB [ \-verbose " | " \-noverbose ] .RB [ \-version ] @@ -36,6 +38,20 @@ is given, each digest is preserved, no table of contents is produced, and the messages contained within the digest are placed at the end of the folder. Other messages are not tampered with in any way. .PP +If +.B \-automime +is given, +.B burst +will try to determine if the message is formatted with MIME and contains MIME parts of +type \*(lqmessage/rfc822\*(rq. If it does, it will burst the message using MIME +formatting rules. The +.B \-mime +switch can be used to enforce the use of MIME formatting. The +.B \-nomime +switch will force +.B burst +to use RFC-934 rules. +.PP The .B \-quiet switch directs @@ -93,6 +109,8 @@ The current message. .TP \-noinplace .TP +\-automime +.TP \-noquiet .TP \-noverbose diff --git a/uip/burst.c b/uip/burst.c index 0b4a2409..e4792335 100644 --- a/uip/burst.c +++ b/uip/burst.c @@ -9,10 +9,14 @@ #include #include +#include #define BURST_SWITCHES \ X("inplace", 0, INPLSW) \ X("noinplace", 0, NINPLSW) \ + X("mime", 0, MIMESW) \ + X("nomime", 0, NMIMESW) \ + X("automime", 0, AUTOMIMESW) \ X("quiet", 0, QIETSW) \ X("noquiet", 0, NQIETSW) \ X("verbose", 0, VERBSW) \ @@ -33,12 +37,21 @@ struct smsg { off_t s_stop; }; +/* + * For the MIME parsing routines + */ + +int debugsw = 0; +pid_t xpid = 0; + /* * static prototypes */ -static int find_delim (int, struct smsg *); -static void burst (struct msgs **, int, struct smsg *, int, int, int, char *); -static void cpybrst (FILE *, FILE *, char *, char *, int); +static int find_delim (int, struct smsg *, int *); +static void find_mime_parts (CT, struct smsg *, int *); +static void burst (struct msgs **, int, struct smsg *, int, int, int, + char *, int); +static void cpybrst (FILE *, FILE *, char *, char *, int, int); /* * A macro to check to see if we have reached a message delimiter @@ -54,7 +67,7 @@ static void cpybrst (FILE *, FILE *, char *, char *, int); int main (int argc, char **argv) { - int inplace = 0, quietsw = 0, verbosw = 0; + int inplace = 0, quietsw = 0, verbosw = 0, mimesw = 1; int hi, msgnum, numburst; char *cp, *maildir, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; @@ -98,6 +111,16 @@ main (int argc, char **argv) inplace = 0; continue; + case MIMESW: + mimesw = 2; + continue; + case NMIMESW: + mimesw = 0; + continue; + case AUTOMIMESW: + mimesw = 1; + continue; + case QIETSW: quietsw++; continue; @@ -158,11 +181,12 @@ main (int argc, char **argv) /* burst all the SELECTED messages */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { - if ((numburst = find_delim (msgnum, smsgs)) >= 1) { + if ((numburst = find_delim (msgnum, smsgs, &mimesw)) >= 1) { if (verbosw) printf ("%d message%s exploded from digest %d\n", numburst, numburst > 1 ? "s" : "", msgnum); - burst (&mp, msgnum, smsgs, numburst, inplace, verbosw, maildir); + burst (&mp, msgnum, smsgs, numburst, inplace, verbosw, + maildir, mimesw); } else { if (numburst == 0) { if (!quietsw) @@ -203,18 +227,49 @@ main (int argc, char **argv) /* * Scan the message and find the beginning and * end of all the messages in the digest. + * + * If requested, see if the message is MIME-formatted and contains any + * message/rfc822 parts; if so, burst those parts. */ static int -find_delim (int msgnum, struct smsg *smsgs) +find_delim (int msgnum, struct smsg *smsgs, int *mimesw) { int wasdlm = 0, msgp; off_t pos; char c, *msgnam; char buffer[BUFSIZ]; FILE *in; + CT content; - if ((in = fopen (msgnam = m_name (msgnum), "r")) == NULL) + msgnam = m_name (msgnum); + + /* + * If mimesw is 1 or 2, try to see if it's got proper MIME formatting. + */ + + if (*mimesw > 0) { + content = parse_mime(msgnam); + if (! content && *mimesw == 2) + return 0; + else if (content) { + smsgs[0].s_start = 0; + smsgs[0].s_stop = content->c_begin - 1; + msgp = 1; + find_mime_parts(content, smsgs, &msgp); + free_content(content); + if (msgp == 1 && *mimesw == 2) { + adios (msgnam, "does not have any message/rfc822 parts"); + } else if (msgp > 1) { + *mimesw = 1; + return (msgp - 1); + } + } + } + + *mimesw = 0; + + if ((in = fopen (msgnam, "r")) == NULL) adios (msgnam, "unable to read message"); for (msgp = 0, pos = 0L; msgp <= MAXFOLDER;) { @@ -275,13 +330,51 @@ find_delim (int msgnum, struct smsg *smsgs) } +/* + * Find any MIME content in the message that is a message/rfc822 and add + * it to the list of messages to burst. + */ + +static void +find_mime_parts (CT content, struct smsg *smsgs, int *msgp) +{ + struct multipart *m; + struct part *part; + + /* + * If we have a message/rfc822, then it's easy. + */ + + if (content->c_type == CT_MESSAGE && + content->c_subtype == MESSAGE_RFC822) { + smsgs[*msgp].s_start = content->c_begin; + smsgs[*msgp].s_stop = content->c_end; + (*msgp)++; + return; + } + + /* + * Otherwise, if we do have multiparts, try all of the sub-parts. + */ + + if (content->c_type == CT_MULTIPART) { + m = (struct multipart *) content->c_ctparams; + + for (part = m->mp_parts; part; part = part->mp_next) + find_mime_parts(part->mp_part, smsgs, msgp); + } + + return; +} + + /* * Burst out the messages in the digest into the folder */ static void burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, - int inplace, int verbosw, char *maildir) + int inplace, int verbosw, char *maildir, int mimesw) { int i, j, mode; char *msgnam; @@ -380,7 +473,7 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, chmod (f2, mode); fseeko (in, smsgs[j].s_start, SEEK_SET); cpybrst (in, out, msgnam, f2, - (int) (smsgs[j].s_stop - smsgs[j].s_start)); + (int) (smsgs[j].s_stop - smsgs[j].s_start), mimesw); fclose (out); if (i == msgnum) { @@ -408,6 +501,7 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, #define S1 0 #define S2 1 #define S3 2 +#define S4 3 /* * Copy a mesage which is being burst out of a digest. @@ -415,11 +509,11 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, */ static void -cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len) +cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len, int mime) { register int c, state; - for (state = S1; (c = fgetc (in)) != EOF && len > 0; len--) { + for (state = mime ? S4 : S1; (c = fgetc (in)) != EOF && len > 0; len--) { if (c == 0) continue; switch (state) { @@ -460,6 +554,10 @@ cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len) break; } break; + + case S4: + fputc (c, out); + break; } }