Postfix3.3.1
header_body_checks.c
[詳解]
1 /*++
2 /* NAME
3 /* header_body_checks 3
4 /* SUMMARY
5 /* header/body checks
6 /* SYNOPSIS
7 /* #include <header_body_checks.h>
8 /*
9 /* typedef struct {
10 /* void (*logger) (void *context, const char *action,
11 /* const char *where, const char *line,
12 /* const char *optional_text);
13 /* void (*prepend) (void *context, int rec_type,
14 /* const char *buf, ssize_t len, off_t offset);
15 /* char *(*extend) (void *context, const char *command,
16 /* ssize_t cmd_len, const char *cmd_args,
17 /* const char *where, const char *line,
18 /* ssize_t line_len, off_t offset);
19 /* } HBC_CALL_BACKS;
20 /*
21 /* HBC_CHECKS *hbc_header_checks_create(
22 /* header_checks_name, header_checks_value
23 /* mime_header_checks_name, mime_header_checks_value,
24 /* nested_header_checks_name, nested_header_checks_value,
25 /* call_backs)
26 /* const char *header_checks_name;
27 /* const char *header_checks_value;
28 /* const char *mime_header_checks_name;
29 /* const char *mime_header_checks_value;
30 /* const char *nested_header_checks_name;
31 /* const char *nested_header_checks_value;
32 /* HBC_CALL_BACKS *call_backs;
33 /*
34 /* HBC_CHECKS *hbc_body_checks_create(
35 /* body_checks_name, body_checks_value,
36 /* call_backs)
37 /* const char *body_checks_name;
38 /* const char *body_checks_value;
39 /* HBC_CALL_BACKS *call_backs;
40 /*
41 /* char *hbc_header_checks(context, hbc, header_class, hdr_opts, header)
42 /* void *context;
43 /* HBC_CHECKS *hbc;
44 /* int header_class;
45 /* const HEADER_OPTS *hdr_opts;
46 /* VSTRING *header;
47 /*
48 /* char *hbc_body_checks(context, hbc, body_line, body_line_len)
49 /* void *context;
50 /* HBC_CHECKS *hbc;
51 /* const char *body_line;
52 /* ssize_t body_line_len;
53 /*
54 /* void hbc_header_checks_free(hbc)
55 /* HBC_CHECKS *hbc;
56 /*
57 /* void hbc_body_checks_free(hbc)
58 /* HBC_CHECKS *hbc;
59 /* DESCRIPTION
60 /* This module implements header_checks and body_checks.
61 /* Actions are executed while mail is being delivered. The
62 /* following actions are recognized: INFO, WARN, REPLACE,
63 /* PREPEND, IGNORE, DUNNO, and OK. These actions are safe for
64 /* use in delivery agents.
65 /*
66 /* Other actions may be supplied via the extension mechanism
67 /* described below. For example, actions that change the
68 /* message delivery time or destination. Such actions do not
69 /* make sense in delivery agents, but they can be appropriate
70 /* in, for example, before-queue filters.
71 /*
72 /* hbc_header_checks_create() creates a context for header
73 /* inspection. This function is typically called once during
74 /* program initialization. The result is a null pointer when
75 /* all _value arguments specify zero-length strings; in this
76 /* case, hbc_header_checks() and hbc_header_checks_free() must
77 /* not be called.
78 /*
79 /* hbc_header_checks() inspects the specified logical header.
80 /* The result is either the original header, HBC_CHECKS_STAT_IGNORE
81 /* (meaning: discard the header), HBC_CHECKS_STAT_ERROR, or a
82 /* new header (meaning: replace the header and destroy the new
83 /* header with myfree()).
84 /*
85 /* hbc_header_checks_free() returns memory to the pool.
86 /*
87 /* hbc_body_checks_create(), hbc_body_checks(), hbc_body_free()
88 /* perform similar functions for body lines.
89 /*
90 /* Arguments:
91 /* .IP body_line
92 /* One line of body text.
93 /* .IP body_line_len
94 /* Body line length.
95 /* .IP call_backs
96 /* Table with call-back function pointers. This argument is
97 /* not copied. Note: the description below is not necessarily
98 /* in data structure order.
99 /* .RS
100 /* .IP logger
101 /* Call-back function for logging an action with the action's
102 /* name in lower case, a location within a message ("header"
103 /* or "body"), the content of the header or body line that
104 /* triggered the action, and optional text or a zero-length
105 /* string. This call-back feature must be specified.
106 /* .IP prepend
107 /* Call-back function for the PREPEND action. The arguments
108 /* are the same as those of mime_state(3) body output call-back
109 /* functions. Specify a null pointer to disable this action.
110 /* .IP extend
111 /* Call-back function that logs and executes other actions.
112 /* This function receives as arguments the command name and
113 /* name length, the command arguments if any, the location
114 /* within the message ("header" or "body"), the content and
115 /* length of the header or body line that triggered the action,
116 /* and the input byte offset within the current header or body
117 /* segment. The result value is either the original line
118 /* argument, HBC_CHECKS_STAT_IGNORE (delete the line from the
119 /* input stream) or HBC_CHECKS_STAT_UNKNOWN (the command was
120 /* not recognized). Specify a null pointer to disable this
121 /* feature.
122 /* .RE
123 /* .IP context
124 /* Application context for call-back functions specified with the
125 /* call_backs argument.
126 /* .IP header
127 /* A logical message header. Lines within a multi-line header
128 /* are separated by a newline character.
129 /* .IP "header_checks_name, mime_header_checks_name"
130 /* .IP "nested_header_checks_name, body_checks_name"
131 /* The main.cf configuration parameter names for header and body
132 /* map lists.
133 /* .IP "header_checks_value, mime_header_checks_value"
134 /* .IP "nested_header_checks_value, body_checks_value"
135 /* The values of main.cf configuration parameters for header and body
136 /* map lists. Specify a zero-length string to disable a specific list.
137 /* .IP header_class
138 /* A number in the range MIME_HDR_FIRST..MIME_HDR_LAST.
139 /* .IP hbc
140 /* A handle created with hbc_header_checks_create() or
141 /* hbc_body_checks_create().
142 /* .IP hdr_opts
143 /* Message header properties.
144 /* SEE ALSO
145 /* msg(3) diagnostics interface
146 /* DIAGNOSTICS
147 /* Fatal errors: memory allocation problem.
148 /* LICENSE
149 /* .ad
150 /* .fi
151 /* The Secure Mailer license must be distributed with this software.
152 /* AUTHOR(S)
153 /* Wietse Venema
154 /* IBM T.J. Watson Research
155 /* P.O. Box 704
156 /* Yorktown Heights, NY 10598, USA
157 /*
158 /* Wietse Venema
159 /* Google, Inc.
160 /* 111 8th Avenue
161 /* New York, NY 10011, USA
162 /*--*/
163 
164 /* System library. */
165 
166 #include <sys_defs.h>
167 #include <ctype.h>
168 #include <string.h>
169 #ifdef STRCASECMP_IN_STRINGS_H
170 #include <strings.h>
171 #endif
172 
173 /* Utility library. */
174 
175 #include <msg.h>
176 #include <mymalloc.h>
177 
178 /* Global library. */
179 
180 #include <mime_state.h>
181 #include <rec_type.h>
182 #include <is_header.h>
183 #include <cleanup_user.h>
184 #include <dsn_util.h>
185 #include <header_body_checks.h>
186 
187 /* Application-specific. */
188 
189  /*
190  * Something that is guaranteed to be different from a real string result
191  * from header/body_checks.
192  */
195 
196  /*
197  * Header checks are stored as an array of HBC_MAP_INFO structures, one
198  * structure for each header class (MIME_HDR_PRIMARY, MIME_HDR_MULTIPART, or
199  * MIME_HDR_NESTED).
200  *
201  * Body checks are stored as one single HBC_MAP_INFO structure, because we make
202  * no distinction between body segments.
203  */
204 #define HBC_HEADER_INDEX(class) ((class) - MIME_HDR_FIRST)
205 #define HBC_BODY_INDEX (0)
206 
207 #define HBC_INIT(hbc, index, name, value) do { \
208  HBC_MAP_INFO *_mp = (hbc)->map_info + (index); \
209  if (*(value) != 0) { \
210  _mp->map_class = (name); \
211  _mp->maps = maps_create((name), (value), DICT_FLAG_LOCK); \
212  } else { \
213  _mp->map_class = 0; \
214  _mp->maps = 0; \
215  } \
216  } while (0)
217 
218 /* How does the action routine know where we are? */
219 
220 #define HBC_CTXT_HEADER "header"
221 #define HBC_CTXT_BODY "body"
222 
223 /* Silly little macros. */
224 
225 #define STR(x) vstring_str(x)
226 #define LEN(x) VSTRING_LEN(x)
227 
228 /* hbc_action - act upon a header/body match */
229 
230 static char *hbc_action(void *context, HBC_CALL_BACKS *cb,
231  const char *map_class, const char *where,
232  const char *cmd, const char *line,
233  ssize_t line_len, off_t offset)
234 {
235  const char *cmd_args = cmd + strcspn(cmd, " \t");
236  ssize_t cmd_len = cmd_args - cmd;
237  char *ret;
238 
239  /*
240  * XXX We don't use a hash table for action lookup. Mail rarely triggers
241  * an action, and mail that triggers multiple actions is even rarer.
242  * Setting up the hash table costs more than we would gain from using it.
243  */
244  while (*cmd_args && ISSPACE(*cmd_args))
245  cmd_args++;
246 
247 #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)
248 
249  if (cb->extend
250  && (ret = cb->extend(context, cmd, cmd_len, cmd_args, where, line,
251  line_len, offset)) != HBC_CHECKS_STAT_UNKNOWN)
252  return (ret);
253 
254  if (STREQUAL(cmd, "WARN", cmd_len)) {
255  cb->logger(context, "warning", where, line, cmd_args);
256  return ((char *) line);
257  }
258  if (STREQUAL(cmd, "INFO", cmd_len)) {
259  cb->logger(context, "info", where, line, cmd_args);
260  return ((char *) line);
261  }
262  if (STREQUAL(cmd, "REPLACE", cmd_len)) {
263  if (*cmd_args == 0) {
264  msg_warn("REPLACE action without text in %s map", map_class);
265  return ((char *) line);
266  } else if (strcmp(where, HBC_CTXT_HEADER) == 0
267  && !is_header(cmd_args)) {
268  msg_warn("bad REPLACE header text \"%s\" in %s map -- "
269  "need \"headername: headervalue\"", cmd_args, map_class);
270  return ((char *) line);
271  } else {
272  cb->logger(context, "replace", where, line, cmd_args);
273  return (mystrdup(cmd_args));
274  }
275  }
276  if (cb->prepend && STREQUAL(cmd, "PREPEND", cmd_len)) {
277  if (*cmd_args == 0) {
278  msg_warn("PREPEND action without text in %s map", map_class);
279  } else if (strcmp(where, HBC_CTXT_HEADER) == 0
280  && !is_header(cmd_args)) {
281  msg_warn("bad PREPEND header text \"%s\" in %s map -- "
282  "need \"headername: headervalue\"", cmd_args, map_class);
283  } else {
284  cb->logger(context, "prepend", where, line, cmd_args);
285  cb->prepend(context, REC_TYPE_NORM, cmd_args, strlen(cmd_args), offset);
286  }
287  return ((char *) line);
288  }
289  if (STREQUAL(cmd, "STRIP", cmd_len)) {
290  cb->logger(context, "strip", where, line, cmd_args);
291  return (HBC_CHECKS_STAT_IGNORE);
292  }
293  /* Allow and ignore optional text after the action. */
294 
295  if (STREQUAL(cmd, "IGNORE", cmd_len))
296  /* XXX Not logged for compatibility with cleanup(8). */
297  return (HBC_CHECKS_STAT_IGNORE);
298 
299  if (STREQUAL(cmd, "DUNNO", cmd_len) /* preferred */
300  ||STREQUAL(cmd, "OK", cmd_len)) /* compatibility */
301  return ((char *) line);
302 
303  msg_warn("unsupported command in %s map: %s", map_class, cmd);
304  return ((char *) line);
305 }
306 
307 /* hbc_header_checks - process one complete header line */
308 
309 char *hbc_header_checks(void *context, HBC_CHECKS *hbc, int header_class,
310  const HEADER_OPTS *hdr_opts,
311  VSTRING *header, off_t offset)
312 {
313  const char *myname = "hbc_header_checks";
314  const char *action;
315  HBC_MAP_INFO *mp;
316 
317  if (msg_verbose)
318  msg_info("%s: '%.30s'", myname, STR(header));
319 
320  /*
321  * XXX This is for compatibility with the cleanup(8) server.
322  */
323  if (hdr_opts && (hdr_opts->flags & HDR_OPT_MIME))
324  header_class = MIME_HDR_MULTIPART;
325 
326  mp = hbc->map_info + HBC_HEADER_INDEX(header_class);
327 
328  if (mp->maps != 0 && (action = maps_find(mp->maps, STR(header), 0)) != 0) {
329  return (hbc_action(context, hbc->call_backs,
330  mp->map_class, HBC_CTXT_HEADER, action,
331  STR(header), LEN(header), offset));
332  } else if (mp->maps && mp->maps->error) {
333  return (HBC_CHECKS_STAT_ERROR);
334  } else {
335  return (STR(header));
336  }
337 }
338 
339 /* hbc_body_checks - inspect one body record */
340 
341 char *hbc_body_checks(void *context, HBC_CHECKS *hbc, const char *line,
342  ssize_t len, off_t offset)
343 {
344  const char *myname = "hbc_body_checks";
345  const char *action;
346  HBC_MAP_INFO *mp;
347 
348  if (msg_verbose)
349  msg_info("%s: '%.30s'", myname, line);
350 
351  mp = hbc->map_info;
352 
353  if ((action = maps_find(mp->maps, line, 0)) != 0) {
354  return (hbc_action(context, hbc->call_backs,
355  mp->map_class, HBC_CTXT_BODY, action,
356  line, len, offset));
357  } else if (mp->maps->error) {
358  return (HBC_CHECKS_STAT_ERROR);
359  } else {
360  return ((char *) line);
361  }
362 }
363 
364 /* hbc_header_checks_create - create header checking context */
365 
366 HBC_CHECKS *hbc_header_checks_create(const char *header_checks_name,
367  const char *header_checks_value,
368  const char *mime_header_checks_name,
369  const char *mime_header_checks_value,
370  const char *nested_header_checks_name,
371  const char *nested_header_checks_value,
372  HBC_CALL_BACKS *call_backs)
373 {
374  HBC_CHECKS *hbc;
375 
376  /*
377  * Optimize for the common case.
378  */
379  if (*header_checks_value == 0 && *mime_header_checks_value == 0
380  && *nested_header_checks_value == 0) {
381  return (0);
382  } else {
383  hbc = (HBC_CHECKS *) mymalloc(sizeof(*hbc)
384  + (MIME_HDR_LAST - MIME_HDR_FIRST) * sizeof(HBC_MAP_INFO));
385  hbc->call_backs = call_backs;
387  header_checks_name, header_checks_value);
389  mime_header_checks_name, mime_header_checks_value);
391  nested_header_checks_name, nested_header_checks_value);
392  return (hbc);
393  }
394 }
395 
396 /* hbc_body_checks_create - create body checking context */
397 
398 HBC_CHECKS *hbc_body_checks_create(const char *body_checks_name,
399  const char *body_checks_value,
400  HBC_CALL_BACKS *call_backs)
401 {
402  HBC_CHECKS *hbc;
403 
404  /*
405  * Optimize for the common case.
406  */
407  if (*body_checks_value == 0) {
408  return (0);
409  } else {
410  hbc = (HBC_CHECKS *) mymalloc(sizeof(*hbc));
411  hbc->call_backs = call_backs;
412  HBC_INIT(hbc, HBC_BODY_INDEX, body_checks_name, body_checks_value);
413  return (hbc);
414  }
415 }
416 
417 /* _hbc_checks_free - destroy header/body checking context */
418 
419 void _hbc_checks_free(HBC_CHECKS *hbc, ssize_t len)
420 {
421  HBC_MAP_INFO *mp;
422 
423  for (mp = hbc->map_info; mp < hbc->map_info + len; mp++)
424  if (mp->maps)
425  maps_free(mp->maps);
426  myfree((void *) hbc);
427 }
428 
429  /*
430  * Test program. Specify the four maps on the command line, and feed a
431  * MIME-formatted message on stdin.
432  */
433 
434 #ifdef TEST
435 
436 #include <stdlib.h>
437 #include <stringops.h>
438 #include <vstream.h>
439 #include <msg_vstream.h>
440 #include <rec_streamlf.h>
441 #include <mail_params.h>
442 
443 typedef struct {
444  HBC_CHECKS *header_checks;
445  HBC_CHECKS *body_checks;
446  HBC_CALL_BACKS *call_backs;
447  VSTREAM *fp;
448  VSTRING *buf;
449  const char *queueid;
450  int recno;
451 } HBC_TEST_CONTEXT;
452 
453 /*#define REC_LEN 40*/
454 #define REC_LEN 1024
455 
456 /* log_cb - log action with context */
457 
458 static void log_cb(void *context, const char *action, const char *where,
459  const char *content, const char *text)
460 {
461  const HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;
462 
463  if (*text) {
464  msg_info("%s: %s: %s %.200s: %s",
465  dp->queueid, action, where, content, text);
466  } else {
467  msg_info("%s: %s: %s %.200s",
468  dp->queueid, action, where, content);
469  }
470 }
471 
472 /* out_cb - output call-back */
473 
474 static void out_cb(void *context, int rec_type, const char *buf,
475  ssize_t len, off_t offset)
476 {
477  const HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;
478 
479  vstream_fwrite(dp->fp, buf, len);
480  VSTREAM_PUTC('\n', dp->fp);
481  vstream_fflush(dp->fp);
482 }
483 
484 /* head_out - MIME_STATE header call-back */
485 
486 static void head_out(void *context, int header_class,
487  const HEADER_OPTS *header_info,
488  VSTRING *buf, off_t offset)
489 {
490  HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;
491  char *out;
492 
493  if (dp->header_checks == 0
494  || (out = hbc_header_checks(context, dp->header_checks, header_class,
495  header_info, buf, offset)) == STR(buf)) {
496  vstring_sprintf(dp->buf, "%d %s %ld\t|%s",
497  dp->recno,
498  header_class == MIME_HDR_PRIMARY ? "MAIN" :
499  header_class == MIME_HDR_MULTIPART ? "MULT" :
500  header_class == MIME_HDR_NESTED ? "NEST" :
501  "ERROR", (long) offset, STR(buf));
502  out_cb(dp, REC_TYPE_NORM, STR(dp->buf), LEN(dp->buf), offset);
503  } else if (out != 0) {
504  vstring_sprintf(dp->buf, "%d %s %ld\t|%s",
505  dp->recno,
506  header_class == MIME_HDR_PRIMARY ? "MAIN" :
507  header_class == MIME_HDR_MULTIPART ? "MULT" :
508  header_class == MIME_HDR_NESTED ? "NEST" :
509  "ERROR", (long) offset, out);
510  out_cb(dp, REC_TYPE_NORM, STR(dp->buf), LEN(dp->buf), offset);
511  myfree(out);
512  }
513  dp->recno += 1;
514 }
515 
516 /* header_end - MIME_STATE end-of-header call-back */
517 
518 static void head_end(void *context)
519 {
520  HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;
521 
522  out_cb(dp, 0, "HEADER END", sizeof("HEADER END") - 1, 0);
523 }
524 
525 /* body_out - MIME_STATE body line call-back */
526 
527 static void body_out(void *context, int rec_type, const char *buf,
528  ssize_t len, off_t offset)
529 {
530  HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;
531  char *out;
532 
533  if (dp->body_checks == 0
534  || (out = hbc_body_checks(context, dp->body_checks,
535  buf, len, offset)) == buf) {
536  vstring_sprintf(dp->buf, "%d BODY %c %ld\t|%s",
537  dp->recno, rec_type, (long) offset, buf);
538  out_cb(dp, rec_type, STR(dp->buf), LEN(dp->buf), offset);
539  } else if (out != 0) {
540  vstring_sprintf(dp->buf, "%d BODY %c %ld\t|%s",
541  dp->recno, rec_type, (long) offset, out);
542  out_cb(dp, rec_type, STR(dp->buf), LEN(dp->buf), offset);
543  myfree(out);
544  }
545  dp->recno += 1;
546 }
547 
548 /* body_end - MIME_STATE end-of-message call-back */
549 
550 static void body_end(void *context)
551 {
552  HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;
553 
554  out_cb(dp, 0, "BODY END", sizeof("BODY END") - 1, 0);
555 }
556 
557 /* err_print - print MIME_STATE errors */
558 
559 static void err_print(void *unused_context, int err_flag,
560  const char *text, ssize_t len)
561 {
562  msg_warn("%s: %.*s", mime_state_error(err_flag),
563  len < 100 ? (int) len : 100, text);
564 }
565 
566 int var_header_limit = 2000;
567 int var_mime_maxdepth = 20;
568 int var_mime_bound_len = 2000;
570 
571 int main(int argc, char **argv)
572 {
573  int rec_type;
574  VSTRING *buf;
575  int err;
576  MIME_STATE *mime_state;
577  HBC_TEST_CONTEXT context;
578  static HBC_CALL_BACKS call_backs[1] = {
579  log_cb, /* logger */
580  out_cb, /* prepend */
581  };
582 
583  /*
584  * Sanity check.
585  */
586  if (argc != 5)
587  msg_fatal("usage: %s header_checks mime_header_checks nested_header_checks body_checks", argv[0]);
588 
589  /*
590  * Initialize.
591  */
592 #define MIME_OPTIONS \
593  (MIME_OPT_REPORT_8BIT_IN_7BIT_BODY \
594  | MIME_OPT_REPORT_8BIT_IN_HEADER \
595  | MIME_OPT_REPORT_ENCODING_DOMAIN \
596  | MIME_OPT_REPORT_TRUNC_HEADER \
597  | MIME_OPT_REPORT_NESTING \
598  | MIME_OPT_DOWNGRADE)
600  buf = vstring_alloc(10);
601  mime_state = mime_state_alloc(MIME_OPTIONS,
602  head_out, head_end,
603  body_out, body_end,
604  err_print,
605  (void *) &context);
606  context.header_checks =
607  hbc_header_checks_create("header_checks", argv[1],
608  "mime_header_checks", argv[2],
609  "nested_header_checks", argv[3],
610  call_backs);
611  context.body_checks =
612  hbc_body_checks_create("body_checks", argv[4], call_backs);
613  context.buf = vstring_alloc(100);
614  context.fp = VSTREAM_OUT;
615  context.queueid = "test-queueID";
616  context.recno = 0;
617 
618  /*
619  * Main loop.
620  */
621  do {
622  rec_type = rec_streamlf_get(VSTREAM_IN, buf, REC_LEN);
623  VSTRING_TERMINATE(buf);
624  err = mime_state_update(mime_state, rec_type, STR(buf), LEN(buf));
626  } while (rec_type > 0);
627 
628  /*
629  * Error reporting.
630  */
631  if (err & MIME_ERR_TRUNC_HEADER)
632  msg_warn("message header length exceeds safety limit");
633  if (err & MIME_ERR_NESTING)
634  msg_warn("MIME nesting exceeds safety limit");
635  if (err & MIME_ERR_8BIT_IN_HEADER)
636  msg_warn("improper use of 8-bit data in message header");
637  if (err & MIME_ERR_8BIT_IN_7BIT_BODY)
638  msg_warn("improper use of 8-bit data in message body");
639  if (err & MIME_ERR_ENCODING_DOMAIN)
640  msg_warn("improper message/* or multipart/* encoding domain");
641 
642  /*
643  * Cleanup.
644  */
645  if (context.header_checks)
646  hbc_header_checks_free(context.header_checks);
647  if (context.body_checks)
648  hbc_body_checks_free(context.body_checks);
649  vstring_free(context.buf);
650  mime_state_free(mime_state);
651  vstring_free(buf);
652  exit(0);
653 }
654 
655 #endif
int msg_verbose
Definition: msg.c:177
void myfree(void *ptr)
Definition: mymalloc.c:207
#define HBC_CHECKS_STAT_UNKNOWN
char * mystrdup(const char *str)
Definition: mymalloc.c:225
MIME_STATE * mime_state_alloc(int flags, MIME_STATE_HEAD_OUT head_out, MIME_STATE_ANY_END head_end, MIME_STATE_BODY_OUT body_out, MIME_STATE_ANY_END body_end, MIME_STATE_ERR_PRINT err_print, void *context)
Definition: mime_state.c:493
#define HBC_CHECKS_STAT_IGNORE
#define MIME_ERR_NESTING
Definition: mime_state.h:66
#define VSTREAM_OUT
Definition: vstream.h:67
void(* prepend)(void *, int, const char *, ssize_t, off_t)
#define MIME_ERR_ENCODING_DOMAIN
Definition: mime_state.h:70
int main(int argc, char **argv)
Definition: anvil.c:1010
#define MIME_HDR_MULTIPART
Definition: mime_state.h:81
int var_mime_bound_len
Definition: mail_params.c:319
char * var_drop_hdrs
Definition: mail_params.c:348
#define MIME_HDR_FIRST
#define DEF_DROP_HDRS
Definition: mail_params.h:391
#define VSTREAM_IN
Definition: vstream.h:66
int var_mime_maxdepth
Definition: mail_params.c:318
char hbc_checks_error
#define MIME_ERR_8BIT_IN_HEADER
Definition: mime_state.h:68
int rec_streamlf_get(VSTREAM *stream, VSTRING *buf, int maxlen)
Definition: rec_streamlf.c:76
#define STR(x)
HBC_MAP_INFO map_info[1]
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define HBC_CTXT_HEADER
const char hbc_checks_unknown
#define is_header(str)
Definition: is_header.h:17
int mime_state_update(MIME_STATE *state, int rec_type, const char *text, ssize_t len)
Definition: mime_state.c:755
void(* logger)(void *, const char *, const char *, const char *, const char *)
MIME_STATE * mime_state_free(MIME_STATE *state)
Definition: mime_state.c:530
#define MIME_ERR_TRUNC_HEADER
Definition: mime_state.h:67
char *(* extend)(void *, const char *, ssize_t, const char *, const char *, const char *, ssize_t, off_t)
#define STREQUAL(x, y, l)
#define MIME_HDR_PRIMARY
Definition: mime_state.h:80
void msg_warn(const char *fmt,...)
Definition: msg.c:215
char * hbc_header_checks(void *context, HBC_CHECKS *hbc, int header_class, const HEADER_OPTS *hdr_opts, VSTRING *header, off_t offset)
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define HBC_CTXT_BODY
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
#define MIME_ERR_8BIT_IN_7BIT_BODY
Definition: mime_state.h:69
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define HBC_INIT(hbc, index, name, value)
MAPS * maps_free(MAPS *maps)
Definition: maps.c:213
const char * mime_state_error(int error_code)
Definition: mime_state.c:1149
#define hbc_body_checks_free(hbc)
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
int error
Definition: maps.h:25
#define vstream_fwrite(v, b, n)
Definition: vstream.h:105
#define LEN(x)
HBC_CHECKS * hbc_header_checks_create(const char *header_checks_name, const char *header_checks_value, const char *mime_header_checks_name, const char *mime_header_checks_value, const char *nested_header_checks_name, const char *nested_header_checks_value, HBC_CALL_BACKS *call_backs)
void _hbc_checks_free(HBC_CHECKS *hbc, ssize_t len)
int var_header_limit
Definition: mail_params.c:320
#define HBC_CHECKS_STAT_ERROR
HBC_CHECKS * hbc_body_checks_create(const char *body_checks_name, const char *body_checks_value, HBC_CALL_BACKS *call_backs)
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
HBC_CALL_BACKS * call_backs
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
#define MIME_HDR_NESTED
Definition: mime_state.h:82
#define REC_TYPE_NORM
Definition: rec_type.h:59
#define ISSPACE(c)
Definition: sys_defs.h:1753
#define VSTREAM_PUTC(ch, vp)
Definition: vstream.h:107
#define hbc_header_checks_free(hbc)
#define MIME_HDR_LAST
char * hbc_body_checks(void *context, HBC_CHECKS *hbc, const char *line, ssize_t len, off_t offset)
const char * maps_find(MAPS *maps, const char *name, int flags)
Definition: maps.c:162
#define HDR_OPT_MIME
Definition: header_opts.h:67
#define basename
Definition: stringops.h:36
#define HBC_BODY_INDEX
const char * map_class
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
#define HBC_HEADER_INDEX(class)
void msg_info(const char *fmt,...)
Definition: msg.c:199