Annotation of embedaddon/nginx/src/http/ngx_http_parse_time.c, revision 1.1.1.1
1.1 misho 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>