diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/ip/httpd/imagemap.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ip/httpd/imagemap.c')
-rwxr-xr-x | sys/src/cmd/ip/httpd/imagemap.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/sys/src/cmd/ip/httpd/imagemap.c b/sys/src/cmd/ip/httpd/imagemap.c new file mode 100755 index 000000000..9ecf42782 --- /dev/null +++ b/sys/src/cmd/ip/httpd/imagemap.c @@ -0,0 +1,320 @@ +#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; +} |