view src/http/ngx_http_parse_time.c @ 25:a8b156554dfe

nginx-0.0.1-2002-12-11-19:57:54 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 11 Dec 2002 16:57:54 +0000
parents 77c7629a2627
children 53cb81681040
line wrap: on
line source


#include <time.h>

#define NGX_ERROR  -1

static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

time_t ngx_http_parse_time(char *value, size_t len)
{
    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;

    end = value + len;

    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';
    }

    printf("%d.%d.%d %d:%d:%d\n", day, month + 1, year, hour, min, sec);

    if (hour > 23 || min > 60 || sec > 60)
         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;

    if (--month <= 0) {
       month += 12;
       year -= 1;
    }

    return year / 4 - year / 100 + year / 400
           + 367 * month / 12 + day + year * 365 - 719499;
}

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);
}