home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / linux / apache / contrib / modules / probably_obsolete / mod_imap_new.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  15.4 KB  |  535 lines

  1.  
  2. /*-
  3.  * Copyright (c) 1995 The Apache Group. All rights reserved.
  4.  * 
  5.  *
  6.  * Apache httpd license
  7.  * ====================
  8.  * 
  9.  *
  10.  * This is the license for the Apache Server. It covers all the
  11.  * files which come in this distribution, and should never be removed.
  12.  * 
  13.  * The "Apache Group" has based this server, called "Apache", on
  14.  * public domain code distributed under the name "NCSA httpd 1.3".
  15.  * 
  16.  * NCSA httpd 1.3 was placed in the public domain by the National Center 
  17.  * for Supercomputing Applications at the University of Illinois 
  18.  * at Urbana-Champaign.
  19.  * 
  20.  * As requested by NCSA we acknowledge,
  21.  * 
  22.  *  "Portions developed at the National Center for Supercomputing
  23.  *   Applications at the University of Illinois at Urbana-Champaign."
  24.  *
  25.  * Copyright on the sections of code added by the "Apache Group" belong
  26.  * to the "Apache Group" and/or the original authors. The "Apache Group" and
  27.  * authors hereby grant permission for their code, along with the
  28.  * public domain NCSA code, to be distributed under the "Apache" name.
  29.  * 
  30.  * Reuse of "Apache Group" code outside of the Apache distribution should
  31.  * be acknowledged with the following quoted text, to be included with any new
  32.  * work;
  33.  * 
  34.  * "Portions developed by the "Apache Group", taken with permission 
  35.  *  from the Apache Server   http://www.apache.org/apache/   "
  36.  *
  37.  *
  38.  * Permission is hereby granted to anyone to redistribute Apache under
  39.  * the "Apache" name. We do not grant permission for the resale of Apache, but
  40.  * we do grant permission for vendors to bundle Apache free with other software,
  41.  * or to charge a reasonable price for redistribution, provided it is made
  42.  * clear that Apache is free. Permission is also granted for vendors to 
  43.  * sell support for Apache. We explicitly forbid the redistribution of 
  44.  * Apache under any other name.
  45.  * 
  46.  * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
  47.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  48.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  49.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
  50.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  51.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  52.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  53.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  54.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  55.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  56.  * SUCH DAMAGE.
  57.  * 
  58.  */
  59.  
  60. /*
  61.  * This imagemap module started as a port of the original imagemap.c
  62.  * written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu).
  63.  * This version includes the mapping algorithms found in version 1.3
  64.  * of imagemap.c.
  65.  *
  66.  * Contributors to this code include:
  67.  *
  68.  * Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
  69.  *
  70.  * Eric Haines, erich@eye.com
  71.  * "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
  72.  *
  73.  * Randy Terbush, randy@zyzzyva.com
  74.  * port to Apache module format, "base_uri" and support for relative URLs
  75.  * 
  76.  * James H. Cloos, Jr., cloos@jhcloos.com
  77.  * Added point datatype, using code in NCSA's version 1.8 imagemap.c
  78.  * program, as distributed with version 1.4.1 of their server.
  79.  * The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu
  80.  *
  81.  * Nathan Kurz, nate@tripod.com
  82.  * Partial rewrite/reorginazation to be generally more forgiving.
  83.  * main changes:  uses 'default' if no coordinates given (Lynx).
  84.  *                ignores bad lines in map file instead of server error.
  85.  *                bug in uri_base handling that sometimes caused relative
  86.  *              urls in Location fixed; more schemes checked for.
  87.  *          'point' directive mixes better with 'default' directive.
  88.  */
  89.  
  90. #include "httpd.h"
  91. #include "http_config.h"
  92. #include "http_request.h"
  93. #include "http_core.h"
  94. #include "http_protocol.h"
  95. #include "http_main.h"
  96. #include "http_log.h"
  97. #include "util_script.h"
  98.  
  99.  
  100. #define IMAP_MAGIC_TYPE "application/x-httpd-imap"
  101. #define MAXLINE 500
  102. #define MAXVERTS 100
  103. #define X 0
  104. #define Y 1
  105.  
  106. char *getline(char *, int, FILE *);
  107. double strtod();   /* SunOS needed this */
  108.  
  109. module imap_module;
  110.  
  111. int pointinrect(double point[2], double coords[MAXVERTS][2])
  112. {
  113.     return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
  114.         (point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
  115. }
  116.  
  117. int pointincircle(double point[2], double coords[MAXVERTS][2])
  118. {
  119.     int radius1, radius2;
  120.  
  121.     radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
  122.     + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
  123.     
  124.     radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
  125.     + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  126.  
  127.     return (radius2 <= radius1);
  128. }
  129.  
  130. int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  131. {
  132.     int i, numverts, inside_flag, xflag0;
  133.     int crossings;
  134.     double *p, *stop;
  135.     double tx, ty, y;
  136.  
  137.     for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++);
  138.  
  139.     numverts = i;
  140.     crossings = 0;
  141.  
  142.     tx = point[X];
  143.     ty = point[Y];
  144.     y = pgon[numverts - 1][Y];
  145.  
  146.     p = (double *) pgon + 1;
  147.     if ((y >= ty) != (*p >= ty)) {
  148.  
  149.     if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx)) {
  150.         if (xflag0)
  151.         crossings++;
  152.     }
  153.     else {
  154.         crossings += (pgon[numverts - 1][X] - (y - ty) *
  155.               (*(double *) pgon - pgon[numverts - 1][X]) /
  156.               (*p - y)) >= tx;
  157.     }
  158.     }
  159.  
  160.     stop = pgon[numverts];
  161.  
  162.     for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  163.     
  164.     if (y >= ty) {
  165.         
  166.         while ((p < stop) && (*p >= ty))
  167.         p += 2;
  168.         
  169.         if (p >= stop)
  170.         break;
  171.         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  172.         
  173.         if (xflag0)
  174.             crossings++;
  175.         }
  176.         else {
  177.         crossings += (*(p - 3) - (*(p - 2) - ty) *
  178.                   (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  179.         }
  180.     }
  181.     else {
  182.         while ((p < stop) && (*p < ty))
  183.         p += 2;
  184.  
  185.         if (p >= stop)
  186.         break;
  187.  
  188.         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  189.         if (xflag0)
  190.             crossings++;
  191.         }
  192.         else {
  193.         crossings += (*(p - 3) - (*(p - 2) - ty) *
  194.                   (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  195.         }
  196.     }
  197.     }
  198.  
  199.     inside_flag = crossings & 0x01;
  200.     return (inside_flag);
  201. }
  202.  
  203.  
  204. int is_closer(double point[2], double coords[MAXVERTS][2], double *closest)
  205. {
  206.   double dist_squared =((point[X] - coords[0][X]) * (point[X] - coords[0][X]))
  207.          + ((point[Y] - coords[0][Y]) * (point[Y] - coords[0][Y]));
  208.  
  209.   if (point[X] < 0 || point[Y] < 0 ) 
  210.     return(0);          /* don't mess around with negative coordinates */
  211.  
  212.   if ( *closest < 0 || dist_squared < *closest ) {
  213.     *closest = dist_squared;
  214.     return(1);         /* if this is the first point or is the closest yet
  215.               set 'closest' equal to this distance^2 */
  216.   }
  217.   
  218.   return(0);           /* if it's not the first or closest */
  219.  
  220. }
  221.  
  222. double get_x_coord(char *args) 
  223. {
  224.   char *endptr = NULL;
  225.   double x_coord = -1;    /* -1 is returned if no coordinate is given */
  226.  
  227.   if (args == NULL)
  228.     return(-1);           /* in case we aren't passed anything */
  229.  
  230.   while( *args && !isdigit(*args) && *args != ',') 
  231.     args++;   /* jump to the first digit, but not past a comma or end */
  232.  
  233.   x_coord = strtod(args, &endptr);
  234.  
  235.   if (endptr > args)   /* if a conversion was made */
  236.     return(x_coord); 
  237.  
  238.   return(-1);  /* else if no conversion was made, or if no args was given */
  239. }
  240.  
  241. double get_y_coord(char *args) 
  242. {
  243.   char *endptr = NULL;
  244.   char *start_of_y = NULL;
  245.   double y_coord = -1;    /* -1 is returned on error */
  246.  
  247.   if (args == NULL)
  248.     return(-1);           /* in case we aren't passed anything */
  249.  
  250.   start_of_y = strchr(args, ',');  /* the comma */
  251.  
  252.   if (start_of_y) {
  253.     
  254.     start_of_y++;    /* start looking at the character after the comma */
  255.  
  256.     while( *start_of_y && !isdigit(*start_of_y))  
  257.       start_of_y++;  /* jump to the first digit, but not past the end */
  258.  
  259.     y_coord = strtod(start_of_y, &endptr);
  260.  
  261.     if (endptr > start_of_y) 
  262.       return(y_coord); 
  263.   }
  264.   
  265.   return(-1);   /* if no conversion was made, or no comma was found in args */
  266. }
  267.   
  268.  
  269. void set_redirect(request_rec *r, char *base_uri, char *mapurl) 
  270. {
  271.   char redirect[MAXLINE] = {'\0'};
  272.   char *string_pos      = base_uri;
  273.   char *directory       = NULL;
  274.  
  275.   if (
  276.       (!strncmp(mapurl, "http:", 5))   ||
  277.       (!strncmp(mapurl, "mailto:", 7)) ||
  278.       (!strncmp(mapurl, "news:", 5))   ||
  279.       (!strncmp(mapurl, "ftp:", 4))    ||
  280.       (!strncmp(mapurl, "gopher:", 7)) ||
  281.       (!strncmp(mapurl, "nntp:", 5))       ) {
  282.  
  283.     table_set(r->headers_out, "Location", mapurl);
  284.     return;                    /* if they give us an absolute URL, use it! */
  285.   }
  286.  
  287.   while (*string_pos) {   /* starts out the same as base_uri */
  288.  
  289.     if (*string_pos == '/' && *(string_pos+1) == '/') {
  290.       string_pos += 2;  /* if there are two slashes, jump over them */
  291.       continue;
  292.     }
  293.  
  294.     if (*string_pos == '/') {  /* the first single slash */
  295.     if ( mapurl[0] == '/' ) {
  296.       *string_pos = '\0';  
  297.     }              /* if the URL from the map starts from root, end the
  298.               base URL string at the first single slash */
  299.     else {
  300.       directory = string_pos; /* save the start of the directory portion */
  301.  
  302.       string_pos = strrchr(string_pos, '/');  /* now reuse string_pos */
  303.       string_pos++;  /* step over that last slash */
  304.       *string_pos = '\0';
  305.     }              /* otherwise make sure we are dealing with a directory
  306.               instead of a file */
  307.     break;
  308.       }
  309.     
  310.     string_pos++;   /* until we get to the end of base_uri without finding
  311.                a slash by itself */
  312.   }
  313.                     /* by this point, base_uri never ends with a slash.
  314.                it has to come from mapurl if there's to be one. */
  315.  
  316.   while ( ! strncmp(mapurl, "../", 3) || ! strcmp(mapurl, "..") ) { 
  317.                        /* handle relative mapurl's from the map file */
  318.  
  319.     if ( directory && (string_pos = strrchr(directory, '/')) ) 
  320.       *string_pos = '\0';
  321.                        /* for each '..',  knock a directory off the end 
  322.                by ending the string right at the last slash.
  323.                But only consider the directory portion: don't eat
  324.                into the server name.  And only try if a directory
  325.                portion was found */    
  326.  
  327.     mapurl += 2;      /* jump over the '..' that we found in the mapurl */
  328.       
  329.     if (! strncmp(mapurl, "/../", 4) || ! strcmp(mapurl, "/..") )
  330.                       /* check for both so a file ..foo still works */
  331.  
  332.       mapurl++;       /* step over the '/' if there are more '..' to do.
  333.                this way, we leave the starting '/' on mapurl after
  334.                the last '..', but get rid of it otherwise */ 
  335.      
  336.   }                   /* by this point, mapurl does not start with '..' */
  337.  
  338.                          
  339.   sprintf(redirect, "%s%s", base_uri, mapurl);   
  340.  
  341.   table_set(r->headers_out, "Location", redirect);
  342.  
  343.   return;
  344.  
  345. }
  346.  
  347.  
  348.  
  349. int imap_handler(request_rec *r)
  350. {
  351.   char base_uri[MAXLINE] = {'\0'};
  352.   char input[MAXLINE] = {'\0'};
  353.   char maptype[MAXLINE] = {'\0'};
  354.   char mapurl[MAXLINE] = {'\0'};
  355.   char mapdflt[MAXLINE] = {'\0'};
  356.   char mapclosest[MAXLINE] = {'\0'};
  357.   double closest = -1;
  358.  
  359.   double testpoint[2];
  360.   double pointarray[MAXVERTS][2] = { {-1,-1} };
  361.   int vertex = 0;
  362.  
  363.   char *referer = table_get(r->headers_in, "Referer");
  364.  
  365.   char *string_pos = NULL;
  366.   int chars_read = 0;
  367.  
  368.   FILE *imap;
  369.   
  370.   if (! (imap = fopen(r->filename, "r"))) 
  371.     return SERVER_ERROR;
  372.  
  373.   if (r->server->port == 80 ) 
  374.     sprintf(base_uri, "http://%s", r->server->server_hostname);
  375.   else
  376.     sprintf(base_uri, "http://%s:%d", r->server->server_hostname,
  377.         r->server->port);
  378.                            /* base_uri starts as http://server_hostname,
  379.                   can later be changed by lines in map file */
  380.  
  381.   testpoint[X] = get_x_coord(r->args);
  382.   testpoint[Y] = get_y_coord(r->args);
  383.  
  384.   while (getline(input, MAXLINE, imap)) {
  385.  
  386.     if ( input[0] == '#' ||  ! input[0] )
  387.       continue;            /* ignore comments and blank lines */
  388.  
  389.     string_pos = input;   /* always start at the beginning of line */
  390.  
  391.     bzero(maptype, MAXLINE);
  392.     bzero(mapurl, MAXLINE);  /* clear these just to be safe */
  393.  
  394.     sscanf(input, "%s %s %n", maptype, mapurl, &chars_read);
  395.     string_pos += chars_read;
  396.     
  397.     if ( ! strcmp(maptype, "base_uri")  ) {         /* base_uri */
  398.  
  399.       if      ( ! strcmp(mapurl, "map") ) 
  400.     strcpy(base_uri, r->uri);  /* use the map as the base */
  401.  
  402.       else if ( ! strcmp(mapurl, "referer") )
  403.     if (referer)
  404.       strcpy(base_uri, referer); /* use the refering page as base */
  405.       /* if there is no refering page, the base is left as http://servername */
  406.  
  407.       else
  408.     strcpy(base_uri, mapurl);  /* use what we are given as base */
  409.  
  410.       continue;
  411.     }    
  412.  
  413.     if ( ! strcmp(maptype, "default")   ) {        /* default */
  414.  
  415.       strcpy(mapdflt, mapurl);     /* use what is given as the default */
  416.       
  417.       continue;
  418.     }
  419.     
  420.     if ( testpoint[X] < 0 || testpoint[Y] < 0 ) { /* no coordinates */
  421.  
  422.       /* if we don't have valid test coordinates,
  423.      don't bother trying any of the tests that 
  424.      follow (point, rect, poly, etc) */
  425.       continue;
  426.     }
  427.  
  428.     vertex = 0;
  429.     while ( vertex < MAXVERTS &&  
  430.        sscanf(string_pos, "%lf,%lf %n", &pointarray[vertex][X], 
  431.           &pointarray[vertex][Y], &chars_read)   == 2) {
  432.       string_pos += chars_read;
  433.       vertex++;
  434.     }                /* so long as there are more vertices to read, and
  435.             we have room, read them in.  We start where we left
  436.             off of the last sscanf, not at the beginning.*/
  437.                   
  438.     pointarray[vertex][X] = -1;  /* signals the end of vertices */
  439.  
  440.     
  441.     if ( ! strcmp(maptype, "poly")   ) {        /* poly */
  442.  
  443.       if (pointinpoly (testpoint, pointarray) ) {
  444.     set_redirect(r, base_uri, mapurl);     
  445.     fclose(imap);
  446.     return REDIRECT;
  447.  
  448.       }
  449.     }
  450.  
  451.     if ( ! strcmp(maptype, "circle")   ) {        /* circle */
  452.  
  453.       if (pointincircle (testpoint, pointarray) ) {
  454.     set_redirect(r, base_uri, mapurl);     
  455.     fclose(imap);
  456.     return REDIRECT;
  457.  
  458.       }
  459.     }
  460.  
  461.     if ( ! strcmp(maptype, "rect")   ) {        /* rect */
  462.  
  463.       if (pointinrect (testpoint, pointarray) ) {
  464.     set_redirect(r, base_uri, mapurl);     
  465.     fclose(imap);
  466.     return REDIRECT;
  467.  
  468.       }
  469.     }
  470.     
  471.     if ( ! strcmp(maptype, "point") ) {         /* point */
  472.       
  473.       if (is_closer(testpoint, pointarray, &closest) ) 
  474.     strcpy(mapclosest, mapurl);  /* if the closest point yet save it */
  475.  
  476.       continue;    
  477.     }     /* move on to next line whether it's closest or not */
  478.  
  479.           /* nothing matched, so we get another line! */
  480.   }       /* (I wonder if that should be logged as an error?) */
  481.         
  482.  
  483.   fclose(imap);         /* we won't be needing the map file anymore */
  484.   
  485.   if (*mapclosest) {    /* if a 'point' directive has been seen */
  486.     set_redirect(r, base_uri, mapclosest);     
  487.     fclose(imap);       /* redirect to the closest point found */
  488.     return REDIRECT;
  489.   }    
  490.  
  491.   if (*mapdflt) {       /* if a default has been assigned */
  492.     set_redirect(r, base_uri, mapdflt);
  493.     fclose(imap);       /* redirect to that default */
  494.     return REDIRECT;
  495.   }    
  496.  
  497.   return SERVER_ERROR;  /* they lose -- but we get here if and only if there
  498.                was no default and nothing matched */
  499.  
  500. }
  501.  
  502.  
  503. handler_rec imap_handlers[] = {
  504. { IMAP_MAGIC_TYPE, imap_handler },
  505. { NULL }
  506. };
  507.  
  508. module imap_module = {
  509.    STANDARD_MODULE_STUFF,
  510.    NULL,            /* initializer */
  511.    NULL,            /* dir config creater */
  512.    NULL,            /* dir merger --- default is to override */
  513.    NULL,            /* server config */
  514.    NULL,            /* merge server config */
  515.    NULL,            /* command table */
  516.    imap_handlers,        /* handlers */
  517.    NULL,            /* filename translation */
  518.    NULL,            /* check_user_id */
  519.    NULL,            /* check auth */
  520.    NULL,            /* check access */
  521.    NULL,            /* type_checker */
  522.    NULL,            /* fixups */
  523.    NULL                /* logger */
  524. };
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.