Return-Path: Delivered-To: apmail-jakarta-tomcat-dev-archive@jakarta.apache.org Received: (qmail 58588 invoked by uid 500); 25 Jun 2001 09:16:27 -0000 Mailing-List: contact tomcat-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: tomcat-dev@jakarta.apache.org Delivered-To: mailing list tomcat-dev@jakarta.apache.org Received: (qmail 58568 invoked by uid 500); 25 Jun 2001 09:16:25 -0000 Delivered-To: apmail-jakarta-tomcat-connectors-cvs@apache.org Date: 25 Jun 2001 09:16:24 -0000 Message-ID: <20010625091624.58555.qmail@apache.org> From: andya@apache.org To: jakarta-tomcat-connectors-cvs@apache.org Subject: cvs commit: jakarta-tomcat-connectors/jk/native/isapi tomcat_redirector.reg poolbuf.h poolbuf.c jk_isapi_plugin.c isapi.dsw isapi.dsp inifile.h inifile.c config.h andya 01/06/25 02:16:24 Added: jk/native/isapi tomcat_redirector.reg poolbuf.h poolbuf.c jk_isapi_plugin.c isapi.dsw isapi.dsp inifile.h inifile.c config.h Log: Experimental new ISAPI connector. Should build but not functional. Revision Changes Path 1.1 jakarta-tomcat-connectors/jk/native/isapi/tomcat_redirector.reg Index: tomcat_redirector.reg =================================================================== REGEDIT4 [HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Isapi Redirector\2.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" 1.1 jakarta-tomcat-connectors/jk/native/isapi/poolbuf.h Index: poolbuf.h =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation ." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact . * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see . * * * * ========================================================================= */ /*************************************************************************** * Description: ISAPI plugin for Tomcat * * Author: Andy Armstrong * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef __poolbuf_h #define __poolbuf_h #include #include "jk_pool.h" #define poolbuf__MINCHUNK 2048 typedef struct poolbuf__chunk { size_t size; struct poolbuf__chunk *next; } poolbuf__chunk; typedef enum { WRITE, READ } poolbuf__state; typedef struct { jk_pool_t *p; poolbuf__chunk *head; poolbuf__chunk *current; /* current state */ poolbuf__state state; /* total number of bytes available to read */ size_t avail; /* offsets within the current chunk */ unsigned int writePos; unsigned int readPos; } poolbuf; /* Initialise a poolbuf. */ void poolbuf_init(poolbuf *pb, jk_pool_t *p); size_t poolbuf_write(poolbuf *pb, const void *buf, size_t size); size_t poolbuf_read(poolbuf *pb, void *buf, size_t size); size_t poolbuf_available(poolbuf *pb); void poolbuf_destroy(poolbuf *pb); #endif /* __poolbuf_h */ 1.1 jakarta-tomcat-connectors/jk/native/isapi/poolbuf.c Index: poolbuf.c =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation ." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be avail to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact . * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see . * * * * ========================================================================= */ /*************************************************************************** * Description: ISAPI plugin for Tomcat * * Author: Andy Armstrong * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "poolbuf.h" /* Macro to return the address of the first byte in a poolbuf__chunk on * the understanding that the buffer follows the structure in memory. */ #define poolbuf__buf(chnk) \ ((char *) ((poolbuf__chunk *) chnk + 1)) void poolbuf_init(poolbuf *pb, jk_pool_t *p) { pb->p = p; pb->head = pb->current = NULL; pb->readPos = pb->writePos = 0; pb->avail = 0; pb->state = WRITE; } /* Write bytes to the buffer returning the number of bytes successfully * written. Can't be called again once poolbuf_read() has been called. */ size_t poolbuf_write(poolbuf *pb, const void *buf, size_t size) { const char *cbuf = (const char *) buf; size_t left = size; if (READ == pb->state) return 0; /* first work out what we can write into the current buffer */ if (pb->current != NULL && pb->writePos < pb->current->size) { char *chbuf = poolbuf__buf(pb->current) + pb->writePos; size_t sz = pb->current->size - pb->writePos; if (sz > left) sz = left; memcpy(chbuf, cbuf, sz); pb->writePos += sz; pb->avail += sz; cbuf += sz; left -= sz; } /* something left that we couldn't fit in the last chunk */ if (left > 0) { poolbuf__chunk *chnk; size_t sz = size; if (sz < poolbuf__MINCHUNK) sz = poolbuf__MINCHUNK; if (NULL == pb->p || NULL == (chnk = jk_pool_alloc(pb->p, sz + sizeof(poolbuf__chunk)))) return size - left; chnk->next = NULL; chnk->size = sz; if (NULL == pb->head) pb->head = chnk; if (NULL != pb->current) pb->current->next = chnk; pb->current = chnk; memcpy(poolbuf__buf(chnk), cbuf, left); pb->avail += left; pb->writePos = left; } return size; } /* Read bytes from the buffer returning the number of bytes read (which * will be less than desired when the end of the buffer is reached). Once * poolbuf_read() has been called poolbuf_write() may not be called again. */ size_t poolbuf_read(poolbuf *pb, void *buf, size_t size) { char *cbuf = (char *) buf; size_t nread = 0; if (WRITE == pb->state) { /* Move to read mode. Once we've done this subsequent * writes are not allowed. */ pb->current = pb->head; pb->readPos = 0; pb->state = READ; } while (size > 0 && pb->avail > 0) { size_t sz = pb->current->size - pb->readPos; if (sz > pb->avail) sz = pb->avail; if (sz > size) sz = size; memcpy(cbuf, poolbuf__buf(pb->current) + pb->readPos, sz); pb->readPos += sz; if (pb->readPos == pb->current->size) { pb->current = pb->current->next; pb->readPos = 0; } pb->avail -= sz; nread += sz; } return nread; } /* Find out how many bytes are available for reading. */ size_t poolbuf_available(poolbuf *pb) { return pb->avail; } /* Destroy the buffer. This doesn't actually free any memory * because the jk_pool functions don't support freeing individual * chunks, but it does recycle the buffer for subsequent use. */ void poolbuf_destroy(poolbuf *pb) { pb->p = NULL; pb->head = pb->current = NULL; pb->readPos = pb->writePos = 0; pb->avail = 0; pb->state = WRITE; } 1.1 jakarta-tomcat-connectors/jk/native/isapi/jk_isapi_plugin.c Index: jk_isapi_plugin.c =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation ." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact . * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see . * * * * ========================================================================= */ /*************************************************************************** * Description: ISAPI plugin for Tomcat * * Author: Andy Armstrong * * Version: $Revision: 1.1 $ * ***************************************************************************/ /* Based on the the server redirector which was, in turn, based on the IIS * redirector by Gal Shachor */ #include "config.h" #include "inifile.h" #include "poolbuf.h" /* ISAPI stuff */ #include #include #include /* 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" #include #define NOERROR 0 #include #include #include #if !defined(DLLEXPORT) #ifdef WIN32 #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif #endif #define VERSION "2.0" #define VERSION_STRING "Jakarta/ISAPI/" VERSION /* What we call ourselves */ #define FILTERDESC "Apache Tomcat Interceptor (" VERSION_STRING ")" #define SERVERDFLT "Microsoft IIS" /* Registry location of configuration data */ #define REGISTRY_LOCATION "Software\\Apache Software Foundation\\Jakarta Isapi Redirector\\2.0" /* Name of INI file relative to whatever the 'current' directory is when the filter is * loaded. Certainly on Linux this is the the server data directory -- it seems likely that * it's the same on other platforms */ #define ININAME "libtomcat.ini" /* Names of registry keys/ini items 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 jk_pool_t cfgPool; static const char *logFile; static const char *workerFile; static const char *workerMountFile; static const char *tomcatStart; static const char *tomcatStop; #if defined(JK_VERSION) && JK_VERSION >= MAKEVERSION(1, 2, 0, 1) static jk_worker_env_t worker_env; #endif static char *crlf = "\r\n"; typedef enum { HDR, BODY } rq_state; typedef struct private_ws { jk_pool_t p; /* Passed in by server, used to access various methods and data. */ LPEXTENSION_CONTROL_BLOCK lpEcb; /* True iff the response headers have been sent */ int responseStarted; rq_state state; poolbuf hdr; poolbuf body; } 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); #ifndef USE_INIFILE static const char *GetRegString(HKEY hkey, const char *key); #endif //static unsigned int ParsedRequest(PHTTP_FILTER_CONTEXT *context, FilterParsedRequest *reqData); /* Case insentive memcmp() clone */ #ifdef HAVE_MEMICMP #define NoCaseMemCmp(ci, cj, l) _memicmp((void *) (ci), (void *) (cj), (l)) #else static int NoCaseMemCmp(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 insentive strcmp() clone */ #ifdef HAVE_STRICMP #define NoCaseStrCmp(si, sj) _stricmp((void *) (si), (void *) (sj)) #else static int NoCaseStrCmp(const char *si, const char *sj) { if (0 == strcmp(si, sj)) return 0; while (*si && tolower(*si) == tolower(*sj)) si++, sj++; return tolower(*si) - tolower(*sj); } #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 FindPathElem(const char *str, int slen, const char *ptn, int plen) { const char *sp = str; while (slen >= plen) { /* We're looking for a match for the specified string bounded by * the start of the string, \ or / at the left and the end of the * string, \ or / at the right. We look for \ as well as / on the * suspicion that a Windows hosted server might accept URIs * containing \. */ if (NoCaseMemCmp(sp, ptn, plen) == 0 && (sp == str || *sp == '\\' || *sp == '/') && (*sp == '\0' || *sp == '\\' || *sp == '/')) return 1; slen--; sp++; } return 0; } static void LogMessage(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"); } /* 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) { LPEXTENSION_CONTROL_BLOCK lpEcb = ws->lpEcb; if (lpEcb->GetServerVariable(lpEcb->ConnID, hdrName, buf, (LPDWORD) &bufsz)) { if (bufsz > 0) buf[bufsz-1] = '\0'; *dest = jk_pool_strdup(&ws->p, buf); return JK_TRUE; } *dest = jk_pool_strdup(&ws->p, dflt); return JK_FALSE; } /* 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) { LPEXTENSION_CONTROL_BLOCK lpEcb = ws->lpEcb; if (lpEcb->GetServerVariable(lpEcb->ConnID, hdrName, buf, (LPDWORD) &bufsz)) { if (bufsz > 0) buf[bufsz-1] = '\0'; *dest = atoi(buf); return JK_TRUE; } *dest = dflt; return JK_FALSE; } /* Get the value of a server (CGI) variable as a boolean switch */ static int GetVariableBool(private_ws_t *ws, char *hdrName, char *buf, DWORD bufsz, int *dest, int dflt) { LPEXTENSION_CONTROL_BLOCK lpEcb = ws->lpEcb; if (lpEcb->GetServerVariable(lpEcb->ConnID, hdrName, buf, (LPDWORD) &bufsz)) { if (bufsz > 0) buf[bufsz-1] = '\0'; if (isdigit(buf[0])) *dest = atoi(buf) != 0; else if (NoCaseStrCmp(buf, "yes") == 0 || NoCaseStrCmp(buf, "on") == 0) *dest = 1; else *dest = 0; return JK_TRUE; } *dest = dflt; return JK_FALSE; } /* 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)) #define GETVARIABLEBOOL(name, dest, dflt) GetVariableBool(ws, (name), workBuf, sizeof(workBuf), (dest), (dflt)) /* Return 1 iff the supplied string contains "web-inf" (in any case * variation. We don't allow URIs containing web-inf, although * FindPathElem() actually looks for the string bounded by path punctuation * or the ends of the string, so web-inf must appear as a single element * of the supplied URI */ static int BadURI(const char *uri) { static char *wi = "web-inf"; return FindPathElem(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) { DEBUG(("StartResponse()\n")); 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 *statBuf; char *hdrBuf; size_t statLen; p->responseStarted = JK_TRUE; if (NULL == reason) reason = ""; /* TODO: coallesce the to jk_pool_alloc() calls into a single * buffer alloc */ statLen = 4 + strlen(reason); statBuf = jk_pool_alloc(&p->p, statLen + 1); /* slightly quicker than sprintf() we hope */ statBuf[0] = (status / 100) % 10 + '0'; statBuf[1] = (status / 10) % 10 + '0'; statBuf[2] = (status / 1) % 10 + '0'; statBuf[3] = ' '; strcpy(statBuf + 4, reason); /* Build a single string containing all the headers * because that's what the server 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; } DEBUG(("%d %s\n%s", status, reason, hdrBuf)); /* TODO: check API docs for this */ if (!p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, statBuf, (LPDWORD) &statLen, (LPDWORD) hdrBuf)) { jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::start_response, 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) { #if 0 DEBUG(("Read(%p, %p, %u, %p)\n", s, bytes, len, 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 the server's buffer. Although it seems slightly * improbably we're believing that the server 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"); #endif return JK_FALSE; } static int JK_METHOD Write(jk_ws_service_t *s, const void *bytes, unsigned len) { DEBUG(("Write(%p, %p, %u)\n", s, bytes, 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; DWORD dwLen = len; /* 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); DEBUG(("Writing %d bytes of content\n", len)); /* Send the data */ if (len > 0) { if (!p->lpEcb->WriteClient(p->lpEcb->ConnID, (LPVOID) bytes, &dwLen, 0)) { jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::Write, WriteClient failed\n"); return JK_FALSE; } } return JK_TRUE; } jk_log(logger, JK_LOG_ERROR, "jk_ws_service_t::Write, NULL parameters\n"); return JK_FALSE; } static int RunProg(const char *cmd) { #ifdef WIN32 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, (char *) cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { DWORD err = GetLastError(); LogMessage("Command \"%s\" (error %u)", NOERROR, cmd, err); return FALSE; } if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, TOMCAT_STARTSTOP_TO)) return TRUE; LogMessage("Command \"%s\" didn't complete in time", NOERROR, cmd); return FALSE; #else int err = system(cmd); if (0 == err) return 1; LogMessage("Command \"%s\" failed (error %d)", NOERROR, cmd, err); return 0; #endif } /* Called when the filter is unloaded. Free various resources and * display a banner. */ BOOL WINAPI TerminateFilter(DWORD dwFlags) { if (initDone) { uri_worker_map_free(&uw_map, logger); wc_close(logger); if (logger) jk_close_file_logger(&logger); initDone = JK_FALSE; } if (NULL != tomcatStop && '\0' != *tomcatStop) { LogMessage("Attempting to stop Tomcat: %s", NOERROR, tomcatStop); RunProg(tomcatStop); } LogMessage(FILTERDESC " unloaded", NOERROR); jk_close_pool(&cfgPool); return TRUE; } /* Called when the server loads the filter. Reads a load of config data from * the registry and elsewhere and displays a banner. */ BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer) { jk_open_pool(&cfgPool, NULL, 0); /* empty pool for config data */ if (!ReadInitData()) goto initFailed; if (!jk_open_file_logger(&logger, logFile, logLevel)) logger = NULL; if (NULL != tomcatStart && '\0' != *tomcatStart) { LogMessage("Attempting to start Tomcat: %s", NOERROR, tomcatStart); RunProg(tomcatStart); } pVer->dwFilterVersion = pVer->dwServerFilterVersion; //if (pVer->dwFilterVersion > HTTP_FILTER_REVISION) // pVer->dwFilterVersion = HTTP_FILTER_REVISION; /* Come back and check these... */ pVer->dwFlags = SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT | SF_NOTIFY_PREPROC_HEADERS; strcpy(pVer->lpszFilterDesc, FILTERDESC); /* Banner */ LogMessage("%s loaded", NOERROR, pVer->lpszFilterDesc); return TRUE; initFailed: LogMessage("Error loading %s", NOERROR, FILTERDESC); return FALSE; } /* Read parameters from the registry */ static int ReadInitData(void) { int ok = JK_TRUE; const char *v; #ifdef USE_INIFILE // Using an INIFILE #define GETV(key) inifile_lookup(key) ERRTYPE e; if (e = inifile_read(&cfgPool, ININAME), ERRNONE != e) { LogMessage("Error reading: %s, %s", NOERROR, ININAME, ERRTXT(e)); return JK_FALSE; } #else // Using the registry #define GETV(key) GetRegString(hkey, key) HKEY hkey; long rc; rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD) 0, KEY_READ, &hkey); if (ERROR_SUCCESS != rc) return JK_FALSE; #endif #define GETVNB(tag, var) \ var = GETV(tag); \ if (NULL == var) \ { \ LogMessage("%s not defined in %s", NOERROR, tag, ININAME); \ ok = JK_FALSE; \ } GETVNB(JK_LOG_FILE_TAG, logFile) GETVNB(JK_LOG_LEVEL_TAG, v); GETVNB(JK_WORKER_FILE_TAG, workerFile); GETVNB(JK_MOUNT_FILE_TAG, workerMountFile); logLevel = (NULL == v) ? 0 : jk_parse_log_level(v); tomcatStart = GETV(TOMCAT_START); tomcatStop = GETV(TOMCAT_STOP); #ifndef USE_INIFILE RegCloseKey(hkey); #endif return ok; } #ifndef USE_INIFILE static const char *GetRegString(HKEY hkey, const char *key) { DWORD type = 0; DWORD sz = 0; LONG rc; char *val; rc = RegQueryValueEx(hkey, key, (LPDWORD) 0, &type, NULL, &sz); if (rc != ERROR_SUCCESS || type != REG_SZ) return NULL; if (val = jk_pool_alloc(&cfgPool, sz), NULL == val) return NULL; rc = RegQueryValueEx(hkey, key, (LPDWORD) 0, &type, val, &sz); if (rc == ERROR_SUCCESS) return val; return NULL; } #endif /* Main entry point for the filter. Called by the server for every HTTP request. */ DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD dwNotificationType, LPVOID pvNotification) { #if 0 switch (dwNotificationType) { case kFilterParsedRequest: return ParsedRequest(context, (FilterParsedRequest *) eventData); default: break; } return kFilterNotHandled; #endif return SF_STATUS_REQ_NEXT_NOTIFICATION; } /* 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(PHTTP_FILTER_CONTEXT *context, int status, char *reason, char *body) { #if 0 FilterResponseHeaders frh; int rc, errID; char hdrBuf[35]; 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); #endif } /* 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 DWORD RejectBadURI(PHTTP_FILTER_CONTEXT *context) { static char *msg = "

Access is Forbidden

"; SimpleResponse(context, 403, "Forbidden", msg); return SF_STATUS_REQ_NEXT_NOTIFICATION; } /* 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); DEBUG(("%s = %s\n", s->headers_names[hdrCount], s->headers_values[hdrCount])); } hdrCount++; } return hdrCount; } #if 0 /* 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) { /* This is the only fixed size buffer left. It won't be overflowed * because the the server API that reads into the buffer accepts a length * constraint, and it's unlikely ever to be exhausted because the * strings being will typically be short, but it's still aesthetically * troublesome. */ char workBuf[16 * 1024]; FilterRequest fr; char *hdrs, *qp; int hdrsz; int errID; int hdrCount; int rc /*, dummy*/; 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, SERVERDFLT); GETVARIABLEINT("CONTENT_LENGTH", &s->content_length, 0); /* SSL Support */ GETVARIABLEBOOL("HTTPS", &s->is_ssl, 0); if (ws->reqData->requestMethod < 0 || ws->reqData->requestMethod >= sizeof(methodName) / sizeof(methodName[0])) return JK_FALSE; s->method = methodName[ws->reqData->requestMethod]; s->headers_names = NULL; s->headers_values = NULL; s->num_headers = 0; s->ssl_cert_len = fr.clientCertLen; s->ssl_cert = fr.clientCert; s->ssl_cipher = NULL; /* required by Servlet 2.3 Api */ s->ssl_session = NULL; #if defined(JK_VERSION) && JK_VERSION >= MAKEVERSION(1, 2, 0, 1) s->ssl_key_size = -1; /* required by Servlet 2.3 Api, added in jtc */ #endif if (s->is_ssl) { int dummy; #if 0 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; #endif DEBUG(("SSL request\n")); #if defined(JK_VERSION) && JK_VERSION >= MAKEVERSION(1, 2, 0, 1) /* Read the variable into a dummy variable: we do this for the side effect of * reading it into workBuf. */ GETVARIABLEINT("HTTPS_KEYSIZE", &dummy, 0); if (workBuf[0] == '[') s->ssl_key_size = atoi(workBuf+1); #else (void) dummy; #endif #if 0 for (i = 0; i < sizeof(sslNames)/sizeof(sslNames[0]); i++) { GETVARIABLE(sslNames[i], &sslValues[i], NULL); if (sslValues[i]) varCount++; } /* Andy, some SSL vars must be mapped directly in s->ssl_cipher, * ssl->session and s->ssl_key_size * ie: * Cipher could be "RC4-MD5" * KeySize 128 (bits) * SessionID a string containing the UniqID used in SSL dialogue */ 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; } #endif } /* Duplicate all the headers now */ hdrsz = ws->reqData->GetAllHeaders(ws->context, &hdrs, &errID); DEBUG(("\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); DEBUG(("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; } #endif #if 0 /* Handle an HTTP request. Works out whether Tomcat will be interested then either * despatches it to Tomcat or passes it back to the server. */ static unsigned int ParsedRequest(PHTTP_FILTER_CONTEXT *context, FilterParsedRequest *reqData) { unsigned int errID; int rc; FilterRequest fr; int result = kFilterNotHandled; DEBUG(("\nParsedRequest starting\n")); rc = context->GetRequest(context, &fr, &errID); if (fr.URL && strlen(fr.URL)) { char *uri = fr.URL; char *workerName, *qp; if (!initDone) { /* One time initialisation which is deferred so that we have the name of * the server software to plug into worker_env */ int ok = JK_FALSE; jk_map_t *map = NULL; DEBUG(("Initialising worker map\n")); if (map_alloc(&map)) { if (map_read_properties(map, workerMountFile)) if (uri_worker_map_alloc(&uw_map, map, logger)) ok = JK_TRUE; map_free(&map); } DEBUG(("Got the URI worker map\n")); if (ok) { ok = JK_FALSE; DEBUG(("About to allocate map\n")); if (map_alloc(&map)) { DEBUG(("About to read %s\n", workerFile)); if (map_read_properties(map, workerFile)) { #if defined(JK_VERSION) && JK_VERSION >= MAKEVERSION(1, 2, 0, 1) char server[256]; worker_env.uri_to_worker = uw_map; if (context->GetServerVariable(context, "SERVER_SOFTWARE", server, sizeof(server)-1, &errID)) worker_env.server_name = jk_pool_strdup(&cfgPool, server); else worker_env.server_name = SERVERDFLT; DEBUG(("Server name %s\n", worker_env.server_name)); if (wc_open(map, &worker_env, logger)) ok = JK_TRUE; #else if (wc_open(map, logger)) ok = JK_TRUE; #endif DEBUG(("OK = %d\n", ok)); } DEBUG(("Read %s, OK = %d\n", workerFile, ok)); map_free(&map); } } if (!ok) return kFilterError; initDone = JK_TRUE; } if (qp = strchr(uri, '?'), qp != NULL) *qp = '\0'; workerName = map_uri_to_worker(uw_map, uri, logger); if (qp) *qp = '?'; DEBUG(("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"); DEBUG(("HttpExtensionProc service() returned OK\n")); } else { result = kFilterError; jk_log(logger, JK_LOG_ERROR, "HttpExtensionProc error, service() failed\n"); DEBUG(("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; } #endif BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason, LPVOID lpReserved) { BOOL fReturn = TRUE; switch (ulReason) { case DLL_PROCESS_DETACH: TerminateFilter(HSE_TERM_MUST_UNLOAD); break; default: break; } return fReturn; } 1.1 jakarta-tomcat-connectors/jk/native/isapi/isapi.dsw Index: isapi.dsw =================================================================== Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "isapi"=".\isapi.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### 1.1 jakarta-tomcat-connectors/jk/native/isapi/isapi.dsp Index: isapi.dsp =================================================================== # Microsoft Developer Studio Project File - Name="isapi" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=isapi - 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 "isapi.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 "isapi.mak" CFG="isapi - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "isapi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "isapi - 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)" == "isapi - 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 "isapi_EXPORTS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_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" !ELSEIF "$(CFG)" == "isapi - 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 "isapi_EXPORTS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_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 "isapi - Win32 Release" # Name "isapi - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\inifile.c # End Source File # Begin Source File SOURCE=..\common\jk_ajp12_worker.c # End Source File # Begin Source File SOURCE=..\common\jk_ajp13.c # End Source File # Begin Source File SOURCE=..\common\jk_ajp13_worker.c # End Source File # Begin Source File SOURCE=..\common\jk_ajp14.c # End Source File # Begin Source File SOURCE=..\common\jk_ajp14_worker.c # End Source File # Begin Source File SOURCE=..\common\jk_ajp_common.c # End Source File # Begin Source File SOURCE=..\common\jk_connect.c # End Source File # Begin Source File SOURCE=..\common\jk_context.c # End Source File # Begin Source File SOURCE=.\jk_isapi_plugin.c # End Source File # Begin Source File SOURCE=..\common\jk_jni_worker.c # End Source File # Begin Source File SOURCE=..\common\jk_lb_worker.c # End Source File # Begin Source File SOURCE=..\common\jk_map.c # End Source File # Begin Source File SOURCE=..\common\jk_md5.c # End Source File # Begin Source File SOURCE=..\common\jk_msg_buff.c # End Source File # Begin Source File SOURCE=..\common\jk_nwmain.c # End Source File # Begin Source File SOURCE=..\common\jk_pool.c # End Source File # Begin Source File SOURCE=..\common\jk_sockbuf.c # End Source File # Begin Source File SOURCE=..\common\jk_uri_worker_map.c # End Source File # Begin Source File SOURCE=..\common\jk_util.c # End Source File # Begin Source File SOURCE=..\common\jk_worker.c # End Source File # Begin Source File SOURCE=.\poolbuf.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=.\inifile.h # End Source File # Begin Source File SOURCE=.\isapifilter.h # End Source File # Begin Source File SOURCE=..\common\jk_ajp12_worker.h # End Source File # Begin Source File SOURCE=..\common\jk_ajp13.h # End Source File # Begin Source File SOURCE=..\common\jk_ajp13_worker.h # End Source File # Begin Source File SOURCE=..\common\jk_ajp14.h # End Source File # Begin Source File SOURCE=..\common\jk_ajp14_worker.h # End Source File # Begin Source File SOURCE=..\common\jk_ajp_common.h # End Source File # Begin Source File SOURCE=..\common\jk_connect.h # End Source File # Begin Source File SOURCE=..\common\jk_context.h # End Source File # Begin Source File SOURCE=..\common\jk_global.h # End Source File # Begin Source File SOURCE=..\common\jk_jni_worker.h # End Source File # Begin Source File SOURCE=..\common\jk_lb_worker.h # End Source File # Begin Source File SOURCE=..\common\jk_logger.h # End Source File # Begin Source File SOURCE=..\common\jk_map.h # End Source File # Begin Source File SOURCE=..\common\jk_md5.h # End Source File # Begin Source File SOURCE=..\common\jk_msg_buff.h # End Source File # Begin Source File SOURCE=..\common\jk_mt.h # End Source File # Begin Source File SOURCE=..\common\jk_pool.h # End Source File # Begin Source File SOURCE=..\common\jk_service.h # End Source File # Begin Source File SOURCE=..\common\jk_sockbuf.h # End Source File # Begin Source File SOURCE=..\common\jk_uri_worker_map.h # End Source File # Begin Source File SOURCE=..\common\jk_util.h # End Source File # Begin Source File SOURCE=..\common\jk_worker.h # End Source File # Begin Source File SOURCE=..\common\jk_worker_list.h # End Source File # Begin Source File SOURCE=.\poolbuf.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/native/isapi/inifile.h Index: inifile.h =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation ." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact . * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see . * * * * ========================================================================= */ /*************************************************************************** * Description: DSAPI plugin for Lotus Domino * * Author: Andy Armstrong * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef __inifile_h #define __inifile_h #include "jk_pool.h" #define ERRTYPE const char * #define ERRFMT "%s" /* natural printf format for errors */ #define ERRTXT(e) (e) /* macro to return text for an error */ #define ERRNONE NULL extern ERRTYPE inifile_outofmemory; extern ERRTYPE inifile_filenotfound; extern ERRTYPE inifile_readerror; /* Read an INI file from disk */ ERRTYPE inifile_read(jk_pool_t *pool, const char *name); /* Find the value associated with the given key returning it or NULL * if no match is found. Key name matching is case insensitive. */ const char *inifile_lookup(const char *key); #endif /* __inifile_h */ 1.1 jakarta-tomcat-connectors/jk/native/isapi/inifile.c Index: inifile.c =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation ." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact . * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see . * * * * ========================================================================= */ /*************************************************************************** * Description: DSAPI plugin for Lotus Domino * * Author: Andy Armstrong * * Date: 20010603 * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "config.h" #include "inifile.h" #include #include #include #include /* We have one of these for each ini file line. Once we've read the * file and parsed it we'll have an array in key order containing one * of these for each configuration item in file. */ typedef struct { const char *key; const char *value; } inifile_key; static char *file; /* the text of the ini file */ static inifile_key *keys; /* an array of keys, one per item */ static size_t klen; /* length of the key array */ /* Text that will prefix all of our error messages */ #define ERRPFX "INIFILE: " /* Various error messages that we can return */ ERRTYPE inifile_outofmemory = ERRPFX "Out of memory"; ERRTYPE inifile_filenotfound = ERRPFX "File not found"; ERRTYPE inifile_readerror = ERRPFX "Error reading file"; #define SYNFMT ERRPFX "File %s, line %d: %s" /* Case insensitive string comparison, works like strcmp() */ static int inifile__stricmp(const char *s1, const char *s2) { while (*s1 && tolower(*s1) == tolower(*s2)) s1++, s2++; return tolower(*s1) - tolower(*s2); } /* Compare keys, suitable for passing to qsort() */ static int inifile__cmp(const void *k1, const void *k2) { const inifile_key *kk1 = (const inifile_key *) k1; const inifile_key *kk2 = (const inifile_key *) k2; return inifile__stricmp(kk1->key, kk2->key); } /* Return a new syntax error message. */ static ERRTYPE inifile__syntax(jk_pool_t *p, const char *file, int line, const char *msg) { static const char synfmt[] = SYNFMT; size_t len = sizeof(synfmt) + strlen(msg) + strlen(file) + 10 /* fudge for line number */; char *buf = jk_pool_alloc(p, len); sprintf(buf, synfmt, file, line, msg); return buf; } /* Various macros to tidy up the parsing code */ /* Characters that are OK in the keyname */ #define KEYCHR(c) \ (isalnum(c) || (c) == '.' || (c) == '_') /* Skip whitespace */ #define SKIPSPC() \ while (*fp == '\t' || *fp == ' ') fp++ /* Skip to the end of the current line */ #define SKIPLN() \ while (*fp != '\0' && *fp != '\r' && *fp != '\n') fp++ /* Move from the end of the current line to the start of the next, learning what the * newline character is and counting lines */ #define NEXTLN() \ do { while (*fp == '\r' || *fp == '\n') { if (nlc == -1) nlc = *fp; if (*fp == nlc) ln++; fp++; } } while (0) /* Build the index. Called when the inifile is loaded by inifile_load() */ static ERRTYPE inifile__index(jk_pool_t *p, const char *name) { int pass; int ln = 1; int nlc = -1; /* Make two passes over the data. First time we're just counting * the lines that contain values so we can allocate the index, second * time we build the index. */ for (pass = 0; pass < 2; pass++) { char *fp = file; char *ks = NULL, *ke; /* key start, end */ char *vs = NULL, *ve; /* value start, end */ klen = 0; while (*fp != '\0') { SKIPSPC(); /* turn a comment into an empty line by moving to the next \r|\n */ if (*fp == '#' || *fp == ';') SKIPLN(); if (*fp != '\0' && *fp != '\r' && *fp != '\n') { ks = fp; /* start of key */ while (KEYCHR(*fp)) fp++; ke = fp; /* end of key */ SKIPSPC(); if (*fp != '=') return inifile__syntax(p, name, ln, "Missing '=' or illegal character in key"); fp++; /* past the = */ SKIPSPC(); vs = fp; SKIPLN(); ve = fp; /* back up over any trailing space */ while (ve > vs && (ve[-1] == ' ' || ve[-1] == '\t')) ve--; NEXTLN(); /* move forwards *before* we trash the eol characters */ if (NULL != keys) /* second pass? if so stash a pointer */ { *ke = '\0'; *ve = '\0'; keys[klen].key = ks; keys[klen].value = vs; } klen++; } else { NEXTLN(); } } if (NULL == keys && (keys = jk_pool_alloc(p, sizeof(inifile_key) * klen), NULL == keys)) return inifile_outofmemory; } /* got the index now, sort it so we can search it quickly */ qsort(keys, klen, sizeof(inifile_key), inifile__cmp); return ERRNONE; } /* Read an INI file from disk */ ERRTYPE inifile_read(jk_pool_t *p, const char *name) { FILE *fl; size_t flen; int ok; if (fl = fopen(name, "rb"), NULL == fl) return inifile_filenotfound; fseek(fl, 0L, SEEK_END); flen = (size_t) ftell(fl); fseek(fl, 0L, SEEK_SET); /* allocate one extra byte for trailing \0 */ if (file = jk_pool_alloc(p, flen+1), NULL == file) { fclose(fl); return inifile_outofmemory; } ok = (fread(file, flen, 1, fl) == 1); fclose(fl); if (!ok) return inifile_readerror; file[flen] = '\0'; /* terminate it to simplify parsing */ return inifile__index(p, name); } /* Find the value associated with the given key returning it or NULL * if no match is found. Key name matching is case insensitive. */ const char *inifile_lookup(const char *key) { int lo, mid, hi, cmp; if (NULL == keys) return NULL; for (lo = 0, hi = klen-1; lo <= hi; ) { mid = (lo + hi) / 2; cmp = inifile__stricmp(key, keys[mid].key); if (cmp < 0) /* key in array is greater */ hi = mid-1; else if (cmp > 0) lo = mid+1; else return keys[mid].value; } return NULL; } #ifdef TEST static jk_pool_t pool; extern void jk_dump_pool(jk_pool_t *p, FILE *f); /* not declared in header */ int main(void) { ERRTYPE e; unsigned k; int rc = 0; jk_open_pool(&pool, NULL, 0); e = inifile_read(&pool, "ok.ini"); if (e == ERRNONE) { printf("%u keys in ok.ini\n", klen); for (k = 0; k < klen; k++) { const char *val = inifile_lookup(keys[k].key); printf("Key: \"%s\", value: \"%s\"\n", keys[k].key, val); } } else { printf("Error reading ok.ini: %s\n", e); rc = 1; } e = inifile_read(&pool, "bad.ini"); if (e == ERRNONE) { printf("%u keys in bad.ini\n", klen); for (k = 0; k < klen; k++) { const char *val = inifile_lookup(keys[k].key); printf("Key: \"%s\", value: \"%s\"\n", keys[k].key, val); } rc = 1; /* should be a syntax error */ } else { printf("Error reading bad.ini: %s (which is OK: that's what we expected)\n", e); } jk_dump_pool(&pool, stdout); jk_close_pool(&pool); return rc; } #endif 1.1 jakarta-tomcat-connectors/jk/native/isapi/config.h Index: config.h =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation ." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact . * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see . * * * * ========================================================================= */ /*************************************************************************** * Description: ISAPI plugin for Tomcat * * Author: Andy Armstrong * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef __config_h #define __config_h #define MAKEVERSION(a, b, c, d) \ (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) /* the _memicmp() function is available */ #if defined(WIN32) #define HAVE_MEMICMP #undef USE_INIFILE #elif defined(LINUX) #undef HAVE_MEMICMP #define USE_INIFILE #else #error Please define either WIN32 or LINUX #endif #define DEBUG(args) \ do { /*printf args ;*/ } while (0) #endif /* __config_h */