simplify mutt_parse_date
[apps/madmutt.git] / lib-mime / rfc822parse.c
index e0cd6b0..6032132 100644 (file)
@@ -671,138 +671,127 @@ static struct tz_t {
  * This routine assumes that `h' has been initialized to 0.  the `timezone'
  * field is optional, defaulting to +0000 if missing.
  */
-time_t mutt_parse_date (const char *s, HEADER * h)
+time_t mutt_parse_date(const char *s, HEADER *h)
 {
-  int count = 0;
-  char *t;
-  int hour, min, sec;
-  struct tm tm;
-  int i;
-  int tz_offset = 0;
-  int zhours = 0;
-  int zminutes = 0;
-  int zoccident = 0;
-  const char *ptz;
-  char tzstr[SHORT_STRING];
-  char scratch[SHORT_STRING];
-
-  /* Don't modify our argument. Fixed-size buffer is ok here since
-   * the date format imposes a natural limit.
-   */
-
-  m_strcpy(scratch, sizeof(scratch), s);
-
-  /* kill the day of the week, if it exists. */
-  if ((t = strchr (scratch, ',')))
-    t++;
-  else
-    t = scratch;
-  t = vskipspaces(t);
-
-  p_clear(&tm, 1);
-
-  while ((t = strtok (t, " \t")) != NULL) {
-    switch (count) {
-    case 0:                    /* day of the month */
-      if (!isdigit ((unsigned char) *t))
-        return (-1);
-      tm.tm_mday = atoi (t);
-      if (tm.tm_mday > 31)
-        return (-1);
-      break;
-
-    case 1:                    /* month of the year */
-      if ((i = mutt_check_month (t)) < 0)
-        return (-1);
-      tm.tm_mon = i;
-      break;
-
-    case 2:                    /* year */
-      tm.tm_year = atoi (t);
-      if (tm.tm_year < 50)
-        tm.tm_year += 100;
-      else if (tm.tm_year >= 1900)
-        tm.tm_year -= 1900;
-      break;
-
-    case 3:                    /* time of day */
-      if (sscanf (t, "%d:%d:%d", &hour, &min, &sec) == 3);
-      else if (sscanf (t, "%d:%d", &hour, &min) == 2)
-        sec = 0;
-      else {
-        debug_print (1, ("could not process time format: %s\n", t));
-        return (-1);
-      }
-      tm.tm_hour = hour;
-      tm.tm_min = min;
-      tm.tm_sec = sec;
-      break;
-
-    case 4:                    /* timezone */
-      /* sometimes we see things like (MST) or (-0700) so attempt to
-       * compensate by uncommenting the string if non-RFC822 compliant
-       */
-      ptz = uncomment_timezone (tzstr, sizeof (tzstr), t);
-
-      if (*ptz == '+' || *ptz == '-') {
-        if (ptz[1] && ptz[2] && ptz[3] && ptz[4]
-            && isdigit ((unsigned char) ptz[1])
-            && isdigit ((unsigned char) ptz[2])
-            && isdigit ((unsigned char) ptz[3])
-            && isdigit ((unsigned char) ptz[4])) {
-          zhours = (ptz[1] - '0') * 10 + (ptz[2] - '0');
-          zminutes = (ptz[3] - '0') * 10 + (ptz[4] - '0');
-
-          if (ptz[0] == '-')
-            zoccident = 1;
-        }
-      }
-      else {
-        struct tz_t *tz;
-
-        tz = bsearch (ptz, TimeZones, sizeof TimeZones / sizeof (struct tz_t),
-                      sizeof (struct tz_t),
-                      (int (*)(const void *, const void *)) ascii_strcasecmp
-                      /* This is safe to do: A pointer to a struct equals
-                       * a pointer to its first element*/ );
-
-        if (tz) {
-          zhours = tz->zhours;
-          zminutes = tz->zminutes;
-          zoccident = tz->zoccident;
-        }
+    int count = 0;
+    char *p;
+    struct tm tm;
+    int tz_offset = 0;
+    int zhours = 0, zminutes = 0, zoccident = 0;
+    const char *ptz;
+    char tzstr[SHORT_STRING];
+    char scratch[SHORT_STRING];
+
+    /* Don't modify our argument. Fixed-size buffer is ok here since
+       the date format imposes a natural limit.  */
+
+    m_strcpy(scratch, sizeof(scratch), s);
+
+    /* kill the day of the week, if it exists. */
+    p = strchr(scratch, ',');
+    p = vskipspaces(p ? p + 1 : scratch);
+
+    p_clear(&tm, 1);
+
+    while ((p = strtok (p, " \t")) != NULL) {
+        switch (count) {
+          case 0:                    /* day of the month */
+            if (!isdigit((unsigned char)*p))
+                return -1;
+            tm.tm_mday = atoi(p);
+            if (tm.tm_mday > 31)
+                return -1;
+            break;
 
-        /* ad hoc support for the European MET (now officially CET) TZ */
-        if (ascii_strcasecmp (t, "MET") == 0) {
-          if ((t = strtok (NULL, " \t")) != NULL) {
-            if (!ascii_strcasecmp (t, "DST"))
-              zhours++;
-          }
+          case 1:                    /* month of the year */
+            tm.tm_mon = mutt_check_month(p);
+            if (tm.tm_mon < 0)
+                return -1;
+            break;
+
+          case 2:                    /* year */
+            tm.tm_year = atoi(p);
+            if (tm.tm_year < 50)
+                tm.tm_year += 100;
+            else if (tm.tm_year >= 1900)
+                tm.tm_year -= 1900;
+            break;
+
+          case 3:                    /* time of day */
+            tm.tm_hour = strtol(p, &p, 10);
+            if (*p++ != ':')
+                return -1;
+            tm.tm_min  = strtol(p, &p, 10);
+            if (*p++ == ':') {
+                tm.tm_sec = strtol(p, &p, 10);
+            } else {
+                tm.tm_sec = 0;
+            }
+            break;
+
+          case 4:                    /* timezone */
+            /* sometimes we see things like (MST) or (-0700) so attempt to
+             * compensate by uncommenting the string if non-RFC822 compliant
+             */
+            ptz = uncomment_timezone(tzstr, sizeof(tzstr), p);
+
+            if (*ptz == '+' || *ptz == '-') {
+                if (isdigit((unsigned char)ptz[1])
+                &&  isdigit((unsigned char)ptz[2])
+                &&  isdigit((unsigned char)ptz[3])
+                &&  isdigit((unsigned char)ptz[4]))
+                {
+                    zoccident = ptz[0] == '-';
+                    zhours    = (ptz[1] - '0') * 10 + (ptz[2] - '0');
+                    zminutes  = (ptz[3] - '0') * 10 + (ptz[4] - '0');
+                }
+            } else {
+                struct tz_t *tz;
+
+                /* This is safe to do: A pointer to a struct equals a pointer to its
+                 * first element*/
+                tz = bsearch(ptz, TimeZones, countof(TimeZones), sizeof(TimeZones[0]),
+                             (int (*)(const void *, const void *))ascii_strcasecmp);
+
+                if (tz) {
+                    zhours = tz->zhours;
+                    zminutes = tz->zminutes;
+                    zoccident = tz->zoccident;
+                }
+
+                /* ad hoc support for the European MET (now officially CET) TZ */
+                if (ascii_strcasecmp(p, "MET") == 0) {
+                    if ((p = strtok (NULL, " \t")) && !ascii_strcasecmp(p, "DST")) {
+                        zhours++;
+                    }
+                }
+            }
+
+            tz_offset = zhours * 3600 + zminutes * 60;
+            if (!zoccident)
+                tz_offset = -tz_offset;
+            break;
         }
-      }
-      tz_offset = zhours * 3600 + zminutes * 60;
-      if (!zoccident)
-        tz_offset = -tz_offset;
-      break;
+        count++;
+        p = NULL;
     }
-    count++;
-    t = 0;
-  }
 
-  if (count < 4) {              /* don't check for missing timezone */
-    debug_print (1, ("error parsing date format, using received time\n"));
-    return (-1);
-  }
+    if (count < 4) {  /* don't check for missing timezone */
+        debug_print (1, ("error parsing date format, using received time\n"));
+        return -1;
+    }
 
-  if (h) {
-    h->zhours = zhours;
-    h->zminutes = zminutes;
-    h->zoccident = zoccident;
-  }
+    if (h) {
+        h->zhours    = zhours;
+        h->zminutes  = zminutes;
+        h->zoccident = zoccident;
+    }
 
-  return (mutt_mktime (&tm, 0) + tz_offset);
+    return mutt_mktime(&tm, 0) + tz_offset;
 }
 
+/*** XXX: MC READ MARK ***/
+
 /* extract the first substring that looks like a message-id */
 static char *extract_message_id(const char *s)
 {