X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/de4636bb664106d9932ae7acb517e471b848f1f3..ef1ba39e8dae81091b6c3e73e72825ef6edea3c6:/uip/burst.c diff --git a/uip/burst.c b/uip/burst.c index 0b4a2409..49dad2d1 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,20 @@ struct smsg { off_t s_stop; }; +/* + * For the MIME parsing routines + */ + +int debugsw = 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 +66,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; @@ -62,13 +74,7 @@ main (int argc, char **argv) struct smsg *smsgs; struct msgs *mp; -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); - - /* read user profile/context */ - context_read(); + if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; @@ -98,6 +104,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; @@ -135,7 +151,7 @@ main (int argc, char **argv) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ - if (!(mp = folder_read (folder))) + if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ @@ -148,21 +164,19 @@ main (int argc, char **argv) done (1); seq_setprev (mp); /* set the previous-sequence */ - smsgs = (struct smsg *) - calloc ((size_t) (MAXFOLDER + 2), sizeof(*smsgs)); - if (smsgs == NULL) - adios (NULL, "unable to allocate burst storage"); + smsgs = mh_xcalloc(MAXFOLDER + 2, sizeof *smsgs); hi = mp->hghmsg + 1; /* 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) @@ -175,7 +189,7 @@ main (int argc, char **argv) } } - free ((char *) smsgs); + free(smsgs); context_replace (pfolder, folder); /* update current folder */ /* @@ -203,18 +217,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; + 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;) { @@ -239,7 +284,7 @@ find_delim (int msgnum, struct smsg *smsgs) /* * Read in lines until we get to a message delimiter. * - * Previously we checked to make sure the preceeding line and + * Previously we checked to make sure the preceding line and * next line was a newline. That actually does not comply with * RFC 934, so make sure we break on a message delimiter even * if the previous character was NOT a newline. @@ -275,13 +320,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; @@ -371,8 +454,14 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, i = inplace ? msgnum + numburst : mp->hghmsg; for (j = numburst; j >= (inplace ? 0 : 1); i--, j--) { + char *tempfile; + + if ((tempfile = m_mktemp2(NULL, invo_name, NULL, &out)) == NULL) { + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); + } + strncpy (f2, tempfile, sizeof(f2)); strncpy (f1, m_name (i), sizeof(f1)); - strncpy (f2, m_mktemp(invo_name, NULL, &out), sizeof(f2)); if (verbosw && i != msgnum) printf ("message %d of digest %d becomes message %d\n", j, msgnum, i); @@ -380,7 +469,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) { @@ -389,13 +478,13 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, admonish (f3, "unable to rename %s to", f1); (void)snprintf(f3, sizeof (f3), "%s/%d", maildir, i); - ext_hook("del-hook", f3, (char *)0); + ext_hook("del-hook", f3, NULL); } if (rename (f2, f1) == NOTOK) admonish (f1, "unable to rename %s to", f2); (void)snprintf(f3, sizeof (f3), "%s/%d", maildir, i); - ext_hook("add-hook", f3, (char *)0); + ext_hook("add-hook", f3, NULL); copy_msg_flags (mp, i, msgnum); mp->msgflags |= SEQMOD; @@ -408,18 +497,19 @@ 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. + * Copy a message which is being burst out of a digest. * It will remove any "dashstuffing" in the message. */ 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; + 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 +550,10 @@ cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len) break; } break; + + case S4: + fputc (c, out); + break; } }