diff src/http/ngx_http_parse_time.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children 7ca9bdc82b3f
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_parse_time.c
@@ -0,0 +1,287 @@
+
+/*
+ * 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