X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fmhparse.c;h=04333f49b2f069943312b8f9ea9f9d090a692351;hp=d2f69bc6a1eb979917369b7ad63f7144520e38a9;hb=a87df3543d3bc128ba4079d1f95638476ba5ca50;hpb=4e38095f027a81c005a48a888d0f8937e98543a5 diff --git a/uip/mhparse.c b/uip/mhparse.c index d2f69bc..04333f4 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -8,21 +8,16 @@ #include #include -#include -#include -#include -#include #include -#include +#include #include #include #include #include - -#ifdef HAVE_SYS_WAIT_H -# include -#endif - +#include +#include +#include +#include extern int debugsw; @@ -30,12 +25,6 @@ extern int endian; /* mhmisc.c */ extern pid_t xpid; /* mhshowsbr.c */ -/* cache policies */ -extern int rcachesw; /* mhcachesbr.c */ -extern int wcachesw; /* mhcachesbr.c */ - -int checksw = 0; /* check Content-MD5 field */ - /* ** Directory to place temp files. This must ** be set before these routines are called. @@ -89,9 +78,6 @@ struct k2v SubApplication[] = { }; -/* mhcachesbr.c */ -int find_cache(CT, int, int *, char *, char *, int); - /* mhmisc.c */ int part_ok(CT, int); int type_ok(CT, int); @@ -121,14 +107,6 @@ static int openBase64(CT, char **); static int InitQuoted(CT); static int openQuoted(CT, char **); static int Init7Bit(CT); -static int openExternal(CT, CT, CE, char **, int *); -static int InitFile(CT); -static int openFile(CT, char **); -static int InitFTP(CT); -static int openFTP(CT, char **); -static int InitMail(CT); -static int openMail(CT, char **); -static int readDigest(CT, char *); struct str2init str2cts[] = { { "application", CT_APPLICATION, InitApplication }, @@ -152,20 +130,6 @@ struct str2init str2ces[] = { { NULL, CE_UNKNOWN, NULL }, }; -/* -** NOTE WELL: si_key MUST NOT have value of NOTOK -** -** si_key is 1 if access method is anonymous. -*/ -struct str2init str2methods[] = { - { "afs", 1, InitFile }, - { "anon-ftp", 1, InitFTP }, - { "ftp", 0, InitFTP }, - { "local-file", 0, InitFile }, - { "mail-server", 0, InitMail }, - { NULL, 0, NULL } -}; - int pidcheck(int status) @@ -175,7 +139,7 @@ pidcheck(int status) fflush(stdout); fflush(stderr); - done(1); + exit(EX_SOFTWARE); return 1; } @@ -267,15 +231,14 @@ parse_mime(char *file) static CT get_content(FILE *in, char *file, int toplevel) { - int compnum, state; - char buf[BUFSIZ], name[NAMESZ]; - char *np, *vp; + enum state state; + struct field f = free_field; + int compnum; CT ct; HF hp; /* allocate the content structure */ - if (!(ct = (CT) calloc(1, sizeof(*ct)))) - adios(NULL, "out of memory"); + ct = (CT) mh_xcalloc(1, sizeof(*ct)); ct->c_fp = in; ct->c_file = getcpy(file); @@ -285,53 +248,34 @@ get_content(FILE *in, char *file, int toplevel) ** Parse the header fields for this ** content into a linked list. */ - for (compnum = 1, state = FLD;;) { - switch (state = m_getfld(state, name, buf, sizeof(buf), in)) { - case FLD: - case FLDPLUS: - case FLDEOF: + for (compnum = 1, state = FLD2;;) { + switch (state = m_getfld2(state, &f, in)) { + case FLD2: compnum++; - /* get copies of the buffers */ - np = getcpy(name); - vp = getcpy(buf); + /* add the header data to the list */ + add_header(ct, getcpy(f.name), getcpy(f.value)); - /* if necessary, get rest of field */ - while (state == FLDPLUS) { - state = m_getfld(state, name, buf, - sizeof(buf), in); - vp = add(buf, vp); /* add to previous value */ - } - - /* Now add the header data to the list */ - add_header(ct, np, vp); - - /* continue, if this isn't the last header field */ - if (state != FLDEOF) { - ct->c_begin = ftell(in) + 1; - continue; - } - /* else fall... */ + ct->c_begin = ftell(in) + 1; + continue; - case BODY: - case BODYEOF: - ct->c_begin = ftell(in) - strlen(buf); + case BODY2: + ct->c_begin = ftell(in) - strlen(f.value); break; - case FILEEOF: + case FILEEOF2: ct->c_begin = ftell(in); break; - case LENERR: - case FMTERR: - adios(NULL, "message format error in component #%d", + case LENERR2: + case FMTERR2: + case IOERR2: + adios(EX_DATAERR, NULL, "message format error in component #%d", compnum); default: - adios(NULL, "getfld() returned %d", state); + adios(EX_SOFTWARE, NULL, "getfld() returned %d", state); } - - /* break out of the loop */ break; } @@ -451,45 +395,6 @@ get_content(FILE *in, char *file, int toplevel) if (s2i->si_init && (*s2i->si_init) (ct) == NOTOK) goto out; - } else if (!mh_strcasecmp(hp->name, MD5_FIELD)) { - /* Get Content-MD5 field */ - unsigned char *cp, *dp; - char *ep; - - if (!checksw) - goto next_header; - - if (ct->c_digested) { - advise(NULL, "message %s has multiple %s: fields", ct->c_file, MD5_FIELD); - goto next_header; - } - - ep = cp = getcpy(hp->value); - - while (isspace(*cp)) - cp++; - for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n')) - *dp++ = ' '; - for (dp = cp + strlen(cp) - 1; dp >= cp; dp--) - if (!isspace(*dp)) - break; - *++dp = '\0'; - if (debugsw) - fprintf(stderr, "%s: %s\n", MD5_FIELD, cp); - - if (*cp == '(' && get_comment(ct, &cp, 0) == NOTOK) { - free(ep); - goto out; - } - - for (dp = cp; *dp && !isspace(*dp); dp++) - continue; - *dp = '\0'; - - readDigest(ct, cp); - free(ep); - ct->c_digested++; - } else if (!mh_strcasecmp(hp->name, ID_FIELD)) { /* Get Content-ID field */ ct->c_id = add(hp->value, ct->c_id); @@ -841,7 +746,9 @@ bad_quote: } if (!*vp) { advise(NULL, "invalid parameter in message %s's %s: field\n%*.*s(parameter %s)", ct->c_file, TYPE_FIELD, i, i, "", *ap); - return NOTOK; + *ci->ci_values[ap - ci->ci_attrs] = '\0'; + *ci->ci_attrs[ap - ci->ci_attrs] = '\0'; + continue; } ap++; @@ -1040,9 +947,7 @@ InitGeneric(CT ct) static int InitText(CT ct) { - char buffer[BUFSIZ]; - char *chset = NULL; - char **ap, **ep, *cp; + char **ap, **ep; struct k2v *kv; struct text *t; CI ci = &ct->c_ctinfo; @@ -1058,8 +963,7 @@ InitText(CT ct) ct->c_subtype = kv->kv_value; /* allocate text character set structure */ - if ((t = (struct text *) calloc(1, sizeof(*t))) == NULL) - adios(NULL, "out of memory"); + t = (struct text *) mh_xcalloc(1, sizeof(*t)); ct->c_ctparams = (void *) t; /* scan for charset parameter */ @@ -1069,10 +973,11 @@ InitText(CT ct) /* check if content specified a character set */ if (*ap) { + /* store its name */ + ct->c_charset = getcpy(norm_charmap(*ep)); /* match character set or set to CHARSET_UNKNOWN */ for (kv = Charset; kv->kv_key; kv++) { if (!mh_strcasecmp(*ep, kv->kv_key)) { - chset = *ep; break; } } @@ -1081,20 +986,6 @@ InitText(CT ct) t->tx_charset = CHARSET_UNSPECIFIED; } - /* - ** If we can not handle character set natively, - ** then check profile for string to modify the - ** terminal or display method. - ** - ** termproc is for mhshow, though mhlist -debug prints it, too. - */ - if (chset != NULL && !check_charset(chset, strlen(chset))) { - snprintf(buffer, sizeof(buffer), "%s-charset-%s", - invo_name, chset); - if ((cp = context_find(buffer))) - ct->c_termproc = getcpy(cp); - } - return OK; } @@ -1125,7 +1016,7 @@ InitMultiPart(CT ct) if (ct->c_encoding != CE_7BIT && ct->c_encoding != CE_8BIT && ct->c_encoding != CE_BINARY) { admonish(NULL, "\"%s/%s\" type in message %s must be encoded in 7bit, 8bit, or binary", ci->ci_type, ci->ci_subtype, ct->c_file); - return NOTOK; + ct->c_encoding = CE_7BIT; } /* match subtype */ @@ -1153,8 +1044,7 @@ InitMultiPart(CT ct) } /* allocate primary structure for multipart info */ - if ((m = (struct multipart *) calloc(1, sizeof(*m))) == NULL) - adios(NULL, "out of memory"); + m = (struct multipart *) mh_xcalloc(1, sizeof(*m)); ct->c_ctparams = (void *) m; /* check if boundary parameter contains only whitespace characters */ @@ -1197,9 +1087,7 @@ InitMultiPart(CT ct) if (strcmp(buffer + 2, m->mp_start)!=0) continue; next_part: - if ((part = (struct part *) calloc(1, sizeof(*part))) - == NULL) - adios(NULL, "out of memory"); + part = (struct part *) mh_xcalloc(1, sizeof(*part)); *next = part; next = &part->mp_next; @@ -1313,8 +1201,7 @@ reverse_parts(CT ct) i++; /* allocate array of pointers to the parts */ - if (!(base = (struct part **) calloc((size_t) (i + 1), sizeof(*base)))) - adios(NULL, "out of memory"); + base = (struct part **) mh_xcalloc((size_t) (i + 1), sizeof(*base)); bmp = base; /* point at all the parts */ @@ -1370,8 +1257,7 @@ InitMessage(CT ct) char **ap, **ep; struct partial *p; - if ((p = (struct partial *) calloc(1, sizeof(*p))) == NULL) - adios(NULL, "out of memory"); + p = (struct partial *) mh_xcalloc(1, sizeof(*p)); ct->c_ctparams = (void *) p; /* @@ -1409,15 +1295,9 @@ invalid_param: case MESSAGE_EXTERNAL: { - int exresult; - struct exbody *e; CT p; FILE *fp; - if ((e = (struct exbody *) calloc(1, sizeof(*e))) == NULL) - adios(NULL, "out of memory"); - ct->c_ctparams = (void *) e; - if (!ct->c_fp && (ct->c_fp = fopen(ct->c_file, "r")) == NULL) { advise(ct->c_file, "unable to open for reading"); return NOTOK; @@ -1430,46 +1310,12 @@ invalid_param: return NOTOK; } - e->eb_parent = ct; - e->eb_content = p; - p->c_ctexbody = e; - if ((exresult = params_external(ct, 0)) != NOTOK && - p->c_ceopenfnx == openMail) { - int cc, size; - char *bp; - - if ((size = ct->c_end - p->c_begin) <= 0) { - if (!e->eb_subject) - content_error(NULL, ct, "empty body for access-type=mail-server"); - goto no_body; - } - - e->eb_body = bp = mh_xmalloc((unsigned) size); - fseek(p->c_fp, p->c_begin, SEEK_SET); - while (size > 0) - switch (cc = fread(bp, sizeof(*bp), size, p->c_fp)) { - case NOTOK: - adios("failed", "fread"); - case OK: - adios(NULL, "unexpected EOF from fread"); - default: - bp += cc, size -= cc; - break; - } - *bp = 0; - } -no_body: p->c_fp = NULL; p->c_end = p->c_begin; fclose(ct->c_fp); ct->c_fp = NULL; - if (exresult == NOTOK) - return NOTOK; - if (e->eb_flags == NOTOK) - return OK; - switch (p->c_type) { case CT_MULTIPART: break; @@ -1477,9 +1323,8 @@ no_body: case CT_MESSAGE: if (p->c_subtype != MESSAGE_RFC822) break; - /* else fall... */ + /* else fall... */ default: - e->eb_partno = ct->c_partno; if (p->c_ctinitfnx) (*p->c_ctinitfnx) (p); break; @@ -1495,83 +1340,6 @@ no_body: } -int -params_external(CT ct, int composing) -{ - char **ap, **ep; - struct exbody *e = (struct exbody *) ct->c_ctparams; - CI ci = &ct->c_ctinfo; - - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - if (!mh_strcasecmp(*ap, "access-type")) { - struct str2init *s2i; - CT p = e->eb_content; - - for (s2i = str2methods; s2i->si_key; s2i++) - if (!mh_strcasecmp(*ep, s2i->si_key)) - break; - if (!s2i->si_key) { - e->eb_access = *ep; - e->eb_flags = NOTOK; - p->c_encoding = CE_EXTERNAL; - continue; - } - e->eb_access = s2i->si_key; - e->eb_flags = s2i->si_val; - p->c_encoding = CE_EXTERNAL; - - /* Call the Init function for this external type */ - if ((*s2i->si_init)(p) == NOTOK) - return NOTOK; - continue; - } - if (!mh_strcasecmp(*ap, "name")) { - e->eb_name = *ep; - continue; - } - if (!mh_strcasecmp(*ap, "permission")) { - e->eb_permission = *ep; - continue; - } - if (!mh_strcasecmp(*ap, "site")) { - e->eb_site = *ep; - continue; - } - if (!mh_strcasecmp(*ap, "directory")) { - e->eb_dir = *ep; - continue; - } - if (!mh_strcasecmp(*ap, "mode")) { - e->eb_mode = *ep; - continue; - } - if (!mh_strcasecmp(*ap, "size")) { - sscanf(*ep, "%lu", &e->eb_size); - continue; - } - if (!mh_strcasecmp(*ap, "server")) { - e->eb_server = *ep; - continue; - } - if (!mh_strcasecmp(*ap, "subject")) { - e->eb_subject = *ep; - continue; - } - if (composing && !mh_strcasecmp(*ap, "body")) { - e->eb_body = getcpy(*ep); - continue; - } - } - - if (!e->eb_access) { - advise(NULL, "invalid parameters for \"%s/%s\" type in message %s's %s field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD); - return NOTOK; - } - - return OK; -} - - /* ** APPLICATION */ @@ -1601,8 +1369,7 @@ init_encoding(CT ct, OpenCEFunc openfnx) { CE ce; - if ((ce = (CE) calloc(1, sizeof(*ce))) == NULL) - adios(NULL, "out of memory"); + ce = (CE) mh_xcalloc(1, sizeof(*ce)); ct->c_cefile = ce; ct->c_ceopenfnx = openfnx; @@ -1701,8 +1468,8 @@ InitBase64(CT ct) static int openBase64(CT ct, char **file) { - int bitno, cc, digested; - int fd, len, skip; + int bitno, cc; + int fd, len, skip, own_ct_fp = 0; unsigned long bits; unsigned char value, *b, *b1, *b2, *b3; unsigned char *cp, *ep; @@ -1710,7 +1477,6 @@ openBase64(CT ct, char **file) /* sbeck -- handle suffixes */ CI ci; CE ce; - MD5_CTX mdContext; b = (unsigned char *) &bits; b1 = &b[endian > 0 ? 1 : 2]; @@ -1747,7 +1513,7 @@ openBase64(CT ct, char **file) cp = context_find(buffer); if (cp == NULL || *cp == '\0') { snprintf(buffer, sizeof(buffer), "%s-suffix-%s", invo_name, - ci->ci_type); + ci->ci_type); cp = context_find(buffer); } if (cp != NULL && *cp != '\0') { @@ -1759,7 +1525,7 @@ openBase64(CT ct, char **file) char *file_org = strdup(ce->ce_file); ce->ce_file = add(cp, ce->ce_file); if (rename(file_org, ce->ce_file)) { - adios(ce->ce_file, "unable to rename %s to ", + adios(EX_IOERR, ce->ce_file, "unable to rename %s to ", file_org); } free(file_org); @@ -1776,16 +1542,17 @@ openBase64(CT ct, char **file) } if ((len = ct->c_end - ct->c_begin) < 0) - adios(NULL, "internal error(1)"); + adios(EX_SOFTWARE, NULL, "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; + if (!ct->c_fp) { + if ((ct->c_fp = fopen(ct->c_file, "r")) == NULL) { + content_error(ct->c_file, ct, + "unable to open for reading"); + return NOTOK; + } + own_ct_fp = 1; } - if ((digested = ct->c_digested)) - MD5Init(&mdContext); - bitno = 18; bits = 0L; skip = 0; @@ -1823,16 +1590,10 @@ openBase64(CT ct, char **file) test_end: if ((bitno -= 6) < 0) { putc((char) *b1, ce->ce_fp); - if (digested) - MD5Update(&mdContext, b1, 1); if (skip < 2) { putc((char) *b2, ce->ce_fp); - if (digested) - MD5Update(&mdContext, b2, 1); if (skip < 1) { putc((char) *b3, ce->ce_fp); - if (digested) - MD5Update(&mdContext, b3, 1); } } @@ -1871,25 +1632,22 @@ self_delimiting: goto clean_up; } - if (digested) { - unsigned char digest[16]; - - MD5Final(digest, &mdContext); - if (memcmp((char *) digest, (char *) ct->c_digest, - sizeof(digest) / sizeof(digest[0]))) - content_error(NULL, ct, "content integrity suspect (digest mismatch) -- continuing"); - else if (debugsw) - fprintf(stderr, "content integrity confirmed\n"); - } - fseek(ce->ce_fp, 0L, SEEK_SET); ready_to_go: *file = ce->ce_file; + if (own_ct_fp) { + fclose(ct->c_fp); + ct->c_fp = NULL; + } return fileno(ce->ce_fp); clean_up: free_encoding(ct, 0); + if (own_ct_fp) { + fclose(ct->c_fp); + ct->c_fp = NULL; + } return NOTOK; } @@ -1928,14 +1686,13 @@ InitQuoted(CT ct) static int openQuoted(CT ct, char **file) { - int cc, digested, len, quoted; + int cc, len, quoted, own_ct_fp = 0; unsigned char *cp, *ep; char buffer[BUFSIZ]; - unsigned char mask; + unsigned char mask = 0; CE ce; /* sbeck -- handle suffixes */ CI ci; - MD5_CTX mdContext; ce = ct->c_cefile; if (ce->ce_fp) { @@ -1972,12 +1729,14 @@ openQuoted(CT ct, char **file) } if (cp != NULL && *cp != '\0') { if (ce->ce_unlink) { - // Temporary file already exists, so we rename to - // version with extension. + /* + ** Temporary file already exists, so we rename to + ** version with extension. + */ char *file_org = strdup(ce->ce_file); ce->ce_file = add(cp, ce->ce_file); if (rename(file_org, ce->ce_file)) { - adios(ce->ce_file, "unable to rename %s to ", + adios(EX_IOERR, ce->ce_file, "unable to rename %s to ", file_org); } free(file_org); @@ -1993,27 +1752,19 @@ openQuoted(CT ct, char **file) return NOTOK; } - if ((ce->ce_fp = fopen(ce->ce_file, "w+")) == NULL) { - content_error(ce->ce_file, ct, - "unable to fopen for reading/writing"); - return NOTOK; - } - if ((len = ct->c_end - ct->c_begin) < 0) - adios(NULL, "internal error(2)"); + adios(EX_SOFTWARE, NULL, "internal error(2)"); - 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; + if (!ct->c_fp) { + if ((ct->c_fp = fopen(ct->c_file, "r")) == NULL) { + content_error(ct->c_file, ct, + "unable to open for reading"); + return NOTOK; + } + own_ct_fp = 1; } - if ((digested = ct->c_digested)) - MD5Init(&mdContext); - quoted = 0; -#ifdef lint - mask = 0; -#endif fseek(ct->c_fp, ct->c_begin, SEEK_SET); while (len > 0) { @@ -2044,8 +1795,6 @@ openQuoted(CT ct, char **file) mask <<= 4; mask |= hex2nib[*cp & 0x7f]; putc(mask, ce->ce_fp); - if (digested) - MD5Update(&mdContext, &mask, 1); if (ferror(ce->ce_fp)) { content_error(ce->ce_file, ct, "error writing to"); goto clean_up; @@ -2098,13 +1847,6 @@ openQuoted(CT ct, char **file) /* Just show the raw byte. */ putc(*cp, ce->ce_fp); - if (digested) { - if (*cp == '\n') { - MD5Update(&mdContext, (unsigned char *) "\r\n",2); - } else { - MD5Update(&mdContext, (unsigned char *) cp, 1); - } - } if (ferror(ce->ce_fp)) { content_error(ce->ce_file, ct, "error writing to"); @@ -2124,25 +1866,22 @@ openQuoted(CT ct, char **file) goto clean_up; } - if (digested) { - unsigned char digest[16]; - - MD5Final(digest, &mdContext); - if (memcmp((char *) digest, (char *) ct->c_digest, - sizeof(digest) / sizeof(digest[0]))) - content_error(NULL, ct, "content integrity suspect (digest mismatch) -- continuing"); - else if (debugsw) - fprintf(stderr, "content integrity confirmed\n"); - } - fseek(ce->ce_fp, 0L, SEEK_SET); ready_to_go: *file = ce->ce_file; + if (own_ct_fp) { + fclose(ct->c_fp); + ct->c_fp = NULL; + } return fileno(ce->ce_fp); clean_up: free_encoding(ct, 0); + if (own_ct_fp) { + fclose(ct->c_fp); + ct->c_fp = NULL; + } return NOTOK; } @@ -2165,7 +1904,7 @@ Init7Bit(CT ct) int open7Bit(CT ct, char **file) { - int cc, fd, len; + int cc, fd, len, own_ct_fp = 0; char buffer[BUFSIZ]; /* sbeck -- handle suffixes */ char *cp; @@ -2202,7 +1941,7 @@ open7Bit(CT ct, char **file) cp = context_find(buffer); if (cp == NULL || *cp == '\0') { snprintf(buffer, sizeof(buffer), "%s-suffix-%s", invo_name, - ci->ci_type); + ci->ci_type); cp = context_find(buffer); } if (cp != NULL && *cp != '\0') { @@ -2214,7 +1953,7 @@ open7Bit(CT ct, char **file) char *file_org = strdup(ce->ce_file); ce->ce_file = add(cp, ce->ce_file); if (rename(file_org, ce->ce_file)) { - adios(ce->ce_file, "unable to rename %s to ", + adios(EX_IOERR, ce->ce_file, "unable to rename %s to ", file_org); } free(file_org); @@ -2280,11 +2019,15 @@ open7Bit(CT ct, char **file) } if ((len = ct->c_end - ct->c_begin) < 0) - adios(NULL, "internal error(3)"); + adios(EX_SOFTWARE, NULL, "internal error(3)"); - 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; + if (!ct->c_fp) { + if ((ct->c_fp = fopen(ct->c_file, "r")) == NULL) { + content_error(ct->c_file, ct, + "unable to open for reading"); + return NOTOK; + } + own_ct_fp = 1; } lseek(fd = fileno(ct->c_fp), (off_t) ct->c_begin, SEEK_SET); @@ -2322,544 +2065,17 @@ open7Bit(CT ct, char **file) ready_to_go: *file = ce->ce_file; + if (own_ct_fp) { + fclose(ct->c_fp); + ct->c_fp = NULL; + } return fileno(ce->ce_fp); clean_up: free_encoding(ct, 0); - return NOTOK; -} - - -/* -** External -*/ - -static int -openExternal(CT ct, CT cb, CE ce, char **file, int *fd) -{ - char cachefile[BUFSIZ]; - - if (ce->ce_fp) { - fseek(ce->ce_fp, 0L, SEEK_SET); - goto ready_already; - } - - 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; - } - goto ready_already; - } - - if (find_cache(ct, rcachesw, (int *) 0, cb->c_id, - cachefile, sizeof(cachefile)) != NOTOK) { - if ((ce->ce_fp = fopen(cachefile, "r"))) { - ce->ce_file = getcpy(cachefile); - ce->ce_unlink = 0; - goto ready_already; - } else { - admonish(cachefile, "unable to fopen for reading"); - } - } - - return OK; - -ready_already: - *file = ce->ce_file; - *fd = fileno(ce->ce_fp); - return DONE; -} - -/* -** File -*/ - -static int -InitFile(CT ct) -{ - return init_encoding(ct, openFile); -} - - -static int -openFile(CT ct, char **file) -{ - int fd, cachetype; - char cachefile[BUFSIZ]; - struct exbody *e = ct->c_ctexbody; - CE ce = ct->c_cefile; - - switch (openExternal(e->eb_parent, e->eb_content, ce, file, &fd)) { - case NOTOK: - return NOTOK; - case OK: - break; - case DONE: - return fd; - } - - if (!e->eb_name) { - content_error(NULL, ct, "missing name parameter"); - return NOTOK; - } - - ce->ce_file = getcpy(e->eb_name); - ce->ce_unlink = 0; - - if ((ce->ce_fp = fopen(ce->ce_file, "r")) == NULL) { - content_error(ce->ce_file, ct, "unable to fopen for reading"); - return NOTOK; - } - - if ((!e->eb_permission || - mh_strcasecmp(e->eb_permission, "read-write")) && - find_cache(NULL, wcachesw, &cachetype, - e->eb_content->c_id, cachefile, sizeof(cachefile)) - != NOTOK) { - int mask; - FILE *fp; - - mask = umask(cachetype ? ~m_gmprot() : 0222); - if ((fp = fopen(cachefile, "w"))) { - int cc; - char buffer[BUFSIZ]; - FILE *gp = ce->ce_fp; - - fseek(gp, 0L, SEEK_SET); - - while ((cc = fread(buffer, sizeof(*buffer), - sizeof(buffer), gp)) > 0) - fwrite(buffer, sizeof(*buffer), cc, fp); - fflush(fp); - - if (ferror(gp)) { - admonish(ce->ce_file, "error reading"); - unlink(cachefile); - } else if (ferror(fp)) { - admonish(cachefile, "error writing"); - unlink(cachefile); - } - fclose(fp); - } - umask(mask); - } - - fseek(ce->ce_fp, 0L, SEEK_SET); - *file = ce->ce_file; - return fileno(ce->ce_fp); -} - -/* -** FTP -*/ - -static int -InitFTP(CT ct) -{ - return init_encoding(ct, openFTP); -} - - -static int -openFTP(CT ct, char **file) -{ - int cachetype, caching, fd; - int len, buflen; - char *bp, *ftp, *user, *pass; - char buffer[BUFSIZ], cachefile[BUFSIZ]; - struct exbody *e; - CE ce; - static char *username = NULL; - static char *password = NULL; - int child_id, i, vecp; - char *vec[9]; - - e = ct->c_ctexbody; - ce = ct->c_cefile; - - if ((ftp = context_find(nmhaccessftp)) && !*ftp) - ftp = NULL; - - if (!ftp) - return NOTOK; - - switch (openExternal(e->eb_parent, e->eb_content, ce, file, &fd)) { - case NOTOK: - return NOTOK; - case OK: - break; - case DONE: - return fd; - } - - if (!e->eb_name || !e->eb_site) { - content_error(NULL, ct, "missing %s parameter", - e->eb_name ? "site": "name"); - return NOTOK; - } - - if (xpid) { - if (xpid < 0) - xpid = -xpid; - pidcheck(pidwait(xpid, NOTOK)); - xpid = 0; - } - - /* Get the buffer ready to go */ - bp = buffer; - buflen = sizeof(buffer); - - /* - ** Construct the query message for user - */ - snprintf(bp, buflen, "Retrieve %s", e->eb_name); - len = strlen(bp); - bp += len; - buflen -= len; - - if (e->eb_partno) { - snprintf(bp, buflen, " (content %s)", e->eb_partno); - len = strlen(bp); - bp += len; - buflen -= len; - } - - snprintf(bp, buflen, "\n using %sFTP from site %s", - e->eb_flags ? "anonymous " : "", e->eb_site); - len = strlen(bp); - bp += len; - buflen -= len; - - if (e->eb_size > 0) { - snprintf(bp, buflen, " (%lu octets)", e->eb_size); - len = strlen(bp); - bp += len; - buflen -= len; - } - snprintf(bp, buflen, "? "); - - /* - ** Now, check the answer - */ - if (!getanswer(buffer)) - return NOTOK; - - if (e->eb_flags) { - user = "anonymous"; - snprintf(buffer, sizeof(buffer), "%s@%s", getusername(), - LocalName()); - pass = buffer; - } else { - ruserpass(e->eb_site, &username, &password); - user = username; - pass = password; - } - - ce->ce_unlink = (*file == NULL); - caching = 0; - cachefile[0] = '\0'; - if ((!e->eb_permission || - mh_strcasecmp(e->eb_permission, "read-write")) && - find_cache(NULL, wcachesw, &cachetype, - e->eb_content->c_id, cachefile, sizeof(cachefile)) - != NOTOK) { - if (*file == NULL) { - ce->ce_unlink = 0; - caching = 1; - } - } - - if (*file) - ce->ce_file = getcpy(*file); - else if (caching) - ce->ce_file = getcpy(cachefile); - else - ce->ce_file = getcpy(m_mktemp(tmp, NULL, NULL)); - - if ((ce->ce_fp = fopen(ce->ce_file, "w+")) == NULL) { - content_error (ce->ce_file, ct, - "unable to fopen for reading/writing"); - return NOTOK; - } - - vecp = 0; - vec[vecp++] = mhbasename(ftp); - vec[vecp++] = e->eb_site; - vec[vecp++] = user; - vec[vecp++] = pass; - vec[vecp++] = e->eb_dir; - vec[vecp++] = e->eb_name; - vec[vecp++] = ce->ce_file, - vec[vecp++] = e->eb_mode && - !mh_strcasecmp(e->eb_mode, "ascii") ? - "ascii" : "binary"; - vec[vecp] = NULL; - - fflush(stdout); - - for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) - sleep(5); - switch (child_id) { - case NOTOK: - adios("fork", "unable to"); - /* NOTREACHED */ - - case OK: - close(fileno(ce->ce_fp)); - execvp(ftp, vec); - fprintf(stderr, "unable to exec "); - perror(ftp); - _exit(-1); - /* NOTREACHED */ - - default: - if (pidXwait(child_id, NULL)) { - username = password = NULL; - ce->ce_unlink = 1; - return NOTOK; - } - break; - } - - if (cachefile[0]) { - if (caching) - chmod(cachefile, cachetype ? m_gmprot() : 0444); - else { - int mask; - FILE *fp; - - mask = umask(cachetype ? ~m_gmprot() : 0222); - if ((fp = fopen(cachefile, "w"))) { - int cc; - FILE *gp = ce->ce_fp; - - fseek(gp, 0L, SEEK_SET); - - while ((cc= fread(buffer, sizeof(*buffer), - sizeof(buffer), gp)) > 0) - fwrite(buffer, sizeof(*buffer), cc, fp); - fflush(fp); - - if (ferror(gp)) { - admonish(ce->ce_file, "error reading"); - unlink(cachefile); - } else if (ferror(fp)) { - admonish(cachefile, "error writing"); - unlink(cachefile); - } - fclose(fp); - } - umask(mask); - } - } - - fseek(ce->ce_fp, 0L, SEEK_SET); - *file = ce->ce_file; - return fileno(ce->ce_fp); -} - - -/* -** Mail -*/ - -static int -InitMail(CT ct) -{ - return init_encoding(ct, openMail); -} - - -static int -openMail(CT ct, char **file) -{ - int child_id, fd, i, vecp; - int len, buflen; - char *bp, buffer[BUFSIZ], *vec[7]; - struct exbody *e = ct->c_ctexbody; - CE ce = ct->c_cefile; - - switch (openExternal(e->eb_parent, e->eb_content, ce, file, &fd)) { - case NOTOK: - return NOTOK; - case OK: - break; - case DONE: - return fd; - } - - if (!e->eb_server) { - content_error(NULL, ct, "missing server parameter"); - return NOTOK; - } - - if (xpid) { - if (xpid < 0) - xpid = -xpid; - pidcheck(pidwait(xpid, NOTOK)); - xpid = 0; - } - - /* Get buffer ready to go */ - bp = buffer; - buflen = sizeof(buffer); - - /* Now, construct query message */ - snprintf(bp, buflen, "Retrieve content"); - len = strlen(bp); - bp += len; - buflen -= len; - - if (e->eb_partno) { - snprintf(bp, buflen, " %s", e->eb_partno); - len = strlen(bp); - bp += len; - buflen -= len; - } - - snprintf(bp, buflen, " by asking %s\n\n%s\n? ", e->eb_server, - e->eb_subject ? e->eb_subject : e->eb_body); - - /* Now, check answer */ - if (!getanswer(buffer)) - return NOTOK; - - vecp = 0; - vec[vecp++] = mhbasename(mailproc); - vec[vecp++] = e->eb_server; - vec[vecp++] = "-subject"; - vec[vecp++] = e->eb_subject ? e->eb_subject : "mail-server request"; - vec[vecp++] = "-body"; - vec[vecp++] = e->eb_body; - vec[vecp] = NULL; - - for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) - sleep(5); - switch (child_id) { - case NOTOK: - advise("fork", "unable to"); - return NOTOK; - - case OK: - execvp(mailproc, vec); - fprintf(stderr, "unable to exec "); - perror(mailproc); - _exit(-1); - /* NOTREACHED */ - - default: - if (pidXwait(child_id, NULL) == OK) - advise(NULL, "request sent"); - break; - } - - if (*file == NULL) { - ce->ce_file = getcpy(m_mktemp(tmp, NULL, NULL)); - ce->ce_unlink = 1; - } else { - ce->ce_file = getcpy(*file); - ce->ce_unlink = 0; - } - - if ((ce->ce_fp = fopen(ce->ce_file, "w+")) == NULL) { - content_error(ce->ce_file, ct, - "unable to fopen for reading/writing"); - return NOTOK; - } - - /* - ** showproc is for mhshow and mhstore, though mhlist -debug - ** prints it, too. - */ - if (ct->c_showproc) - free(ct->c_showproc); - ct->c_showproc = getcpy("true"); - - fseek(ce->ce_fp, 0L, SEEK_SET); - *file = ce->ce_file; - return fileno(ce->ce_fp); -} - - -static int -readDigest(CT ct, char *cp) -{ - int bitno, skip; - unsigned long bits; - char *bp = cp; - unsigned char *dp, value, *ep; - unsigned char *b, *b1, *b2, *b3; - - b = (unsigned char *) &bits, - b1 = &b[endian > 0 ? 1 : 2], - b2 = &b[endian > 0 ? 2 : 1], - b3 = &b[endian > 0 ? 3 : 0]; - bitno = 18; - bits = 0L; - skip = 0; - - for (ep = (dp = ct->c_digest) - + sizeof(ct->c_digest) / sizeof(ct->c_digest[0]); *cp; cp++) - switch (*cp) { - default: - if (skip || (*cp & 0x80) || - (value = b642nib[*cp & 0x7f]) - > 0x3f) { - if (debugsw) - fprintf(stderr, "invalid BASE64 encoding\n"); - return NOTOK; - } - - bits |= value << bitno; -test_end: - if ((bitno -= 6) < 0) { - if (dp + (3 - skip) > ep) - goto invalid_digest; - *dp++ = *b1; - if (skip < 2) { - *dp++ = *b2; - if (skip < 1) - *dp++ = *b3; - } - bitno = 18; - bits = 0L; - skip = 0; - } - break; - - case '=': - if (++skip > 3) - goto self_delimiting; - goto test_end; - } - if (bitno != 18) { - if (debugsw) - fprintf(stderr, "premature ending (bitno %d)\n", - bitno); - - return NOTOK; - } -self_delimiting: - if (dp != ep) { -invalid_digest: - if (debugsw) { - while (*cp) - cp++; - fprintf(stderr, "invalid MD5 digest (got %d octets)\n", - (int)(cp - bp)); - } - - return NOTOK; - } - - if (debugsw) { - fprintf(stderr, "MD5 digest="); - for (dp = ct->c_digest; dp < ep; dp++) - fprintf(stderr, "%02x", *dp & 0xff); - fprintf(stderr, "\n"); + if (own_ct_fp) { + fclose(ct->c_fp); + ct->c_fp = NULL; } - - return OK; + return NOTOK; }