mod_imagemap.c revision fda1a61aacb6950953b7393b845b0639d8e87359
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd/* Licensed to the Apache Software Foundation (ASF) under one or more
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * contributor license agreements. See the NOTICE file distributed with
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * this work for additional information regarding copyright ownership.
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * The ASF licenses this file to You under the Apache License, Version 2.0
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * (the "License"); you may not use this file except in compliance with
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * the License. You may obtain a copy of the License at
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * Unless required by applicable law or agreed to in writing, software
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * distributed under the License is distributed on an "AS IS" BASIS,
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
2e545ce2450a9953665f701bb05350f0d3f26275nd * limitations under the License.
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * This imagemap module started as a port of the original imagemap.c
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu).
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * This version includes the mapping algorithms found in version 1.3
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Contributors to this code include:
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Eric Haines, erich@eye.com
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh * Randy Terbush, randy@zyzzyva.com
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * port to Apache module format, "base_uri" and support for relative URLs
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * James H. Cloos, Jr., cloos@jhcloos.com
e7135fcbd2e1439ae327ecb63365c143d93d4b98humbedooh * Added point datatype, using code in NCSA's version 1.8 imagemap.c
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * program, as distributed with version 1.4.1 of their server.
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Nathan Kurz, nate@tripod.com
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Rewrite/reorganization. New handling of default, base and relative URLs.
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * New Configuration directives:
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * ImapMenu {none, formatted, semiformatted, unformatted}
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * ImapDefault {error, nocontent, referer, menu, URL}
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * ImapBase {map, referer, URL}
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Support for creating non-graphical menu added. (backwards compatible):
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * Old: directive URL [x,y ...]
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar * New: directive URL "Menu text" [x,y ...]
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar * or: directive URL x,y ... "Menu text"
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar * Map format and menu concept courtesy Joshua Bell, jsbell@acs.ucalgary.ca.
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh * Mark Cox, mark@ukweb.com, Allow relative URLs even when no base specified
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar#define X 0
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar#define Y 1
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coartypedef struct {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9ndstatic void *create_imap_dir_config(apr_pool_t *p, char *dummy)
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen (imap_conf_rec *) apr_palloc(p, sizeof(imap_conf_rec));
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowenstatic void *merge_imap_dir_configs(apr_pool_t *p, void *basev, void *addv)
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen imap_conf_rec *new = (imap_conf_rec *) apr_pcalloc(p, sizeof(imap_conf_rec));
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
4aa603e6448b99f9371397d439795c91a93637eand new->imap_default = add->imap_default ? add->imap_default
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd (void *)APR_OFFSETOF(imap_conf_rec, imap_menu), OR_INDEXES,
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd "the type of menu generated: none, formatted, semiformatted, "
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen "unformatted"),
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen (void *)APR_OFFSETOF(imap_conf_rec, imap_default), OR_INDEXES,
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen "the action taken if no match: error, nocontent, referer, "
4a56677aad9b66a36f3dc9fddbca8dc1230ad471rbowen "menu, URL"),
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen (void *)APR_OFFSETOF(imap_conf_rec, imap_base), OR_INDEXES,
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar "the base for all URL's: map, referer, URL (or start of)"),
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coarstatic int pointinrect(const double point[2], double coords[MAXVERTS][2])
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedoohstatic int pointincircle(const double point[2], double coords[MAXVERTS][2])
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
dc1328abb455410dfc5e4828f5e0e60dd859db49humbedooh#define fmin(a,b) (((a)>(b))?(b):(a))
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen#define fmax(a,b) (((a)>(b))?(a):(b))
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coarstatic int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar for (numverts = 0; pgon[numverts][X] != -1 && numverts < MAXVERTS;
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd /* just counting the vertexes */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd for (i = 0; i < numverts; i++) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9ndstatic int is_closer(const double point[2], double coords[MAXVERTS][2],
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar return (0); /* don't mess around with negative coordinates */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd return (1); /* if this is the first point or is the closest yet
4aa603e6448b99f9371397d439795c91a93637eand set 'closest' equal to this distance^2 */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen return (0); /* if it's not the first or closest */
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh double x_coord = -1; /* -1 is returned if no coordinate is given */
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh while (*args && !apr_isdigit(*args) && *args != ',') {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd a comma or end */
b58e08539de1f9a9167ed379efe2d5fdaf70200fhumbedooh if (endptr > args) { /* if a conversion was made */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd or if no args was given */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd the comma */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen past the end */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar no comma was found in args */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen/* See if string has a "quoted part", and if so set *quoted_part to
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * the first character of the quoted part, then hammer a \0 onto the
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar * trailing quote, and set *string to point at the first character
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * past the second quote.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * Otherwise set *quoted_part to NULL, and leave *string alone.
4aa603e6448b99f9371397d439795c91a93637eandstatic void read_quoted(char **string, char **quoted_part)
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen /* assume there's no quoted part */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar if (*strp == '"') { /* if that character is a double quote */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen *quoted_part = strp; /* note where the quoted part begins */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * returns the mapped URL or NULL.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowenstatic char *imap_url(request_rec *r, const char *base, const char *value)
b58e08539de1f9a9167ed379efe2d5fdaf70200fhumbedooh/* translates a value into a URL. */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd return apr_pstrdup(r->pool, value); /* these are handled elsewhere,
4aa603e6448b99f9371397d439795c91a93637eand so just copy them */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* XXX: This used to do *value = '\0'; ... which is totally bogus
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * because it hammers the passed in value, which can be a string
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * constant, or part of a config, or whatever. Total garbage.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * This works around that without changing the rest of this
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * code much
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen null the value */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd until a non-letter */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd /* if letters and then a colon (like http:) */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd /* it's an absolute URL, so use it! */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar return apr_pstrdup(r->pool, value); /* no base: use what is given */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen /* no base, no value: pick a simple default */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* must be a relative URL to be combined with base */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen if (ap_strchr_c(base, '/') == NULL && (!strncmp(value, "../", 3)
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar string_pos += 2; /* if there are two slashes, jump over them */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd } /* if the URL from the map starts from root,
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen end the base URL string at the first single
e7135fcbd2e1439ae327ecb63365c143d93d4b98humbedooh the directory portion */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd string_pos */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd } /* but if the map url is relative, leave the
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd slash on the base (if there is one) */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd string_pos++; /* until we get to the end of my_base without
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd finding a slash by itself */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd /* for each '..', knock a directory off the end
fdfb488408aaf846476d8c42532952e088ea2258humbedooh by ending the string right at the last slash.
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd But only consider the directory portion: don't eat
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd into the server name. And only try if a directory
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar portion was found */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd if (clen == 0) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd else if (directory) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd to do. This way, we leave the starting
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd '/' on value after the last '..', but get
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen rid of it otherwise */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd } /* by this point, value does not start
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd with '..' */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar /* they actually requested an error! */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd /* tell the client to keep the page it has */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar /* must be a URL, so redirect to it */
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh apr_table_setn(r->headers_out, "Location", redirect);
e7135fcbd2e1439ae327ecb63365c143d93d4b98humbedooh ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ",
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coarstatic void menu_comment(request_rec *r, char *menu, char *comment)
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd ap_rputs("\n", r); /* print just a newline if 'formatted' */
4aa603e6448b99f9371397d439795c91a93637eand return; /* comments are ignored in the
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen 'formatted' form */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowenstatic void menu_default(request_rec *r, char *menu, char *href, char *text)
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar return; /* don't print such lines, these aren't
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh really href's */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9ndstatic void menu_directive(request_rec *r, char *menu, char *href, char *text)
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen return; /* don't print such lines, as this isn't
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar really an href */
156e9dfbbab272a462dadedda424385a706a8637humbedooh ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
156e9dfbbab272a462dadedda424385a706a8637humbedooh ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh ap_rputs("\n\n</body>\n</html>\n", r); /* finish the menu */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen icr = ap_get_module_config(r->per_dir_config, &imagemap_module);
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen status = ap_pcfg_openfile(&imap, r->pool, r->filename);
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen base = imap_url(r, NULL, imap_base); /* set base according
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen to default */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen mapdflt = imap_url(r, NULL, imap_default); /* and default to
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar global default */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* if either is -1 or if both are zero (new Lynx) */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* we don't have valid coordinates */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen 'none' or 'no' */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar we're going to */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen } /* blank lines and comments are ignored
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen if we aren't printing a menu */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* find the first two space delimited fields, recall that
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * ap_cfg_getline has removed leading/trailing whitespace.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * note that we're tokenizing as we go... if we were to use the
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * ap_getword() class of functions we would end up allocating extra
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * memory for every line of the map file
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen while (*string_pos && !apr_isspace(*string_pos)) { /* past directive */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen while(*string_pos && apr_isspace(*string_pos)) { /* past whitespace */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen while (*string_pos && !apr_isspace(*string_pos)) { /* past value */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* end of input, don't advance past it */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen continue; /* base is never printed to a menu */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen if (!strcasecmp(directive, "default")) { /* default */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd if (showmenu) { /* print the default if there's a menu */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen &pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar /* Now skip what we just read... we can't use ANSIism %n */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar while (apr_isspace(*string_pos)) { /* past whitespace */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen while (apr_isdigit(*string_pos)) { /* and the 1st number */
dc1328abb455410dfc5e4828f5e0e60dd859db49humbedooh while (apr_isspace(*string_pos)) { /* past any more whitespace */
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh while (apr_isdigit(*string_pos)) { /* 2nd number */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen } /* so long as there are more vertices to
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd read, and we have room, read them in.
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd We start where we left off of the last
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd sscanf, not at the beginning. */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen pointarray[vertex][X] = -1; /* signals the end of vertices */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen read_quoted(&string_pos, &href_text); /* href text could
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd be here instead */
4aa603e6448b99f9371397d439795c91a93637eand /* note that we don't make it past here if we are making a menu */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen continue; /* don't try the following tests if testpoints
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen are invalid, or if there are no
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen coordinates */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen if (is_closer(testpoint, pointarray, &closest_yet)) {
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd } /* move on to next line whether it's
e7135fcbd2e1439ae327ecb63365c143d93d4b98humbedooh closest or not */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar } /* nothing matched, so we get another line! */
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar ap_cfg_closefile(imap); /* we are done with the map file; close it */
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen menu_footer(r); /* finish the menu and we are done */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd if (closest) { /* if a 'point' directive has been seen */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen only 'nocontent' */
fed0ff87936117a4db604de57c6bdfe449a4b7behumbedooh return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far,
35ac4e1a6ec5aa3cfa1a34d8f20fe8a841cc46b7rbowen we failed. They lose! */
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd "map file %s, line %d syntax error: requires at "
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* fall through */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen /* There's not much else we can do ... we've already sent the headers
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * to the client.
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd /* Optimization: skip the allocation of large local variables on the
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar * stack (in imap_handler_internal()) on requests that aren't using
16055ce2030d5a9ab3b1797dfe4ba2c1177a6af9nd * imagemaps
e7135fcbd2e1439ae327ecb63365c143d93d4b98humbedooh if (r->method_number != M_GET || (strcmp(r->handler,IMAP_MAGIC_TYPE)
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar merge_imap_dir_configs, /* dir merger --- default is to override */