bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen atext = ALPHA / DIGIT / ; Any character except controls,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen "!" / "#" / ; SP, and specials.
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen "$" / "%" / ; Used for atoms
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen or tspecials>
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen tspecials := "(" / ")" / "<" / ">" / "@" /
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen "," / ";" / ":" / "\" / <">
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen "/" / "[" / "]" / "?" / "="
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen So token is same as dot-atom, except stops also at '/', '?' and '='.
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen/* atext chars are marked with 1, alpha and digits with 2,
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen atext-but-mime-tspecials with 4 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 4, /* 32-47 */
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 4, 0, 4, /* 48-63 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 64-79 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1, /* 80-95 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 96-111 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, /* 112-127 */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenvoid rfc822_parser_init(struct rfc822_parser_context *ctx,
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_skip_comment(struct rfc822_parser_context *ctx)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen if (--level == 0) {
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen /* missing ')' */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_skip_lwsp(struct rfc822_parser_context *ctx)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen if (*ctx->data == ' ' || *ctx->data == '\t' ||
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_parse_atom(struct rfc822_parser_context *ctx, string_t *str)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen atom = [CFWS] 1*atext [CFWS]
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen ; Any character except controls, SP, and specials.
f4b1d7e52e983ba3063584c8b0ef577d6946331cTimo Sirainen if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data))
f4b1d7e52e983ba3063584c8b0ef577d6946331cTimo Sirainen for (start = ctx->data++; ctx->data != ctx->end; ctx->data++) {
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_parse_dot_atom(struct rfc822_parser_context *ctx, string_t *str)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen dot-atom = [CFWS] dot-atom-text [CFWS]
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen dot-atom-text = 1*atext *("." 1*atext)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen ; Any character except controls, SP, and specials.
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen For RFC-822 compatibility allow LWSP around '.'
f4b1d7e52e983ba3063584c8b0ef577d6946331cTimo Sirainen if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data))
f53915d18c75bb167cf4f86f7325baae7ea12ce9Timo Sirainen for (start = ctx->data++; ctx->data != ctx->end; ) {
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainenint rfc822_parse_mime_token(struct rfc822_parser_context *ctx, string_t *str)
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
2de709376eddc50ec5fa470358bb57cf0a87bb1fTimo Sirainen if (IS_ATEXT_NON_TSPECIAL(*ctx->data) || *ctx->data == '.')
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_parse_quoted_string(struct rfc822_parser_context *ctx, string_t *str)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
0452398b245ac9643f6b47dfc450dc5bf7da51d0Timo Sirainen /* folding whitespace, remove the (CR)LF */
4c0c72a8b6791910bbc970eff0c75a91bdc38eb3Timo Sirainen str_append_n(str, start, ctx->data - start - 1);
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen /* missing '"' */
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainenrfc822_parse_atom_or_dot(struct rfc822_parser_context *ctx, string_t *str)
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen atom = [CFWS] 1*atext [CFWS]
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen ; Any character except controls, SP, and specials.
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen The difference between this function and rfc822_parse_dot_atom()
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen is that this doesn't just silently skip over all the whitespace.
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen if (IS_ATEXT(*ctx->data) || *ctx->data == '.')
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_parse_phrase(struct rfc822_parser_context *ctx, string_t *str)
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen phrase = 1*word / obs-phrase
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen word = atom / quoted-string
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen obs-phrase = word *(word / "." / CFWS)
d290217adc3d17ba82fd81f164da3c2b88489700Timo Sirainen if (!IS_ATEXT(*ctx->data) && *ctx->data != '"'
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenrfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen dcontent = dtext / quoted-pair
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen dtext = NO-WS-CTL / ; Non white space controls
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen %d33-90 / ; The rest of the US-ASCII
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen %d94-126 ; characters not including "[",
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen ; "]", or "\"
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen /* missing ']' */
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainenint rfc822_parse_domain(struct rfc822_parser_context *ctx, string_t *str)
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen domain = dot-atom / domain-literal / obs-domain
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
a24665de9d5c773115a5918e60ed587aafe67d5cTimo Sirainen obs-domain = atom *("." atom)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainenint rfc822_parse_content_type(struct rfc822_parser_context *ctx, string_t *str)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen /* get main type */
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen /* skip over "/" */
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen /* get subtype */
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainenint rfc822_parse_content_param(struct rfc822_parser_context *ctx,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen /* .. := *(";" parameter)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen parameter := attribute "=" value
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen attribute := token
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen value := token / quoted-string
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen /* broken / no value */
a37b4f6dfcf753c0071ff0480b9510dce0d6f4aeTimo Sirainen } else if (ctx->data != ctx->end && *ctx->data == '=') {
a37b4f6dfcf753c0071ff0480b9510dce0d6f4aeTimo Sirainen /* workaround for broken input:
a37b4f6dfcf753c0071ff0480b9510dce0d6f4aeTimo Sirainen name==?utf-8?b?...?= */
a37b4f6dfcf753c0071ff0480b9510dce0d6f4aeTimo Sirainen while (ctx->data != ctx->end && *ctx->data != ';' &&