xref: /inferno-os/appl/svc/httpd/contents.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Contents;
2
3include "sys.m";
4	sys: Sys;
5	dbg_log : ref Sys->FD;
6include "draw.m";
7
8include "bufio.m";
9	bufio: Bufio;
10Iobuf : import bufio;
11
12include "contents.m";
13
14include "cache.m";
15
16include "httpd.m";
17
18include "string.m";
19	str : String;
20
21Suffix: adt{
22	suffix : string;
23	generic : string;
24	specific : string;
25	encoding : string;
26};
27
28suffixes: list of Suffix;
29
30#internal functions...
31parsesuffix : fn(nil:string): (int,Suffix);
32
33mkcontent(generic,specific : string): ref Content
34{
35	c:= ref Content;
36	c.generic = generic;
37	c.specific = specific;
38	c.q = real 1;
39	return c;
40}
41
42badmod(m: string)
43{
44	sys->fprint(stderr(), "contents: cannot load %s: %r\n", m);
45	raise "fail:bad module";
46}
47
48contentinit(log: ref Sys->FD)
49{
50	if(suffixes != nil)
51		return;
52
53	sys = load Sys Sys->PATH;
54
55	bufio = load Bufio Bufio->PATH;
56	if (bufio == nil) badmod(Bufio->PATH);
57
58	str = load String String->PATH;
59	if (str == nil) badmod(String->PATH);
60
61	iob := bufio->open(Httpd->HTTP_SUFF, bufio->OREAD);
62	if (iob==nil) {
63		sys->fprint(stderr(), "contents: cannot open %s: %r\n", Httpd->HTTP_SUFF);
64		raise "fail:no suffix file";;
65	}
66	while((s := iob.gets('\n'))!=nil) {
67		(i, su) := parsesuffix(s);
68		if (i != 0)
69			suffixes =  su :: suffixes;
70	}
71	dbg_log = log;
72}
73
74# classify by file name extensions
75
76uriclass(name : string): (ref Content, ref Content)
77{
78	s : Suffix;
79	typ, enc: ref Content;
80	p : string;
81	lis := suffixes;
82	typ=nil;
83	enc=nil;
84	uri:=name;
85	(nil,p) = str->splitr(name,"/");
86	if (p!=nil) name=p;
87
88	if(str->in('.',name)){
89		(nil,p) = str->splitl(name,".");
90		for(s = hd lis; lis!=nil; lis = tl lis){
91			if(p == s.suffix){
92				if(s.generic != nil && typ==nil)
93					typ = mkcontent(s.generic, s.specific);
94				if(s.encoding != nil && enc==nil)
95					enc = mkcontent(s.encoding, "");
96			}
97		s = hd lis;
98		}
99	}
100	if(typ == nil && enc == nil){
101		buff := array[64] of byte;
102		fd := sys->open(uri, sys->OREAD);
103		n := sys->read(fd, buff, len buff);
104		if(n > 0){
105			tmp := string buff[0:n];
106			(typ, enc) = dataclass(tmp);
107		}
108	}
109	return (typ, enc);
110}
111
112
113parsesuffix(line: string): (int, Suffix)
114{
115	s : Suffix;
116	if (str->in('#',line))
117		(line,nil) = str->splitl(line, "#");
118	if (line!=nil){
119		(n,slist):=sys->tokenize(line,"\n\t ");
120		if (n!=4 && n!=0){
121			if (dbg_log!=nil)
122				sys->fprint(dbg_log,"Error in suffixes file!, n=%d\n",n);
123			sys->print("Error in suffixes file!, n=%d\n",n);
124			exit;
125		}
126		s.suffix = hd slist;
127		slist = tl slist;
128		s.generic = hd slist;
129		if (s.generic == "-") s.generic="";
130		slist = tl slist;
131		s.specific = hd slist;
132		if (s.specific == "-") s.specific="";
133		slist = tl slist;
134		s.encoding = hd slist;
135		if (s.encoding == "-") s.encoding="";
136
137	}
138	if (((s.generic ==  "")||(s.specific ==  "")) && s.encoding=="")
139		return (0,s);
140	return (1,s);
141}
142
143#classify by initial contents of file
144dataclass(buf : string): (ref Content,ref Content)
145{
146	c,n : int;
147	c=0;
148	n = len buf;
149	for(; n > 0; n --){
150		if(buf[c] < 16r80)
151			if(buf[c] < 32 && buf[c] != '\n' && buf[c] != '\r'
152					&& buf[c] != '\t' && buf[c] != '\v')
153				return (nil,nil);
154		c++;
155	}
156	return (mkcontent("text", "plain"),nil);
157}
158
159checkcontent(me: ref Content,oks :list of ref Content, clist : string): int
160{
161	ok:=oks;
162	try : ref Content;
163	if(oks == nil || me == nil)
164		return 1;
165	for(; ok != nil; ok = tl ok){
166		try = hd ok;
167		if((try.generic==me.generic || try.generic=="*")
168		&& (try.specific==me.specific || try.specific=="*")){
169			return 1;
170		}
171	}
172
173	sys->fprint(dbg_log,"%s/%s not found",
174				me.generic, me.specific);
175	logcontent(clist, oks);
176	return 1;
177}
178
179logcontent(name : string, c : list of ref Content)
180{
181	buf : string;
182	if (dbg_log!=nil){
183		for(; c!=nil; c = tl c)
184			buf+=sys->sprint("%s/%s ", (hd c).generic,(hd c).specific);
185		sys->fprint(dbg_log,"%s: %s: %s", "client", name, buf);
186	}
187}
188
189stderr(): ref Sys->FD
190{
191	return sys->fildes(2);
192}
193