Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <httpd.h>

/*
 * print dates in the format
 * Wkd, DD Mon YYYY HH:MM:SS GMT
 * parse dates of formats
 * Wkd, DD Mon YYYY HH:MM:SS GMT
 * Weekday, DD-Mon-YY HH:MM:SS GMT
 * Wkd Mon ( D|DD) HH:MM:SS YYYY
 * plus anything similar
 */
static char *
weekdayname[7] =
{
        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
static char *
wdayname[7] =
{
        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

static char *
monname[12] =
{
        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

static  int     dateindex(char*, char**, int);

static int
dtolower(int c)
{
        if(c >= 'A' && c <= 'Z')
                return c - 'A' + 'a';
        return c;
}

static int
disalpha(int c)
{
        return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
}

static int
disdig(int c)
{
        return c >= '0' && c <= '9';
}

int
hdatefmt(Fmt *f)
{
        Tm *tm;
        ulong t;

        t = va_arg(f->args, ulong);
        tm = gmtime(t);
        return fmtprint(f, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
                wdayname[tm->wday], tm->mday, monname[tm->mon], tm->year+1900,
                tm->hour, tm->min, tm->sec);
}

static char*
dateword(char *date, char *buf)
{
        char *p;
        int c;

        p = buf;
        while(!disalpha(c = *date) && !disdig(c) && c)
                date++;
        while(disalpha(c = *date)){
                if(p - buf < 30)
                        *p++ = dtolower(c);
                date++;
        }
        *p = 0;
        return date;
}

static int
datenum(char **d)
{
        char *date;
        int c, n;

        date = *d;
        while(!disdig(c = *date) && c)
                date++;
        if(c == 0){
                *d = date;
                return -1;
        }
        n = 0;
        while(disdig(c = *date)){
                n = n * 10 + c - '0';
                date++;
        }
        *d = date;
        return n;
}

/*
 * parse a date and return the seconds since the epoch
 * return 0 for a failure
 */
ulong
hdate2sec(char *date)
{
        Tm tm;
        char buf[32];

        /*
         * Weekday|Wday
         */
        date = dateword(date, buf);
        tm.wday = dateindex(buf, wdayname, 7);
        if(tm.wday < 0)
                tm.wday = dateindex(buf, weekdayname, 7);
        if(tm.wday < 0)
                return 0;

        /*
         * check for the two major formats
         */
        date = dateword(date, buf);
        tm.mon = dateindex(buf, monname, 12);
        if(tm.mon >= 0){
                /*
                 * MM
                 */
                tm.mday = datenum(&date);
                if(tm.mday < 1 || tm.mday > 31)
                        return 0;

                /*
                 * HH:MM:SS
                 */
                tm.hour = datenum(&date);
                if(tm.hour < 0 || tm.hour >= 24)
                        return 0;
                tm.min = datenum(&date);
                if(tm.min < 0 || tm.min >= 60)
                        return 0;
                tm.sec = datenum(&date);
                if(tm.sec < 0 || tm.sec >= 60)
                        return 0;

                /*
                 * YYYY
                 */
                tm.year = datenum(&date);
                if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
                        return 0;
                if(tm.year >= 1970)
                        tm.year -= 1900;
        }else{
                /*
                 * MM-Mon-(YY|YYYY)
                 */
                tm.mday = datenum(&date);
                if(tm.mday < 1 || tm.mday > 31)
                        return 0;
                date = dateword(date, buf);
                tm.mon = dateindex(buf, monname, 12);
                if(tm.mon < 0 || tm.mon >= 12)
                        return 0;
                tm.year = datenum(&date);
                if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
                        return 0;
                if(tm.year >= 1970)
                        tm.year -= 1900;

                /*
                 * HH:MM:SS
                 */
                tm.hour = datenum(&date);
                if(tm.hour < 0 || tm.hour >= 24)
                        return 0;
                tm.min = datenum(&date);
                if(tm.min < 0 || tm.min >= 60)
                        return 0;
                tm.sec = datenum(&date);
                if(tm.sec < 0 || tm.sec >= 60)
                        return 0;

                /*
                 * timezone
                 */
                dateword(date, buf);
                if(strncmp(buf, "gmt", 3) != 0)
                        return 0;
        }

        strcpy(tm.zone, "GMT");
        tm.tzoff = 0;
        tm.yday = 0;
        return tm2sec(&tm);
}

static int
dateindex(char *d, char **tab, int n)
{
        int i;

        for(i = 0; i < n; i++)
                if(cistrcmp(d, tab[i]) == 0)
                        return i;
        return -1;
}