headers.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:37k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #ifndef lint
  14. static char id[] = "@(#)$Id: headers.c,v 8.196 1999/12/07 00:00:37 gshapiro Exp $";
  15. #endif /* ! lint */
  16. #include <sendmail.h>
  17. static bool fix_mime_header __P((char *));
  18. static int priencode __P((char *));
  19. static void put_vanilla_header __P((HDR *, char *, MCI *));
  20. /*
  21. **  SETUPHEADERS -- initialize headers in symbol table
  22. **
  23. ** Parameters:
  24. ** none
  25. **
  26. ** Returns:
  27. ** none
  28. */
  29. void
  30. setupheaders()
  31. {
  32. struct hdrinfo *hi;
  33. STAB *s;
  34. for (hi = HdrInfo; hi->hi_field != NULL; hi++)
  35. {
  36. s = stab(hi->hi_field, ST_HEADER, ST_ENTER);
  37. s->s_header.hi_flags = hi->hi_flags;
  38. s->s_header.hi_ruleset = NULL;
  39. }
  40. }
  41. /*
  42. **  CHOMPHEADER -- process and save a header line.
  43. **
  44. ** Called by collect, readcf, and readqf to deal with header lines.
  45. **
  46. ** Parameters:
  47. ** line -- header as a text line.
  48. ** pflag -- flags:
  49. ** CHHDR_DEF: this is a default value.
  50. ** CHHDR_CHECK: call rulesets.
  51. ** hdrp -- a pointer to the place to save the header.
  52. ** e -- the envelope including this header.
  53. **
  54. ** Returns:
  55. ** flags for this header.
  56. **
  57. ** Side Effects:
  58. ** The header is saved on the header list.
  59. ** Contents of 'line' are destroyed.
  60. */
  61. static struct hdrinfo NormalHeader = { NULL, 0, NULL };
  62. u_long
  63. chompheader(line, pflag, hdrp, e)
  64. char *line;
  65. int *pflag;
  66. HDR **hdrp;
  67. register ENVELOPE *e;
  68. {
  69. u_char mid = '';
  70. register char *p;
  71. register HDR *h;
  72. HDR **hp;
  73. char *fname;
  74. char *fvalue;
  75. bool cond = FALSE;
  76. bool headeronly;
  77. STAB *s;
  78. struct hdrinfo *hi;
  79. bool nullheader = FALSE;
  80. BITMAP256 mopts;
  81. if (tTd(31, 6))
  82. {
  83. dprintf("chompheader: ");
  84. xputs(line);
  85. dprintf("n");
  86. }
  87. headeronly = hdrp != NULL;
  88. if (!headeronly)
  89. hdrp = &e->e_header;
  90. /* strip off options */
  91. clrbitmap(mopts);
  92. p = line;
  93. if (*p == '?')
  94. {
  95. /* have some */
  96. register char *q = strchr(p + 1, *p);
  97. if (q != NULL)
  98. {
  99. *q++ = '';
  100. while (*++p != '')
  101. setbitn(*p, mopts);
  102. p = q;
  103. }
  104. else
  105. syserr("553 5.3.0 header syntax error, line "%s"",
  106.        line);
  107. cond = TRUE;
  108. }
  109. else if (!isascii(*p) || *p == '$')
  110. {
  111. int c;
  112. /* possibly macro conditional */
  113. c = *p & 0377;
  114. if (c == MACROEXPAND)
  115. {
  116. p++;
  117. mid = (u_char) *p++;
  118. }
  119. else if (c == '$')
  120. {
  121. p++;
  122. mid = (u_char)macid(p, NULL);
  123. if (bitset(0200, mid))
  124. p += strlen(macname(mid)) + 2;
  125. else
  126. p++;
  127. }
  128. }
  129. /* find canonical name */
  130. fname = p;
  131. while (isascii(*p) && isgraph(*p) && *p != ':')
  132. p++;
  133. fvalue = p;
  134. while (isascii(*p) && isspace(*p))
  135. p++;
  136. if (*p++ != ':' || fname == fvalue)
  137. {
  138. syserr("553 5.3.0 header syntax error, line "%s"", line);
  139. return 0;
  140. }
  141. *fvalue = '';
  142. /* strip field value on front */
  143. if (*p == ' ')
  144. p++;
  145. fvalue = p;
  146. /* if the field is null, go ahead and use the default */
  147. while (isascii(*p) && isspace(*p))
  148. p++;
  149. if (*p == '')
  150. nullheader = TRUE;
  151. /* security scan: long field names are end-of-header */
  152. if (strlen(fname) > 100)
  153. return H_EOH;
  154. /* check to see if it represents a ruleset call */
  155. if (bitset(*pflag, CHHDR_DEF))
  156. {
  157. char hbuf[50];
  158. (void) expand(fvalue, hbuf, sizeof hbuf, e);
  159. for (p = hbuf; isascii(*p) && isspace(*p); )
  160. p++;
  161. if ((*p++ & 0377) == CALLSUBR)
  162. {
  163. auto char *endp;
  164. bool strc;
  165. strc = *p == '+'; /* strip comments? */
  166. if (strc)
  167. ++p;
  168. if (strtorwset(p, &endp, ST_ENTER) > 0)
  169. {
  170. *endp = '';
  171. s = stab(fname, ST_HEADER, ST_ENTER);
  172. s->s_header.hi_ruleset = newstr(p);
  173. if (!strc)
  174. s->s_header.hi_flags |= H_STRIPCOMM;
  175. }
  176. return 0;
  177. }
  178. }
  179. /* see if it is a known type */
  180. s = stab(fname, ST_HEADER, ST_FIND);
  181. if (s != NULL)
  182. hi = &s->s_header;
  183. else
  184. hi = &NormalHeader;
  185. if (tTd(31, 9))
  186. {
  187. if (s == NULL)
  188. dprintf("no header flags matchn");
  189. else
  190. dprintf("header match, flags=%lx, ruleset=%sn",
  191. hi->hi_flags,
  192. hi->hi_ruleset == NULL ? "<NULL>" : hi->hi_ruleset);
  193. }
  194. /* see if this is a resent message */
  195. if (!bitset(*pflag, CHHDR_DEF) && !headeronly &&
  196.     bitset(H_RESENT, hi->hi_flags))
  197. e->e_flags |= EF_RESENT;
  198. /* if this is an Errors-To: header keep track of it now */
  199. if (UseErrorsTo && !bitset(*pflag, CHHDR_DEF) && !headeronly &&
  200.     bitset(H_ERRORSTO, hi->hi_flags))
  201. (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
  202. /* if this means "end of header" quit now */
  203. if (!headeronly && bitset(H_EOH, hi->hi_flags))
  204. return hi->hi_flags;
  205. /*
  206. **  Horrible hack to work around problem with Lotus Notes SMTP
  207. **  mail gateway, which generates From: headers with newlines in
  208. **  them and the <address> on the second line.  Although this is
  209. **  legal RFC 822, many MUAs don't handle this properly and thus
  210. **  never find the actual address.
  211. */
  212. if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)
  213. {
  214. while ((p = strchr(fvalue, 'n')) != NULL)
  215. *p = ' ';
  216. }
  217. /*
  218. **  If there is a check ruleset, verify it against the header.
  219. */
  220. if (bitset(*pflag, CHHDR_CHECK))
  221. {
  222. bool stripcom = FALSE;
  223. char *rs;
  224. /* no ruleset? look for default */
  225. rs = hi->hi_ruleset;
  226. if (rs == NULL)
  227. {
  228. s = stab("*", ST_HEADER, ST_FIND);
  229. if (s != NULL)
  230. {
  231. rs = (&s->s_header)->hi_ruleset;
  232. stripcom = bitset((&s->s_header)->hi_flags,
  233.   H_STRIPCOMM);
  234. }
  235. }
  236. else
  237. stripcom = bitset(hi->hi_flags, H_STRIPCOMM);
  238. if (rs != NULL)
  239. {
  240. int l;
  241. char qval[MAXNAME];
  242. char hlen[16];
  243. char *sp, *dp;
  244. dp = qval;
  245. l = 0;
  246. dp[l++] = '"';
  247. for (sp = fvalue; *sp != '' && l < MAXNAME - 2; sp++)
  248. {
  249. switch(*sp)
  250. {
  251.   case '11': /* ht */
  252.   case '12': /* nl */
  253.   case '13': /* vt */
  254.   case '14': /* np */
  255.   case '15': /* cr */
  256. dp[l++] = ' ';
  257. break;
  258.   case '"':
  259. dp[l++] = '\';
  260. /* FALLTHROUGH */
  261.   default:
  262. dp[l++] = *sp;
  263. break;
  264. }
  265. }
  266. dp[l++] = '"';
  267. dp[l++] = '';
  268. l = strlen(fvalue);
  269. snprintf(hlen, sizeof hlen, "%d", l);
  270. define(macid("{hdrlen}", NULL), newstr(hlen), e);
  271. if (l >= MAXNAME)
  272. {
  273. if (LogLevel > 9)
  274. sm_syslog(LOG_WARNING, e->e_id,
  275.   "Warning: truncated header '%s' before check with '%s' len=%d max=%d",
  276.   fname, rs, l, MAXNAME);
  277. }
  278. if ((sp = macvalue(macid("{currHeader}", NULL), e)) !=
  279.     NULL)
  280. free(sp);
  281. define(macid("{currHeader}", NULL), newstr(qval), e);
  282. define(macid("{hdr_name}", NULL), newstr(fname), e);
  283. (void) rscheck(rs, fvalue, NULL, e, stripcom, TRUE);
  284. }
  285. }
  286. /*
  287. **  Drop explicit From: if same as what we would generate.
  288. **  This is to make MH (which doesn't always give a full name)
  289. **  insert the full name information in all circumstances.
  290. */
  291. p = "resent-from";
  292. if (!bitset(EF_RESENT, e->e_flags))
  293. p += 7;
  294. if (!bitset(*pflag, CHHDR_DEF) && !headeronly &&
  295.     !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)
  296. {
  297. if (tTd(31, 2))
  298. {
  299. dprintf("comparing header from (%s) against default (%s or %s)n",
  300. fvalue, e->e_from.q_paddr, e->e_from.q_user);
  301. }
  302. if (e->e_from.q_paddr != NULL &&
  303.     e->e_from.q_mailer != NULL &&
  304.     bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&
  305.     (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
  306.      strcmp(fvalue, e->e_from.q_user) == 0))
  307. return hi->hi_flags;
  308. }
  309. /* delete default value for this header */
  310. for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
  311. {
  312. if (strcasecmp(fname, h->h_field) == 0 &&
  313.     bitset(H_DEFAULT, h->h_flags) &&
  314.     !bitset(H_FORCE, h->h_flags))
  315. {
  316. if (nullheader)
  317. {
  318. /* user-supplied value was null */
  319. return 0;
  320. }
  321. h->h_value = NULL;
  322. if (!cond)
  323. {
  324. /* copy conditions from default case */
  325. memmove((char *)mopts, (char *)h->h_mflags,
  326. sizeof mopts);
  327. }
  328. h->h_macro = mid;
  329. }
  330. }
  331. /* create a new node */
  332. h = (HDR *) xalloc(sizeof *h);
  333. h->h_field = newstr(fname);
  334. h->h_value = newstr(fvalue);
  335. h->h_link = NULL;
  336. memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts);
  337. h->h_macro = mid;
  338. *hp = h;
  339. h->h_flags = hi->hi_flags;
  340. /* strip EOH flag if parsing MIME headers */
  341. if (headeronly)
  342. h->h_flags &= ~H_EOH;
  343. if (bitset(*pflag, CHHDR_DEF))
  344. h->h_flags |= H_DEFAULT;
  345. if (cond || mid != '')
  346. h->h_flags |= H_CHECK;
  347. /* hack to see if this is a new format message */
  348. if (!bitset(*pflag, CHHDR_DEF) && !headeronly &&
  349.     bitset(H_RCPT|H_FROM, h->h_flags) &&
  350.     (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
  351.      strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
  352. {
  353. e->e_flags &= ~EF_OLDSTYLE;
  354. }
  355. return h->h_flags;
  356. }
  357. /*
  358. **  ADDHEADER -- add a header entry to the end of the queue.
  359. **
  360. ** This bypasses the special checking of chompheader.
  361. **
  362. ** Parameters:
  363. ** field -- the name of the header field.
  364. ** value -- the value of the field.
  365. ** hdrlist -- an indirect pointer to the header structure list.
  366. **
  367. ** Returns:
  368. ** none.
  369. **
  370. ** Side Effects:
  371. ** adds the field on the list of headers for this envelope.
  372. */
  373. void
  374. addheader(field, value, hdrlist)
  375. char *field;
  376. char *value;
  377. HDR **hdrlist;
  378. {
  379. register HDR *h;
  380. STAB *s;
  381. HDR **hp;
  382. /* find info struct */
  383. s = stab(field, ST_HEADER, ST_FIND);
  384. /* find current place in list -- keep back pointer? */
  385. for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
  386. {
  387. if (strcasecmp(field, h->h_field) == 0)
  388. break;
  389. }
  390. /* allocate space for new header */
  391. h = (HDR *) xalloc(sizeof *h);
  392. h->h_field = field;
  393. h->h_value = newstr(value);
  394. h->h_link = *hp;
  395. h->h_flags = H_DEFAULT;
  396. if (s != NULL)
  397. h->h_flags |= s->s_header.hi_flags;
  398. clrbitmap(h->h_mflags);
  399. h->h_macro = '';
  400. *hp = h;
  401. }
  402. /*
  403. **  HVALUE -- return value of a header.
  404. **
  405. ** Only "real" fields (i.e., ones that have not been supplied
  406. ** as a default) are used.
  407. **
  408. ** Parameters:
  409. ** field -- the field name.
  410. ** header -- the header list.
  411. **
  412. ** Returns:
  413. ** pointer to the value part.
  414. ** NULL if not found.
  415. **
  416. ** Side Effects:
  417. ** none.
  418. */
  419. char *
  420. hvalue(field, header)
  421. char *field;
  422. HDR *header;
  423. {
  424. register HDR *h;
  425. for (h = header; h != NULL; h = h->h_link)
  426. {
  427. if (!bitset(H_DEFAULT, h->h_flags) &&
  428.     strcasecmp(h->h_field, field) == 0)
  429. return h->h_value;
  430. }
  431. return NULL;
  432. }
  433. /*
  434. **  ISHEADER -- predicate telling if argument is a header.
  435. **
  436. ** A line is a header if it has a single word followed by
  437. ** optional white space followed by a colon.
  438. **
  439. ** Header fields beginning with two dashes, although technically
  440. ** permitted by RFC822, are automatically rejected in order
  441. ** to make MIME work out.  Without this we could have a technically
  442. ** legal header such as ``--"foo:bar"'' that would also be a legal
  443. ** MIME separator.
  444. **
  445. ** Parameters:
  446. ** h -- string to check for possible headerness.
  447. **
  448. ** Returns:
  449. ** TRUE if h is a header.
  450. ** FALSE otherwise.
  451. **
  452. ** Side Effects:
  453. ** none.
  454. */
  455. bool
  456. isheader(h)
  457. char *h;
  458. {
  459. register char *s = h;
  460. if (s[0] == '-' && s[1] == '-')
  461. return FALSE;
  462. while (*s > ' ' && *s != ':' && *s != '')
  463. s++;
  464. if (h == s)
  465. return FALSE;
  466. /* following technically violates RFC822 */
  467. while (isascii(*s) && isspace(*s))
  468. s++;
  469. return (*s == ':');
  470. }
  471. /*
  472. **  EATHEADER -- run through the stored header and extract info.
  473. **
  474. ** Parameters:
  475. ** e -- the envelope to process.
  476. ** full -- if set, do full processing (e.g., compute
  477. ** message priority).  This should not be set
  478. ** when reading a queue file because some info
  479. ** needed to compute the priority is wrong.
  480. **
  481. ** Returns:
  482. ** none.
  483. **
  484. ** Side Effects:
  485. ** Sets a bunch of global variables from information
  486. ** in the collected header.
  487. ** Aborts the message if the hop count is exceeded.
  488. */
  489. void
  490. eatheader(e, full)
  491. register ENVELOPE *e;
  492. bool full;
  493. {
  494. register HDR *h;
  495. register char *p;
  496. int hopcnt = 0;
  497. char *msgid;
  498. char buf[MAXLINE];
  499. /*
  500. **  Set up macros for possible expansion in headers.
  501. */
  502. define('f', e->e_sender, e);
  503. define('g', e->e_sender, e);
  504. if (e->e_origrcpt != NULL && *e->e_origrcpt != '')
  505. define('u', e->e_origrcpt, e);
  506. else
  507. define('u', NULL, e);
  508. /* full name of from person */
  509. p = hvalue("full-name", e->e_header);
  510. if (p != NULL)
  511. {
  512. if (!rfc822_string(p))
  513. {
  514. /*
  515. **  Quote a full name with special characters
  516. **  as a comment so crackaddr() doesn't destroy
  517. **  the name portion of the address.
  518. */
  519. p = addquotes(p);
  520. }
  521. define('x', p, e);
  522. }
  523. if (tTd(32, 1))
  524. dprintf("----- collected header -----n");
  525. msgid = NULL;
  526. for (h = e->e_header; h != NULL; h = h->h_link)
  527. {
  528. if (tTd(32, 1))
  529. dprintf("%s: ", h->h_field);
  530. if (h->h_value == NULL)
  531. {
  532. if (tTd(32, 1))
  533. dprintf("<NULL>n");
  534. continue;
  535. }
  536. /* do early binding */
  537. if (bitset(H_DEFAULT, h->h_flags) &&
  538.     !bitset(H_BINDLATE, h->h_flags))
  539. {
  540. if (tTd(32, 1))
  541. {
  542. dprintf("(");
  543. xputs(h->h_value);
  544. dprintf(") ");
  545. }
  546. expand(h->h_value, buf, sizeof buf, e);
  547. if (buf[0] != '')
  548. {
  549. if (bitset(H_FROM, h->h_flags))
  550. expand(crackaddr(buf), buf, sizeof buf, e);
  551. h->h_value = newstr(buf);
  552. h->h_flags &= ~H_DEFAULT;
  553. }
  554. }
  555. if (tTd(32, 1))
  556. {
  557. xputs(h->h_value);
  558. dprintf("n");
  559. }
  560. /* count the number of times it has been processed */
  561. if (bitset(H_TRACE, h->h_flags))
  562. hopcnt++;
  563. /* send to this person if we so desire */
  564. if (GrabTo && bitset(H_RCPT, h->h_flags) &&
  565.     !bitset(H_DEFAULT, h->h_flags) &&
  566.     (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
  567. {
  568. #if 0
  569. int saveflags = e->e_flags;
  570. #endif /* 0 */
  571. (void) sendtolist(h->h_value, NULLADDR,
  572.   &e->e_sendqueue, 0, e);
  573. #if 0
  574. /*
  575. **  Change functionality so a fatal error on an
  576. **  address doesn't affect the entire envelope.
  577. */
  578. /* delete fatal errors generated by this address */
  579. if (!bitset(EF_FATALERRS, saveflags))
  580. e->e_flags &= ~EF_FATALERRS;
  581. #endif /* 0 */
  582. }
  583. /* save the message-id for logging */
  584. p = "resent-message-id";
  585. if (!bitset(EF_RESENT, e->e_flags))
  586. p += 7;
  587. if (strcasecmp(h->h_field, p) == 0)
  588. {
  589. msgid = h->h_value;
  590. while (isascii(*msgid) && isspace(*msgid))
  591. msgid++;
  592. }
  593. }
  594. if (tTd(32, 1))
  595. dprintf("----------------------------n");
  596. /* if we are just verifying (that is, sendmail -t -bv), drop out now */
  597. if (OpMode == MD_VERIFY)
  598. return;
  599. /* store hop count */
  600. if (hopcnt > e->e_hopcount)
  601. e->e_hopcount = hopcnt;
  602. /* message priority */
  603. p = hvalue("precedence", e->e_header);
  604. if (p != NULL)
  605. e->e_class = priencode(p);
  606. if (e->e_class < 0)
  607. e->e_timeoutclass = TOC_NONURGENT;
  608. else if (e->e_class > 0)
  609. e->e_timeoutclass = TOC_URGENT;
  610. if (full)
  611. {
  612. e->e_msgpriority = e->e_msgsize
  613.  - e->e_class * WkClassFact
  614.  + e->e_nrcpts * WkRecipFact;
  615. }
  616. /* message timeout priority */
  617. p = hvalue("priority", e->e_header);
  618. if (p != NULL)
  619. {
  620. /* (this should be in the configuration file) */
  621. if (strcasecmp(p, "urgent") == 0)
  622. e->e_timeoutclass = TOC_URGENT;
  623. else if (strcasecmp(p, "normal") == 0)
  624. e->e_timeoutclass = TOC_NORMAL;
  625. else if (strcasecmp(p, "non-urgent") == 0)
  626. e->e_timeoutclass = TOC_NONURGENT;
  627. }
  628. /* date message originated */
  629. p = hvalue("posted-date", e->e_header);
  630. if (p == NULL)
  631. p = hvalue("date", e->e_header);
  632. if (p != NULL)
  633. define('a', p, e);
  634. /* check to see if this is a MIME message */
  635. if ((e->e_bodytype != NULL &&
  636.      strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
  637.     hvalue("MIME-Version", e->e_header) != NULL)
  638. {
  639. e->e_flags |= EF_IS_MIME;
  640. if (HasEightBits)
  641. e->e_bodytype = "8BITMIME";
  642. }
  643. else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
  644. {
  645. /* this may be an RFC 1049 message */
  646. p = strpbrk(p, ";/");
  647. if (p == NULL || *p == ';')
  648. {
  649. /* yep, it is */
  650. e->e_flags |= EF_DONT_MIME;
  651. }
  652. }
  653. /*
  654. **  From person in antiquated ARPANET mode
  655. ** required by UK Grey Book e-mail gateways (sigh)
  656. */
  657. if (OpMode == MD_ARPAFTP)
  658. {
  659. register struct hdrinfo *hi;
  660. for (hi = HdrInfo; hi->hi_field != NULL; hi++)
  661. {
  662. if (bitset(H_FROM, hi->hi_flags) &&
  663.     (!bitset(H_RESENT, hi->hi_flags) ||
  664.      bitset(EF_RESENT, e->e_flags)) &&
  665.     (p = hvalue(hi->hi_field, e->e_header)) != NULL)
  666. break;
  667. }
  668. if (hi->hi_field != NULL)
  669. {
  670. if (tTd(32, 2))
  671. dprintf("eatheader: setsender(*%s == %s)n",
  672. hi->hi_field, p);
  673. setsender(p, e, NULL, '', TRUE);
  674. }
  675. }
  676. /*
  677. **  Log collection information.
  678. */
  679. if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
  680. logsender(e, msgid);
  681. e->e_flags &= ~EF_LOGSENDER;
  682. }
  683. /*
  684. **  LOGSENDER -- log sender information
  685. **
  686. ** Parameters:
  687. ** e -- the envelope to log
  688. ** msgid -- the message id
  689. **
  690. ** Returns:
  691. ** none
  692. */
  693. void
  694. logsender(e, msgid)
  695. register ENVELOPE *e;
  696. char *msgid;
  697. {
  698. char *name;
  699. register char *sbp;
  700. register char *p;
  701. int l;
  702. char hbuf[MAXNAME + 1];
  703. char sbuf[MAXLINE + 1];
  704. char mbuf[MAXNAME + 1];
  705. /* don't allow newlines in the message-id */
  706. if (msgid != NULL)
  707. {
  708. l = strlen(msgid);
  709. if (l > sizeof mbuf - 1)
  710. l = sizeof mbuf - 1;
  711. memmove(mbuf, msgid, l);
  712. mbuf[l] = '';
  713. p = mbuf;
  714. while ((p = strchr(p, 'n')) != NULL)
  715. *p++ = ' ';
  716. }
  717. if (bitset(EF_RESPONSE, e->e_flags))
  718. name = "[RESPONSE]";
  719. else if ((name = macvalue('_', e)) != NULL)
  720. /* EMPTY */
  721. ;
  722. else if (RealHostName == NULL)
  723. name = "localhost";
  724. else if (RealHostName[0] == '[')
  725. name = RealHostName;
  726. else
  727. {
  728. name = hbuf;
  729. (void) snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName);
  730. if (RealHostAddr.sa.sa_family != 0)
  731. {
  732. p = &hbuf[strlen(hbuf)];
  733. (void) snprintf(p, SPACELEFT(hbuf, p), " (%.100s)",
  734. anynet_ntoa(&RealHostAddr));
  735. }
  736. }
  737. /* some versions of syslog only take 5 printf args */
  738. #if (SYSLOG_BUFSIZE) >= 256
  739. sbp = sbuf;
  740. snprintf(sbp, SPACELEFT(sbuf, sbp),
  741.     "from=%.200s, size=%ld, class=%d, nrcpts=%d",
  742.     e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
  743.     e->e_msgsize, e->e_class, e->e_nrcpts);
  744. sbp += strlen(sbp);
  745. if (msgid != NULL)
  746. {
  747. snprintf(sbp, SPACELEFT(sbuf, sbp), ", msgid=%.100s", mbuf);
  748. sbp += strlen(sbp);
  749. }
  750. if (e->e_bodytype != NULL)
  751. {
  752. (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", bodytype=%.20s",
  753. e->e_bodytype);
  754. sbp += strlen(sbp);
  755. }
  756. p = macvalue('r', e);
  757. if (p != NULL)
  758. {
  759. (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p);
  760. sbp += strlen(sbp);
  761. }
  762. p = macvalue(macid("{daemon_name}", NULL), e);
  763. if (p != NULL)
  764. {
  765. (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", daemon=%.20s", p);
  766. sbp += strlen(sbp);
  767. }
  768. sm_syslog(LOG_INFO, e->e_id,
  769.   "%.850s, relay=%.100s",
  770.   sbuf, name);
  771. #else /* (SYSLOG_BUFSIZE) >= 256 */
  772. sm_syslog(LOG_INFO, e->e_id,
  773.   "from=%s",
  774.   e->e_from.q_paddr == NULL ? "<NONE>"
  775.     : shortenstring(e->e_from.q_paddr, 83));
  776. sm_syslog(LOG_INFO, e->e_id,
  777.   "size=%ld, class=%ld, nrcpts=%d",
  778.   e->e_msgsize, e->e_class, e->e_nrcpts);
  779. if (msgid != NULL)
  780. sm_syslog(LOG_INFO, e->e_id,
  781.   "msgid=%s",
  782.   shortenstring(mbuf, 83));
  783. sbp = sbuf;
  784. *sbp = '';
  785. if (e->e_bodytype != NULL)
  786. {
  787. snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype);
  788. sbp += strlen(sbp);
  789. }
  790. p = macvalue('r', e);
  791. if (p != NULL)
  792. {
  793. snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p);
  794. sbp += strlen(sbp);
  795. }
  796. sm_syslog(LOG_INFO, e->e_id,
  797.   "%.400srelay=%.100s", sbuf, name);
  798. #endif /* (SYSLOG_BUFSIZE) >= 256 */
  799. }
  800. /*
  801. **  PRIENCODE -- encode external priority names into internal values.
  802. **
  803. ** Parameters:
  804. ** p -- priority in ascii.
  805. **
  806. ** Returns:
  807. ** priority as a numeric level.
  808. **
  809. ** Side Effects:
  810. ** none.
  811. */
  812. static int
  813. priencode(p)
  814. char *p;
  815. {
  816. register int i;
  817. for (i = 0; i < NumPriorities; i++)
  818. {
  819. if (!strcasecmp(p, Priorities[i].pri_name))
  820. return Priorities[i].pri_val;
  821. }
  822. /* unknown priority */
  823. return 0;
  824. }
  825. /*
  826. **  CRACKADDR -- parse an address and turn it into a macro
  827. **
  828. ** This doesn't actually parse the address -- it just extracts
  829. ** it and replaces it with "$g".  The parse is totally ad hoc
  830. ** and isn't even guaranteed to leave something syntactically
  831. ** identical to what it started with.  However, it does leave
  832. ** something semantically identical.
  833. **
  834. ** This algorithm has been cleaned up to handle a wider range
  835. ** of cases -- notably quoted and backslash escaped strings.
  836. ** This modification makes it substantially better at preserving
  837. ** the original syntax.
  838. **
  839. ** Parameters:
  840. ** addr -- the address to be cracked.
  841. **
  842. ** Returns:
  843. ** a pointer to the new version.
  844. **
  845. ** Side Effects:
  846. ** none.
  847. **
  848. ** Warning:
  849. ** The return value is saved in local storage and should
  850. ** be copied if it is to be reused.
  851. */
  852. char *
  853. crackaddr(addr)
  854. register char *addr;
  855. {
  856. register char *p;
  857. register char c;
  858. int cmtlev;
  859. int realcmtlev;
  860. int anglelev, realanglelev;
  861. int copylev;
  862. int bracklev;
  863. bool qmode;
  864. bool realqmode;
  865. bool skipping;
  866. bool putgmac = FALSE;
  867. bool quoteit = FALSE;
  868. bool gotangle = FALSE;
  869. bool gotcolon = FALSE;
  870. register char *bp;
  871. char *buflim;
  872. char *bufhead;
  873. char *addrhead;
  874. static char buf[MAXNAME + 1];
  875. if (tTd(33, 1))
  876. dprintf("crackaddr(%s)n", addr);
  877. /* strip leading spaces */
  878. while (*addr != '' && isascii(*addr) && isspace(*addr))
  879. addr++;
  880. /*
  881. **  Start by assuming we have no angle brackets.  This will be
  882. **  adjusted later if we find them.
  883. */
  884. bp = bufhead = buf;
  885. buflim = &buf[sizeof buf - 7];
  886. p = addrhead = addr;
  887. copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
  888. bracklev = 0;
  889. qmode = realqmode = FALSE;
  890. while ((c = *p++) != '')
  891. {
  892. /*
  893. **  If the buffer is overful, go into a special "skipping"
  894. **  mode that tries to keep legal syntax but doesn't actually
  895. **  output things.
  896. */
  897. skipping = bp >= buflim;
  898. if (copylev > 0 && !skipping)
  899. *bp++ = c;
  900. /* check for backslash escapes */
  901. if (c == '\')
  902. {
  903. /* arrange to quote the address */
  904. if (cmtlev <= 0 && !qmode)
  905. quoteit = TRUE;
  906. if ((c = *p++) == '')
  907. {
  908. /* too far */
  909. p--;
  910. goto putg;
  911. }
  912. if (copylev > 0 && !skipping)
  913. *bp++ = c;
  914. goto putg;
  915. }
  916. /* check for quoted strings */
  917. if (c == '"' && cmtlev <= 0)
  918. {
  919. qmode = !qmode;
  920. if (copylev > 0 && !skipping)
  921. realqmode = !realqmode;
  922. continue;
  923. }
  924. if (qmode)
  925. goto putg;
  926. /* check for comments */
  927. if (c == '(')
  928. {
  929. cmtlev++;
  930. /* allow space for closing paren */
  931. if (!skipping)
  932. {
  933. buflim--;
  934. realcmtlev++;
  935. if (copylev++ <= 0)
  936. {
  937. if (bp != bufhead)
  938. *bp++ = ' ';
  939. *bp++ = c;
  940. }
  941. }
  942. }
  943. if (cmtlev > 0)
  944. {
  945. if (c == ')')
  946. {
  947. cmtlev--;
  948. copylev--;
  949. if (!skipping)
  950. {
  951. realcmtlev--;
  952. buflim++;
  953. }
  954. }
  955. continue;
  956. }
  957. else if (c == ')')
  958. {
  959. /* syntax error: unmatched ) */
  960. if (copylev > 0 && !skipping)
  961. bp--;
  962. }
  963. /* count nesting on [ ... ] (for IPv6 domain literals) */
  964. if (c == '[')
  965. bracklev++;
  966. else if (c == ']')
  967. bracklev--;
  968. /* check for group: list; syntax */
  969. if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
  970.     !gotcolon && !ColonOkInAddr)
  971. {
  972. register char *q;
  973. /*
  974. **  Check for DECnet phase IV ``::'' (host::user)
  975. **  or **  DECnet phase V ``:.'' syntaxes.  The latter
  976. **  covers ``user@DEC:.tay.myhost'' and
  977. **  ``DEC:.tay.myhost::user'' syntaxes (bletch).
  978. */
  979. if (*p == ':' || *p == '.')
  980. {
  981. if (cmtlev <= 0 && !qmode)
  982. quoteit = TRUE;
  983. if (copylev > 0 && !skipping)
  984. {
  985. *bp++ = c;
  986. *bp++ = *p;
  987. }
  988. p++;
  989. goto putg;
  990. }
  991. gotcolon = TRUE;
  992. bp = bufhead;
  993. if (quoteit)
  994. {
  995. *bp++ = '"';
  996. /* back up over the ':' and any spaces */
  997. --p;
  998. while (isascii(*--p) && isspace(*p))
  999. continue;
  1000. p++;
  1001. }
  1002. for (q = addrhead; q < p; )
  1003. {
  1004. c = *q++;
  1005. if (bp < buflim)
  1006. {
  1007. if (quoteit && c == '"')
  1008. *bp++ = '\';
  1009. *bp++ = c;
  1010. }
  1011. }
  1012. if (quoteit)
  1013. {
  1014. if (bp == &bufhead[1])
  1015. bp--;
  1016. else
  1017. *bp++ = '"';
  1018. while ((c = *p++) != ':')
  1019. {
  1020. if (bp < buflim)
  1021. *bp++ = c;
  1022. }
  1023. *bp++ = c;
  1024. }
  1025. /* any trailing white space is part of group: */
  1026. while (isascii(*p) && isspace(*p) && bp < buflim)
  1027. *bp++ = *p++;
  1028. copylev = 0;
  1029. putgmac = quoteit = FALSE;
  1030. bufhead = bp;
  1031. addrhead = p;
  1032. continue;
  1033. }
  1034. if (c == ';' && copylev <= 0 && !ColonOkInAddr)
  1035. {
  1036. if (bp < buflim)
  1037. *bp++ = c;
  1038. }
  1039. /* check for characters that may have to be quoted */
  1040. if (strchr(MustQuoteChars, c) != NULL)
  1041. {
  1042. /*
  1043. **  If these occur as the phrase part of a <>
  1044. **  construct, but are not inside of () or already
  1045. **  quoted, they will have to be quoted.  Note that
  1046. **  now (but don't actually do the quoting).
  1047. */
  1048. if (cmtlev <= 0 && !qmode)
  1049. quoteit = TRUE;
  1050. }
  1051. /* check for angle brackets */
  1052. if (c == '<')
  1053. {
  1054. register char *q;
  1055. /* assume first of two angles is bogus */
  1056. if (gotangle)
  1057. quoteit = TRUE;
  1058. gotangle = TRUE;
  1059. /* oops -- have to change our mind */
  1060. anglelev = 1;
  1061. if (!skipping)
  1062. realanglelev = 1;
  1063. bp = bufhead;
  1064. if (quoteit)
  1065. {
  1066. *bp++ = '"';
  1067. /* back up over the '<' and any spaces */
  1068. --p;
  1069. while (isascii(*--p) && isspace(*p))
  1070. continue;
  1071. p++;
  1072. }
  1073. for (q = addrhead; q < p; )
  1074. {
  1075. c = *q++;
  1076. if (bp < buflim)
  1077. {
  1078. if (quoteit && c == '"')
  1079. *bp++ = '\';
  1080. *bp++ = c;
  1081. }
  1082. }
  1083. if (quoteit)
  1084. {
  1085. if (bp == &buf[1])
  1086. bp--;
  1087. else
  1088. *bp++ = '"';
  1089. while ((c = *p++) != '<')
  1090. {
  1091. if (bp < buflim)
  1092. *bp++ = c;
  1093. }
  1094. *bp++ = c;
  1095. }
  1096. copylev = 0;
  1097. putgmac = quoteit = FALSE;
  1098. continue;
  1099. }
  1100. if (c == '>')
  1101. {
  1102. if (anglelev > 0)
  1103. {
  1104. anglelev--;
  1105. if (!skipping)
  1106. {
  1107. realanglelev--;
  1108. buflim++;
  1109. }
  1110. }
  1111. else if (!skipping)
  1112. {
  1113. /* syntax error: unmatched > */
  1114. if (copylev > 0)
  1115. bp--;
  1116. quoteit = TRUE;
  1117. continue;
  1118. }
  1119. if (copylev++ <= 0)
  1120. *bp++ = c;
  1121. continue;
  1122. }
  1123. /* must be a real address character */
  1124. putg:
  1125. if (copylev <= 0 && !putgmac)
  1126. {
  1127. if (bp > bufhead && bp[-1] == ')')
  1128. *bp++ = ' ';
  1129. *bp++ = MACROEXPAND;
  1130. *bp++ = 'g';
  1131. putgmac = TRUE;
  1132. }
  1133. }
  1134. /* repair any syntactic damage */
  1135. if (realqmode)
  1136. *bp++ = '"';
  1137. while (realcmtlev-- > 0)
  1138. *bp++ = ')';
  1139. while (realanglelev-- > 0)
  1140. *bp++ = '>';
  1141. *bp++ = '';
  1142. if (tTd(33, 1))
  1143. {
  1144. dprintf("crackaddr=>`");
  1145. xputs(buf);
  1146. dprintf("'n");
  1147. }
  1148. return buf;
  1149. }
  1150. /*
  1151. **  PUTHEADER -- put the header part of a message from the in-core copy
  1152. **
  1153. ** Parameters:
  1154. ** mci -- the connection information.
  1155. ** hdr -- the header to put.
  1156. ** e -- envelope to use.
  1157. ** flags -- MIME conversion flags.
  1158. **
  1159. ** Returns:
  1160. ** none.
  1161. **
  1162. ** Side Effects:
  1163. ** none.
  1164. */
  1165. /*
  1166.  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
  1167.  */
  1168. #ifndef MAX
  1169. # define MAX(a,b) (((a)>(b))?(a):(b))
  1170. #endif /* ! MAX */
  1171. void
  1172. putheader(mci, hdr, e, flags)
  1173. register MCI *mci;
  1174. HDR *hdr;
  1175. register ENVELOPE *e;
  1176. int flags;
  1177. {
  1178. register HDR *h;
  1179. char buf[MAX(MAXLINE,BUFSIZ)];
  1180. char obuf[MAXLINE];
  1181. if (tTd(34, 1))
  1182. dprintf("--- putheader, mailer = %s ---n",
  1183. mci->mci_mailer->m_name);
  1184. /*
  1185. **  If we're in MIME mode, we're not really in the header of the
  1186. **  message, just the header of one of the parts of the body of
  1187. **  the message.  Therefore MCIF_INHEADER should not be turned on.
  1188. */
  1189. if (!bitset(MCIF_INMIME, mci->mci_flags))
  1190. mci->mci_flags |= MCIF_INHEADER;
  1191. for (h = hdr; h != NULL; h = h->h_link)
  1192. {
  1193. register char *p = h->h_value;
  1194. if (tTd(34, 11))
  1195. {
  1196. dprintf("  %s: ", h->h_field);
  1197. xputs(p);
  1198. }
  1199. /* heuristic shortening of MIME fields to avoid MUA overflows */
  1200. if (MaxMimeFieldLength > 0 &&
  1201.     wordinclass(h->h_field,
  1202. macid("{checkMIMEFieldHeaders}", NULL)))
  1203. {
  1204. if (fix_mime_header(h->h_value))
  1205. {
  1206. sm_syslog(LOG_ALERT, e->e_id,
  1207.   "Truncated MIME %s header due to field size (possible attack)",
  1208.   h->h_field);
  1209. if (tTd(34, 11))
  1210. dprintf("  truncated MIME %s header due to field size (possible attack)n",
  1211. h->h_field);
  1212. }
  1213. }
  1214. if (MaxMimeHeaderLength > 0 &&
  1215.     wordinclass(h->h_field,
  1216. macid("{checkMIMETextHeaders}", NULL)))
  1217. {
  1218. if (strlen(h->h_value) > MaxMimeHeaderLength)
  1219. {
  1220. h->h_value[MaxMimeHeaderLength - 1] = '';
  1221. sm_syslog(LOG_ALERT, e->e_id,
  1222.   "Truncated long MIME %s header (possible attack)",
  1223.   h->h_field);
  1224. if (tTd(34, 11))
  1225. dprintf("  truncated long MIME %s header (possible attack)n",
  1226. h->h_field);
  1227. }
  1228. }
  1229. if (MaxMimeHeaderLength > 0 &&
  1230.     wordinclass(h->h_field,
  1231. macid("{checkMIMEHeaders}", NULL)))
  1232. {
  1233. if (shorten_rfc822_string(h->h_value, MaxMimeHeaderLength))
  1234. {
  1235. sm_syslog(LOG_ALERT, e->e_id,
  1236.   "Truncated long MIME %s header (possible attack)",
  1237.   h->h_field);
  1238. if (tTd(34, 11))
  1239. dprintf("  truncated long MIME %s header (possible attack)n",
  1240. h->h_field);
  1241. }
  1242. }
  1243. /*
  1244. **  Suppress Content-Transfer-Encoding: if we are MIMEing
  1245. **  and we are potentially converting from 8 bit to 7 bit
  1246. **  MIME.  If converting, add a new CTE header in
  1247. **  mime8to7().
  1248. */
  1249. if (bitset(H_CTE, h->h_flags) &&
  1250.     bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME,
  1251.    mci->mci_flags) &&
  1252.     !bitset(M87F_NO8TO7, flags))
  1253. {
  1254. if (tTd(34, 11))
  1255. dprintf(" (skipped (content-transfer-encoding))n");
  1256. continue;
  1257. }
  1258. if (bitset(MCIF_INMIME, mci->mci_flags))
  1259. {
  1260. if (tTd(34, 11))
  1261. dprintf("n");
  1262. put_vanilla_header(h, p, mci);
  1263. continue;
  1264. }
  1265. if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
  1266.     !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
  1267.     (h->h_macro == '' ||
  1268.      macvalue(h->h_macro & 0377, e) == NULL))
  1269. {
  1270. if (tTd(34, 11))
  1271. dprintf(" (skipped)n");
  1272. continue;
  1273. }
  1274. /* handle Resent-... headers specially */
  1275. if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
  1276. {
  1277. if (tTd(34, 11))
  1278. dprintf(" (skipped (resent))n");
  1279. continue;
  1280. }
  1281. /* suppress return receipts if requested */
  1282. if (bitset(H_RECEIPTTO, h->h_flags) &&
  1283.     (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
  1284. {
  1285. if (tTd(34, 11))
  1286. dprintf(" (skipped (receipt))n");
  1287. continue;
  1288. }
  1289. /* macro expand value if generated internally */
  1290. if (bitset(H_DEFAULT, h->h_flags) ||
  1291.     bitset(H_BINDLATE, h->h_flags))
  1292. {
  1293. expand(p, buf, sizeof buf, e);
  1294. p = buf;
  1295. if (*p == '')
  1296. {
  1297. if (tTd(34, 11))
  1298. dprintf(" (skipped -- null value)n");
  1299. continue;
  1300. }
  1301. }
  1302. if (bitset(H_BCC, h->h_flags))
  1303. {
  1304. /* Bcc: field -- either truncate or delete */
  1305. if (bitset(EF_DELETE_BCC, e->e_flags))
  1306. {
  1307. if (tTd(34, 11))
  1308. dprintf(" (skipped -- bcc)n");
  1309. }
  1310. else
  1311. {
  1312. /* no other recipient headers: truncate value */
  1313. (void) snprintf(obuf, sizeof obuf, "%s:",
  1314. h->h_field);
  1315. putline(obuf, mci);
  1316. }
  1317. continue;
  1318. }
  1319. if (tTd(34, 11))
  1320. dprintf("n");
  1321. if (bitset(H_FROM|H_RCPT, h->h_flags))
  1322. {
  1323. /* address field */
  1324. bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
  1325. if (bitset(H_FROM, h->h_flags))
  1326. oldstyle = FALSE;
  1327. commaize(h, p, oldstyle, mci, e);
  1328. }
  1329. else
  1330. {
  1331. put_vanilla_header(h, p, mci);
  1332. }
  1333. }
  1334. /*
  1335. **  If we are converting this to a MIME message, add the
  1336. **  MIME headers (but not in MIME mode!).
  1337. */
  1338. #if MIME8TO7
  1339. if (bitset(MM_MIME8BIT, MimeMode) &&
  1340.     bitset(EF_HAS8BIT, e->e_flags) &&
  1341.     !bitset(EF_DONT_MIME, e->e_flags) &&
  1342.     !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
  1343.     !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
  1344.     hvalue("MIME-Version", e->e_header) == NULL)
  1345. {
  1346. putline("MIME-Version: 1.0", mci);
  1347. if (hvalue("Content-Type", e->e_header) == NULL)
  1348. {
  1349. snprintf(obuf, sizeof obuf,
  1350. "Content-Type: text/plain; charset=%s",
  1351. defcharset(e));
  1352. putline(obuf, mci);
  1353. }
  1354. if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
  1355. putline("Content-Transfer-Encoding: 8bit", mci);
  1356. }
  1357. #endif /* MIME8TO7 */
  1358. }
  1359. /*
  1360. **  PUT_VANILLA_HEADER -- output a fairly ordinary header
  1361. **
  1362. ** Parameters:
  1363. ** h -- the structure describing this header
  1364. ** v -- the value of this header
  1365. ** mci -- the connection info for output
  1366. **
  1367. ** Returns:
  1368. ** none.
  1369. */
  1370. static void
  1371. put_vanilla_header(h, v, mci)
  1372. HDR *h;
  1373. char *v;
  1374. MCI *mci;
  1375. {
  1376. register char *nlp;
  1377. register char *obp;
  1378. int putflags;
  1379. char obuf[MAXLINE];
  1380. putflags = PXLF_HEADER;
  1381. if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
  1382. putflags |= PXLF_STRIP8BIT;
  1383. (void) snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
  1384. obp = obuf + strlen(obuf);
  1385. while ((nlp = strchr(v, 'n')) != NULL)
  1386. {
  1387. int l;
  1388. l = nlp - v;
  1389. if (SPACELEFT(obuf, obp) - 1 < l)
  1390. l = SPACELEFT(obuf, obp) - 1;
  1391. snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
  1392. putxline(obuf, strlen(obuf), mci, putflags);
  1393. v += l + 1;
  1394. obp = obuf;
  1395. if (*v != ' ' && *v != 't')
  1396. *obp++ = ' ';
  1397. }
  1398. snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
  1399. (int) sizeof obuf - (obp - obuf) - 1, v);
  1400. putxline(obuf, strlen(obuf), mci, putflags);
  1401. }
  1402. /*
  1403. **  COMMAIZE -- output a header field, making a comma-translated list.
  1404. **
  1405. ** Parameters:
  1406. ** h -- the header field to output.
  1407. ** p -- the value to put in it.
  1408. ** oldstyle -- TRUE if this is an old style header.
  1409. ** mci -- the connection information.
  1410. ** e -- the envelope containing the message.
  1411. **
  1412. ** Returns:
  1413. ** none.
  1414. **
  1415. ** Side Effects:
  1416. ** outputs "p" to file "fp".
  1417. */
  1418. void
  1419. commaize(h, p, oldstyle, mci, e)
  1420. register HDR *h;
  1421. register char *p;
  1422. bool oldstyle;
  1423. register MCI *mci;
  1424. register ENVELOPE *e;
  1425. {
  1426. register char *obp;
  1427. int opos;
  1428. int omax;
  1429. bool firstone = TRUE;
  1430. int putflags = PXLF_HEADER;
  1431. char obuf[MAXLINE + 3];
  1432. /*
  1433. **  Output the address list translated by the
  1434. **  mailer and with commas.
  1435. */
  1436. if (tTd(14, 2))
  1437. dprintf("commaize(%s: %s)n", h->h_field, p);
  1438. if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
  1439. putflags |= PXLF_STRIP8BIT;
  1440. obp = obuf;
  1441. (void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field);
  1442. opos = strlen(h->h_field) + 2;
  1443. if (opos > 202)
  1444. opos = 202;
  1445. obp += opos;
  1446. omax = mci->mci_mailer->m_linelimit - 2;
  1447. if (omax < 0 || omax > 78)
  1448. omax = 78;
  1449. /*
  1450. **  Run through the list of values.
  1451. */
  1452. while (*p != '')
  1453. {
  1454. register char *name;
  1455. register int c;
  1456. char savechar;
  1457. int flags;
  1458. auto int status;
  1459. /*
  1460. **  Find the end of the name.  New style names
  1461. **  end with a comma, old style names end with
  1462. **  a space character.  However, spaces do not
  1463. **  necessarily delimit an old-style name -- at
  1464. **  signs mean keep going.
  1465. */
  1466. /* find end of name */
  1467. while ((isascii(*p) && isspace(*p)) || *p == ',')
  1468. p++;
  1469. name = p;
  1470. for (;;)
  1471. {
  1472. auto char *oldp;
  1473. char pvpbuf[PSBUFSIZE];
  1474. (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
  1475.        sizeof pvpbuf, &oldp, NULL);
  1476. p = oldp;
  1477. /* look to see if we have an at sign */
  1478. while (*p != '' && isascii(*p) && isspace(*p))
  1479. p++;
  1480. if (*p != '@')
  1481. {
  1482. p = oldp;
  1483. break;
  1484. }
  1485. p += *p == '@' ? 1 : 2;
  1486. while (*p != '' && isascii(*p) && isspace(*p))
  1487. p++;
  1488. }
  1489. /* at the end of one complete name */
  1490. /* strip off trailing white space */
  1491. while (p >= name &&
  1492.        ((isascii(*p) && isspace(*p)) || *p == ',' || *p == ''))
  1493. p--;
  1494. if (++p == name)
  1495. continue;
  1496. savechar = *p;
  1497. *p = '';
  1498. /* translate the name to be relative */
  1499. flags = RF_HEADERADDR|RF_ADDDOMAIN;
  1500. if (bitset(H_FROM, h->h_flags))
  1501. flags |= RF_SENDERADDR;
  1502. #if USERDB
  1503. else if (e->e_from.q_mailer != NULL &&
  1504.  bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
  1505. {
  1506. char *q;
  1507. q = udbsender(name);
  1508. if (q != NULL)
  1509. name = q;
  1510. }
  1511. #endif /* USERDB */
  1512. status = EX_OK;
  1513. name = remotename(name, mci->mci_mailer, flags, &status, e);
  1514. if (*name == '')
  1515. {
  1516. *p = savechar;
  1517. continue;
  1518. }
  1519. name = denlstring(name, FALSE, TRUE);
  1520. /*
  1521. **  record data progress so DNS timeouts
  1522. **  don't cause DATA timeouts
  1523. */
  1524. DataProgress = TRUE;
  1525. /* output the name with nice formatting */
  1526. opos += strlen(name);
  1527. if (!firstone)
  1528. opos += 2;
  1529. if (opos > omax && !firstone)
  1530. {
  1531. snprintf(obp, SPACELEFT(obuf, obp), ",n");
  1532. putxline(obuf, strlen(obuf), mci, putflags);
  1533. obp = obuf;
  1534. (void) strlcpy(obp, "        ", sizeof obp);
  1535. opos = strlen(obp);
  1536. obp += opos;
  1537. opos += strlen(name);
  1538. }
  1539. else if (!firstone)
  1540. {
  1541. snprintf(obp, SPACELEFT(obuf, obp), ", ");
  1542. obp += 2;
  1543. }
  1544. while ((c = *name++) != '' && obp < &obuf[MAXLINE])
  1545. *obp++ = c;
  1546. firstone = FALSE;
  1547. *p = savechar;
  1548. }
  1549. *obp = '';
  1550. putxline(obuf, strlen(obuf), mci, putflags);
  1551. }
  1552. /*
  1553. **  COPYHEADER -- copy header list
  1554. **
  1555. ** This routine is the equivalent of newstr for header lists
  1556. **
  1557. ** Parameters:
  1558. ** header -- list of header structures to copy.
  1559. **
  1560. ** Returns:
  1561. ** a copy of 'header'.
  1562. **
  1563. ** Side Effects:
  1564. ** none.
  1565. */
  1566. HDR *
  1567. copyheader(header)
  1568. register HDR *header;
  1569. {
  1570. register HDR *newhdr;
  1571. HDR *ret;
  1572. register HDR **tail = &ret;
  1573. while (header != NULL)
  1574. {
  1575. newhdr = (HDR *) xalloc(sizeof *newhdr);
  1576. STRUCTCOPY(*header, *newhdr);
  1577. *tail = newhdr;
  1578. tail = &newhdr->h_link;
  1579. header = header->h_link;
  1580. }
  1581. *tail = NULL;
  1582. return ret;
  1583. }
  1584. /*
  1585. **  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
  1586. **
  1587. ** Run through all of the parameters of a MIME header and
  1588. ** possibly truncate and rebalance the parameter according
  1589. ** to MaxMimeFieldLength.
  1590. **
  1591. ** Parameters:
  1592. ** string -- the full header
  1593. **
  1594. ** Returns:
  1595. ** TRUE if the header was modified, FALSE otherwise
  1596. **
  1597. ** Side Effects:
  1598. ** string modified in place
  1599. */
  1600. static bool
  1601. fix_mime_header(string)
  1602. char *string;
  1603. {
  1604. bool modified = FALSE;
  1605. char *begin = string;
  1606. char *end;
  1607. if (string == NULL || *string == '')
  1608. return FALSE;
  1609. /* Split on each ';' */
  1610. while ((end = find_character(begin, ';')) != NULL)
  1611. {
  1612. char save = *end;
  1613. char *bp;
  1614. *end = '';
  1615. /* Shorten individual parameter */
  1616. if (shorten_rfc822_string(begin, MaxMimeFieldLength))
  1617. modified = TRUE;
  1618. /* Collapse the possibly shortened string with rest */
  1619. bp = begin + strlen(begin);
  1620. if (bp != end)
  1621. {
  1622. char *ep = end;
  1623. *end = save;
  1624. end = bp;
  1625. /* copy character by character due to overlap */
  1626. while (*ep != '')
  1627. *bp++ = *ep++;
  1628. *bp = '';
  1629. }
  1630. else
  1631. *end = save;
  1632. if (*end == '')
  1633. break;
  1634. /* Move past ';' */
  1635. begin = end + 1;
  1636. }
  1637. return modified;
  1638. }