in modules/mappers/mod_imagemap.c [571:866]
static int imap_handler_internal(request_rec *r)
{
char input[MAX_STRING_LEN];
char *directive;
char *value;
char *href_text;
const char *base;
const char *redirect;
const char *mapdflt;
char *closest = NULL;
double closest_yet = -1;
apr_status_t status;
double testpoint[2];
double pointarray[MAXVERTS + 1][2];
int vertex;
char *string_pos;
int showmenu = 0;
imap_conf_rec *icr;
char *imap_menu;
char *imap_default;
char *imap_base;
ap_configfile_t *imap;
icr = ap_get_module_config(r->per_dir_config, &imagemap_module);
imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
imap_default = icr->imap_default
? icr->imap_default : IMAP_DEFAULT_DEFAULT;
imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
status = ap_pcfg_openfile(&imap, r->pool, r->filename);
if (status != APR_SUCCESS) {
return HTTP_NOT_FOUND;
}
base = imap_url(r, NULL, imap_base); /* set base according
to default */
if (!base) {
return HTTP_INTERNAL_SERVER_ERROR;
}
mapdflt = imap_url(r, NULL, imap_default); /* and default to
global default */
if (!mapdflt) {
return HTTP_INTERNAL_SERVER_ERROR;
}
testpoint[X] = get_x_coord(r->args);
testpoint[Y] = get_y_coord(r->args);
if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
(testpoint[X] == 0 && testpoint[Y] == 0)) {
/* if either is -1 or if both are zero (new Lynx) */
/* we don't have valid coordinates */
testpoint[X] = -1;
testpoint[Y] = -1;
if (strncasecmp(imap_menu, "none", 2)) {
showmenu = 1; /* show the menu _unless_ ImapMenu is
'none' or 'no' */
}
}
if (showmenu) { /* send start of imagemap menu if
we're going to */
menu_header(r, imap_menu);
}
while (!ap_cfg_getline(input, sizeof(input), imap)) {
if (!input[0]) {
if (showmenu) {
menu_blank(r, imap_menu);
}
continue;
}
if (input[0] == '#') {
if (showmenu) {
menu_comment(r, imap_menu, input + 1);
}
continue;
} /* blank lines and comments are ignored
if we aren't printing a menu */
/* find the first two space delimited fields, recall that
* ap_cfg_getline has removed leading/trailing whitespace.
*
* note that we're tokenizing as we go... if we were to use the
* ap_getword() class of functions we would end up allocating extra
* memory for every line of the map file
*/
string_pos = input;
if (!*string_pos) { /* need at least two fields */
goto need_2_fields;
}
directive = string_pos;
while (*string_pos && !apr_isspace(*string_pos)) { /* past directive */
++string_pos;
}
if (!*string_pos) { /* need at least two fields */
goto need_2_fields;
}
*string_pos++ = '\0';
if (!*string_pos) { /* need at least two fields */
goto need_2_fields;
}
while (apr_isspace(*string_pos)) { /* past whitespace */
++string_pos;
}
value = string_pos;
while (*string_pos && !apr_isspace(*string_pos)) { /* past value */
++string_pos;
}
if (apr_isspace(*string_pos)) {
*string_pos++ = '\0';
}
else {
/* end of input, don't advance past it */
*string_pos = '\0';
}
if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */
base = imap_url(r, NULL, value);
if (!base) {
goto menu_bail;
}
continue; /* base is never printed to a menu */
}
read_quoted(&string_pos, &href_text);
if (!strcasecmp(directive, "default")) { /* default */
mapdflt = imap_url(r, NULL, value);
if (!mapdflt) {
goto menu_bail;
}
if (showmenu) { /* print the default if there's a menu */
redirect = imap_url(r, base, mapdflt);
if (!redirect) {
goto menu_bail;
}
menu_default(r, imap_menu, redirect,
href_text ? href_text : mapdflt);
}
continue;
}
vertex = 0;
while (vertex < MAXVERTS &&
sscanf(string_pos, "%lf%*[, ]%lf",
&pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
/* Now skip what we just read... we can't use ANSIism %n */
while (apr_isspace(*string_pos)) { /* past whitespace */
string_pos++;
}
while (apr_isdigit(*string_pos)) { /* and the 1st number */
string_pos++;
}
string_pos++; /* skip the ',' */
while (apr_isspace(*string_pos)) { /* past any more whitespace */
string_pos++;
}
while (apr_isdigit(*string_pos)) { /* 2nd number */
string_pos++;
}
vertex++;
} /* so long as there are more vertices to
read, and we have room, read them in.
We start where we left off of the last
sscanf, not at the beginning. */
pointarray[vertex][X] = -1; /* signals the end of vertices */
if (showmenu) {
if (!href_text) {
read_quoted(&string_pos, &href_text); /* href text could
be here instead */
}
redirect = imap_url(r, base, value);
if (!redirect) {
goto menu_bail;
}
menu_directive(r, imap_menu, redirect,
href_text ? href_text : value);
continue;
}
/* note that we don't make it past here if we are making a menu */
if (testpoint[X] == -1 || pointarray[0][X] == -1) {
continue; /* don't try the following tests if testpoints
are invalid, or if there are no
coordinates */
}
if (!strcasecmp(directive, "poly")) { /* poly */
if (pointinpoly(testpoint, pointarray)) {
ap_cfg_closefile(imap);
redirect = imap_url(r, base, value);
if (!redirect) {
return HTTP_INTERNAL_SERVER_ERROR;
}
return (imap_reply(r, redirect));
}
continue;
}
if (!strcasecmp(directive, "circle")) { /* circle */
if (pointincircle(testpoint, pointarray)) {
ap_cfg_closefile(imap);
redirect = imap_url(r, base, value);
if (!redirect) {
return HTTP_INTERNAL_SERVER_ERROR;
}
return (imap_reply(r, redirect));
}
continue;
}
if (!strcasecmp(directive, "rect")) { /* rect */
if (pointinrect(testpoint, pointarray)) {
ap_cfg_closefile(imap);
redirect = imap_url(r, base, value);
if (!redirect) {
return HTTP_INTERNAL_SERVER_ERROR;
}
return (imap_reply(r, redirect));
}
continue;
}
if (!strcasecmp(directive, "point")) { /* point */
if (is_closer(testpoint, pointarray, &closest_yet)) {
closest = apr_pstrdup(r->pool, value);
}
continue;
} /* move on to next line whether it's
closest or not */
} /* nothing matched, so we get another line! */
ap_cfg_closefile(imap); /* we are done with the map file; close it */
if (showmenu) {
menu_footer(r); /* finish the menu and we are done */
return OK;
}
if (closest) { /* if a 'point' directive has been seen */
redirect = imap_url(r, base, closest);
if (!redirect) {
return HTTP_INTERNAL_SERVER_ERROR;
}
return (imap_reply(r, redirect));
}
if (mapdflt) { /* a default should be defined, even if
only 'nocontent' */
redirect = imap_url(r, base, mapdflt);
if (!redirect) {
return HTTP_INTERNAL_SERVER_ERROR;
}
return (imap_reply(r, redirect));
}
return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far,
we failed. They lose! */
need_2_fields:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00679)
"map file %s, line %d syntax error: requires at "
"least two fields", r->uri, imap->line_number);
/* fall through */
menu_bail:
ap_cfg_closefile(imap);
if (showmenu) {
/* There's not much else we can do ... we've already sent the headers
* to the client.
*/
ap_rputs("\n\n[an internal server error occurred]\n", r);
menu_footer(r);
return OK;
}
return HTTP_INTERNAL_SERVER_ERROR;
}