diff options
Diffstat (limited to 'src/ragel/smtp_date.rl')
-rw-r--r-- | src/ragel/smtp_date.rl | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/ragel/smtp_date.rl b/src/ragel/smtp_date.rl new file mode 100644 index 0000000..125ae8a --- /dev/null +++ b/src/ragel/smtp_date.rl @@ -0,0 +1,230 @@ +%%{ + machine smtp_date; + + # SMTP date spec + # Obtained from: http://tools.ietf.org/html/rfc5322#section_3.3 + + + action Day_Start { + tmp = p; + } + action Day_End { + if (p > tmp) { + gulong n; + if (rspamd_strtoul (tmp, p - tmp, &n)) { + if (n > 0 && n <= 31) { + tm.tm_mday = n; + } + else { + fbreak; + } + } + } + } + action Month_End { + + } + action Year_Start { + tmp = p; + } + action Year_End { + if (p > tmp) { + gulong n; + if (rspamd_strtoul (tmp, p - tmp, &n)) { + if (n < 1000) { + if (n < 50) { + tm.tm_year = n - 1900 + 2000; + } + else { + tm.tm_year = n; + } + } + else { + tm.tm_year = n - 1900; + } + } + } + } + action Hour_Start { + tmp = p; + } + action Hour_End { + if (p > tmp) { + gulong n; + if (rspamd_strtoul (tmp, p - tmp, &n)) { + if (n < 24) { + tm.tm_hour = n; + } + else { + fbreak; + } + } + } + else { + fbreak; + } + } + action Minute_Start { + tmp = p; + } + action Minute_End { + if (p > tmp) { + gulong n; + if (rspamd_strtoul (tmp, p - tmp, &n)) { + if (n < 60) { + tm.tm_min = n; + } + else { + fbreak; + } + } + } + else { + fbreak; + } + } + action Second_Start { + tmp = p; + } + action Second_End { + if (p > tmp) { + gulong n; + if (rspamd_strtoul (tmp, p - tmp, &n)) { + if (n <= 60) { /* Leap second */ + tm.tm_sec = n; + } + else { + fbreak; + } + } + } + else { + fbreak; + } + } + action TZ_Sign { + tmp = p; + } + action TZ_Offset_Start { + + } + action TZ_Offset_End { + if (p > tmp) { + rspamd_strtoul (tmp, p - tmp, (gulong *)&tz); + + if (*(tmp - 1) == '-') { + tz = -(tz); + } + } + } + action Obs_Zone_End { + } + action DT_End { + } + + # Specific actions + # Months + action Month_Jan { + tm.tm_mon = 0; + } + action Month_Feb { + tm.tm_mon = 1; + } + action Month_Mar { + tm.tm_mon = 2; + } + action Month_Apr { + tm.tm_mon = 3; + } + action Month_May { + tm.tm_mon = 4; + } + action Month_Jun { + tm.tm_mon = 5; + } + action Month_Jul { + tm.tm_mon = 6; + } + action Month_Aug { + tm.tm_mon = 7; + } + action Month_Sep { + tm.tm_mon = 8; + } + action Month_Oct { + tm.tm_mon = 9; + } + action Month_Nov { + tm.tm_mon = 10; + } + action Month_Dec { + tm.tm_mon = 11; + } + # Obsoleted timezones + action TZ_UT { + tz = 0; + } + action TZ_GMT { + tz = 0; + } + action TZ_EST { + tz = -500; + } + action TZ_EDT { + tz = -400; + } + action TZ_CST { + tz = -600; + } + action TZ_CDT { + tz = -500; + } + action TZ_MST { + tz = -700; + } + action TZ_MDT { + tz = -600; + } + action TZ_PST { + tz = -800; + } + action TZ_PDT { + tz = -700; + } + prepush { + if (top >= st_storage.size) { + st_storage.size = (top + 1) * 2; + st_storage.data = realloc (st_storage.data, st_storage.size * sizeof (int)); + g_assert (st_storage.data != NULL); + stack = st_storage.data; + } + } + ccontent = ctext | FWS | '(' @{ fcall balanced_ccontent; }; + balanced_ccontent := ccontent* ')' @{ fret; }; + comment = "(" (FWS? ccontent)* FWS? ")"; + CFWS = ((FWS? comment)+ FWS?) | FWS; + digit_2 = digit{2}; + digit_4 = digit{4}; + day_name = "Mon" | "Tue" | "Wed" | "Thu" | + "Fri" | "Sat" | "Sun"; + day_of_week = FWS? day_name; + day = FWS? digit{1,2} >Day_Start %Day_End FWS; + month = "Jan" %Month_Jan | "Feb" %Month_Feb | "Mar" %Month_Mar | "Apr" %Month_Apr | + "May" %Month_May | "Jun" %Month_Jun | "Jul" %Month_Jul | "Aug" %Month_Aug | + "Sep" %Month_Sep | "Oct" %Month_Oct | "Nov" %Month_Nov | "Dec" %Month_Dec; + year = FWS digit{2,4} >Year_Start %Year_End FWS; + date = day month %Month_End year; + hour = digit_2; + minute = digit_2; + second = digit_2; + time_of_day = hour >Hour_Start %Hour_End ":" minute >Minute_Start %Minute_End (":" second >Second_Start %Second_End )?; + zone = ("+" | "-") %TZ_Sign digit_4 >TZ_Offset_Start %TZ_Offset_End; + obs_zone = "UT" %TZ_UT | "GMT" %TZ_GMT | + "EST" %TZ_EST | "EDT" %TZ_EDT | + "CST" %TZ_CST | "CDT" %TZ_CDT | + "MST" %TZ_MST | "MDT" %TZ_MDT | + "PST" %TZ_PST | "PDT" %TZ_PDT | + [a-iA-I] | [k-zK-Z]; + time = time_of_day %DT_End FWS (zone | obs_zone %Obs_Zone_End) FWS*; + date_time = (day_of_week ",")? date time CFWS?; +}%% |