Browse Source

Add functions to format and parse RFC1123-style times, for HTTP protocol.

svn:r2129
Nick Mathewson 21 years ago
parent
commit
14d5478f29
3 changed files with 66 additions and 0 deletions
  1. 51 0
      src/common/util.c
  2. 3 0
      src/common/util.h
  3. 12 0
      src/or/test.c

+ 51 - 0
src/common/util.c

@@ -914,6 +914,57 @@ time_t tor_timegm (struct tm *tm) {
   return ret;
 }
 
+/* strftime is locale-specific, so we need to replace those parts */
+static const char *WEEKDAY_NAMES[] =
+  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+static const char *MONTH_NAMES[] =
+  { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+void tor_format_rfc1123_time(char *buf, time_t t) {
+  struct tm *tm = gmtime(&t);
+
+  strftime(buf, RFC1123_TIME_LEN+1, "XXX, %d XXX %Y %H:%M:%S GMT", tm);
+  tor_assert(tm->tm_wday >= 0 && tm->tm_wday <= 6);
+  memcpy(buf, WEEKDAY_NAMES[tm->tm_wday], 3);
+  tor_assert(tm->tm_wday >= 0 && tm->tm_mon <= 11);
+  memcpy(buf+8, MONTH_NAMES[tm->tm_mon], 3);
+}
+
+int tor_parse_rfc1123_time(const char *buf, time_t *t) {
+  struct tm tm;
+  char month[4];
+  char weekday[4];
+  int i, m;
+
+  if (strlen(buf) != RFC1123_TIME_LEN)
+    return -1;
+  memset(&tm, 0, sizeof(tm));
+  if (sscanf(buf, "%3s, %d %3s %d %d:%d:%d GMT", weekday,
+             &tm.tm_mday, month, &tm.tm_year, &tm.tm_hour,
+             &tm.tm_min, &tm.tm_sec) < 7) {
+    log_fn(LOG_WARN, "Got invalid RFC1123 time \"%s\"", buf);
+    return -1;
+  }
+
+  m = -1;
+  for (i = 0; i < 12; ++i) {
+    if (!strcmp(month, MONTH_NAMES[i])) {
+      m = i;
+      break;
+    }
+  }
+  if (m<0) {
+    log_fn(LOG_WARN, "Got invalid RFC1123 time \"%s\"", buf);
+    return -1;
+  }
+
+  tm.tm_mon = m;
+  tm.tm_year -= 1900;
+  *t = tor_timegm(&tm);
+  return 0;
+}
+
 /*
  *   Low-level I/O.
  */

+ 3 - 0
src/common/util.h

@@ -201,6 +201,9 @@ void tv_addms(struct timeval *a, long ms);
 void tv_add(struct timeval *a, struct timeval *b);
 int tv_cmp(struct timeval *a, struct timeval *b);
 time_t tor_timegm(struct tm *tm);
+#define RFC1123_TIME_LEN 29
+void tor_format_rfc1123_time(char *buf, time_t t);
+int tor_parse_rfc1123_time(const char *buf, time_t *t);
 
 int write_all(int fd, const char *buf, size_t count, int isSocket);
 int read_all(int fd, char *buf, size_t count, int isSocket);

+ 12 - 0
src/or/test.c

@@ -439,6 +439,9 @@ test_util() {
   struct timeval start, end;
   struct tm a_time;
   smartlist_t *sl;
+  char timestr[RFC1123_TIME_LEN+1];
+  time_t t_res;
+  int i;
 
   start.tv_sec = 5;
   start.tv_usec = 5000;
@@ -479,6 +482,15 @@ test_util() {
   a_time.tm_mday = 10;
   test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
 
+  tor_format_rfc1123_time(timestr, 0);
+  test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr);
+  tor_format_rfc1123_time(timestr, (time_t)1091580502UL);
+  test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr);
+
+  t_res = 0;
+  i = tor_parse_rfc1123_time(timestr, &t_res);
+  test_eq(i,0);
+  test_eq(t_res, (time_t)1091580502UL);
 
   /* Test smartlist */
   sl = smartlist_create();