aboutsummaryrefslogtreecommitdiff
path: root/src/http/ngx_http_parse_time.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/ngx_http_parse_time.c')
-rw-r--r--src/http/ngx_http_parse_time.c244
1 files changed, 205 insertions, 39 deletions
diff --git a/src/http/ngx_http_parse_time.c b/src/http/ngx_http_parse_time.c
index 3e730a61a..f4097ad51 100644
--- a/src/http/ngx_http_parse_time.c
+++ b/src/http/ngx_http_parse_time.c
@@ -1,64 +1,230 @@
-time_t ngx_http_parse_time()
+#include <time.h>
+
+#define NGX_ERROR -1
+
+static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+time_t ngx_http_parse_time(char *value, size_t len)
{
+ char *p, *end;
+ int day, month, year, hour, min, sec;
enum {
- sw_start = 0,
- } state;
+ no = 0,
+ rfc822, /* Tue 10 Nov 2002 23:50:13 */
+ rfc850, /* Tuesday, 10-Dec-02 23:50:13 */
+ isoc /* Tue Dec 10 23:50:13 2002 */
+ } fmt;
- state = sw_start;
+ end = value + len;
- while () {
- switch (state) {
-
- case sw_start:
- if (ch == ' ') {
- ansi = 1;
- state = sw_month;
+ for (p = value; p < end; p++) {
+ if (*p == ',')
+ break;
- } else if (ch == ',')
- state = sw_day_first_digit;
+ if (*p == ' ') {
+ fmt = isoc;
+ break;
+ }
+ }
+ for (p++; p < end; p++)
+ if (*p != ' ')
break;
- case sw_day_first_digit:
- if (ch == ' ')
- break;
+ if (end - p < 18)
+ return NGX_ERROR;
- if (ch >= '0' && ch <= '9') {
- day = ch - '0';
- state = sw_day;
- break;
+ if (fmt != isoc) {
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
+ return NGX_ERROR;
- }
+ day = (*p - '0') * 10 + *(p + 1) - '0';
+ p += 2;
+ if (*p == ' ') {
+ if (end - p < 18)
+ return NGX_ERROR;
+ fmt = rfc822;
+
+ } else if (*p == '-') {
+ fmt = rfc850;
+
+ } else {
return NGX_ERROR;
+ }
+
+ p++;
+ }
+
+ switch (*p) {
+
+ case 'J':
+ month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
+ break;
+
+ case 'F':
+ month = 1;
+ break;
- case sw_day:
- if (ansi && ch == ' ') {
- state = sw_hour_first_digit;
- break;
- }
+ case 'M':
+ month = *(p + 2) == 'r' ? 2 : 4;
+ break;
- if (ch >= '0' && ch <= '9') {
- day = ch - '0';
- state = ansi ? sw_space_before_hour : sw_before_month;
- break;
- }
+ case 'A':
+ month = *(p + 1) == 'p' ? 3 : 7;
+ break;
+ case 'S':
+ month = 8;
+ break;
+
+ case 'O':
+ month = 9;
+ break;
+
+ case 'N':
+ month = 10;
+ break;
+
+ case 'D':
+ month = 11;
+ break;
+
+ default:
+ return NGX_ERROR;
+ }
+
+ p += 3;
+
+ if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-'))
+ return NGX_ERROR;
+
+ p++;
+
+ if (fmt == rfc822) {
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
+ || *(p + 2) < '0' || *(p + 2) > '9'
+ || *(p + 3) < '0' || *(p + 3) > '9')
return NGX_ERROR;
- case sw_before_month:
- if (ch == ' ') {
- rfc822 = 1;
- }
+ year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
+ + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
+ p += 4;
- if (ch == '-') {
- rfc850 = 1;
- }
+ } else if (fmt == rfc850) {
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
+ return NGX_ERROR;
+
+ year = (*p - '0') * 10 + *(p + 1) - '0';
+ year += (year < 70) ? 2000 : 1900;
+ p += 2;
+ }
+
+ if (fmt == isoc) {
+ if (*p == ' ')
+ p++;
- case sw_space_before_hour:
+ if (*p < '0' || *p > '9')
+ return NGX_ERROR;
+
+ day = *p++ - '0';
+ if (*p != ' ') {
+ if (*p < '0' || *p > '9')
+ return NGX_ERROR;
+ day = day * 10 + *p++ - '0';
}
+
+ if (end - p < 14)
+ return NGX_ERROR;
}
+
+ if (*p++ != ' ')
+ return NGX_ERROR;
+
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
+ return NGX_ERROR;
+
+ hour = (*p - '0') * 10 + *(p + 1) - '0';
+ p += 2;
+
+ if (*p++ != ':')
+ return NGX_ERROR;
+
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
+ return NGX_ERROR;
+
+ min = (*p - '0') * 10 + *(p + 1) - '0';
+ p += 2;
+
+ if (*p++ != ':')
+ return NGX_ERROR;
+
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
+ return NGX_ERROR;
+
+ sec = (*p - '0') * 10 + *(p + 1) - '0';
+
+ if (fmt == isoc) {
+ p += 2;
+
+ if (*p++ != ' ')
+ return NGX_ERROR;
+
+ if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
+ || *(p + 2) < '0' || *(p + 2) > '9'
+ || *(p + 3) < '0' || *(p + 3) > '9')
+ return NGX_ERROR;
+
+ year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
+ + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
+ }
+
+ printf("%d.%d.%d %d:%d:%d\n", day, month + 1, year, hour, min, sec);
+
+ if (hour > 23 || min > 60 || sec > 60)
+ return NGX_ERROR;
+
+ if (day == 29 && month == 1) {
+ if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0))
+ return NGX_ERROR;
+
+ } else if (day > mday[month])
+ return NGX_ERROR;
+ }
+
+ if (sizeof(time_t) <= 4 && year >= 2038)
+ return NGX_ERROR;
+
+ if (--month <= 0) {
+ month += 12;
+ year -= 1;
+ }
+
+ return year / 4 - year / 100 + year / 400
+ + 367 * month / 12 + day + year * 365 - 719499;
+}
+
+char zero[] = "Sun, 01 Jan 1970 08:49:30";
+char one[] = "Sunday, 11-Dec-02 08:49:30";
+char two[] = "Sun Mar 1 08:49:37 2000";
+char thr[] = "Sun Dec 11 08:49:37 2002";
+
+main()
+{
+ int rc;
+
+ rc = ngx_http_parse_time(zero, sizeof(zero) - 1);
+ printf("rc: %d\n", rc);
+
+ rc = ngx_http_parse_time(one, sizeof(one) - 1);
+ printf("rc: %d\n", rc);
+
+ rc = ngx_http_parse_time(two, sizeof(two) - 1);
+ printf("rc: %d\n", rc);
+
+ rc = ngx_http_parse_time(thr, sizeof(thr) - 1);
+ printf("rc: %d\n", rc);
}