summaryrefslogtreecommitdiffstats
path: root/src/global/header_opts.c
blob: c0c4d5ceb81027960c4ad4e91a04458202a90fb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*++
/* NAME
/*	header_opts 3
/* SUMMARY
/*	message header classification
/* SYNOPSIS
/*	#include <header_opts.h>
/*
/*	const HEADER_OPTS *header_opts_find(string)
/*	const char *string;
/* DESCRIPTION
/*	header_opts_find() takes a message header line and looks up control
/*	information for the corresponding header type.
/* DIAGNOSTICS
/*	Panic: input is not a valid header line. The result is a pointer
/*	to HEADER_OPTS in case of success, a null pointer when the header
/*	label was not recognized.
/* SEE ALSO
/*	header_opts(3h) the gory details
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <ctype.h>

/* Utility library. */

#include <msg.h>
#include <htable.h>
#include <vstring.h>
#include <stringops.h>
#include <argv.h>
#include <mymalloc.h>

/* Global library. */

#include <mail_params.h>
#include <header_opts.h>

 /*
  * Header names are given in the preferred capitalization. The lookups are
  * case-insensitive.
  * 
  * XXX Removing Return-Path: headers should probably be done only with mail
  * that enters via a non-SMTP channel. Changing this now could break other
  * software. See also comments in bounce_notify_util.c.
  */
static HEADER_OPTS header_opts[] = {
    "Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
    "Bcc", HDR_BCC, HDR_OPT_XRECIP,
    "Cc", HDR_CC, HDR_OPT_XRECIP,
    "Content-Description", HDR_CONTENT_DESCRIPTION, HDR_OPT_MIME,
    "Content-Disposition", HDR_CONTENT_DISPOSITION, HDR_OPT_MIME,
    "Content-ID", HDR_CONTENT_ID, HDR_OPT_MIME,
    "Content-Length", HDR_CONTENT_LENGTH, 0,
    "Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, HDR_OPT_MIME,
    "Content-Type", HDR_CONTENT_TYPE, HDR_OPT_MIME,
    "Delivered-To", HDR_DELIVERED_TO, 0,
    "Disposition-Notification-To", HDR_DISP_NOTIFICATION, HDR_OPT_SENDER,
    "Date", HDR_DATE, 0,
    "Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
    "From", HDR_FROM, HDR_OPT_SENDER,
    "Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
    "Message-Id", HDR_MESSAGE_ID, 0,
    "MIME-Version", HDR_MIME_VERSION, HDR_OPT_MIME,
    "Received", HDR_RECEIVED, 0,
    "Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
    "Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_XRECIP | HDR_OPT_RR,
    "Resent-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | HDR_OPT_RR,
    "Resent-Date", HDR_RESENT_DATE, HDR_OPT_RR,
    "Resent-From", HDR_RESENT_FROM, HDR_OPT_SENDER | HDR_OPT_RR,
    "Resent-Message-Id", HDR_RESENT_MESSAGE_ID, HDR_OPT_RR,
    "Resent-Reply-To", HDR_RESENT_REPLY_TO, HDR_OPT_RECIP | HDR_OPT_RR,
    "Resent-Sender", HDR_RESENT_SENDER, HDR_OPT_SENDER | HDR_OPT_RR,
    "Resent-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
    "Return-Path", HDR_RETURN_PATH, HDR_OPT_SENDER,
    "Return-Receipt-To", HDR_RETURN_RECEIPT_TO, HDR_OPT_SENDER,
    "Sender", HDR_SENDER, HDR_OPT_SENDER,
    "To", HDR_TO, HDR_OPT_XRECIP,
};

#define HEADER_OPTS_SIZE (sizeof(header_opts) / sizeof(header_opts[0]))

static HTABLE *header_hash;		/* quick lookup */
static VSTRING *header_key;

/* header_opts_init - initialize */

static void header_opts_init(void)
{
    const HEADER_OPTS *hp;
    const char *cp;

    /*
     * Build a hash table for quick lookup, and allocate memory for
     * lower-casing the lookup key.
     */
    header_key = vstring_alloc(10);
    header_hash = htable_create(HEADER_OPTS_SIZE);
    for (hp = header_opts; hp < header_opts + HEADER_OPTS_SIZE; hp++) {
	VSTRING_RESET(header_key);
	for (cp = hp->name; *cp; cp++)
	    VSTRING_ADDCH(header_key, TOLOWER(*cp));
	VSTRING_TERMINATE(header_key);
	htable_enter(header_hash, vstring_str(header_key), (void *) hp);
    }
}

/* header_drop_init - initialize "header drop" flags */

static void header_drop_init(void)
{
    ARGV   *hdr_drop_list;
    char  **cpp;
    HTABLE_INFO *ht;
    HEADER_OPTS *hp;

    /*
     * Having one main.cf parameter for the "drop" header flag does not
     * generalize to the "sender", "extract", etc., flags. Flags would need
     * to be grouped by header name, but that would be unwieldy, too:
     * 
     * message_header_flags = { apparently-to = recipient }, { bcc = recipient,
     * extract, drop }, { from = sender }, ...
     * 
     * Thus, it is unlikely that all header flags will become configurable.
     */
    hdr_drop_list = argv_split(var_drop_hdrs, CHARS_COMMA_SP);
    for (cpp = hdr_drop_list->argv; *cpp; cpp++) {
	lowercase(*cpp);
	if ((ht = htable_locate(header_hash, *cpp)) == 0) {
	    hp = (HEADER_OPTS *) mymalloc(sizeof(*hp));
	    hp->type = HDR_OTHER;
	    hp->flags = HDR_OPT_DROP;
	    ht = htable_enter(header_hash, *cpp, (void *) hp);
	    hp->name = ht->key;
	} else
	    hp = (HEADER_OPTS *) ht->value;
	hp->flags |= HDR_OPT_DROP;
    }
    argv_free(hdr_drop_list);
}

/* header_opts_find - look up header options */

const HEADER_OPTS *header_opts_find(const char *string)
{
    const char *cp;

    if (header_hash == 0) {
	header_opts_init();
	header_drop_init();
    }

    /*
     * Look up the lower-cased version of the header name.
     */
    VSTRING_RESET(header_key);
    for (cp = string; *cp != ':'; cp++) {
	if (*cp == 0)
	    msg_panic("header_opts_find: no colon in header: %.30s", string);
	VSTRING_ADDCH(header_key, TOLOWER(*cp));
    }
    vstring_truncate(header_key,
		     trimblanks(vstring_str(header_key), cp - string)
		     - vstring_str(header_key));
    VSTRING_TERMINATE(header_key);
    return ((const HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
}