diff options
Diffstat (limited to 'appl/svc/httpd/imagemap.b')
| -rw-r--r-- | appl/svc/httpd/imagemap.b | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/appl/svc/httpd/imagemap.b b/appl/svc/httpd/imagemap.b new file mode 100644 index 00000000..34a08edc --- /dev/null +++ b/appl/svc/httpd/imagemap.b @@ -0,0 +1,251 @@ +implement imagemap; + +include "sys.m"; + sys : Sys; + +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; + +include "draw.m"; + draw: Draw; + +include "cache.m"; +include "contents.m"; + +include "httpd.m"; + Private_info: import Httpd; + OnlySearch, BadSearch, NotFound: import Httpd; + g : ref Private_info; + +include "parser.m"; + parser : Parser; + +include "daytime.m"; + daytime: Daytime; + +include "string.m"; + str : String; + +imagemap : module +{ + init: fn(g : ref Private_info, req: Httpd->Request); +}; + +Point : adt { + x,y : int; +}; + +me : string; + +badmod(p: string) +{ + sys->fprint(sys->fildes(2), "imagemap: cannot load %s: %r\n", p); + raise "fail:bad module"; +} + +init(k : ref Private_info, req: Httpd->Request) +{ + dest, s : string; + sys = load Sys "$Sys"; + draw = load Draw "$Draw"; + + daytime = load Daytime Daytime->PATH; + if(daytime == nil) badmod(Daytime->PATH); + + parser = load Parser Parser->PATH; + if(parser == nil) badmod(Parser->PATH); + + str = load String String->PATH; + if (str == nil) badmod(String->PATH); + + me = "imagemap"; + + g=k; + bufio=g.bufio; + parser->init(); + parser->httpheaders(g,req.version); + dest = translate(req.uri, req.search); + if(dest == nil){ + if(req.version!= ""){ + parser->okheaders(g); + g.bout.puts(sys->sprint("Date: %s\r\n", daytime->time())); + g.bout.puts("Content-type: text/html\r\n"); + g.bout.puts("\r\n"); + } + g.bout.puts("<head><title>Nothing Found</title></head><body>\n"); + g.bout.puts("Nothing satisfying your search request could be found.\n</body>\n"); + return; + } + + g.bout.puts(sys->sprint("%s 301 Moved Permanently\r\n", g.version)); + g.bout.puts(sys->sprint("Date: %s\r\n", daytime->time())); + g.bout.puts("Server: Charon\r\n"); + g.bout.puts("MIME-version: 1.0\r\n"); + g.bout.puts("Content-type: text/html\r\n"); + (s,nil)=str->splitl(dest, ":"); + if(s!=nil){ + g.bout.puts(sys->sprint("URI: <%s>\r\n", parser->urlconv(dest))); + g.bout.puts(sys->sprint("Location: %s\r\n", parser->urlconv(dest))); + }else if(dest[0] == '/'){ + g.bout.puts(sys->sprint("URI: <%s>\r\n",parser->urlconv(dest))); + g.bout.puts(sys->sprint("Location: http://%s%s\r\n", parser->urlconv(g.mydomain), parser->urlconv(dest))); + } else { + (req.uri,s) = str->splitr(req.uri, "/"); + g.bout.puts(sys->sprint("URI: <%s/%s>\r\n", parser->urlconv(req.uri), parser->urlconv(dest))); + g.bout.puts(sys->sprint("Location: http://%s%s/%s\r\n", parser->urlconv(g.mydomain), parser->urlconv(req.uri), parser->urlconv(dest))); + } + g.bout.puts("\r\n"); + g.bout.puts("<head><title>Object Moved</title></head>\r\n"); + g.bout.puts("<body><h1>Object Moved</h1></body>\r\n"); + if(dest[0] == '/') + g.bout.puts(sys->sprint("Your selection mapped to <a href=\"%s\"> here</a>.<p>\r\n", parser->urlconv(dest))); + else + g.bout.puts(sys->sprint("Your selection mapped to <a href=\"%s/%s\"> here</a>.<p>\r\n", parser->urlconv(req.uri), parser->urlconv(dest))); +} + + +translate(uri, search : string) : string +{ + b : ref Iobuf; + p, c, q, start : Point; + close, d : real; + line, To, def, s : string; + ok, n, inside, r : int; + (pth,nil):=str->splitr(uri,"/"); + # sys->print("pth is %s",pth); + if(search == nil) + parser->fail(g,OnlySearch, me); + (p, ok) = pt(search); + if(!ok) + parser->fail(g,BadSearch, me); + + b = bufio->open(uri, bufio->OREAD); + if(b == nil){ + sys->fprint(sys->fildes(2), "imagemap: cannot open %s: %r\n", uri); + parser->fail(g, NotFound, uri); + } + To = ""; + def = ""; + close = 0.; + while((line = b.gets('\n'))!=nil){ + line=line[0:len line-1]; + + (s, line) = getfield(line); + if(s== "rect"){ + (s, line) = getfield(line); + (q, ok) = pt(s); + if(!ok || q.x > p.x || q.y > p.y) + continue; + (s, line) = getfield(line); + (q, ok) = pt(s); + if(!ok || q.x < p.x || q.y < p.y) + continue; + (s, nil) = getfield(line); + return pth+s; + }else if(s== "circle"){ + (s, line) = getfield(line); + (c, ok) = pt(s); + if(!ok) + continue; + (s, line) = getfield(line); + (r,nil) = str->toint(s,10); + (s, line) = getfield(line); + d = real (r * r); + if(d >= dist(p, c)) + return pth+s; + }else if(s=="poly"){ + (s, line) = getfield(line); + (start, ok) = pt(s); + if(!ok) + continue; + inside = 0; + c = start; + for(n = 1; ; n++){ + (s, line) = getfield(line); + (q, ok) = pt(s); + if(!ok) + break; + inside = polytest(inside, p, c, q); + c = q; + } + inside = polytest(inside, p, c, start); + if(n >= 3 && inside) + return pth+s; + }else if(s== "point"){ + (s, line) = getfield(line); + (q, ok) = pt(s); + if(!ok) + continue; + d = dist(p, q); + (s, line) = getfield(line); + if(d == 0.) + return pth+s; + if(close == 0. || d < close){ + close = d; + To = s; + } + }else if(s == "default"){ + (def, line) = getfield(line); + } + } + if(To == nil) + To = def; + return pth+To; +} + + +polytest(inside : int,p, b, a : Point) : int{ + pa, ba : Point; + + if(b.y>a.y){ + pa=sub(p, a); + ba=sub(b, a); + }else{ + pa=sub(p, b); + ba=sub(a, b); + } + if(0<=pa.y && pa.y<ba.y && pa.y*ba.x<=pa.x*ba.y) + inside = !inside; + return inside; +} + + +sub(p, q : Point) : Point { + return (Point)(p.x-q.x, p.y-q.y); +} + + +dist(p, q : Point) : real { + p.x -= q.x; + p.y -= q.y; + return real (p.x * p.x + p.y *p.y); +} + + +pt(s : string) : (Point, int) { + p : Point; + x, y : string; + + if(s[0] == '(') + s=s[1:]; + (s,nil)=str->splitl(s, ")"); + p = Point(0, 0); + (x,y) = str->splitl(s, ","); + if(x == s) + return (p, 0); + (p.x,nil) = str->toint(x,10); + if(y==nil) + return (p, 0); + y=y[1:]; + (p.y,nil) = str->toint(y, 10); + return (p, 1); +} + + +getfield(s : string) : (string,string) { + i:=0; + while(s[i] == '\t' || s[i] == ' ') + i++; + return str->splitl(s[i:],"\t "); +} |
