map.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:12k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** map.c
  3. **
  4. ** Copyright (c) 1994-1997 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <string.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <errno.h>
  26. #include <math.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include "phttpd.h"
  30. static char *get_next_line(char *buf, char *last_char,
  31.    char *line, int line_size,
  32.    char *comment, int comment_size)
  33. {
  34.     char ch;
  35.     char *last_line_char = line+line_size-1;
  36.     char *last_cmt_char = comment+comment_size-1;
  37.     if ( buf >= last_char )
  38. return NULL;
  39.     /* Read up to comment or end of line */
  40.     for ( ch = *buf;
  41.   ch != 'n' && ch != 'r' && ch != '#'
  42.      && line < last_line_char && buf < last_char ;
  43.   ch = *++buf )
  44.     {
  45. *line++ = ch;
  46.     }
  47.     /* Read up to end of line */
  48.     for ( ;
  49.   ch != 'n' && ch != 'r' && comment < last_cmt_char && buf < last_char ;
  50.   ch = *++buf )
  51.     {
  52. *comment++ = ch;
  53.     }
  54.     /* Read up to end of line */
  55.     for ( ;
  56.   ch != 'n' && ch != 'r' && buf < last_char ;
  57.   ch = *++buf )
  58. ;
  59.     *line = *comment = '';
  60.     return(buf+1);
  61. }
  62. static void print_map_line(int fd, int have_xy, char *url, char *comment)
  63. {
  64.     int flag = 0;
  65.     if ( have_xy )
  66. return;
  67.     if ( url )
  68. if ( url[0] != '' )
  69. {
  70.     fd_printf(fd, "<A HREF="%s">%s</A> ", url, url);
  71.     flag = 1;
  72. }
  73.     if ( comment )
  74. if ( comment[0] != '' )
  75. {
  76.     fd_puts(comment, fd);
  77.     flag = 1;
  78. }
  79.     if ( flag )
  80. fd_puts("<BR>n", fd);
  81. }
  82. struct pair
  83. {
  84.     int x;
  85.     int y;
  86. };
  87. static int in_cern_circle(int rq_x,
  88.   int rq_y,
  89.   struct pair *p,
  90.   int r)
  91. {
  92.     int dx, dy;
  93.     
  94.     dx = (rq_x - p->x);
  95.     dy = (rq_y - p->y);
  96.     return ( (dx*dx+dy*dy) <= r*r );
  97. }
  98. static int in_ncsa_circle(int rq_x,
  99.   int rq_y,
  100.   struct pair *p1,
  101.   struct pair *p2)
  102. {
  103.     int dx1, dy1;
  104.     int dx2, dy2;
  105.     
  106.     
  107.     dx1 = (p1->x - p2->x);
  108.     dy1 = (p1->y - p2->y);
  109.     dx2 = (rq_x - p1->x);
  110.     dy2 = (rq_y - p1->y);
  111.     return ( (dx1*dx1+dy1*dy1) >= (dx2*dx2+dy2*dy2) );
  112. }
  113. static int in_rectangle(int rq_x,
  114. int rq_y,
  115. struct pair *p1,
  116. struct pair *p2)
  117. {
  118.     if (rq_x >= p1->x && rq_x <= p2->x &&
  119. rq_y >= p1->y && rq_y <= p2->y)
  120. return 1;
  121.     else
  122. return 0;
  123. }
  124. static int max(int v1, int v2)
  125. {
  126.     return v1 > v2 ? v1 : v2;
  127. }
  128. static int min(int v1, int v2)
  129. {
  130.     return v1 < v2 ? v1 : v2;
  131. }
  132. static int in_polygon(int rq_x, int rq_y,
  133.       struct table *tp)
  134. {
  135.     int i, n;
  136.     int dx, dy;
  137.     
  138.     
  139.     n = 0;
  140.     
  141.     for (i = 0; i+1 < tp->length; i++)
  142.     {
  143. struct pair *p0, *p1;
  144. p0 = tp->value[i];
  145. p1 = tp->value[i+1];
  146.     
  147. dx = p1->x - p0->x;
  148. dy = p1->y - p0->y;
  149. if ( dy < 0 )
  150. {
  151.     dx = -dx;
  152.     dy = -dy;
  153. }
  154. if (max(p1->y, p0->y) > rq_y &&
  155.     min(p1->y, p0->y) < rq_y &&
  156.     (rq_y - p0->y) * dx > (rq_x - p0->x) * dy)
  157. {
  158.     n++;
  159. }
  160.     }
  161.     return n & 1;
  162. }
  163. static struct options map_cfg_table[] =
  164. {
  165.     { NULL,                 -1,       NULL, NULL }
  166. };
  167. int pm_init(const char **argv)
  168. {
  169.     char *cfg_path, *cp;
  170.     const char *name = argv[0];
  171.     int cfgsize;
  172.     
  173.     if (debug > 1)
  174. fprintf(stderr, "*** libmap/pm_init("%s") called ***n", name);
  175.     cfgsize = strlen(name)+6;
  176.     cfg_path = s_malloc(cfgsize);
  177.     s_strcpy(cfg_path, cfgsize, name);
  178.     
  179.     cp = strrchr(cfg_path, '.');
  180.     if (cp && strcmp(cp, ".so") == 0)
  181. *cp = '';
  182.     
  183.     s_strcat(cfg_path, cfgsize, ".conf");
  184.     if (config_parse_file(cfg_path, map_cfg_table, 0) < 0)
  185. return -1;
  186.     if (config_parse_argv(argv+1, map_cfg_table) < 0)
  187. return -1;
  188.     return 0;
  189. }
  190. void pm_exit(void)
  191. {
  192.     if (debug > 1)
  193. fprintf(stderr, "*** libmap/pm_exit() called ***n");
  194. }
  195. static int get_int(char **cp, int *val)
  196. {
  197.     while (s_isspace(**cp))
  198. ++*cp;
  199.     if (!s_isdigit(**cp))
  200. return 0;
  201.     *val = 0;
  202.     
  203.     while (s_isdigit(**cp))
  204.     {
  205. *val *= 10;
  206. *val += **cp - '0';
  207. ++*cp;
  208.     }
  209.     return 1;
  210. }
  211. static int get_string(char **cp, char *buf, int size)
  212. {
  213.     int i;
  214.     buf[0] = '';
  215.     if (cp == NULL || *cp == NULL)
  216. return 0;
  217.     
  218.     while (s_isspace(**cp))
  219. ++*cp;
  220.     i = 0;
  221.     while (**cp && !s_isspace(**cp) && i < size-1)
  222.     {
  223. buf[i++] = **cp;
  224. ++*cp;
  225.     }
  226.     buf[i] = '';
  227.     return i;
  228. }
  229. static int get_pair(char **cp, struct pair *pp)
  230. {
  231.     while (s_isspace(**cp))
  232. ++*cp;
  233.     if (**cp == '(')
  234.       ++*cp;
  235.     
  236.     if (!get_int(cp, &pp->x))
  237. return 0;
  238.     while (s_isspace(**cp))
  239. ++*cp;
  240.     if (**cp != ',')
  241. return 0;
  242.     ++*cp;
  243.     
  244.     if (!get_int(cp, &pp->y))
  245. return 0;
  246.     while (s_isspace(**cp))
  247. ++*cp;
  248.     if (**cp == ')' || **cp ==',')
  249.       ++*cp;
  250.     return 1;
  251. }
  252. static int http_get_head(struct connectioninfo *cip)
  253. {
  254.     char default_url[2048], url_buf[2048];
  255.     int dist, mindist, sawpoint;
  256.     char *map_p, *map_last, comment[2048], line[2048];
  257.     int have_label;
  258.     int have_xy;
  259.     int rq_x, rq_y;
  260.     int result = 0;
  261.     fscentry_t *fep;
  262.     fsinfo_t *fip;
  263.     
  264.     char *statement;
  265.     char *rest;
  266.     char *buf_p;
  267.     char *url;
  268.     int fd = cip->fd;
  269.     struct httpinfo *hip = cip->hip;
  270.     unsigned int fsc_flags = 0;
  271.     url = NULL;
  272.     
  273.     if (debug > 1)
  274. fprintf(stderr, "*** libmap/http_get_head() called ***n");
  275.     if (hip && hip->mip && (hip->mip->pragma_flags & MPF_NOCACHE))
  276. fsc_flags = FSCF_RELOAD;
  277.     
  278.     fep = fscache_lookup(hip->url, FSCF_GETDATA+fsc_flags);
  279.     if (fep == NULL)
  280. return -1;
  281.     fip = fep->fip;
  282.     if (fip == NULL)
  283.     {
  284. fscache_release(fep);
  285. return -1;
  286.     }
  287.     map_p = fip->data.file.content;
  288.     map_last = map_p + fip->sb.st_size;
  289.     
  290.     default_url[0] = '';
  291.     mindist = 999999;
  292.     sawpoint = 0;
  293.     have_label = 0;
  294.     have_xy = 0;
  295.     
  296.     if (hip->request)
  297.     {
  298. if (strcmp(hip->request, "xyzzy") == 0)
  299. {
  300.     rq_x = (unsigned) rand() % 500;
  301.     rq_y = (unsigned) rand() % 500;
  302.     have_xy = 1;
  303. }
  304. else if (sscanf(hip->request, " %d , %d", &rq_x, &rq_y) == 2)
  305. {
  306.     if (debug > 4)
  307. fprintf(stderr, "libmap: Got request: %d , %dn", rq_x, rq_y);
  308.     
  309.     have_xy = 1;
  310. }
  311.     }
  312.     else
  313.     {
  314. if (debug > 4)
  315.     fprintf(stderr, "libmap: Got NULL default requestn");
  316. have_label = 1;
  317.     }
  318.     
  319.     if ( !have_xy )
  320.     {
  321. if (debug > 4)
  322.     fprintf(stderr, "libmap: Got improper coordinatesn");
  323. result = 200;
  324. if (hip->mip != NULL)
  325. {
  326.     http_sendheaders(fd, cip, result, NULL);
  327.     http_sendlastmodified(fd, cip->cn_time);
  328.     
  329.     fd_puts("Content-Type: text/htmln", fd);
  330. }
  331. if (hip->mip != NULL)
  332.     fd_putc('n', fd);
  333. if (strcasecmp(hip->method, "HEAD") == 0)
  334. {
  335.     fscache_release(fep);
  336.     return result;
  337. }
  338. html_sysheader(fd, "H1", "Improper map coordinates");
  339. fd_puts("Your browser does not appear to support image maps.n", fd);
  340. fd_puts("Attempting textual display.n<hr>n", fd);
  341.     }
  342.     while ((map_p = get_next_line(map_p, map_last,
  343.   line, sizeof(line),
  344.   comment, sizeof(comment))))
  345.     {
  346. char *cp;
  347. if (debug > 4)
  348.     fprintf(stderr, "libmap: Got MAPFILE line: %s", line);
  349. *url_buf = '';
  350. cp = line;
  351. while (s_isspace(*cp))
  352.     ++cp;
  353. if (*cp == '')
  354. {
  355.     print_map_line(fd, have_xy, NULL, comment);
  356.     continue;
  357. }
  358. if (debug > 4)
  359.     fprintf(stderr, "Got line: %sn", line);
  360. buf_p = cp;
  361. statement = strtok_r(cp, " t", &buf_p);
  362. if (statement == NULL)
  363. {
  364.     print_map_line(fd, have_xy, NULL, comment);
  365.     continue;
  366. }
  367. rest = strtok_r(NULL, "nr", &buf_p);
  368. if (strcmp(statement, "circle") == 0 ||
  369.     strcmp(statement, "circ") == 0)
  370. {
  371.     struct pair p1, p2;
  372.     int r;
  373.     if (get_pair(&rest, &p1) &&
  374. get_int(&rest, &r) &&
  375. get_string(&rest, url_buf, sizeof(url_buf)))
  376.     {
  377. if (have_xy && in_cern_circle(rq_x, rq_y, &p1, r))
  378. {
  379.     url = url_buf;
  380.     goto Found;
  381. }
  382.     } else if (get_string(&rest, url_buf, sizeof(url_buf)) &&
  383.        get_pair(&rest, &p1) &&
  384.        get_pair(&rest, &p2))
  385.     {
  386. if (have_xy && in_ncsa_circle(rq_x, rq_y, &p1, &p2))
  387. {
  388.     url = url_buf;
  389.     goto Found;
  390. }
  391.     }
  392. }
  393. else if (strcmp(statement, "rectangle") == 0 ||
  394.  strcmp(statement, "rect") == 0)
  395. {
  396.     struct pair p1, p2;
  397.     
  398.     if ((get_pair(&rest, &p1) && 
  399.  get_pair(&rest, &p2) &&
  400.  get_string(&rest, url_buf, sizeof(url_buf))) ||
  401. (get_string(&rest, url_buf, sizeof(url_buf)) &&
  402.  get_pair(&rest, &p1) && 
  403.  get_pair(&rest, &p2)))
  404.     {
  405. if (have_xy && in_rectangle(rq_x, rq_y, &p1, &p2))
  406. {
  407.     url = url_buf;
  408.     goto Found;
  409. }
  410.     }
  411. }
  412. else if (strcmp(statement, "polygon") == 0 ||
  413.  strcmp(statement, "poly") == 0)
  414. {
  415.     struct table *tp;
  416.     int found;
  417.     struct pair *first_p;
  418.     struct pair *pp;
  419.     
  420.     first_p = NULL;
  421.     pp = NULL;
  422.     found = 0;
  423.     url = NULL;
  424.     
  425.     tp = tbl_create(0);
  426.     
  427.     pp = s_malloc(sizeof(struct pair));
  428.     
  429.     if (get_pair(&rest, pp)) /* CERN style */
  430. first_p = pp;
  431.     else /* NCSA style */
  432. if (get_string(&rest, url_buf, sizeof(url_buf)) &&
  433.     get_pair(&rest, pp))
  434. {
  435.     first_p = pp;
  436.     url = url_buf;
  437. }
  438.     if (first_p)
  439.     {
  440. tbl_append(tp, pp);
  441. pp = s_malloc(sizeof(struct pair));
  442. while (get_pair(&rest, pp))
  443. {
  444.     tbl_append(tp, pp);
  445.     pp = s_malloc(sizeof(struct pair));
  446. }
  447. if (pp->x != first_p->x || pp->y != first_p->y)
  448. {
  449.     pp->x = first_p->x;
  450.     pp->y = first_p->y;
  451.     
  452.     tbl_append(tp, pp);
  453.     pp = NULL;
  454. }
  455. if (url == NULL)
  456.     if (get_string(&rest, url_buf, sizeof(url_buf)))
  457. url = url_buf;
  458. found = (have_xy && in_polygon(rq_x, rq_y, tp));
  459.     }
  460.     if (pp)
  461. s_free(pp);
  462.     
  463.     tbl_free(tp, s_free);
  464.     if (found)
  465. goto Found;
  466. }
  467. else if (strcmp(statement, "point") == 0)
  468. {
  469.     struct pair p;
  470.     
  471.     if ((get_pair(&rest, &p) &&
  472.  get_string(&rest, url_buf, sizeof(url_buf))) ||
  473. (get_string(&rest, url_buf, sizeof(url_buf)) &&
  474.  get_pair(&rest, &p)))
  475.     {
  476. if ( have_xy )
  477. {
  478.     dist = (rq_x-p.x)*(rq_x-p.x) + (rq_y-p.y)*(rq_y-p.y);
  479.     if ( !sawpoint || dist < mindist )
  480.     {
  481. mindist = dist;
  482. s_strcpy(default_url, sizeof(default_url), url_buf);
  483.     }
  484.     sawpoint++;
  485. }
  486.     }
  487. }
  488. else if (strcmp(statement, "default") == 0 ||
  489.  strcmp(statement, "def") == 0)
  490. {
  491.     if (!sawpoint && get_string(&rest, url_buf, sizeof(url_buf)))
  492. if ( have_xy )
  493.     s_strcpy(default_url, sizeof(default_url), url_buf);
  494. }
  495. else
  496.     if (debug)
  497. fprintf(stderr, "Illegal statement in MAP file: %sn",
  498. statement);
  499. print_map_line(fd, have_xy, url_buf, comment);
  500.     }
  501.     if ( have_xy )
  502.     {
  503. if (default_url[0] == '')
  504. {
  505.     result = 204;
  506.     
  507.     if (hip->mip != NULL)
  508.     {
  509. http_sendheaders(fd, cip, result, NULL);
  510. http_sendlastmodified(fd, cip->cn_time);
  511.     
  512. fd_puts("Content-Type: text/htmln", fd);
  513.     }
  514.     if (strcasecmp(hip->method, "HEAD") == 0)
  515.     {
  516. fscache_release(fep);
  517. return result;
  518.     }
  519.     if (hip->mip != NULL)
  520. fd_putc('n', fd);
  521.     html_sysheader(fd, "H2", "No default");
  522.     fd_puts("No default URL was specified in the map file.n", fd);
  523.     html_sysfooter(fd);
  524.     goto End;
  525. }
  526.     } else {
  527. html_sysfooter(fd);
  528. goto End;
  529.     }
  530.     url = default_url;
  531.   Found:
  532.     if (debug > 1)
  533. fprintf(stderr, "Sending Redirect: %sn", url);
  534.     result = http_redirect(cip, url, NULL, NULL, 302);
  535.     
  536.   End:
  537.     fscache_release(fep);
  538.     if (debug > 2)
  539. fprintf(stderr, "libmap/http_get_head: Returningn");
  540.     
  541.     return result;
  542. }
  543. int pm_request(struct connectioninfo *cip)
  544. {
  545.     struct httpinfo *hip = cip->hip;
  546.     
  547.     if (strcasecmp(hip->method, "GET") == 0 ||
  548. strcasecmp(hip->method, "HEAD") == 0)
  549. return http_get_head(cip);
  550.     else
  551. return -2;
  552. }