123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "httpd.h"
- #include "httpsrv.h"
- typedef struct Point Point;
- typedef struct OkPoint OkPoint;
- typedef struct Strings Strings;
- struct Point
- {
- int x;
- int y;
- };
- struct OkPoint
- {
- Point p;
- int ok;
- };
- struct Strings
- {
- char *s1;
- char *s2;
- };
- static char *me;
- int polytest(int, Point, Point, Point);
- Strings getfield(char*);
- OkPoint pt(char*);
- char* translate(HConnect*, char*, char*);
- Point sub(Point, Point);
- float dist(Point, Point);
- void
- main(int argc, char **argv)
- {
- HConnect *c;
- Hio *hout;
- char *dest;
- me = "imagemap";
- c = init(argc, argv);
- hout = &c->hout;
- if(hparseheaders(c, HSTIMEOUT) < 0)
- exits("failed");
- anonymous(c);
- if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0){
- hunallowed(c, "GET, HEAD");
- exits("unallowed");
- }
- if(c->head.expectother || c->head.expectcont){
- hfail(c, HExpectFail, nil);
- exits("failed");
- }
- dest = translate(c, c->req.uri, c->req.search);
- if(dest == nil){
- if(c->req.vermaj){
- hokheaders(c);
- hprint(hout, "Content-type: text/html\r\n");
- hprint(hout, "\r\n");
- }
- hprint(hout, "<head><title>Nothing Found</title></head><body>\n");
- hprint(hout, "Nothing satisfying your search request could be found.\n</body>\n");
- hflush(hout);
- writelog(c, "Reply: 200 imagemap %ld %ld\n", hout->seek, hout->seek);
- exits(nil);
- }
- if(http11(c) && strcmp(c->req.meth, "POST") == 0)
- hredirected(c, "303 See Other", dest);
- else
- hredirected(c, "302 Found", dest);
- exits(nil);
- }
- char*
- translate(HConnect *c, char *uri, char *search)
- {
- Biobuf *b;
- Strings ss;
- OkPoint okp;
- Point p, cen, q, start;
- float close, d;
- char *line, *to, *def, *s, *dst;
- int n, inside, r, ncsa;
- if(search == nil){
- hfail(c, HNoData, me);
- exits("failed");
- }
- okp = pt(search);
- if(!okp.ok){
- hfail(c, HBadSearch, me);
- exits("failed");
- }
- p = okp.p;
- b = Bopen(uri, OREAD);
- if(b == nil){
- hfail(c, HNotFound, uri);
- exits("failed");
- }
- to = nil;
- def = nil;
- dst = nil;
- close = 0.;
- ncsa = 1;
- while(line = Brdline(b, '\n')){
- line[Blinelen(b)-1] = 0;
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- if(ncsa){
- ss = getfield(line);
- dst = ss.s1;
- line = ss.s2;
- }
- if(strcmp(s, "#cern") == 0){
- ncsa = 0;
- continue;
- }
- if(strcmp(s, "rect") == 0){
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- okp = pt(s);
- q = okp.p;
- if(!okp.ok || q.x > p.x || q.y > p.y)
- continue;
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- okp = pt(s);
- q = okp.p;
- if(!okp.ok || q.x < p.x || q.y < p.y)
- continue;
- if(!ncsa){
- ss = getfield(line);
- dst = ss.s1;
- }
- return dst;
- }else if(strcmp(s, "circle") == 0){
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- okp = pt(s);
- cen = okp.p;
- if(!okp.ok)
- continue;
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- if(ncsa){
- okp = pt(s);
- if(!okp.ok)
- continue;
- if(dist(okp.p, cen) >= dist(p, cen))
- return dst;
- }else{
- r = strtol(s, nil, 10);
- ss = getfield(line);
- dst = ss.s1;
- d = (float)r * r;
- if(d >= dist(p, cen))
- return dst;
- }
- }else if(strcmp(s, "poly") == 0){
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- okp = pt(s);
- start = okp.p;
- if(!okp.ok)
- continue;
- inside = 0;
- cen = start;
- for(n = 1; ; n++){
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- okp = pt(s);
- q = okp.p;
- if(!okp.ok)
- break;
- inside = polytest(inside, p, cen, q);
- cen = q;
- }
- inside = polytest(inside, p, cen, start);
- if(!ncsa)
- dst = s;
- if(n >= 3 && inside)
- return dst;
- }else if(strcmp(s, "point") == 0){
- ss = getfield(line);
- s = ss.s1;
- line = ss.s2;
- okp = pt(s);
- q = okp.p;
- if(!okp.ok)
- continue;
- d = dist(p, q);
- if(!ncsa){
- ss = getfield(line);
- dst = ss.s1;
- }
- if(d == 0.)
- return dst;
- if(close == 0. || d < close){
- close = d;
- to = dst;
- }
- }else if(strcmp(s, "default") == 0){
- if(!ncsa){
- ss = getfield(line);
- dst = ss.s1;
- }
- def = dst;
- }
- }
- if(to == nil)
- to = def;
- return to;
- }
- int
- polytest(int inside, Point p, Point b, Point a)
- {
- Point pa, ba;
- 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;
- }
- Point
- sub(Point p, Point q)
- {
- p.x -= q.x;
- p.y -= q.y;
- return p;
- }
- float
- dist(Point p, Point q)
- {
- p.x -= q.x;
- p.y -= q.y;
- return (float)p.x * p.x + (float)p.y * p.y;
- }
- OkPoint
- pt(char *s)
- {
- OkPoint okp;
- Point p;
- char *t, *e;
- if(*s == '(')
- s++;
- t = strchr(s, ')');
- if(t != nil)
- *t = 0;
- p.x = 0;
- p.y = 0;
- t = strchr(s, ',');
- if(t == nil){
- okp.p = p;
- okp.ok = 0;
- return okp;
- }
- e = nil;
- p.x = strtol(s, &e, 10);
- if(e != t){
- okp.p = p;
- okp.ok = 0;
- return okp;
- }
- p.y = strtol(t+1, &e, 10);
- if(e == nil || *e != 0){
- okp.p = p;
- okp.ok = 0;
- return okp;
- }
- okp.p = p;
- okp.ok = 1;
- return okp;
- }
- Strings
- getfield(char *s)
- {
- Strings ss;
- char *f;
- while(*s == '\t' || *s == ' ')
- s++;
- f = s;
- while(*s && *s != '\t' && *s != ' ')
- s++;
- if(*s)
- *s++ = 0;
- ss.s1 = f;
- ss.s2 = s;
- return ss;
- }
|