rfc822_parsedt.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:5k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc.
- ** See COPYING for distribution information.
- */
- /*
- ** $Id: rfc822_parsedt.c,v 1.3 1999/12/06 13:29:49 mrsam Exp $
- */
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- /*
- ** time_t rfc822_parsedate(const char *p)
- **
- ** p - contents of the Date: header, attempt to parse it into a time_t.
- **
- ** returns - time_t, or 0 if the date cannot be parsed
- */
- static unsigned parsedig(const char **p)
- {
- unsigned i=0;
- while (isdigit((int)(unsigned char)**p))
- {
- i=i*10 + **p - '0';
- ++*p;
- }
- return (i);
- }
- static const char * const weekdays[7]={
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- } ;
- static const char * const mnames[13]={
- "Jan", "Feb", "Mar", "Apr",
- "May", "Jun", "Jul", "Aug",
- "Sep", "Oct", "Nov", "Dec", NULL};
- #define leap(y) (
- ((y) % 400) == 0 ||
- (((y) % 4) == 0 && (y) % 100) )
- static unsigned mlength[]={31,28,31,30,31,30,31,31,30,31,30,31};
- #define mdays(m,y) ( (m) != 2 ? mlength[(m)-1] : leap(y) ? 29:28)
- static const char * const zonenames[] = {
- "UT","GMT",
- "EST","EDT",
- "CST","CDT",
- "MST","MDT",
- "PST","PDT",
- "Z",
- "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M",
- "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
- NULL};
- #define ZH(n) ( (n) * 60 * 60 )
- static int zoneoffset[] = {
- 0, 0,
- ZH(-5), ZH(-4),
- ZH(-6), ZH(-5),
- ZH(-7), ZH(-6),
- ZH(-8), ZH(-7),
- 0,
- ZH(-1), ZH(-2), ZH(-3), ZH(-4), ZH(-5), ZH(-6), ZH(-7), ZH(-8), ZH(-9), ZH(-10), ZH(-11), ZH(-12),
- ZH(1), ZH(2), ZH(3), ZH(4), ZH(5), ZH(6), ZH(7), ZH(8), ZH(9), ZH(10), ZH(11), ZH(12) };
- static unsigned parsekey(const char **mon, const char * const *ary)
- {
- unsigned m, j;
- for (m=0; ary[m]; m++)
- {
- for (j=0; ary[m][j]; j++)
- if (tolower(ary[m][j]) != tolower((*mon)[j]))
- break;
- if (!ary[m][j])
- {
- *mon += j;
- return (m+1);
- }
- }
- return (0);
- }
- static int parsetime(const char **t)
- {
- unsigned h,m,s=0;
- if (!isdigit((int)(unsigned char)**t)) return (-1);
- h=parsedig(t);
- if (h > 23) return (-1);
- if (**t != ':') return (-1);
- ++*t;
- if (!isdigit((int)(unsigned char)**t)) return (-1);
- m=parsedig(t);
- if (**t == ':')
- {
- ++*t;
- if (!isdigit((int)(unsigned char)**t)) return (-1);
- s=parsedig(t);
- }
- if (m > 59 || s > 59) return (-1);
- return (h * 60 * 60 + m * 60 + s);
- }
- time_t rfc822_parsedt(const char *rfcdt)
- {
- unsigned day=0, mon=0, year;
- int secs;
- int offset;
- time_t t;
- unsigned y;
- /* Ignore day of the week. Tolerate "Tue, 25 Feb 1997 ... "
- ** without the comma. Tolerate "Feb 25 1997 ...".
- */
- while (!day || !mon)
- {
- if (!*rfcdt) return (0);
- if (isalpha((int)(unsigned char)*rfcdt))
- {
- if (mon) return (0);
- mon=parsekey(&rfcdt, mnames);
- if (!mon)
- while (*rfcdt && isalpha((int)(unsigned char)*rfcdt))
- ++rfcdt;
- continue;
- }
- if (isdigit((int)(unsigned char)*rfcdt))
- {
- if (day) return (0);
- day=parsedig(&rfcdt);
- if (!day) return (0);
- continue;
- }
- ++rfcdt;
- }
- while (*rfcdt && isspace((int)(unsigned char)*rfcdt))
- ++rfcdt;
- if (!isdigit((int)(unsigned char)*rfcdt)) return (0);
- year=parsedig(&rfcdt);
- if (year < 70) year += 2000;
- if (year < 100) year += 1900;
- while (*rfcdt && isspace((int)(unsigned char)*rfcdt))
- ++rfcdt;
- if (day == 0 || mon == 0 || mon > 12 || day > mdays(mon,year))
- return (0);
- secs=parsetime(&rfcdt);
- if (secs < 0) return (0);
- offset=0;
- /* RFC822 sez no parenthesis, but I've seen (EST) */
- while ( *rfcdt )
- {
- if (isalnum((int)(unsigned char)*rfcdt) || *rfcdt == '+' || *rfcdt == '-')
- break;
- ++rfcdt;
- }
- if (isalpha((int)(unsigned char)*rfcdt))
- {
- int n=parsekey(&rfcdt, zonenames);
- if (n > 0) offset= zoneoffset[n-1];
- }
- else
- {
- int sign=1;
- unsigned n;
- switch (*rfcdt) {
- case '-':
- sign= -1;
- case '+':
- ++rfcdt;
- }
- if (isdigit((int)(unsigned char)*rfcdt))
- {
- n=parsedig(&rfcdt);
- if (n > 2359 || (n % 100) > 59) n=0;
- offset = sign * ( (n % 100) * 60 + n / 100 * 60 * 60);
- }
- }
- if (year < 1970) return (0);
- t=0;
- for (y=1970; y<year; y++)
- {
- if ( leap(y) )
- {
- if (year-y >= 4)
- {
- y += 3;
- t += ( 365*3+366 ) * 24 * 60 * 60;
- continue;
- }
- t += 24 * 60 * 60;
- }
- t += 365 * 24 * 60 * 60;
- }
- for (y=1; y < mon; y++)
- t += mdays(y, year) * 24 * 60 * 60;
- return ( t + (day-1) * 24 * 60 * 60 + secs - offset );
- }
- const char *rfc822_mkdt(time_t t)
- {
- static char buf[80];
- struct tm *tmptr=gmtime(&t);
- buf[0]=0;
- if (tmptr)
- {
- sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
- weekdays[tmptr->tm_wday],
- tmptr->tm_mday,
- mnames[tmptr->tm_mon],
- tmptr->tm_year + 1900,
- tmptr->tm_hour,
- tmptr->tm_min,
- tmptr->tm_sec);
- }
- return (buf);
- }