fix date parsing, make text UTF-8

This commit is contained in:
Neale Pickett 2011-08-16 15:16:03 -06:00
parent b58da7211d
commit 03fb0e042c
2 changed files with 176 additions and 58 deletions

View File

@ -2,7 +2,7 @@ CC=gcc
CXX=g++ CXX=g++
#LIBOWFAT=../libowfat/ #LIBOWFAT=../libowfat/
DIET=diet -Os #DIET=diet -Os
CFLAGS=-Os -fomit-frame-pointer CFLAGS=-Os -fomit-frame-pointer
#CFLAGS=-g #CFLAGS=-g

224
httpd.c
View File

@ -660,11 +660,12 @@ static char* header(char* buf,int buflen,const char* hname) {
} }
static char* encoding=0; static char* encoding=0;
static char* mimetype="text/plain"; static char* mimetype="application/octet-stream";
static struct mimeentry { const char* name, *type; } mimetab[] = { static struct mimeentry { const char* name, *type; } mimetab[] = {
{ "html", "text/html" }, { "html", "text/html; charset=UTF-8" },
{ "htm", "text/html" }, { "htm", "text/html; charset=UTF-8" },
{ "txt", "text/plain; charset=UTF-8" },
{ "css", "text/css" }, { "css", "text/css" },
{ "dvi", "application/x-dvi" }, { "dvi", "application/x-dvi" },
{ "ps", "application/postscript" }, { "ps", "application/postscript" },
@ -685,7 +686,6 @@ static struct mimeentry { const char* name, *type; } mimetab[] = {
{ "pac", "application/x-ns-proxy-autoconfig" }, { "pac", "application/x-ns-proxy-autoconfig" },
{ "sig", "application/pgp-signature" }, { "sig", "application/pgp-signature" },
{ "torrent", "application/x-bittorrent" }, { "torrent", "application/x-bittorrent" },
{ "class", "application/octet-stream" },
{ "js", "application/x-javascript" }, { "js", "application/x-javascript" },
{ "tar", "application/x-tar" }, { "tar", "application/x-tar" },
{ "zip", "application/zip" }, { "zip", "application/zip" },
@ -763,58 +763,175 @@ static int findincommalist(const char* needle,const char* haystack) {
return 1; return 1;
} }
static int parsetime(const char*c,struct tm* x) { /*
unsigned long tmp; * timerfc function Copyright 1996, Michiel Boland.
c+=scan_ulong(c,&tmp); x->tm_hour=tmp; * All rights reserved.
if (*c!=':') return -1; ++c; *
c+=scan_ulong(c,&tmp); x->tm_min=tmp; * Redistribution and use in source and binary forms, with or
if (*c!=':') return -1; ++c; * without modification, are permitted provided that the following
c+=scan_ulong(c,&tmp); x->tm_sec=tmp; * conditions are met:
if (*c!=' ') return -1; *
return 0; * 1. Redistributions of source code must retain the above
} * copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
static time_t timerfc(const char *s)
{
static const int daytab[2][12] = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
};
unsigned sec, min, hour, day, mon, year;
char month[3];
int c;
unsigned n;
char flag;
char state;
char isctime;
enum { D_START, D_END, D_MON, D_DAY, D_YEAR, D_HOUR, D_MIN, D_SEC };
static time_t parsedate(const char*c) { sec = 60;
struct tm x; min = 60;
int i; hour = 24;
unsigned long tmp; day = 32;
if (!c) return (time_t)-1; year = 1969;
/* "Sun, 06 Nov 1994 08:49:37 GMT", isctime = 0;
* "Sunday, 06-Nov-94 08:49:37 GMT" and month[0] = 0;
* "Sun Nov 6 08:49:37 1994" */ state = D_START;
if (c[3]==',') c+=5; else n = 0;
if (c[6]==',') c+=8; else { flag = 1;
c+=4; do {
for (i=0; i<12; ++i) { c = *s++;
// fprintf(stderr,"comparing %s to %.3s\n",c,months+i*3); switch (state) {
if (!strncasecmp(c,months+i*3,3)) { case D_START:
x.tm_mon=i; break; if (c == ' ') {
state = D_MON;
isctime = 1;
} else if (c == ',')
state = D_DAY;
break;
case D_MON:
if (isalpha(c)) {
if (n < 3)
month[n++] = c;
} else {
if (n < 3)
return -1;
n = 0;
state = isctime ? D_DAY : D_YEAR;
} }
break;
case D_DAY:
if (c == ' ' && flag)
;
else if (isdigit(c)) {
flag = 0;
n = 10 * n + (c - '0');
} else {
day = n;
n = 0;
state = isctime ? D_HOUR : D_MON;
} }
c+=4; if (*c==' ') ++c; break;
c+=scan_ulong(c,&tmp); x.tm_mday=tmp; case D_YEAR:
++c; if (isdigit(c))
if (parsetime(c,&x)) return (time_t)-1; n = 10 * n + (c - '0');
c+=9; else {
c+=scan_ulong(c,&tmp); x.tm_year=tmp-1900; year = n;
goto done; n = 0;
state = isctime ? D_END : D_HOUR;
} }
c+=scan_ulong(c,&tmp); x.tm_mday=tmp; break;
++c; case D_HOUR:
for (i=0; i<12; ++i) if (isdigit(c))
if (!strncasecmp(c,months+i*3,3)) { n = 10 * n + (c - '0');
x.tm_mon=i; break; else {
hour = n;
n = 0;
state = D_MIN;
} }
c+=4; break;
c+=scan_ulong(c,&tmp); case D_MIN:
if (tmp>1000) x.tm_year=tmp-1900; else if (isdigit(c))
if (tmp<70) x.tm_year=tmp+100; else n = 10 * n + (c - '0');
x.tm_year=tmp; else {
++c; min = n;
if (parsetime(c,&x)) return (time_t)-1; n = 0;
done: state = D_SEC;
x.tm_wday=x.tm_yday=x.tm_isdst=0; }
return mktime(&x); break;
case D_SEC:
if (isdigit(c))
n = 10 * n + (c - '0');
else {
sec = n;
n = 0;
state = isctime ? D_YEAR : D_END;
}
break;
}
} while (state != D_END && c);
switch (month[0]) {
case 'A':
mon = (month[1] == 'p') ? 4 : 8;
break;
case 'D':
mon = 12;
break;
case 'F':
mon = 2;
break;
case 'J':
mon = (month[1] == 'a') ? 1 : ((month[2] == 'l') ? 7 : 6);
break;
case 'M':
mon = (month[2] == 'r') ? 3 : 5;
break;
case 'N':
mon = 11;
break;
case 'O':
mon = 10;
break;
case 'S':
mon = 9;
break;
default:
return -1;
}
if (year <= 100)
year += (year < 70) ? 2000 : 1900;
--mon;
--day;
if (sec >= 60 || min >= 60 || hour >= 60 || day >= 31)
return -1;
if (year < 1970)
return 0;
return sec + 60L * (min + 60L * (hour + 24L * ( day +
daytab[year % 4 == 0 && (year % 100 || year % 400 == 0)][mon] +
365L * (year - 1970L) + ((year - 1969L) >> 2))));
} }
static struct stat st; static struct stat st;
@ -850,8 +967,9 @@ ok:
if (S_ISDIR(st.st_mode)) goto bad; if (S_ISDIR(st.st_mode)) goto bad;
/* see if the peer accepts MIME type */ /* see if the peer accepts MIME type */
/* see if the document has been changed */ /* see if the document has been changed */
ims=parsedate(header(buf,buflen,"If-Modified-Since")); ims=timerfc(header(buf,buflen,"If-Modified-Since"));
if (ims!=(time_t)-1 && st.st_mtime<=ims) { retcode=304; goto bad; } //fprintf(stderr, "ims: %lu %lu %d\n", ims, st.st_mtime, st.st_mtime - ims);
if ((ims!=(time_t)-1) && (st.st_mtime<=ims)) { retcode=304; goto bad; }
rangestart=0; rangeend=st.st_size; rangestart=0; rangeend=st.st_size;
if ((accept=header(buf,buflen,"Range"))) { if ((accept=header(buf,buflen,"Range"))) {
/* format: "bytes=17-23", "bytes=23-" */ /* format: "bytes=17-23", "bytes=23-" */