home *** CD-ROM | disk | FTP | other *** search
/ CGI How-To / CGI HOW-TO.iso / chap3 / 3_1 / imagemap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-15  |  10.9 KB  |  369 lines

  1. /*
  2. ** mapper 1.2
  3. ** 7/26/93 Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
  4. ** "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
  5. ** All suggestions, help, etc. gratefully accepted!
  6. **
  7. ** 1.1 : Better formatting, added better polygon code.
  8. ** 1.2 : Changed isname(), added config file specification.
  9. **
  10. ** 11/13/93: Rob McCool, robm@ncsa.uiuc.edu
  11. **
  12. ** 1.3 : Rewrote configuration stuff for NCSA /htbin script
  13. **
  14. ** 12/05/93: Rob McCool, robm@ncsa.uiuc.edu
  15. ** 
  16. ** 1.4 : Made CGI/1.0 compliant.
  17. **
  18. ** 06/27/94: Chris Hyams, cgh@rice.edu
  19. **          Based on an idea by Rick Troth (troth@rice.edu)
  20. ** 
  21. ** 1.5 : Imagemap configuration file in PATH_INFO.  Backwards compatible.
  22. **
  23. **  Old-style lookup in imagemap table:
  24. **    <a href="http://foo.edu/cgi-bin/imagemap/oldmap">
  25. **
  26. **  New-style specification of mapfile relative to DocumentRoot:
  27. **    <a href="http://foo.edu/cgi-bin/imagemap/path/for/new.map">
  28. **
  29. **  New-style specification of mapfile in user's public HTML directory:
  30. **    <a href="http://foo.edu/cgi-bin/imagemap/~username/path/for/new.map">
  31. **
  32. ** 07/11/94: Craig Milo Rogers, Rogers@ISI.Edu
  33. **
  34. ** 1.6 : Added "point" datatype: the nearest point wins.  Overrides "default".
  35. **
  36. ** 08/28/94: Carlos Varela, cvarela@ncsa.uiuc.edu
  37. **
  38. ** 1.7 : Fixed bug:  virtual URLs are now understood.
  39. **       Better error reporting when not able to open configuration file.
  40. **
  41. ** 03/07/95: Carlos Varela, cvarela@ncsa.uiuc.edu
  42. **
  43. ** 1.8 : Fixed bug (strcat->sprintf) when reporting error.
  44. **       Included getline() function from util.c in NCSA httpd distribution.
  45. **
  46. */
  47.  
  48. #include <stdio.h>
  49. #include <string.h>
  50. #if !defined(pyr) && !defined(NO_STDLIB_H)
  51. #include <stdlib.h>
  52. #else
  53. #include <sys/types.h>
  54. #include <ctype.h>
  55. char *getenv();
  56. #include <ctype.h>
  57. #endif
  58. #include <sys/types.h>
  59. /* #include "util.h" */
  60. #include <sys/stat.h>
  61.  
  62. #define CONF_FILE "/usr/local/etc/httpd/conf/imagemap.conf"
  63.  
  64. #define MAXLINE 500
  65. #define MAXVERTS 100
  66. #define X 0
  67. #define Y 1
  68. #define LF 10
  69. #define CR 13
  70.  
  71.  
  72. static void servererr(char *msg);
  73. static void sendmesg(char *url);
  74. static int pointinpoly(double point[2], double pgon[MAXVERTS][2]);
  75. static int pointincircle(double point[2], double coords[MAXVERTS][2]);
  76. static int pointinrect(double point[2], double coords[MAXVERTS][2]);
  77.  
  78. int isname(char);
  79.  
  80. int main(int argc, char **argv)
  81. {
  82.     char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE];
  83.     double testpoint[2], pointarray[MAXVERTS][2];
  84.     int i, j, k;
  85.     FILE *fp;
  86.     char *t;
  87.     double dist, mindist;
  88.     int sawpoint = 0;
  89.     
  90.     if (argc != 2)
  91.         servererr("Wrong number of arguments, client may not support ISMAP.");
  92.     mapname=getenv("PATH_INFO");
  93.  
  94.     if((!mapname) || (!mapname[0]))
  95.         servererr("No map name given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>");
  96.  
  97.  
  98.     mapname++;
  99.     if(!(t = strchr(argv[1],',')))
  100.         servererr("Your client doesn't support image mapping properly.");
  101.     *t++ = '\0';
  102.     testpoint[X] = (double) atoi(argv[1]);
  103.     testpoint[Y] = (double) atoi(t);
  104.  
  105.     /*
  106.      * if the mapname contains a '/', it represents a unix path -
  107.      * we get the translated path, and skip reading the configuration file.
  108.      */
  109.     if (strchr(mapname,'/')) {
  110.       strcpy(conf,getenv("PATH_TRANSLATED"));
  111.       goto openconf;
  112.     }
  113.     
  114.     if ((fp = fopen(CONF_FILE, "r")) == NULL){
  115.         sprintf(errstr, "Couldn't open configuration file: %s", CONF_FILE);
  116.         servererr(errstr);
  117.     }
  118.  
  119.     while(!(getline(input,MAXLINE,fp))) {
  120.         char confname[MAXLINE];
  121.         if((input[0] == '#') || (!input[0]))
  122.             continue;
  123.         for(i=0;isname(input[i]) && (input[i] != ':');i++)
  124.             confname[i] = input[i];
  125.         confname[i] = '\0';
  126.         if(!strcmp(confname,mapname))
  127.             goto found;
  128.     }
  129.     /*
  130.      * if mapname was not found in the configuration file, it still
  131.      * might represent a file in the server root directory -
  132.      * we get the translated path, and check to see if a file of that
  133.      * name exists, jumping to the opening of the map file if it does.
  134.      */
  135.     if(feof(fp)) {
  136.       struct stat sbuf;
  137.       strcpy(conf,getenv("PATH_TRANSLATED"));
  138.       if (!stat(conf,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
  139.     goto openconf;
  140.       else
  141.     servererr("Map not found in configuration file.");
  142.     }
  143.     
  144.   found:
  145.     fclose(fp);
  146.     while(isspace(input[i]) || input[i] == ':') ++i;
  147.  
  148.     for(j=0;input[i] && isname(input[i]);++i,++j)
  149.         conf[j] = input[i];
  150.     conf[j] = '\0';
  151.  
  152.   openconf:
  153.     if(!(fp=fopen(conf,"r"))){
  154.     sprintf(errstr, "Couldn't open configuration file: %s", conf);
  155.         servererr(errstr);
  156.     }
  157.  
  158.     while(!(getline(input,MAXLINE,fp))) {
  159.         char type[MAXLINE];
  160.         char url[MAXLINE];
  161.         char num[10];
  162.  
  163.         if((input[0] == '#') || (!input[0]))
  164.             continue;
  165.  
  166.         type[0] = '\0';url[0] = '\0';
  167.  
  168.         for(i=0;isname(input[i]) && (input[i]);i++)
  169.             type[i] = input[i];
  170.         type[i] = '\0';
  171.  
  172.         while(isspace(input[i])) ++i;
  173.         for(j=0;input[i] && isname(input[i]);++i,++j)
  174.             url[j] = input[i];
  175.         url[j] = '\0';
  176.  
  177.         if(!strcmp(type,"default") && !sawpoint) {
  178.             strcpy(def,url);
  179.             continue;
  180.         }
  181.  
  182.         k=0;
  183.         while (input[i]) {
  184.             while (isspace(input[i]) || input[i] == ',')
  185.                 i++;
  186.             j = 0;
  187.             while (isdigit(input[i]))
  188.                 num[j++] = input[i++];
  189.             num[j] = '\0';
  190.             if (num[0] != '\0')
  191.                 pointarray[k][X] = (double) atoi(num);
  192.             else
  193.                 break;
  194.             while (isspace(input[i]) || input[i] == ',')
  195.                 i++;
  196.             j = 0;
  197.             while (isdigit(input[i]))
  198.                 num[j++] = input[i++];
  199.             num[j] = '\0';
  200.             if (num[0] != '\0')
  201.                 pointarray[k++][Y] = (double) atoi(num);
  202.             else {
  203.                 fclose(fp);
  204.                 servererr("Missing y value.");
  205.             }
  206.         }
  207.         pointarray[k][X] = -1;
  208.         if(!strcmp(type,"poly"))
  209.             if(pointinpoly(testpoint,pointarray))
  210.                 sendmesg(url);
  211.         if(!strcmp(type,"circle"))
  212.             if(pointincircle(testpoint,pointarray))
  213.                 sendmesg(url);
  214.         if(!strcmp(type,"rect"))
  215.             if(pointinrect(testpoint,pointarray))
  216.                 sendmesg(url);
  217.         if(!strcmp(type,"point")) {
  218.         /* Don't need to take square root. */
  219.         dist = ((testpoint[X] - pointarray[0][X])
  220.             * (testpoint[X] - pointarray[0][X]))
  221.            + ((testpoint[Y] - pointarray[0][Y])
  222.               * (testpoint[Y] - pointarray[0][Y]));
  223.         /* If this is the first point, or the nearest, set the default. */
  224.         if ((! sawpoint) || (dist < mindist)) {
  225.         mindist = dist;
  226.             strcpy(def,url);
  227.         }
  228.         sawpoint++;
  229.     }
  230.     }
  231.     if(def[0])
  232.         sendmesg(def);
  233.     servererr("No default specified.");
  234. }
  235.  
  236. static void sendmesg(char *url)
  237. {
  238.   if (strchr(url, ':'))   /*** It is a full URL ***/
  239.     printf("Location: ");
  240.   else {                   /*** It is a virtual URL ***/
  241.     char *port;
  242.     printf("Location: http://%s", getenv("SERVER_NAME"));
  243.  
  244.       /* only add port if it's not the default */
  245.      if ((port = getenv("SERVER_PORT")) && strcmp(port,"80"))
  246.       printf(":%s",port);
  247.     }
  248.     printf("%s%c%c",url,10,10);
  249.     printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10);
  250.     exit(1);
  251. }
  252.  
  253. static int pointinrect(double point[2], double coords[MAXVERTS][2])
  254. {
  255.         return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
  256.         (point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
  257. }
  258.  
  259. static int pointincircle(double point[2], double coords[MAXVERTS][2])
  260. {
  261.         int radius1, radius2;
  262.  
  263.         radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] -
  264.         coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] -
  265.         coords[1][X]));
  266.         radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) +
  267.         ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  268.         return (radius2 <= radius1);
  269. }
  270.  
  271. static int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  272. {
  273.         int i, numverts, inside_flag, xflag0;
  274.         int crossings;
  275.         double *p, *stop;
  276.         double tx, ty, y;
  277.  
  278.         for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
  279.                 ;
  280.         numverts = i;
  281.         crossings = 0;
  282.  
  283.         tx = point[X];
  284.         ty = point[Y];
  285.         y = pgon[numverts - 1][Y];
  286.  
  287.         p = (double *) pgon + 1;
  288.         if ((y >= ty) != (*p >= ty)) {
  289.                 if ((xflag0 = (pgon[numverts - 1][X] >= tx)) ==
  290.                 (*(double *) pgon >= tx)) {
  291.                         if (xflag0)
  292.                                 crossings++;
  293.                 }
  294.                 else {
  295.                         crossings += (pgon[numverts - 1][X] - (y - ty) *
  296.                         (*(double *) pgon - pgon[numverts - 1][X]) /
  297.                         (*p - y)) >= tx;
  298.                 }
  299.         }
  300.  
  301.         stop = pgon[numverts];
  302.  
  303.         for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  304.                 if (y >= ty) {
  305.                         while ((p < stop) && (*p >= ty))
  306.                                 p += 2;
  307.                         if (p >= stop)
  308.                                 break;
  309.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  310.                                 if (xflag0)
  311.                                         crossings++;
  312.                         }
  313.                         else {
  314.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  315.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  316.                         }
  317.                 }
  318.                 else {
  319.                         while ((p < stop) && (*p < ty))
  320.                                 p += 2;
  321.                         if (p >= stop)
  322.                                 break;
  323.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  324.                                 if (xflag0)
  325.                                         crossings++;
  326.                         }
  327.                         else {
  328.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  329.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  330.                         }
  331.                 }
  332.         }
  333.         inside_flag = crossings & 0x01;
  334.         return (inside_flag);
  335. }
  336.  
  337. static void servererr(char *msg)
  338. {
  339.     printf("Content-type: text/html%c%c",10,10);
  340.     printf("<title>Mapping Server Error</title>");
  341.     printf("<h1>Mapping Server Error</h1>");
  342.     printf("This server encountered an error:<p>");
  343.     printf("%s", msg);
  344.     exit(-1);
  345. }
  346.  
  347. int isname(char c)
  348. {
  349.         return (!isspace(c));
  350. }
  351.  
  352. int getline(char *s, int n, FILE *f) {
  353.     register int i=0;
  354.  
  355.     while(1) {
  356.         s[i] = (char)fgetc(f);
  357.  
  358.         if(s[i] == CR)
  359.             s[i] = fgetc(f);
  360.  
  361.         if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
  362.             s[i] = '\0';
  363.             return (feof(f) ? 1 : 0);
  364.         }
  365.         ++i;
  366.     }
  367. }
  368.  
  369.