#include <h/mh.h>
#include <fcntl.h>
#include <h/signals.h>
-#include <h/md5.h>
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
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.
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 },
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);
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;
/* sbeck -- handle suffixes */
CI ci;
CE ce;
- MD5_CTX mdContext;
b = (unsigned char *) &bits;
b1 = &b[endian > 0 ? 1 : 2];
if ((len = ct->c_end - ct->c_begin) < 0)
adios(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;
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);
}
}
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;
}
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) {
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)");
- 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) {
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;
/* 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");
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;
}
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;
if ((len = ct->c_end - ct->c_begin) < 0)
adios(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);
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;
}
*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");
- }
-
- return OK;
-}