home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ** mapper 1.2 ** 7/26/93 Kevin Hughes, kevinh@pulua.hcc.hawaii.edu ** "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com ** All suggestions, help, etc. gratefully accepted! ** ** 1.1 : Better formatting, added better polygon code. ** 1.2 : Changed isname(), added config file specification. ** ** 11/13/93: Rob McCool, robm@ncsa.uiuc.edu ** ** 1.3 : Rewrote configuration stuff for NCSA /htbin script ** ** 12/05/93: Rob McCool, robm@ncsa.uiuc.edu ** ** 1.4 : Made CGI/1.0 compliant. ** ** 06/27/94: Chris Hyams, cgh@rice.edu ** Based on an idea by Rick Troth (troth@rice.edu) ** ** 1.5 : Imagemap configuration file in PATH_INFO. Backwards compatible. ** ** Old-style lookup in imagemap table: ** <a href="http://foo.edu/cgi-bin/imagemap/oldmap"> ** ** New-style specification of mapfile relative to DocumentRoot: ** <a href="http://foo.edu/cgi-bin/imagemap/path/for/new.map"> ** ** New-style specification of mapfile in user's public HTML directory: ** <a href="http://foo.edu/cgi-bin/imagemap/~username/path/for/new.map"> ** ** 07/11/94: Craig Milo Rogers, Rogers@ISI.Edu ** ** 1.6 : Added "point" datatype: the nearest point wins. Overrides "default". ** ** 08/28/94: Carlos Varela, cvarela@ncsa.uiuc.edu ** ** 1.7 : Fixed bug: virtual URLs are now understood. ** Better error reporting when not able to open configuration file. ** ** 03/07/95: Carlos Varela, cvarela@ncsa.uiuc.edu ** ** 1.8 : Fixed bug (strcat->sprintf) when reporting error. ** Included getline() function from util.c in NCSA httpd distribution. ** ** 20/10/95: Stewart Brodie, s.n.brodie@ecs.soton.ac.uk ** ** 1.9 : Port to Acorn RISC OS and changes for my own HTTPServer ** It isn't pretty but that's not the point ** */ #include <stdio.h> #include <string.h> #if !defined(pyr) && !defined(NO_STDLIB_H) #include <stdlib.h> #else #include <sys/types.h> #include <ctype.h> char *getenv(); #endif #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #define RCONF_FILE "<HTTPServer$Dir>.imap_" #define MAXLINE 500 #define MAXVERTS 100 #define X 0 #define Y 1 #define LF 10 #define CR 13 static int sockid = -1; static char *myhost = NULL; struct sockaddr_in osin; int isname(char); int getline(char *s, int n, FILE *f); int pointinpoly(double point[2], double pgon[MAXVERTS][2]); int pointinrect(double point[2], double coords[MAXVERTS][2]); int pointincircle(double point[2], double coords[MAXVERTS][2]); void sendmesg(char *url); void servererr(char *msg) { #define CSTRANDLEN(obj) obj,sizeof(obj)-1 #define STRANDLEN(obj) obj, strlen(obj) 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); send(sockid, STRANDLEN(msg), 0); exit(-1); } void sendmesg(char *url) { struct hostent *h = gethostbyaddr((char *)&osin.sin_addr, 4, AF_INET); if (!h) { myhost = inet_ntoa(osin.sin_addr); } else { myhost = h->h_name; } send(sockid, CSTRANDLEN("HTTP/1.0 302 Imagemap redirection\n"), 0); if (strchr(url, ':')) /*** It is a full URL ***/ send(sockid, CSTRANDLEN("Location: "), 0); else /*** It is a virtual URL ***/ { char buffer[512]; sprintf(buffer, "Location: http://%s:%d", myhost, htons(osin.sin_port)); send(sockid, STRANDLEN(buffer), 0); } send(sockid, STRANDLEN(url), 0); send(sockid, CSTRANDLEN("\n\nThis document has moved <A HREF=\""), 0); send(sockid, STRANDLEN(url), 0); send(sockid, CSTRANDLEN("\">here</A>\n"), 0); exit(1); } static char *var_name(int port, int s) { static char buf[256]; sprintf(buf, "HTTPServer$%d$%d$Query", port, s); return buf; } static void atexit_func(void) { if (sockid > -1) close(sockid); } int main(int argc, char **argv) { char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE]; char CONF_FILE[256]; double testpoint[2], pointarray[MAXVERTS][2]; int i, j, k; FILE *fp; char *t; double dist, mindist; int sawpoint = 0; int ctr; int ssize = sizeof(osin); char *par; for (ctr=1; ctr<argc; ++ctr) { if (!strcmp(argv[ctr], "-socket")) { sockid = atoi(argv[ctr+1]); if (!isdigit(argv[ctr+1])) { exit(-1); } atexit(atexit_func); } } if (sockid == -1) { exit(-1); } if (getsockname(sockid, (struct sockaddr *)&osin, &ssize) < 0) { exit(-1); } par = getenv(var_name(htons(osin.sin_port), sockid)); if (!par) { exit(-1); } sprintf(CONF_FILE, RCONF_FILE "%d", htons(osin.sin_port)); ssize = strlen(par) + 1; mapname = malloc(ssize); if (mapname) memcpy(mapname, par, ssize); if((!mapname) || (!mapname[0])) servererr("No map name given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>"); par = strchr(mapname, '?'); if (!par) { servererr("Your client doesn't support image mapping properly."); } *par++ = '\0'; if(!(t = strchr(par,','))) servererr("Your client doesn't support image mapping properly."); *t++ = '\0'; testpoint[X] = (double) atoi(par); testpoint[Y] = (double) atoi(t); if ((fp = fopen(CONF_FILE, "r")) == NULL){ sprintf(errstr, "Couldn't open configuration file: %s", CONF_FILE); servererr(errstr); } while(!(getline(input,MAXLINE,fp))) { char confname[MAXLINE]; if((input[0] == '#') || (!input[0])) continue; for(i=0;isname(input[i]) && (input[i] != ':');i++) confname[i] = input[i]; confname[i] = '\0'; if(!strcmp(confname,mapname)) goto found; } /* * if mapname was not found in the configuration file, it still * might represent a file in the server root directory - * we get the translated path, and check to see if a file of that * name exists, jumping to the opening of the map file if it does. */ if(feof(fp)) { servererr("Map not found in configuration file."); } found: fclose(fp); while(isspace(input[i]) || input[i] == ':') ++i; for(j=0;input[i] && isname(input[i]);++i,++j) conf[j] = input[i]; conf[j] = '\0'; openconf: if(!(fp=fopen(conf,"r"))){ sprintf(errstr, "Couldn't open configuration file: %s", conf); servererr(errstr); } while(!(getline(input,MAXLINE,fp))) { char type[MAXLINE]; char url[MAXLINE]; char num[10]; if((input[0] == '#') || (!input[0])) continue; type[0] = '\0';url[0] = '\0'; for(i=0;isname(input[i]) && (input[i]);i++) type[i] = input[i]; type[i] = '\0'; while(isspace(input[i])) ++i; for(j=0;input[i] && isname(input[i]);++i,++j) url[j] = input[i]; url[j] = '\0'; if(!strcmp(type,"default") && !sawpoint) { strcpy(def,url); continue; } k=0; while (input[i]) { while (isspace(input[i]) || input[i] == ',') i++; j = 0; while (isdigit(input[i])) num[j++] = input[i++]; num[j] = '\0'; if (num[0] != '\0') pointarray[k][X] = (double) atoi(num); else break; while (isspace(input[i]) || input[i] == ',') i++; j = 0; while (isdigit(input[i])) num[j++] = input[i++]; num[j] = '\0'; if (num[0] != '\0') pointarray[k++][Y] = (double) atoi(num); else { fclose(fp); servererr("Missing y value."); } } pointarray[k][X] = -1; if(!strcmp(type,"poly")) if(pointinpoly(testpoint,pointarray)) sendmesg(url); if(!strcmp(type,"circle")) if(pointincircle(testpoint,pointarray)) sendmesg(url); if(!strcmp(type,"rect")) if(pointinrect(testpoint,pointarray)) sendmesg(url); if(!strcmp(type,"point")) { /* Don't need to take square root. */ dist = ((testpoint[X] - pointarray[0][X]) * (testpoint[X] - pointarray[0][X])) + ((testpoint[Y] - pointarray[0][Y]) * (testpoint[Y] - pointarray[0][Y])); /* If this is the first point, or the nearest, set the default. */ if ((! sawpoint) || (dist < mindist)) { mindist = dist; strcpy(def,url); } sawpoint++; } } if(def[0]) sendmesg(def); servererr("No default specified."); } int pointinrect(double point[2], double coords[MAXVERTS][2]) { return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) && (point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y])); } int pointincircle(double point[2], double coords[MAXVERTS][2]) { int radius1, radius2; radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X])); radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) + ((coords[0][X] - point[X]) * (coords[0][X] - point[X])); return (radius2 <= radius1); } int pointinpoly(double point[2], double pgon[MAXVERTS][2]) { int i, numverts, inside_flag, xflag0; int crossings; double *p, *stop; double tx, ty, y; for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++) ; numverts = i; crossings = 0; tx = point[X]; ty = point[Y]; y = pgon[numverts - 1][Y]; p = (double *) pgon + 1; if ((y >= ty) != (*p >= ty)) { if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx)) { if (xflag0) crossings++; } else { crossings += (pgon[numverts - 1][X] - (y - ty) * (*(double *) pgon - pgon[numverts - 1][X]) / (*p - y)) >= tx; } } stop = pgon[numverts]; for (y = *p, p += 2; p < stop; y = *p, p += 2) { if (y >= ty) { while ((p < stop) && (*p >= ty)) p += 2; if (p >= stop) break; if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) { if (xflag0) crossings++; } else { crossings += (*(p - 3) - (*(p - 2) - ty) * (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx; } } else { while ((p < stop) && (*p < ty)) p += 2; if (p >= stop) break; if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) { if (xflag0) crossings++; } else { crossings += (*(p - 3) - (*(p - 2) - ty) * (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx; } } } inside_flag = crossings & 0x01; return (inside_flag); } int isname(char c) { return (!isspace(c)); } int getline(char *s, int n, FILE *f) { register int i=0; while(1) { s[i] = (char)fgetc(f); if(s[i] == CR) s[i] = fgetc(f); if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) { s[i] = '\0'; return (feof(f) ? 1 : 0); } ++i; } }