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     if (end - p < 18) {
0053         return NGX_ERROR;
0054         }
0055 
0056     if (fmt != isoc) {
0057         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0058             return NGX_ERROR;
0059         }
0060 
0061         day = (*p - '0') * 10 + *(p + 1) - '0';
0062         p += 2;
0063 
0064         if (*p == ' ') {
0065             if (end - p < 18) {
0066                 return NGX_ERROR;
0067             }
0068             fmt = rfc822;
0069 
0070         } else if (*p == '-') {
0071             fmt = rfc850;
0072 
0073         } else {
0074             return NGX_ERROR;
0075         }
0076 
0077         p++;
0078     }
0079 
0080     switch (*p) {
0081 
0082     case 'J':
0083         month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
0084         break;
0085 
0086     case 'F':
0087         month = 1;
0088         break;
0089 
0090     case 'M':
0091         month = *(p + 2) == 'r' ? 2 : 4;
0092         break;
0093 
0094     case 'A':
0095         month = *(p + 1) == 'p' ? 3 : 7;
0096         break;
0097 
0098     case 'S':
0099         month = 8;
0100         break;
0101 
0102     case 'O':
0103         month = 9;
0104         break;
0105 
0106     case 'N':
0107         month = 10;
0108         break;
0109 
0110     case 'D':
0111         month = 11;
0112         break;
0113 
0114     default:
0115         return NGX_ERROR;
0116     }
0117 
0118     p += 3;
0119 
0120     if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-')) {
0121         return NGX_ERROR;
0122     }
0123 
0124     p++;
0125 
0126     if (fmt == rfc822) {
0127         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
0128             || *(p + 2) < '0' || *(p + 2) > '9'
0129             || *(p + 3) < '0' || *(p + 3) > '9')
0130         {
0131             return NGX_ERROR;
0132         }
0133 
0134         year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
0135                + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
0136         p += 4;
0137 
0138     } else if (fmt == rfc850) {
0139         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0140             return NGX_ERROR;
0141         }
0142 
0143         year = (*p - '0') * 10 + *(p + 1) - '0';
0144         year += (year < 70) ? 2000 : 1900;
0145         p += 2;
0146     }
0147 
0148     if (fmt == isoc) {
0149         if (*p == ' ') {
0150             p++;
0151         }
0152 
0153         if (*p < '0' || *p > '9') {
0154             return NGX_ERROR;
0155         }
0156 
0157         day = *p++ - '0';
0158 
0159         if (*p != ' ') {
0160             if (*p < '0' || *p > '9') {
0161                 return NGX_ERROR;
0162             }
0163 
0164             day = day * 10 + *p++ - '0';
0165         }
0166 
0167         if (end - p < 14) {
0168             return NGX_ERROR;
0169         }
0170     }
0171 
0172     if (*p++ != ' ') {
0173         return NGX_ERROR;
0174     }
0175 
0176     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0177         return NGX_ERROR;
0178     }
0179 
0180     hour = (*p - '0') * 10 + *(p + 1) - '0';
0181     p += 2;
0182 
0183     if (*p++ != ':') {
0184         return NGX_ERROR;
0185     }
0186 
0187     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0188         return NGX_ERROR;
0189     }
0190 
0191     min = (*p - '0') * 10 + *(p + 1) - '0';
0192     p += 2;
0193 
0194     if (*p++ != ':') {
0195         return NGX_ERROR;
0196     }
0197 
0198     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
0199         return NGX_ERROR;
0200     }
0201 
0202     sec = (*p - '0') * 10 + *(p + 1) - '0';
0203 
0204     if (fmt == isoc) {
0205         p += 2;
0206 
0207         if (*p++ != ' ') {
0208             return NGX_ERROR;
0209         }
0210 
0211         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
0212             || *(p + 2) < '0' || *(p + 2) > '9'
0213             || *(p + 3) < '0' || *(p + 3) > '9')
0214         {
0215             return NGX_ERROR;
0216         }
0217 
0218         year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
0219                + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
0220     }
0221 
0222     if (hour > 23 || min > 59 || sec > 59) {
0223         return NGX_ERROR;
0224     }
0225 
0226     if (day == 29 && month == 1) {
0227         if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) {
0228             return NGX_ERROR;
0229         }
0230 
0231     } else if (day > mday[month]) {
0232         return NGX_ERROR;
0233     }
0234 
0235     /*
0236      * shift new year to March 1 and start months from 1 (not 0),
0237      * it is needed for Gauss' formula
0238      */
0239 
0240     if (--month <= 0) {
0241         month += 12;
0242         year -= 1;
0243     }
0244 
0245     /* Gauss' formula for Gregorian days since March 1, 1 BC */
0246 
0247     time = (uint64_t) (
0248             /* days in years including leap years since March 1, 1 BC */
0249 
0250             365 * year + year / 4 - year / 100 + year / 400
0251 
0252             /* days before the month */
0253 
0254             + 367 * month / 12 - 30
0255 
0256             /* days before the day */
0257 
0258             + day - 1
0259 
0260             /*
0261              * 719527 days were between March 1, 1 BC and March 1, 1970,
0262              * 31 and 28 days were in January and February 1970
0263              */
0264 
0265             - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
0266 
0267 #if (NGX_TIME_T_SIZE <= 4)
0268 
0269     if (time > 0x7fffffff) {
0270         return NGX_ERROR;
0271     }
0272 
0273 #endif
0274 
0275     return (time_t) time;
0276 }