This is a patch to mhn in the 6.8.4 distribution, to support external
Content-Transfer-Encoding types. For an encoding type "x-typename" it
searches the profile for "mhn-decode-typename" which is expected to be
a commandline that takes input on stdin. Since I mainly added it to
support uudecode, which always creates an output file by itself, the code
also assumes that the output file will be created by the external program.
But just to cover all bases, the external program's stdout is also set
to the output file. I also expect that the desired filename is present
in the content attributes, but will generate a tempname if not.
Oh, I also added a definition for multipart/report, the crap that some
mailer daemons send for bounced email. This may not have been the proper
treatment, but it was annoying and I did it in a hurry.
Howard Chu Principal Member of Technical Staff
hyc(_at_)locus(_dot_)com PLATINUM technology,
Los Angeles Lab
*** /tmp/T0ipoB4o Sun Dec 15 21:45:49 1996
--- mhn.c Sun Dec 15 21:42:30 1996
***************
*** 195,200 ****
--- 195,201 ----
static char *dir;
static char *errs = NULL;
static char *tmp;
+ static char *maildir;
extern int errno;
***************
*** 361,367 ****
*f7 = NULL,
*file = NULL,
*folder = NULL,
- *maildir,
buf[100],
**ap,
**argp,
--- 362,367 ----
***************
*** 1039,1045 ****
};
! static int InitBase64 (), InitQuoted (), Init7Bit ();
static struct str2init str2ces[] = {
"base64", CE_BASE64, InitBase64,
--- 1039,1045 ----
};
! static int InitBase64 (), InitQuoted (), Init7Bit (), InitExtension ();
static struct str2init str2ces[] = {
"base64", CE_BASE64, InitBase64,
***************
*** 1048,1054 ****
"7bit", CE_7BIT, Init7Bit,
"binary", CE_BINARY, NULL,
! NULL, CE_EXTENSION, NULL, /* these two must be last! */
NULL, CE_UNKNOWN, NULL,
};
--- 1048,1054 ----
"7bit", CE_7BIT, Init7Bit,
"binary", CE_BINARY, NULL,
! NULL, CE_EXTENSION, InitExtension, /* these two must be
last! */
NULL, CE_UNKNOWN, NULL,
};
***************
*** 1186,1192 ****
goto out;
}
- ct -> c_celine = cp;
while (isspace (*cp))
cp++;
for (dp = cp; istoken (*dp); dp++)
--- 1186,1191 ----
***************
*** 1197,1203 ****
break;
if (!s2i -> si_key && !uprf (cp, "X-"))
s2i++;
! *dp = c;
ct -> c_encoding = s2i -> si_val;
if (s2i -> si_init && (*s2i -> si_init) (ct) == NOTOK)
goto out;
--- 1196,1202 ----
break;
if (!s2i -> si_key && !uprf (cp, "X-"))
s2i++;
! ct -> c_celine = cp;
ct -> c_encoding = s2i -> si_val;
if (s2i -> si_init && (*s2i -> si_init) (ct) == NOTOK)
goto out;
***************
*** 2868,2873 ****
--- 2867,2873 ----
#define MULTI_ALTERNATE 0x02
#define MULTI_DIGEST 0x03
#define MULTI_PARALLEL 0x04
+ #define MULTI_REPORT 0x05
struct multipart {
***************
*** 3238,3243 ****
--- 3238,3244 ----
"alternative", MULTI_ALTERNATE,
"digest", MULTI_DIGEST,
"parallel", MULTI_PARALLEL,
+ "report", MULTI_REPORT,
NULL, MULTI_UNKNOWN /* this one must be last! */
};
***************
*** 3451,3456 ****
--- 3452,3458 ----
#define MESSAGE_RFC822 0x01
#define MESSAGE_PARTIAL 0x02
#define MESSAGE_EXTERNAL 0x03
+ #define MESSAGE_DELIVERY_STATUS 0x04
struct partial {
***************
*** 3818,3823 ****
--- 3820,3826 ----
"rfc822", MESSAGE_RFC822,
"partial", MESSAGE_PARTIAL,
"external-body", MESSAGE_EXTERNAL,
+ "delivery-status", MESSAGE_DELIVERY_STATUS,
NULL, MESSAGE_UNKNOWN /* this one must be last! */
};
***************
*** 3843,3848 ****
--- 3846,3852 ----
switch (ct -> c_subtype = kv -> kv_value) {
case MESSAGE_RFC822:
+ case MESSAGE_DELIVERY_STATUS:
ct -> c_showproc = add ("%pshow -file '%F'", NULLCP);
break;
***************
*** 4243,4248 ****
--- 4247,4373 ----
return OK;
}
+ /* Extension encoding */
+
+ static int openExtension (ct, file)
+ register CT ct;
+ char **file;
+ {
+ register char *cp;
+ register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
+ char buffer[BUFSIZ];
+ char *vec[4];
+ int fds[2], fd, len, child_id, i, cc;
+
+ (void) sprintf (buffer, "%s-decode-%s", invo_name, ct -> c_celine+2);
+ if ((cp = m_find (buffer)) == NULL || *cp == 0) {
+ content_error (NULLCP, ct,
+ "don't know how to decode content");
+ return NOTOK;
+ }
+
+ if (ce -> ce_fp)
+ goto ready_to_go;
+ if (ce -> ce_file) {
+ if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
+ content_error (ce -> ce_file, ct, "unable to fopen for reading");
+ return NOTOK;
+ }
+
+ *file = ce -> ce_file;
+ return fileno (ce -> ce_fp);
+ }
+
+ ce -> ce_unlink = *file == NULL;
+ for (i=0; ct->c_ctinfo.ci_attrs[i]; ++i) {
+ if (uprf(ct->c_ctinfo.ci_attrs[i], "name") ||
+ uprf(ct->c_ctinfo.ci_attrs[i], "filename")) {
+ sprintf(buffer, "%s/%s", maildir, ct->c_ctinfo.ci_values[i]);
+ ce -> ce_file = getcpy (buffer);
+ break;
+ }
+ }
+ if (!ce -> ce_file)
+ ce -> ce_file = add (*file ? *file : m_scratch ("", tmp), NULLCP);
+ if ((ce -> ce_fp = fopen (ce -> ce_file, "w+")) == NULL) {
+ content_error (ce -> ce_file, ct,
+ "unable to fopen for writing and reading");
+ return NOTOK;
+ }
+ if ((len = ct -> c_end - ct -> c_begin) < 0)
+ adios (NULLCP, "internal error(1)");
+
+ if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
+ content_error (ct -> c_file, ct, "unable to open for reading");
+ return NOTOK;
+ }
+
+ (void) lseek (fd = fileno (ct -> c_fp), (off_t)ct -> c_begin, 0);
+
+ (void) sprintf (buffer, "exec %s", cp);
+
+ vec[0] = "/bin/sh";
+ vec[1] = "-c";
+ vec[2] = buffer;
+ vec[3] = NULL;
+
+ if (pipe(fds) == NOTOK)
+ {
+ advise ("pipe", "unable to create");
+ return NOTOK;
+ }
+ for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
+ sleep (5);
+ switch (child_id) {
+ case NOTOK:
+ advise ("fork", "unable to");
+ return NOTOK;
+
+ case OK:
+ dup2(fds[0], 0);
+ dup2 (fileno (ce->ce_fp), 1);
+ close (fds[0]);
+ close (fds[1]);
+ (void) execvp ("/bin/sh", vec);
+ fprintf (stderr, "unable to exec ");
+ perror ("/bin/sh");
+ _exit (-1);
+ /* NOTREACHED */
+
+ default:
+ close(fds[0]);
+ while (len > 0)
+ switch (cc = read (fd, buffer, sizeof buffer)) {
+ case NOTOK:
+ content_error (ct -> c_file, ct, "error reading from");
+ goto clean_up;
+
+ case OK:
+ content_error (NULLCP, ct, "premature eof");
+ goto clean_up;
+
+ default:
+ if (cc > len)
+ cc = len;
+ len -= cc;
+ write (fds[1], buffer, cc);
+ }
+ close (fds[1]);
+
+ (void) pidcheck (pidwait (child_id, NOTOK));
+ break;
+ }
+ ready_to_go: ;
+ (void) fseek (ce -> ce_fp, 0L, 0);
+ *file = ce -> ce_file;
+ return fileno (ce -> ce_fp);
+
+ clean_up: ;
+ free_encoding (ct, 0);
+
+ return NOTOK;
+ }
+
/* BASE64 */
static unsigned char b642nib[0x80] = {
***************
*** 4426,4431 ****
--- 4551,4562 ----
return NOTOK;
}
+
+ static int InitExtension (ct)
+ register CT ct;
+ {
+ return init_encoding (ct, openExtension);
+ }
static int InitBase64 (ct)
register CT ct;