# HG changeset patch # User Maxim Dounin # Date 1434044551 -10800 # Node ID 8b6fa4842133eeabff9857f006d02971a0ba8b45 # Parent c61210e2e08169deb7b05ba0774c97652675b3e0 Moved ngx_http_parse_time() to core, renamed accordingly. The function is now called ngx_parse_http_time(), and can be used by any code to parse HTTP-style date and time. In particular, it will be used for OCSP stapling. For compatibility, a macro to map ngx_http_parse_time() to the new name provided for a while. diff -r c61210e2e081 -r 8b6fa4842133 auto/sources --- a/auto/sources Thu Jun 11 20:42:24 2015 +0300 +++ b/auto/sources Thu Jun 11 20:42:31 2015 +0300 @@ -19,6 +19,7 @@ src/core/ngx_queue.h \ src/core/ngx_string.h \ src/core/ngx_parse.h \ + src/core/ngx_parse_time.h \ src/core/ngx_inet.h \ src/core/ngx_file.h \ src/core/ngx_crc.h \ @@ -53,6 +54,7 @@ src/core/ngx_output_chain.c \ src/core/ngx_string.c \ src/core/ngx_parse.c \ + src/core/ngx_parse_time.c \ src/core/ngx_inet.c \ src/core/ngx_file.c \ src/core/ngx_crc32.c \ @@ -303,7 +305,6 @@ src/http/ngx_http_script.c \ src/http/ngx_http_upstream.c \ src/http/ngx_http_upstream_round_robin.c \ - src/http/ngx_http_parse_time.c \ src/http/modules/ngx_http_static_module.c \ src/http/modules/ngx_http_index_module.c \ src/http/modules/ngx_http_chunked_filter_module.c \ diff -r c61210e2e081 -r 8b6fa4842133 src/core/ngx_core.h --- a/src/core/ngx_core.h Thu Jun 11 20:42:24 2015 +0300 +++ b/src/core/ngx_core.h Thu Jun 11 20:42:31 2015 +0300 @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include diff -r c61210e2e081 -r 8b6fa4842133 src/core/ngx_parse_time.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/ngx_parse_time.c Thu Jun 11 20:42:31 2015 +0300 @@ -0,0 +1,276 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +time_t +ngx_parse_http_time(u_char *value, size_t len) +{ + u_char *p, *end; + ngx_int_t month; + ngx_uint_t day, year, hour, min, sec; + uint64_t time; + 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; + + fmt = 0; + end = value + len; + +#if (NGX_SUPPRESS_WARN) + day = 32; + year = 2038; +#endif + + for (p = value; p < end; p++) { + if (*p == ',') { + break; + } + + if (*p == ' ') { + fmt = isoc; + break; + } + } + + for (p++; p < end; p++) + if (*p != ' ') { + 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; + + 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; + } + + 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'; + } + + if (hour > 23 || min > 59 || sec > 59) { + 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; + } + + /* + * shift new year to March 1 and start months from 1 (not 0), + * it is needed for Gauss' formula + */ + + if (--month <= 0) { + month += 12; + year -= 1; + } + + /* Gauss' formula for Gregorian days since March 1, 1 BC */ + + time = (uint64_t) ( + /* days in years including leap years since March 1, 1 BC */ + + 365 * year + year / 4 - year / 100 + year / 400 + + /* days before the month */ + + + 367 * month / 12 - 30 + + /* days before the day */ + + + day - 1 + + /* + * 719527 days were between March 1, 1 BC and March 1, 1970, + * 31 and 28 days were in January and February 1970 + */ + + - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; + +#if (NGX_TIME_T_SIZE <= 4) + + if (time > 0x7fffffff) { + return NGX_ERROR; + } + +#endif + + return (time_t) time; +} diff -r c61210e2e081 -r 8b6fa4842133 src/core/ngx_parse_time.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/ngx_parse_time.h Thu Jun 11 20:42:31 2015 +0300 @@ -0,0 +1,22 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_PARSE_TIME_H_INCLUDED_ +#define _NGX_PARSE_TIME_H_INCLUDED_ + + +#include +#include + + +time_t ngx_parse_http_time(u_char *value, size_t len); + +/* compatibility */ +#define ngx_http_parse_time(value, len) ngx_parse_http_time(value, len) + + +#endif /* _NGX_PARSE_TIME_H_INCLUDED_ */ diff -r c61210e2e081 -r 8b6fa4842133 src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/modules/ngx_http_dav_module.c Thu Jun 11 20:42:31 2015 +0300 @@ -255,7 +255,7 @@ ext.log = r->connection->log; if (r->headers_in.date) { - date = ngx_http_parse_time(r->headers_in.date->value.data, + date = ngx_parse_http_time(r->headers_in.date->value.data, r->headers_in.date->value.len); if (date != NGX_ERROR) { diff -r c61210e2e081 -r 8b6fa4842133 src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/modules/ngx_http_headers_filter_module.c Thu Jun 11 20:42:31 2015 +0300 @@ -498,7 +498,7 @@ } r->headers_out.last_modified_time = - (value->len) ? ngx_http_parse_time(value->data, value->len) : -1; + (value->len) ? ngx_parse_http_time(value->data, value->len) : -1; return NGX_OK; } diff -r c61210e2e081 -r 8b6fa4842133 src/http/modules/ngx_http_not_modified_filter_module.c --- a/src/http/modules/ngx_http_not_modified_filter_module.c Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/modules/ngx_http_not_modified_filter_module.c Thu Jun 11 20:42:31 2015 +0300 @@ -118,7 +118,7 @@ return 0; } - iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data, + iums = ngx_parse_http_time(r->headers_in.if_unmodified_since->value.data, r->headers_in.if_unmodified_since->value.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -148,7 +148,7 @@ return 1; } - ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data, + ims = ngx_parse_http_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, diff -r c61210e2e081 -r 8b6fa4842133 src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/modules/ngx_http_range_filter_module.c Thu Jun 11 20:42:31 2015 +0300 @@ -204,7 +204,7 @@ goto next_filter; } - if_range_time = ngx_http_parse_time(if_range->data, if_range->len); + if_range_time = ngx_parse_http_time(if_range->data, if_range->len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ir:%d lm:%d", diff -r c61210e2e081 -r 8b6fa4842133 src/http/ngx_http.h --- a/src/http/ngx_http.h Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/ngx_http.h Thu Jun 11 20:42:31 2015 +0300 @@ -148,9 +148,6 @@ void ngx_http_clean_header(ngx_http_request_t *r); -time_t ngx_http_parse_time(u_char *value, size_t len); - - ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r); void ngx_http_discarded_request_body_handler(ngx_http_request_t *r); void ngx_http_block_reading(ngx_http_request_t *r); diff -r c61210e2e081 -r 8b6fa4842133 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/ngx_http_core_module.c Thu Jun 11 20:42:31 2015 +0300 @@ -2195,7 +2195,7 @@ return NGX_DECLINED; } - expires = ngx_http_parse_time(e->value.data, e->value.len); + expires = ngx_parse_http_time(e->value.data, e->value.len); if (expires == NGX_ERROR) { return NGX_DECLINED; } @@ -2203,7 +2203,7 @@ d = r->headers_out.date; if (d) { - date = ngx_http_parse_time(d->value.data, d->value.len); + date = ngx_parse_http_time(d->value.data, d->value.len); if (date == NGX_ERROR) { return NGX_DECLINED; } diff -r c61210e2e081 -r 8b6fa4842133 src/http/ngx_http_parse_time.c --- a/src/http/ngx_http_parse_time.c Thu Jun 11 20:42:24 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) Nginx, Inc. - */ - - -#include -#include -#include - - -static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -time_t -ngx_http_parse_time(u_char *value, size_t len) -{ - u_char *p, *end; - ngx_int_t month; - ngx_uint_t day, year, hour, min, sec; - uint64_t time; - 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; - - fmt = 0; - end = value + len; - -#if (NGX_SUPPRESS_WARN) - day = 32; - year = 2038; -#endif - - for (p = value; p < end; p++) { - if (*p == ',') { - break; - } - - if (*p == ' ') { - fmt = isoc; - break; - } - } - - for (p++; p < end; p++) - if (*p != ' ') { - 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; - - 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; - } - - 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'; - } - - if (hour > 23 || min > 59 || sec > 59) { - 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; - } - - /* - * shift new year to March 1 and start months from 1 (not 0), - * it is needed for Gauss' formula - */ - - if (--month <= 0) { - month += 12; - year -= 1; - } - - /* Gauss' formula for Gregorian days since March 1, 1 BC */ - - time = (uint64_t) ( - /* days in years including leap years since March 1, 1 BC */ - - 365 * year + year / 4 - year / 100 + year / 400 - - /* days before the month */ - - + 367 * month / 12 - 30 - - /* days before the day */ - - + day - 1 - - /* - * 719527 days were between March 1, 1 BC and March 1, 1970, - * 31 and 28 days were in January and February 1970 - */ - - - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; - -#if (NGX_TIME_T_SIZE <= 4) - - if (time > 0x7fffffff) { - return NGX_ERROR; - } - -#endif - - return (time_t) time; -} diff -r c61210e2e081 -r 8b6fa4842133 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu Jun 11 20:42:24 2015 +0300 +++ b/src/http/ngx_http_upstream.c Thu Jun 11 20:42:31 2015 +0300 @@ -3731,7 +3731,7 @@ if (u->headers_in.last_modified) { - lm = ngx_http_parse_time(u->headers_in.last_modified->value.data, + lm = ngx_parse_http_time(u->headers_in.last_modified->value.data, u->headers_in.last_modified->value.len); if (lm != NGX_ERROR) { @@ -4128,7 +4128,7 @@ #if (NGX_HTTP_CACHE) if (u->cacheable) { - u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data, + u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, h->value.len); } @@ -4292,7 +4292,7 @@ return NGX_OK; } - expires = ngx_http_parse_time(h->value.data, h->value.len); + expires = ngx_parse_http_time(h->value.data, h->value.len); if (expires == NGX_ERROR || expires < ngx_time()) { u->cacheable = 0;