xref: /plan9/sys/src/cmd/ip/httpd/content.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include "httpd.h"
580ee5cbfSDavid du Colombier #include "httpsrv.h"
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier typedef struct Suffix	Suffix;
87dd7cddfSDavid du Colombier struct Suffix
97dd7cddfSDavid du Colombier {
107dd7cddfSDavid du Colombier 	Suffix	*next;
117dd7cddfSDavid du Colombier 	char	*suffix;
127dd7cddfSDavid du Colombier 	char	*generic;
137dd7cddfSDavid du Colombier 	char	*specific;
147dd7cddfSDavid du Colombier 	char	*encoding;
157dd7cddfSDavid du Colombier };
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier Suffix	*suffixes = nil;
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier static	Suffix*			parsesuffix(char*, Suffix*);
207dd7cddfSDavid du Colombier static	char*			skipwhite(char*);
2180ee5cbfSDavid du Colombier static	HContents		suffixclass(char*);
227dd7cddfSDavid du Colombier static	char*			towhite(char*);
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier int
updateQid(int fd,Qid * q)257dd7cddfSDavid du Colombier updateQid(int fd, Qid *q)
267dd7cddfSDavid du Colombier {
27*9a747e4fSDavid du Colombier 	Dir *dir;
28*9a747e4fSDavid du Colombier 	Qid dq;
297dd7cddfSDavid du Colombier 
30*9a747e4fSDavid du Colombier 	dir = dirfstat(fd);
31*9a747e4fSDavid du Colombier 	if(dir == nil)
327dd7cddfSDavid du Colombier 		sysfatal("can't dirfstat");
33*9a747e4fSDavid du Colombier 	dq = dir->qid;
34*9a747e4fSDavid du Colombier 	free(dir);
35*9a747e4fSDavid du Colombier 	if(q->path == dq.path && q->vers == dq.vers && q->type == dq.type)
367dd7cddfSDavid du Colombier 		return 0;
37*9a747e4fSDavid du Colombier 	*q = dq;
387dd7cddfSDavid du Colombier 	return 1;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier void
contentinit(void)427dd7cddfSDavid du Colombier contentinit(void)
437dd7cddfSDavid du Colombier {
447dd7cddfSDavid du Colombier 	static Biobuf *b = nil;
457dd7cddfSDavid du Colombier 	static Qid qid;
467dd7cddfSDavid du Colombier 	char *file, *s;
477dd7cddfSDavid du Colombier 	Suffix *this;
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier 	file = "/sys/lib/mimetype";
507dd7cddfSDavid du Colombier 	if(b == nil){ /* first time */
517dd7cddfSDavid du Colombier 		b = Bopen(file, OREAD);
527dd7cddfSDavid du Colombier 		if(b == nil)
537dd7cddfSDavid du Colombier 			sysfatal("can't read from %s", file);
547dd7cddfSDavid du Colombier 	}
557dd7cddfSDavid du Colombier 	if(updateQid(Bfildes(b), &qid) == 0)
567dd7cddfSDavid du Colombier 		return;
577dd7cddfSDavid du Colombier 	Bseek(b, 0, 0);
587dd7cddfSDavid du Colombier 	while(suffixes!=nil){
597dd7cddfSDavid du Colombier 		this = suffixes;
607dd7cddfSDavid du Colombier 		suffixes = suffixes->next;
617dd7cddfSDavid du Colombier 		free(this->suffix);
627dd7cddfSDavid du Colombier 		free(this->generic);
637dd7cddfSDavid du Colombier 		free(this->specific);
647dd7cddfSDavid du Colombier 		free(this->encoding);
657dd7cddfSDavid du Colombier 		free(this);
667dd7cddfSDavid du Colombier 	}
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier 	while((s = Brdline(b, '\n')) != nil){
697dd7cddfSDavid du Colombier 		s[Blinelen(b) - 1] = 0;
707dd7cddfSDavid du Colombier 		suffixes = parsesuffix(s, suffixes);
717dd7cddfSDavid du Colombier 	}
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier static Suffix*
parsesuffix(char * line,Suffix * suffix)757dd7cddfSDavid du Colombier parsesuffix(char *line, Suffix *suffix)
767dd7cddfSDavid du Colombier {
777dd7cddfSDavid du Colombier 	Suffix *s;
787dd7cddfSDavid du Colombier 	char *p, *fields[5];
797dd7cddfSDavid du Colombier 	int i, nf;
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	p = strchr(line, '#');
827dd7cddfSDavid du Colombier 	if(p != nil)
837dd7cddfSDavid du Colombier 		*p = '\0';
847dd7cddfSDavid du Colombier 	nf = tokenize(line, fields, 5);
857dd7cddfSDavid du Colombier 	for(i = 0; i < 4; i++)
8659cc4ca5SDavid du Colombier 		if(i >= nf || fields[i][0] == '-')
877dd7cddfSDavid du Colombier 			fields[i] = nil;
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier 	if(fields[2] == nil)
907dd7cddfSDavid du Colombier 		fields[1] = nil;
917dd7cddfSDavid du Colombier 	if(fields[1] == nil && fields[3] == nil)
927dd7cddfSDavid du Colombier 		return suffix;
93*9a747e4fSDavid du Colombier 	if(fields[0] == nil)
94*9a747e4fSDavid du Colombier 		return suffix;
957dd7cddfSDavid du Colombier 
967dd7cddfSDavid du Colombier 	s = ezalloc(sizeof *s);
977dd7cddfSDavid du Colombier 	s->next = suffix;
987dd7cddfSDavid du Colombier 	s->suffix = estrdup(fields[0]);
997dd7cddfSDavid du Colombier 	if(fields[1] != nil){
1007dd7cddfSDavid du Colombier 		s->generic = estrdup(fields[1]);
1017dd7cddfSDavid du Colombier 		s->specific = estrdup(fields[2]);
1027dd7cddfSDavid du Colombier 	}
1037dd7cddfSDavid du Colombier 	if(fields[3] != nil)
1047dd7cddfSDavid du Colombier 		s->encoding = estrdup(fields[3]);
1057dd7cddfSDavid du Colombier 	return s;
1067dd7cddfSDavid du Colombier }
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier /*
1097dd7cddfSDavid du Colombier  * classify by file name extensions
1107dd7cddfSDavid du Colombier  */
11180ee5cbfSDavid du Colombier HContents
uriclass(HConnect * hc,char * name)11280ee5cbfSDavid du Colombier uriclass(HConnect *hc, char *name)
1137dd7cddfSDavid du Colombier {
11480ee5cbfSDavid du Colombier 	HContents conts;
1157dd7cddfSDavid du Colombier 	Suffix *s;
11680ee5cbfSDavid du Colombier 	HContent *type, *enc;
117*9a747e4fSDavid du Colombier 	char *buf, *p;
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier 	type = nil;
1207dd7cddfSDavid du Colombier 	enc = nil;
1217dd7cddfSDavid du Colombier 	if((p = strrchr(name, '/')) != nil)
1227dd7cddfSDavid du Colombier 		name = p + 1;
123*9a747e4fSDavid du Colombier 	buf = hstrdup(hc, name);
1247dd7cddfSDavid du Colombier 	while((p = strrchr(buf, '.')) != nil){
1257dd7cddfSDavid du Colombier 		for(s = suffixes; s; s = s->next){
1267dd7cddfSDavid du Colombier 			if(strcmp(p, s->suffix) == 0){
1277dd7cddfSDavid du Colombier 				if(s->generic != nil && type == nil)
12880ee5cbfSDavid du Colombier 					type = hmkcontent(hc, s->generic, s->specific, nil);
1297dd7cddfSDavid du Colombier 				if(s->encoding != nil && enc == nil)
13080ee5cbfSDavid du Colombier 					enc = hmkcontent(hc, s->encoding, nil, nil);
1317dd7cddfSDavid du Colombier 			}
1327dd7cddfSDavid du Colombier 		}
1337dd7cddfSDavid du Colombier 		*p = 0;
1347dd7cddfSDavid du Colombier 	}
1357dd7cddfSDavid du Colombier 	conts.type = type;
1367dd7cddfSDavid du Colombier 	conts.encoding = enc;
1377dd7cddfSDavid du Colombier 	return conts;
1387dd7cddfSDavid du Colombier }
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier /*
1417dd7cddfSDavid du Colombier  * classify by initial contents of file
1427dd7cddfSDavid du Colombier  */
14380ee5cbfSDavid du Colombier HContents
dataclass(HConnect * hc,char * buf,int n)14480ee5cbfSDavid du Colombier dataclass(HConnect *hc, char *buf, int n)
1457dd7cddfSDavid du Colombier {
14680ee5cbfSDavid du Colombier 	HContents conts;
1477dd7cddfSDavid du Colombier 	Rune r;
1487dd7cddfSDavid du Colombier 	int c, m;
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 	for(; n > 0; n -= m){
1517dd7cddfSDavid du Colombier 		c = *buf;
1527dd7cddfSDavid du Colombier 		if(c < Runeself){
1537dd7cddfSDavid du Colombier 			if(c < 32 && c != '\n' && c != '\r' && c != '\t' && c != '\v'){
1547dd7cddfSDavid du Colombier 				conts.type = nil;
1557dd7cddfSDavid du Colombier 				conts.encoding = nil;
1567dd7cddfSDavid du Colombier 				return conts;
1577dd7cddfSDavid du Colombier 			}
1587dd7cddfSDavid du Colombier 			m = 1;
1597dd7cddfSDavid du Colombier 		}else{
1607dd7cddfSDavid du Colombier 			m = chartorune(&r, buf);
1617dd7cddfSDavid du Colombier 			if(r == Runeerror){
1627dd7cddfSDavid du Colombier 				conts.type = nil;
1637dd7cddfSDavid du Colombier 				conts.encoding = nil;
1647dd7cddfSDavid du Colombier 				return conts;
1657dd7cddfSDavid du Colombier 			}
1667dd7cddfSDavid du Colombier 		}
1677dd7cddfSDavid du Colombier 		buf += m;
1687dd7cddfSDavid du Colombier 	}
16980ee5cbfSDavid du Colombier 	conts.type = hmkcontent(hc, "text", "plain", nil);
1707dd7cddfSDavid du Colombier 	conts.encoding = nil;
1717dd7cddfSDavid du Colombier 	return conts;
1727dd7cddfSDavid du Colombier }
173