1/*	$NetBSD$	*/
2
3/*++
4/* NAME
5/*	header_opts 3
6/* SUMMARY
7/*	message header classification
8/* SYNOPSIS
9/*	#include <header_opts.h>
10/*
11/*	const HEADER_OPTS *header_opts_find(string)
12/*	const char *string;
13/* DESCRIPTION
14/*	header_opts_find() takes a message header line and looks up control
15/*	information for the corresponding header type.
16/* DIAGNOSTICS
17/*	Panic: input is not a valid header line. The result is a pointer
18/*	to HEADER_OPTS in case of success, a null pointer when the header
19/*	label was not recognized.
20/* SEE ALSO
21/*	header_opts(3h) the gory details
22/* LICENSE
23/* .ad
24/* .fi
25/*	The Secure Mailer license must be distributed with this software.
26/* AUTHOR(S)
27/*	Wietse Venema
28/*	IBM T.J. Watson Research
29/*	P.O. Box 704
30/*	Yorktown Heights, NY 10598, USA
31/*--*/
32
33/* System library. */
34
35#include <sys_defs.h>
36#include <ctype.h>
37
38/* Utility library. */
39
40#include <msg.h>
41#include <htable.h>
42#include <vstring.h>
43#include <stringops.h>
44
45/* Global library. */
46
47#include "header_opts.h"
48
49 /*
50  * Header names are given in the preferred capitalization. The lookups are
51  * case-insensitive.
52  *
53  * XXX Removing Return-Path: headers should probably be done only with mail
54  * that enters via a non-SMTP channel. Changing this now could break other
55  * software. See also comments in bounce_notify_util.c.
56  */
57static const HEADER_OPTS header_opts[] = {
58    "Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
59    "Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP,
60    "Cc", HDR_CC, HDR_OPT_XRECIP,
61    "Content-Description", HDR_CONTENT_DESCRIPTION, HDR_OPT_MIME,
62    "Content-Disposition", HDR_CONTENT_DISPOSITION, HDR_OPT_MIME,
63    "Content-ID", HDR_CONTENT_ID, HDR_OPT_MIME,
64    "Content-Length", HDR_CONTENT_LENGTH, HDR_OPT_DROP,
65    "Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, HDR_OPT_MIME,
66    "Content-Type", HDR_CONTENT_TYPE, HDR_OPT_MIME,
67    "Delivered-To", HDR_DELIVERED_TO, 0,
68    "Disposition-Notification-To", HDR_DISP_NOTIFICATION, HDR_OPT_SENDER,
69    "Date", HDR_DATE, 0,
70    "Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
71    "From", HDR_FROM, HDR_OPT_SENDER,
72    "Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
73    "Message-Id", HDR_MESSAGE_ID, 0,
74    "MIME-Version", HDR_MIME_VERSION, HDR_OPT_MIME,
75    "Received", HDR_RECEIVED, 0,
76    "Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
77    "Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP | HDR_OPT_RR,
78    "Resent-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | HDR_OPT_RR,
79    "Resent-Date", HDR_RESENT_DATE, HDR_OPT_RR,
80    "Resent-From", HDR_RESENT_FROM, HDR_OPT_SENDER | HDR_OPT_RR,
81    "Resent-Message-Id", HDR_RESENT_MESSAGE_ID, HDR_OPT_RR,
82    "Resent-Reply-To", HDR_RESENT_REPLY_TO, HDR_OPT_RECIP | HDR_OPT_RR,
83    "Resent-Sender", HDR_RESENT_SENDER, HDR_OPT_SENDER | HDR_OPT_RR,
84    "Resent-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
85    "Return-Path", HDR_RETURN_PATH, HDR_OPT_DROP | HDR_OPT_SENDER,
86    "Return-Receipt-To", HDR_RETURN_RECEIPT_TO, HDR_OPT_SENDER,
87    "Sender", HDR_SENDER, HDR_OPT_SENDER,
88    "To", HDR_TO, HDR_OPT_XRECIP,
89};
90
91#define HEADER_OPTS_SIZE (sizeof(header_opts) / sizeof(header_opts[0]))
92
93static HTABLE *header_hash;		/* quick lookup */
94static VSTRING *header_key;
95
96/* header_opts_init - initialize */
97
98static void header_opts_init(void)
99{
100    const HEADER_OPTS *hp;
101    const char *cp;
102
103    /*
104     * Build a hash table for quick lookup, and allocate memory for
105     * lower-casing the lookup key.
106     */
107    header_key = vstring_alloc(10);
108    header_hash = htable_create(HEADER_OPTS_SIZE);
109    for (hp = header_opts; hp < header_opts + HEADER_OPTS_SIZE; hp++) {
110	VSTRING_RESET(header_key);
111	for (cp = hp->name; *cp; cp++)
112	    VSTRING_ADDCH(header_key, TOLOWER(*cp));
113	VSTRING_TERMINATE(header_key);
114	htable_enter(header_hash, vstring_str(header_key), (char *) hp);
115    }
116}
117
118/* header_opts_find - look up header options */
119
120const HEADER_OPTS *header_opts_find(const char *string)
121{
122    const char *cp;
123
124    if (header_hash == 0)
125	header_opts_init();
126
127    /*
128     * Look up the lower-cased version of the header name.
129     */
130    VSTRING_RESET(header_key);
131    for (cp = string; *cp != ':'; cp++) {
132	if (*cp == 0)
133	    msg_panic("header_opts_find: no colon in header: %.30s", string);
134	VSTRING_ADDCH(header_key, TOLOWER(*cp));
135    }
136    vstring_truncate(header_key,
137		     trimblanks(vstring_str(header_key), cp - string)
138		     - vstring_str(header_key));
139    VSTRING_TERMINATE(header_key);
140    return ((const HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
141}
142