From 9e85dc61a03f83e9482e496d181297dceb21b6c6 Mon Sep 17 00:00:00 2001 From: leitner Date: Sun, 27 Apr 2003 17:11:50 +0000 Subject: [PATCH] add scan_httpdate --- CHANGES | 2 +- scan.h | 10 ++++++++ scan/scan_httpdate.3 | 15 +++++++++++ scan/scan_httpdate.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ test/fmt_httpdate.c | 10 +++++++- 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 scan/scan_httpdate.3 create mode 100644 scan/scan_httpdate.c diff --git a/CHANGES b/CHANGES index cf9365c..67120c8 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ add stralloc versions of textcode API (Kai Ruemmler) add html to textcode ('<' to '<' etc) add fmt_human and fmt_humank (format numbers ala ls -H/-h) - add fmt_httpdate + add fmt_httpdate and scan_httpdate 0.14: avoid bus errors in byte_copy diff --git a/scan.h b/scan.h index be8fbae..41a62f2 100644 --- a/scan.h +++ b/scan.h @@ -1,6 +1,8 @@ #ifndef SCAN_H #define SCAN_H +#include + #ifdef __dietlibc__ #include #endif @@ -58,4 +60,12 @@ extern unsigned int scan_charsetnskip(const char *in,const char *charset,unsigne * charset (ASCIIZ string) for all 0<=i<=n */ extern unsigned int scan_noncharsetnskip(const char *in,const char *charset,unsigned int limit) __pure__; +/* try to parse ASCII GMT date; does not understand time zones. */ +/* example dates: + * "Sun, 06 Nov 1994 08:49:37 GMT" + * "Sunday, 06-Nov-94 08:49:37 GMT" + * "Sun Nov 6 08:49:37 1994" + */ +extern unsigned int scan_httpdate(const char *in,time_t *t) __pure__; + #endif diff --git a/scan/scan_httpdate.3 b/scan/scan_httpdate.3 new file mode 100644 index 0000000..e14271d --- /dev/null +++ b/scan/scan_httpdate.3 @@ -0,0 +1,15 @@ +.TH scan_httpdate 3 +.SH NAME +scan_httpdate \- parse a HTTP date +.SH SYNTAX +.B #include + +int \fBscan_httpdate\fP(const char *\fIsrc\fR,time_t *\fIdest\fR); +.SH DESCRIPTION +scan_httpdate parses a date as defined in the HTTP standard into a +time_t. It returns the number of bytes read from \fIsrc\fR (0 for parse +error). + +The only supported time zone is GMT. +.SH "SEE ALSO" +fmt_httpdate(3) diff --git a/scan/scan_httpdate.c b/scan/scan_httpdate.c new file mode 100644 index 0000000..4ead698 --- /dev/null +++ b/scan/scan_httpdate.c @@ -0,0 +1,59 @@ +#include "scan.h" +#include "byte.h" +#include "case.h" +#include + +static int parsetime(const char*c,struct tm* x) { + unsigned long tmp; + c+=scan_ulong(c,&tmp); x->tm_hour=tmp; + if (*c!=':') return -1; ++c; + c+=scan_ulong(c,&tmp); x->tm_min=tmp; + if (*c!=':') return -1; ++c; + c+=scan_ulong(c,&tmp); x->tm_sec=tmp; + if (*c!=' ') return -1; + return 0; +} + +unsigned int scan_httpdate(const char *in,time_t *t) { + struct tm x; + int i; + unsigned long tmp; + const char* c; + static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + if (!(c=in)) return 0; + if (c[3]==',') c+=5; else + if (c[6]==',') c+=8; else { + c+=4; + for (i=0; i<12; ++i) { + if (case_equalb(c,3,months+i*3)) { + x.tm_mon=i; break; + } + } + c+=4; if (*c==' ') ++c; + c+=scan_ulong(c,&tmp); x.tm_mday=tmp; + ++c; + if (parsetime(c,&x)) return 0; + c+=9; + c+=scan_ulong(c,&tmp); x.tm_year=tmp-1900; + goto done; + } + c+=scan_ulong(c,&tmp); x.tm_mday=tmp; + ++c; + for (i=0; i<12; ++i) + if (case_equalb(c,3,months+i*3)) { + x.tm_mon=i; break; + } + c+=4; + c+=scan_ulong(c,&tmp); + if (tmp>1000) x.tm_year=tmp-1900; else + if (tmp<70) x.tm_year=tmp+100; else + x.tm_year=tmp; + ++c; + if (parsetime(c,&x)) return 0; + c+=9; + if (byte_equal(c,3,"GMT")) c+=3; +done: + x.tm_wday=x.tm_yday=x.tm_isdst=0; + *t=mktime(&x); + return c-in; +} diff --git a/test/fmt_httpdate.c b/test/fmt_httpdate.c index 80ba788..497433d 100644 --- a/test/fmt_httpdate.c +++ b/test/fmt_httpdate.c @@ -1,8 +1,16 @@ #include +#include #include main() { char buf[100]; - buffer_put(buffer_1,buf,fmt_httpdate(buf,time(0))); + time_t s,t; + buffer_put(buffer_1,buf,fmt_httpdate(buf,time(&s))); + buffer_putnlflush(buffer_1); + buffer_puts(buffer_1,buf+scan_httpdate(buf,&t)); + buffer_putnlflush(buffer_1); + buffer_putulong(buffer_1,s); + buffer_puts(buffer_1," vs. "); + buffer_putulong(buffer_1,t); buffer_putnlflush(buffer_1); }