Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_parse_time.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
14 
15 time_t
16 ngx_http_parse_time(u_char *value, size_t len)
17 {
18  u_char *p, *end;
19  ngx_int_t month;
20  ngx_uint_t day, year, hour, min, sec;
21  uint64_t time;
22  enum {
23  no = 0,
24  rfc822, /* Tue, 10 Nov 2002 23:50:13 */
25  rfc850, /* Tuesday, 10-Dec-02 23:50:13 */
26  isoc /* Tue Dec 10 23:50:13 2002 */
27  } fmt;
28 
29  fmt = 0;
30  end = value + len;
31 
32 #if (NGX_SUPPRESS_WARN)
33  day = 32;
34  year = 2038;
35 #endif
36 
37  for (p = value; p < end; p++) {
38  if (*p == ',') {
39  break;
40  }
41 
42  if (*p == ' ') {
43  fmt = isoc;
44  break;
45  }
46  }
47 
48  for (p++; p < end; p++)
49  if (*p != ' ') {
50  break;
51  }
52 
53  if (end - p < 18) {
54  return NGX_ERROR;
55  }
56 
57  if (fmt != isoc) {
58  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
59  return NGX_ERROR;
60  }
61 
62  day = (*p - '0') * 10 + *(p + 1) - '0';
63  p += 2;
64 
65  if (*p == ' ') {
66  if (end - p < 18) {
67  return NGX_ERROR;
68  }
69  fmt = rfc822;
70 
71  } else if (*p == '-') {
72  fmt = rfc850;
73 
74  } else {
75  return NGX_ERROR;
76  }
77 
78  p++;
79  }
80 
81  switch (*p) {
82 
83  case 'J':
84  month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
85  break;
86 
87  case 'F':
88  month = 1;
89  break;
90 
91  case 'M':
92  month = *(p + 2) == 'r' ? 2 : 4;
93  break;
94 
95  case 'A':
96  month = *(p + 1) == 'p' ? 3 : 7;
97  break;
98 
99  case 'S':
100  month = 8;
101  break;
102 
103  case 'O':
104  month = 9;
105  break;
106 
107  case 'N':
108  month = 10;
109  break;
110 
111  case 'D':
112  month = 11;
113  break;
114 
115  default:
116  return NGX_ERROR;
117  }
118 
119  p += 3;
120 
121  if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-')) {
122  return NGX_ERROR;
123  }
124 
125  p++;
126 
127  if (fmt == rfc822) {
128  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
129  || *(p + 2) < '0' || *(p + 2) > '9'
130  || *(p + 3) < '0' || *(p + 3) > '9')
131  {
132  return NGX_ERROR;
133  }
134 
135  year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
136  + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
137  p += 4;
138 
139  } else if (fmt == rfc850) {
140  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
141  return NGX_ERROR;
142  }
143 
144  year = (*p - '0') * 10 + *(p + 1) - '0';
145  year += (year < 70) ? 2000 : 1900;
146  p += 2;
147  }
148 
149  if (fmt == isoc) {
150  if (*p == ' ') {
151  p++;
152  }
153 
154  if (*p < '0' || *p > '9') {
155  return NGX_ERROR;
156  }
157 
158  day = *p++ - '0';
159 
160  if (*p != ' ') {
161  if (*p < '0' || *p > '9') {
162  return NGX_ERROR;
163  }
164 
165  day = day * 10 + *p++ - '0';
166  }
167 
168  if (end - p < 14) {
169  return NGX_ERROR;
170  }
171  }
172 
173  if (*p++ != ' ') {
174  return NGX_ERROR;
175  }
176 
177  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
178  return NGX_ERROR;
179  }
180 
181  hour = (*p - '0') * 10 + *(p + 1) - '0';
182  p += 2;
183 
184  if (*p++ != ':') {
185  return NGX_ERROR;
186  }
187 
188  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
189  return NGX_ERROR;
190  }
191 
192  min = (*p - '0') * 10 + *(p + 1) - '0';
193  p += 2;
194 
195  if (*p++ != ':') {
196  return NGX_ERROR;
197  }
198 
199  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
200  return NGX_ERROR;
201  }
202 
203  sec = (*p - '0') * 10 + *(p + 1) - '0';
204 
205  if (fmt == isoc) {
206  p += 2;
207 
208  if (*p++ != ' ') {
209  return NGX_ERROR;
210  }
211 
212  if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
213  || *(p + 2) < '0' || *(p + 2) > '9'
214  || *(p + 3) < '0' || *(p + 3) > '9')
215  {
216  return NGX_ERROR;
217  }
218 
219  year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
220  + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
221  }
222 
223  if (hour > 23 || min > 59 || sec > 59) {
224  return NGX_ERROR;
225  }
226 
227  if (day == 29 && month == 1) {
228  if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) {
229  return NGX_ERROR;
230  }
231 
232  } else if (day > mday[month]) {
233  return NGX_ERROR;
234  }
235 
236  /*
237  * shift new year to March 1 and start months from 1 (not 0),
238  * it is needed for Gauss' formula
239  */
240 
241  if (--month <= 0) {
242  month += 12;
243  year -= 1;
244  }
245 
246  /* Gauss' formula for Gregorian days since March 1, 1 BC */
247 
248  time = (uint64_t) (
249  /* days in years including leap years since March 1, 1 BC */
250 
251  365 * year + year / 4 - year / 100 + year / 400
252 
253  /* days before the month */
254 
255  + 367 * month / 12 - 30
256 
257  /* days before the day */
258 
259  + day - 1
260 
261  /*
262  * 719527 days were between March 1, 1 BC and March 1, 1970,
263  * 31 and 28 days were in January and February 1970
264  */
265 
266  - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
267 
268 #if (NGX_TIME_T_SIZE <= 4)
269 
270  if (time > 0x7fffffff) {
271  return NGX_ERROR;
272  }
273 
274 #endif
275 
276  return (time_t) time;
277 }