home *** CD-ROM | disk | FTP | other *** search
/ The HTML Web Publisher's Construction Kit / HTMLWPCK.ISO / unix / servers / httpd_14 / source.z / source / httpd_1.4.1 / cgi-src / imagemap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-18  |  10.4 KB  |  356 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. #endif
  57. #include <sys/types.h>
  58. #include <sys/stat.h>
  59.  
  60. #define CONF_FILE "/usr/local/etc/httpd/conf/imagemap.conf"
  61.  
  62. #define MAXLINE 500
  63. #define MAXVERTS 100
  64. #define X 0
  65. #define Y 1
  66. #define LF 10
  67. #define CR 13
  68.  
  69. int isname(char);
  70.  
  71. int main(int argc, char **argv)
  72. {
  73.     char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE];
  74.     double testpoint[2], pointarray[MAXVERTS][2];
  75.     int i, j, k;
  76.     FILE *fp;
  77.     char *t;
  78.     double dist, mindist;
  79.     int sawpoint = 0;
  80.     
  81.     if (argc != 2)
  82.         servererr("Wrong number of arguments, client may not support ISMAP.");
  83.     mapname=getenv("PATH_INFO");
  84.  
  85.     if((!mapname) || (!mapname[0]))
  86.         servererr("No map name given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>");
  87.  
  88.  
  89.     mapname++;
  90.     if(!(t = strchr(argv[1],',')))
  91.         servererr("Your client doesn't support image mapping properly.");
  92.     *t++ = '\0';
  93.     testpoint[X] = (double) atoi(argv[1]);
  94.     testpoint[Y] = (double) atoi(t);
  95.  
  96.     /*
  97.      * if the mapname contains a '/', it represents a unix path -
  98.      * we get the translated path, and skip reading the configuration file.
  99.      */
  100.     if (strchr(mapname,'/')) {
  101.       strcpy(conf,getenv("PATH_TRANSLATED"));
  102.       goto openconf;
  103.     }
  104.     
  105.     if ((fp = fopen(CONF_FILE, "r")) == NULL){
  106.         sprintf(errstr, "Couldn't open configuration file: %s", CONF_FILE);
  107.         servererr(errstr);
  108.     }
  109.  
  110.     while(!(getline(input,MAXLINE,fp))) {
  111.         char confname[MAXLINE];
  112.         if((input[0] == '#') || (!input[0]))
  113.             continue;
  114.         for(i=0;isname(input[i]) && (input[i] != ':');i++)
  115.             confname[i] = input[i];
  116.         confname[i] = '\0';
  117.         if(!strcmp(confname,mapname))
  118.             goto found;
  119.     }
  120.     /*
  121.      * if mapname was not found in the configuration file, it still
  122.      * might represent a file in the server root directory -
  123.      * we get the translated path, and check to see if a file of that
  124.      * name exists, jumping to the opening of the map file if it does.
  125.      */
  126.     if(feof(fp)) {
  127.       struct stat sbuf;
  128.       strcpy(conf,getenv("PATH_TRANSLATED"));
  129.       if (!stat(conf,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
  130.     goto openconf;
  131.       else
  132.     servererr("Map not found in configuration file.");
  133.     }
  134.     
  135.   found:
  136.     fclose(fp);
  137.     while(isspace(input[i]) || input[i] == ':') ++i;
  138.  
  139.     for(j=0;input[i] && isname(input[i]);++i,++j)
  140.         conf[j] = input[i];
  141.     conf[j] = '\0';
  142.  
  143.   openconf:
  144.     if(!(fp=fopen(conf,"r"))){
  145.     sprintf(errstr, "Couldn't open configuration file: %s", conf);
  146.         servererr(errstr);
  147.     }
  148.  
  149.     while(!(getline(input,MAXLINE,fp))) {
  150.         char type[MAXLINE];
  151.         char url[MAXLINE];
  152.         char num[10];
  153.  
  154.         if((input[0] == '#') || (!input[0]))
  155.             continue;
  156.  
  157.         type[0] = '\0';url[0] = '\0';
  158.  
  159.         for(i=0;isname(input[i]) && (input[i]);i++)
  160.             type[i] = input[i];
  161.         type[i] = '\0';
  162.  
  163.         while(isspace(input[i])) ++i;
  164.         for(j=0;input[i] && isname(input[i]);++i,++j)
  165.             url[j] = input[i];
  166.         url[j] = '\0';
  167.  
  168.         if(!strcmp(type,"default") && !sawpoint) {
  169.             strcpy(def,url);
  170.             continue;
  171.         }
  172.  
  173.         k=0;
  174.         while (input[i]) {
  175.             while (isspace(input[i]) || input[i] == ',')
  176.                 i++;
  177.             j = 0;
  178.             while (isdigit(input[i]))
  179.                 num[j++] = input[i++];
  180.             num[j] = '\0';
  181.             if (num[0] != '\0')
  182.                 pointarray[k][X] = (double) atoi(num);
  183.             else
  184.                 break;
  185.             while (isspace(input[i]) || input[i] == ',')
  186.                 i++;
  187.             j = 0;
  188.             while (isdigit(input[i]))
  189.                 num[j++] = input[i++];
  190.             num[j] = '\0';
  191.             if (num[0] != '\0')
  192.                 pointarray[k++][Y] = (double) atoi(num);
  193.             else {
  194.                 fclose(fp);
  195.                 servererr("Missing y value.");
  196.             }
  197.         }
  198.         pointarray[k][X] = -1;
  199.         if(!strcmp(type,"poly"))
  200.             if(pointinpoly(testpoint,pointarray))
  201.                 sendmesg(url);
  202.         if(!strcmp(type,"circle"))
  203.             if(pointincircle(testpoint,pointarray))
  204.                 sendmesg(url);
  205.         if(!strcmp(type,"rect"))
  206.             if(pointinrect(testpoint,pointarray))
  207.                 sendmesg(url);
  208.         if(!strcmp(type,"point")) {
  209.         /* Don't need to take square root. */
  210.         dist = ((testpoint[X] - pointarray[0][X])
  211.             * (testpoint[X] - pointarray[0][X]))
  212.            + ((testpoint[Y] - pointarray[0][Y])
  213.               * (testpoint[Y] - pointarray[0][Y]));
  214.         /* If this is the first point, or the nearest, set the default. */
  215.         if ((! sawpoint) || (dist < mindist)) {
  216.         mindist = dist;
  217.             strcpy(def,url);
  218.         }
  219.         sawpoint++;
  220.     }
  221.     }
  222.     if(def[0])
  223.         sendmesg(def);
  224.     servererr("No default specified.");
  225. }
  226.  
  227. sendmesg(char *url)
  228. {
  229.   if (strchr(url, ':'))   /*** It is a full URL ***/
  230.     printf("Location: ");
  231.   else                    /*** It is a virtual URL ***/
  232.     printf("Location: http://%s:%s", getenv("SERVER_NAME"), 
  233.            getenv("SERVER_PORT"));
  234.  
  235.     printf("%s%c%c",url,10,10);
  236.     printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10);
  237.     exit(1);
  238. }
  239.  
  240. int pointinrect(double point[2], double coords[MAXVERTS][2])
  241. {
  242.         return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
  243.         (point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
  244. }
  245.  
  246. int pointincircle(double point[2], double coords[MAXVERTS][2])
  247. {
  248.         int radius1, radius2;
  249.  
  250.         radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] -
  251.         coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] -
  252.         coords[1][X]));
  253.         radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) +
  254.         ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  255.         return (radius2 <= radius1);
  256. }
  257.  
  258. int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  259. {
  260.         int i, numverts, inside_flag, xflag0;
  261.         int crossings;
  262.         double *p, *stop;
  263.         double tx, ty, y;
  264.  
  265.         for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
  266.                 ;
  267.         numverts = i;
  268.         crossings = 0;
  269.  
  270.         tx = point[X];
  271.         ty = point[Y];
  272.         y = pgon[numverts - 1][Y];
  273.  
  274.         p = (double *) pgon + 1;
  275.         if ((y >= ty) != (*p >= ty)) {
  276.                 if ((xflag0 = (pgon[numverts - 1][X] >= tx)) ==
  277.                 (*(double *) pgon >= tx)) {
  278.                         if (xflag0)
  279.                                 crossings++;
  280.                 }
  281.                 else {
  282.                         crossings += (pgon[numverts - 1][X] - (y - ty) *
  283.                         (*(double *) pgon - pgon[numverts - 1][X]) /
  284.                         (*p - y)) >= tx;
  285.                 }
  286.         }
  287.  
  288.         stop = pgon[numverts];
  289.  
  290.         for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  291.                 if (y >= ty) {
  292.                         while ((p < stop) && (*p >= ty))
  293.                                 p += 2;
  294.                         if (p >= stop)
  295.                                 break;
  296.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  297.                                 if (xflag0)
  298.                                         crossings++;
  299.                         }
  300.                         else {
  301.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  302.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  303.                         }
  304.                 }
  305.                 else {
  306.                         while ((p < stop) && (*p < ty))
  307.                                 p += 2;
  308.                         if (p >= stop)
  309.                                 break;
  310.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  311.                                 if (xflag0)
  312.                                         crossings++;
  313.                         }
  314.                         else {
  315.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  316.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  317.                         }
  318.                 }
  319.         }
  320.         inside_flag = crossings & 0x01;
  321.         return (inside_flag);
  322. }
  323.  
  324. servererr(char *msg)
  325. {
  326.     printf("Content-type: text/html%c%c",10,10);
  327.     printf("<title>Mapping Server Error</title>");
  328.     printf("<h1>Mapping Server Error</h1>");
  329.     printf("This server encountered an error:<p>");
  330.     printf("%s", msg);
  331.     exit(-1);
  332. }
  333.  
  334. int isname(char c)
  335. {
  336.         return (!isspace(c));
  337. }
  338.  
  339. int getline(char *s, int n, FILE *f) {
  340.     register int i=0;
  341.  
  342.     while(1) {
  343.         s[i] = (char)fgetc(f);
  344.  
  345.         if(s[i] == CR)
  346.             s[i] = fgetc(f);
  347.  
  348.         if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
  349.             s[i] = '\0';
  350.             return (feof(f) ? 1 : 0);
  351.         }
  352.         ++i;
  353.     }
  354. }
  355.  
  356.