summaryrefslogtreecommitdiff
path: root/appl/svc/httpd/contents.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/svc/httpd/contents.b')
-rw-r--r--appl/svc/httpd/contents.b192
1 files changed, 192 insertions, 0 deletions
diff --git a/appl/svc/httpd/contents.b b/appl/svc/httpd/contents.b
new file mode 100644
index 00000000..5e57dd25
--- /dev/null
+++ b/appl/svc/httpd/contents.b
@@ -0,0 +1,192 @@
+implement Contents;
+
+include "sys.m";
+ sys: Sys;
+ dbg_log : ref Sys->FD;
+include "draw.m";
+
+include "bufio.m";
+ bufio: Bufio;
+Iobuf : import bufio;
+
+include "contents.m";
+
+include "cache.m";
+
+include "httpd.m";
+
+include "string.m";
+ str : String;
+
+Suffix: adt{
+ suffix : string;
+ generic : string;
+ specific : string;
+ encoding : string;
+};
+
+suffixes: list of Suffix;
+
+#internal functions...
+parsesuffix : fn(nil:string): (int,Suffix);
+
+mkcontent(generic,specific : string): ref Content
+{
+ c:= ref Content;
+ c.generic = generic;
+ c.specific = specific;
+ c.q = real 1;
+ return c;
+}
+
+badmod(m: string)
+{
+ sys->fprint(stderr(), "contents: cannot load %s: %r\n", m);
+ raise "fail:bad module";
+}
+
+contentinit(log: ref Sys->FD)
+{
+ if(suffixes != nil)
+ return;
+
+ sys = load Sys Sys->PATH;
+
+ bufio = load Bufio Bufio->PATH;
+ if (bufio == nil) badmod(Bufio->PATH);
+
+ str = load String String->PATH;
+ if (str == nil) badmod(String->PATH);
+
+ iob := bufio->open(Httpd->HTTP_SUFF, bufio->OREAD);
+ if (iob==nil) {
+ sys->fprint(stderr(), "contents: cannot open %s: %r\n", Httpd->HTTP_SUFF);
+ raise "fail:no suffix file";;
+ }
+ while((s := iob.gets('\n'))!=nil) {
+ (i, su) := parsesuffix(s);
+ if (i != 0)
+ suffixes = su :: suffixes;
+ }
+ dbg_log = log;
+}
+
+# classify by file name extensions
+
+uriclass(name : string): (ref Content, ref Content)
+{
+ s : Suffix;
+ typ, enc: ref Content;
+ p : string;
+ lis := suffixes;
+ typ=nil;
+ enc=nil;
+ uri:=name;
+ (nil,p) = str->splitr(name,"/");
+ if (p!=nil) name=p;
+
+ if(str->in('.',name)){
+ (nil,p) = str->splitl(name,".");
+ for(s = hd lis; lis!=nil; lis = tl lis){
+ if(p == s.suffix){
+ if(s.generic != nil && typ==nil)
+ typ = mkcontent(s.generic, s.specific);
+ if(s.encoding != nil && enc==nil)
+ enc = mkcontent(s.encoding, "");
+ }
+ s = hd lis;
+ }
+ }
+ if(typ == nil && enc == nil){
+ buff := array[64] of byte;
+ fd := sys->open(uri, sys->OREAD);
+ n := sys->read(fd, buff, len buff);
+ if(n > 0){
+ tmp := string buff[0:n];
+ (typ, enc) = dataclass(tmp);
+ }
+ }
+ return (typ, enc);
+}
+
+
+parsesuffix(line: string): (int, Suffix)
+{
+ s : Suffix;
+ if (str->in('#',line))
+ (line,nil) = str->splitl(line, "#");
+ if (line!=nil){
+ (n,slist):=sys->tokenize(line,"\n\t ");
+ if (n!=4 && n!=0){
+ if (dbg_log!=nil)
+ sys->fprint(dbg_log,"Error in suffixes file!, n=%d\n",n);
+ sys->print("Error in suffixes file!, n=%d\n",n);
+ exit;
+ }
+ s.suffix = hd slist;
+ slist = tl slist;
+ s.generic = hd slist;
+ if (s.generic == "-") s.generic="";
+ slist = tl slist;
+ s.specific = hd slist;
+ if (s.specific == "-") s.specific="";
+ slist = tl slist;
+ s.encoding = hd slist;
+ if (s.encoding == "-") s.encoding="";
+
+ }
+ if (((s.generic == "")||(s.specific == "")) && s.encoding=="")
+ return (0,s);
+ return (1,s);
+}
+
+#classify by initial contents of file
+dataclass(buf : string): (ref Content,ref Content)
+{
+ c,n : int;
+ c=0;
+ n = len buf;
+ for(; n > 0; n --){
+ if(buf[c] < 16r80)
+ if(buf[c] < 32 && buf[c] != '\n' && buf[c] != '\r'
+ && buf[c] != '\t' && buf[c] != '\v')
+ return (nil,nil);
+ c++;
+ }
+ return (mkcontent("text", "plain"),nil);
+}
+
+checkcontent(me: ref Content,oks :list of ref Content, clist : string): int
+{
+ ok:=oks;
+ try : ref Content;
+ if(oks == nil || me == nil)
+ return 1;
+ for(; ok != nil; ok = tl ok){
+ try = hd ok;
+ if((try.generic==me.generic || try.generic=="*")
+ && (try.specific==me.specific || try.specific=="*")){
+ return 1;
+ }
+ }
+
+ sys->fprint(dbg_log,"%s/%s not found",
+ me.generic, me.specific);
+ logcontent(clist, oks);
+ return 1;
+}
+
+logcontent(name : string, c : list of ref Content)
+{
+ buf : string;
+ if (dbg_log!=nil){
+ for(; c!=nil; c = tl c)
+ buf+=sys->sprint("%s/%s ", (hd c).generic,(hd c).specific);
+ sys->fprint(dbg_log,"%s: %s: %s", "client", name, buf);
+ }
+}
+
+stderr(): ref Sys->FD
+{
+ return sys->fildes(2);
+}