summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2017-07-06 18:22:30 +0300
committerSergey Poznyakoff <gray@gnu.org>2017-07-06 18:22:30 +0300
commitee8ede905a301f2fa1e85f47b4fd0f1cd087921f (patch)
treee31231c953c555cc5e05686ff4c6e9cb1eeec8e8
parentea69d766b0a882b66836d7000ac676c9c6d31dec (diff)
downloadmailutils-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.h5
-rw-r--r--libmailutils/address/parse822.c371
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 *****/

Return to:

Send suggestions and report system problems to the System administrator.