rfc1123.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "rfc1123.h"
11 
12 /*
13  * Adapted from HTSUtils.c in CERN httpd 3.0 (http://info.cern.ch/httpd/)
14  * by Darren Hardy <hardy@cs.colorado.edu>, November 1994.
15  */
16 #if HAVE_STRING_H
17 #include <string.h>
18 #endif
19 #if HAVE_CTYPE_H
20 #include <ctype.h>
21 #endif
22 #if HAVE_TIME_H
23 #include <time.h>
24 #endif
25 
26 #define RFC850_STRFTIME "%A, %d-%b-%y %H:%M:%S GMT"
27 #define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
28 
29 static int make_month(const char *s);
30 static int make_num(const char *s);
31 
32 static const char *month_names[12] = {
33  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
34  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
35 };
36 
37 static int
38 make_num(const char *s)
39 {
40  if (*s >= '0' && *s <= '9')
41  return 10 * (*s - '0') + *(s + 1) - '0';
42  else
43  return *(s + 1) - '0';
44 }
45 
46 static int
47 make_month(const char *s)
48 {
49  int i;
50  char month[3];
51 
52  month[0] = xtoupper(*s);
53  month[1] = xtolower(*(s + 1));
54  month[2] = xtolower(*(s + 2));
55 
56  for (i = 0; i < 12; i++)
57  if (!strncmp(month_names[i], month, 3))
58  return i;
59  return -1;
60 }
61 
62 static int
63 tmSaneValues(struct tm *tm)
64 {
65  if (tm->tm_sec < 0 || tm->tm_sec > 59)
66  return 0;
67  if (tm->tm_min < 0 || tm->tm_min > 59)
68  return 0;
69  if (tm->tm_hour < 0 || tm->tm_hour > 23)
70  return 0;
71  if (tm->tm_mday < 1 || tm->tm_mday > 31)
72  return 0;
73  if (tm->tm_mon < 0 || tm->tm_mon > 11)
74  return 0;
75  return 1;
76 }
77 
78 static struct tm *
79 parse_date_elements(const char *day, const char *month, const char *year,
80  const char *aTime, const char *zone) {
81  static struct tm tm;
82  char *t;
83  memset(&tm, 0, sizeof(tm));
84 
85  if (!day || !month || !year || !aTime || (zone && strcmp(zone, "GMT")))
86  return NULL;
87  tm.tm_mday = atoi(day);
88  tm.tm_mon = make_month(month);
89  if (tm.tm_mon < 0)
90  return NULL;
91  tm.tm_year = atoi(year);
92  if (strlen(year) == 4)
93  tm.tm_year -= 1900;
94  else if (tm.tm_year < 70)
95  tm.tm_year += 100;
96  else if (tm.tm_year > 19000)
97  tm.tm_year -= 19000;
98  tm.tm_hour = make_num(aTime);
99  t = strchr(aTime, ':');
100  if (!t)
101  return NULL;
102  t++;
103  tm.tm_min = atoi(t);
104  t = strchr(t, ':');
105  if (t)
106  tm.tm_sec = atoi(t + 1);
107  return tmSaneValues(&tm) ? &tm : NULL;
108 }
109 
110 static struct tm *
111 parse_date(const char *str) {
112  struct tm *tm;
113  static char tmp[64];
114  char *t;
115  char *wday = NULL;
116  char *day = NULL;
117  char *month = NULL;
118  char *year = NULL;
119  char *timestr = NULL;
120  char *zone = NULL;
121 
122  xstrncpy(tmp, str, 64);
123 
124  for (t = strtok(tmp, ", "); t; t = strtok(NULL, ", ")) {
125  if (xisdigit(*t)) {
126  if (!day) {
127  day = t;
128  t = strchr(t, '-');
129  if (t) {
130  *t++ = '\0';
131  month = t;
132  t = strchr(t, '-');
133  if (!t)
134  return NULL;
135  *t++ = '\0';
136  year = t;
137  }
138  } else if (strchr(t, ':'))
139  timestr = t;
140  else if (!year)
141  year = t;
142  else
143  return NULL;
144  } else if (!wday)
145  wday = t;
146  else if (!month)
147  month = t;
148  else if (!zone)
149  zone = t;
150  else
151  return NULL;
152  }
153  tm = parse_date_elements(day, month, year, timestr, zone);
154 
155  return tm;
156 }
157 
158 time_t
159 parse_rfc1123(const char *str)
160 {
161  struct tm *tm;
162  time_t t;
163  if (NULL == str)
164  return -1;
165  tm = parse_date(str);
166  if (!tm)
167  return -1;
168  tm->tm_isdst = -1;
169 #if HAVE_TIMEGM
170  t = timegm(tm);
171 #elif HAVE_TM_TM_GMTOFF
172  t = mktime(tm);
173  if (t != -1) {
174  struct tm *local = localtime(&t);
175  t += local->tm_gmtoff;
176  }
177 #else
178  /* some systems do not have tm_gmtoff so we fake it */
179  t = mktime(tm);
180  if (t != -1) {
181  time_t dst = 0;
182 #if !(defined(_TIMEZONE) || defined(_timezone) || _SQUID_AIX_ || _SQUID_WINDOWS_ || _SQUID_SGI_)
183  extern long timezone;
184 #endif
185  /*
186  * The following assumes a fixed DST offset of 1 hour,
187  * which is probably wrong.
188  */
189  if (tm->tm_isdst > 0)
190  dst = -3600;
191 #if defined(_timezone) || _SQUID_WINDOWS_
192  t -= (_timezone + dst);
193 #else
194  t -= (timezone + dst);
195 #endif
196  }
197 #endif
198  return t;
199 }
200 
201 const char *
202 mkrfc1123(time_t t)
203 {
204  static char buf[128];
205 
206  struct tm *gmt = gmtime(&t);
207 
208  buf[0] = '\0';
209  strftime(buf, 127, RFC1123_STRFTIME, gmt);
210  return buf;
211 }
212 
213 #if 0
214 int
215 main()
216 {
217  char *x;
218  time_t t, pt;
219 
220  t = time(NULL);
221  x = mkrfc1123(t);
222  printf("HTTP Time: %s\n", x);
223 
224  pt = parse_rfc1123(x);
225  printf("Parsed: %d vs. %d\n", pt, t);
226 }
227 
228 #endif
229 
int main(int, char *[])
Definition: unitTestMain.h:25
#define xtoupper(x)
Definition: xis.h:18
time_t parse_rfc1123(const char *str)
Definition: rfc1123.c:159
int i
Definition: membanger.c:49
static const char * month_names[12]
Definition: rfc1123.c:32
static int tmSaneValues(struct tm *tm)
Definition: rfc1123.c:63
static struct tm * parse_date(const char *str)
Definition: rfc1123.c:111
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
const char * mkrfc1123(time_t t)
Definition: rfc1123.c:202
static struct tm * parse_date_elements(const char *day, const char *month, const char *year, const char *aTime, const char *zone)
Definition: rfc1123.c:79
void const char * buf
Definition: stub_helper.cc:16
static int make_month(const char *s)
Definition: rfc1123.c:47
#define xisdigit(x)
Definition: xis.h:20
#define RFC1123_STRFTIME
Definition: rfc1123.c:27
static int make_num(const char *s)
Definition: rfc1123.c:38
#define xtolower(x)
Definition: xis.h:19
#define NULL
Definition: types.h:166

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors