57
57
/* COMMAND-LINE ARGUMENTS
61
/* Enable message body query mode. When reading lookup keys
62
/* from standard input with "\fB-q -\fR", process the input
63
/* as if it is an email message in RFC 2822 format. Each line
64
/* of body content becomes one lookup key.
66
/* By default, the \fB-b\fR option starts generating lookup
67
/* keys at the first non-header line, and stops when the end
68
/* of the message is reached.
69
/* To simulate \fBbody_checks\fR(5) processing, enable MIME
70
/* parsing with \fB-m\fR. With this, the \fB-b\fR option
71
/* generates no body-style lookup keys for attachment MIME
72
/* headers and for attached message/* headers.
74
/* This feature is available in Postfix version 2.6 and later.
60
75
/* .IP "\fB-c \fIconfig_dir\fR"
61
76
/* Read the \fBmain.cf\fR configuration file in the named directory
62
77
/* instead of the default configuration directory.
74
89
/* With Postfix version 2.3 and later, this option has no
75
90
/* effect for regular expression tables. There, case folding
76
91
/* is controlled by appending a flag to a pattern.
93
/* Enable message header query mode. When reading lookup keys
94
/* from standard input with "\fB-q -\fR", process the input
95
/* as if it is an email message in RFC 2822 format. Each
96
/* logical header line becomes one lookup key. A multi-line
97
/* header becomes one lookup key with one or more embedded
98
/* newline characters.
100
/* By default, the \fB-h\fR option generates lookup keys until
101
/* the first non-header line is reached.
102
/* To simulate \fBheader_checks\fR(5) processing, enable MIME
103
/* parsing with \fB-m\fR. With this, the \fB-h\fR option also
104
/* generates header-style lookup keys for attachment MIME
105
/* headers and for attached message/* headers.
107
/* This feature is available in Postfix version 2.6 and later.
78
109
/* Incremental mode. Read entries from standard input and do not
79
110
/* truncate an existing database. By default, \fBpostmap\fR(1) creates
80
111
/* a new database from the entries in \fBfile_name\fR.
113
/* Enable MIME parsing with "\fB-b\fR" and "\fB-h\fR".
115
/* This feature is available in Postfix version 2.6 and later.
82
117
/* Include the terminating null character that terminates lookup keys
83
118
/* and values. By default, \fBpostmap\fR(1) does whatever is
253
289
#include <mkmap.h>
254
290
#include <mail_task.h>
255
291
#include <dict_proxy.h>
292
#include <mime_state.h>
293
#include <rec_type.h>
257
295
/* Application-specific. */
259
297
#define STR vstring_str
298
#define LEN VSTRING_LEN
261
300
#define POSTMAP_FLAG_AS_OWNER (1<<0) /* open dest as owner of source */
262
301
#define POSTMAP_FLAG_SAVE_PERM (1<<1) /* copy access permission from source */
302
#define POSTMAP_FLAG_HEADER_KEY (1<<2) /* apply to header text */
303
#define POSTMAP_FLAG_BODY_KEY (1<<3) /* apply to body text */
304
#define POSTMAP_FLAG_MIME_KEY (1<<4) /* enable MIME parsing */
306
#define POSTMAP_FLAG_HB_KEY (POSTMAP_FLAG_HEADER_KEY | POSTMAP_FLAG_BODY_KEY)
307
#define POSTMAP_FLAG_FULL_KEY (POSTMAP_FLAG_BODY_KEY | POSTMAP_FLAG_MIME_KEY)
308
#define POSTMAP_FLAG_ANY_KEY (POSTMAP_FLAG_HB_KEY | POSTMAP_FLAG_MIME_KEY)
311
* MIME Engine call-back state for generating lookup keys from an email
312
* message read from standard input.
315
DICT **dicts; /* map handles */
316
char **maps; /* map names */
317
int map_count; /* yes, indeed */
318
int dict_flags; /* query flags */
319
int header_done; /* past primary header */
320
int found; /* result */
264
323
/* postmap - create or update mapping database */
369
428
vstream_fclose(source_fp);
431
/* postmap_body - MIME engine body call-back routine */
433
static void postmap_body(void *ptr, int unused_rec_type,
438
POSTMAP_KEY_STATE *state = (POSTMAP_KEY_STATE *) ptr;
439
DICT **dicts = state->dicts;
440
char **maps = state->maps;
441
int map_count = state->map_count;
442
int dict_flags = state->dict_flags;
443
const char *map_name;
447
for (n = 0; n < map_count; n++) {
449
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
450
dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
451
dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
452
if ((value = dict_get(dicts[n], keybuf)) != 0) {
454
msg_warn("table %s:%s: key %s: empty string result is not allowed",
455
dicts[n]->type, dicts[n]->name, keybuf);
456
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
457
dicts[n]->type, dicts[n]->name);
459
vstream_printf("%s %s\n", keybuf, value);
466
/* postmap_header - MIME engine header call-back routine */
468
static void postmap_header(void *ptr, int unused_header_class,
469
const HEADER_OPTS *unused_header_info,
475
* Don't re-invent an already working wheel.
477
postmap_body(ptr, 0, STR(header_buf), LEN(header_buf), offset);
480
/* postmap_head_end - MIME engine end-of-header call-back routine */
482
static void postmap_head_end(void *ptr)
484
POSTMAP_KEY_STATE *state = (POSTMAP_KEY_STATE *) ptr;
487
* Don't process the message body when we only examine primary headers.
489
state->header_done = 1;
372
492
/* postmap_queries - apply multiple requests from stdin */
374
494
static int postmap_queries(VSTREAM *in, char **maps, const int map_count,
495
const int postmap_flags,
375
496
const int dict_flags)
398
519
* Perform all queries. Open maps on the fly, to avoid opening unecessary
401
while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
402
for (n = 0; n < map_count; n++) {
404
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
522
if ((postmap_flags & POSTMAP_FLAG_HB_KEY) == 0) {
523
while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
524
for (n = 0; n < map_count; n++) {
526
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
405
527
dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
406
528
dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
407
if ((value = dict_get(dicts[n], STR(keybuf))) != 0) {
409
msg_warn("table %s:%s: key %s: empty string result is not allowed",
410
dicts[n]->type, dicts[n]->name, STR(keybuf));
411
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
412
dicts[n]->type, dicts[n]->name);
529
if ((value = dict_get(dicts[n], STR(keybuf))) != 0) {
531
msg_warn("table %s:%s: key %s: empty string result is not allowed",
532
dicts[n]->type, dicts[n]->name, STR(keybuf));
533
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
534
dicts[n]->type, dicts[n]->name);
536
vstream_printf("%s %s\n", STR(keybuf), value);
414
vstream_printf("%s %s\n", STR(keybuf), value);
543
POSTMAP_KEY_STATE key_state;
544
MIME_STATE *mime_state;
548
* Bundle up the request and instantiate a MIME parsing engine.
550
key_state.dicts = dicts;
551
key_state.maps = maps;
552
key_state.map_count = map_count;
553
key_state.dict_flags = dict_flags;
554
key_state.header_done = 0;
557
mime_state_alloc((postmap_flags & POSTMAP_FLAG_MIME_KEY) ?
558
0 : MIME_OPT_DISABLE_MIME,
559
(postmap_flags & POSTMAP_FLAG_HEADER_KEY) ?
560
postmap_header : (MIME_STATE_HEAD_OUT) 0,
561
(postmap_flags & POSTMAP_FLAG_FULL_KEY) ?
562
(MIME_STATE_ANY_END) 0 : postmap_head_end,
563
(postmap_flags & POSTMAP_FLAG_BODY_KEY) ?
564
postmap_body : (MIME_STATE_BODY_OUT) 0,
565
(MIME_STATE_ANY_END) 0,
566
(MIME_STATE_ERR_PRINT) 0,
567
(void *) &key_state);
570
* Process the input message.
572
while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF
573
&& key_state.header_done == 0 && mime_errs == 0)
574
mime_errs = mime_state_update(mime_state, REC_TYPE_NORM,
575
STR(keybuf), LEN(keybuf));
578
* Flush the MIME engine output buffer and tidy up loose ends.
581
mime_errs = mime_state_update(mime_state, REC_TYPE_END, "", 0);
583
msg_fatal("message format error: %s",
584
mime_state_detail(mime_errs)->text);
585
mime_state_free(mime_state);
586
found = key_state.found;
421
589
vstream_fflush(VSTREAM_OUT);
729
909
if (strcmp(query, "-") == 0)
730
910
exit(postmap_queries(VSTREAM_IN, argv + optind, argc - optind,
731
dict_flags | DICT_FLAG_LOCK) == 0);
911
postmap_flags, dict_flags | DICT_FLAG_LOCK) == 0);
732
912
while (optind < argc) {
733
913
if ((path_name = split_at(argv[optind], ':')) != 0) {
734
914
found = postmap_query(argv[optind], path_name, query,