imagemap.c 5.1 KB

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