home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 2 / AUCD2.iso / internet / httpserv.arc / source / c / imagemap
Text File  |  1995-11-10  |  12KB  |  414 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. ** 20/10/95: Stewart Brodie, s.n.brodie@ecs.soton.ac.uk
  47. **
  48. ** 1.9 : Port to Acorn RISC OS and changes for my own HTTPServer
  49. **       It isn't pretty but that's not the point
  50. **
  51. */
  52.  
  53. #include <stdio.h>
  54. #include <string.h>
  55. #if !defined(pyr) && !defined(NO_STDLIB_H)
  56. #include <stdlib.h>
  57. #else
  58. #include <sys/types.h>
  59. #include <ctype.h>
  60. char *getenv();
  61. #endif
  62. #include <sys/types.h>
  63. #include <sys/socket.h>
  64. #include <netinet/in.h>
  65. #include <netdb.h>
  66. #include <arpa/inet.h>
  67.  
  68. #define RCONF_FILE "<HTTPServer$Dir>.imap_"
  69.  
  70. #define MAXLINE 500
  71. #define MAXVERTS 100
  72. #define X 0
  73. #define Y 1
  74. #define LF 10
  75. #define CR 13
  76.  
  77. static int sockid = -1;
  78. static char *myhost = NULL;
  79. struct sockaddr_in osin;
  80.  
  81. int isname(char);
  82. int getline(char *s, int n, FILE *f);
  83. int pointinpoly(double point[2], double pgon[MAXVERTS][2]);
  84. int pointinrect(double point[2], double coords[MAXVERTS][2]);
  85. int pointincircle(double point[2], double coords[MAXVERTS][2]);
  86. void sendmesg(char *url);
  87.  
  88. void servererr(char *msg)
  89. {
  90. #define CSTRANDLEN(obj) obj,sizeof(obj)-1
  91. #define STRANDLEN(obj) obj, strlen(obj)
  92.     send(sockid, CSTRANDLEN("HTTP/1.0 500 Server Error\nContent-type: text/html\n\n<title>Mapping Server Error</title><h1>Mapping Server Error</h1>This server encountered an error:<p>"), 0);
  93.     send(sockid, STRANDLEN(msg), 0);
  94.     exit(-1);
  95. }
  96.  
  97. void sendmesg(char *url)
  98. {
  99.   struct hostent *h = gethostbyaddr((char *)&osin.sin_addr, 4, AF_INET);
  100.   
  101.   if (!h) {
  102.           myhost = inet_ntoa(osin.sin_addr);
  103.   }
  104.   else {
  105.           myhost = h->h_name;
  106.   }
  107.  
  108.   send(sockid, CSTRANDLEN("HTTP/1.0 302 Imagemap redirection\n"), 0);
  109.  
  110.   if (strchr(url, ':'))   /*** It is a full URL ***/
  111.     send(sockid, CSTRANDLEN("Location: "), 0);
  112.   else                    /*** It is a virtual URL ***/ {
  113.           char buffer[512];
  114.     sprintf(buffer, "Location: http://%s:%d", myhost, 
  115.            htons(osin.sin_port));
  116.     send(sockid, STRANDLEN(buffer), 0);
  117.   }
  118.  
  119.     send(sockid, STRANDLEN(url), 0);
  120.     send(sockid, CSTRANDLEN("\n\nThis document has moved <A HREF=\""), 0);
  121.     send(sockid, STRANDLEN(url), 0);
  122.     send(sockid, CSTRANDLEN("\">here</A>\n"), 0);
  123.     exit(1);
  124. }
  125.  
  126. static char *var_name(int port, int s)
  127. {
  128.         static char buf[256];
  129.     sprintf(buf, "HTTPServer$%d$%d$Query", port, s);
  130.         return buf;
  131. }
  132.  
  133. static void atexit_func(void)
  134. {
  135.         if (sockid > -1) close(sockid);
  136. }
  137.  
  138. int main(int argc, char **argv)
  139. {
  140.     char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE];
  141.     char CONF_FILE[256];
  142.     double testpoint[2], pointarray[MAXVERTS][2];
  143.     int i, j, k;
  144.     FILE *fp;
  145.     char *t;
  146.     double dist, mindist;
  147.     int sawpoint = 0;
  148.  
  149.     int ctr;
  150.     int ssize = sizeof(osin);
  151.     char *par;
  152.     
  153.     for (ctr=1; ctr<argc; ++ctr) {
  154.             if (!strcmp(argv[ctr], "-socket")) {
  155.                     sockid = atoi(argv[ctr+1]);
  156.                     if (!isdigit(argv[ctr+1])) { exit(-1); }
  157.                     atexit(atexit_func);
  158.             }
  159.     }
  160.  
  161.     if (sockid == -1) { exit(-1); }
  162.  
  163.     if (getsockname(sockid, (struct sockaddr *)&osin, &ssize) < 0) {
  164.             exit(-1);
  165.     }
  166.     
  167.     par = getenv(var_name(htons(osin.sin_port), sockid));
  168.     if (!par) { exit(-1); }
  169.  
  170.     sprintf(CONF_FILE, RCONF_FILE "%d", htons(osin.sin_port));
  171.  
  172.     ssize  = strlen(par) + 1;
  173.     mapname = malloc(ssize); if (mapname) memcpy(mapname, par, ssize);
  174.  
  175.     if((!mapname) || (!mapname[0]))
  176.         servererr("No map name given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>");
  177.  
  178.     par = strchr(mapname, '?');
  179.     if (!par) { servererr("Your client doesn't support image mapping properly."); }
  180.     
  181.     *par++ = '\0';
  182.  
  183.     if(!(t = strchr(par,',')))
  184.         servererr("Your client doesn't support image mapping properly.");
  185.     *t++ = '\0';
  186.     testpoint[X] = (double) atoi(par);
  187.     testpoint[Y] = (double) atoi(t);
  188.  
  189.     if ((fp = fopen(CONF_FILE, "r")) == NULL){
  190.         sprintf(errstr, "Couldn't open configuration file: %s", CONF_FILE);
  191.         servererr(errstr);
  192.     }
  193.  
  194.     while(!(getline(input,MAXLINE,fp))) {
  195.         char confname[MAXLINE];
  196.         if((input[0] == '#') || (!input[0]))
  197.             continue;
  198.         for(i=0;isname(input[i]) && (input[i] != ':');i++)
  199.             confname[i] = input[i];
  200.         confname[i] = '\0';
  201.         if(!strcmp(confname,mapname))
  202.             goto found;
  203.     }
  204.     /*
  205.      * if mapname was not found in the configuration file, it still
  206.      * might represent a file in the server root directory -
  207.      * we get the translated path, and check to see if a file of that
  208.      * name exists, jumping to the opening of the map file if it does.
  209.      */
  210.     if(feof(fp)) {
  211.     servererr("Map not found in configuration file.");
  212.     }
  213.     
  214.   found:
  215.     fclose(fp);
  216.     while(isspace(input[i]) || input[i] == ':') ++i;
  217.  
  218.     for(j=0;input[i] && isname(input[i]);++i,++j)
  219.         conf[j] = input[i];
  220.     conf[j] = '\0';
  221.  
  222.   openconf:
  223.     if(!(fp=fopen(conf,"r"))){
  224.     sprintf(errstr, "Couldn't open configuration file: %s", conf);
  225.         servererr(errstr);
  226.     }
  227.  
  228.     while(!(getline(input,MAXLINE,fp))) {
  229.         char type[MAXLINE];
  230.         char url[MAXLINE];
  231.         char num[10];
  232.  
  233.         if((input[0] == '#') || (!input[0]))
  234.             continue;
  235.  
  236.         type[0] = '\0';url[0] = '\0';
  237.  
  238.         for(i=0;isname(input[i]) && (input[i]);i++)
  239.             type[i] = input[i];
  240.         type[i] = '\0';
  241.  
  242.         while(isspace(input[i])) ++i;
  243.         for(j=0;input[i] && isname(input[i]);++i,++j)
  244.             url[j] = input[i];
  245.         url[j] = '\0';
  246.  
  247.         if(!strcmp(type,"default") && !sawpoint) {
  248.             strcpy(def,url);
  249.             continue;
  250.         }
  251.  
  252.         k=0;
  253.         while (input[i]) {
  254.             while (isspace(input[i]) || input[i] == ',')
  255.                 i++;
  256.             j = 0;
  257.             while (isdigit(input[i]))
  258.                 num[j++] = input[i++];
  259.             num[j] = '\0';
  260.             if (num[0] != '\0')
  261.                 pointarray[k][X] = (double) atoi(num);
  262.             else
  263.                 break;
  264.             while (isspace(input[i]) || input[i] == ',')
  265.                 i++;
  266.             j = 0;
  267.             while (isdigit(input[i]))
  268.                 num[j++] = input[i++];
  269.             num[j] = '\0';
  270.             if (num[0] != '\0')
  271.                 pointarray[k++][Y] = (double) atoi(num);
  272.             else {
  273.                 fclose(fp);
  274.                 servererr("Missing y value.");
  275.             }
  276.         }
  277.         pointarray[k][X] = -1;
  278.         if(!strcmp(type,"poly"))
  279.             if(pointinpoly(testpoint,pointarray))
  280.                 sendmesg(url);
  281.         if(!strcmp(type,"circle"))
  282.             if(pointincircle(testpoint,pointarray))
  283.                 sendmesg(url);
  284.         if(!strcmp(type,"rect"))
  285.             if(pointinrect(testpoint,pointarray))
  286.                 sendmesg(url);
  287.         if(!strcmp(type,"point")) {
  288.         /* Don't need to take square root. */
  289.         dist = ((testpoint[X] - pointarray[0][X])
  290.             * (testpoint[X] - pointarray[0][X]))
  291.            + ((testpoint[Y] - pointarray[0][Y])
  292.               * (testpoint[Y] - pointarray[0][Y]));
  293.         /* If this is the first point, or the nearest, set the default. */
  294.         if ((! sawpoint) || (dist < mindist)) {
  295.         mindist = dist;
  296.             strcpy(def,url);
  297.         }
  298.         sawpoint++;
  299.     }
  300.     }
  301.     if(def[0])
  302.         sendmesg(def);
  303.     servererr("No default specified.");
  304. }
  305.  
  306.  
  307. int pointinrect(double point[2], double coords[MAXVERTS][2])
  308. {
  309.         return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
  310.         (point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
  311. }
  312.  
  313. int pointincircle(double point[2], double coords[MAXVERTS][2])
  314. {
  315.         int radius1, radius2;
  316.  
  317.         radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] -
  318.         coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] -
  319.         coords[1][X]));
  320.         radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) +
  321.         ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  322.         return (radius2 <= radius1);
  323. }
  324.  
  325. int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  326. {
  327.         int i, numverts, inside_flag, xflag0;
  328.         int crossings;
  329.         double *p, *stop;
  330.         double tx, ty, y;
  331.  
  332.         for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
  333.                 ;
  334.         numverts = i;
  335.         crossings = 0;
  336.  
  337.         tx = point[X];
  338.         ty = point[Y];
  339.         y = pgon[numverts - 1][Y];
  340.  
  341.         p = (double *) pgon + 1;
  342.         if ((y >= ty) != (*p >= ty)) {
  343.                 if ((xflag0 = (pgon[numverts - 1][X] >= tx)) ==
  344.                 (*(double *) pgon >= tx)) {
  345.                         if (xflag0)
  346.                                 crossings++;
  347.                 }
  348.                 else {
  349.                         crossings += (pgon[numverts - 1][X] - (y - ty) *
  350.                         (*(double *) pgon - pgon[numverts - 1][X]) /
  351.                         (*p - y)) >= tx;
  352.                 }
  353.         }
  354.  
  355.         stop = pgon[numverts];
  356.  
  357.         for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  358.                 if (y >= ty) {
  359.                         while ((p < stop) && (*p >= ty))
  360.                                 p += 2;
  361.                         if (p >= stop)
  362.                                 break;
  363.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  364.                                 if (xflag0)
  365.                                         crossings++;
  366.                         }
  367.                         else {
  368.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  369.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  370.                         }
  371.                 }
  372.                 else {
  373.                         while ((p < stop) && (*p < ty))
  374.                                 p += 2;
  375.                         if (p >= stop)
  376.                                 break;
  377.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  378.                                 if (xflag0)
  379.                                         crossings++;
  380.                         }
  381.                         else {
  382.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  383.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  384.                         }
  385.                 }
  386.         }
  387.         inside_flag = crossings & 0x01;
  388.         return (inside_flag);
  389. }
  390.  
  391.  
  392. int isname(char c)
  393. {
  394.         return (!isspace(c));
  395. }
  396.  
  397. int getline(char *s, int n, FILE *f) {
  398.     register int i=0;
  399.  
  400.     while(1) {
  401.         s[i] = (char)fgetc(f);
  402.  
  403.         if(s[i] == CR)
  404.             s[i] = fgetc(f);
  405.  
  406.         if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
  407.             s[i] = '\0';
  408.             return (feof(f) ? 1 : 0);
  409.         }
  410.         ++i;
  411.     }
  412. }
  413.  
  414.