/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "strescape.h"
#include "rfc822-parser.h"
/*
atext = ALPHA / DIGIT / ; Any character except controls,
"!" / "#" / ; SP, and specials.
"$" / "%" / ; Used for atoms
"&" / "'" /
"*" / "+" /
"-" / "/" /
"=" / "?" /
"^" / "_" /
"`" / "{" /
"|" / "}" /
"~"
MIME:
token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
or tspecials>
tspecials := "(" / ")" / "<" / ">" / "@" /
"," / ";" / ":" / "\" / <">
"/" / "[" / "]" / "?" / "="
So token is same as dot-atom, except stops also at '/', '?' and '='.
*/
/* atext chars are marked with 1, alpha and digits with 2,
atext-but-mime-tspecials with 4 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 4, /* 32-47 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 4, 0, 4, /* 48-63 */
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 64-79 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1, /* 80-95 */
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 96-111 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, /* 112-127 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
};
{
}
{
const unsigned char *start;
case '(':
level++;
break;
case ')':
if (--level == 0) {
}
}
break;
case '\\':
}
return -1;
break;
}
}
/* missing ')' */
return -1;
}
{
continue;
}
break;
if (rfc822_skip_comment(ctx) < 0)
return -1;
}
}
{
const unsigned char *start;
/*
atom = [CFWS] 1*atext [CFWS]
atext =
; Any character except controls, SP, and specials.
*/
return -1;
continue;
return rfc822_skip_lwsp(ctx);
}
return 0;
}
{
const unsigned char *start;
int ret;
/*
dot-atom = [CFWS] dot-atom-text [CFWS]
dot-atom-text = 1*atext *("." 1*atext)
atext =
; Any character except controls, SP, and specials.
For RFC-822 compatibility allow LWSP around '.'
*/
return -1;
continue;
}
return ret;
return 1;
return ret;
}
return 0;
}
{
const unsigned char *start;
continue;
return rfc822_skip_lwsp(ctx);
}
return 0;
}
{
const unsigned char *start;
case '"':
return rfc822_skip_lwsp(ctx);
case '\n':
/* folding whitespace, remove the (CR)LF */
len--;
break;
case '\\':
return -1;
break;
}
}
/* missing '"' */
return -1;
}
static int
{
const unsigned char *start;
/*
atom = [CFWS] 1*atext [CFWS]
atext =
; Any character except controls, SP, and specials.
The difference between this function and rfc822_parse_dot_atom()
is that this doesn't just silently skip over all the whitespace.
*/
continue;
return rfc822_skip_lwsp(ctx);
}
return 0;
}
{
int ret;
/*
phrase = 1*word / obs-phrase
word = atom / quoted-string
obs-phrase = word *(word / "." / CFWS)
*/
return 0;
return -1;
for (;;) {
else
if (ret <= 0)
return ret;
break;
}
return rfc822_skip_lwsp(ctx);
}
static int
{
const unsigned char *start;
/*
domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
dcontent = dtext / quoted-pair
dtext = NO-WS-CTL / ; Non white space controls
%d33-90 / ; The rest of the US-ASCII
%d94-126 ; characters not including "[",
; "]", or "\"
*/
break;
return rfc822_skip_lwsp(ctx);
}
}
/* missing ']' */
return -1;
}
{
/*
domain = dot-atom / domain-literal / obs-domain
domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
obs-domain = atom *("." atom)
*/
if (rfc822_skip_lwsp(ctx) <= 0)
return -1;
else
}
{
if (rfc822_skip_lwsp(ctx) <= 0)
return -1;
/* get main type */
return -1;
/* skip over "/" */
return -1;
if (rfc822_skip_lwsp(ctx) <= 0)
return -1;
/* get subtype */
}
{
int ret;
/* .. := *(";" parameter)
parameter := attribute "=" value
attribute := token
value := token / quoted-string
*/
return 0;
return -1;
if (rfc822_skip_lwsp(ctx) <= 0)
return -1;
return -1;
return -1;
/* broken / no value */
/* workaround for broken input:
name==?utf-8?b?...?= */
}
} else {
}
}