www-apache-bugdb mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Richard Huveneers" <rich...@hekkihek.hacom.nl>
Subject Re: mod_include/1994: MSIE 4 still choking on chunks with bputc()
Date Wed, 25 Mar 1998 23:10:00 GMT
The following reply was made to PR mod_include/1994; it has been noted by GNATS.

From: "Richard Huveneers" <richard@hekkihek.hacom.nl>
To: "Dean Gaudet" <dgaudet@arctic.org>
Cc: <apbugs@hyperreal.org>
Subject: Re: mod_include/1994: MSIE 4 still choking on chunks with bputc()
Date: Wed, 25 Mar 1998 23:51:22 +0100

 This is a multi-part message in MIME format.
 
 ------=_NextPart_000_0003_01BD5848.EA0D6D40
 Content-Type: text/plain;
 	charset="iso-8859-1"
 Content-Transfer-Encoding: 7bit
 
 >Aha, <!--#include virtual="/servlet/VenA?f=0&topic=0" -->... what's that? 
 >Is that using mod_jserv or some other module?  This happens to be in the
 >chunk where things go wrong, so it's suspicious. 
 
 That's the mod_servlet.c from JavaSoft's JSDK, with the patch
 from Apacheweek applied for Apache 1.2. No local hacks. This
 one doesn't contain any bputc() or rputc() calls.
 
 Still suspicious? Oh well, I'll attach the patched source for
 you anyway. My other two testcases use servlets two, so this
 module may well be the culprit.
 
 Richard
 
 
 
 ------=_NextPart_000_0003_01BD5848.EA0D6D40
 Content-Type: application/octet-stream;
 	name="mod_servlet.c"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment;
 	filename="mod_servlet.c"
 
 /* @(#)mod_servlet.c	1.6 97/05/12=0A=
 **=0A=
 ** Apache module for running Jeeves-compatible servlets.=0A=
 ** This Apache module lets you run Jeeves-style Servlets from your=0A=
 ** Apache web server.=0A=
 ** =0A=
 ** To install the module:=0A=
 ** =0A=
 ** 1) Get the *source* distribution of Apache, not a binary distribution,=0A=
 **    from "http://www.apache.org/dist/".  Unpack it.=0A=
 ** =0A=
 ** 2) Copy mod_servlet.c into the Apache src directory.=0A=
 ** =0A=
 ** 3) Follow the instructions in the Apache src/INSTALL file:=0A=
 **   3a) Edit Configuration, setting your system customizations as the=0A=
 **       comments direct, and adding this to the list of modules:=0A=
 ** 	  Module servlet_module          mod_servlet.o=0A=
 **   3b) Configure=0A=
 **   3c) make=0A=
 ** =0A=
 ** 4) Continue with the instructions in the Apache README file:=0A=
 **   4a) Copy the Apache conf/*.dist files to conf/*.conf.=0A=
 **   4b) Edit conf/*.conf, setting your local system configuration.=0A=
 **   4c) Add this to conf/srm.conf:=0A=
 ** 	  <Location /servlet>=0A=
 ** 	  SetHandler servlet-handler=0A=
 ** 	  </Location>=0A=
 **   4d) Add ServletConfig commands if you want to override the defaults:=0A=
 ** 	  ServletConfig JAVA_HOME /opt/local/pkgs/java=0A=
 ** 	  ServletConfig JAVA_EXE java=0A=
 ** 	  ServletConfig JAVA_EXE_PATH /opt/local/pkgs/java/bin/java=0A=
 ** 	  ServletConfig CLASSPATH /opt/local/pkgs/java/lib/classes.zip=0A=
 ** 	  ServletConfig SERVAPI_HOME /opt/local/pkgs/ServAPI=0A=
 ** 	  ServletConfig SERVLET_HOME /opt/local/pkgs/ServAPI/servlets=0A=
 **        ServletConfig SERVLET_CONFIG =
 /opt/local/pkgs/ServAPI/servlets.properties=0A=
 ** 	  ServletConfig NCGI_CLASS sun.servlet.embedding.ncgi.NcgiServletGate=0A=
 ** 	  ServletConfig NCGI_HOST localhost=0A=
 ** 	  ServletConfig NCGI_PORT 31461=0A=
 ** 	  ServletConfig NCGI_AUTHFILE /tmp/ncgiauth=0A=
 **   4e) Start apache.  You should be able to run the module via=0A=
 **       a "/servlet" URL=0A=
 ** =0A=
 ** The Apache home page is http://www.apache.org/=0A=
 ** The Apache module API is documented at =
 http://www.apache.org/docs/API.html=0A=
 ** The Apache Module Registry: =
 http://www.zyzzyva.com/server/module_registry/=0A=
 ** =0A=
 ** The Jeeves home page is http://java.sun.com/products/jeeves/=0A=
 ** The Servlet API is documented at=0A=
 ** http://java.sun.com/products/jeeves/CurrentRelease/doc/api.html=0A=
 **=0A=
 **=0A=
 ** Copyright (c) 1996 Sun Microsystems, Inc.  All Rights reserved=0A=
 ** Permission to use, copy, modify, and distribute this software=0A=
 ** and its documentation for NON-COMMERCIAL purposes and without=0A=
 ** fee is hereby granted provided that this copyright notice=0A=
 ** appears in all copies. Please refer to the file copyright.html=0A=
 ** for further important copyright and licensing information.=0A=
 **=0A=
 ** SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF=0A=
 ** THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED=0A=
 ** TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A=0A=
 ** PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR=0A=
 ** ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR=0A=
 ** DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.=0A=
 **=0A=
 ** Tweaked for Apache 1.2.0 by <paulp@go2net.com>=0A=
 */=0A=
 =0A=
 =0A=
 /* Default values for config params. */=0A=
 =0A=
 #ifndef JAVA_HOME=0A=
 #define JAVA_HOME "/opt/local/pkgs/java"=0A=
 #endif=0A=
 #ifndef JAVA_EXE=0A=
 #define JAVA_EXE "java"=0A=
 #endif=0A=
 #ifndef CLASSPATH=0A=
 #define CLASSPATH "/opt/local/pkgs/java/lib/classes.zip"=0A=
 #endif=0A=
 #ifndef SERVAPI_HOME=0A=
 #define SERVAPI_HOME "/opt/local/pkgs/ServAPI"=0A=
 #endif=0A=
 #ifndef SERVLET_HOME=0A=
 #define SERVLET_HOME "/opt/local/pkgs/ServAPI/servlets"=0A=
 #endif=0A=
 #ifndef SERVLET_CONFIG=0A=
 #define SERVLET_CONFIG "/opt/local/pkgs/ServAPI/servlets.properties"=0A=
 #endif=0A=
 #ifndef NCGI_CLASS=0A=
 #define NCGI_CLASS "sun.servlet.apache.NcgiServletGate"=0A=
 #endif=0A=
 #ifndef NCGI_HOST=0A=
 #define NCGI_HOST "localhost"=0A=
 #endif=0A=
 #ifndef NCGI_PORT=0A=
 #define NCGI_PORT "31461"=0A=
 #endif=0A=
 #ifndef NCGI_AUTHFILE=0A=
 #define NCGI_AUTHFILE "/tmp/ncgiauth"=0A=
 #endif=0A=
 #ifndef NCGI_MAGIC=0A=
 #define NCGI_MAGIC "NCGI/1.0"=0A=
 #endif=0A=
 =0A=
 =0A=
 /* General includes. */=0A=
 =0A=
 #include <unistd.h>=0A=
 #include <stdlib.h>=0A=
 #include <stdio.h>=0A=
 #include <string.h>=0A=
 #include <errno.h>=0A=
 #include <sys/types.h>=0A=
 #include <sys/socket.h>=0A=
 #include <sys/stat.h>=0A=
 #include <fcntl.h>=0A=
 #include <netinet/in.h>=0A=
 #include <netdb.h>=0A=
 =0A=
 =0A=
 /* Apache includes. */=0A=
 =0A=
 #include "httpd.h"=0A=
 #include "http_config.h"=0A=
 #include "http_request.h"=0A=
 #include "http_core.h"=0A=
 #include "http_protocol.h"=0A=
 #include "http_main.h"=0A=
 #include "http_log.h"=0A=
 #include "util_script.h"=0A=
 =0A=
 =0A=
 /* NCGI client routines.=0A=
 **=0A=
 ** NCGI is a simple protocol for sending CGI requests over a network=0A=
 ** connection.  It's the same basic idea as FastCGI =
 (http://www.fastcgi.com/),=0A=
 ** but simpler.  There are four parts:=0A=
 **=0A=
 ** The first part is to send a "magic" string identifying the protocol =
 and=0A=
 ** version.  That string is currently "NCGI/1.0".  The string is =
 preceeded=0A=
 ** by the length as an unsigned short in network order.=0A=
 **=0A=
 ** The second part is authorization.  The server has previously written a=0A=
 ** random string to a designated file.  The file is protected so that it=0A=
 ** can only be read by the userid running the CGI program.  That program,=0A=
 ** the client, reads the file and sends the entire contents to the =
 server,=0A=
 ** again preceeded by the length as an unsigned short in network order.=0A=
 **=0A=
 ** The third part is to send the request.  Since CGI has already=0A=
 ** encapsulated the request as environment variables, the client just=0A=
 ** sends those strings.  Again each one is preceeded by its length as an=0A=
 ** unsigned short in network order.  A length of zero is sent at the end,=0A=
 ** indicating there are no more strings.=0A=
 **=0A=
 ** The fourth part is to send any data back and forth.  Data is read from=0A=
 ** stdin and sent to the server, while simultaneously the response data=0A=
 ** from the server is read and then written to stdout.  This continues=0A=
 ** until the client gets an EOF reading from the server.  At that point=0A=
 ** the transaction is complete, the socket is closed, and the client=0A=
 ** exits.=0A=
 **=0A=
 ** The security of this protocol is pretty weak.  The same authorization=0A=
 ** string is sent on every request, between server restarts - basically a=0A=
 ** password sent over the net in the clear.  However, most of the time =
 the=0A=
 ** network connection will only be to localhost, so that makes=0A=
 ** eavesdropping less of an issue.  Still, future versions could improve=0A=
 ** the security, perhaps using nonces.=0A=
 */=0A=
 =0A=
 /* Find the host, make the socket, bind, and connect. */=0A=
 static int=0A=
 get_socket( char* host, int port, server_rec *s, int nolog )=0A=
     {=0A=
     struct hostent *he;=0A=
     struct sockaddr_in sin;=0A=
     int sock;=0A=
 =0A=
     he =3D gethostbyname( host );=0A=
     if ( he =3D=3D (struct hostent*) 0 )=0A=
 	{=0A=
 	if ( ! nolog )=0A=
 	    log_error( "problem finding host", s );=0A=
         return -1;=0A=
 	}=0A=
     bzero( (caddr_t) &sin, sizeof(sin) );=0A=
     sin.sin_family =3D AF_INET;=0A=
     sock =3D socket( AF_INET, SOCK_STREAM, 0 );=0A=
     if ( sock < 0 )=0A=
 	{=0A=
 	if ( ! nolog )=0A=
 	    log_unixerr( "socket", host, "problem creating socket", s );=0A=
         return -1;=0A=
 	}=0A=
     if ( bind( sock, (struct sockaddr*) &sin, sizeof(sin) ) < 0 )=0A=
 	{=0A=
 	if ( ! nolog )=0A=
 	    log_unixerr( "bind", host, "problem binding to socket", s );=0A=
         return -1;=0A=
 	}=0A=
     bcopy( he->h_addr, &sin.sin_addr, he->h_length );=0A=
     sin.sin_port =3D htons( port );=0A=
     if ( connect( sock, (struct sockaddr*) &sin, sizeof(sin) ) < 0 )=0A=
 	{=0A=
 	if ( ! nolog )=0A=
 	    log_unixerr( "connect", host, "problem connecting to socket", s );=0A=
         return -1;=0A=
 	}=0A=
     return sock;=0A=
     }=0A=
 =0A=
 =0A=
 static int=0A=
 write_ushort( int fd, unsigned short us, server_rec* s )=0A=
     {=0A=
     unsigned short nus;=0A=
 =0A=
     nus =3D htons( us );=0A=
     if ( write( fd, &nus, sizeof(nus) ) !=3D sizeof(nus) )=0A=
 	{=0A=
 	log_unixerr( "write", (char*) 0, "problem writing ushort", s );=0A=
 	return -1;=0A=
 	}=0A=
     return 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Send a string to the NCGI server.  Each string is preceeded by its=0A=
 ** length as an unsigned short in network order.=0A=
 */=0A=
 static int=0A=
 write_string( int fd, char* cp, unsigned short len, server_rec* s )=0A=
     {=0A=
     if ( write_ushort( fd, len, s ) < 0 )=0A=
 	return -1;=0A=
     if ( write( fd, cp, len ) !=3D len )=0A=
 	{=0A=
 	log_unixerr( "write", (char*) 0, "problem writing string", s );=0A=
 	return -1;=0A=
 	}=0A=
     return 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Send the magic string to the NCGI server. */=0A=
 static int=0A=
 send_magic( int fd, server_rec* s )=0A=
     {=0A=
     if ( write_string( fd, NCGI_MAGIC, strlen( NCGI_MAGIC ), s ) < 0 )=0A=
 	return -1;=0A=
     return 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Send the authorization string to the NCGI server. */=0A=
 static int=0A=
 send_auth( int fd, char* authfile, server_rec* s )=0A=
     {=0A=
     int afd;=0A=
     struct stat sb;=0A=
     size_t len;=0A=
     char* cp;=0A=
 =0A=
     afd =3D open( authfile, O_RDONLY );=0A=
     if ( afd < 0 )=0A=
 	{=0A=
 	log_unixerr( "open", authfile, "problem opening authfile", s );=0A=
         return -1;=0A=
 	}=0A=
     if ( fstat( afd, &sb ) < 0 )=0A=
 	{=0A=
 	log_unixerr( "fstat", authfile, "problem statting authfile", s );=0A=
 	(void) close( afd );=0A=
         return -1;=0A=
 	}=0A=
     len =3D sb.st_size;=0A=
     cp =3D malloc( len );=0A=
     if ( cp =3D=3D (char*) 0 )=0A=
 	{=0A=
 	log_error( "out of memory", s );=0A=
 	(void) close( afd );=0A=
         return -1;=0A=
 	}=0A=
     if ( read( afd, cp, len ) !=3D len )=0A=
 	{=0A=
 	log_unixerr( "read", authfile, "problem reading authfile", s );=0A=
 	(void) close( afd );=0A=
 	free( cp );=0A=
         return -1;=0A=
 	}=0A=
     if ( write_string( fd, cp, len, s ) < 0 )=0A=
 	{=0A=
 	(void) close( afd );=0A=
 	free( cp );=0A=
         return -1;=0A=
 	}=0A=
     (void) close( afd );=0A=
     free( cp );=0A=
     return 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Send an environment variable to the NCGI server.  var should=0A=
 ** be passed in as "name=3Dvalue" form.=0A=
 */=0A=
 static int=0A=
 send_var( int fd, char* var, server_rec* s )=0A=
     {=0A=
     unsigned short len;=0A=
 =0A=
     len =3D strlen( var );=0A=
     if ( len !=3D 0 )=0A=
 	if ( write_string( fd, var, len, s ) < 0 )=0A=
 	    return -1;=0A=
     return 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Tell the NCGI server that we're done sending environment variables. */=0A=
 static int=0A=
 send_done_vars( int fd, server_rec* s )=0A=
     {=0A=
     unsigned short len;=0A=
 =0A=
     len =3D 0;=0A=
     if ( write_ushort( fd, len, s ) < 0 )=0A=
 	return -1;=0A=
     return 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Apache definitions. */=0A=
 =0A=
 typedef struct=0A=
     {=0A=
     char* java_home;=0A=
     char* java_exe;=0A=
     char* java_exe_path;=0A=
     char* classpath;=0A=
     char* servapi_home;=0A=
     char* servlet_home;=0A=
     char* servlet_config;=0A=
     char* ncgi_class;=0A=
     char* ncgi_host;=0A=
     char* ncgi_port;=0A=
     char* ncgi_authfile;=0A=
     } servlet_conf;=0A=
 =0A=
 =0A=
 /* Apache routines. */=0A=
 =0A=
 =0A=
 /* Forward declaration for module object. */=0A=
 module servlet_module;=0A=
 =0A=
 =0A=
 /* Make a config record. */=0A=
 static void*=0A=
 make_servlet_conf( pool *p, server_rec *s )=0A=
     {=0A=
     servlet_conf* c =3D (servlet_conf*) pcalloc( p, sizeof(servlet_conf) =
 );=0A=
 =0A=
     c->java_home =3D JAVA_HOME;=0A=
     c->java_exe =3D JAVA_EXE;=0A=
     c->java_exe_path =3D (char*) 0;=0A=
     c->classpath =3D CLASSPATH;=0A=
     c->servapi_home =3D SERVAPI_HOME;=0A=
     c->servlet_home =3D SERVLET_HOME;=0A=
     c->servlet_config =3D SERVLET_CONFIG;=0A=
     c->ncgi_class =3D NCGI_CLASS;=0A=
     c->ncgi_host =3D NCGI_HOST;=0A=
     c->ncgi_port =3D NCGI_PORT;=0A=
     c->ncgi_authfile =3D NCGI_AUTHFILE;=0A=
 =0A=
     return (void*) c;=0A=
     }=0A=
 =0A=
 =0A=
 /* Java child process.  Execs the java runtime and starts up the=0A=
 ** NCGI server / servlet runner.=0A=
 */=0A=
 static void=0A=
 java_child( void* data )=0A=
     {=0A=
     server_rec* s =3D (server_rec*) data;=0A=
     servlet_conf* c =3D get_module_config( s->module_config, =
 &servlet_module );=0A=
     char executable[HUGE_STRING_LEN];=0A=
     char* oclasspath;=0A=
     char classpath[HUGE_STRING_LEN];=0A=
     char path[HUGE_STRING_LEN];=0A=
     char tz[HUGE_STRING_LEN];=0A=
     char* env[4];=0A=
     int n;=0A=
 =0A=
     if ( c->java_exe_path !=3D (char*) 0 )=0A=
 	(void) strcpy( executable, c->java_exe_path );=0A=
     else=0A=
 	(void) sprintf( executable, "%s/bin/%s", c->java_home, c->java_exe );=0A=
 =0A=
     n =3D 0;=0A=
     if (c->classpath !=3D (char*) 0)=0A=
 	oclasspath =3D c->classpath;=0A=
     else=0A=
         oclasspath =3D getenv( "CLASSPATH" );=0A=
 =0A=
     if ( oclasspath =3D=3D (char*) 0 )=0A=
 	(void) sprintf(=0A=
 	    classpath, "CLASSPATH=3D%s/classes:%s/lib/classes.zip:%s",=0A=
 	    c->servapi_home, c->servapi_home , c->servlet_home);=0A=
     else=0A=
 	(void) sprintf(=0A=
 	    classpath, "CLASSPATH=3D%s/classes:%s/lib/classes.zip:%s:%s",=0A=
 	    c->servapi_home, c->servapi_home, c->servlet_home, oclasspath );=0A=
     env[n++] =3D classpath;=0A=
     if ( getenv( "PATH" ) !=3D (char*) 0 )=0A=
 	{=0A=
 	(void) sprintf( path, "PATH=3D%s", getenv( "PATH" ) );=0A=
 	env[n++] =3D path;=0A=
 	}=0A=
     if ( getenv( "TZ" ) !=3D (char*) 0 )=0A=
 	{=0A=
 	(void) sprintf( tz, "TZ=3D%s", getenv( "TZ" ) );=0A=
 	env[n++] =3D tz;=0A=
 	}=0A=
     env[n++] =3D (char*) 0;=0A=
 =0A=
     error_log2stderr ( s );=0A=
     cleanup_for_exec();=0A=
     execle(=0A=
 	executable, c->java_exe, c->ncgi_class,=0A=
 	"-p", c->ncgi_port, "-a", c->ncgi_authfile,=0A=
 	"-s", c->servlet_config,=0A=
 	(char*) 0, env );=0A=
     perror( "exec java" );=0A=
     exit( 1 );=0A=
     }=0A=
 =0A=
 =0A=
 /* Make sure a filename exists and is read-protected. */=0A=
 static void=0A=
 create_and_protect( char* filename, server_rec* s )=0A=
     {=0A=
     int fd;=0A=
 =0A=
     fd =3D open( filename, O_RDWR );=0A=
     if ( fd < 0 )=0A=
 	{=0A=
 	fd =3D open( filename, O_RDWR|O_CREAT );=0A=
 	if ( fd < 0 )=0A=
 	    {=0A=
 	    log_unixerr( "open", filename, "problem creating file", s );=0A=
 	    return;=0A=
 	    }=0A=
 	}=0A=
     (void) fchmod( fd, 0600 );=0A=
     (void) close( fd );=0A=
     }=0A=
 =0A=
 =0A=
 /* Initialization routine.  Spawns child process to run the server. */=0A=
 static void=0A=
 servlet_init_nonroot( server_rec* s, pool* p )=0A=
     {=0A=
     servlet_conf* c =3D get_module_config( s->module_config, =
 &servlet_module );=0A=
     int sock;=0A=
     int i;=0A=
 =0A=
     /* Try connecting. */=0A=
     sock =3D get_socket( c->ncgi_host, atoi( c->ncgi_port ), s, 1 );=0A=
     if ( sock >=3D 0 )=0A=
 	{=0A=
 	/* Connect worked, the server must already be running. */=0A=
 	(void) close( sock );=0A=
 	return;=0A=
 	}=0A=
 =0A=
     /* Connect failed.  Start the server. */=0A=
     create_and_protect( c->ncgi_authfile, s );=0A=
     if ( spawn_child(=0A=
 	     p, java_child, (void*) s, kill_never,=0A=
 	     (FILE**) 0, (FILE**) 0 ) =3D=3D 0 )=0A=
 	{=0A=
         log_error( "couldn't spawn java process", s );=0A=
         return;=0A=
 	}=0A=
 =0A=
     /* Make a few tries to connect. */=0A=
     for ( i =3D 0; i < 5; ++i )=0A=
 	{=0A=
 	sleep( 2 );=0A=
 	sock =3D get_socket( c->ncgi_host, atoi( c->ncgi_port ), s, 1 );=0A=
 	if ( sock >=3D 0 )=0A=
 	    {=0A=
 	    (void) close( sock );=0A=
 	    return;=0A=
 	    }=0A=
 	}=0A=
     /* If we couldn't connect, just give up. */=0A=
     }=0A=
 =0A=
 =0A=
 /* ServletConfig command. */=0A=
 const char*=0A=
 servlet_config( cmd_parms* parms, void* dummy, char* var, char* val )=0A=
     {=0A=
     server_rec* s =3D parms->server;=0A=
     servlet_conf* c =3D get_module_config( s->module_config, =
 &servlet_module );=0A=
     if ( strcasecmp( var, "JAVA_HOME" ) =3D=3D 0 )=0A=
 	c->java_home =3D val;=0A=
     else if ( strcasecmp( var, "JAVA_EXE" ) =3D=3D 0 )=0A=
 	c->java_exe =3D val;=0A=
     else if ( strcasecmp( var, "JAVA_EXE_PATH" ) =3D=3D 0 )=0A=
 	c->java_exe_path =3D val;=0A=
     else if ( strcasecmp( var, "CLASSPATH" ) =3D=3D 0 )=0A=
 	c->classpath =3D val;=0A=
     else if ( strcasecmp( var, "SERVAPI_HOME" ) =3D=3D 0 )=0A=
 	c->servapi_home =3D val;=0A=
     else if ( strcasecmp( var, "SERVLET_HOME" ) =3D=3D 0 )=0A=
 	c->servlet_home =3D val;=0A=
     else if ( strcasecmp( var, "SERVLET_CONFIG" ) =3D=3D 0 )=0A=
 	c->servlet_config =3D val;=0A=
     else if ( strcasecmp( var, "NCGI_CLASS" ) =3D=3D 0 )=0A=
 	c->ncgi_class =3D val;=0A=
     else if ( strcasecmp( var, "NCGI_HOST" ) =3D=3D 0 )=0A=
 	c->ncgi_host =3D val;=0A=
     else if ( strcasecmp( var, "NCGI_PORT" ) =3D=3D 0 )=0A=
 	c->ncgi_port =3D val;=0A=
     else if ( strcasecmp( var, "NCGI_AUTHFILE" ) =3D=3D 0 )=0A=
 	c->ncgi_authfile =3D val;=0A=
     else=0A=
 	return "unknown variable in ServletConfig command";=0A=
     return (char*) 0;=0A=
     }=0A=
 =0A=
 =0A=
 /* Cleanup routine for request handler. */=0A=
 static void=0A=
 cleanup_handler( request_rec* r, int sock, void (*handler)() )=0A=
     {=0A=
     if ( sock !=3D -1 )=0A=
 	(void) close( sock );=0A=
     if ( handler !=3D 0 )=0A=
 	signal( SIGPIPE, handler );=0A=
     kill_timeout( r );=0A=
     }=0A=
 =0A=
 =0A=
 /* Request handler.  Called on each request. */=0A=
 static int=0A=
 servlet_handler( request_rec* r )=0A=
 {=0A=
     static int inited =3D 0;=0A=
     server_rec* s =3D r->server;=0A=
     table* e =3D r->subprocess_env;=0A=
     request_rec* pa_req;=0A=
     servlet_conf* c =3D get_module_config( s->module_config, =
 &servlet_module );=0A=
     char* lenp =3D table_get( r->headers_in, "Content-length" );=0A=
     void (*handler)() =3D 0;=0A=
     int sock =3D -1;=0A=
     char** env;=0A=
     char** ep;=0A=
     char databuffer[HUGE_STRING_LEN];=0A=
     int path_info_start;=0A=
     char* path_info_str;=0A=
     int retval;=0A=
 =0A=
     /* Initialize if necessary.  We call the init routine from the =
 request=0A=
     ** handler rather than via the init entry in the module struct =
 because=0A=
     ** if we did it the latter way, it would get called as root!=0A=
     */=0A=
     if ( ! inited )=0A=
 	{=0A=
 	inited =3D 1;=0A=
 	servlet_init_nonroot( s, permanent_pool );=0A=
 	}=0A=
 =0A=
     /* Check for bad request. */=0A=
     if ( ( r->method_number =3D=3D M_POST || r->method_number =3D=3D =
 M_PUT ) &&=0A=
 	 lenp =3D=3D (char*) 0 )=0A=
 	{=0A=
         log_reason( "POST or PUT without Content-length:", r->uri, r );=0A=
 	return BAD_REQUEST;=0A=
 	}=0A=
 =0A=
     /* Set up timeout. */=0A=
     hard_timeout( "run servlet", r );=0A=
     handler =3D signal( SIGPIPE, SIG_IGN );=0A=
 =0A=
     /* Find the host, make the socket, bind, and connect. */=0A=
     sock =3D get_socket( c->ncgi_host, atoi( c->ncgi_port ), s, 0 );=0A=
     if ( sock < 0 )=0A=
 	{=0A=
 	log_reason( "problem creating socket", r->uri, r );=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return SERVER_ERROR;=0A=
 	}=0A=
 =0A=
     /* Send the magic string. */=0A=
     if ( send_magic( sock, s ) < 0 )=0A=
 	{=0A=
         log_reason( "problem sending magic", r->uri, r );=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return SERVER_ERROR;=0A=
 	}=0A=
 =0A=
     /* Send the authorization file. */=0A=
     if ( send_auth( sock, c->ncgi_authfile, s ) < 0 )=0A=
 	{=0A=
         log_reason( "problem sending auth string", r->uri, r );=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return SERVER_ERROR;=0A=
 	}=0A=
 =0A=
     /* No chunked requests via our NCGI interface, sorry folks */=0A=
     if((retval =3D setup_client_block(r, REQUEST_CHUNKED_ERROR)) !=3D =
 OK) {=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return retval;=0A=
     }=0A=
 =0A=
     /* Make a CGI environment array. */=0A=
     add_common_vars( r );=0A=
 =0A=
     /* add_cgi_vars( r );=0A=
      *=0A=
      *  essentially have to rewrite this method below=0A=
      */=0A=
 =0A=
     /* Adjusting variables for servlet location =0A=
      */=0A=
 =0A=
     table_set (e, "GATEWAY_INTERFACE", "servlet");=0A=
     table_set (e, "SERVER_PROTOCOL", r->protocol);=0A=
     table_set (e, "REQUEST_METHOD", r->method);=0A=
     table_set (e, "QUERY_STRING", r->args ? r->args : "");=0A=
 =0A=
     /* This hardcode of /servlet/ is an offense against all=0A=
      * that is right and good... but it's very pervasive and=0A=
      * I can't get rid of it without tweaking all kinds of=0A=
      * code. =0A=
      */=0A=
     if (strncmp(r->uri,"/servlet/",strlen("/servlet/"))) {=0A=
         log_reason( "servlets must be in /servlet directory", r->uri, r =
 );=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return SERVER_ERROR;=0A=
     }=0A=
     if (!r->path_info || !r->path_info[0]) {=0A=
 	/* someone is trying to get to the "servlets directory". tsk.*/=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return FORBIDDEN;=0A=
     }=0A=
 =0A=
     /* length =3D total - path_info + strlen("/servlet/") */=0A=
 =0A=
     path_info_str  =3D strchr(r->uri + strlen("/servlet/"),'/');=0A=
     if (path_info_str) {=0A=
 	r->path_info =3D path_info_str;=0A=
         path_info_start =3D strlen(r->uri) - strlen(r->path_info);=0A=
         r->uri[path_info_start] =3D '\0';=0A=
         table_set (e, "SCRIPT_NAME", r->uri);=0A=
         r->uri[path_info_start] =3D '/';=0A=
     =0A=
         pa_req =3D sub_req_lookup_uri(=0A=
 			          escape_uri(r->pool, r->path_info), r);=0A=
         table_set(e, "PATH_INFO", r->path_info);=0A=
         if (pa_req->filename) {=0A=
 	    table_set (e, "PATH_TRANSLATED", =0A=
 	        pstrcat (r->pool, pa_req->filename, pa_req->path_info, NULL));=0A=
         }=0A=
         destroy_sub_req(pa_req);=0A=
     } else {=0A=
         table_set (e, "SCRIPT_NAME", r->uri);=0A=
     }=0A=
 =0A=
     env =3D create_environment( r->pool, r->subprocess_env );=0A=
 =0A=
     /* Send all environment variables to NCGI server.  Each string is=0A=
     ** preceeded by its length as an unsigned short in network order.=0A=
     ** After the last string, a length of zero is sent.=0A=
     */=0A=
     for ( ep =3D env; *ep !=3D (char*) 0; ++ep )=0A=
 	if ( send_var( sock, *ep, s ) < 0 )=0A=
 	    {=0A=
 	    log_reason( "problem sending environment string", r->uri, r );=0A=
 	    cleanup_handler( r, sock, handler );=0A=
 	    return SERVER_ERROR;=0A=
 	    }=0A=
     if ( send_done_vars( sock, s ) < 0 )=0A=
 	{=0A=
 	log_reason( "problem sending env end marker", r->uri, r );=0A=
 	cleanup_handler( r, sock, handler );=0A=
 	return SERVER_ERROR;=0A=
 	}=0A=
 =0A=
     /* Transfer any put/post data, CERN style...=0A=
     ** Note that if a buggy servlet fails to read everything we throw=0A=
     ** at it, or a buggy client sends too much, we get a SIGPIPE, so=0A=
     ** we have to ignore SIGPIPE while doing this.  CERN does the same=0A=
     ** (and in fact, they pretty nearly guarantee themselves a SIGPIPE=0A=
     ** on every invocation by chasing the real client data with a=0A=
     ** spurious newline).=0A=
     */=0A=
 =0A=
     if(should_client_block(r))=0A=
     {=0A=
 	int len_read;=0A=
 =0A=
 	while((len_read =3D =0A=
 		get_client_block(r, databuffer, HUGE_STRING_LEN)) > 0)=0A=
 	{=0A=
 =0A=
 	    reset_timeout(r);=0A=
 	    if(write(sock, databuffer, len_read) < (size_t)len_read)=0A=
 	    {=0A=
 		/* script stopped reading */=0A=
 		while(get_client_block(r, databuffer, HUGE_STRING_LEN) > 0)=0A=
 		    ;	/* dump read data */=0A=
 		break;=0A=
 	    }=0A=
 	}=0A=
 =0A=
 	kill_timeout(r);=0A=
     }=0A=
 =0A=
     /* Send back the results. */=0A=
     bflush( r->connection->client );=0A=
     for (;;) {=0A=
 	int len_read =3D read( sock, databuffer, sizeof(databuffer) );=0A=
 	if ( len_read <=3D 0 )=0A=
 	    break;=0A=
 	if ( write( r->connection->client->fd, databuffer, len_read ) <=3D 0 )=0A=
 	    break;=0A=
     }=0A=
 =0A=
     /* All done. */=0A=
     cleanup_handler( r, sock, handler );=0A=
     return OK;			/* NOT r->status, even if it has changed */=0A=
 }=0A=
 =0A=
 =0A=
 /* Command table. */=0A=
 static command_rec servlet_commands [] =3D=0A=
     {=0A=
     { "ServletConfig", servlet_config, NULL, ACCESS_CONF|RSRC_CONF, =
 TAKE2,=0A=
       "a variable to set followed by its value" },=0A=
     NULL=0A=
     };=0A=
 =0A=
 /* Handler record. */=0A=
 static handler_rec servlet_handlers[] =3D=0A=
     {=0A=
     { "servlet-handler", servlet_handler },=0A=
     NULL=0A=
     };=0A=
 =0A=
 /* Module structure. */=0A=
 module servlet_module =3D=0A=
     {=0A=
     STANDARD_MODULE_STUFF,=0A=
     NULL,			/* initializer */=0A=
     NULL,			/* dir config creater */=0A=
     NULL,			/* dir merger - default is to override */=0A=
     make_servlet_conf,		/* server config */=0A=
     NULL,			/* merge server config */=0A=
     servlet_commands,		/* command table */=0A=
     servlet_handlers,		/* handlers */=0A=
     NULL,			/* filename translation */=0A=
     NULL,			/* check_user_id */=0A=
     NULL,			/* check auth */=0A=
     NULL,			/* check access */=0A=
     NULL,			/* type_checker */=0A=
     NULL,			/* fixups */=0A=
     NULL			/* logger */=0A=
     };=0A=
 
 ------=_NextPart_000_0003_01BD5848.EA0D6D40--
 

Mime
View raw message