mirror of
https://github.com/nginx/nginx.git
synced 2024-12-16 22:47:47 +08:00
288 lines
5.7 KiB
C
288 lines
5.7 KiB
C
|
|
/*
|
|
* Copyright (C) Igor Sysoev
|
|
*/
|
|
|
|
|
|
#include <ngx_config.h>
|
|
#include <ngx_core.h>
|
|
#include <ngx_types.h>
|
|
|
|
|
|
static int 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;
|
|
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;
|
|
|
|
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 0
|
|
printf("%d.%d.%d %d:%d:%d\n", day, month + 1, year, hour, min, sec);
|
|
#endif
|
|
|
|
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;
|
|
}
|
|
|
|
if (sizeof(time_t) <= 4 && year >= 2038) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
/*
|
|
* shift new year to March 1 and start months from 1 (not 0),
|
|
* it's needed for Gauss's formula
|
|
*/
|
|
|
|
if (--month <= 0) {
|
|
month += 12;
|
|
year -= 1;
|
|
}
|
|
|
|
/* Gauss's formula for Grigorian days from 1 March 1 BC */
|
|
|
|
return (365 * year + year / 4 - year / 100 + year / 400
|
|
+ 367 * month / 12 - 31
|
|
+ day
|
|
|
|
/*
|
|
* 719527 days were between March 1, 1 BC and March 1, 1970,
|
|
* 31 and 28 days in January and February 1970
|
|
*/
|
|
|
|
- 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
|
|
}
|
|
|
|
#if 0
|
|
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);
|
|
}
|
|
|
|
#endif
|