X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/8bb0f8000b86df9270f2410de3fb6f41fa63e88b..4dff00a2d1a9e0b1e301c3015d8f7bdf87e2e37a:/uip/mhbuildsbr.c diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c index 5b7f0746..5d3679f6 100644 --- a/uip/mhbuildsbr.c +++ b/uip/mhbuildsbr.c @@ -36,7 +36,6 @@ extern int debugsw; extern int verbosw; -extern int ebcdicsw; extern int listsw; extern int rfc934sw; extern int contentidsw; @@ -55,6 +54,12 @@ pid_t xpid = 0; static char prefix[] = "----- =_aaaaaaaaaa"; +/* + * Maximum size of URL token in message/external-body + */ + +#define MAXURLTOKEN 40 + /* mhmisc.c */ void content_error (char *, CT, char *, ...); @@ -63,7 +68,6 @@ void content_error (char *, CT, char *, ...); int find_cache (CT, int, int *, char *, char *, int); /* mhfree.c */ -void free_content (CT); void free_ctinfo (CT); void free_encoding (CT, int); @@ -163,6 +167,7 @@ build_mime (char *infile, int directives) * draft into the linked list of header fields for * the new MIME message. */ + m_getfld_track_filepos (&gstate, in); for (compnum = 1;;) { int bufsz = sizeof buf; switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) { @@ -342,12 +347,6 @@ finish_field: static int init_decoded_content (CT ct) { - CE ce; - - if ((ce = (CE) calloc (1, sizeof(*ce))) == NULL) - adios (NULL, "out of memory"); - - ct->c_cefile = ce; ct->c_ceopenfnx = open7Bit; /* since unencoded */ ct->c_ceclosefnx = close_encoding; ct->c_cesizefnx = NULL; /* since unencoded */ @@ -403,8 +402,7 @@ static int user_content (FILE *in, char *file, char *buf, CT *ctp) { int extrnal, vrsn; - unsigned char *cp; - char **ap; + char *cp, **ap; char buffer[BUFSIZ]; struct multipart *m; struct part **pp; @@ -426,7 +424,7 @@ user_content (FILE *in, char *file, char *buf, CT *ctp) /* allocate basic structure for handling decoded content */ init_decoded_content (ct); - ce = ct->c_cefile; + ce = &ct->c_cefile; ci = &ct->c_ctinfo; set_id (ct, 0); @@ -677,7 +675,7 @@ use_forw: if (ci->ci_magic) { /* check if specifies command to execute */ if (*ci->ci_magic == '|' || *ci->ci_magic == '!') { - for (cp = ci->ci_magic + 1; isspace (*cp); cp++) + for (cp = ci->ci_magic + 1; isspace ((unsigned char) *cp); cp++) continue; if (!*cp) adios (NULL, "empty pipe command for #%s directive", ci->ci_type); @@ -749,7 +747,7 @@ use_forw: if (!folder) folder = add (getfolder (1), NULL); - if (!(mp = folder_read (folder))) + if (!(mp = folder_read (folder, 0))) adios (NULL, "unable to read folder %s", folder); for (ap = arguments; *ap; ap++) { cp = *ap; @@ -787,7 +785,7 @@ use_forw: if ((p = (CT) calloc (1, sizeof(*p))) == NULL) adios (NULL, "out of memory"); init_decoded_content (p); - pe = p->c_cefile; + pe = &p->c_cefile; if (get_ctinfo ("message/rfc822", p, 0) == NOTOK) done (1); p->c_type = CT_MESSAGE; @@ -913,42 +911,6 @@ set_id (CT ct, int top) } -static char ebcdicsafe[0x100] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - /* * Fill out, or expand the various contents in the composition * draft. Read-in any necessary files. Parse and execute any @@ -958,7 +920,7 @@ static char ebcdicsafe[0x100] = { static int compose_content (CT ct) { - CE ce = ct->c_cefile; + CE ce = &ct->c_cefile; switch (ct->c_type) { case CT_MULTIPART: @@ -1132,7 +1094,7 @@ raw: if ((out = fopen (ce->ce_file, "w")) == NULL) adios (ce->ce_file, "unable to open for writing"); - for (i = 0; (child_id = vfork()) == NOTOK && i > 5; i++) + for (i = 0; (child_id = fork()) == NOTOK && i > 5; i++) sleep (5); switch (child_id) { case NOTOK: @@ -1192,11 +1154,10 @@ scan_content (CT ct) int checklinelen = 0, linelen = 0; /* check for long lines */ int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary */ int checklinespace = 0, linespace = 0; /* check if any line ends with space */ - int checkebcdic = 0, ebcdicunsafe = 0; /* check if contains ebcdic unsafe characters */ - unsigned char *cp = NULL, buffer[BUFSIZ]; + char *cp = NULL, buffer[BUFSIZ]; struct text *t = NULL; FILE *in = NULL; - CE ce = ct->c_cefile; + CE ce = &ct->c_cefile; /* * handle multipart by scanning all subparts @@ -1233,11 +1194,9 @@ scan_content (CT ct) check8bit = 1; checkboundary = 1; if (ct->c_subtype == TEXT_PLAIN) { - checkebcdic = 0; checklinelen = 0; checklinespace = 0; } else { - checkebcdic = ebcdicsw; checklinelen = 1; checklinespace = 1; } @@ -1245,7 +1204,6 @@ scan_content (CT ct) case CT_APPLICATION: check8bit = 1; - checkebcdic = ebcdicsw; checklinelen = 1; checklinespace = 1; checkboundary = 1; @@ -1253,7 +1211,6 @@ scan_content (CT ct) case CT_MESSAGE: check8bit = 0; - checkebcdic = 0; checklinelen = 0; checklinespace = 0; @@ -1272,7 +1229,6 @@ scan_content (CT ct) * since we are forcing use of base64. */ check8bit = 0; - checkebcdic = 0; checklinelen = 0; checklinespace = 0; checkboundary = 0; @@ -1293,18 +1249,10 @@ scan_content (CT ct) */ if (check8bit) { for (cp = buffer; *cp; cp++) { - if (!isascii (*cp)) { + if (!isascii ((unsigned char) *cp)) { contains8bit = 1; check8bit = 0; /* no need to keep checking */ } - /* - * Check if character is ebcdic-safe. We only check - * this if also checking for 8bit data. - */ - if (checkebcdic && !ebcdicsafe[*cp & 0xff]) { - ebcdicunsafe = 1; - checkebcdic = 0; /* no need to keep checking */ - } } } @@ -1319,7 +1267,7 @@ scan_content (CT ct) /* * Check if line ends with a space. */ - if (checklinespace && (cp = buffer + strlen (buffer) - 2) > buffer && isspace (*cp)) { + if (checklinespace && (cp = buffer + strlen (buffer) - 2) > buffer && isspace ((unsigned char) *cp)) { linespace = 1; checklinespace = 0; /* no need to keep checking */ } @@ -1330,10 +1278,10 @@ scan_content (CT ct) */ if (checkboundary && buffer[0] == '-' && buffer[1] == '-') { for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) - if (!isspace (*cp)) + if (!isspace ((unsigned char) *cp)) break; *++cp = '\0'; - if (!strncmp(buffer + 2, prefix, len) && isdigit(buffer[2 + len])) { + if (!strncmp(buffer + 2, prefix, len) && isdigit((unsigned char) buffer[2 + len])) { boundaryclash = 1; checkboundary = 0; /* no need to keep checking */ } @@ -1372,7 +1320,7 @@ scan_content (CT ct) *ep = cp; } - if (contains8bit || ebcdicunsafe || linelen || linespace || checksw) + if (contains8bit || linelen || linespace || checksw) ct->c_encoding = CE_QUOTED; else ct->c_encoding = CE_7BIT; @@ -1380,7 +1328,7 @@ scan_content (CT ct) case CT_APPLICATION: /* For application type, use base64, except when postscript */ - if (contains8bit || ebcdicunsafe || linelen || linespace || checksw) + if (contains8bit || linelen || linespace || checksw) ct->c_encoding = (ct->c_subtype == APPLICATION_POSTSCRIPT) ? CE_QUOTED : CE_BASE64; else @@ -1412,7 +1360,7 @@ scan_content (CT ct) static int build_headers (CT ct) { - int cc, mailbody, len; + int cc, mailbody, extbody, len; char **ap, **ep; char *np, *vp, buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; @@ -1454,9 +1402,8 @@ build_headers (CT ct) len = strlen (TYPE_FIELD) + strlen (ci->ci_type) + strlen (ci->ci_subtype) + 3; - mailbody = ct->c_type == CT_MESSAGE - && ct->c_subtype == MESSAGE_EXTERNAL - && ((struct exbody *) ct->c_ctparams)->eb_body; + extbody = ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_EXTERNAL; + mailbody = extbody && ((struct exbody *) ct->c_ctparams)->eb_body; /* * Append the attribute/value pairs to @@ -1469,6 +1416,42 @@ build_headers (CT ct) vp = add (";", vp); len++; + /* + * According to RFC 2017, if we have a URL longer than 40 characters + * we have to break it across multiple lines + */ + + if (extbody && mh_strcasecmp (*ap, "url") == 0) { + char *value = *ep; + + /* 7 here refers to " url=\"\"" */ + if (len + 1 + (cc = (min(MAXURLTOKEN, strlen(value)) + 7)) >= + CPERLIN) { + vp = add ("\n\t", vp); + len = 8; + } else { + vp = add (" ", vp); + len++; + } + + vp = add ("url=\"", vp); + len += 5; + + while (strlen(value) > MAXURLTOKEN) { + strncpy(buffer, value, MAXURLTOKEN); + buffer[MAXURLTOKEN] = '\0'; + vp = add (buffer, vp); + vp = add ("\n\t", vp); + value += MAXURLTOKEN; + len = 8; + } + + vp = add (value, vp); + vp = add ("\"", vp); + len += strlen(value) + 1; + continue; + } + snprintf (buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep); if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) { vp = add ("\n\t", vp); @@ -1643,7 +1626,7 @@ calculate_digest (CT ct, int asciiP) unsigned char digest[16]; unsigned char outbuf[25]; MD5_CTX mdContext; - CE ce = ct->c_cefile; + CE ce = &ct->c_cefile; char *infilename = ce->ce_file ? ce->ce_file : ct->c_file; FILE *in; @@ -1692,7 +1675,8 @@ calculate_digest (CT ct, int asciiP) } /* encode the digest using base64 */ - for (dp = digest, op = outbuf, cc = sizeof(digest) / sizeof(digest[0]); + for (dp = digest, op = (char *) outbuf, + cc = sizeof(digest) / sizeof(digest[0]); cc > 0; cc -= 3, op += 4) { unsigned long bits; char *bp;