|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* This imagemap module started as a port of the original imagemap.c
|
|
Packit |
90a5c9 |
* written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu).
|
|
Packit |
90a5c9 |
* This version includes the mapping algorithms found in version 1.3
|
|
Packit |
90a5c9 |
* of imagemap.c.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Contributors to this code include:
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Eric Haines, erich@eye.com
|
|
Packit |
90a5c9 |
* "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Randy Terbush, randy@zyzzyva.com
|
|
Packit |
90a5c9 |
* port to Apache module format, "base_uri" and support for relative URLs
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* James H. Cloos, Jr., cloos@jhcloos.com
|
|
Packit |
90a5c9 |
* Added point datatype, using code in NCSA's version 1.8 imagemap.c
|
|
Packit |
90a5c9 |
* program, as distributed with version 1.4.1 of their server.
|
|
Packit |
90a5c9 |
* The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Nathan Kurz, nate@tripod.com
|
|
Packit |
90a5c9 |
* Rewrite/reorganization. New handling of default, base and relative URLs.
|
|
Packit |
90a5c9 |
* New Configuration directives:
|
|
Packit |
90a5c9 |
* ImapMenu {none, formatted, semiformatted, unformatted}
|
|
Packit |
90a5c9 |
* ImapDefault {error, nocontent, referer, menu, URL}
|
|
Packit |
90a5c9 |
* ImapBase {map, referer, URL}
|
|
Packit |
90a5c9 |
* Support for creating non-graphical menu added. (backwards compatible):
|
|
Packit |
90a5c9 |
* Old: directive URL [x,y ...]
|
|
Packit |
90a5c9 |
* New: directive URL "Menu text" [x,y ...]
|
|
Packit |
90a5c9 |
* or: directive URL x,y ... "Menu text"
|
|
Packit |
90a5c9 |
* Map format and menu concept courtesy Joshua Bell, jsbell@acs.ucalgary.ca.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Mark Cox, mark@ukweb.com, Allow relative URLs even when no base specified
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "apr.h"
|
|
Packit |
90a5c9 |
#include "apr_strings.h"
|
|
Packit |
90a5c9 |
#include "apr_lib.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define APR_WANT_STDIO /* for sscanf() */
|
|
Packit |
90a5c9 |
#define APR_WANT_STRFUNC
|
|
Packit |
90a5c9 |
#include "apr_want.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "ap_config.h"
|
|
Packit |
90a5c9 |
#include "httpd.h"
|
|
Packit |
90a5c9 |
#include "http_config.h"
|
|
Packit |
90a5c9 |
#include "http_request.h"
|
|
Packit |
90a5c9 |
#include "http_core.h"
|
|
Packit |
90a5c9 |
#include "http_protocol.h"
|
|
Packit |
90a5c9 |
#include "http_main.h"
|
|
Packit |
90a5c9 |
#include "http_log.h"
|
|
Packit |
90a5c9 |
#include "util_script.h"
|
|
Packit |
90a5c9 |
#include "mod_core.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define IMAP_MAGIC_TYPE "application/x-httpd-imap"
|
|
Packit |
90a5c9 |
#define MAXVERTS 100
|
|
Packit |
90a5c9 |
#define X 0
|
|
Packit |
90a5c9 |
#define Y 1
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define IMAP_MENU_DEFAULT "formatted"
|
|
Packit |
90a5c9 |
#define IMAP_DEFAULT_DEFAULT "nocontent"
|
|
Packit |
90a5c9 |
#define IMAP_BASE_DEFAULT "map"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
module AP_MODULE_DECLARE_DATA imagemap_module;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct {
|
|
Packit |
90a5c9 |
char *imap_menu;
|
|
Packit |
90a5c9 |
char *imap_default;
|
|
Packit |
90a5c9 |
char *imap_base;
|
|
Packit |
90a5c9 |
} imap_conf_rec;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void *create_imap_dir_config(apr_pool_t *p, char *dummy)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
imap_conf_rec *icr =
|
|
Packit |
90a5c9 |
(imap_conf_rec *) apr_palloc(p, sizeof(imap_conf_rec));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
icr->imap_menu = NULL;
|
|
Packit |
90a5c9 |
icr->imap_default = NULL;
|
|
Packit |
90a5c9 |
icr->imap_base = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return icr;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void *merge_imap_dir_configs(apr_pool_t *p, void *basev, void *addv)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
imap_conf_rec *new = (imap_conf_rec *) apr_palloc(p, sizeof(imap_conf_rec));
|
|
Packit |
90a5c9 |
imap_conf_rec *base = (imap_conf_rec *) basev;
|
|
Packit |
90a5c9 |
imap_conf_rec *add = (imap_conf_rec *) addv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
|
|
Packit |
90a5c9 |
new->imap_default = add->imap_default ? add->imap_default
|
|
Packit |
90a5c9 |
: base->imap_default;
|
|
Packit |
90a5c9 |
new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return new;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static const command_rec imap_cmds[] =
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1("ImapMenu", ap_set_string_slot,
|
|
Packit |
90a5c9 |
(void *)APR_OFFSETOF(imap_conf_rec, imap_menu), OR_INDEXES,
|
|
Packit |
90a5c9 |
"the type of menu generated: none, formatted, semiformatted, "
|
|
Packit |
90a5c9 |
"unformatted"),
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1("ImapDefault", ap_set_string_slot,
|
|
Packit |
90a5c9 |
(void *)APR_OFFSETOF(imap_conf_rec, imap_default), OR_INDEXES,
|
|
Packit |
90a5c9 |
"the action taken if no match: error, nocontent, referer, "
|
|
Packit |
90a5c9 |
"menu, URL"),
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1("ImapBase", ap_set_string_slot,
|
|
Packit |
90a5c9 |
(void *)APR_OFFSETOF(imap_conf_rec, imap_base), OR_INDEXES,
|
|
Packit |
90a5c9 |
"the base for all URL's: map, referer, URL (or start of)"),
|
|
Packit |
90a5c9 |
{NULL}
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int pointinrect(const double point[2], double coords[MAXVERTS][2])
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
double max[2], min[2];
|
|
Packit |
90a5c9 |
if (coords[0][X] > coords[1][X]) {
|
|
Packit |
90a5c9 |
max[0] = coords[0][X];
|
|
Packit |
90a5c9 |
min[0] = coords[1][X];
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
max[0] = coords[1][X];
|
|
Packit |
90a5c9 |
min[0] = coords[0][X];
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (coords[0][Y] > coords[1][Y]) {
|
|
Packit |
90a5c9 |
max[1] = coords[0][Y];
|
|
Packit |
90a5c9 |
min[1] = coords[1][Y];
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
max[1] = coords[1][Y];
|
|
Packit |
90a5c9 |
min[1] = coords[0][Y];
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return ((point[X] >= min[0] && point[X] <= max[0]) &&
|
|
Packit |
90a5c9 |
(point[Y] >= min[1] && point[Y] <= max[1]));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int pointincircle(const double point[2], double coords[MAXVERTS][2])
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
double radius1, radius2;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
|
|
Packit |
90a5c9 |
+ ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
|
|
Packit |
90a5c9 |
+ ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return (radius2 <= radius1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define fmin(a,b) (((a)>(b))?(b):(a))
|
|
Packit |
90a5c9 |
#define fmax(a,b) (((a)>(b))?(a):(b))
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i, numverts, crossings = 0;
|
|
Packit |
90a5c9 |
double x = point[X], y = point[Y];
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (numverts = 0; numverts < MAXVERTS && pgon[numverts][X] != -1;
|
|
Packit |
90a5c9 |
numverts++) {
|
|
Packit |
90a5c9 |
/* just counting the vertexes */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = 0; i < numverts; i++) {
|
|
Packit |
90a5c9 |
double x1=pgon[i][X];
|
|
Packit |
90a5c9 |
double y1=pgon[i][Y];
|
|
Packit |
90a5c9 |
double x2=pgon[(i + 1) % numverts][X];
|
|
Packit |
90a5c9 |
double y2=pgon[(i + 1) % numverts][Y];
|
|
Packit |
90a5c9 |
double d=(y - y1) * (x2 - x1) - (x - x1) * (y2 - y1);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((y1 >= y) != (y2 >= y)) {
|
|
Packit |
90a5c9 |
crossings +=y2 - y1 >= 0 ? d >= 0 : d <= 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!d && fmin(x1,x2) <= x && x <= fmax(x1,x2)
|
|
Packit |
90a5c9 |
&& fmin(y1,y2) <= y && y <= fmax(y1,y2)) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return crossings & 0x01;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int is_closer(const double point[2], double coords[MAXVERTS][2],
|
|
Packit |
90a5c9 |
double *closest)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
double dist_squared = ((point[X] - coords[0][X])
|
|
Packit |
90a5c9 |
* (point[X] - coords[0][X]))
|
|
Packit |
90a5c9 |
+ ((point[Y] - coords[0][Y])
|
|
Packit |
90a5c9 |
* (point[Y] - coords[0][Y]));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (point[X] < 0 || point[Y] < 0) {
|
|
Packit |
90a5c9 |
return (0); /* don't mess around with negative coordinates */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (*closest < 0 || dist_squared < *closest) {
|
|
Packit |
90a5c9 |
*closest = dist_squared;
|
|
Packit |
90a5c9 |
return (1); /* if this is the first point or is the closest yet
|
|
Packit |
90a5c9 |
set 'closest' equal to this distance^2 */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return (0); /* if it's not the first or closest */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static double get_x_coord(const char *args)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *endptr; /* we want it non-null */
|
|
Packit |
90a5c9 |
double x_coord = -1; /* -1 is returned if no coordinate is given */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (args == NULL) {
|
|
Packit |
90a5c9 |
return (-1); /* in case we aren't passed anything */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (*args && !apr_isdigit(*args) && *args != ',') {
|
|
Packit |
90a5c9 |
args++; /* jump to the first digit, but not past
|
|
Packit |
90a5c9 |
a comma or end */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
x_coord = strtod(args, &endptr);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (endptr > args) { /* if a conversion was made */
|
|
Packit |
90a5c9 |
return (x_coord);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return (-1); /* else if no conversion was made,
|
|
Packit |
90a5c9 |
or if no args was given */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static double get_y_coord(const char *args)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *endptr; /* we want it non-null */
|
|
Packit |
90a5c9 |
const char *start_of_y = NULL;
|
|
Packit |
90a5c9 |
double y_coord = -1; /* -1 is returned on error */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (args == NULL) {
|
|
Packit |
90a5c9 |
return (-1); /* in case we aren't passed anything */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
start_of_y = ap_strchr_c(args, ','); /* the comma */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (start_of_y) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
start_of_y++; /* start looking at the character after
|
|
Packit |
90a5c9 |
the comma */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (*start_of_y && !apr_isdigit(*start_of_y)) {
|
|
Packit |
90a5c9 |
start_of_y++; /* jump to the first digit, but not
|
|
Packit |
90a5c9 |
past the end */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
y_coord = strtod(start_of_y, &endptr);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (endptr > start_of_y) {
|
|
Packit |
90a5c9 |
return (y_coord);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return (-1); /* if no conversion was made, or
|
|
Packit |
90a5c9 |
no comma was found in args */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* See if string has a "quoted part", and if so set *quoted_part to
|
|
Packit |
90a5c9 |
* the first character of the quoted part, then hammer a \0 onto the
|
|
Packit |
90a5c9 |
* trailing quote, and set *string to point at the first character
|
|
Packit |
90a5c9 |
* past the second quote.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Otherwise set *quoted_part to NULL, and leave *string alone.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void read_quoted(char **string, char **quoted_part)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *strp = *string;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* assume there's no quoted part */
|
|
Packit |
90a5c9 |
*quoted_part = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (apr_isspace(*strp)) {
|
|
Packit |
90a5c9 |
strp++; /* go along string until non-whitespace */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (*strp == '"') { /* if that character is a double quote */
|
|
Packit |
90a5c9 |
strp++; /* step over it */
|
|
Packit |
90a5c9 |
*quoted_part = strp; /* note where the quoted part begins */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (*strp && *strp != '"') {
|
|
Packit |
90a5c9 |
++strp; /* skip the quoted portion */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
*strp = '\0'; /* end the string with a NUL */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
strp++; /* step over the last double quote */
|
|
Packit |
90a5c9 |
*string = strp;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* returns the mapped URL or NULL.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static const char *imap_url(request_rec *r, const char *base, const char *value)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
/* translates a value into a URL. */
|
|
Packit |
90a5c9 |
int slen, clen;
|
|
Packit |
90a5c9 |
char *string_pos = NULL;
|
|
Packit |
90a5c9 |
const char *string_pos_const = NULL;
|
|
Packit |
90a5c9 |
char *directory = NULL;
|
|
Packit |
90a5c9 |
const char *referer = NULL;
|
|
Packit |
90a5c9 |
char *my_base;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
|
|
Packit |
90a5c9 |
return ap_construct_url(r->pool, r->uri, r);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
|
|
Packit |
90a5c9 |
return apr_pstrdup(r->pool, value); /* these are handled elsewhere,
|
|
Packit |
90a5c9 |
so just copy them */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(value, "referer")) {
|
|
Packit |
90a5c9 |
referer = apr_table_get(r->headers_in, "Referer");
|
|
Packit |
90a5c9 |
if (referer && *referer) {
|
|
Packit |
90a5c9 |
return referer;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
/* XXX: This used to do *value = '\0'; ... which is totally bogus
|
|
Packit |
90a5c9 |
* because it hammers the passed in value, which can be a string
|
|
Packit |
90a5c9 |
* constant, or part of a config, or whatever. Total garbage.
|
|
Packit |
90a5c9 |
* This works around that without changing the rest of this
|
|
Packit |
90a5c9 |
* code much
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
value = ""; /* if 'referer' but no referring page,
|
|
Packit |
90a5c9 |
null the value */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
string_pos_const = value;
|
|
Packit |
90a5c9 |
while (apr_isalpha(*string_pos_const)) {
|
|
Packit |
90a5c9 |
string_pos_const++; /* go along the URL from the map
|
|
Packit |
90a5c9 |
until a non-letter */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (*string_pos_const == ':') {
|
|
Packit |
90a5c9 |
/* if letters and then a colon (like http:) */
|
|
Packit |
90a5c9 |
/* it's an absolute URL, so use it! */
|
|
Packit |
90a5c9 |
return apr_pstrdup(r->pool, value);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!base || !*base) {
|
|
Packit |
90a5c9 |
if (value && *value) {
|
|
Packit |
90a5c9 |
return apr_pstrdup(r->pool, value); /* no base: use what is given */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
/* no base, no value: pick a simple default */
|
|
Packit |
90a5c9 |
return ap_construct_url(r->pool, "/", r);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* must be a relative URL to be combined with base */
|
|
Packit |
90a5c9 |
if (ap_strchr_c(base, '/') == NULL && (!strncmp(value, "../", 3)
|
|
Packit |
90a5c9 |
|| !strcmp(value, ".."))) {
|
|
Packit |
90a5c9 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00677)
|
|
Packit |
90a5c9 |
"invalid base directive in map file: %s", r->uri);
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
my_base = apr_pstrdup(r->pool, base);
|
|
Packit |
90a5c9 |
string_pos = my_base;
|
|
Packit |
90a5c9 |
while (*string_pos) {
|
|
Packit |
90a5c9 |
if (*string_pos == '/' && *(string_pos + 1) == '/') {
|
|
Packit |
90a5c9 |
string_pos += 2; /* if there are two slashes, jump over them */
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (*string_pos == '/') { /* the first single slash */
|
|
Packit |
90a5c9 |
if (value[0] == '/') {
|
|
Packit |
90a5c9 |
*string_pos = '\0';
|
|
Packit |
90a5c9 |
} /* if the URL from the map starts from root,
|
|
Packit |
90a5c9 |
end the base URL string at the first single
|
|
Packit |
90a5c9 |
slash */
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
directory = string_pos; /* save the start of
|
|
Packit |
90a5c9 |
the directory portion */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
string_pos = strrchr(string_pos, '/'); /* now reuse
|
|
Packit |
90a5c9 |
string_pos */
|
|
Packit |
90a5c9 |
string_pos++; /* step over that last slash */
|
|
Packit |
90a5c9 |
*string_pos = '\0';
|
|
Packit |
90a5c9 |
} /* but if the map url is relative, leave the
|
|
Packit |
90a5c9 |
slash on the base (if there is one) */
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
string_pos++; /* until we get to the end of my_base without
|
|
Packit |
90a5c9 |
finding a slash by itself */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (directory && (slen = strlen(directory))) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* for each '..', knock a directory off the end
|
|
Packit |
90a5c9 |
by ending the string right at the last slash.
|
|
Packit |
90a5c9 |
But only consider the directory portion: don't eat
|
|
Packit |
90a5c9 |
into the server name. And only try if a directory
|
|
Packit |
90a5c9 |
portion was found */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
clen = slen - 1;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while ((slen - clen) == 1) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((string_pos = strrchr(directory, '/'))) {
|
|
Packit |
90a5c9 |
*string_pos = '\0';
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
clen = strlen(directory);
|
|
Packit |
90a5c9 |
if (clen == 0) {
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
value += 2; /* jump over the '..' that we found in the
|
|
Packit |
90a5c9 |
value */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (directory) {
|
|
Packit |
90a5c9 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00678)
|
|
Packit |
90a5c9 |
"invalid directory name in map file: %s", r->uri);
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) {
|
|
Packit |
90a5c9 |
value++; /* step over the '/' if there are more '..'
|
|
Packit |
90a5c9 |
to do. This way, we leave the starting
|
|
Packit |
90a5c9 |
'/' on value after the last '..', but get
|
|
Packit |
90a5c9 |
rid of it otherwise */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
} /* by this point, value does not start
|
|
Packit |
90a5c9 |
with '..' */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (value && *value) {
|
|
Packit |
90a5c9 |
return apr_pstrcat(r->pool, my_base, value, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return my_base;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int imap_reply(request_rec *r, const char *redirect)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
if (!strcasecmp(redirect, "error")) {
|
|
Packit |
90a5c9 |
/* they actually requested an error! */
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!strcasecmp(redirect, "nocontent")) {
|
|
Packit |
90a5c9 |
/* tell the client to keep the page it has */
|
|
Packit |
90a5c9 |
return HTTP_NO_CONTENT;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (redirect && *redirect) {
|
|
Packit |
90a5c9 |
/* must be a URL, so redirect to it */
|
|
Packit |
90a5c9 |
apr_table_setn(r->headers_out, "Location", redirect);
|
|
Packit |
90a5c9 |
return HTTP_MOVED_TEMPORARILY;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void menu_header(request_rec *r, char *menu)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ap_set_content_type(r, "text/html; charset=ISO-8859-1");
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ",
|
|
Packit |
90a5c9 |
ap_escape_html(r->pool, r->uri),
|
|
Packit |
90a5c9 |
"</title>\n</head><body>\n", NULL);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(menu, "formatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, "Menu for ",
|
|
Packit |
90a5c9 |
ap_escape_html(r->pool, r->uri),
|
|
Packit |
90a5c9 |
"\n \n\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void menu_blank(request_rec *r, char *menu)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
if (!strcasecmp(menu, "formatted")) {
|
|
Packit |
90a5c9 |
ap_rputs("\n", r);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "semiformatted")) {
|
|
Packit |
90a5c9 |
ap_rputs(" \n", r);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "unformatted")) {
|
|
Packit |
90a5c9 |
ap_rputs("\n", r);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void menu_comment(request_rec *r, char *menu, char *comment)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
/* comments are ignored in the 'formatted' form */
|
|
Packit |
90a5c9 |
if (!strcasecmp(menu, "formatted")) {
|
|
Packit |
90a5c9 |
ap_rputs("\n", r); /* print just a newline if 'formatted' */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "semiformatted") && *comment) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, comment, "\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "unformatted") && *comment) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, comment, "\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void menu_default(request_rec *r, const char *menu, const char *href, const char *text)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *ehref, *etext;
|
|
Packit |
90a5c9 |
if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
|
|
Packit |
90a5c9 |
return; /* don't print such lines, these aren't
|
|
Packit |
90a5c9 |
really href's */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ehref = ap_escape_uri(r->pool, href);
|
|
Packit |
90a5c9 |
etext = ap_escape_html(r->pool, text);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(menu, "formatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, "(Default) ", etext,
|
|
Packit |
90a5c9 |
"\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "semiformatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, "(Default) ", etext,
|
|
Packit |
90a5c9 |
"\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "unformatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, "", etext, "", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void menu_directive(request_rec *r, const char *menu, const char *href, const char *text)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *ehref, *etext;
|
|
Packit |
90a5c9 |
if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
|
|
Packit |
90a5c9 |
return; /* don't print such lines, as this isn't
|
|
Packit |
90a5c9 |
really an href */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ehref = ap_escape_uri(r->pool, href);
|
|
Packit |
90a5c9 |
etext = ap_escape_html(r->pool, text);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(menu, "formatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, " ", etext,
|
|
Packit |
90a5c9 |
"\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "semiformatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, " ", etext,
|
|
Packit |
90a5c9 |
"\n", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!strcasecmp(menu, "unformatted")) {
|
|
Packit |
90a5c9 |
ap_rvputs(r, "", etext, "", NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void menu_footer(request_rec *r)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ap_rputs("\n\n</body>\n</html>\n", r); /* finish the menu */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int imap_handler_internal(request_rec *r)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char input[MAX_STRING_LEN];
|
|
Packit |
90a5c9 |
char *directive;
|
|
Packit |
90a5c9 |
char *value;
|
|
Packit |
90a5c9 |
char *href_text;
|
|
Packit |
90a5c9 |
const char *base;
|
|
Packit |
90a5c9 |
const char *redirect;
|
|
Packit |
90a5c9 |
const char *mapdflt;
|
|
Packit |
90a5c9 |
char *closest = NULL;
|
|
Packit |
90a5c9 |
double closest_yet = -1;
|
|
Packit |
90a5c9 |
apr_status_t status;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
double testpoint[2];
|
|
Packit |
90a5c9 |
double pointarray[MAXVERTS + 1][2];
|
|
Packit |
90a5c9 |
int vertex;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *string_pos;
|
|
Packit |
90a5c9 |
int showmenu = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
imap_conf_rec *icr;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *imap_menu;
|
|
Packit |
90a5c9 |
char *imap_default;
|
|
Packit |
90a5c9 |
char *imap_base;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_configfile_t *imap;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
icr = ap_get_module_config(r->per_dir_config, &imagemap_module);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
|
|
Packit |
90a5c9 |
imap_default = icr->imap_default
|
|
Packit |
90a5c9 |
? icr->imap_default : IMAP_DEFAULT_DEFAULT;
|
|
Packit |
90a5c9 |
imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
status = ap_pcfg_openfile(&imap, r->pool, r->filename);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return HTTP_NOT_FOUND;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
base = imap_url(r, NULL, imap_base); /* set base according
|
|
Packit |
90a5c9 |
to default */
|
|
Packit |
90a5c9 |
if (!base) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
mapdflt = imap_url(r, NULL, imap_default); /* and default to
|
|
Packit |
90a5c9 |
global default */
|
|
Packit |
90a5c9 |
if (!mapdflt) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
testpoint[X] = get_x_coord(r->args);
|
|
Packit |
90a5c9 |
testpoint[Y] = get_y_coord(r->args);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
|
|
Packit |
90a5c9 |
(testpoint[X] == 0 && testpoint[Y] == 0)) {
|
|
Packit |
90a5c9 |
/* if either is -1 or if both are zero (new Lynx) */
|
|
Packit |
90a5c9 |
/* we don't have valid coordinates */
|
|
Packit |
90a5c9 |
testpoint[X] = -1;
|
|
Packit |
90a5c9 |
testpoint[Y] = -1;
|
|
Packit |
90a5c9 |
if (strncasecmp(imap_menu, "none", 2)) {
|
|
Packit |
90a5c9 |
showmenu = 1; /* show the menu _unless_ ImapMenu is
|
|
Packit |
90a5c9 |
'none' or 'no' */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (showmenu) { /* send start of imagemap menu if
|
|
Packit |
90a5c9 |
we're going to */
|
|
Packit |
90a5c9 |
menu_header(r, imap_menu);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (!ap_cfg_getline(input, sizeof(input), imap)) {
|
|
Packit |
90a5c9 |
if (!input[0]) {
|
|
Packit |
90a5c9 |
if (showmenu) {
|
|
Packit |
90a5c9 |
menu_blank(r, imap_menu);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (input[0] == '#') {
|
|
Packit |
90a5c9 |
if (showmenu) {
|
|
Packit |
90a5c9 |
menu_comment(r, imap_menu, input + 1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
} /* blank lines and comments are ignored
|
|
Packit |
90a5c9 |
if we aren't printing a menu */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* find the first two space delimited fields, recall that
|
|
Packit |
90a5c9 |
* ap_cfg_getline has removed leading/trailing whitespace.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* note that we're tokenizing as we go... if we were to use the
|
|
Packit |
90a5c9 |
* ap_getword() class of functions we would end up allocating extra
|
|
Packit |
90a5c9 |
* memory for every line of the map file
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
string_pos = input;
|
|
Packit |
90a5c9 |
if (!*string_pos) { /* need at least two fields */
|
|
Packit |
90a5c9 |
goto need_2_fields;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
directive = string_pos;
|
|
Packit |
90a5c9 |
while (*string_pos && !apr_isspace(*string_pos)) { /* past directive */
|
|
Packit |
90a5c9 |
++string_pos;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!*string_pos) { /* need at least two fields */
|
|
Packit |
90a5c9 |
goto need_2_fields;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
*string_pos++ = '\0';
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!*string_pos) { /* need at least two fields */
|
|
Packit |
90a5c9 |
goto need_2_fields;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
while (apr_isspace(*string_pos)) { /* past whitespace */
|
|
Packit |
90a5c9 |
++string_pos;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
value = string_pos;
|
|
Packit |
90a5c9 |
while (*string_pos && !apr_isspace(*string_pos)) { /* past value */
|
|
Packit |
90a5c9 |
++string_pos;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (apr_isspace(*string_pos)) {
|
|
Packit |
90a5c9 |
*string_pos++ = '\0';
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
/* end of input, don't advance past it */
|
|
Packit |
90a5c9 |
*string_pos = '\0';
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */
|
|
Packit |
90a5c9 |
base = imap_url(r, NULL, value);
|
|
Packit |
90a5c9 |
if (!base) {
|
|
Packit |
90a5c9 |
goto menu_bail;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue; /* base is never printed to a menu */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
read_quoted(&string_pos, &href_text);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(directive, "default")) { /* default */
|
|
Packit |
90a5c9 |
mapdflt = imap_url(r, NULL, value);
|
|
Packit |
90a5c9 |
if (!mapdflt) {
|
|
Packit |
90a5c9 |
goto menu_bail;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (showmenu) { /* print the default if there's a menu */
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, mapdflt);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
goto menu_bail;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
menu_default(r, imap_menu, redirect,
|
|
Packit |
90a5c9 |
href_text ? href_text : mapdflt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
vertex = 0;
|
|
Packit |
90a5c9 |
while (vertex < MAXVERTS &&
|
|
Packit |
90a5c9 |
sscanf(string_pos, "%lf%*[, ]%lf",
|
|
Packit |
90a5c9 |
&pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
|
|
Packit |
90a5c9 |
/* Now skip what we just read... we can't use ANSIism %n */
|
|
Packit |
90a5c9 |
while (apr_isspace(*string_pos)) { /* past whitespace */
|
|
Packit |
90a5c9 |
string_pos++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
while (apr_isdigit(*string_pos)) { /* and the 1st number */
|
|
Packit |
90a5c9 |
string_pos++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
string_pos++; /* skip the ',' */
|
|
Packit |
90a5c9 |
while (apr_isspace(*string_pos)) { /* past any more whitespace */
|
|
Packit |
90a5c9 |
string_pos++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
while (apr_isdigit(*string_pos)) { /* 2nd number */
|
|
Packit |
90a5c9 |
string_pos++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
vertex++;
|
|
Packit |
90a5c9 |
} /* so long as there are more vertices to
|
|
Packit |
90a5c9 |
read, and we have room, read them in.
|
|
Packit |
90a5c9 |
We start where we left off of the last
|
|
Packit |
90a5c9 |
sscanf, not at the beginning. */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
pointarray[vertex][X] = -1; /* signals the end of vertices */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (showmenu) {
|
|
Packit |
90a5c9 |
if (!href_text) {
|
|
Packit |
90a5c9 |
read_quoted(&string_pos, &href_text); /* href text could
|
|
Packit |
90a5c9 |
be here instead */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, value);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
goto menu_bail;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
menu_directive(r, imap_menu, redirect,
|
|
Packit |
90a5c9 |
href_text ? href_text : value);
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
/* note that we don't make it past here if we are making a menu */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (testpoint[X] == -1 || pointarray[0][X] == -1) {
|
|
Packit |
90a5c9 |
continue; /* don't try the following tests if testpoints
|
|
Packit |
90a5c9 |
are invalid, or if there are no
|
|
Packit |
90a5c9 |
coordinates */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(directive, "poly")) { /* poly */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (pointinpoly(testpoint, pointarray)) {
|
|
Packit |
90a5c9 |
ap_cfg_closefile(imap);
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, value);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return (imap_reply(r, redirect));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(directive, "circle")) { /* circle */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (pointincircle(testpoint, pointarray)) {
|
|
Packit |
90a5c9 |
ap_cfg_closefile(imap);
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, value);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return (imap_reply(r, redirect));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(directive, "rect")) { /* rect */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (pointinrect(testpoint, pointarray)) {
|
|
Packit |
90a5c9 |
ap_cfg_closefile(imap);
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, value);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return (imap_reply(r, redirect));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(directive, "point")) { /* point */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (is_closer(testpoint, pointarray, &closest_yet)) {
|
|
Packit |
90a5c9 |
closest = apr_pstrdup(r->pool, value);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
} /* move on to next line whether it's
|
|
Packit |
90a5c9 |
closest or not */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
} /* nothing matched, so we get another line! */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_cfg_closefile(imap); /* we are done with the map file; close it */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (showmenu) {
|
|
Packit |
90a5c9 |
menu_footer(r); /* finish the menu and we are done */
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (closest) { /* if a 'point' directive has been seen */
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, closest);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return (imap_reply(r, redirect));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (mapdflt) { /* a default should be defined, even if
|
|
Packit |
90a5c9 |
only 'nocontent' */
|
|
Packit |
90a5c9 |
redirect = imap_url(r, base, mapdflt);
|
|
Packit |
90a5c9 |
if (!redirect) {
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return (imap_reply(r, redirect));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far,
|
|
Packit |
90a5c9 |
we failed. They lose! */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
need_2_fields:
|
|
Packit |
90a5c9 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00679)
|
|
Packit |
90a5c9 |
"map file %s, line %d syntax error: requires at "
|
|
Packit |
90a5c9 |
"least two fields", r->uri, imap->line_number);
|
|
Packit |
90a5c9 |
/* fall through */
|
|
Packit |
90a5c9 |
menu_bail:
|
|
Packit |
90a5c9 |
ap_cfg_closefile(imap);
|
|
Packit |
90a5c9 |
if (showmenu) {
|
|
Packit |
90a5c9 |
/* There's not much else we can do ... we've already sent the headers
|
|
Packit |
90a5c9 |
* to the client.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
ap_rputs("\n\n[an internal server error occured]\n", r);
|
|
Packit |
90a5c9 |
menu_footer(r);
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return HTTP_INTERNAL_SERVER_ERROR;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int imap_handler(request_rec *r)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
/* Optimization: skip the allocation of large local variables on the
|
|
Packit |
90a5c9 |
* stack (in imap_handler_internal()) on requests that aren't using
|
|
Packit |
90a5c9 |
* imagemaps
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (r->method_number != M_GET || (strcmp(r->handler,IMAP_MAGIC_TYPE)
|
|
Packit |
90a5c9 |
&& strcmp(r->handler, "imap-file"))) {
|
|
Packit |
90a5c9 |
return DECLINED;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
return imap_handler_internal(r);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void register_hooks(apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ap_hook_handler(imap_handler,NULL,NULL,APR_HOOK_MIDDLE);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
AP_DECLARE_MODULE(imagemap) =
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
STANDARD20_MODULE_STUFF,
|
|
Packit |
90a5c9 |
create_imap_dir_config, /* dir config creater */
|
|
Packit |
90a5c9 |
merge_imap_dir_configs, /* dir merger --- default is to override */
|
|
Packit |
90a5c9 |
NULL, /* server config */
|
|
Packit |
90a5c9 |
NULL, /* merge server config */
|
|
Packit |
90a5c9 |
imap_cmds, /* command apr_table_t */
|
|
Packit |
90a5c9 |
register_hooks /* register hooks */
|
|
Packit |
90a5c9 |
};
|