/*++ /* NAME /* mime_state 3 /* SUMMARY /* MIME parser state machine /* SYNOPSIS /* #include <mime_state.h> /* /* MIME_STATE *mime_state_alloc(flags, head_out, head_end, /* body_out, body_end, /* err_print, context) /* int flags; /* void (*head_out)(void *ptr, int header_class, /* const HEADER_OPTS *header_info, /* VSTRING *buf, off_t offset); /* void (*head_end)(void *ptr); /* void (*body_out)(void *ptr, int rec_type, /* const char *buf, ssize_t len, /* off_t offset); /* void (*body_end)(void *ptr); /* void (*err_print)(void *ptr, int err_flag, const char *text) /* void *context; /* /* int mime_state_update(state, rec_type, buf, len) /* MIME_STATE *state; /* int rec_type; /* const char *buf; /* ssize_t len; /* /* int mime_state_status(state) /* MIME_STATE *state; /* /* MIME_STATE *mime_state_free(state) /* MIME_STATE *state; /* /* const char *mime_state_error(error_code) /* int error_code; /* /* typedef struct { /* .in +4
/* const int code; /* internal error code */ /* const char *dsn; /* RFC 3463 */ /* const char *text; /* descriptive text */ /* .in -4 /* } MIME_STATE_DETAIL; /* /* const MIME_STATE_DETAIL *mime_state_detail(error_code) /* int error_code; /* DESCRIPTION /* This module implements a one-pass MIME processor with optional /* 8-bit to quoted-printable conversion. /* /* In order to fend off denial of service attacks, message headers /* are truncated at or above var_header_limit bytes, message boundary /* strings are truncated at var_mime_bound_len bytes, and the multipart /* nesting level is limited to var_mime_maxdepth levels. /* /* mime_state_alloc() creates a MIME state machine. The machine /* is delivered in its initial state, expecting content type /* text/plain, 7-bit data. /* /* mime_state_update() updates the MIME state machine according /* to the input record type and the record content. /* The result value is the bit-wise OR of zero or more of the following: /* .IP MIME_ERR_TRUNC_HEADER /* A message header was longer than var_header_limit bytes. /* .IP MIME_ERR_NESTING /* The MIME structure was nested more than var_mime_maxdepth levels. /* .IP MIME_ERR_8BIT_IN_HEADER /* A message header contains 8-bit data. This is always illegal. /* .IP MIME_ERR_8BIT_IN_7BIT_BODY /* A MIME header specifies (or defaults to) 7-bit content, but the /* corresponding message body or body parts contain 8-bit content. /* .IP MIME_ERR_ENCODING_DOMAIN /* An entity of type "message" or "multipart" specifies the wrong /* content transfer encoding domain, or specifies a transformation /* (quoted-printable, base64) instead of a domain (7bit, 8bit, /* or binary). /* .IP MIME_ERR_NON_EMPTY_EOH /* The primary message header was terminated with a non-empty line. /* .PP /* mime_state_status() reports the same result as /* mime_state_update(), but without changing state. /* /* mime_state_free() releases storage for a MIME state machine, /* and conveniently returns a null pointer. /* /* mime_state_error() returns a string representation for the /* specified error code. When multiple errors are specified it /* reports what it deems the most serious one. /* /* mime_state_detail() returns a table entry with error /* information for the specified error code. When multiple /* errors are specified it reports what it deems the most /* serious one. /* /* Arguments: /* .IP body_out /* The output routine for body lines. It receives unmodified input /* records, or the result of 8-bit -> 7-bit conversion. /* .IP body_end /* A null pointer, or a pointer to a routine that is called after /* the last input record is processed. /* .IP buf /* Buffer with the content of a logical or physical message record. /* .IP context /* Caller context that is passed on to the head_out and body_out /* routines. /* .IP enc_type /* The content encoding: MIME_ENC_7BIT or MIME_ENC_8BIT. /* .IP err_print /* Null pointer, or pointer to a function that is called with /* arguments: the application context, the error type, and the /* offending input. Only one instance per error type is reported. /* .IP flags /* Special processing options. Specify the bit-wise OR of zero or /* more of the following: /* .RS /* .IP MIME_OPT_DISABLE_MIME /* Pay no attention to Content-* message headers, and switch to /* message body state at the end of the primary message headers. /* .IP MIME_OPT_REPORT_TRUNC_HEADER /* Report errors that set the MIME_ERR_TRUNC_HEADER error flag /* (see above). /* .IP MIME_OPT_REPORT_8BIT_IN_HEADER /* Report errors that set the MIME_ERR_8BIT_IN_HEADER error /* flag (see above). This rarely stops legitimate mail. /* .IP MIME_OPT_REPORT_8BIT_IN_7BIT_BODY /* Report errors that set the MIME_ERR_8BIT_IN_7BIT_BODY error /* flag (see above). This currently breaks Majordomo mail that is /* forwarded for approval, because Majordomo does not propagate /* MIME type information from the enclosed message to the message /* headers of the request for approval. /* .IP MIME_OPT_REPORT_ENCODING_DOMAIN /* Report errors that set the MIME_ERR_ENCODING_DOMAIN error /* flag (see above). /* .IP MIME_OPT_REPORT_NESTING /* Report errors that set the MIME_ERR_NESTING error flag /* (see above). /* .IP MIME_OPT_REPORT_NON_EMPTY_EOH /* Report errors that terminate the primary message header with a /* non-empty line. /* .IP MIME_OPT_DOWNGRADE /* Transform content that claims to be 8-bit into quoted-printable. /* Where appropriate, update Content-Transfer-Encoding: message /* headers. /* .RE /* .sp /* For convenience, MIME_OPT_NONE requests no special processing. /* .IP header_class /* Specifies where a message header is located. /* .RS /* .IP MIME_HDR_PRIMARY /* In the primary message header section. /* .IP MIME_HDR_MULTIPART /* In the header section after a multipart boundary string. /* .IP MIME_HDR_NESTED /* At the start of a nested (e.g., message/rfc822) message. /* .RE /* .sp /* For convenience, the macros MIME_HDR_FIRST and MIME_HDR_LAST /* specify the range of MIME_HDR_MUMBLE macros. /* .sp /* To find out if something is a MIME header at the beginning /* of an RFC 822 message or an attached message, look at the /* header_info argument. /* .IP header_info /* Null pointer or information about the message header, see /* header_opts(3). /* .IP head_out /* The output routine that is invoked for outputting a message header. /* A multi-line header is passed as one chunk of text with embedded /* newlines. /* It is the responsibility of the output routine to break the text /* at embedded newlines, and to break up long text between newlines /* into multiple output records. /* Note: an output routine is explicitly allowed to modify the text. /* .IP head_end /* A null pointer, or a pointer to a routine that is called after /* the last message header in the first header block is processed. /* .IP len /* Length of non-VSTRING input buffer. /* .IP offset /* The offset in bytes from the start of the current block of message /* headers or body lines. Line boundaries are counted as one byte. /* .IP rec_type /* The input record type as defined in rec_type(3h). State is /* updated for text records (REC_TYPE_NORM or REC_TYPE_CONT). /* Some input records are stored internally in order to reconstruct /* multi-line input. Upon receipt of any non-text record type, all /* stored input is flushed and the state is set to "body". /* .IP state /* MIME parser state created with mime_state_alloc(). /* BUGS /* NOTE: when the end of headers is reached, mime_state_update() /* may execute up to three call-backs before returning to the /* caller: head_out(), head_end(), and body_out() or body_end(). /* As long as call-backs return no result, it is up to the /* call-back routines to check if a previous call-back experienced /* an error. /* /* Different mail user agents treat malformed message boundary /* strings in different ways. The Postfix MIME processor cannot /* be bug-compatible with everything. /* /* This module will not glue together multipart boundary strings that /* span multiple input records. /* /* This module will not glue together RFC 2231 formatted (boundary) /* parameter values. RFC 2231 claims compatibility with existing /* MIME processors. Splitting boundary strings is not backwards /* compatible. /* /* The "8-bit data inside 7-bit body" test is myopic. It is not aware /* of any enclosing (message or multipart) encoding information. /* /* If the input ends in data other than a hard line break, this module /* will add a hard line break of its own. No line break is added to /* empty input. /* /* This code recognizes the obsolete form "headername :" but will /* normalize it to the canonical form "headername:". Leaving the /* obsolete form alone would cause too much trouble with existing code /* that expects only the normalized form. /* SEE ALSO /* msg(3) diagnostics interface /* header_opts(3) header information lookup /* RFC 822 (ARPA Internet Text Messages) /* RFC 2045 (MIME: Format of internet message bodies) /* RFC 2046 (MIME: Media types) /* DIAGNOSTICS /* Fatal errors: memory allocation problem. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* HISTORY /* .ad /* .fi /* This code was implemented from scratch after reading the RFC /* documents. This was a relatively straightforward effort with /* few if any surprises. Victor Duchovni of Morgan Stanley shared /* his experiences with ambiguities in real-life MIME implementations. /* Liviu Daia of the Romanian Academy shared his insights in some /* of the darker corners. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA
/*--*/
/* *Mimeparserstate.
*/ #define MIME_MAX_TOKEN 3/* tokens per attribute */
struct MIME_STATE {
/* *Volatilemembers.
*/ int curr_state; /* header/body state */ int curr_ctype; /* last or default content type */ int curr_stype; /* last or default content subtype */ int curr_encoding; /* last or default content encoding */ int curr_domain; /* last or default encoding unit */
VSTRING *output_buffer; /* headers, quoted-printable body */ int prev_rec_type; /* previous input record type */ int nesting_level; /* safety */
MIME_STACK *stack; /* for composite types */
HEADER_TOKEN token[MIME_MAX_TOKEN]; /* header token array */
VSTRING *token_buffer; /* header parser scratch buffer */ int err_flags; /* processing errors */
off_t head_offset; /* offset in header block */
off_t body_offset; /* offset in body block */
/* *Staticmembers.
*/ int static_flags; /* static processing options */
MIME_STATE_HEAD_OUT head_out; /* header output routine */
MIME_STATE_ANY_END head_end; /* end of primary header routine */
MIME_STATE_BODY_OUT body_out; /* body output routine */
MIME_STATE_ANY_END body_end; /* end of body output routine */
MIME_STATE_ERR_PRINT err_print; /* error report */ void *app_context; /* application context */
};
#define SET_CURR_STATE(ptr, state) do { \
(ptr)->curr_state = (state); \ if ((state) == MIME_STATE_BODY) \
(ptr)->body_offset = 0; \ else \
(ptr)->head_offset = 0; \
} while (0)
/* *MIMEencodingsanddomains.Weintentionallyusethesamecodesfor *encodingsanddomains,sothatwecaneasilyfindoutwhetheracontent *transferencodingheaderspecifiesadomainorwhetheritspecifies *domain+encoding,whichisillegalformultipart/anyandmessage/any.
*/ typedefstruct MIME_ENCODING { constchar *name; /* external representation */ int encoding; /* internal representation */ int domain; /* subset of encoding */
} MIME_ENCODING;
#define MIME_ENC_QP 1/* encoding + domain */ #define MIME_ENC_BASE64 2/* encoding + domain */ /* These are defined in mime_state.h as part of the external interface. */ #ifndef MIME_ENC_7BIT #define MIME_ENC_7BIT 7/* domain only */ #define MIME_ENC_8BIT 8/* domain only */ #define MIME_ENC_BINARY 9/* domain only */ #endif
if (error_code == 0)
msg_panic("mime_state_error: there is no error"); for (mp = mime_err_detail; mp->code; mp++) if (mp->code & error_code) return (mp->text);
msg_panic("mime_state_error: unknown error code %d", error_code);
}
/* mime_state_detail - error code to table entry with assorted data */
if (error_code == 0)
msg_panic("mime_state_detail: there is no error"); for (mp = mime_err_detail; mp->code; mp++) if (mp->code & error_code) return (mp);
msg_panic("mime_state_detail: unknown error code %d", error_code);
}
/* *Mainloop.
*/ do {
rec_type = rec_streamlf_get(VSTREAM_IN, buf, REC_LEN);
VSTRING_TERMINATE(buf);
err = mime_state_update(state, last = rec_type, STR(buf), LEN(buf));
vstream_fflush(VSTREAM_OUT);
} while (rec_type > 0);
/* *Errorreporting.
*/ if (err & MIME_ERR_TRUNC_HEADER)
msg_warn("message header length exceeds safety limit"); if (err & MIME_ERR_NESTING)
msg_warn("MIME nesting exceeds safety limit"); if (err & MIME_ERR_8BIT_IN_HEADER)
msg_warn("improper use of 8-bit data in message header"); if (err & MIME_ERR_8BIT_IN_7BIT_BODY)
msg_warn("improper use of 8-bit data in message body"); if (err & MIME_ERR_ENCODING_DOMAIN)
msg_warn("improper message/* or multipart/* encoding domain"); if (err & MIME_ERR_NON_EMPTY_EOH)
msg_warn("non-empty end-of-header");
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.42Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.