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 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* 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 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 251 sub(Point p, Point q) 252 { 253 p.x -= q.x; 254 p.y -= q.y; 255 return p; 256 } 257 258 float 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 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 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