X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/c6e5547c9da87292c554449e8b91d83bac70b7be..b3d4a4452c332fc3550db3fbdf9e02027b41e985:/sbr/mf.c diff --git a/sbr/mf.c b/sbr/mf.c index 27c06bb1..4f59e616 100644 --- a/sbr/mf.c +++ b/sbr/mf.c @@ -1,25 +1,18 @@ - -/* - * mf.c -- mail filter subroutines - * - * $Id$ +/* mf.c -- mail filter subroutines * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ -#include -#include -#include +#include "h/mh.h" +#include "h/mf.h" +#include "h/utils.h" /* * static prototypes */ -static char *getcpy (char *); -static char *add (char *, char *); -static void compress (char *, char *); -static int isat (char *); +static int isat (const char *); static int parse_address (void); static int phrase (char *); static int route_addr (char *); @@ -29,221 +22,13 @@ static int route (char *); static int my_lex (char *); -static char * -getcpy (char *s) -{ - register char *p; - - if (!s) { -/* causes compiles to blow up because the symbol _cleanup is undefined - where did this ever come from? */ - /* _cleanup(); */ - abort(); - for(;;) - pause(); - } - if ((p = malloc ((size_t) (strlen (s) + 2)))) - strcpy (p, s); - return p; -} - - -static char * -add (char *s1, char *s2) -{ - register char *p; - - if (!s2) - return getcpy (s1); - - if ((p = malloc ((size_t) (strlen (s1) + strlen (s2) + 2)))) - sprintf (p, "%s%s", s2, s1); - free (s2); - return p; -} - -int -isfrom(char *string) -{ - return (strncmp (string, "From ", 5) == 0 - || strncmp (string, ">From ", 6) == 0); -} - - -int -lequal (char *a, char *b) -{ - for (; *a; a++, b++) - if (*b == 0) - return FALSE; - else { - char c1 = islower (*a) ? toupper (*a) : *a; - char c2 = islower (*b) ? toupper (*b) : *b; - if (c1 != c2) - return FALSE; - } - - return (*b == 0); -} - - -/* - * seekadrx() is tricky. We want to cover both UUCP-style and ARPA-style - * addresses, so for each list of addresses we see if we can find some - * character to give us a hint. - */ - - -#define CHKADR 0 /* undertermined address style */ -#define UNIXDR 1 /* UNIX-style address */ -#define ARPADR 2 /* ARPAnet-style address */ - - -static char *punctuators = ";<>.()[]"; -static char *vp = NULL; -static char *tp = NULL; - -static struct adrx adrxs1; - - -struct adrx * -seekadrx (char *addrs) -{ - static int state = CHKADR; - register char *cp; - register struct adrx *adrxp; - - if (state == CHKADR) - for (state = UNIXDR, cp = addrs; *cp; cp++) - if (strchr(punctuators, *cp)) { - state = ARPADR; - break; - } - - switch (state) { - case UNIXDR: - adrxp = uucpadrx (addrs); - break; - - case ARPADR: - default: - adrxp = getadrx (addrs); - break; - } - - if (adrxp == NULL) - state = CHKADR; - - return adrxp; -} - - -/* - * uucpadrx() implements a partial UUCP-style address parser. It's based - * on the UUCP notion that addresses are separated by spaces or commas. - */ - - -struct adrx * -uucpadrx (char *addrs) -{ - register char *cp, *wp, *xp, *yp, *zp; - register struct adrx *adrxp = &adrxs1; - - if (vp == NULL) { - vp = tp = getcpy (addrs); - compress (addrs, vp); - } - else - if (tp == NULL) { - free (vp); - vp = NULL; - return NULL; - } - - for (cp = tp; isspace (*cp); cp++) - continue; - if (*cp == 0) { - free (vp); - vp = tp = NULL; - return NULL; - } - - if ((wp = strchr(cp, ',')) == NULL) { - if ((wp = strchr(cp, ' ')) != NULL) { - xp = wp; - while (isspace (*xp)) - xp++; - if (*xp != 0 && isat (--xp)) { - yp = xp + 4; - while (isspace (*yp)) - yp++; - if (*yp != 0) { - if ((zp = strchr(yp, ' ')) != NULL) - *zp = 0, tp = ++zp; - else - tp = NULL; - } - else - *wp = 0, tp = ++wp; - } - else - *wp = 0, tp = ++wp; - } - else - tp = NULL; - } - else - *wp = 0, tp = ++wp; - - if (adrxp->text) - free (adrxp->text); - adrxp->text = getcpy (cp); - adrxp->mbox = cp; - adrxp->host = adrxp->path = NULL; - if ((wp = strrchr(cp, '@')) != NULL) { - *wp++ = 0; - adrxp->host = *wp ? wp : NULL; - } - else - for (wp = cp + strlen (cp) - 4; wp >= cp; wp--) - if (isat (wp)) { - *wp++ = 0; - adrxp->host = wp + 3; - } - - adrxp->pers = adrxp->grp = adrxp->note = adrxp->err = NULL; - adrxp->ingrp = 0; - - return adrxp; -} - - -static void -compress (char *fp, char *tp) -{ - register char c, *cp; - - for (c = ' ', cp = tp; (*tp = *fp++) != 0;) - if (isspace (*tp)) { - if (c != ' ') - *tp++ = c = ' '; - } - else - c = *tp++; - - if (c == ' ' && cp < tp) - *--tp = 0; -} - - static int -isat (char *p) +isat (const char *p) { - return (strncmp (p, " AT ", 4) - && strncmp (p, " At ", 4) - && strncmp (p, " aT ", 4) - && strncmp (p, " at ", 4) ? FALSE : TRUE); + return *p == ' ' && + (p[1] == 'a' || p[1] == 'A') && + (p[2] == 't' || p[2] == 'T') && + p[3] == ' '; } @@ -252,7 +37,7 @@ isat (char *p) * getadrx() implements a partial 822-style address parser. The parser * is neither complete nor correct. It does however recognize nearly all * of the 822 address syntax. In addition it handles the majority of the - * 733 syntax as well. Most problems arise from trying to accomodate both. + * 733 syntax as well. Most problems arise from trying to accommodate both. * * In terms of 822, the route-specification in * @@ -305,8 +90,6 @@ isat (char *p) * */ -#define QUOTE '\\' - #define LX_END 0 #define LX_ERR 1 #define LX_ATOM 2 @@ -335,7 +118,7 @@ static struct specials special[] = { { '@', LX_AT }, { '(', LX_ERR }, { ')', LX_ERR }, - { QUOTE, LX_ERR }, + { '\\', LX_ERR }, { '"', LX_ERR }, { '[', LX_ERR }, { ']', LX_ERR }, @@ -352,7 +135,7 @@ static char *ap = NULL; static char *pers = NULL; static char *mbox = NULL; static char *host = NULL; -static char *path = NULL; +static char *routepath = NULL; static char *grp = NULL; static char *note = NULL; static char err[BUFSIZ]; @@ -361,79 +144,59 @@ static char adr[BUFSIZ]; static struct adrx adrxs2; +/* eai = Email Address Internationalization */ struct adrx * -getadrx (char *addrs) +getadrx (const char *addrs, int eai) { - register char *bp; - register struct adrx *adrxp = &adrxs2; - - if (pers) - free (pers); - if (mbox) - free (mbox); - if (host) - free (host); - if (path) - free (path); - if (grp) - free (grp); - if (note) - free (note); - pers = mbox = host = path = grp = note = NULL; + int parse; + char *bp; + struct adrx *adrxp = &adrxs2; + + free(pers); + free(mbox); + free(host); + free(routepath); + free(grp); + free(note); + pers = mbox = host = routepath = grp = note = NULL; err[0] = 0; if (dp == NULL) { - dp = cp = getcpy (addrs ? addrs : ""); + dp = cp = strdup (FENDNULL(addrs)); glevel = 0; + } else if (cp == NULL) { + free (dp); + dp = NULL; + return NULL; } - else - if (cp == NULL) { - free (dp); - dp = NULL; - return NULL; - } - - switch (parse_address ()) { - case DONE: - free (dp); - dp = cp = NULL; - return NULL; - case OK: - switch (last_lex) { - case LX_COMA: - case LX_END: - break; + parse = parse_address(); + if (parse == DONE) { + free(dp); + dp = cp = NULL; + return NULL; + } + if (parse == OK && last_lex != LX_COMA && last_lex != LX_END) { + /* catch trailing comments */ + bp = cp; + my_lex(adr); + cp = bp; + } - default: /* catch trailing comments */ - bp = cp; - my_lex (adr); - cp = bp; - break; - } - break; - - default: - break; - } + /* Reject the address if key fields contain 8bit characters. */ + if (!eai && + (contains8bit(mbox, NULL) || contains8bit(host, NULL) || + contains8bit(routepath, NULL) || contains8bit(grp, NULL))) + strcpy(err, "Address contains 8-bit characters"); if (err[0]) - for (;;) { - switch (last_lex) { - case LX_COMA: - case LX_END: - break; + while (last_lex != LX_COMA && last_lex != LX_END) + my_lex(adr); - default: - my_lex (adr); - continue; - } - break; - } - while (isspace (*ap)) + while (isspace ((unsigned char) *ap)) ap++; if (cp) - sprintf (adr, "%.*s", cp - ap, ap); + snprintf(adr, sizeof adr, "%.*s", (int)(cp - ap), ap); else strcpy (adr, ap); bp = adr + strlen (adr) - 1; @@ -444,7 +207,7 @@ getadrx (char *addrs) adrxp->pers = pers; adrxp->mbox = mbox; adrxp->host = host; - adrxp->path = path; + adrxp->path = routepath; adrxp->grp = grp; adrxp->ingrp = ingrp; adrxp->note = note; @@ -464,7 +227,7 @@ again: ; switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: - pers = getcpy (buffer); + pers = strdup (buffer); break; case LX_SEMI: @@ -472,11 +235,10 @@ again: ; strcpy (err, "extraneous semi-colon"); return NOTOK; } + /* FALLTHRU */ case LX_COMA: - if (note) { - free (note); - note = NULL; - } + free(note); + note = NULL; goto again; case LX_END: @@ -492,7 +254,7 @@ again: ; return OK; /* why be choosy? */ default: - sprintf (err, "illegal address construct (%s)", buffer); + snprintf(err, sizeof err, "illegal address construct (%s)", buffer); return NOTOK; } @@ -511,13 +273,13 @@ again: ; return NOTOK; if (last_lex == LX_RBRK) return OK; - sprintf (err, "missing right-bracket (%s)", buffer); + snprintf(err, sizeof err, "missing right-bracket (%s)", buffer); return NOTOK; case LX_COLN: get_group: ; if (glevel++ > 0) { - sprintf (err, "nested groups not allowed (%s)", pers); + snprintf(err, sizeof err, "nested groups not allowed (%s)", pers); return NOTOK; } grp = add (": ", pers); @@ -546,7 +308,7 @@ again: ; goto more_phrase; default: - sprintf (err, "no mailbox in address, only a phrase (%s%s)", + snprintf(err, sizeof err, "no mailbox in address, only a phrase (%s%s)", pers, buffer); return NOTOK; } @@ -577,12 +339,13 @@ again: ; strcpy (err, "extraneous semi-colon"); return NOTOK; } + return OK; case LX_COMA: case LX_END: return OK; default: - sprintf (err, "junk after local@domain (%s)", buffer); + snprintf(err, sizeof err, "junk after local@domain (%s)", buffer); return NOTOK; } @@ -599,7 +362,7 @@ again: ; return OK; default: - sprintf (err, "missing mailbox (%s)", buffer); + snprintf(err, sizeof err, "missing mailbox (%s)", buffer); return NOTOK; } } @@ -608,23 +371,19 @@ again: ; static int phrase (char *buffer) { - for (;;) - switch (my_lex (buffer)) { - case LX_ATOM: - case LX_QSTR: - pers = add (buffer, add (" ", pers)); - continue; + int lex; - default: - return OK; - } + while ((lex = my_lex(buffer)) == LX_ATOM || lex == LX_QSTR) + pers = add(buffer, add(" ", pers)); + + return OK; } static int route_addr (char *buffer) { - register char *pp = cp; + char *pp = cp; if (my_lex (buffer) == LX_AT) { if (route (buffer) == NOTOK) @@ -647,7 +406,7 @@ route_addr (char *buffer) return OK; default: - sprintf (err, "no at-sign after local-part (%s)", buffer); + snprintf(err, sizeof err, "no at-sign after local-part (%s)", buffer); return NOTOK; } } @@ -666,7 +425,7 @@ local_part (char *buffer) break; default: - sprintf (err, "no mailbox in local-part (%s)", buffer); + snprintf(err, sizeof err, "no mailbox in local-part (%s)", buffer); return NOTOK; } @@ -693,7 +452,7 @@ domain (char *buffer) break; default: - sprintf (err, "no sub-domain in domain-part of address (%s)", buffer); + snprintf(err, sizeof err, "no sub-domain in domain-part of address (%s)", buffer); return NOTOK; } @@ -718,33 +477,33 @@ domain (char *buffer) static int route (char *buffer) { - path = getcpy ("@"); + routepath = mh_xstrdup ("@"); for (;;) { switch (my_lex (buffer)) { case LX_ATOM: case LX_DLIT: - path = add (buffer, path); + routepath = add (buffer, routepath); break; default: - sprintf (err, "no sub-domain in domain-part of address (%s)", buffer); + snprintf(err, sizeof err, "no sub-domain in domain-part of address (%s)", buffer); return NOTOK; } switch (my_lex (buffer)) { case LX_COMA: - path = add (buffer, path); + routepath = add (buffer, routepath); for (;;) { switch (my_lex (buffer)) { case LX_COMA: continue; case LX_AT: - path = add (buffer, path); + routepath = add (buffer, routepath); break; default: - sprintf (err, "no at-sign found for next domain in route (%s)", + snprintf(err, sizeof err, "no at-sign found for next domain in route (%s)", buffer); } break; @@ -753,15 +512,15 @@ route (char *buffer) case LX_AT: /* XXX */ case LX_DOT: - path = add (buffer, path); + routepath = add (buffer, routepath); continue; case LX_COLN: - path = add (buffer, path); + routepath = add (buffer, routepath); return OK; default: - sprintf (err, "no colon found to terminate route (%s)", buffer); + snprintf(err, sizeof err, "no colon found to terminate route (%s)", buffer); return NOTOK; } } @@ -773,7 +532,7 @@ my_lex (char *buffer) { /* buffer should be at least BUFSIZ bytes long */ int i, gotat = 0; - register char c, *bp; + char c, *bp; /* Add C to the buffer bp. After use of this macro *bp is guaranteed to be within the buffer. */ #define ADDCHR(C) do { *bp++ = (C); if ((bp - buffer) == (BUFSIZ-1)) goto my_lex_buffull; } while (0) @@ -781,15 +540,15 @@ my_lex (char *buffer) bp = buffer; *bp = 0; if (!cp) - return (last_lex = LX_END); + return last_lex = LX_END; gotat = isat (cp); c = *cp++; - while (isspace (c)) + while (isspace ((unsigned char) c)) c = *cp++; if (c == 0) { cp = NULL; - return (last_lex = LX_END); + return last_lex = LX_END; } if (c == '(') { @@ -798,17 +557,18 @@ my_lex (char *buffer) switch (c = *cp++) { case 0: cp = NULL; - return (last_lex = LX_ERR); - case QUOTE: + return last_lex = LX_ERR; + case '\\': ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; - return (last_lex = LX_ERR); + return last_lex = LX_ERR; } ADDCHR(c); continue; case '(': i++; + /* FALLTHRU */ default: ADDCHR(c); continue; @@ -817,7 +577,7 @@ my_lex (char *buffer) if (--i < 0) { *bp = 0; note = note ? add (buffer, add (" ", note)) - : getcpy (buffer); + : strdup (buffer); return my_lex (buffer); } } @@ -829,20 +589,21 @@ my_lex (char *buffer) switch (c = *cp++) { case 0: cp = NULL; - return (last_lex = LX_ERR); - case QUOTE: + return last_lex = LX_ERR; + case '\\': ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; - return (last_lex = LX_ERR); + return last_lex = LX_ERR; } + /* FALLTHRU */ default: ADDCHR(c); continue; case '"': ADDCHR(c); *bp = 0; - return (last_lex = LX_QSTR); + return last_lex = LX_QSTR; } } @@ -852,20 +613,21 @@ my_lex (char *buffer) switch (c = *cp++) { case 0: cp = NULL; - return (last_lex = LX_ERR); - case QUOTE: + return last_lex = LX_ERR; + case '\\': ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; - return (last_lex = LX_ERR); + return last_lex = LX_ERR; } + /* FALLTHRU */ default: ADDCHR(c); continue; case ']': ADDCHR(c); *bp = 0; - return (last_lex = LX_DLIT); + return last_lex = LX_DLIT; } } @@ -873,10 +635,10 @@ my_lex (char *buffer) *bp = 0; for (i = 0; special[i].lx_chr != 0; i++) if (c == special[i].lx_chr) - return (last_lex = special[i].lx_val); + return last_lex = special[i].lx_val; - if (iscntrl (c)) - return (last_lex = LX_ERR); + if (iscntrl ((unsigned char) c)) + return last_lex = LX_ERR; for (;;) { if ((c = *cp++) == 0) @@ -884,7 +646,7 @@ my_lex (char *buffer) for (i = 0; special[i].lx_chr != 0; i++) if (c == special[i].lx_chr) goto got_atom; - if (iscntrl (c) || isspace (c)) + if (iscntrl ((unsigned char) c) || isspace ((unsigned char) c)) break; ADDCHR(c); } @@ -901,87 +663,25 @@ got_atom: ; my_lex_buffull: /* Out of buffer space. *bp is the last byte in the buffer */ *bp = 0; - return (last_lex = LX_ERR); + return last_lex = LX_ERR; } char * -legal_person (char *p) +legal_person (const char *p) { int i; - register char *cp; + const char *cp; static char buffer[BUFSIZ]; if (*p == '"') - return p; + return (char *) p; for (cp = p; *cp; cp++) for (i = 0; special[i].lx_chr; i++) if (*cp == special[i].lx_chr) { - sprintf (buffer, "\"%s\"", p); + snprintf(buffer, sizeof buffer, "\"%s\"", p); return buffer; } - return p; -} - - -int -mfgets (FILE *in, char **bp) -{ - int i; - register char *cp, *dp, *ep; - static int len = 0; - static char *pp = NULL; - - if (pp == NULL) - if (!(pp = malloc ((size_t) (len = BUFSIZ)))) - return NOTOK; - - for (ep = (cp = pp) + len - 2;;) { - switch (i = getc (in)) { - case EOF: - eol: ; - if (cp != pp) { - *cp = 0; - *bp = pp; - return OK; - } - eoh: ; - *bp = NULL; - free (pp); - pp = NULL; - return DONE; - - case 0: - continue; - - case '\n': - if (cp == pp) /* end of headers, gobble it */ - goto eoh; - switch (i = getc (in)) { - default: /* end of line */ - case '\n': /* end of headers, save for next call */ - ungetc (i, in); - goto eol; - - case ' ': /* continue headers */ - case '\t': - *cp++ = '\n'; - break; - } /* fall into default case */ - - default: - *cp++ = i; - break; - } - if (cp >= ep) { - if (!(dp = realloc (pp, (size_t) (len += BUFSIZ)))) { - free (pp); - pp = NULL; - return NOTOK; - } - else - cp += dp - pp, ep = (pp = cp) + len - 2; - } - } + return (char *) p; }