# HG changeset patch # User Igor Sysoev # Date 1039625874 0 # Node ID a8b156554dfe8e00d4600c9d84447ddfc7943494 # Parent 77c7629a262765d7d567c477c67e1a2aca0e6ad2 nginx-0.0.1-2002-12-11-19:57:54 import diff --git a/src/http/ngx_http_parse_time.c b/src/http/ngx_http_parse_time.c --- 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() -{ - enum { - sw_start = 0, - } state; +#include - state = sw_start; +#define NGX_ERROR -1 + +static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - while () { - switch (state) { +time_t ngx_http_parse_time(char *value, size_t len) +{ + char *p, *end; + int day, month, year, hour, min, sec; + enum { + 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; + + end = value + len; - 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 (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 'M': + month = *(p + 2) == 'r' ? 2 : 4; + break; + + case 'A': + month = *(p + 1) == 'p' ? 3 : 7; + break; + + case 'S': + month = 8; + break; - if (ch >= '0' && ch <= '9') { - day = ch - '0'; - state = sw_day; - 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; + + year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 + + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + p += 4; + } 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++; + + if (*p < '0' || *p > '9') return NGX_ERROR; - case sw_day: - if (ansi && ch == ' ') { - state = sw_hour_first_digit; - break; - } + 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 (ch >= '0' && ch <= '9') { - day = ch - '0'; - state = ansi ? sw_space_before_hour : sw_before_month; - break; - } + 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; - case sw_before_month: - if (ch == ' ') { - rfc822 = 1; - } + 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; + } - if (ch == '-') { - rfc850 = 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; - case sw_space_before_hour: + 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); }