]> diplodocus.org Git - nmh/commitdiff
Make burst(1) be able to burst MIME-formatted messages with message/rfc822
authorKen Hornstein <kenh@pobox.com>
Fri, 8 Feb 2013 20:46:31 +0000 (15:46 -0500)
committerKen Hornstein <kenh@pobox.com>
Fri, 8 Feb 2013 20:46:31 +0000 (15:46 -0500)
parts in them.

Makefile.am
docs/pending-release-notes
man/burst.man
uip/burst.c

index 0208910..4e83898 100644 (file)
@@ -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
index a6ae19c..9624ac6 100644 (file)
@@ -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
index 526870c..2ef0975 100644 (file)
@@ -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
index 0b4a240..e479233 100644 (file)
@@ -9,10 +9,14 @@
 
 #include <h/mh.h>
 #include <h/utils.h>
+#include <h/mhparse.h>
 
 #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;
        }
     }