source: trunk/third/libghttp/http_date.c @ 15592

Revision 15592, 8.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15591, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * http_date.c -- Routines for parsing and generating http dates
3 * Created: Christopher Blizzard <blizzard@appliedtheory.com>, 16-Aug-1998
4 *
5 * Copyright (C) 1998 Free Software Foundation
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <string.h>
23#include <ctype.h>
24#include "http_date.h"
25
26static int
27month_from_string_short(const char *a_month);
28
29/*
30 *  date formats come in one of the following three flavors according to
31 *  rfc 2068 and later drafts:
32 * 
33 *  Sun, 06 Nov 1994 08:49:37 GMT     ; RFC 822, updated by RFC 1123
34 *  Sunday, 06-Nov-1994, 08:49:37 GMT ; RFC 850, updated by RFC 1036
35 *  Sun Nov  6 08:49:37 1994          ; ANSI C's asctime() format
36 *
37 *  the first format is preferred however all must be supported.
38*/
39   
40
41time_t
42http_date_to_time(const char *a_date)
43{
44  struct tm       l_tm_time;
45  time_t          l_return = 0;
46  char            l_buf[12];
47  const char     *l_start_date = NULL;
48  int             i = 0;
49
50  /* make sure we can use it */
51  if (!a_date)
52    return -1;
53  memset(&l_tm_time, 0, sizeof(struct tm));
54  memset(l_buf, 0, 12);
55  /* try to figure out which format it's in */
56  /* rfc 1123 */
57  if (a_date[3] == ',')
58    {
59      if (strlen(a_date) != 29)
60        return -1;
61      /* make sure that everything is legal */
62      if (a_date[4] != ' ')
63        return -1;
64      /* 06 */
65      if ((isdigit(a_date[5]) == 0) ||
66          (isdigit(a_date[6]) == 0))
67        return -1;
68      /* Nov */
69      if ((l_tm_time.tm_mon = month_from_string_short(&a_date[8])) < 0)
70        return -1;
71      /* 1994 */
72      if ((isdigit(a_date[12]) == 0) ||
73          (isdigit(a_date[13]) == 0) ||
74          (isdigit(a_date[14]) == 0) ||
75          (isdigit(a_date[15]) == 0))
76        return -1;
77      if (a_date[16] != ' ')
78        return -1;
79      /* 08:49:37 */
80      if ((isdigit(a_date[17]) == 0) ||
81          (isdigit(a_date[18]) == 0) ||
82          (a_date[19] != ':') ||
83          (isdigit(a_date[20]) == 0) ||
84          (isdigit(a_date[21]) == 0) ||
85          (a_date[22] != ':') ||
86          (isdigit(a_date[23]) == 0) ||
87          (isdigit(a_date[24]) == 0))
88        return -1;
89      if (a_date[25] != ' ')
90        return -1;
91      /* GMT */
92      if (strncmp(&a_date[26], "GMT", 3) != 0)
93        return -1;
94      /* ok, it's valid.  Do it */
95      /* parse out the day of the month */
96      l_tm_time.tm_mday += (a_date[5] - 0x30) * 10;
97      l_tm_time.tm_mday += (a_date[6] - 0x30);
98      /* already got the month from above */
99      /* parse out the year */
100      l_tm_time.tm_year += (a_date[12] - 0x30) * 1000;
101      l_tm_time.tm_year += (a_date[13] - 0x30) * 100;
102      l_tm_time.tm_year += (a_date[14] - 0x30) * 10;
103      l_tm_time.tm_year += (a_date[15] - 0x30);
104      l_tm_time.tm_year -= 1900;
105      /* parse out the time */
106      l_tm_time.tm_hour += (a_date[17] - 0x30) * 10;
107      l_tm_time.tm_hour += (a_date[18] - 0x30);
108      l_tm_time.tm_min  += (a_date[20] - 0x30) * 10;
109      l_tm_time.tm_min  += (a_date[21] - 0x30);
110      l_tm_time.tm_sec  += (a_date[23] - 0x30) * 10;
111      l_tm_time.tm_sec  += (a_date[24] - 0x30);
112      /* ok, generate the result */
113      l_return = mktime(&l_tm_time);
114    }
115  /* ansi C */
116  else if (a_date[3] == ' ')
117    {
118      if (strlen(a_date) != 24)
119        return -1;
120      /* Nov */
121      if ((l_tm_time.tm_mon =
122           month_from_string_short(&a_date[4])) < 0)
123        return -1;
124      if (a_date[7] != ' ')
125        return -1;
126      /* "10" or " 6" */
127      if (((a_date[8] != ' ') && (isdigit(a_date[8]) == 0)) ||
128          (isdigit(a_date[9]) == 0))
129        return -1;
130      if (a_date[10] != ' ')
131        return -1;
132      /* 08:49:37 */
133      if ((isdigit(a_date[11]) == 0) ||
134          (isdigit(a_date[12]) == 0) ||
135          (a_date[13] != ':') ||
136          (isdigit(a_date[14]) == 0) ||
137          (isdigit(a_date[15]) == 0) ||
138          (a_date[16] != ':') ||
139          (isdigit(a_date[17]) == 0) ||
140          (isdigit(a_date[18]) == 0))
141        return -1;
142      if (a_date[19] != ' ')
143        return -1;
144      /* 1994 */
145      if ((isdigit(a_date[20]) == 0) ||
146          (isdigit(a_date[21]) == 0) ||
147          (isdigit(a_date[22]) == 0) ||
148          (isdigit(a_date[23]) == 0))
149        return -1;
150      /* looks good */
151      /* got the month from above */
152      /* parse out the day of the month */
153      if (a_date[8] != ' ')
154        l_tm_time.tm_mday += (a_date[8] - 0x30) * 10;
155      l_tm_time.tm_mday += (a_date[9] - 0x30);
156      /* parse out the time */
157      l_tm_time.tm_hour += (a_date[11] - 0x30) * 10;
158      l_tm_time.tm_hour += (a_date[12] - 0x30);
159      l_tm_time.tm_min  += (a_date[14] - 0x30) * 10;
160      l_tm_time.tm_min  += (a_date[15] - 0x30);
161      l_tm_time.tm_sec  += (a_date[17] - 0x30) * 10;
162      l_tm_time.tm_sec  += (a_date[18] - 0x30);
163      /* parse out the year */
164      l_tm_time.tm_year += (a_date[20] - 0x30) * 1000;
165      l_tm_time.tm_year += (a_date[21] - 0x30) * 100;
166      l_tm_time.tm_year += (a_date[22] - 0x30) * 10;
167      l_tm_time.tm_year += (a_date[23] - 0x30);
168      l_tm_time.tm_year -= 1900;
169      /* generate the result */
170      l_return = mktime(&l_tm_time);
171    }
172  /* must be the 1036... */
173  else
174    {
175      /* check to make sure we won't rn out of any bounds */
176      if (strlen(a_date) < 11)
177        return -1;
178      while (a_date[i])
179        {
180          if (a_date[i] == ' ')
181            {
182              l_start_date = &a_date[i+1];
183              break;
184            }
185          i++;
186        }
187      /* check to make sure there was a space found */
188      if (l_start_date == NULL)
189        return -1;
190      /* check to make sure that we don't overrun anything */
191      if (strlen(l_start_date) != 22)
192        return -1;
193      /* make sure that the rest of the date was valid */
194      /* 06- */
195      if ((isdigit(l_start_date[0]) == 0) ||
196          (isdigit(l_start_date[1]) == 0) ||
197          (l_start_date[2] != '-'))
198        return -1;
199      /* Nov */
200      if ((l_tm_time.tm_mon =
201           month_from_string_short(&l_start_date[3])) < 0)
202        return -1;
203      /* -94 */
204      if ((l_start_date[6] != '-') ||
205          (isdigit(l_start_date[7]) == 0) ||
206          (isdigit(l_start_date[8]) == 0))
207        return -1;
208      if (l_start_date[9] != ' ')
209        return -1;
210      /* 08:49:37 */
211      if ((isdigit(l_start_date[10]) == 0) ||
212          (isdigit(l_start_date[11]) == 0) ||
213          (l_start_date[12] != ':') ||
214          (isdigit(l_start_date[13]) == 0) ||
215          (isdigit(l_start_date[14]) == 0) ||
216          (l_start_date[15] != ':') ||
217          (isdigit(l_start_date[16]) == 0) ||
218          (isdigit(l_start_date[17]) == 0))
219        return -1;
220      if (l_start_date[18] != ' ')
221        return -1;
222      if (strncmp(&l_start_date[19], "GMT", 3) != 0)
223        return -1;
224      /* looks ok to parse */
225      /* parse out the day of the month */
226      l_tm_time.tm_mday += (l_start_date[0] - 0x30) * 10;
227      l_tm_time.tm_mday += (l_start_date[1] - 0x30);
228      /* have the month from above */
229      /* parse out the year */
230      l_tm_time.tm_year += (l_start_date[7] - 0x30) * 10;
231      l_tm_time.tm_year += (l_start_date[8] - 0x30);
232      /* check for y2k */
233      if (l_tm_time.tm_year < 20)
234        l_tm_time.tm_year += 100;
235      /* parse out the time */
236      l_tm_time.tm_hour += (l_start_date[10] - 0x30) * 10;
237      l_tm_time.tm_hour += (l_start_date[11] - 0x30);
238      l_tm_time.tm_min  += (l_start_date[13] - 0x30) * 10;
239      l_tm_time.tm_min  += (l_start_date[14] - 0x30);
240      l_tm_time.tm_sec  += (l_start_date[16] - 0x30) * 10;
241      l_tm_time.tm_sec  += (l_start_date[17] - 0x30);
242      /* generate the result */
243      l_return = mktime(&l_tm_time);
244    }
245  return l_return;
246}
247
248static int
249month_from_string_short(const char *a_month)
250{
251  if (strncmp(a_month, "Jan", 3) == 0)
252    return 0;
253  if (strncmp(a_month, "Feb", 3) == 0)
254    return 1;
255  if (strncmp(a_month, "Mar", 3) == 0)
256    return 2;
257  if (strncmp(a_month, "Apr", 3) == 0)
258    return 3;
259  if (strncmp(a_month, "May", 3) == 0)
260    return 4;
261  if (strncmp(a_month, "Jun", 3) == 0)
262    return 5;
263  if (strncmp(a_month, "Jul", 3) == 0)
264    return 6;
265  if (strncmp(a_month, "Aug", 3) == 0)
266    return 7;
267  if (strncmp(a_month, "Sep", 3) == 0)
268    return 8;
269  if (strncmp(a_month, "Oct", 3) == 0)
270    return 9;
271  if (strncmp(a_month, "Nov", 3) == 0)
272    return 10;
273  if (strncmp(a_month, "Dec", 3) == 0)
274    return 11;
275  /* not a valid date */
276  return -1;
277}
278
Note: See TracBrowser for help on using the repository browser.