diff options
Diffstat (limited to 'contrib/sendmail/src/headers.c')
-rw-r--r-- | contrib/sendmail/src/headers.c | 206 |
1 files changed, 163 insertions, 43 deletions
diff --git a/contrib/sendmail/src/headers.c b/contrib/sendmail/src/headers.c index b7c5ef9..59bbf56 100644 --- a/contrib/sendmail/src/headers.c +++ b/contrib/sendmail/src/headers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -14,8 +14,9 @@ #include <sendmail.h> -SM_RCSID("@(#)$Id: headers.c,v 8.266.4.9 2003/10/30 00:17:22 gshapiro Exp $") +SM_RCSID("@(#)$Id: headers.c,v 8.286 2004/07/08 17:57:32 ca Exp $") +static HDR *allocheader __P((char *, char *, int, SM_RPOOL_T *)); static size_t fix_mime_header __P((HDR *, ENVELOPE *)); static int priencode __P((char *)); static void put_vanilla_header __P((HDR *, char *, MCI *)); @@ -88,7 +89,7 @@ chompheader(line, pflag, hdrp, e) if (tTd(31, 6)) { sm_dprintf("chompheader: "); - xputs(line); + xputs(sm_debug_file(), line); sm_dprintf("\n"); } @@ -292,11 +293,12 @@ hse: int rscheckflags; char *rs; - /* no ruleset? look for default */ - rs = hi->hi_ruleset; rscheckflags = RSF_COUNT; if (!bitset(hi->hi_flags, H_FROM|H_RCPT)) rscheckflags |= RSF_UNSTRUCTURED; + + /* no ruleset? look for default */ + rs = hi->hi_ruleset; if (rs == NULL) { s = stab("*", ST_HEADER, ST_FIND); @@ -358,17 +360,10 @@ hse: (void) sm_snprintf(qval, sizeof qval, "%d", k); macdefine(&e->e_macro, A_TEMP, macid("{hdrlen}"), qval); #if _FFR_HDR_TYPE - /* - ** XXX: h isn't set yet - ** If we really want to be precise then we have - ** to lookup the header (see below). - ** It's probably not worth the effort. - */ - - if (bitset(H_FROM, h->h_flags)) + if (bitset(H_FROM, hi->hi_flags)) macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "h s"); - else if (bitset(H_RCPT, h->h_flags)) + else if (bitset(H_RCPT, hi->hi_flags)) macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "h r"); else @@ -467,6 +462,44 @@ hse: return h->h_flags; } /* +** ALLOCHEADER -- allocate a header entry +** +** Parameters: +** field -- the name of the header field. +** value -- the value of the field. +** flags -- flags to add to h_flags. +** rp -- resource pool for allocations +** +** Returns: +** Pointer to a newly allocated and populated HDR. +*/ + +static HDR * +allocheader(field, value, flags, rp) + char *field; + char *value; + int flags; + SM_RPOOL_T *rp; +{ + HDR *h; + STAB *s; + + /* find info struct */ + s = stab(field, ST_HEADER, ST_FIND); + + /* allocate space for new header */ + h = (HDR *) sm_rpool_malloc_x(rp, sizeof *h); + h->h_field = field; + h->h_value = sm_rpool_strdup_x(rp, value); + h->h_flags = flags; + if (s != NULL) + h->h_flags |= s->s_header.hi_flags; + clrbitmap(h->h_mflags); + h->h_macro = '\0'; + + return h; +} +/* ** ADDHEADER -- add a header entry to the end of the queue. ** ** This bypasses the special checking of chompheader. @@ -492,13 +525,9 @@ addheader(field, value, flags, e) ENVELOPE *e; { register HDR *h; - STAB *s; HDR **hp; HDR **hdrlist = &e->e_header; - /* find info struct */ - s = stab(field, ST_HEADER, ST_FIND); - /* find current place in list -- keep back pointer? */ for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link) { @@ -507,18 +536,65 @@ addheader(field, value, flags, e) } /* allocate space for new header */ - h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof *h); - h->h_field = field; - h->h_value = sm_rpool_strdup_x(e->e_rpool, value); + h = allocheader(field, value, flags, e->e_rpool); h->h_link = *hp; - h->h_flags = flags; - if (s != NULL) - h->h_flags |= s->s_header.hi_flags; - clrbitmap(h->h_mflags); - h->h_macro = '\0'; *hp = h; } /* +** INSHEADER -- insert a header entry at the specified index +** +** This bypasses the special checking of chompheader. +** +** Parameters: +** idx -- index into the header list at which to insert +** field -- the name of the header field. +** value -- the value of the field. +** flags -- flags to add to h_flags. +** e -- envelope. +** +** Returns: +** none. +** +** Side Effects: +** inserts the field on the list of headers for this envelope. +*/ + +void +insheader(idx, field, value, flags, e) + int idx; + char *field; + char *value; + int flags; + ENVELOPE *e; +{ + HDR *h, *srch, *last = NULL; + + /* allocate space for new header */ + h = allocheader(field, value, flags, e->e_rpool); + + /* find insertion position */ + for (srch = e->e_header; srch != NULL && idx > 0; + srch = srch->h_link, idx--) + last = srch; + + if (e->e_header == NULL) + { + e->e_header = h; + h->h_link = NULL; + } + else if (srch == NULL) + { + SM_ASSERT(last != NULL); + last->h_link = h; + h->h_link = NULL; + } + else + { + h->h_link = srch->h_link; + srch->h_link = h; + } +} +/* ** HVALUE -- return value of a header. ** ** Only "real" fields (i.e., ones that have not been supplied @@ -674,7 +750,7 @@ eatheader(e, full, log) if (tTd(32, 1)) { sm_dprintf("("); - xputs(h->h_value); + xputs(sm_debug_file(), h->h_value); sm_dprintf(") "); } expand(h->h_value, buf, sizeof buf, e); @@ -689,7 +765,7 @@ eatheader(e, full, log) } if (tTd(32, 1)) { - xputs(h->h_value); + xputs(sm_debug_file(), h->h_value); sm_dprintf("\n"); } @@ -731,10 +807,8 @@ eatheader(e, full, log) e->e_msgid = h->h_value; while (isascii(*e->e_msgid) && isspace(*e->e_msgid)) e->e_msgid++; -#if _FFR_MESSAGEID_MACRO macdefine(&e->e_macro, A_PERM, macid("{msg_id}"), - e->e_msgid); -#endif /* _FFR_MESSAGEID_MACRO */ + e->e_msgid); } } if (tTd(32, 1)) @@ -767,6 +841,60 @@ eatheader(e, full, log) + e->e_nrcpts * WkRecipFact; } + /* check for DSN to properly set e_timeoutclass */ + p = hvalue("content-type", e->e_header); + if (p != NULL) + { + bool oldsupr; + char **pvp; + char pvpbuf[MAXLINE]; + extern unsigned char MimeTokenTab[256]; + + /* tokenize header */ + oldsupr = SuprErrs; + SuprErrs = true; + pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL, + MimeTokenTab, false); + SuprErrs = oldsupr; + + /* Check if multipart/report */ + if (pvp != NULL && pvp[0] != NULL && + pvp[1] != NULL && pvp[2] != NULL && + sm_strcasecmp(*pvp++, "multipart") == 0 && + strcmp(*pvp++, "/") == 0 && + sm_strcasecmp(*pvp++, "report") == 0) + { + /* Look for report-type=delivery-status */ + while (*pvp != NULL) + { + /* skip to semicolon separator */ + while (*pvp != NULL && strcmp(*pvp, ";") != 0) + pvp++; + + /* skip semicolon */ + if (*pvp++ == NULL || *pvp == NULL) + break; + + /* look for report-type */ + if (sm_strcasecmp(*pvp++, "report-type") != 0) + continue; + + /* skip equal */ + if (*pvp == NULL || strcmp(*pvp, "=") != 0) + continue; + + /* check value */ + if (*++pvp != NULL && + sm_strcasecmp(*pvp, + "delivery-status") == 0) + e->e_timeoutclass = TOC_DSN; + + /* found report-type, no need to continue */ + break; + } + } + } + /* message timeout priority */ p = hvalue("priority", e->e_header); if (p != NULL) @@ -778,15 +906,11 @@ eatheader(e, full, log) e->e_timeoutclass = TOC_NORMAL; else if (sm_strcasecmp(p, "non-urgent") == 0) e->e_timeoutclass = TOC_NONURGENT; -#if _FFR_QUEUERETURN_DSN else if (bitset(EF_RESPONSE, e->e_flags)) e->e_timeoutclass = TOC_DSN; -#endif /* _FFR_QUEUERETURN_DSN */ } -#if _FFR_QUEUERETURN_DSN else if (bitset(EF_RESPONSE, e->e_flags)) e->e_timeoutclass = TOC_DSN; -#endif /* _FFR_QUEUERETURN_DSN */ /* date message originated */ p = hvalue("posted-date", e->e_header); @@ -1240,12 +1364,8 @@ crackaddr(addr, e) { c = *q++; if (quoteit && c == '"') - { SM_APPEND_CHAR('\\'); - SM_APPEND_CHAR(c); - } - else - SM_APPEND_CHAR(c); + SM_APPEND_CHAR(c); } if (quoteit) { @@ -1407,7 +1527,7 @@ crackaddr(addr, e) if (tTd(33, 1)) { sm_dprintf("crackaddr=>`"); - xputs(buf); + xputs(sm_debug_file(), buf); sm_dprintf("'\n"); } return buf; @@ -1460,7 +1580,7 @@ putheader(mci, hdr, e, flags) if (tTd(34, 11)) { sm_dprintf(" %s: ", h->h_field); - xputs(p); + xputs(sm_debug_file(), p); } /* Skip empty headers */ @@ -1814,7 +1934,7 @@ commaize(h, p, oldstyle, mci, e) char pvpbuf[PSBUFSIZE]; res = prescan(p, oldstyle ? ' ' : ',', pvpbuf, - sizeof pvpbuf, &oldp, NULL); + sizeof pvpbuf, &oldp, NULL, false); p = oldp; #if _FFR_IGNORE_BOGUS_ADDR /* ignore addresses that can't be parsed */ |