#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 portnum = 80;
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;
int showmenu = 0;
if (argc == 1)
showmenu = 1; /* Just the map was selected - return a menu */
else
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 instructions.");
if (!showmenu) {
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);
/*
* to handle newer Lynx releases which insist on sending arbitrary
* coordinates, 0,0 is treated as "no coordinates". Should almost
* never be clicked on by a user, we hope.
*/
showmenu = (!testpoint[X] && !testpoint[Y]);
}
/*
* 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;
}
portnum = atoi(getenv("SERVER_PORT"));
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);
}
if (showmenu) {
printf("Content-type: text/html%c%c", 10, 10);\
printf("
Imagemap menu: %s%c", getenv("PATH_TRANSLATED"), 10);
}
while(!(getline(input,MAXLINE,fp))) {
char type[MAXLINE];
char url[MAXLINE];
char text[MAXLINE];
char num[10];
if((input[0] == '#') || (!input[0]))
continue;
type[0] = '\0';url[0] = '\0';text[0] = '\0';
for(i=0;isname(input[i]) && (input[i]);i++)
type[i] = input[i];
type[i] = '\0';
while(isspace(input[i])) ++i;
if(!strcmp(type,"text") && showmenu) {
printf("%s%c", &(input[i]), 10);
continue;
}
for(j=0;input[i] && isname(input[i]);++i,++j)
url[j] = input[i];
url[j] = '\0';
if(!strcmp(type,"default") && !sawpoint && !showmenu) {
strcpy(def,url);
continue;
}
k=0;
while (input[i]) {
while (isspace(input[i]) || input[i] == ',')
i++;
if (input[i] == '"') {
i++;
j = 0;
while(input[i] != '"' && input[i]) {
text[j++] = input[i++];
}
text[j] = '\0';
if (input[i] == '\0')
break;
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.");
}
}
if(showmenu) {
showline(type, url, text);
continue;
}
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(showmenu) {
printf("");
exit(0);
}
if(def[0])
sendmesg(def);
printf("Status: 204 No content%c",10);
servererr("No default specified.");
}
sendmesg(char *url)
{
printf("Location: ");
if (!strchr(url, ':')) { /*** It is a virtual URL ***/
printf("http://%s", getenv("SERVER_NAME"));
if(portnum != 80)
printf("%d", portnum);
}
printf("%s%c%c",url,10,10);
printf("This document has moved here%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("Mapping Server Error");
printf("Mapping Server Error
");
printf("This server encountered an error:");
printf("%s", msg);
exit(-1);
}
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;
}
}
showline(char *type, char *url, char *text)
{
printf("
%s%c", url, text, 10);
else
printf("%s\">(%s) %s