httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@hyperreal.org
Subject cvs commit: apache/src mod_imap.c
Date Mon, 05 Jan 1998 20:49:00 GMT
marc        98/01/05 12:48:59

  Modified:    src      Tag: APACHE_1_2_X mod_imap.c
  Log:
  SECURITY: Numerous changes to mod_imap in a general cleanup including
  fixing a possible buffer overflow.  This cleanup was done with 1.3
  code as a basis.
  
  Dean says:
  
  This is a bit large, but that's deliberate because I took the opportunity
  to do the crap that we've been wanting done to mod_imap.
  
  - liberal use of const to help find stack assignments
  
  - remove all constant sized char arrays except input[]; replaced by pool
      string functions or by pointers into tokens inside the input[]
      array
  
  - in particular, the use of read_quoted() had a stack overrun potential.
      Eliminated.
  
  - These changes can chew memory when generating a menu.  I don't care,
      I'd rather have them do that than have them overrun the stack.  It
      shouldn't chew more than approx the size of the map file though.
  
  - better error handling
  
  Submitted by:	Dean Gaudet
  Reviewed by:	Martin Kraemer, Mark J Cox, Marc Slemko, Randy Terbush
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.21.2.3  +654 -623  apache/src/mod_imap.c
  
  Index: mod_imap.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_imap.c,v
  retrieving revision 1.21.2.2
  retrieving revision 1.21.2.3
  diff -u -r1.21.2.2 -r1.21.2.3
  --- mod_imap.c	1997/11/05 11:43:14	1.21.2.2
  +++ mod_imap.c	1998/01/05 20:48:58	1.21.2.3
  @@ -20,7 +20,8 @@
    *
    * 4. The names "Apache Server" and "Apache Group" must not be used to
    *    endorse or promote products derived from this software without
  - *    prior written permission.
  + *    prior written permission. For written permission, please contact
  + *    apache@apache.org.
    *
    * 5. Redistributions of any form whatsoever must retain the following
    *    acknowledgment:
  @@ -96,8 +97,6 @@
   #include "util_script.h"
   
   #define IMAP_MAGIC_TYPE "application/x-httpd-imap"
  -#define LARGEBUF 500
  -#define SMALLBUF 256
   #define MAXVERTS 100
   #define X 0
   #define Y 1
  @@ -107,62 +106,65 @@
   #define IMAP_BASE_DEFAULT "map"
   
   #ifdef SUNOS4
  -double strtod();   /* SunOS needed this */
  +double strtod();                /* SunOS needed this */
   #endif
   
   module imap_module;
   
  -typedef struct { 
  -  char *imap_menu;
  -  char *imap_default;
  -  char *imap_base;
  +typedef struct {
  +    char *imap_menu;
  +    char *imap_default;
  +    char *imap_base;
   } imap_conf_rec;
   
  -void *create_imap_dir_config (pool *p, char *dummy) { 
  -  imap_conf_rec *icr = 
  -    (imap_conf_rec *)palloc(p, sizeof(imap_conf_rec));
  -
  -  icr->imap_menu = NULL;
  -  icr->imap_default = NULL;
  -  icr->imap_base = NULL;
  -
  -  return icr;
  -}
  -
  -void *merge_imap_dir_configs (pool *p, void *basev, void *addv)
  -{
  -  imap_conf_rec *new=(imap_conf_rec *)pcalloc (p, sizeof(imap_conf_rec));
  -  imap_conf_rec *base = (imap_conf_rec *)basev;
  -  imap_conf_rec *add = (imap_conf_rec *)addv;
  - 
  -  new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
  -  new->imap_default=add->imap_default ? add->imap_default : base->imap_default;
  -  new->imap_base =add-> imap_base ? add->imap_base : base->imap_base;
  -
  -  return new;
  +static void *create_imap_dir_config(pool *p, char *dummy)
  +{
  +    imap_conf_rec *icr =
  +    (imap_conf_rec *) palloc(p, sizeof(imap_conf_rec));
  +
  +    icr->imap_menu = NULL;
  +    icr->imap_default = NULL;
  +    icr->imap_base = NULL;
  +
  +    return icr;
  +}
  +
  +static void *merge_imap_dir_configs(pool *p, void *basev, void *addv)
  +{
  +    imap_conf_rec *new = (imap_conf_rec *) pcalloc(p, sizeof(imap_conf_rec));
  +    imap_conf_rec *base = (imap_conf_rec *) basev;
  +    imap_conf_rec *add = (imap_conf_rec *) addv;
  +
  +    new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
  +    new->imap_default = add->imap_default ? add->imap_default : base->imap_default;
  +    new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
  +
  +    return new;
   }
   
   
  -command_rec imap_cmds[] = {
  -{ "ImapMenu", set_string_slot, 
  -    (void*)XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1,
  -    "the type of menu generated: none, formatted, semiformatted, unformatted"},
  -{ "ImapDefault", set_string_slot, 
  -    (void*)XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1,
  -    "the action taken if no match: error, nocontent, referer, menu, URL" },
  -{ "ImapBase", set_string_slot, 
  -    (void*)XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1,
  -    "the base for all URL's: map, referer, URL (or start of)" },
  -{ NULL }
  +static command_rec imap_cmds[] =
  +{
  +    {"ImapMenu", set_string_slot,
  +     (void *) XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1,
  + "the type of menu generated: none, formatted, semiformatted, unformatted"},
  +    {"ImapDefault", set_string_slot,
  +     (void *) XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1,
  +     "the action taken if no match: error, nocontent, referer, menu, URL"},
  +    {"ImapBase", set_string_slot,
  +     (void *) XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1,
  +     "the base for all URL's: map, referer, URL (or start of)"},
  +    {NULL}
   };
   
  -int pointinrect(double point[2], double coords[MAXVERTS][2])
  +static int pointinrect(const double point[2], const double coords[MAXVERTS][2])
   {
       double max[2], min[2];
       if (coords[0][X] > coords[1][X]) {
           max[0] = coords[0][X];
           min[0] = coords[1][X];
  -    } else {
  +    }
  +    else {
           max[0] = coords[1][X];
           min[0] = coords[0][X];
       }
  @@ -170,33 +172,35 @@
       if (coords[0][Y] > coords[1][Y]) {
           max[1] = coords[0][Y];
           min[1] = coords[1][Y];
  -    } else {
  +    }
  +    else {
           max[1] = coords[1][Y];
           min[1] = coords[0][Y];
       }
   
       return ((point[X] >= min[0] && point[X] <= max[0]) &&
  -	    (point[Y] >= min[1] && point[Y] <= max[1]));
  +            (point[Y] >= min[1] && point[Y] <= max[1]));
   }
   
  -int pointincircle(double point[2], double coords[MAXVERTS][2])
  +static int pointincircle(const double point[2], const double coords[MAXVERTS][2])
   {
  -    int radius1, radius2;
  +    double radius1, radius2;
   
       radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
  -	+ ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
  -    
  +        + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
  +
       radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
  -	+ ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  +        + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
   
       return (radius2 <= radius1);
   }
   
  -int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  +static int pointinpoly(const double point[2], const double pgon[MAXVERTS][2])
   {
       int i, numverts, inside_flag, xflag0;
       int crossings;
  -    double *p, *stop;
  +    double *p;
  +    const double *stop;
       double tx, ty, y;
   
       for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++);
  @@ -211,54 +215,54 @@
       p = (double *) pgon + 1;
       if ((y >= ty) != (*p >= ty)) {
   
  -	if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx)) {
  -	    if (xflag0)
  -		crossings++;
  -	}
  -	else {
  -	    crossings += (pgon[numverts - 1][X] - (y - ty) *
  -			  (*(double *) pgon - pgon[numverts - 1][X]) /
  -			  (*p - y)) >= tx;
  -	}
  +        if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx)) {
  +            if (xflag0)
  +                crossings++;
  +        }
  +        else {
  +            crossings += (pgon[numverts - 1][X] - (y - ty) *
  +                          (*(double *) pgon - pgon[numverts - 1][X]) /
  +                          (*p - y)) >= tx;
  +        }
       }
   
       stop = pgon[numverts];
   
       for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  -	
  -	if (y >= ty) {
  -        
  -	    while ((p < stop) && (*p >= ty))
  -		p += 2;
  -	    
  -	    if (p >= stop)
  -		break;
  -	    if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  -		
  -		if (xflag0)
  -		    crossings++;
  -	    }
  -	    else {
  -		crossings += (*(p - 3) - (*(p - 2) - ty) *
  -			      (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  -	    }
  -	}
  -	else {
  -	    while ((p < stop) && (*p < ty))
  -		p += 2;
   
  -	    if (p >= stop)
  -		break;
  +        if (y >= ty) {
   
  -	    if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  -		if (xflag0)
  -		    crossings++;
  -	    }
  -	    else {
  -		crossings += (*(p - 3) - (*(p - 2) - ty) *
  -			      (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  -	    }
  -	}
  +            while ((p < stop) && (*p >= ty))
  +                p += 2;
  +
  +            if (p >= stop)
  +                break;
  +            if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  +
  +                if (xflag0)
  +                    crossings++;
  +            }
  +            else {
  +                crossings += (*(p - 3) - (*(p - 2) - ty) *
  +                              (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  +            }
  +        }
  +        else {
  +            while ((p < stop) && (*p < ty))
  +                p += 2;
  +
  +            if (p >= stop)
  +                break;
  +
  +            if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  +                if (xflag0)
  +                    crossings++;
  +            }
  +            else {
  +                crossings += (*(p - 3) - (*(p - 2) - ty) *
  +                              (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  +            }
  +        }
       }
   
       inside_flag = crossings & 0x01;
  @@ -266,580 +270,607 @@
   }
   
   
  -int is_closer(double point[2], double coords[MAXVERTS][2], double *closest)
  +static int is_closer(const double point[2], const double coords[MAXVERTS][2], double *closest)
   {
  -  double dist_squared =((point[X] - coords[0][X]) * (point[X] - coords[0][X]))
  -	     + ((point[Y] - coords[0][Y]) * (point[Y] - coords[0][Y]));
  +    double dist_squared = ((point[X] - coords[0][X]) * (point[X] - coords[0][X]))
  +    + ((point[Y] - coords[0][Y]) * (point[Y] - coords[0][Y]));
  +
  +    if (point[X] < 0 || point[Y] < 0)
  +        return (0);             /* don't mess around with negative coordinates */
   
  -  if (point[X] < 0 || point[Y] < 0 ) 
  -    return(0);          /* don't mess around with negative coordinates */
  +    if (*closest < 0 || dist_squared < *closest) {
  +        *closest = dist_squared;
  +        return (1);             /* if this is the first point or is the closest yet
  +                                   set 'closest' equal to this distance^2 */
  +    }
   
  -  if ( *closest < 0 || dist_squared < *closest ) {
  -    *closest = dist_squared;
  -    return(1);         /* if this is the first point or is the closest yet
  -			  set 'closest' equal to this distance^2 */
  -  }
  -  
  -  return(0);           /* if it's not the first or closest */
  +    return (0);                 /* if it's not the first or closest */
   
   }
   
  -double get_x_coord(char *args) 
  +static double get_x_coord(const char *args)
   {
  -  char *endptr;           /* we want it non-null */
  -  double x_coord = -1;    /* -1 is returned if no coordinate is given */
  +    char *endptr;               /* we want it non-null */
  +    double x_coord = -1;        /* -1 is returned if no coordinate is given */
   
  -  if (args == NULL)
  -    return(-1);           /* in case we aren't passed anything */
  +    if (args == NULL)
  +        return (-1);            /* in case we aren't passed anything */
   
  -  while( *args && !isdigit(*args) && *args != ',') 
  -    args++;   /* jump to the first digit, but not past a comma or end */
  +    while (*args && !isdigit(*args) && *args != ',')
  +        args++;                 /* jump to the first digit, but not past a comma or end */
   
  -  x_coord = strtod(args, &endptr);
  +    x_coord = strtod(args, &endptr);
   
  -  if (endptr > args)   /* if a conversion was made */
  -    return(x_coord); 
  +    if (endptr > args)          /* if a conversion was made */
  +        return (x_coord);
   
  -  return(-1);  /* else if no conversion was made, or if no args was given */
  +    return (-1);                /* else if no conversion was made, or if no args was given */
   }
   
  -double get_y_coord(char *args) 
  +static double get_y_coord(const char *args)
   {
  -  char *endptr;        /* we want it non-null */
  -  char *start_of_y = NULL;
  -  double y_coord = -1;    /* -1 is returned on error */
  +    char *endptr;               /* we want it non-null */
  +    char *start_of_y = NULL;
  +    double y_coord = -1;        /* -1 is returned on error */
   
  -  if (args == NULL)
  -    return(-1);           /* in case we aren't passed anything */
  +    if (args == NULL)
  +        return (-1);            /* in case we aren't passed anything */
   
  -  start_of_y = strchr(args, ',');  /* the comma */
  +    start_of_y = strchr(args, ',');     /* the comma */
   
  -  if (start_of_y) {
  -    
  -    start_of_y++;    /* start looking at the character after the comma */
  +    if (start_of_y) {
   
  -    while( *start_of_y && !isdigit(*start_of_y))  
  -      start_of_y++;  /* jump to the first digit, but not past the end */
  +        start_of_y++;           /* start looking at the character after the comma */
   
  -    y_coord = strtod(start_of_y, &endptr);
  +        while (*start_of_y && !isdigit(*start_of_y))
  +            start_of_y++;       /* jump to the first digit, but not past the end */
  +
  +        y_coord = strtod(start_of_y, &endptr);
  +
  +        if (endptr > start_of_y)
  +            return (y_coord);
  +    }
   
  -    if (endptr > start_of_y) 
  -      return(y_coord); 
  -  }
  -  
  -  return(-1);   /* if no conversion was made, or no comma was found in args */
  +    return (-1);                /* if no conversion was made, or no comma was found in args */
   }
  -  
   
  -int read_quoted(char *string, char *quoted_part)
  -{ 
  -  char *starting_pos = string;
  -  
  -  while ( isspace(*string) )
  -    string++;    /* go along string until non-whitespace */
   
  -  if ( *string == '"' ) { /* if that character is a double quote */
  +/* See if string has a "quoted part", and if so set *quoted_part to
  + * the first character of the quoted part, then hammer a \0 onto the
  + * trailing quote, and set *string to point at the first character
  + * past the second quote.
  + *
  + * Otherwise set *quoted_part to NULL, and leave *string alone.
  + */
  +static void read_quoted(char **string, char **quoted_part)
  +{
  +    char *strp = *string;
   
  -    string++;  /* step over it */
  +    /* assume there's no quoted part */
  +    *quoted_part = NULL;
   
  -    while ( *string && *string != '"' ) {
  -      *quoted_part++ = *string++;  /* copy the quoted portion */
  -    }
  +    while (isspace(*strp))
  +        strp++;               	/* go along string until non-whitespace */
  +
  +    if (*strp == '"') {       	/* if that character is a double quote */
  +        strp++;               	/* step over it */
  +	*quoted_part = strp;  	/* note where the quoted part begins */
  +
  +        while (*strp && *strp != '"') {
  +	    ++strp;		/* skip the quoted portion */
  +        }
   
  -    *quoted_part = '\0';  /* end the string with a SNUL */
  -	
  -    string++;  /* step over the last double quote */
  -  }
  +        *strp = '\0';    	/* end the string with a NUL */
   
  -  return(string - starting_pos); /* return the total characters read */
  +        strp++;               	/* step over the last double quote */
  +	*string = strp;
  +    }
   }
   
   /*
  - * url needs to point to a string with at least SMALLBUF memory allocated
  + * returns the mapped URL or NULL.
    */
  -void imap_url(request_rec *r, char *base, char *value, char *url) 
  +static char *imap_url(request_rec *r, const char *base, const char *value)
   {
   /* translates a value into a URL. */
  -  int slen, clen;
  -  char *string_pos = NULL;
  -  char *directory = NULL;
  -  char *referer = NULL;
  -  char my_base[SMALLBUF] = {'\0'};
  -
  -  if ( ! strcasecmp(value, "map" ) || ! strcasecmp(value, "menu") ) {
  -    if (r->server->port == DEFAULT_PORT ) { 
  -      ap_snprintf(url, SMALLBUF,
  -		"http://%s%s", r->server->server_hostname, r->uri);
  +    int slen, clen;
  +    char *string_pos = NULL;
  +    const char *string_pos_const = NULL;
  +    char *directory = NULL;
  +    char *referer = NULL;
  +    char *my_base;
  +
  +    if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
  +	return construct_url(r->pool, r->uri, r->server);
  +    }
  +
  +    if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
  +        return pstrdup(r->pool, value);                 /* these are handled elsewhere, so just copy them */
  +    }
  +
  +    if (!strcasecmp(value, "referer")) {
  +        referer = table_get(r->headers_in, "Referer");
  +        if (referer && *referer) {
  +	    return pstrdup(r->pool, referer);
  +        }
  +        else {
  +	    /* XXX:  This used to do *value = '\0'; ... which is totally bogus
  +	     * because it hammers the passed in value, which can be a string constant,
  +	     * or part of a config, or whatever.  Total garbage.  This works around
  +	     * that without changing the rest of this code much
  +	     */
  +            value = "";      /* if 'referer' but no referring page, null the value */
  +        }
  +    }
  +
  +    string_pos_const = value;
  +    while (isalpha(*string_pos_const))
  +	string_pos_const++;           /* go along the URL from the map until a non-letter */
  +    if (*string_pos_const == ':') {
  +	/* if letters and then a colon (like http:) */
  +	/* it's an absolute URL, so use it! */
  +	return pstrdup(r->pool, value);
  +    }
  +
  +    if (!base || !*base) {
  +        if (value && *value) {
  +	    return pstrdup(r->pool, value); /* no base: use what is given */
  +        }
  +	/* no base, no value: pick a simple default */
  +	return construct_url(r->pool, "/", r->server);
  +    }
  +
  +    /* must be a relative URL to be combined with base */
  +    if (strchr(base, '/') == NULL && (!strncmp(value, "../", 3) || !strcmp(value, ".."))) {
  +        log_reason("invalid base directive in map file: %s", r->uri, r);
  +        return NULL;
  +    }
  +    my_base = pstrdup(r->pool, base);
  +    string_pos = my_base;
  +    while (*string_pos) {
  +        if (*string_pos == '/' && *(string_pos + 1) == '/') {
  +            string_pos += 2;    /* if there are two slashes, jump over them */
  +            continue;
  +        }
  +        if (*string_pos == '/') {       /* the first single slash */
  +            if (value[0] == '/') {
  +                *string_pos = '\0';
  +            }                   /* if the URL from the map starts from root, end the
  +                                   base URL string at the first single slash */
  +            else {
  +                directory = string_pos;         /* save the start of the directory portion */
  +
  +                string_pos = strrchr(string_pos, '/');  /* now reuse string_pos */
  +                string_pos++;   /* step over that last slash */
  +                *string_pos = '\0';
  +            }                   /* but if the map url is relative, leave the
  +                                   slash on the base (if there is one) */
  +            break;
  +        }
  +        string_pos++;           /* until we get to the end of my_base without finding
  +                                   a slash by itself */
  +    }
  +
  +    while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
  +
  +        if (directory && (slen = strlen(directory))) {
  +
  +            /* for each '..',  knock a directory off the end 
  +               by ending the string right at the last slash.
  +               But only consider the directory portion: don't eat
  +               into the server name.  And only try if a directory
  +               portion was found */
  +
  +            clen = slen - 1;
  +
  +            while ((slen - clen) == 1) {
  +
  +                if ((string_pos = strrchr(directory, '/')))
  +                    *string_pos = '\0';
  +                clen = strlen(directory);
  +                if (clen == 0)
  +                    break;
  +            }
  +
  +            value += 2;         /* jump over the '..' that we found in the value */
  +        }
  +        else if (directory) {
  +            log_reason("invalid directory name in map file: %s", r->uri, r);
  +            return NULL;
  +        }
  +
  +        if (!strncmp(value, "/../", 4) || !strcmp(value, "/.."))
  +            value++;            /* step over the '/' if there are more '..' to do.
  +                                   this way, we leave the starting '/' on value after
  +                                   the last '..', but get rid of it otherwise */
  +
  +    }                           /* by this point, value does not start with '..' */
  +
  +    if (value && *value) {
  +	return pstrcat(r->pool, my_base, value, NULL);
  +    }
  +    return my_base;
  +}
  +
  +static int imap_reply(request_rec *r, char *redirect)
  +{
  +    if (!strcasecmp(redirect, "error")) {
  +        return SERVER_ERROR;    /* they actually requested an error! */
  +    }
  +    if (!strcasecmp(redirect, "nocontent")) {
  +        return HTTP_NO_CONTENT; /* tell the client to keep the page it has */
  +    }
  +    if (redirect && *redirect) {
  +        table_set(r->headers_out, "Location", redirect);
  +        return REDIRECT;        /* must be a URL, so redirect to it */
  +    }
  +    return SERVER_ERROR;
  +}
  +
  +static void menu_header(request_rec *r, char *menu)
  +{
  +    r->content_type = "text/html";
  +    send_http_header(r);
  +    hard_timeout("send menu", r);       /* killed in menu_footer */
  +
  +    rvputs(r, "<html><head>\n<title>Menu for ", r->uri,
  +           "</title>\n</head><body>\n", NULL);
  +
  +    if (!strcasecmp(menu, "formatted")) {
  +        rvputs(r, "<h1>Menu for ", r->uri, "</h1>\n<hr>\n\n", NULL);
       }
  -    else {
  -      ap_snprintf(url, SMALLBUF, "http://%s:%d%s", r->server->server_hostname,
  -	      r->server->port, r->uri);      
  +
  +    return;
  +}
  +
  +static void menu_blank(request_rec *r, char *menu)
  +{
  +    if (!strcasecmp(menu, "formatted")) {
  +        rputs("\n", r);
  +    }
  +    if (!strcasecmp(menu, "semiformatted")) {
  +        rputs("<br>\n", r);
  +    }
  +    if (!strcasecmp(menu, "unformatted")) {
  +        rputs("\n", r);
  +    }
  +    return;
  +}
  +
  +static void menu_comment(request_rec *r, char *menu, char *comment)
  +{
  +    if (!strcasecmp(menu, "formatted")) {
  +        rputs("\n", r);         /* print just a newline if 'formatted' */
  +    }
  +    if (!strcasecmp(menu, "semiformatted") && *comment) {
  +        rvputs(r, comment, "\n", NULL);
  +    }
  +    if (!strcasecmp(menu, "unformatted") && *comment) {
  +        rvputs(r, comment, "\n", NULL);
       }
  -    return;  
  -  }
  +    return;                     /* comments are ignored in the 'formatted' form */
  +}
   
  -  if ( ! strcasecmp(value, "nocontent") || ! strcasecmp(value, "error") ) {
  -    strncpy(url, value, SMALLBUF-1);
  -    url[SMALLBUF-1] = '\0';
  -    return;    /* these are handled elsewhere, so just copy them */
  -  }
  -
  -  if ( ! strcasecmp(value, "referer" ) ) {
  -    referer = table_get(r->headers_in, "Referer");
  -    if ( referer && *referer ) {
  -      strncpy(url, referer, SMALLBUF-1);
  -      url[SMALLBUF-1] = '\0';
  -      return;
  +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'te really href's */
  +    }
  +    if (!strcasecmp(menu, "formatted")) {
  +        rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "semiformatted")) {
  +        rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "unformatted")) {
  +        rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
       }
  -    else {
  -      *value = '\0';  /* if 'referer' but no referring page, null the value */
  -    }                 
  -  }         
  -
  -  string_pos = value;
  -  while ( isalpha(*string_pos) )
  -    string_pos++;    /* go along the URL from the map until a non-letter */
  -  if ( *string_pos == ':' ) { 
  -    strncpy(url, value, SMALLBUF-1);        /* if letters and then a colon (like http:) */
  -    url[SMALLBUF-1] = '\0';
  -    return;                    /* it's an absolute URL, so use it! */
  -  }
  -
  -  if ( ! base || ! *base ) {
  -    if ( value && *value ) {  
  -      strncpy(url, value, SMALLBUF-1);   /* no base: use what is given */
  -      url[SMALLBUF-1] = '\0';
  -    }         
  -    else {                  
  -      if (r->server->port == DEFAULT_PORT ) {  
  -	ap_snprintf(url, SMALLBUF, "http://%s/", r->server->server_hostname);
  -      }            
  -      if (r->server->port != DEFAULT_PORT ) {
  -	ap_snprintf(url, SMALLBUF, "http://%s:%d/",
  -		r->server->server_hostname, r->server->port);
  -      }                     /* no base, no value: pick a simple default */
  -    }
  -    return;  
  -  }
  -
  -  strncpy(my_base, base, sizeof(my_base)-1);  /* must be a relative URL to be combined with base */
  -  my_base[sizeof(my_base)-1] = '\0';
  -  if (strchr(my_base, '/') == NULL && (!strncmp(value, "../", 3) || !strcmp(value, "..")) ) {
  -    url[0] = '\0';
  -    log_reason("invalid base directive in map file", r->uri, r);
       return;
  -  }
  -  string_pos = my_base; 
  -  while (*string_pos) {  
  -    if (*string_pos == '/' && *(string_pos+1) == '/') {
  -      string_pos += 2;  /* if there are two slashes, jump over them */
  -      continue;
  -    }
  -    if (*string_pos == '/') {  /* the first single slash */
  -	if ( value[0] == '/' ) {
  -	  *string_pos = '\0';  
  -	}              /* if the URL from the map starts from root, end the
  -			  base URL string at the first single slash */
  -	else {
  -	  directory = string_pos; /* save the start of the directory portion */
  +}
  +
  +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")) {
  +        rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "semiformatted")) {
  +        rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "unformatted")) {
  +        rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
  +    }
  +    return;
  +}
  +
  +static void menu_footer(request_rec *r)
  +{
  +    rputs("\n\n</body>\n</html>\n", r);         /* finish the menu */
  +    kill_timeout(r);
  +}
   
  -	  string_pos = strrchr(string_pos, '/');  /* now reuse string_pos */
  -	  string_pos++;  /* step over that last slash */
  -	  *string_pos = '\0';
  -	}              /* but if the map url is relative, leave the
  -			slash on the base (if there is one) */
  -	break;
  -      }
  -    string_pos++;   /* until we get to the end of my_base without finding
  -		       a slash by itself */
  -  }
  -
  -  while ( ! strncmp(value, "../", 3) || ! strcmp(value, "..") ) { 
  -
  -      if (directory && (slen = strlen (directory))) {
  -
  -	  /* for each '..',  knock a directory off the end 
  -	     by ending the string right at the last slash.
  -	     But only consider the directory portion: don't eat
  -	     into the server name.  And only try if a directory
  -	     portion was found */    
  -	  
  -	  clen = slen - 1;
  -	
  -	  while ((slen - clen) == 1) {
  -	
  -	      if ((string_pos = strrchr(directory, '/')))
  -		  *string_pos = '\0';
  -	      clen = strlen (directory);
  -	      if (clen == 0) break;
  -	  }
  -
  -	  value += 2;      /* jump over the '..' that we found in the value */
  -      } else if (directory) {
  -	url[0] = '\0';
  -	log_reason("invalid directory name in map file", r->uri, r);
  -	return;
  -      }
  -      
  -      if (! strncmp(value, "/../", 4) || ! strcmp(value, "/..") )
  -
  -	  value++;       /* step over the '/' if there are more '..' to do.
  -			   this way, we leave the starting '/' on value after
  -			   the last '..', but get rid of it otherwise */ 
  -     
  -  }                   /* by this point, value does not start with '..' */
  -
  -  if ( value && *value ) {
  -    ap_snprintf(url, SMALLBUF, "%s%s", my_base, value);   
  -  }
  -  else {
  -    ap_snprintf(url, SMALLBUF, "%s", my_base);   
  -  }
  -  return;
  -}
  -
  -int imap_reply(request_rec *r, char *redirect)
  -{ 
  -  if ( ! strcasecmp(redirect, "error") ) {
  -    return SERVER_ERROR;  /* they actually requested an error! */
  -  }
  -  if ( ! strcasecmp(redirect, "nocontent") ) {
  -    return HTTP_NO_CONTENT; /* tell the client to keep the page it has */
  -  }
  -  if (redirect && *redirect ) { 
  -    table_set(r->headers_out, "Location", redirect);
  -    return REDIRECT;      /* must be a URL, so redirect to it */
  -  }    
  -  return SERVER_ERROR;
  -}
  -
  -void menu_header(request_rec *r, char *menu)
  -{
  -  r->content_type = "text/html";
  -  send_http_header(r);
  -  hard_timeout("send menu", r);   /* killed in menu_footer */
  -
  -  rvputs(r, "<html><head>\n<title>Menu for ", r->uri,
  -	    "</title>\n</head><body>\n", NULL);
  -
  -  if (!strcasecmp(menu, "formatted")) {
  -    rvputs(r, "<h1>Menu for ", r->uri, "</h1>\n<hr>\n\n", NULL);
  -  } 
  -
  -  return;
  -}
  -
  -void menu_blank(request_rec *r, char *menu)
  -{
  -  if (! strcasecmp(menu, "formatted") ) {
  -    rputs("\n", r);
  -  }
  -  if (! strcasecmp(menu, "semiformatted") ) {
  -    rputs("<br>\n", r);
  -  }
  -  if (! strcasecmp(menu, "unformatted") ) {
  -    rputs("\n", r);  
  -  }
  -  return;  
  -}
  -
  -void menu_comment(request_rec *r, char *menu, char *comment)
  -{
  -  if (! strcasecmp(menu, "formatted") ) {
  -    rputs("\n", r);  /* print just a newline if 'formatted' */
  -  }
  -  if (! strcasecmp(menu, "semiformatted") && *comment ) {
  -    rvputs(r, comment, "\n", NULL);
  -  }             
  -  if (! strcasecmp(menu, "unformatted") && *comment ) {
  -    rvputs(r, comment, "\n", NULL);
  -  }             
  -  return;    /* comments are ignored in the 'formatted' form */
  -}
  -
  -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'te really href's */
  -  }
  -  if ( ! strcasecmp(menu, "formatted" ) ) {
  -    rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "semiformatted" ) ) {
  -    rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "unformatted" ) ) {
  -    rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
  -  }
  -  return;
  -}
  -
  -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" ) ) {
  -    rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "semiformatted" ) ) {
  -    rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "unformatted" ) ) {
  -    rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
  -  }
  -  return;
  -}
  -
  -void menu_footer(request_rec *r)
  -{
  -  rputs("\n\n</body>\n</html>\n", r);  /* finish the menu */
  -  kill_timeout(r);
  -}
  -
  -int imap_handler(request_rec *r)
  -{
  -  char input[LARGEBUF] = {'\0'};
  -	/* size of input can not be lowered without changing hard-coded
  -	 * checks
  +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 = 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;
  +
  +    FILE *imap; 
  +
  +    if (r->method_number != M_GET)
  +	return DECLINED;
  +
  +    imap = pfopen(r->pool, r->filename, "r"); 
  +
  +    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 (!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
  +	 * cfg_getline has removed leading/trailing whitespace and
  +	 * compressed the other whitespace down to one space a piece
  +	 *
  +	 * note that we're tokenizing as we go... if we were to use the
  +	 * getword() class of functions we would end up allocating extra
  +	 * memory for every line of the map file
   	 */
  -  char href_text[SMALLBUF] = {'\0'};
  -  char base[SMALLBUF] = {'\0'};
  -  char redirect[SMALLBUF] = {'\0'};
  -  char directive[SMALLBUF] = {'\0'};
  -  char value[SMALLBUF] = {'\0'};
  -  char mapdflt[SMALLBUF] = {'\0'};
  -  char closest[SMALLBUF] = {'\0'};
  -  double closest_yet = -1;
  -
  -  double testpoint[2] = { -1,-1 }; 
  -  double pointarray[MAXVERTS + 1][2] = { {-1,-1} };
  -  int vertex = 0;
  -
  -  char *string_pos = NULL;
  -  int chars_read = 0;
  -  int showmenu = 0;
  -
  -  imap_conf_rec *icr = 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;
  -
  -  FILE *imap; 
  -
  -  if (r->method_number != M_GET) return DECLINED;
  -
  -  imap = pfopen(r->pool, r->filename, "r"); 
  -
  -  if ( ! imap ) 
  -    return NOT_FOUND;
  -
  -  imap_url(r, NULL, imap_base, base);       /* set base according to default */
  -  imap_url(r, NULL, imap_default, mapdflt); /* and default to global default */
  -
  -  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 (!cfg_getline(input, LARGEBUF, imap)) {
  -    string_pos = input;   /* always start at the beginning of line */
  -
  -    directive[0] = '\0';
  -    value[0] = '\0';  
  -    href_text[0] = '\0';
  -    redirect[0] = '\0';
  -    chars_read = 0; /* clear these before using */
  -
  -    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 */
  -
  -
  -    if (sscanf(input, "%255s %255s", directive, value) != 2) {
  -      continue;                           /* make sure we read two fields */
  -    }
  -    /* Now skip what we just read... we can't use ANSIism %n */
  -    while (!(isspace(*string_pos)))	/* past directive */
  -	string_pos++;
  -    while (isspace(*string_pos))	/* and whitespace */
  -	string_pos++;
  -    while (!(isspace(*string_pos)))	/* and value... have to watch it */
  -	string_pos++;			/* can have punctuation and stuff */
  -    
  -    if ( ! strncasecmp(directive, "base", 4 ) ) {       /* base, base_uri */
  -      imap_url(r, NULL, value, base);
  -      continue; /* base is never printed to a menu */
  -    }	
  -
  -    chars_read = read_quoted(string_pos, href_text);
  -    string_pos += chars_read;      /* read the quoted href text if present */
  -
  -    if ( ! strcasecmp(directive, "default" ) ) {        /* default */
  -      imap_url(r, NULL, value, mapdflt);
  -      if (showmenu) {              /* print the default if there's a menu */
  -	if (! *href_text) {           /* if we didn't find a "href text" */
  -	  strncpy(href_text, mapdflt, sizeof(href_text)-1); /* use the href itself as text */
  -	  href_text[sizeof(href_text)-1] = '\0';
  +        string_pos = input;
  +	if (!*string_pos)		/* need at least two fields */
  +	    goto need_2_fields;
  +
  +	directive = string_pos;
  +	while (*string_pos && *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;
  +	value = string_pos;
  +	while (*string_pos && *string_pos != ' ')	/* past value */
  +	    ++string_pos;
  +	if (*string_pos == ' ') {
  +	    *string_pos++ = '\0';
  +	}
  +	else {
  +	    /* end of input, don't advance past it */
  +	    *string_pos = '\0';
   	}
  -	imap_url(r, base, mapdflt, redirect); 
  -	menu_default(r, imap_menu, redirect, href_text);
  -      }
  -      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(isspace(*string_pos))	/* past whitespace */
  -	    string_pos++;
  -	while(isdigit(*string_pos))	/* and the 1st number */
  -	    string_pos++;
  -	string_pos++;			/* skip the ',' */
  -	while(isspace(*string_pos))	/* past any more whitespace */
  -	    string_pos++;
  -	while(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 (!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 (isspace(*string_pos))        /* past whitespace */
  +                string_pos++;
  +            while (isdigit(*string_pos))        /* and the 1st number */
  +                string_pos++;
  +            string_pos++;       /* skip the ',' */
  +            while (isspace(*string_pos))        /* past any more whitespace */
  +                string_pos++;
  +            while (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)) {
  +		pfclose(r->pool, 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)) {
  +		pfclose(r->pool, 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)) {
  +		pfclose(r->pool, 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 = pstrdup(r->pool, value);
  +            }
  +
  +            continue;
  +        }                       /* move on to next line whether it's closest or not */
  +
  +    }                           /* nothing matched, so we get another line! */
  +
  +    pfclose(r->pool, imap);     /* we are done with the map file, so 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 SERVER_ERROR;        /* If we make it this far, we failed. They lose! */
  +
  +need_2_fields:
  +    log_reason("all map file lines require at least two fields", r->uri, r);
  +    /* fall through */
  +menu_bail:
  +    pfclose(r->pool, imap);
       if (showmenu) {
  -      read_quoted(string_pos, href_text); /* href text could be here instead */
  -      if (! *href_text) {           /* if we didn't find a "href text" */
  -	strncpy(href_text, value, sizeof(href_text)-1);  /* use the href itself in the menu */
  -	href_text[sizeof(href_text)-1] = '\0';
  -      }
  -      imap_url(r, base, value, redirect); 
  -      menu_directive(r, imap_menu, redirect, href_text);
  -      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) ) {
  -	pfclose(r->pool, imap); 
  -	imap_url(r, base, value, redirect);     
  -	return (imap_reply(r, redirect));
  -      }
  -      continue;
  -    }
  -
  -    if ( ! strcasecmp(directive, "circle" ) ) {        /* circle */
  -	
  -      if (pointincircle (testpoint, pointarray) ) {
  -	pfclose(r->pool, imap); 
  -	imap_url(r, base, value, redirect);     
  -	return (imap_reply(r, redirect));
  -      }
  -      continue;
  -    }
  -    
  -    if ( ! strcasecmp(directive, "rect" ) ) {        /* rect */
  -      
  -      if (pointinrect (testpoint, pointarray) ) {
  -	pfclose(r->pool, imap); 
  -	imap_url(r, base, value, redirect);     
  -	return (imap_reply(r, redirect));
  -      }
  -      continue;
  -    }
  -    
  -    if ( ! strcasecmp(directive, "point" ) ) {         /* point */
  -      
  -      if (is_closer(testpoint, pointarray, &closest_yet) ) {
  -	strncpy(closest, value, sizeof(closest)-1);  /* if the closest point yet save it */
  -	closest[sizeof(closest)-1] = '\0';
  -      }
  -      
  -      continue;    
  -    }     /* move on to next line whether it's closest or not */
  -    
  -  }       /* nothing matched, so we get another line! */
  -
  -  pfclose(r->pool, imap);   /* we are done with the map file, so 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 */
  -    imap_url(r, base, closest, redirect);     
  -    return (imap_reply(r, redirect));
  -  }    
  -
  -  if (*mapdflt ) {   /* a default should be defined, even if only 'nocontent'*/
  -    imap_url(r, base, mapdflt, redirect);
  -    return(imap_reply(r, redirect));
  -  }    
  -
  -  return SERVER_ERROR;   /* If we make it this far, we failed. They lose! */
  -}
  -
  -
  -handler_rec imap_handlers[] = {
  -{ IMAP_MAGIC_TYPE, imap_handler },
  -{ "imap-file", imap_handler },
  -{ NULL }
  +	/* There's not much else we can do ... we've already sent the headers
  +	 * to the client.
  +	 */
  +	rputs("\n\n[an internal server error occured]\n", r);
  +	menu_footer(r);
  +	return OK;
  +    }
  +    return HTTP_INTERNAL_SERVER_ERROR;
  +}
  +
  +
  +static handler_rec imap_handlers[] =
  +{
  +    {IMAP_MAGIC_TYPE, imap_handler},
  +    {"imap-file", imap_handler},
  +    {NULL}
   };
   
  -module imap_module = {
  -   STANDARD_MODULE_STUFF,
  -   NULL,			/* initializer */
  -   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,			/* filename translation */
  -   NULL,			/* check_user_id */
  -   NULL,			/* check auth */
  -   NULL,			/* check access */
  -   NULL,			/* type_checker */
  -   NULL,			/* fixups */
  -   NULL,			/* logger */
  -   NULL				/* header parser */
  +module imap_module =
  +{
  +    STANDARD_MODULE_STUFF,
  +    NULL,                       /* initializer */
  +    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,                       /* filename translation */
  +    NULL,                       /* check_user_id */
  +    NULL,                       /* check auth */
  +    NULL,                       /* check access */
  +    NULL,                       /* type_checker */
  +    NULL,                       /* fixups */
  +    NULL,                       /* logger */
  +    NULL                        /* header parser */
   };
  
  
  

Mime
View raw message