diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2017-07-06 18:22:30 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2017-07-06 18:22:30 +0300 |
commit | ee8ede905a301f2fa1e85f47b4fd0f1cd087921f (patch) | |
tree | e31231c953c555cc5e05686ff4c6e9cb1eeec8e8 | |
parent | ea69d766b0a882b66836d7000ac676c9c6d31dec (diff) | |
download | mailutils-ee8ede905a301f2fa1e85f47b4fd0f1cd087921f.tar.gz mailutils-ee8ede905a301f2fa1e85f47b4fd0f1cd087921f.tar.bz2 |
Rewrite rfc822 date parser
* include/mailutils/parse822.h (mu_parse822_day)
(mu_parse822_date,mu_parse822_time): Remove protos.
* libmailutils/address/parse822.c (mu_parse822_date_time): Rewrite
via mu_scan_datetime.
-rw-r--r-- | include/mailutils/parse822.h | 5 | ||||
-rw-r--r-- | libmailutils/address/parse822.c | 371 |
2 files changed, 15 insertions, 361 deletions
diff --git a/include/mailutils/parse822.h b/include/mailutils/parse822.h index f4712b9c5..1cc1b2508 100644 --- a/include/mailutils/parse822.h +++ b/include/mailutils/parse822.h @@ -202,11 +202,6 @@ extern int mu_parse822_field_name (const char **p, const char *e, /***** From RFC 822, 5.1 Date and Time Specification Syntax *****/ -extern int mu_parse822_day (const char **p, const char *e, int *day); -extern int mu_parse822_date (const char **p, const char *e, int *day, - int *mon, int *year); -extern int mu_parse822_time (const char **p, const char *e, int *h, - int *m, int *s, int *tz, const char **tz_name); extern int mu_parse822_date_time (const char **p, const char *e, struct tm *tm, struct mu_timezone *tz); diff --git a/libmailutils/address/parse822.c b/libmailutils/address/parse822.c index bb433da4c..075dc7d64 100644 --- a/libmailutils/address/parse822.c +++ b/libmailutils/address/parse822.c @@ -1382,281 +1382,6 @@ mu_parse822_domain_literal (const char **p, const char *e, char **domain_literal /***** From RFC 822, 5.1 Date and Time Specification Syntax *****/ -int -mu_parse822_day (const char **p, const char *e, int *day) -{ - /* day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" */ - - const char *days[] = { - "Sun", - "Mon", - "Tue", - "Wed", - "Thu", - "Fri", - "Sat", - NULL - }; - - int d; - - mu_parse822_skip_comments (p, e); - - if ((e - *p) < 3) - return EPARSE; - - for (d = 0; days[d]; d++) - { - if (mu_c_strncasecmp (*p, days[d], 3) == 0) - { - *p += 3; - if (day) - *day = d; - return EOK; - } - } - return EPARSE; -} - -int -mu_parse822_date (const char **p, const char *e, int *day, int *mon, int *year) -{ - /* date = 1*2DIGIT month 2*4DIGIT - * month = "Jan" / "Feb" / "Mar" / "Apr" - * / "May" / "Jun" / "Jul" / "Aug" - * / "Sep" / "Oct" / "Nov" / "Dec" - */ - - const char *mons[] = { - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - NULL - }; - - const char *save = *p; - int rc = EOK; - int m = 0; - int yr = 0; - const char *yrbeg = 0; - - mu_parse822_skip_comments (p, e); - - if ((rc = mu_parse822_digits (p, e, 1, 2, day))) - { - *p = save; - return rc; - } - - mu_parse822_skip_comments (p, e); - - if ((e - *p) < 3) - return EPARSE; - - for (m = 0; mons[m]; m++) - { - if (mu_c_strncasecmp (*p, mons[m], 3) == 0) - { - *p += 3; - if (mon) - *mon = m; - break; - } - } - - if (!mons[m]) - { - *p = save; - return EPARSE; - } - - mu_parse822_skip_comments (p, e); - - /* We need to count how many digits their were, and adjust the - * interpretation of the year accordingly. This is from RFC 2822, - * Section 4.3, Obsolete Date and Time. */ - yrbeg = *p; - - if ((rc = mu_parse822_digits (p, e, 2, 4, &yr))) - { - *p = save; - return rc; - } - - /* rationalize year to four digit, then adjust to tz notation */ - switch (*p - yrbeg) - { - case 2: - if (yr >= 0 && yr <= 49) - { - yr += 2000; - break; - } - case 3: - yr += 1900; - break; - } - - if (year) - *year = yr - 1900; - - return EOK; -} - -int -mu_parse822_time (const char **p, const char *e, - int *hour, int *min, int *sec, int *tz, const char **tz_name) -{ - /* time = hour zone - * hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59 - * zone = "UT" / "GMT" ; Universal Time - * ; North American : UT - * / "EST" / "EDT" ; Eastern: - 5/ - 4 - * / "CST" / "CDT" ; Central: - 6/ - 5 - * / "MST" / "MDT" ; Mountain: - 7/ - 6 - * / "PST" / "PDT" ; Pacific: - 8/ - 7 - * / 1ALPHA ; RFC 822 was wrong, RFC 2822 - * ; says treat these all as -0000. - * / ( ("+" / "-") 4DIGIT ) ; Local differential - * ; hours+min. (HHMM) - */ - - struct - { - const char *tzname; - int tz; - } - tzs[] = - { - { "UT", 0 * 60 * 60 }, - { "UTC", 0 * 60 * 60 }, - { "GMT", 0 * 60 * 60 }, - { "EST", -5 * 60 * 60 }, - { "EDT", -4 * 60 * 60 }, - { "CST", -6 * 60 * 60 }, - { "CDT", -5 * 60 * 60 }, - { "MST", -7 * 60 * 60 }, - { "MDT", -6 * 60 * 60 }, - { "PST", -8 * 60 * 60 }, - { "PDT", -7 * 60 * 60 }, - { NULL, 0} - }; - - const char *save = *p; - int rc = EOK; - int z = 0; - char *zone = NULL; - - mu_parse822_skip_comments (p, e); - - if ((rc = mu_parse822_digits (p, e, 1, 2, hour))) - { - *p = save; - return rc; - } - - if ((rc = mu_parse822_special (p, e, ':'))) - { - *p = save; - return rc; - } - - if ((rc = mu_parse822_digits (p, e, 1, 2, min))) - { - *p = save; - return rc; - } - - if ((rc = mu_parse822_special (p, e, ':'))) - { - *sec = 0; - } - else if ((rc = mu_parse822_digits (p, e, 1, 2, sec))) - { - *p = save; - return rc; - } - - mu_parse822_skip_comments (p, e); - - if ((rc = mu_parse822_atom (p, e, &zone))) - { - /* zone is optional */ - if (tz) - *tz = 0; - return EOK; - } - - /* see if it's a timezone */ - for (; tzs[z].tzname; z++) - { - if (mu_c_strcasecmp (zone, tzs[z].tzname) == 0) - break; - } - if (tzs[z].tzname) - { - if (tz_name) - *tz_name = tzs[z].tzname; - - if (tz) - *tz = tzs[z].tz; - } - else if (strlen (zone) > 5 || strlen (zone) < 4) - { - if (*tz) - *tz = 0; /* Assume UTC */ - } - else - { - /* zone = ( + / - ) hhmm */ - int hh; - int mm; - int sign; - char *zp = zone; - - switch (zp[0]) - { - case '-': - sign = -1; - zp++; - break; - case '+': - sign = +1; - zp++; - break; - default: - sign = 1; - break; - } - - if (strspn (zp, "0123456789") == 4) - { - /* convert to seconds from UTC */ - hh = (zone[1] - '0') * 10 + (zone[2] - '0'); - mm = (zone[3] - '0') * 10 + (zone[4] - '0'); - } - else - { - hh = mm = 0; /* Consider equivalent to -0000 */ - } - if (tz) - *tz = sign * (hh * 60 * 60 + mm * 60); - } - - str_free (&zone); - - return EOK; -} - #if 0 For reference, especially for the required range and values of the integer fields. @@ -1682,87 +1407,21 @@ int mu_parse822_date_time (const char **p, const char *e, struct tm *tm, struct mu_timezone *tz) { - /* date-time = [ day "," ] date time */ - - const char *save = *p; - int rc = 0; - - int wday = 0; - - int mday = 0; - int mon = 0; - int year = 0; - - int hour = 0; - int min = 0; - int sec = 0; - - int tzoffset = 0; - const char *tz_name = 0; - - if ((rc = mu_parse822_day (p, e, &wday))) - { - if (rc != EPARSE) - return rc; - } - else - { - /* If we got a day, we MUST have a ','. */ - mu_parse822_skip_comments (p, e); - - if ((rc = mu_parse822_special (p, e, ','))) - { - *p = save; - return rc; - } - } - - if ((rc = mu_parse822_date (p, e, &mday, &mon, &year))) - { - *p = save; - return rc; - } - if ((rc = mu_parse822_time (p, e, &hour, &min, &sec, &tzoffset, &tz_name))) - { - *p = save; - return rc; - } - - if (tm) - { - memset (tm, 0, sizeof (*tm)); - - tm->tm_wday = wday; - - tm->tm_mday = mday; - tm->tm_mon = mon; - tm->tm_year = year; - - tm->tm_hour = hour; - tm->tm_min = min; - tm->tm_sec = sec; - - tm->tm_yday = mu_datetime_dayofyear (tm->tm_year + 1900, - tm->tm_mon + 1, tm->tm_mday) - 1; - -#ifdef HAVE_STRUCT_TM_TM_ISDST - tm->tm_isdst = -1; /* unknown whether it's dst or not */ -#endif -#ifdef HAVE_STRUCT_TM_TM_GMTOFF - tm->tm_gmtoff = tzoffset; -#endif -#ifdef HAVE_STRUCT_TM_TM_ZONE - tm->tm_zone = (char*) tz_name; -#endif - } - - if (tz) - { - tz->utc_offset = tzoffset; - tz->tz_name = tz_name; - } - - return EOK; + char *tmp; + char *end; + size_t len = e - *p; + int rc; + + tmp = malloc (len + 1); + if (!tmp) + return ENOMEM; + memcpy (tmp, *p, len); + tmp[len] = 0; + rc = mu_scan_datetime (tmp, MU_DATETIME_SCAN_RFC822, tm, tz, &end); + if (rc == 0) + *p = end; + free (tmp); + return rc; } /***** From RFC 822, 3.2 Header Field Definitions *****/ |