summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ip/httpd/imagemap.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/ip/httpd/imagemap.c320
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;
+}