From: Vsevolod Stakhov Date: Sat, 23 Apr 2016 10:33:18 +0000 (+0100) Subject: [Feature] Add parsers for SMTP address in ragel X-Git-Tag: 1.3.0~663 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6832271dbc2771c7e3b2512fef2dcc054ab55c49;p=rspamd.git [Feature] Add parsers for SMTP address in ragel --- diff --git a/src/ragel/smtp_addr_parser.rl b/src/ragel/smtp_addr_parser.rl new file mode 100644 index 000000000..5d08d7d4f --- /dev/null +++ b/src/ragel/smtp_addr_parser.rl @@ -0,0 +1,77 @@ +%%{ + + machine smtp_addr_parser; + + action User_start { + addr->user = p; + addr->addr = p; + } + + action User_end { + if (addr->user) { + addr->user_len = p - addr->user; + } + } + + action Domain_start { + addr->domain = p; + } + + action Domain_end { + if (addr->domain) { + addr->domain_len = p - addr->domain; + } + } + + action Domain_addr_start { + addr->domain = p; + addr->flags |= RSPAMD_EMAIL_ADDR_IP; + } + + action Domain_addr_end { + if (addr->domain) { + addr->domain_len = p - addr->domain; + } + } + + action Quoted_addr { + addr->flags |= RSPAMD_EMAIL_ADDR_QUOTED; + } + + action Empty_addr { + addr->flags |= RSPAMD_EMAIL_ADDR_EMPTY; + addr->addr = ""; + } + + action Valid_addr { + addr->flags |= RSPAMD_EMAIL_ADDR_VALID; + } + + action Angled_addr { + addr->flags |= RSPAMD_EMAIL_ADDR_BRACED; + } + + include smtp_address "smtp_address.rl"; + + main := SMTPAddr; +}%% + +%% write data; + +static int +rspamd_smtp_addr_parse (const char *data, size_t len, struct rspamd_email_address *addr) +{ + const char *p = data, *pe = data + len, *eof; + int cs; + + g_assert (addr != NULL); + memset (addr, 0, sizeof (*addr)); + addr->raw = data; + addr->raw_len = len; + eof = pe; + + %% write init; + %% write exec; + + return cs; +} diff --git a/src/ragel/smtp_address.rl b/src/ragel/smtp_address.rl new file mode 100644 index 000000000..c0333acd9 --- /dev/null +++ b/src/ragel/smtp_address.rl @@ -0,0 +1,50 @@ +%%{ + machine smtp_address; + + include smtp_ip "smtp_ip.rl"; + + # SMTP address spec + # Obtained from: https://tools.ietf.org/html/rfc5321#section-4.1.2 + + LF = "\n"; + CR = "\r"; + CRLF = "\r\n"; + DQUOTE = '"'; + + atext = alpha | digit | "!" | "#" | "$" | "%" | "&" | + "'" | "*" | "+" | "_" | "/" | "=" | "?" | "^" | + "_" | "`" | "{" | "|" | "}" | "~"; + + dcontent = 33..90 | 94..126; + Let_dig = alpha | digit; + Ldh_str = ( alpha | digit | "_" )* Let_dig; + + quoted_pairSMTP = "\\" 32..126; + qtextSMTP = 32..33 | 35..91 | 93..126; + Atom = atext+; + Dot_string = Atom ("." Atom)*; + + QcontentSMTP = qtextSMTP | quoted_pairSMTP; + Quoted_string = ( DQUOTE QcontentSMTP* DQUOTE ) %Quoted_addr; + Local_part = ( Dot_string | Quoted_string ) >User_start %User_end; + String = Atom | Quoted_string; + + Standardized_tag = Ldh_str; + General_address_literal = Standardized_tag ":" dcontent+; + address_literal = "[" ( IPv4_address_literal | + IPv6_address_literal | + General_address_literal ) >Domain_addr_start %Domain_addr_end "]"; + + + sub_domain = Let_dig Ldh_str?; + Domain = sub_domain ("." sub_domain)*; + Atdomain = "@" Domain; + Adl = Atdomain ( "," Atdomain )*; + + Mailbox = Local_part "@" (address_literal | Domain >Domain_start %Domain_end); + UnangledPath = ( Adl ":" )? Mailbox; + AngledPath = "<" UnangledPath ">"; + Path = AngledPath %Angled_addr | UnangledPath; + SMTPAddr = space* (Path | "<>" %Empty_addr ) %Valid_addr space*; + +}%% diff --git a/src/ragel/smtp_ip.rl b/src/ragel/smtp_ip.rl new file mode 100644 index 000000000..b6b0080f3 --- /dev/null +++ b/src/ragel/smtp_ip.rl @@ -0,0 +1,19 @@ +%%{ + machine smtp_ip; + + # Parses IPv4/IPv6 address + # Source: https://tools.ietf.org/html/rfc5321#section-4.1.3 + + Snum = digit{1,3}; + IPv4_address_literal = Snum ("." Snum){3}; + IPv6_hex = xdigit{1,4}; + IPv6_full = IPv6_hex (":" IPv6_hex){7}; + IPv6_comp = (IPv6_hex (":" IPv6_hex){0,5})? "::" + (IPv6_hex (":" IPv6_hex){0,5})?; + IPv6v4_full = IPv6_hex (":" IPv6_hex){5} ":" IPv4_address_literal; + IPv6v4_comp = (IPv6_hex (":" IPv6_hex){0,3})? "::" + (IPv6_hex (":" IPv6_hex){0,3} ":")? + IPv4_address_literal; + IPv6_addr = IPv6_full | IPv6_comp | IPv6v4_full | IPv6v4_comp; + IPv6_address_literal = "IPv6:" IPv6_addr; +}%% \ No newline at end of file