1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "httpd.h"
5 #include "httpsrv.h"
6
7 typedef struct Point Point;
8 typedef struct OkPoint OkPoint;
9 typedef struct Strings Strings;
10
11 struct Point
12 {
13 int x;
14 int y;
15 };
16
17 struct OkPoint
18 {
19 Point p;
20 int ok;
21 };
22
23 struct Strings
24 {
25 char *s1;
26 char *s2;
27 };
28
29 static char *me;
30
31 int polytest(int, Point, Point, Point);
32 Strings getfield(char*);
33 OkPoint pt(char*);
34 char* translate(HConnect*, char*, char*);
35 Point sub(Point, Point);
36 float dist(Point, Point);
37
38 void
main(int argc,char ** argv)39 main(int argc, char **argv)
40 {
41 HConnect *c;
42 Hio *hout;
43 char *dest;
44
45 me = "imagemap";
46 c = init(argc, argv);
47 hout = &c->hout;
48 if(hparseheaders(c, HSTIMEOUT) < 0)
49 exits("failed");
50 anonymous(c);
51
52 if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0){
53 hunallowed(c, "GET, HEAD");
54 exits("unallowed");
55 }
56 if(c->head.expectother || c->head.expectcont){
57 hfail(c, HExpectFail, nil);
58 exits("failed");
59 }
60 dest = translate(c, c->req.uri, c->req.search);
61
62 if(dest == nil){
63 if(c->req.vermaj){
64 hokheaders(c);
65 hprint(hout, "Content-type: text/html\r\n");
66 hprint(hout, "\r\n");
67 }
68 hprint(hout, "<head><title>Nothing Found</title></head><body>\n");
69 hprint(hout, "Nothing satisfying your search request could be found.\n</body>\n");
70 hflush(hout);
71 writelog(c, "Reply: 200 imagemap %ld %ld\n", hout->seek, hout->seek);
72 exits(nil);
73 }
74
75 if(http11(c) && strcmp(c->req.meth, "POST") == 0)
76 hredirected(c, "303 See Other", dest);
77 else
78 hredirected(c, "302 Found", dest);
79 exits(nil);
80 }
81
82 char*
translate(HConnect * c,char * uri,char * search)83 translate(HConnect *c, char *uri, char *search)
84 {
85 Biobuf *b;
86 Strings ss;
87 OkPoint okp;
88 Point p, cen, q, start;
89 float close, d;
90 char *line, *to, *def, *s, *dst;
91 int n, inside, r, ncsa;
92
93 if(search == nil){
94 hfail(c, HNoData, me);
95 exits("failed");
96 }
97 okp = pt(search);
98 if(!okp.ok){
99 hfail(c, HBadSearch, me);
100 exits("failed");
101 }
102 p = okp.p;
103
104 b = Bopen(uri, OREAD);
105 if(b == nil){
106 hfail(c, HNotFound, uri);
107 exits("failed");
108 }
109
110 to = nil;
111 def = nil;
112 dst = nil;
113 close = 0.;
114 ncsa = 1;
115 while(line = Brdline(b, '\n')){
116 line[Blinelen(b)-1] = 0;
117
118 ss = getfield(line);
119 s = ss.s1;
120 line = ss.s2;
121 if(ncsa){
122 ss = getfield(line);
123 dst = ss.s1;
124 line = ss.s2;
125 }
126 if(strcmp(s, "#cern") == 0){
127 ncsa = 0;
128 continue;
129 }
130 if(strcmp(s, "rect") == 0){
131 ss = getfield(line);
132 s = ss.s1;
133 line = ss.s2;
134 okp = pt(s);
135 q = okp.p;
136 if(!okp.ok || q.x > p.x || q.y > p.y)
137 continue;
138 ss = getfield(line);
139 s = ss.s1;
140 line = ss.s2;
141 okp = pt(s);
142 q = okp.p;
143 if(!okp.ok || q.x < p.x || q.y < p.y)
144 continue;
145 if(!ncsa){
146 ss = getfield(line);
147 dst = ss.s1;
148 }
149 return dst;
150 }else if(strcmp(s, "circle") == 0){
151 ss = getfield(line);
152 s = ss.s1;
153 line = ss.s2;
154 okp = pt(s);
155 cen = okp.p;
156 if(!okp.ok)
157 continue;
158 ss = getfield(line);
159 s = ss.s1;
160 line = ss.s2;
161 if(ncsa){
162 okp = pt(s);
163 if(!okp.ok)
164 continue;
165 if(dist(okp.p, cen) >= dist(p, cen))
166 return dst;
167 }else{
168 r = strtol(s, nil, 10);
169 ss = getfield(line);
170 dst = ss.s1;
171 d = (float)r * r;
172 if(d >= dist(p, cen))
173 return dst;
174 }
175 }else if(strcmp(s, "poly") == 0){
176 ss = getfield(line);
177 s = ss.s1;
178 line = ss.s2;
179 okp = pt(s);
180 start = okp.p;
181 if(!okp.ok)
182 continue;
183 inside = 0;
184 cen = start;
185 for(n = 1; ; n++){
186 ss = getfield(line);
187 s = ss.s1;
188 line = ss.s2;
189 okp = pt(s);
190 q = okp.p;
191 if(!okp.ok)
192 break;
193 inside = polytest(inside, p, cen, q);
194 cen = q;
195 }
196 inside = polytest(inside, p, cen, start);
197 if(!ncsa)
198 dst = s;
199 if(n >= 3 && inside)
200 return dst;
201 }else if(strcmp(s, "point") == 0){
202 ss = getfield(line);
203 s = ss.s1;
204 line = ss.s2;
205 okp = pt(s);
206 q = okp.p;
207 if(!okp.ok)
208 continue;
209 d = dist(p, q);
210 if(!ncsa){
211 ss = getfield(line);
212 dst = ss.s1;
213 }
214 if(d == 0.)
215 return dst;
216 if(close == 0. || d < close){
217 close = d;
218 to = dst;
219 }
220 }else if(strcmp(s, "default") == 0){
221 if(!ncsa){
222 ss = getfield(line);
223 dst = ss.s1;
224 }
225 def = dst;
226 }
227 }
228 if(to == nil)
229 to = def;
230 return to;
231 }
232
233 int
polytest(int inside,Point p,Point b,Point a)234 polytest(int inside, Point p, Point b, Point a)
235 {
236 Point pa, ba;
237
238 if(b.y>a.y){
239 pa=sub(p, a);
240 ba=sub(b, a);
241 }else{
242 pa=sub(p, b);
243 ba=sub(a, b);
244 }
245 if(0<=pa.y && pa.y<ba.y && pa.y*ba.x<=pa.x*ba.y)
246 inside = !inside;
247 return inside;
248 }
249
250 Point
sub(Point p,Point q)251 sub(Point p, Point q)
252 {
253 p.x -= q.x;
254 p.y -= q.y;
255 return p;
256 }
257
258 float
dist(Point p,Point q)259 dist(Point p, Point q)
260 {
261 p.x -= q.x;
262 p.y -= q.y;
263 return (float)p.x * p.x + (float)p.y * p.y;
264 }
265
266 OkPoint
pt(char * s)267 pt(char *s)
268 {
269 OkPoint okp;
270 Point p;
271 char *t, *e;
272
273 if(*s == '(')
274 s++;
275 t = strchr(s, ')');
276 if(t != nil)
277 *t = 0;
278 p.x = 0;
279 p.y = 0;
280 t = strchr(s, ',');
281 if(t == nil){
282 okp.p = p;
283 okp.ok = 0;
284 return okp;
285 }
286 e = nil;
287 p.x = strtol(s, &e, 10);
288 if(e != t){
289 okp.p = p;
290 okp.ok = 0;
291 return okp;
292 }
293 p.y = strtol(t+1, &e, 10);
294 if(e == nil || *e != 0){
295 okp.p = p;
296 okp.ok = 0;
297 return okp;
298 }
299 okp.p = p;
300 okp.ok = 1;
301 return okp;
302 }
303
304 Strings
getfield(char * s)305 getfield(char *s)
306 {
307 Strings ss;
308 char *f;
309
310 while(*s == '\t' || *s == ' ')
311 s++;
312 f = s;
313 while(*s && *s != '\t' && *s != ' ')
314 s++;
315 if(*s)
316 *s++ = 0;
317 ss.s1 = f;
318 ss.s2 = s;
319 return ss;
320 }
321