xref: /plan9/sys/src/cmd/ip/httpd/imagemap.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include "httpd.h"
5*80ee5cbfSDavid du Colombier #include "httpsrv.h"
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier typedef struct Point	Point;
87dd7cddfSDavid du Colombier typedef struct OkPoint	OkPoint;
97dd7cddfSDavid du Colombier typedef struct Strings	Strings;
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier struct Point
127dd7cddfSDavid du Colombier {
137dd7cddfSDavid du Colombier 	int	x;
147dd7cddfSDavid du Colombier 	int	y;
157dd7cddfSDavid du Colombier };
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier struct OkPoint
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 	Point	p;
207dd7cddfSDavid du Colombier 	int	ok;
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier struct Strings
247dd7cddfSDavid du Colombier {
257dd7cddfSDavid du Colombier 	char	*s1;
267dd7cddfSDavid du Colombier 	char	*s2;
277dd7cddfSDavid du Colombier };
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier static	char *me;
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier int		polytest(int, Point, Point, Point);
327dd7cddfSDavid du Colombier Strings		getfield(char*);
337dd7cddfSDavid du Colombier OkPoint		pt(char*);
34*80ee5cbfSDavid du Colombier char*		translate(HConnect*, char*, char*);
357dd7cddfSDavid du Colombier Point		sub(Point, Point);
367dd7cddfSDavid du Colombier float		dist(Point, Point);
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier void
main(int argc,char ** argv)397dd7cddfSDavid du Colombier main(int argc, char **argv)
407dd7cddfSDavid du Colombier {
41*80ee5cbfSDavid du Colombier 	HConnect *c;
427dd7cddfSDavid du Colombier 	Hio *hout;
437dd7cddfSDavid du Colombier 	char *dest;
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier 	me = "imagemap";
467dd7cddfSDavid du Colombier 	c = init(argc, argv);
477dd7cddfSDavid du Colombier 	hout = &c->hout;
48*80ee5cbfSDavid du Colombier 	if(hparseheaders(c, HSTIMEOUT) < 0)
49*80ee5cbfSDavid du Colombier 		exits("failed");
507dd7cddfSDavid du Colombier 	anonymous(c);
517dd7cddfSDavid du Colombier 
52*80ee5cbfSDavid du Colombier 	if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0){
53*80ee5cbfSDavid du Colombier 		hunallowed(c, "GET, HEAD");
54*80ee5cbfSDavid du Colombier 		exits("unallowed");
55*80ee5cbfSDavid du Colombier 	}
56*80ee5cbfSDavid du Colombier 	if(c->head.expectother || c->head.expectcont){
57*80ee5cbfSDavid du Colombier 		hfail(c, HExpectFail, nil);
58*80ee5cbfSDavid du Colombier 		exits("failed");
59*80ee5cbfSDavid du Colombier 	}
607dd7cddfSDavid du Colombier 	dest = translate(c, c->req.uri, c->req.search);
617dd7cddfSDavid du Colombier 
627dd7cddfSDavid du Colombier 	if(dest == nil){
637dd7cddfSDavid du Colombier 		if(c->req.vermaj){
64*80ee5cbfSDavid du Colombier 			hokheaders(c);
657dd7cddfSDavid du Colombier 			hprint(hout, "Content-type: text/html\r\n");
667dd7cddfSDavid du Colombier 			hprint(hout, "\r\n");
677dd7cddfSDavid du Colombier 		}
687dd7cddfSDavid du Colombier 		hprint(hout, "<head><title>Nothing Found</title></head><body>\n");
697dd7cddfSDavid du Colombier 		hprint(hout, "Nothing satisfying your search request could be found.\n</body>\n");
7014414594SDavid du Colombier 		hflush(hout);
7114414594SDavid du Colombier 		writelog(c, "Reply: 200 imagemap %ld %ld\n", hout->seek, hout->seek);
727dd7cddfSDavid du Colombier 		exits(nil);
737dd7cddfSDavid du Colombier 	}
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier 	if(http11(c) && strcmp(c->req.meth, "POST") == 0)
76*80ee5cbfSDavid du Colombier 		hredirected(c, "303 See Other", dest);
777dd7cddfSDavid du Colombier 	else
78*80ee5cbfSDavid du Colombier 		hredirected(c, "302 Found", dest);
797dd7cddfSDavid du Colombier 	exits(nil);
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier char*
translate(HConnect * c,char * uri,char * search)83*80ee5cbfSDavid du Colombier translate(HConnect *c, char *uri, char *search)
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier 	Biobuf *b;
867dd7cddfSDavid du Colombier 	Strings ss;
877dd7cddfSDavid du Colombier 	OkPoint okp;
887dd7cddfSDavid du Colombier 	Point p, cen, q, start;
897dd7cddfSDavid du Colombier 	float close, d;
907dd7cddfSDavid du Colombier 	char *line, *to, *def, *s, *dst;
917dd7cddfSDavid du Colombier 	int n, inside, r, ncsa;
927dd7cddfSDavid du Colombier 
93*80ee5cbfSDavid du Colombier 	if(search == nil){
94*80ee5cbfSDavid du Colombier 		hfail(c, HNoData, me);
95*80ee5cbfSDavid du Colombier 		exits("failed");
96*80ee5cbfSDavid du Colombier 	}
977dd7cddfSDavid du Colombier 	okp = pt(search);
98*80ee5cbfSDavid du Colombier 	if(!okp.ok){
99*80ee5cbfSDavid du Colombier 		hfail(c, HBadSearch, me);
100*80ee5cbfSDavid du Colombier 		exits("failed");
101*80ee5cbfSDavid du Colombier 	}
1027dd7cddfSDavid du Colombier 	p = okp.p;
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier 	b = Bopen(uri, OREAD);
105*80ee5cbfSDavid du Colombier 	if(b == nil){
106*80ee5cbfSDavid du Colombier 		hfail(c, HNotFound, uri);
107*80ee5cbfSDavid du Colombier 		exits("failed");
108*80ee5cbfSDavid du Colombier 	}
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier 	to = nil;
1117dd7cddfSDavid du Colombier 	def = nil;
1127dd7cddfSDavid du Colombier 	dst = nil;
1137dd7cddfSDavid du Colombier 	close = 0.;
1147dd7cddfSDavid du Colombier 	ncsa = 1;
1157dd7cddfSDavid du Colombier 	while(line = Brdline(b, '\n')){
1167dd7cddfSDavid du Colombier 		line[Blinelen(b)-1] = 0;
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier 		ss = getfield(line);
1197dd7cddfSDavid du Colombier 		s = ss.s1;
1207dd7cddfSDavid du Colombier 		line = ss.s2;
1217dd7cddfSDavid du Colombier 		if(ncsa){
1227dd7cddfSDavid du Colombier 			ss = getfield(line);
1237dd7cddfSDavid du Colombier 			dst = ss.s1;
1247dd7cddfSDavid du Colombier 			line = ss.s2;
1257dd7cddfSDavid du Colombier 		}
1267dd7cddfSDavid du Colombier 		if(strcmp(s, "#cern") == 0){
1277dd7cddfSDavid du Colombier 			ncsa = 0;
1287dd7cddfSDavid du Colombier 			continue;
1297dd7cddfSDavid du Colombier 		}
1307dd7cddfSDavid du Colombier 		if(strcmp(s, "rect") == 0){
1317dd7cddfSDavid du Colombier 			ss = getfield(line);
1327dd7cddfSDavid du Colombier 			s = ss.s1;
1337dd7cddfSDavid du Colombier 			line = ss.s2;
1347dd7cddfSDavid du Colombier 			okp = pt(s);
1357dd7cddfSDavid du Colombier 			q = okp.p;
1367dd7cddfSDavid du Colombier 			if(!okp.ok || q.x > p.x || q.y > p.y)
1377dd7cddfSDavid du Colombier 				continue;
1387dd7cddfSDavid du Colombier 			ss = getfield(line);
1397dd7cddfSDavid du Colombier 			s = ss.s1;
1407dd7cddfSDavid du Colombier 			line = ss.s2;
1417dd7cddfSDavid du Colombier 			okp = pt(s);
1427dd7cddfSDavid du Colombier 			q = okp.p;
1437dd7cddfSDavid du Colombier 			if(!okp.ok || q.x < p.x || q.y < p.y)
1447dd7cddfSDavid du Colombier 				continue;
1457dd7cddfSDavid du Colombier 			if(!ncsa){
1467dd7cddfSDavid du Colombier 				ss = getfield(line);
1477dd7cddfSDavid du Colombier 				dst = ss.s1;
1487dd7cddfSDavid du Colombier 			}
1497dd7cddfSDavid du Colombier 			return dst;
1507dd7cddfSDavid du Colombier 		}else if(strcmp(s, "circle") == 0){
1517dd7cddfSDavid du Colombier 			ss = getfield(line);
1527dd7cddfSDavid du Colombier 			s = ss.s1;
1537dd7cddfSDavid du Colombier 			line = ss.s2;
1547dd7cddfSDavid du Colombier 			okp = pt(s);
1557dd7cddfSDavid du Colombier 			cen = okp.p;
1567dd7cddfSDavid du Colombier 			if(!okp.ok)
1577dd7cddfSDavid du Colombier 				continue;
1587dd7cddfSDavid du Colombier 			ss = getfield(line);
1597dd7cddfSDavid du Colombier 			s = ss.s1;
1607dd7cddfSDavid du Colombier 			line = ss.s2;
1617dd7cddfSDavid du Colombier 			if(ncsa){
1627dd7cddfSDavid du Colombier 				okp = pt(s);
1637dd7cddfSDavid du Colombier 				if(!okp.ok)
1647dd7cddfSDavid du Colombier 					continue;
1657dd7cddfSDavid du Colombier 				if(dist(okp.p, cen) >= dist(p, cen))
1667dd7cddfSDavid du Colombier 					return dst;
1677dd7cddfSDavid du Colombier 			}else{
1687dd7cddfSDavid du Colombier 				r = strtol(s, nil, 10);
1697dd7cddfSDavid du Colombier 				ss = getfield(line);
1707dd7cddfSDavid du Colombier 				dst = ss.s1;
1717dd7cddfSDavid du Colombier 				d = (float)r * r;
1727dd7cddfSDavid du Colombier 				if(d >= dist(p, cen))
1737dd7cddfSDavid du Colombier 					return dst;
1747dd7cddfSDavid du Colombier 			}
1757dd7cddfSDavid du Colombier 		}else if(strcmp(s, "poly") == 0){
1767dd7cddfSDavid du Colombier 			ss = getfield(line);
1777dd7cddfSDavid du Colombier 			s = ss.s1;
1787dd7cddfSDavid du Colombier 			line = ss.s2;
1797dd7cddfSDavid du Colombier 			okp = pt(s);
1807dd7cddfSDavid du Colombier 			start = okp.p;
1817dd7cddfSDavid du Colombier 			if(!okp.ok)
1827dd7cddfSDavid du Colombier 				continue;
1837dd7cddfSDavid du Colombier 			inside = 0;
1847dd7cddfSDavid du Colombier 			cen = start;
1857dd7cddfSDavid du Colombier 			for(n = 1; ; n++){
1867dd7cddfSDavid du Colombier 				ss = getfield(line);
1877dd7cddfSDavid du Colombier 				s = ss.s1;
1887dd7cddfSDavid du Colombier 				line = ss.s2;
1897dd7cddfSDavid du Colombier 				okp = pt(s);
1907dd7cddfSDavid du Colombier 				q = okp.p;
1917dd7cddfSDavid du Colombier 				if(!okp.ok)
1927dd7cddfSDavid du Colombier 					break;
1937dd7cddfSDavid du Colombier 				inside = polytest(inside, p, cen, q);
1947dd7cddfSDavid du Colombier 				cen = q;
1957dd7cddfSDavid du Colombier 			}
1967dd7cddfSDavid du Colombier 			inside = polytest(inside, p, cen, start);
1977dd7cddfSDavid du Colombier 			if(!ncsa)
1987dd7cddfSDavid du Colombier 				dst = s;
1997dd7cddfSDavid du Colombier 			if(n >= 3 && inside)
2007dd7cddfSDavid du Colombier 				return dst;
2017dd7cddfSDavid du Colombier 		}else if(strcmp(s, "point") == 0){
2027dd7cddfSDavid du Colombier 			ss = getfield(line);
2037dd7cddfSDavid du Colombier 			s = ss.s1;
2047dd7cddfSDavid du Colombier 			line = ss.s2;
2057dd7cddfSDavid du Colombier 			okp = pt(s);
2067dd7cddfSDavid du Colombier 			q = okp.p;
2077dd7cddfSDavid du Colombier 			if(!okp.ok)
2087dd7cddfSDavid du Colombier 				continue;
2097dd7cddfSDavid du Colombier 			d = dist(p, q);
2107dd7cddfSDavid du Colombier 			if(!ncsa){
2117dd7cddfSDavid du Colombier 				ss = getfield(line);
2127dd7cddfSDavid du Colombier 				dst = ss.s1;
2137dd7cddfSDavid du Colombier 			}
2147dd7cddfSDavid du Colombier 			if(d == 0.)
2157dd7cddfSDavid du Colombier 				return dst;
2167dd7cddfSDavid du Colombier 			if(close == 0. || d < close){
2177dd7cddfSDavid du Colombier 				close = d;
2187dd7cddfSDavid du Colombier 				to = dst;
2197dd7cddfSDavid du Colombier 			}
2207dd7cddfSDavid du Colombier 		}else if(strcmp(s, "default") == 0){
2217dd7cddfSDavid du Colombier 			if(!ncsa){
2227dd7cddfSDavid du Colombier 				ss = getfield(line);
2237dd7cddfSDavid du Colombier 				dst = ss.s1;
2247dd7cddfSDavid du Colombier 			}
2257dd7cddfSDavid du Colombier 			def = dst;
2267dd7cddfSDavid du Colombier 		}
2277dd7cddfSDavid du Colombier 	}
2287dd7cddfSDavid du Colombier 	if(to == nil)
2297dd7cddfSDavid du Colombier 		to = def;
2307dd7cddfSDavid du Colombier 	return to;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier int
polytest(int inside,Point p,Point b,Point a)2347dd7cddfSDavid du Colombier polytest(int inside, Point p, Point b, Point a)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier 	Point pa, ba;
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 	if(b.y>a.y){
2397dd7cddfSDavid du Colombier 		pa=sub(p, a);
2407dd7cddfSDavid du Colombier 		ba=sub(b, a);
2417dd7cddfSDavid du Colombier 	}else{
2427dd7cddfSDavid du Colombier 		pa=sub(p, b);
2437dd7cddfSDavid du Colombier 		ba=sub(a, b);
2447dd7cddfSDavid du Colombier 	}
2457dd7cddfSDavid du Colombier 	if(0<=pa.y && pa.y<ba.y && pa.y*ba.x<=pa.x*ba.y)
2467dd7cddfSDavid du Colombier 		inside = !inside;
2477dd7cddfSDavid du Colombier 	return inside;
2487dd7cddfSDavid du Colombier }
2497dd7cddfSDavid du Colombier 
2507dd7cddfSDavid du Colombier Point
sub(Point p,Point q)2517dd7cddfSDavid du Colombier sub(Point p, Point q)
2527dd7cddfSDavid du Colombier {
2537dd7cddfSDavid du Colombier 	p.x -= q.x;
2547dd7cddfSDavid du Colombier 	p.y -= q.y;
2557dd7cddfSDavid du Colombier 	return p;
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier float
dist(Point p,Point q)2597dd7cddfSDavid du Colombier dist(Point p, Point q)
2607dd7cddfSDavid du Colombier {
2617dd7cddfSDavid du Colombier 	p.x -= q.x;
2627dd7cddfSDavid du Colombier 	p.y -= q.y;
2637dd7cddfSDavid du Colombier 	return (float)p.x * p.x + (float)p.y * p.y;
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier 
2667dd7cddfSDavid du Colombier OkPoint
pt(char * s)2677dd7cddfSDavid du Colombier pt(char *s)
2687dd7cddfSDavid du Colombier {
2697dd7cddfSDavid du Colombier 	OkPoint okp;
2707dd7cddfSDavid du Colombier 	Point p;
2717dd7cddfSDavid du Colombier 	char *t, *e;
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	if(*s == '(')
2747dd7cddfSDavid du Colombier 		s++;
2757dd7cddfSDavid du Colombier 	t = strchr(s, ')');
2767dd7cddfSDavid du Colombier 	if(t != nil)
2777dd7cddfSDavid du Colombier 		*t = 0;
2787dd7cddfSDavid du Colombier 	p.x = 0;
2797dd7cddfSDavid du Colombier 	p.y = 0;
2807dd7cddfSDavid du Colombier 	t = strchr(s, ',');
2817dd7cddfSDavid du Colombier 	if(t == nil){
2827dd7cddfSDavid du Colombier 		okp.p = p;
2837dd7cddfSDavid du Colombier 		okp.ok = 0;
2847dd7cddfSDavid du Colombier 		return okp;
2857dd7cddfSDavid du Colombier 	}
2867dd7cddfSDavid du Colombier 	e = nil;
2877dd7cddfSDavid du Colombier 	p.x = strtol(s, &e, 10);
2887dd7cddfSDavid du Colombier 	if(e != t){
2897dd7cddfSDavid du Colombier 		okp.p = p;
2907dd7cddfSDavid du Colombier 		okp.ok = 0;
2917dd7cddfSDavid du Colombier 		return okp;
2927dd7cddfSDavid du Colombier 	}
2937dd7cddfSDavid du Colombier 	p.y = strtol(t+1, &e, 10);
2947dd7cddfSDavid du Colombier 	if(e == nil || *e != 0){
2957dd7cddfSDavid du Colombier 		okp.p = p;
2967dd7cddfSDavid du Colombier 		okp.ok = 0;
2977dd7cddfSDavid du Colombier 		return okp;
2987dd7cddfSDavid du Colombier 	}
2997dd7cddfSDavid du Colombier 	okp.p = p;
3007dd7cddfSDavid du Colombier 	okp.ok = 1;
3017dd7cddfSDavid du Colombier 	return okp;
3027dd7cddfSDavid du Colombier }
3037dd7cddfSDavid du Colombier 
3047dd7cddfSDavid du Colombier Strings
getfield(char * s)3057dd7cddfSDavid du Colombier getfield(char *s)
3067dd7cddfSDavid du Colombier {
3077dd7cddfSDavid du Colombier 	Strings ss;
3087dd7cddfSDavid du Colombier 	char *f;
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier 	while(*s == '\t' || *s == ' ')
3117dd7cddfSDavid du Colombier 		s++;
3127dd7cddfSDavid du Colombier 	f = s;
3137dd7cddfSDavid du Colombier 	while(*s && *s != '\t' && *s != ' ')
3147dd7cddfSDavid du Colombier 		s++;
3157dd7cddfSDavid du Colombier 	if(*s)
3167dd7cddfSDavid du Colombier 		*s++ = 0;
3177dd7cddfSDavid du Colombier 	ss.s1 = f;
3187dd7cddfSDavid du Colombier 	ss.s2 = s;
3197dd7cddfSDavid du Colombier 	return ss;
3207dd7cddfSDavid du Colombier }
321