You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by an...@apache.org on 2001/06/25 11:16:24 UTC
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 <http://www.apache.org/>." *
* *
* 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 <ap...@apache.org>. *
* *
* 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 <http://www.apache.org/>. *
* *
* ========================================================================= */
/***************************************************************************
* Description: ISAPI plugin for Tomcat *
* Author: Andy Armstrong <an...@tagish.com> *
* Version: $Revision: 1.1 $ *
***************************************************************************/
#ifndef __poolbuf_h
#define __poolbuf_h
#include <stddef.h>
#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 <http://www.apache.org/>." *
* *
* 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 <ap...@apache.org>. *
* *
* 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 <http://www.apache.org/>. *
* *
* ========================================================================= */
/***************************************************************************
* Description: ISAPI plugin for Tomcat *
* Author: Andy Armstrong <an...@tagish.com> *
* 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 <http://www.apache.org/>." *
* *
* 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 <ap...@apache.org>. *
* *
* 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 <http://www.apache.org/>. *
* *
* ========================================================================= */
/***************************************************************************
* Description: ISAPI plugin for Tomcat *
* Author: Andy Armstrong <an...@tagish.com> *
* Version: $Revision: 1.1 $ *
***************************************************************************/
/* Based on the the server redirector which was, in turn, based on the IIS
* redirector by Gal Shachor <sh...@il.ibm.com>
*/
#include "config.h"
#include "inifile.h"
#include "poolbuf.h"
/* ISAPI stuff */
#include <httpext.h>
#include <httpfilt.h>
#include <wininet.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"
#include <stdarg.h>
#define NOERROR 0
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 = "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>";
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 <http://www.apache.org/>." *
* *
* 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 <ap...@apache.org>. *
* *
* 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 <http://www.apache.org/>. *
* *
* ========================================================================= */
/***************************************************************************
* Description: DSAPI plugin for Lotus Domino *
* Author: Andy Armstrong <an...@tagish.com> *
* 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 <http://www.apache.org/>." *
* *
* 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 <ap...@apache.org>. *
* *
* 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 <http://www.apache.org/>. *
* *
* ========================================================================= */
/***************************************************************************
* Description: DSAPI plugin for Lotus Domino *
* Author: Andy Armstrong <an...@tagish.com> *
* Date: 20010603 *
* Version: $Revision: 1.1 $ *
***************************************************************************/
#include "config.h"
#include "inifile.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* 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 <http://www.apache.org/>." *
* *
* 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 <ap...@apache.org>. *
* *
* 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 <http://www.apache.org/>. *
* *
* ========================================================================= */
/***************************************************************************
* Description: ISAPI plugin for Tomcat *
* Author: Andy Armstrong <an...@tagish.com> *
* 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 */