mod_imap.c revision 19c2bd3fc0a44f0ed4eaa7b4158f3917e9c5f988
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina/* ====================================================================
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Redistribution and use in source and binary forms, with or without
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * modification, are permitted provided that the following conditions
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * are met:
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * 1. Redistributions of source code must retain the above copyright
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * notice, this list of conditions and the following disclaimer.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * 2. Redistributions in binary form must reproduce the above copyright
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * notice, this list of conditions and the following disclaimer in
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * the documentation and/or other materials provided with the
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * distribution.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * 3. All advertising materials mentioning features or use of this
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * software must display the following acknowledgment:
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * "This product includes software developed by the Apache Group
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * for use in the Apache HTTP server project (http://www.apache.org/)."
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * 4. The names "Apache Server" and "Apache Group" must not be used to
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * endorse or promote products derived from this software without
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * prior written permission. For written permission, please contact
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * apache@apache.org.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * 5. Products derived from this software may not be called "Apache"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * nor may "Apache" appear in their names without prior written
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * permission of the Apache Group.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * 6. Redistributions of any form whatsoever must retain the following
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * acknowledgment:
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * "This product includes software developed by the Apache Group
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * for use in the Apache HTTP server project (http://www.apache.org/)."
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * OF THE POSSIBILITY OF SUCH DAMAGE.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * ====================================================================
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * This software consists of voluntary contributions made by many
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * individuals on behalf of the Apache Group and was originally based
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * on public domain software written at the National Center for
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Supercomputing Applications, University of Illinois, Urbana-Champaign.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * For more information on the Apache Group and the Apache HTTP server
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * project, please see <http://www.apache.org/>.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina/*
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * This imagemap module started as a port of the original imagemap.c
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu).
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * This version includes the mapping algorithms found in version 1.3
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * of imagemap.c.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Contributors to this code include:
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Eric Haines, erich@eye.com
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Randy Terbush, randy@zyzzyva.com
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * port to Apache module format, "base_uri" and support for relative URLs
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * James H. Cloos, Jr., cloos@jhcloos.com
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Added point datatype, using code in NCSA's version 1.8 imagemap.c
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * program, as distributed with version 1.4.1 of their server.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Nathan Kurz, nate@tripod.com
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Rewrite/reorganization. New handling of default, base and relative URLs.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * New Configuration directives:
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * ImapMenu {none, formatted, semiformatted, unformatted}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * ImapDefault {error, nocontent, referer, menu, URL}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * ImapBase {map, referer, URL}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Support for creating non-graphical menu added. (backwards compatible):
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Old: directive URL [x,y ...]
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * New: directive URL "Menu text" [x,y ...]
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * or: directive URL x,y ... "Menu text"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Map format and menu concept courtesy Joshua Bell, jsbell@acs.ucalgary.ca.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Mark Cox, mark@ukweb.com, Allow relative URLs even when no base specified
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "httpd.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "http_config.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "http_request.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "http_core.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "http_protocol.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "http_main.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "http_log.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#include "util_script.h"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define IMAP_MAGIC_TYPE "application/x-httpd-imap"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define MAXVERTS 100
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define X 0
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define Y 1
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define IMAP_MENU_DEFAULT "formatted"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define IMAP_DEFAULT_DEFAULT "nocontent"
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define IMAP_BASE_DEFAULT "map"
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#ifdef SUNOS4
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinadouble strtod(); /* SunOS needed this */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#endif
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinamodule MODULE_VAR_EXPORT imap_module;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinatypedef struct {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *imap_menu;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *imap_default;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *imap_base;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina} imap_conf_rec;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic void *create_imap_dir_config(pool *p, char *dummy)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina imap_conf_rec *icr =
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina (imap_conf_rec *) ap_palloc(p, sizeof(imap_conf_rec));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina icr->imap_menu = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina icr->imap_default = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina icr->imap_base = NULL;
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return icr;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic void *merge_imap_dir_configs(pool *p, void *basev, void *addv)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina imap_conf_rec *new = (imap_conf_rec *) ap_pcalloc(p, sizeof(imap_conf_rec));
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek imap_conf_rec *base = (imap_conf_rec *) basev;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina imap_conf_rec *add = (imap_conf_rec *) addv;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina new->imap_default = add->imap_default ? add->imap_default
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina : base->imap_default;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return new;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic const command_rec imap_cmds[] =
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina {"ImapMenu", ap_set_string_slot,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina (void *) XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina "the type of menu generated: none, formatted, semiformatted, unformatted"},
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina {"ImapDefault", ap_set_string_slot,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina (void *) XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina "the action taken if no match: error, nocontent, referer, menu, URL"},
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina {"ImapBase", ap_set_string_slot,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina (void *) XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina "the base for all URL's: map, referer, URL (or start of)"},
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina {NULL}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina};
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic int pointinrect(const double point[2], double coords[MAXVERTS][2])
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek double max[2], min[2];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (coords[0][X] > coords[1][X]) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina max[0] = coords[0][X];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina min[0] = coords[1][X];
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina else {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina max[0] = coords[1][X];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina min[0] = coords[0][X];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (coords[0][Y] > coords[1][Y]) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina max[1] = coords[0][Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina min[1] = coords[1][Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina else {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina max[1] = coords[1][Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina min[1] = coords[0][Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ((point[X] >= min[0] && point[X] <= max[0]) &&
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina (point[Y] >= min[1] && point[Y] <= max[1]));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic int pointincircle(const double point[2], double coords[MAXVERTS][2])
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double radius1, radius2;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (radius2 <= radius1);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define fmin(a,b) (((a)>(b))?(b):(a))
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina#define fmax(a,b) (((a)>(b))?(a):(b))
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina int i, numverts, crossings = 0;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double x = point[X], y = point[Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina for (numverts = 0; pgon[numverts][X] != -1 && numverts < MAXVERTS;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina numverts++) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* just counting the vertexes */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina for (i = 0; i < numverts; i++) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double x1=pgon[i][X];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double y1=pgon[i][Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double x2=pgon[(i + 1) % numverts][X];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double y2=pgon[(i + 1) % numverts][Y];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double d=(y - y1) * (x2 - x1) - (x - x1) * (y2 - y1);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if ((y1 >= y) != (y2 >= y)) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina crossings +=y2 - y1 >= 0 ? d >= 0 : d <= 0;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!d && fmin(x1,x2) <= x && x <= fmax(x1,x2)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina && fmin(y1,y2) <= y && y <= fmax(y1,y2)) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return 1;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return crossings & 0x01;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic int is_closer(const double point[2], double coords[MAXVERTS][2],
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double *closest)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double dist_squared = ((point[X] - coords[0][X])
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * (point[X] - coords[0][X]))
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina + ((point[Y] - coords[0][Y])
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * (point[Y] - coords[0][Y]));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (point[X] < 0 || point[Y] < 0) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (0); /* don't mess around with negative coordinates */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (*closest < 0 || dist_squared < *closest) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *closest = dist_squared;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (1); /* if this is the first point or is the closest yet
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina set 'closest' equal to this distance^2 */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (0); /* if it's not the first or closest */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic double get_x_coord(const char *args)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *endptr; /* we want it non-null */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double x_coord = -1; /* -1 is returned if no coordinate is given */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (args == NULL) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (-1); /* in case we aren't passed anything */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (*args && !ap_isdigit(*args) && *args != ',') {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina args++; /* jump to the first digit, but not past
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina a comma or end */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina x_coord = strtod(args, &endptr);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (endptr > args) { /* if a conversion was made */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (x_coord);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (-1); /* else if no conversion was made,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina or if no args was given */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic double get_y_coord(const char *args)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *endptr; /* we want it non-null */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *start_of_y = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina double y_coord = -1; /* -1 is returned on error */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (args == NULL) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (-1); /* in case we aren't passed anything */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina start_of_y = strchr(args, ','); /* the comma */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (start_of_y) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina start_of_y++; /* start looking at the character after
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina the comma */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (*start_of_y && !ap_isdigit(*start_of_y)) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina start_of_y++; /* jump to the first digit, but not
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina past the end */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina y_coord = strtod(start_of_y, &endptr);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (endptr > start_of_y) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (y_coord);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return (-1); /* if no conversion was made, or
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina no comma was found in args */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina/* See if string has a "quoted part", and if so set *quoted_part to
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * the first character of the quoted part, then hammer a \0 onto the
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * trailing quote, and set *string to point at the first character
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * past the second quote.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * Otherwise set *quoted_part to NULL, and leave *string alone.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic void read_quoted(char **string, char **quoted_part)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *strp = *string;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* assume there's no quoted part */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *quoted_part = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (ap_isspace(*strp)) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina strp++; /* go along string until non-whitespace */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (*strp == '"') { /* if that character is a double quote */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina strp++; /* step over it */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *quoted_part = strp; /* note where the quoted part begins */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (*strp && *strp != '"') {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ++strp; /* skip the quoted portion */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *strp = '\0'; /* end the string with a NUL */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina strp++; /* step over the last double quote */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *string = strp;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina/*
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * returns the mapped URL or NULL.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic char *imap_url(request_rec *r, const char *base, const char *value)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina/* translates a value into a URL. */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina int slen, clen;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *string_pos = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina const char *string_pos_const = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *directory = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina const char *referer = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char *my_base;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_construct_url(r->pool, r->uri, r);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_pstrdup(r->pool, value); /* these are handled elsewhere,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina so just copy them */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(value, "referer")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina referer = ap_table_get(r->headers_in, "Referer");
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (referer && *referer) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_pstrdup(r->pool, referer);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina else {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* XXX: This used to do *value = '\0'; ... which is totally bogus
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * because it hammers the passed in value, which can be a string
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * constant, or part of a config, or whatever. Total garbage.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * This works around that without changing the rest of this
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * code much
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina value = ""; /* if 'referer' but no referring page,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina null the value */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos_const = value;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (ap_isalpha(*string_pos_const)) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos_const++; /* go along the URL from the map
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina until a non-letter */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (*string_pos_const == ':') {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* if letters and then a colon (like http:) */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* it's an absolute URL, so use it! */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_pstrdup(r->pool, value);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!base || !*base) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (value && *value) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_pstrdup(r->pool, value); /* no base: use what is given */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* no base, no value: pick a simple default */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_construct_url(r->pool, "/", r);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* must be a relative URL to be combined with base */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (strchr(base, '/') == NULL && (!strncmp(value, "../", 3)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina || !strcmp(value, ".."))) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina "invalid base directive in map file: %s", r->uri);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina my_base = ap_pstrdup(r->pool, base);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos = my_base;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (*string_pos) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (*string_pos == '/' && *(string_pos + 1) == '/') {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos += 2; /* if there are two slashes, jump over them */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina continue;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (*string_pos == '/') { /* the first single slash */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (value[0] == '/') {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *string_pos = '\0';
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina } /* if the URL from the map starts from root,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina end the base URL string at the first single
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina slash */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina else {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina directory = string_pos; /* save the start of
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina the directory portion */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos = strrchr(string_pos, '/'); /* now reuse
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos++; /* step over that last slash */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *string_pos = '\0';
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina } /* but if the map url is relative, leave the
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina slash on the base (if there is one) */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina break;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_pos++; /* until we get to the end of my_base without
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina finding a slash by itself */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (directory && (slen = strlen(directory))) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* for each '..', knock a directory off the end
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina by ending the string right at the last slash.
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina But only consider the directory portion: don't eat
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina into the server name. And only try if a directory
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina portion was found */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina clen = slen - 1;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while ((slen - clen) == 1) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if ((string_pos = strrchr(directory, '/'))) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina *string_pos = '\0';
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina clen = strlen(directory);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (clen == 0) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina break;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina value += 2; /* jump over the '..' that we found in the
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina value */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina else if (directory) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina "invalid directory name in map file: %s", r->uri);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina value++; /* step over the '/' if there are more '..'
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina to do. This way, we leave the starting
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina '/' on value after the last '..', but get
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina rid of it otherwise */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina } /* by this point, value does not start
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina with '..' */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (value && *value) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return ap_pstrcat(r->pool, my_base, value, NULL);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return my_base;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic int imap_reply(request_rec *r, char *redirect)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(redirect, "error")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return SERVER_ERROR; /* they actually requested an error! */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(redirect, "nocontent")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return HTTP_NO_CONTENT; /* tell the client to keep the page it has */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek if (redirect && *redirect) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_table_setn(r->headers_out, "Location", redirect);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return REDIRECT; /* must be a URL, so redirect to it */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return SERVER_ERROR;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic void menu_header(request_rec *r, char *menu)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina r->content_type = "text/html";
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_send_http_header(r);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ", r->uri,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina "</title>\n</head><body>\n", NULL);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(menu, "formatted")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_rvputs(r, "<h1>Menu for ", r->uri, "</h1>\n<hr>\n\n", NULL);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic void menu_blank(request_rec *r, char *menu)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(menu, "formatted")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_rputs("\n", r);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(menu, "semiformatted")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_rputs("<br>\n", r);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!strcasecmp(menu, "unformatted")) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ap_rputs("\n", r);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek return;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
static void menu_comment(request_rec *r, char *menu, char *comment)
{
if (!strcasecmp(menu, "formatted")) {
ap_rputs("\n", r); /* print just a newline if 'formatted' */
}
if (!strcasecmp(menu, "semiformatted") && *comment) {
ap_rvputs(r, comment, "\n", NULL);
}
if (!strcasecmp(menu, "unformatted") && *comment) {
ap_rvputs(r, comment, "\n", NULL);
}
return; /* comments are ignored in the
'formatted' form */
}
static void menu_default(request_rec *r, char *menu, char *href, char *text)
{
if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
return; /* don't print such lines, these aren't
really href's */
}
if (!strcasecmp(menu, "formatted")) {
ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
"</a></pre>\n", NULL);
}
if (!strcasecmp(menu, "semiformatted")) {
ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
"</a></pre>\n", NULL);
}
if (!strcasecmp(menu, "unformatted")) {
ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
}
return;
}
static void menu_directive(request_rec *r, char *menu, char *href, char *text)
{
if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
return; /* don't print such lines, as this isn't
really an href */
}
if (!strcasecmp(menu, "formatted")) {
ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
"</a></pre>\n", NULL);
}
if (!strcasecmp(menu, "semiformatted")) {
ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
"</a></pre>\n", NULL);
}
if (!strcasecmp(menu, "unformatted")) {
ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
}
return;
}
static void menu_footer(request_rec *r)
{
ap_rputs("\n\n</body>\n</html>\n", r); /* finish the menu */
}
static int imap_handler(request_rec *r)
{
char input[MAX_STRING_LEN];
char *directive;
char *value;
char *href_text;
char *base;
char *redirect;
char *mapdflt;
char *closest = NULL;
double closest_yet = -1;
double testpoint[2];
double pointarray[MAXVERTS + 1][2];
int vertex;
char *string_pos;
int showmenu = 0;
imap_conf_rec *icr = ap_get_module_config(r->per_dir_config, &imap_module);
char *imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
char *imap_default = icr->imap_default
? icr->imap_default : IMAP_DEFAULT_DEFAULT;
char *imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
configfile_t *imap;
if (r->method_number != M_GET) {
return DECLINED;
}
imap = ap_pcfg_openfile(r->pool, r->filename);
if (!imap) {
return 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 && !ap_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(*string_pos && ap_isspace(*string_pos)) { /* past whitespace */
++string_pos;
}
value = string_pos;
while (*string_pos && !ap_isspace(*string_pos)) { /* past value */
++string_pos;
}
if (ap_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 (ap_isspace(*string_pos)) { /* past whitespace */
string_pos++;
}
while (ap_isdigit(*string_pos)) { /* and the 1st number */
string_pos++;
}
string_pos++; /* skip the ',' */
while (ap_isspace(*string_pos)) { /* past any more whitespace */
string_pos++;
}
while (ap_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 = ap_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_NOERRNO|APLOG_ERR, r,
"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 occured]\n", r);
menu_footer(r);
return OK;
}
return HTTP_INTERNAL_SERVER_ERROR;
}
static const handler_rec imap_handlers[] =
{
{IMAP_MAGIC_TYPE, imap_handler},
{"imap-file", imap_handler},
{NULL}
};
module MODULE_VAR_EXPORT imap_module =
{
STANDARD20_MODULE_STUFF,
create_imap_dir_config, /* dir config creater */
merge_imap_dir_configs, /* dir merger --- default is to override */
NULL, /* server config */
NULL, /* merge server config */
imap_cmds, /* command table */
imap_handlers, /* handlers */
NULL /* register hooks */
};