An imagemap is usually made up of regions, or hotspots, defined by polygons, circles, rectangles, and points. The imagemap program is responsible for matching the x,y coordinates of the mouse-click sent to it by the client, with the URI intended for those x,y coordinates.
Listing D.1. The imagemap.c program.
/* ** mapper 1.2 */ #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/stat.h> #define CONF_FILE "/usr/local/etc/httpd/conf/imagemap.conf" #define MAXLINE 500 #define MAXVERTS 100 #define X 0 #define Y 1 #define LF 10 #define CR 13 int isname(char); int main(int argc, char **argv) { char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE]; double testpoint[2], pointarray[MAXVERTS][2]; int i, j, k; FILE *fp; char *t; double dist, mindist; int sawpoint = 0; if (argc != 2) servererr("Wrong number of arguments, client may not support ISMAP."); mapname=getenv("PATH_INFO"); if((!mapname) || (!mapname[0])) servererr("No map name given. Please read the <A HREF=\"http://
hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.asp\">instructions</ A>.<P>"); mapname++; if(!(t = strchr(argv[1],','))) servererr("Your client doesn't support image mapping properly."); *t++ = '\0'; testpoint[X] = (double) atoi(argv[1]); testpoint[Y] = (double) atoi(t); /* * if the mapname contains a '/', it represents a unix path - * we get the translated path, and skip reading the configuration file. */ if (strchr(mapname,'/')) { strcpy(conf,getenv("PATH_TRANSLATED")); goto openconf; } 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)) { struct stat sbuf; strcpy(conf,getenv("PATH_TRANSLATED")); if (!stat(conf,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG)) goto openconf; else 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."); } sendmesg(char *url) { if (strchr(url, ':')) /*** It is a full URL ***/ printf("Location: "); else /*** It is a virtual URL ***/ printf("Location: http://%s:%s", getenv("SERVER_NAME"), getenv("SERVER_PORT")); printf("%s%c%c",url,10,10); printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10); exit(1); } 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); } servererr(char *msg) { printf("Content-type: text/html%c%c",10,10); printf("<title>Mapping Server Error</title>"); printf("<h1>Mapping Server Error</h1>"); printf("This server encountered an error:<p>"); printf("%s", msg); exit(-1); } int isname(char c) { return (!isspace); } 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; } }