Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 
0011 
0012 static ngx_uint_t  mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
0013 
0014 time_t
0015 ngx_parse_http_time(u_char *value, size_t len)
0016 {
0017     u_char      *p, *end;
0018     ngx_int_t    month;
0019     ngx_uint_t   day, year, hour, min, sec;
0020     uint64_t     time;
0021     enum {
0022         no = 0,
0023         rfc822,   /* Tue, 10 Nov 2002 23:50:13   */
0024         rfc850,   /* Tuesday, 10-Dec-02 23:50:13 */
0025         isoc      /* Tue Dec 10 23:50:13 2002    */
0026     } fmt;
0027 
0028     fmt = 0;
0029     end = value + len;
0030 
0031 #if (NGX_SUPPRESS_WARN)
0032     day = 32;
0033     year = 2038;
0034 #endif
0035 
0036     for (p = value; p < end; p++) {
0037         if (*p == ',') {
0038             break;
0039         }
0040 
0041         if (*p == ' ') {
0042             fmt = isoc;
0043             break;
0044         }
0045     }
0046 
0047     for (p++; p < end; p++) {
0048         if (*p != ' ') {
0049             break;
0050         }
0051     }
0052 
0053     if (end - p < 18) {
0054         return NGX_ERROR;
0055     }
0056 
0057     if (fmt != isoc) {
0058         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0059             return NGX_ERROR;
0060         }
0061 
0062         day = (*p - '0') * 10 + (*(p + 1) - '0');
0063         p += 2;
0064 
0065         if (*p == ' ') {
0066             if (end - p < 18) {
0067                 return NGX_ERROR;
0068             }
0069             fmt = rfc822;
0070 
0071         } else if (*p == '-') {
0072             fmt = rfc850;
0073 
0074         } else {
0075             return NGX_ERROR;
0076         }
0077 
0078         p++;
0079     }
0080 
0081     switch (*p) {
0082 
0083     case 'J':
0084         month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
0085         break;
0086 
0087     case 'F':
0088         month = 1;
0089         break;
0090 
0091     case 'M':
0092         month = *(p + 2) == 'r' ? 2 : 4;
0093         break;
0094 
0095     case 'A':
0096         month = *(p + 1) == 'p' ? 3 : 7;
0097         break;
0098 
0099     case 'S':
0100         month = 8;
0101         break;
0102 
0103     case 'O':
0104         month = 9;
0105         break;
0106 
0107     case 'N':
0108         month = 10;
0109         break;
0110 
0111     case 'D':
0112         month = 11;
0113         break;
0114 
0115     default:
0116         return NGX_ERROR;
0117     }
0118 
0119     p += 3;
0120 
0121     if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-')) {
0122         return NGX_ERROR;
0123     }
0124 
0125     p++;
0126 
0127     if (fmt == rfc822) {
0128         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
0129             || *(p + 2) < '0' || *(p + 2) > '9'
0130             || *(p + 3) < '0' || *(p + 3) > '9')
0131         {
0132             return NGX_ERROR;
0133         }
0134 
0135         year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
0136                + (*(p + 2) - '0') * 10 + (*(p + 3) - '0');
0137         p += 4;
0138 
0139     } else if (fmt == rfc850) {
0140         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0141             return NGX_ERROR;
0142         }
0143 
0144         year = (*p - '0') * 10 + (*(p + 1) - '0');
0145         year += (year < 70) ? 2000 : 1900;
0146         p += 2;
0147     }
0148 
0149     if (fmt == isoc) {
0150         if (*p == ' ') {
0151             p++;
0152         }
0153 
0154         if (*p < '0' || *p > '9') {
0155             return NGX_ERROR;
0156         }
0157 
0158         day = *p++ - '0';
0159 
0160         if (*p != ' ') {
0161             if (*p < '0' || *p > '9') {
0162                 return NGX_ERROR;
0163             }
0164 
0165             day = day * 10 + (*p++ - '0');
0166         }
0167 
0168         if (end - p < 14) {
0169             return NGX_ERROR;
0170         }
0171     }
0172 
0173     if (*p++ != ' ') {
0174         return NGX_ERROR;
0175     }
0176 
0177     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0178         return NGX_ERROR;
0179     }
0180 
0181     hour = (*p - '0') * 10 + (*(p + 1) - '0');
0182     p += 2;
0183 
0184     if (*p++ != ':') {
0185         return NGX_ERROR;
0186     }
0187 
0188     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0189         return NGX_ERROR;
0190     }
0191 
0192     min = (*p - '0') * 10 + (*(p + 1) - '0');
0193     p += 2;
0194 
0195     if (*p++ != ':') {
0196         return NGX_ERROR;
0197     }
0198 
0199     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0200         return NGX_ERROR;
0201     }
0202 
0203     sec = (*p - '0') * 10 + (*(p + 1) - '0');
0204 
0205     if (fmt == isoc) {
0206         p += 2;
0207 
0208         if (*p++ != ' ') {
0209             return NGX_ERROR;
0210         }
0211 
0212         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
0213             || *(p + 2) < '0' || *(p + 2) > '9'
0214             || *(p + 3) < '0' || *(p + 3) > '9')
0215         {
0216             return NGX_ERROR;
0217         }
0218 
0219         year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
0220                + (*(p + 2) - '0') * 10 + (*(p + 3) - '0');
0221     }
0222 
0223     if (hour > 23 || min > 59 || sec > 59) {
0224         return NGX_ERROR;
0225     }
0226 
0227     if (day == 29 && month == 1) {
0228         if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) {
0229             return NGX_ERROR;
0230         }
0231 
0232     } else if (day > mday[month]) {
0233         return NGX_ERROR;
0234     }
0235 
0236     /*
0237      * shift new year to March 1 and start months from 1 (not 0),
0238      * it is needed for Gauss' formula
0239      */
0240 
0241     if (--month <= 0) {
0242         month += 12;
0243         year -= 1;
0244     }
0245 
0246     /* Gauss' formula for Gregorian days since March 1, 1 BC */
0247 
0248     time = (uint64_t) (
0249             /* days in years including leap years since March 1, 1 BC */
0250 
0251             365 * year + year / 4 - year / 100 + year / 400
0252 
0253             /* days before the month */
0254 
0255             + 367 * month / 12 - 30
0256 
0257             /* days before the day */
0258 
0259             + day - 1
0260 
0261             /*
0262              * 719527 days were between March 1, 1 BC and March 1, 1970,
0263              * 31 and 28 days were in January and February 1970
0264              */
0265 
0266             - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
0267 
0268 #if (NGX_TIME_T_SIZE <= 4)
0269 
0270     if (time > 0x7fffffff) {
0271         return NGX_ERROR;
0272     }
0273 
0274 #endif
0275 
0276     return (time_t) time;
0277 }