Commit 14d5478f authored by Nick Mathewson's avatar Nick Mathewson 🐘
Browse files

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


svn:r2129
parent 8b55f73b
Loading
Loading
Loading
Loading
+51 −0
Changes for src/common/util.c: 51 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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
Changes for src/common/util.h: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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
Changes for src/or/test.c: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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();