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