hgomez 01/06/01 01:49:27 Added: jk/src/native/domino config.h dsapi.dsp dsapi.dsw dsapifilter.h jk_dsapi_plugin.c tomcat_redirector.reg Log: Initial domino support in JTC Contributed by Andy Armstrong <[EMAIL PROTECTED]> Revision Changes Path 1.1 jakarta-tomcat-connectors/jk/src/native/domino/config.h Index: config.h =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ /*************************************************************************** * Description: DSAPI plugin for Lotus Domino * * Author: Andy Armstrong <[EMAIL PROTECTED]> * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef __config_h #define __config_h /* the _memicmp() function is available */ #define HAVE_MEMICMP /* define if you don't have the Notes C API which is available from * * http://www.lotus.com/rw/dlcapi.nsf */ /* #undef NO_CAPI */ #endif /* __config_h */ 1.1 jakarta-tomcat-connectors/jk/src/native/domino/dsapi.dsp Index: dsapi.dsp =================================================================== # Microsoft Developer Studio Project File - Name="dsapi" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=dsapi - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "dsapi.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dsapi.mak" CFG="dsapi - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dsapi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "dsapi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "dsapi - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DSAPI_EXPORTS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "C:\notesapi\include" /I "C:\JBuilder4\jdk1.3\include" /I "C:\JBuilder4\jdk1.3\include\win32" /I "..\jk" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DSAPI_EXPORTS" /D "NT" /FR /FD /c # SUBTRACT CPP /YX /Yc /Yu # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" # ADD RSC /l 0x809 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib notes.lib /nologo /dll /machine:I386 /out:"Release/tomcat_redirector.dll" /libpath:"C:\notesapi\lib\mswin32" # Begin Special Build Tool SOURCE="$(InputPath)" PostBuild_Cmds=copy Release\tomcat_redirector.dll \\london\c$\lotus\domino # End Special Build Tool !ELSEIF "$(CFG)" == "dsapi - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DSAPI_EXPORTS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\JBuilder4\jdk1.3\include" /I "C:\JBuilder4\jdk1.3\include\win32" /I "..\jk" /I "C:\notesapi\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DSAPI_EXPORTS" /D "NT" /FR /FD /GZ /c # SUBTRACT CPP /YX /Yc /Yu # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" # ADD RSC /l 0x809 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib notes.lib /nologo /dll /debug /machine:I386 /out:"Debug/tomcat_redirector.dll" /pdbtype:sept /libpath:"C:\notesapi\lib\mswin32" !ENDIF # Begin Target # Name "dsapi - Win32 Release" # Name "dsapi - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\jk\jk_ajp12_worker.c # End Source File # Begin Source File SOURCE=..\jk\jk_ajp13.c # End Source File # Begin Source File SOURCE=..\jk\jk_ajp13_worker.c # End Source File # Begin Source File SOURCE=..\jk\jk_connect.c # End Source File # Begin Source File SOURCE=.\jk_dsapi_plugin.c # End Source File # Begin Source File SOURCE=..\jk\jk_jni_worker.c # End Source File # Begin Source File SOURCE=..\jk\jk_lb_worker.c # End Source File # Begin Source File SOURCE=..\jk\jk_map.c # End Source File # Begin Source File SOURCE=..\jk\jk_msg_buff.c # End Source File # Begin Source File SOURCE=..\jk\jk_nwmain.c # End Source File # Begin Source File SOURCE=..\jk\jk_pool.c # End Source File # Begin Source File SOURCE=..\jk\jk_sockbuf.c # End Source File # Begin Source File SOURCE=..\jk\jk_uri_worker_map.c # End Source File # Begin Source File SOURCE=..\jk\jk_util.c # End Source File # Begin Source File SOURCE=..\jk\jk_worker.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\config.h # End Source File # Begin Source File SOURCE=.\dsapifilter.h # End Source File # Begin Source File SOURCE=..\jk\jk_ajp12_worker.h # End Source File # Begin Source File SOURCE=..\jk\jk_ajp13.h # End Source File # Begin Source File SOURCE=..\jk\jk_ajp13_worker.h # End Source File # Begin Source File SOURCE=..\jk\jk_connect.h # End Source File # Begin Source File SOURCE=..\jk\jk_global.h # End Source File # Begin Source File SOURCE=..\jk\jk_jni_worker.h # End Source File # Begin Source File SOURCE=..\jk\jk_lb_worker.h # End Source File # Begin Source File SOURCE=..\jk\jk_logger.h # End Source File # Begin Source File SOURCE=..\jk\jk_map.h # End Source File # Begin Source File SOURCE=..\jk\jk_msg_buff.h # End Source File # Begin Source File SOURCE=..\jk\jk_mt.h # End Source File # Begin Source File SOURCE=..\jk\jk_pool.h # End Source File # Begin Source File SOURCE=..\jk\jk_service.h # End Source File # Begin Source File SOURCE=..\jk\jk_sockbuf.h # End Source File # Begin Source File SOURCE=..\jk\jk_uri_worker_map.h # End Source File # Begin Source File SOURCE=..\jk\jk_util.h # End Source File # Begin Source File SOURCE=..\jk\jk_worker.h # End Source File # Begin Source File SOURCE=..\jk\jk_worker_list.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Source File SOURCE=.\ReadMe.txt # End Source File # End Target # End Project 1.1 jakarta-tomcat-connectors/jk/src/native/domino/dsapi.dsw Index: dsapi.dsw =================================================================== Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "dsapi"=".\dsapi.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### 1.1 jakarta-tomcat-connectors/jk/src/native/domino/dsapifilter.h Index: dsapifilter.h =================================================================== /*-------------------------------------------------------------------- * * File: dsapifilter.h * * Copyright (c)1999 Iris Associates * *-------------------------------------------------------------------*/ #if !defined(DSAPIFILTER_H) #define DSAPIFILTER_H #ifdef __cplusplus extern "C" { #endif /*--- * Types and Defines */ #define kInterfaceVersion 2 #define kMaxFilterDesc 255 typedef unsigned char LMBCS; typedef enum { kFilterNotHandled = 0, kFilterHandledRequest = 1, kFilterHandledEvent = 2, kFilterError = 3 } FilterReturnCode; /*-- * Filter interface */ /*--- * events to register for */ typedef enum { kFilterRawRequest = 0x01, kFilterParsedRequest = 0x02, kFilterAuthUser = 0x04, kFilterUserNameList = 0x08, kFilterMapURL = 0x10, kFilterResponse = 0x20, kFilterRawWrite = 0x40, kFilterEndRequest = 0x80, kFilterAny = 0xFF } EventFlags; /*--- * filter initialization data */ typedef struct { unsigned int serverFilterVersion; unsigned int appFilterVersion; unsigned int eventFlags; unsigned int initFlags; char filterDesc[kMaxFilterDesc + 1]; } FilterInitData; /*--- * request line structure */ typedef struct { unsigned int method; char *URL; char *version; char *userName; char *password; unsigned char *clientCert; unsigned int clientCertLen; char *contentRead; unsigned int contentReadLen; } FilterRequest; /*--- * filter context data included in every call to filter */ typedef struct _FilterContext { unsigned int contextSize; unsigned int revision; void *serverContext; unsigned int serverReserved; unsigned int securePort; void *privateContext; int (*GetRequest) (struct _FilterContext * context, FilterRequest * request, unsigned int *errID); int (*GetRequestContents) (struct _FilterContext * context, char **contents, unsigned int *errID); int (*GetServerVariable) (struct _FilterContext * context, char *name, void *buffer, unsigned int bufferSize, unsigned int *errID); int (*WriteClient) (struct _FilterContext * context, char *buffer, unsigned int bufferLen, unsigned int reserved, unsigned int *errID); void *(*AllocMem) (struct _FilterContext * context, unsigned int size, unsigned int reserved, unsigned int *errID); int (*ServerSupport) (struct _FilterContext * context, unsigned int funcType, void *data1, void *data2, unsigned int other, unsigned int *errID); } FilterContext; typedef unsigned int (*FilterInitFuncType) (FilterInitData * initData); typedef unsigned int (*FilterEventFuncType) (FilterContext * context, unsigned int eventType, void *eventData, unsigned int *errID); typedef unsigned int (*FilterTermFuncType) (unsigned int); /*--- * request methods */ typedef enum { kRequestNone = 0, kRequestHEAD = 1, kRequestGET = 2, kRequestPOST = 3, kRequestPUT = 4, kRequestDELETE = 5 } RequestMethod; /*--- * server support function types */ typedef enum { kWriteResponseHeaders = 1 } ServerSupportTypes; /*--- * 'data1' for server support function 'kWriteResponseHeaders' */ typedef struct { unsigned int responseCode; char *reasonText; char *headerText; } FilterResponseHeaders; /*--- * raw request (headers not processed yet) */ typedef struct { unsigned int requestMethod; int (*GetAllHeaders) (FilterContext * context, char **headers, unsigned int *errID); int (*GetHeader) (FilterContext * context, char *name, char *buffer, unsigned int bufferSize, unsigned int *errID); int (*SetHeader) (FilterContext * context, char *name, char *value, unsigned int *errID); int (*AddHeader) (FilterContext * context, char *header, unsigned int *errID); unsigned int reserved; } FilterRawRequest; /*--- * parsed request */ typedef struct { unsigned int requestMethod; int (*GetAllHeaders) (FilterContext * context, char **headers, unsigned int *errID); int (*GetHeader) (FilterContext * context, char *name, char *buffer, unsigned int bufferSize, unsigned int *errID); unsigned int reserved; } FilterParsedRequest; /*--- * URL map */ typedef struct { const char *url; char *pathBuffer; unsigned int bufferSize; unsigned int mapType; } FilterMapURL; /*--- * URL map types */ typedef enum { kURLMapUnknown = 0, kURLMapPass = 1, kURLMapExec = 2, kURLMapRedirect = 3, kURLMapService = 4, kURLMapDomino = 5 } FilterULMapTypes; /*--- * user authentication */ typedef struct { LMBCS *userName; LMBCS *password; unsigned char *clientCert; unsigned int clientCertLen; unsigned int authFlags; unsigned int preAuthenticated; unsigned int foundInCache; unsigned int authNameSize; LMBCS *authName; unsigned int authType; int (*GetUserNameList) (FilterContext * context, LMBCS * buffer, unsigned int bufferSize, unsigned int *numNames, unsigned int reserved, unsigned int *errID); int (*GetHeader) (FilterContext * context, char *name, char *buffer, unsigned int bufferSize, unsigned int *errID); } FilterAuthenticate; /*--- * user authentication types */ typedef enum { kNotAuthentic = 0, kAuthenticBasic = 1, kAuthenticClientCert = 2 } FilterAuthenticationTypes; /*--- * authentication configuration flags */ typedef enum { kAuthAllowBasic = 1, kAuthAllowAnonymous = 2, kAuthAllowSSLCert = 4, kAuthAllowSSLBasic = 8, kAuthAllowSSLAnonymous = 16, kAuthRedirectToSSL = 32 } FilterAuthConfigFlags; /*--- * user name list */ typedef struct { const LMBCS *userName; int (*GetUserNameList) (FilterContext * context, LMBCS * buffer, unsigned int bufferSize, unsigned int *numNames, unsigned int reserved, unsigned int *errID); int (*PopulateUserNameList) (FilterContext * context, LMBCS * buffer, unsigned int bufferSize, unsigned int *numNames, unsigned int reserved, unsigned int *errID); int (*AddGroupsToList) (FilterContext * context, LMBCS * groupNames, unsigned int numGroupNames, unsigned int reserved, unsigned int *errID); int (*RemoveGroupsFromList) (FilterContext * context, unsigned int reserved, unsigned int *errID); unsigned int reserved; } FilterUserNameList; /*--- * request response */ typedef struct { unsigned int responseCode; char *reasonText; int (*GetAllHeaders) (FilterContext * context, char **headers, unsigned int *errID); int (*GetHeader) (FilterContext * context, char *name, char *buffer, unsigned int bufferSize, unsigned int *errID); int (*SetHeader) (FilterContext * context, char *name, char *value, unsigned int *errID); int (*AddHeader) (FilterContext * context, char *header, unsigned int *errID); unsigned int reserved; } FilterResponse; /*--- * write content */ typedef struct { char *content; unsigned int contentLen; unsigned int reserved; } FilterRawWrite; #ifdef __cplusplus } #endif #endif /* DSAPIFILTER_H */ 1.1 jakarta-tomcat-connectors/jk/src/native/domino/jk_dsapi_plugin.c Index: jk_dsapi_plugin.c =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ /*************************************************************************** * Description: DSAPI plugin for Lotus Domino * * Author: Andy Armstrong <[EMAIL PROTECTED]> * * Version: $Revision: 1.1 $ * ***************************************************************************/ /* Based on the IIS redirector by Gal Shachor <[EMAIL PROTECTED]> */ #include "config.h" /* JK stuff */ #include "jk_global.h" #include "jk_util.h" #include "jk_map.h" #include "jk_pool.h" #include "jk_service.h" #include "jk_worker.h" #include "jk_ajp12_worker.h" #include "jk_uri_worker_map.h" #ifndef NO_CAPI /* Domino stuff */ #include <global.h> #include <addin.h> #else #include <stdarg.h> #define NOERROR 0 #endif #include <stdlib.h> #include <stdio.h> #include <string.h> #include "dsapifilter.h" #if !defined(DLLEXPORT) #ifdef WIN32 #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif #endif #define VERSION "1.0" #define VERSION_STRING "Jakarta/DSAPI/" VERSION /* What we call ourselves */ #define FILTERDESC "Apache Tomcat Interceptor (" VERSION_STRING ")" /* Registry location of configuration data */ #define REGISTRY_LOCATION "Software\\Apache Software Foundation\\Jakarta Dsapi Redirector\\1.0" /* Names of registry keys that contain commands to start, stop Tomcat */ #define TOMCAT_START "tomcat_start" #define TOMCAT_STOP "tomcat_stop" #define TOMCAT_STARTSTOP_TO 30000 /* 30 seconds */ static int initDone = JK_FALSE; static jk_uri_worker_map_t *uw_map = NULL; static jk_logger_t *logger = NULL; static int logLevel = JK_LOG_EMERG_LEVEL; static char logFile[MAX_PATH]; static char workerFile[MAX_PATH]; static char workerMountFile[MAX_PATH]; static char tomcatStart[MAX_PATH]; static char tomcatStop[MAX_PATH]; static char *crlf = "\r\n"; typedef struct private_ws { jk_pool_t p; /* These get passed in by Domino and are used to access various * Domino methods and data. */ FilterContext *context; FilterParsedRequest *reqData; /* True iff the response headers have been sent */ int responseStarted; /* Current pointer into and remaining size * of request body data */ char *reqBuffer; unsigned int reqSize; } private_ws_t; /* These three functions are called back (indirectly) by * Tomcat during request processing. StartResponse() sends * the headers associated with the response. */ static int JK_METHOD StartResponse(jk_ws_service_t * s, int status, const char *reason, const char *const *hdrNames, const char *const *hdrValues, unsigned hdrCount); /* Read() is called by Tomcat to read from the request body (if any). */ static int JK_METHOD Read(jk_ws_service_t * s, void *b, unsigned l, unsigned *a); /* Write() is called by Tomcat to send data back to the client. */ static int JK_METHOD Write(jk_ws_service_t * s, const void *b, unsigned l); static int ReadInitData(void); static int GetRegParam(HKEY hkey, const char *tag, char *b, DWORD sz); static unsigned int ParsedRequest(FilterContext *context, FilterParsedRequest *reqData); /* Case insentive memcmp() clone */ #ifdef HAVE_MEMICMP #define NoCaseCmp(ci, cj, l) _memicmp((void *) (ci), (void *) (cj), (l)) #else static int NoCaseCmp(const char *ci, const char *cj, int len) { if (0 == memcmp(ci, cj, len)) return 0; while (len > 0) { int cmp = tolower(*ci) - tolower(*cj); if (cmp != 0) return cmp; ci++; cj++; len--; } return 0; } #endif /* Case insensitive substring search. * str string to search * slen length of string to search * ptn pattern to search for * plen length of pattern * returns 1 if there's a match otherwise 0 */ static int NoCaseFind(const char *str, int slen, const char *ptn, int plen) { while (slen >= plen) { if (NoCaseCmp(str, ptn, plen) == 0) return 1; slen--; str++; } return 0; } #ifdef NO_CAPI /* Alternative to the Domino function */ static void AddInLogMessageText(char *msg, unsigned short code, ...) { va_list ap; if (code != NOERROR) printf("Error %d: ", code); va_start(ap, code); vprintf(msg, ap); va_end(ap); printf("\n"); } #endif /* Return 1 iff the supplied string contains "web-inf" (in any case * variation. We don't allow URIs containing web-inf. */ static int BadURI(const char *uri) { static char *wi = "web-inf"; return NoCaseFind(uri, strlen(uri), wi, strlen(wi)); } /* Replacement for strcat() that updates a buffer pointer. It's * probably marginal, but this should be more efficient that strcat() * in cases where the string being concatenated to gets long because * strcat() has to count from start of the string each time. */ static void Append(char **buf, const char *str) { int l = strlen(str); memcpy(*buf, str, l); (*buf)[l] = '\0'; *buf += l; } /* Start the response by sending any headers. Invoked by Tomcat. I don't * particularly like the fact that this always allocates memory, but * perhaps jk_pool_alloc() is efficient. */ static int JK_METHOD StartResponse(jk_ws_service_t *s, int status, const char *reason, const char *const *hdrNames, const char *const *hdrValues, unsigned hdrCount) { jk_log(logger, JK_LOG_DEBUG, "Into jk_ws_service_t::StartResponse\n"); if (status < 100 || status > 1000) { jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::StartResponse, invalid status %d\n", status); return JK_FALSE; } if (s && s->ws_private) { private_ws_t *p = s->ws_private; if (!p->responseStarted) { char *hdrBuf; FilterResponseHeaders frh; int rc, errID; p->responseStarted = JK_TRUE; if (NULL == reason) reason = ""; /* Build a single string containing all the headers * because that's what Domino needs. */ if (hdrCount > 0) { unsigned i; unsigned hdrLen; char *bufp; for (i = 0, hdrLen = 3; i < hdrCount; i++) hdrLen += strlen(hdrNames[i]) + strlen(hdrValues[i]) + 4; hdrBuf = jk_pool_alloc(&p->p, hdrLen); bufp = hdrBuf; for (i = 0; i < hdrCount; i++) { Append(&bufp, hdrNames[i]); Append(&bufp, ": "); Append(&bufp, hdrValues[i]); Append(&bufp, crlf); } Append(&bufp, crlf); } else { hdrBuf = crlf; } frh.responseCode = status; frh.reasonText = (char *) reason; frh.headerText = hdrBuf; //printf("%d %s\n%s", status, reason, hdrBuf); /* Send the headers */ rc = p->context->ServerSupport(p->context, kWriteResponseHeaders, &frh, NULL, 0, &errID); /* if (rc) { jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::StartResponse, ServerSupportFunction failed\n"); return JK_FALSE; } */ } return JK_TRUE; } jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::StartResponse, NULL parameters\n"); return JK_FALSE; } static int JK_METHOD Read(jk_ws_service_t * s, void *bytes, unsigned len, unsigned *countp) { jk_log(logger, JK_LOG_DEBUG, "Into jk_ws_service_t::Read\n"); if (s && s->ws_private && bytes && countp) { private_ws_t *p = s->ws_private; /* Copy data from Domino's buffer. Although it seems slightly * improbably we're believing that Domino always buffers the * entire request in memory. Not properly tested yet. */ if (len > p->reqSize) len = p->reqSize; memcpy(bytes, p->reqBuffer, len); p->reqBuffer += len; p->reqSize -= len; *countp = len; return JK_TRUE; } jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::Read, NULL parameters\n"); return JK_FALSE; } static int JK_METHOD Write(jk_ws_service_t *s, const void *bytes, unsigned len) { jk_log(logger, JK_LOG_DEBUG, "Into jk_ws_service_t::Write\n"); if (s && s->ws_private && bytes) { private_ws_t *p = s->ws_private; int errID, rc; /* Make sure the response has really started. I'm almost certain * this isn't necessary, but it was in the ISAPI code, so it's in * here too. */ if (!p->responseStarted) StartResponse(s, 200, NULL, NULL, NULL, 0); //printf("Writing %d bytes of content\n", len); /* Send the data */ if (len > 0) rc = p->context->WriteClient(p->context, (char *) bytes, len, 0, &errID); return JK_TRUE; } jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::Write, NULL parameters\n"); return JK_FALSE; } static int RunProg(char *cmd) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); // Start the child process. si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWMAXIMIZED; if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { DWORD err = GetLastError(); AddInLogMessageText("Command \"%s\" (error %u)", NOERROR, cmd, err); return FALSE; } if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, TOMCAT_STARTSTOP_TO)) return TRUE; AddInLogMessageText("Command \"%s\" didn't complete in time", NOERROR, cmd); return FALSE; } /* Called when the filter is unloaded. Free various resources and * display a banner. */ DLLEXPORT unsigned int TerminateFilter(unsigned int reserved) { if (initDone) { initDone = JK_FALSE; uri_worker_map_free(&uw_map, logger); wc_close(logger); if (logger) jk_close_file_logger(&logger); } if (tomcatStop[0]) { AddInLogMessageText("Attempting to stop Tomcat: %s", NOERROR, tomcatStop); RunProg(tomcatStop); } AddInLogMessageText(FILTERDESC " unloaded", NOERROR); return kFilterHandledEvent; } /* Called when Domino loads the filter. Reads a load of config data from * the registry and elsewhere and displays a banner. */ DLLEXPORT unsigned int FilterInit(FilterInitData * filterInitData) { int rc = JK_FALSE; jk_map_t *map = NULL; if (!ReadInitData()) goto initFailed; if (!jk_open_file_logger(&logger, logFile, logLevel)) logger = NULL; if (tomcatStart[0]) { AddInLogMessageText("Attempting to start Tomcat: %s", NOERROR, tomcatStart); RunProg(tomcatStart); } if (map_alloc(&map)) { if (map_read_properties(map, workerMountFile)) if (uri_worker_map_alloc(&uw_map, map, logger)) rc = JK_TRUE; map_free(&map); } if (!rc) goto initFailed; rc = JK_FALSE; if (map_alloc(&map)) { if (map_read_properties(map, workerFile)) if (wc_open(map, logger)) rc = JK_TRUE; map_free(&map); } if (!rc) goto initFailed; initDone = JK_TRUE; filterInitData->appFilterVersion = kInterfaceVersion; filterInitData->eventFlags = kFilterParsedRequest; strcpy(filterInitData->filterDesc, FILTERDESC); // Banner AddInLogMessageText("%s loaded", NOERROR, filterInitData->filterDesc); return kFilterHandledEvent; initFailed: AddInLogMessageText("Error loading %s", NOERROR, FILTERDESC); return kFilterError; } /* Read parameters from the registry */ static int ReadInitData(void) { char tmpbuf[1024]; HKEY hkey; long rc; int ok = JK_TRUE; rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD) 0, KEY_READ, &hkey); if (ERROR_SUCCESS != rc) return JK_FALSE; if (GetRegParam(hkey, JK_LOG_FILE_TAG, tmpbuf, sizeof (logFile))) strcpy(logFile, tmpbuf); else ok = JK_FALSE; if (GetRegParam(hkey, JK_LOG_LEVEL_TAG, tmpbuf, sizeof (tmpbuf))) logLevel = jk_parse_log_level(tmpbuf); else ok = JK_FALSE; if (GetRegParam(hkey, JK_WORKER_FILE_TAG, tmpbuf, sizeof (workerFile))) strcpy(workerFile, tmpbuf); else ok = JK_FALSE; if (GetRegParam(hkey, JK_MOUNT_FILE_TAG, tmpbuf, sizeof (workerMountFile))) strcpy(workerMountFile, tmpbuf); else ok = JK_FALSE; /* Get the commands that will start and stop Tomcat. We're not too bothered * if they don't exist. */ tomcatStart[0] = '\0'; if (GetRegParam(hkey, TOMCAT_START, tmpbuf, sizeof (tomcatStart))) strcpy(tomcatStart, tmpbuf); tomcatStop[0] = '\0'; if (GetRegParam(hkey, TOMCAT_STOP, tmpbuf, sizeof (tomcatStop))) strcpy(tomcatStop, tmpbuf); RegCloseKey(hkey); return ok; } static int GetRegParam(HKEY hkey, const char *tag, char *b, DWORD sz) { DWORD type = 0; LONG lrc; lrc = RegQueryValueEx(hkey, tag, (LPDWORD) 0, &type, (LPBYTE) b, &sz); if (ERROR_SUCCESS != lrc || type != REG_SZ) return JK_FALSE; b[sz] = '\0'; //printf("%s = %s\n", tag, b); return JK_TRUE; } /* Main entry point for the filter. Called by Domino for every HTTP request. */ DLLEXPORT unsigned int HttpFilterProc(FilterContext *context, unsigned int eventType, void *eventData) { if (initDone) { switch (eventType) { case kFilterParsedRequest: return ParsedRequest(context, (FilterParsedRequest *) eventData); default: break; } } return kFilterNotHandled; } /* Send a simple response. Used when we don't want to bother Tomcat, * which in practice means for various error conditions that we can * detect internally. */ static void SimpleResponse(FilterContext *context, int status, char *reason, char *body) { FilterResponseHeaders frh; int rc, errID; char hdrBuf[40]; sprintf(hdrBuf, "Content-type: text/html%s%s", crlf, crlf); frh.responseCode = status; frh.reasonText = reason; frh.headerText = hdrBuf; rc = context->ServerSupport(context, kWriteResponseHeaders, &frh, NULL, 0, &errID); rc = context->WriteClient(context, body, strlen(body), 0, &errID); } /* Called to reject a URI that contains the string "web-inf". We block * these because they may indicate an attempt to invoke arbitrary code. */ static unsigned int RejectBadURI(FilterContext *context) { static char *msg = "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>"; SimpleResponse(context, 403, "Forbidden", msg); return kFilterHandledRequest; } /* Get the value of a server (CGI) variable as a string */ static int GetVariable(private_ws_t *ws, char *hdrName, char *buf, DWORD bufsz, char **dest, const char *dflt) { int errID; if (ws->context->GetServerVariable(ws->context, hdrName, buf, bufsz, &errID)) *dest = jk_pool_strdup(&ws->p, buf); else *dest = jk_pool_strdup(&ws->p, dflt); //printf("%s = %s\n", hdrName, *dest); return JK_TRUE; } /* Get the value of a server (CGI) variable as an integer */ static int GetVariableInt(private_ws_t *ws, char *hdrName, char *buf, DWORD bufsz, int *dest, int dflt) { int errID; if (ws->context->GetServerVariable(ws->context, hdrName, buf, bufsz, &errID)) *dest = atoi(buf); else *dest = dflt; //printf("%s = %d\n", hdrName, *dest); return JK_TRUE; } /* A couple of utility macros to supply standard arguments to GetVariable() and * GetVariableInt(). */ #define GETVARIABLE(name, dest, dflt) GetVariable(ws, (name), workBuf, sizeof(workBuf), (dest), (dflt)) #define GETVARIABLEINT(name, dest, dflt) GetVariableInt(ws, (name), workBuf, sizeof(workBuf), (dest), (dflt)) /* Allocate space for a string given a start pointer and an end pointer * and return a pointer to the allocated, copied string. */ static char *MemDup(private_ws_t *ws, const char *start, const char *end) { char *out = NULL; if (start != NULL && end != NULL && end > start) { int len = end - start; out = jk_pool_alloc(&ws->p, len + 1); memcpy(out, start, len); out[len] = '\0'; } return out; } /* Given all the HTTP headers as a single string parse them into individual * name, value pairs. Called twice: once to work out how many headers there * are, then again to copy them. */ static int ParseHeaders(private_ws_t *ws, const char *hdrs, int hdrsz, jk_ws_service_t *s) { int hdrCount = 0; const char *limit = hdrs + hdrsz; const char *name, *nameEnd; const char *value, *valueEnd; while (hdrs < limit) { /* Skip line *before* doing anything, cos we want to lose the first line which * contains the request. */ while (hdrs < limit && (*hdrs != '\n' && *hdrs != '\r')) hdrs++; while (hdrs < limit && (*hdrs == '\n' || *hdrs == '\r')) hdrs++; if (hdrs >= limit) break; name = nameEnd = value = valueEnd = NULL; name = hdrs; while (hdrs < limit && *hdrs >= ' ' && *hdrs != ':') hdrs++; nameEnd = hdrs; if (hdrs < limit && *hdrs == ':') { hdrs++; while (hdrs < limit && (*hdrs == ' ' || *hdrs == '\t')) hdrs++; value = hdrs; while (hdrs < limit && *hdrs >= ' ') hdrs++; valueEnd = hdrs; } if (s->headers_names != NULL && s->headers_values != NULL) { s->headers_names[hdrCount] = MemDup(ws, name, nameEnd); s->headers_values[hdrCount] = MemDup(ws, value, valueEnd); //printf("%s = %s\n", s->headers_names[hdrCount], s->headers_values[hdrCount]); } hdrCount++; } return hdrCount; } /* Set up all the necessary jk_* workspace based on the current HTTP request. */ static int InitService(private_ws_t *ws, jk_ws_service_t *s) { char workBuf[16 * 1024]; FilterRequest fr; char *hdrs, *qp; int hdrsz; int errID; int hdrCount; int rc; static char *methodName[] = { "", "HEAD", "GET", "POST", "PUT", "DELETE" }; rc = ws->context->GetRequest(ws->context, &fr, &errID); s->jvm_route = NULL; s->start_response = StartResponse; s->read = Read; s->write = Write; s->req_uri = jk_pool_strdup(&ws->p, fr.URL); s->query_string = NULL; if (qp = strchr(s->req_uri, '?'), qp != NULL) { *qp++ = '\0'; if (strlen(qp)) s->query_string = qp; } GETVARIABLE("AUTH_TYPE", &s->auth_type, ""); GETVARIABLE("REMOTE_USER", &s->remote_user, ""); GETVARIABLE("SERVER_PROTOCOL", &s->protocol, ""); GETVARIABLE("REMOTE_HOST", &s->remote_host, ""); GETVARIABLE("REMOTE_ADDR", &s->remote_addr, ""); GETVARIABLE("SERVER_NAME", &s->server_name, ""); GETVARIABLEINT("SERVER_PORT", &s->server_port, 80); GETVARIABLE("SERVER_SOFTWARE", &s->server_software, "Lotus Domino"); GETVARIABLEINT("SERVER_PORT_SECURE", &s->is_ssl, 0); GETVARIABLEINT("CONTENT_LENGTH", &s->content_length, 0); // not tested s->method = methodName[ws->reqData->requestMethod]; s->ssl_cert = NULL; s->ssl_cert_len = 0; s->ssl_cipher = NULL; s->ssl_session = NULL; s->headers_names = NULL; s->headers_values = NULL; s->num_headers = 0; if (s->is_ssl) { char *sslNames[] = { "CERT_ISSUER", "CERT_SUBJECT", "CERT_COOKIE", "CERT_FLAGS", "CERT_SERIALNUMBER", "HTTPS_SERVER_SUBJECT", "HTTPS_SECRETKEYSIZE", "HTTPS_SERVER_ISSUER", "HTTPS_KEYSIZE" }; char *sslValues[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; unsigned i, varCount = 0; for (i = 0; i < sizeof(sslNames)/sizeof(sslNames[0]); i++) { GETVARIABLE(sslNames[i], &sslValues[i], NULL); if (sslValues[i]) varCount++; } if (varCount > 0) { unsigned j; s->attributes_names = jk_pool_alloc(&ws->p, varCount * sizeof (char *)); s->attributes_values = jk_pool_alloc(&ws->p, varCount * sizeof (char *)); j = 0; for (i = 0; i < sizeof(sslNames)/sizeof(sslNames[0]); i++) { if (sslValues[i]) { s->attributes_names[j] = sslNames[i]; s->attributes_values[j] = sslValues[i]; j++; } } s->num_attributes = varCount; } } /* Duplicate all the headers now */ hdrsz = ws->reqData->GetAllHeaders(ws->context, &hdrs, &errID); //printf("\nGot headers (length %d)\n--------\n%s\n--------\n\n", hdrsz, hdrs); s->headers_names = s->headers_values = NULL; hdrCount = ParseHeaders(ws, hdrs, hdrsz, s); //printf("Found %d headers\n", hdrCount); s->num_headers = hdrCount; s->headers_names = jk_pool_alloc(&ws->p, hdrCount * sizeof(char *)); s->headers_values = jk_pool_alloc(&ws->p, hdrCount * sizeof(char *)); hdrCount = ParseHeaders(ws, hdrs, hdrsz, s); return JK_TRUE; } /* Handle an HTTP request. Works out whether Tomcat will be interested then either * despatches it to Tomcat or passes it back to Domino. */ static unsigned int ParsedRequest(FilterContext *context, FilterParsedRequest *reqData) { unsigned int errID; int rc; FilterRequest fr; int result = kFilterNotHandled; //printf("\nParsedRequest starting\n"); rc = context->GetRequest(context, &fr, &errID); if (fr.URL && strlen(fr.URL)) { char *uri = fr.URL; char *workerName, *qp; if (qp = strchr(uri, '?'), qp != NULL) *qp = '\0'; workerName = map_uri_to_worker(uw_map, uri, logger); if (qp) *qp = '?'; //printf("Worker for this URL is %s\n", workerName); if (NULL != workerName) { private_ws_t ws; jk_ws_service_t s; jk_pool_atom_t buf[SMALL_POOL_SIZE]; if (BadURI(uri)) return RejectBadURI(context); /* Go dispatch the call */ jk_init_ws_service(&s); jk_open_pool(&ws.p, buf, sizeof (buf)); ws.responseStarted = JK_FALSE; ws.context = context; ws.reqData = reqData; ws.reqSize = context->GetRequestContents(context, &ws.reqBuffer, &errID); s.ws_private = &ws; s.pool = &ws.p; if (InitService(&ws, &s)) { jk_worker_t *worker = wc_get_worker_for_name(workerName, logger); jk_log(logger, JK_LOG_DEBUG, "HttpExtensionProc %s a worker for name %s\n", worker ? "got" : "could not get", workerName); if (worker) { jk_endpoint_t *e = NULL; if (worker->get_endpoint(worker, &e, logger)) { int recover = JK_FALSE; if (e->service(e, &s, logger, &recover)) { result = kFilterHandledRequest; jk_log(logger, JK_LOG_DEBUG, "HttpExtensionProc service() returned OK\n"); } else { result = kFilterError; jk_log(logger, JK_LOG_ERROR, "HttpExtensionProc error, service() failed\n"); } e->done(&e, logger); } } else { jk_log(logger, JK_LOG_ERROR, "HttpExtensionProc error, could not get a worker for name %s\n", workerName); } } jk_close_pool(&ws.p); } } return result; } 1.1 jakarta-tomcat-connectors/jk/src/native/domino/tomcat_redirector.reg Index: tomcat_redirector.reg =================================================================== REGEDIT4 [HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Dsapi Redirector\1.0] "log_file"="D:\\tomcat\\logs\\domino.log" "log_level"="debug" "worker_file"="D:\\tomcat\\conf\\workers.properties" "worker_mount_file"="D:\\tomcat\\conf\\uriworkermap.properties" "tomcat_start"="D:\\tomcat\\bin\\tomcat.bat start" "tomcat_stop"="D:\\tomcat\\bin\\tomcat.bat stop"