X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=rfc822.c;h=5315f1b63e934295a016470714837fff0ca64faa;hb=4e1db9d3b89d27acf1b80c51c02e73cc7ad69bc1;hp=3bbad5c4e06896d7bd4fb77536eabd75fa86864f;hpb=9c624b9ce0f6a566193507bbcf4dd360f7a08445;p=~andy%2Ffetchmail diff --git a/rfc822.c b/rfc822.c index 3bbad5c4..5315f1b6 100644 --- a/rfc822.c +++ b/rfc822.c @@ -12,40 +12,63 @@ #include #endif +#include "config.h" #include "fetchmail.h" +#include "i18n.h" #define HEADER_END(p) ((p)[0] == '\n' && ((p)[1] != ' ' && (p)[1] != '\t')) #ifdef TESTMAIN static int verbose; +char *program_name = "rfc822"; #endif /* TESTMAIN */ -char *reply_hack(buf, host) +unsigned char *reply_hack(buf, host) /* hack message headers so replies will work properly */ -char *buf; /* header to be hacked */ -const char *host; /* server hostname */ +unsigned char *buf; /* header to be hacked */ +const unsigned char *host; /* server hostname */ { - char *from, *cp, last_nws = '\0'; + unsigned char *from, *cp, last_nws = '\0', *parens_from = NULL; int parendepth, state, has_bare_name_part, has_host_part; +#ifndef TESTMAIN int addresscount = 1; +#endif /* TESTMAIN */ - if (strncasecmp("From: ", buf, 6) - && strncasecmp("To: ", buf, 4) - && strncasecmp("Reply-To: ", buf, 10) - && strncasecmp("Return-Path: ", buf, 13) - && strncasecmp("Cc: ", buf, 4) - && strncasecmp("Bcc: ", buf, 5)) { + if (strncasecmp("From:", buf, 5) + && strncasecmp("To:", buf, 3) + && strncasecmp("Reply-To:", buf, 9) + && strncasecmp("Return-Path:", buf, 12) + && strncasecmp("Cc:", buf, 3) + && strncasecmp("Bcc:", buf, 4) + && strncasecmp("Resent-From:", buf, 12) + && strncasecmp("Resent-To:", buf, 10) + && strncasecmp("Resent-Cc:", buf, 10) + && strncasecmp("Resent-Bcc:", buf, 11) + && strncasecmp("Apparently-From:", buf, 16) + && strncasecmp("Apparently-To:", buf, 14) + && strncasecmp("Sender:", buf, 7) + && strncasecmp("Resent-Sender:", buf, 14) + ) { return(buf); } #ifndef TESTMAIN + if (outlevel >= O_DEBUG) + report_build(stdout, _("About to rewrite %s"), buf); + /* make room to hack the address; buf must be malloced */ for (cp = buf; *cp; cp++) if (*cp == ',' || isspace(*cp)) addresscount++; - buf = (char *)xrealloc(buf, strlen(buf) + addresscount * strlen(host) + 1); + buf = (unsigned char *)xrealloc(buf, strlen(buf) + addresscount * strlen(host) + 1); #endif /* TESTMAIN */ + /* + * This is going to foo up on some ill-formed addresses. + * Note that we don't rewrite the fake address <> in order to + * avoid screwing up bounce suppression with a null Return-Path. + */ + parendepth = state = 0; has_host_part = has_bare_name_part = FALSE; for (from = buf; *from; from++) @@ -58,10 +81,12 @@ const char *host; /* server hostname */ } #endif /* TESTMAIN */ if (state != 2) + { if (*from == '(') ++parendepth; else if (*from == ')') --parendepth; + } if (!parendepth && !has_host_part) switch (state) @@ -85,13 +110,17 @@ const char *host; /* server hostname */ * an obscure misfeature described in sections * 6.1, 6.2.6, and A.1.5 of the RFC822 standard. */ - else if ((*from == ',' || HEADER_END(from) || from[1] == '(') + else if ((*from == ',' || HEADER_END(from)) && has_bare_name_part && !has_host_part && last_nws != ';') { int hostlen; + unsigned char *p; + p = from; + if (parens_from) + from = parens_from; while (isspace(*from) || (*from == ',')) --from; from++; @@ -100,9 +129,16 @@ const char *host; /* server hostname */ cp[hostlen+1] = *cp; *from++ = '@'; memcpy(from, host, hostlen); - from += hostlen; + from = p + hostlen + 1; has_host_part = TRUE; } + else if (from[1] == '(' + && has_bare_name_part + && !has_host_part + && last_nws != ';' && last_nws != ')') + { + parens_from = from; + } else if (!isspace(*from)) has_bare_name_part = TRUE; break; @@ -115,7 +151,7 @@ const char *host; /* server hostname */ case 3: /* we're in a <>-enclosed address */ if (*from == '@') has_host_part = TRUE; - else if (*from == '>') + else if (*from == '>' && from[-1] != '<') { state = 1; if (!has_host_part) @@ -139,21 +175,26 @@ const char *host; /* server hostname */ */ if (from[-1] == ',' && !parendepth) { has_host_part = has_bare_name_part = FALSE; + parens_from = NULL; } } +#ifndef TESTMAIN + if (outlevel >= O_DEBUG) + report_complete(stdout, _("Rewritten version is %s\n"), buf); +#endif /* TESTMAIN */ return(buf); } -char *nxtaddr(hdr) +unsigned char *nxtaddr(hdr) /* parse addresses in succession out of a specified RFC822 header */ -const char *hdr; /* header to be parsed, NUL to continue previous hdr */ +const unsigned char *hdr; /* header to be parsed, NUL to continue previous hdr */ { - static char *tp, address[POPBUFSIZE+1]; - static const char *hp; + static unsigned char *tp, address[POPBUFSIZE+1]; + static const unsigned char *hp; static int state, oldstate; #ifdef TESTMAIN - static const char *orighdr; + static const unsigned char *orighdr; #endif /* TESTMAIN */ int parendepth = 0; @@ -196,14 +237,14 @@ const char *hdr; /* header to be parsed, NUL to continue previous hdr */ continue; *++tp = '\0'; } - return(tp > address ? (tp = address) : (char *)NULL); + return(tp > address ? (tp = address) : (unsigned char *)NULL); } else if (*hp == '\\') /* handle RFC822 escaping */ { if (state != INSIDE_PARENS) { *tp++ = *hp++; /* take the escape */ - *tp++ = *hp; /* take following char */ + *tp++ = *hp; /* take following unsigned char */ } } else switch (state) @@ -308,9 +349,9 @@ const char *hdr; /* header to be parsed, NUL to continue previous hdr */ } #ifdef TESTMAIN -static void parsebuf(char *longbuf, int reply) +static void parsebuf(unsigned char *longbuf, int reply) { - char *cp; + unsigned char *cp; if (reply) { @@ -318,19 +359,19 @@ static void parsebuf(char *longbuf, int reply) printf("Rewritten buffer: %s", longbuf); } else - if ((cp = nxtaddr(longbuf)) != (char *)NULL) + if ((cp = nxtaddr(longbuf)) != (unsigned char *)NULL) do { printf("\t-> \"%s\"\n", cp); } while - ((cp = nxtaddr((char *)NULL)) != (char *)NULL); + ((cp = nxtaddr((unsigned char *)NULL)) != (unsigned char *)NULL); } main(int argc, char *argv[]) { - char buf[MSGBUFSIZE], longbuf[BUFSIZ]; - int ch, reply; + unsigned char buf[MSGBUFSIZE], longbuf[BUFSIZ]; + int ch, reply; verbose = reply = FALSE; while ((ch = getopt(argc, argv, "rv")) != EOF)