]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add parsers for SMTP address in ragel
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 23 Apr 2016 10:33:18 +0000 (11:33 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 23 Apr 2016 13:45:27 +0000 (14:45 +0100)
src/ragel/smtp_addr_parser.rl [new file with mode: 0644]
src/ragel/smtp_address.rl [new file with mode: 0644]
src/ragel/smtp_ip.rl [new file with mode: 0644]

diff --git a/src/ragel/smtp_addr_parser.rl b/src/ragel/smtp_addr_parser.rl
new file mode 100644 (file)
index 0000000..5d08d7d
--- /dev/null
@@ -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 (file)
index 0000000..c0333ac
--- /dev/null
@@ -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 (file)
index 0000000..b6b0080
--- /dev/null
@@ -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