src/http/ngx_http_parse_time.c - nginx-1.7.10

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. static ngx_uint_t  mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

  9. time_t
  10. ngx_http_parse_time(u_char *value, size_t len)
  11. {
  12.     u_char      *p, *end;
  13.     ngx_int_t    month;
  14.     ngx_uint_t   day, year, hour, min, sec;
  15.     uint64_t     time;
  16.     enum {
  17.         no = 0,
  18.         rfc822,   /* Tue, 10 Nov 2002 23:50:13   */
  19.         rfc850,   /* Tuesday, 10-Dec-02 23:50:13 */
  20.         isoc      /* Tue Dec 10 23:50:13 2002    */
  21.     } fmt;

  22.     fmt = 0;
  23.     end = value + len;

  24. #if (NGX_SUPPRESS_WARN)
  25.     day = 32;
  26.     year = 2038;
  27. #endif

  28.     for (p = value; p < end; p++) {
  29.         if (*p == ',') {
  30.             break;
  31.         }

  32.         if (*p == ' ') {
  33.             fmt = isoc;
  34.             break;
  35.         }
  36.     }

  37.     for (p++; p < end; p++)
  38.         if (*p != ' ') {
  39.             break;
  40.         }

  41.     if (end - p < 18) {
  42.         return NGX_ERROR;
  43.         }

  44.     if (fmt != isoc) {
  45.         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  46.             return NGX_ERROR;
  47.         }

  48.         day = (*p - '0') * 10 + *(p + 1) - '0';
  49.         p += 2;

  50.         if (*p == ' ') {
  51.             if (end - p < 18) {
  52.                 return NGX_ERROR;
  53.             }
  54.             fmt = rfc822;

  55.         } else if (*p == '-') {
  56.             fmt = rfc850;

  57.         } else {
  58.             return NGX_ERROR;
  59.         }

  60.         p++;
  61.     }

  62.     switch (*p) {

  63.     case 'J':
  64.         month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
  65.         break;

  66.     case 'F':
  67.         month = 1;
  68.         break;

  69.     case 'M':
  70.         month = *(p + 2) == 'r' ? 2 : 4;
  71.         break;

  72.     case 'A':
  73.         month = *(p + 1) == 'p' ? 3 : 7;
  74.         break;

  75.     case 'S':
  76.         month = 8;
  77.         break;

  78.     case 'O':
  79.         month = 9;
  80.         break;

  81.     case 'N':
  82.         month = 10;
  83.         break;

  84.     case 'D':
  85.         month = 11;
  86.         break;

  87.     default:
  88.         return NGX_ERROR;
  89.     }

  90.     p += 3;

  91.     if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-')) {
  92.         return NGX_ERROR;
  93.     }

  94.     p++;

  95.     if (fmt == rfc822) {
  96.         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
  97.             || *(p + 2) < '0' || *(p + 2) > '9'
  98.             || *(p + 3) < '0' || *(p + 3) > '9')
  99.         {
  100.             return NGX_ERROR;
  101.         }

  102.         year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
  103.                + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
  104.         p += 4;

  105.     } else if (fmt == rfc850) {
  106.         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  107.             return NGX_ERROR;
  108.         }

  109.         year = (*p - '0') * 10 + *(p + 1) - '0';
  110.         year += (year < 70) ? 2000 : 1900;
  111.         p += 2;
  112.     }

  113.     if (fmt == isoc) {
  114.         if (*p == ' ') {
  115.             p++;
  116.         }

  117.         if (*p < '0' || *p > '9') {
  118.             return NGX_ERROR;
  119.         }

  120.         day = *p++ - '0';

  121.         if (*p != ' ') {
  122.             if (*p < '0' || *p > '9') {
  123.                 return NGX_ERROR;
  124.             }

  125.             day = day * 10 + *p++ - '0';
  126.         }

  127.         if (end - p < 14) {
  128.             return NGX_ERROR;
  129.         }
  130.     }

  131.     if (*p++ != ' ') {
  132.         return NGX_ERROR;
  133.     }

  134.     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  135.         return NGX_ERROR;
  136.     }

  137.     hour = (*p - '0') * 10 + *(p + 1) - '0';
  138.     p += 2;

  139.     if (*p++ != ':') {
  140.         return NGX_ERROR;
  141.     }

  142.     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  143.         return NGX_ERROR;
  144.     }

  145.     min = (*p - '0') * 10 + *(p + 1) - '0';
  146.     p += 2;

  147.     if (*p++ != ':') {
  148.         return NGX_ERROR;
  149.     }

  150.     if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  151.         return NGX_ERROR;
  152.     }

  153.     sec = (*p - '0') * 10 + *(p + 1) - '0';

  154.     if (fmt == isoc) {
  155.         p += 2;

  156.         if (*p++ != ' ') {
  157.             return NGX_ERROR;
  158.         }

  159.         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
  160.             || *(p + 2) < '0' || *(p + 2) > '9'
  161.             || *(p + 3) < '0' || *(p + 3) > '9')
  162.         {
  163.             return NGX_ERROR;
  164.         }

  165.         year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
  166.                + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
  167.     }

  168.     if (hour > 23 || min > 59 || sec > 59) {
  169.          return NGX_ERROR;
  170.     }

  171.     if (day == 29 && month == 1) {
  172.         if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) {
  173.             return NGX_ERROR;
  174.         }

  175.     } else if (day > mday[month]) {
  176.         return NGX_ERROR;
  177.     }

  178.     /*
  179.      * shift new year to March 1 and start months from 1 (not 0),
  180.      * it is needed for Gauss' formula
  181.      */

  182.     if (--month <= 0) {
  183.         month += 12;
  184.         year -= 1;
  185.     }

  186.     /* Gauss' formula for Gregorian days since March 1, 1 BC */

  187.     time = (uint64_t) (
  188.             /* days in years including leap years since March 1, 1 BC */

  189.             365 * year + year / 4 - year / 100 + year / 400

  190.             /* days before the month */

  191.             + 367 * month / 12 - 30

  192.             /* days before the day */

  193.             + day - 1

  194.             /*
  195.              * 719527 days were between March 1, 1 BC and March 1, 1970,
  196.              * 31 and 28 days were in January and February 1970
  197.              */

  198.             - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;

  199. #if (NGX_TIME_T_SIZE <= 4)

  200.     if (time > 0x7fffffff) {
  201.         return NGX_ERROR;
  202.     }

  203. #endif

  204.     return (time_t) time;
  205. }