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 2003/11/13 18:10:56 UTC
cvs commit: jakarta-tomcat-connectors/jk/native2/server/dsapi todo.txt jk_dsapi_plugin.c dsapifilter.h dsapi_redirector2.reg dsapi.dsw dsapi.dsp config.h
andya 2003/11/13 09:10:56
Added: jk/native2/server/dsapi todo.txt jk_dsapi_plugin.c
dsapifilter.h dsapi_redirector2.reg dsapi.dsw
dsapi.dsp config.h
Log:
First release of JK2 Domino redirector. Barely tested.
Revision Changes Path
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/todo.txt
Index: todo.txt
===================================================================
$Id: todo.txt,v 1.1 2003/11/13 17:10:56 andya Exp $
Test SSL
Produce Linux version
Resolve any licence issues with dsapifilter.h
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/jk_dsapi_plugin.c
Index: jk_dsapi_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: DSAPI plugin for Lotus Domino *
* Author: Andy Armstrong <an...@tagish.com> *
* Version: $Revision: 1.1 $ *
***************************************************************************/
/* Based on the IIS redirector by Gal Shachor <sh...@il.ibm.com> */
/* Standard headers */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* If we're building under Windows get windows.h. This must be included
* before any APR includes because APR itself does a #include <windows.h>
* after turning off some features that we need.
*/
#ifdef WIN32
#include <windows.h>
#endif
#include "config.h"
/* JK stuff */
#include "jk_global.h"
#include "jk_requtil.h"
#include "jk_map.h"
#include "jk_pool.h"
#include "jk_logger.h"
#include "jk_env.h"
#include "jk_service.h"
#include "jk_worker.h"
#include "apr_general.h"
#ifndef NO_CAPI
/* Domino stuff */
#include <global.h>
#include <addin.h>
#else
#include <stdarg.h>
#define NOERROR 0
#endif
/* Domino DSAPI filter definitions */
#include "dsapifilter.h"
#if !defined(DLLEXPORT)
#if defined(WIN32) && !defined(TESTING)
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
#endif
/* Configuration tags */
#define SERVER_ROOT_TAG ("serverRoot")
#define WORKER_FILE_TAG ("workersFile")
#define TOMCAT_START_TAG ("tomcatStart")
#define TOMCAT_STOP_TAG ("tomcatStop")
#define VERSION "2.0.0"
#define VERSION_STRING "Jakarta/DSAPI/" VERSION
#define FILTERDESC "Apache Tomcat Interceptor (" VERSION_STRING ")"
#define SERVERDFLT "Lotus Domino"
#ifdef TESTING
#define LOGGER "logger.printf"
int JK_METHOD jk2_logger_printf_factory(jk_env_t *env, jk_pool_t *pool, jk_bean_t *result, const char *type, const char *name);
#else
#define LOGGER "logger.win32"
#endif
#define REGISTRY_LOCATION "Software\\Apache Software Foundation\\Jakarta Dsapi Redirector\\2.0"
#define TOMCAT_STARTSTOP_TO 30000 /* 30 seconds */
#define CONTENT_LENGTH "Content-length" /* Name of CL header */
static char libFileName[MAX_PATH];
static char iniFileName[MAX_PATH];
static int iniFileUsed = JK_FALSE;
static int isInited = JK_FALSE;
static const char *tomcatStart = NULL;
static const char *tomcatStop = NULL;
static const char *workersFile = NULL;
static const char *serverRoot = NULL;
static jk_workerEnv_t *workerEnv;
static apr_pool_t *jk_globalPool;
static const char *crlf = "\r\n";
/* Per request private data */
typedef struct private_ws {
/* These get passed in by Domino and are used to access various
* Domino methods and data.
*/
FilterContext *context;
FilterParsedRequest *reqData;
/* True iff the response headers have been sent
*/
int responseStarted;
/* Current pointer into and remaining size
* of request body data
*/
char *reqBuffer;
unsigned int reqSize;
} private_ws_t;
/* 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[-1] == '\\' || sp[-1] == '/') &&
(slen == plen || sp[plen] == '\\' || sp[plen] == '/')) {
return 1;
}
slen--;
sp++;
}
return 0;
}
#ifdef NO_CAPI
/* Alternative to the Domino function */
static void AddInLogMessageText(char *msg, unsigned short code, ...) {
va_list ap;
if (code != NOERROR) {
printf("Error %d: ", code);
}
va_start(ap, code);
vprintf(msg, ap);
va_end(ap);
printf("\n");
}
#endif
static void _printf(const char *msg, ...) {
char buf[512]; /* dangerous fixed size buffer */
va_list ap;
va_start(ap, msg);
vsprintf(buf, msg, ap);
va_end(ap);
AddInLogMessageText("Debug: %s", NOERROR, buf);
}
/* Get the value of a server (CGI) variable as a string
*/
static int GetVariable(struct jk_env *env, jk_ws_service_t *s, char *hdrName,
char *buf, DWORD bufsz, char **dest, const char *dflt) {
int errID;
private_ws_t *ws = (private_ws_t *) s->ws_private;
if (ws->context->GetServerVariable(ws->context, hdrName, buf, bufsz, &errID)) {
*dest = s->pool->pstrdup(env, s->pool, buf);
} else {
*dest = s->pool->pstrdup(env, s->pool, dflt);
}
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "%s=%s\n", hdrName, *dest); */
return JK_TRUE;
}
/* Get the value of a server (CGI) variable as an integer
*/
static int GetVariableInt(struct jk_env *env, jk_ws_service_t *s, char *hdrName,
char *buf, DWORD bufsz, int *dest, int dflt) {
int errID;
private_ws_t *ws = (private_ws_t *) s->ws_private;
if (ws->context->GetServerVariable(ws->context, hdrName, buf, bufsz, &errID)) {
*dest = atoi(buf);
} else {
*dest = dflt;
}
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "%s=%d\n", hdrName, *dest); */
return JK_TRUE;
}
/* Get the value of a server (CGI) variable as an integer
*/
static int GetVariableBool(struct jk_env *env, jk_ws_service_t *s, char *hdrName,
char *buf, DWORD bufsz, int *dest, int dflt) {
int errID;
private_ws_t *ws = (private_ws_t *) s->ws_private;
if (ws->context->GetServerVariable(ws->context, hdrName, buf, bufsz, &errID)) {
if (isdigit(buf[0]))
*dest = atoi(buf) != 0;
else if (NoCaseStrCmp(buf, "yes") == 0 || NoCaseStrCmp(buf, "on") == 0)
*dest = 1;
else
*dest = 0;
} else {
*dest = dflt;
}
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "%s=%d\n", hdrName, *dest); */
return JK_TRUE;
}
/* A couple of utility macros to supply standard arguments to GetVariable() and
* GetVariableInt().
*/
#define GETVARIABLE(name, dest, dflt) \
GetVariable(env, s, (name), workBuf, sizeof(workBuf), (dest), (dflt))
#define GETVARIABLEINT(name, dest, dflt) \
GetVariableInt(env, s, (name), workBuf, sizeof(workBuf), (dest), (dflt))
#define GETVARIABLEBOOL(name, dest, dflt) \
GetVariableBool(env, s, (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 const 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;
}
/* Allocate space for a string given a start pointer and an end pointer
* and return a pointer to the allocated, copied string.
*/
static char *SubStr(jk_env_t *env, jk_pool_t *pool, const char *start, const char *end) {
char *out = NULL;
if (start != NULL && end != NULL && end > start) {
int len = end - start;
if (out = pool->alloc(env, pool, len + 1), NULL != out) {
memcpy(out, start, len);
out[len] = '\0';
}
}
return out;
}
/* Like SubStr() but use a static buffer if possible.
*/
static char *MagicSubStr(jk_env_t *env, jk_pool_t *pool, char **bufp, int *bufSz,
const char *start, const char *end) {
int len = end - start;
if (len < *bufSz) {
char *rv = *bufp;
memcpy(rv, start, len);
rv[len++] = '\0';
/* Adjust buffer pointer, length */
*bufp += len;
*bufSz -= len;
return rv;
} else {
return SubStr(env, pool, start, end);
}
}
static char *StrDup(jk_env_t *env, jk_pool_t *pool, const char *str) {
if (NULL == str) {
return NULL;
}
return SubStr(env, pool, str, str + strlen(str));
}
/* Given all the HTTP headers as a single string parse them into individual
* name, value pairs.
*/
static int ParseHeaders(jk_env_t *env, jk_ws_service_t *s, const char *hdrs, int hdrSz) {
int hdrCount = 0;
const char *limit = hdrs + hdrSz;
const char *name, *nameEnd;
const char *value, *valueEnd;
int gotContentLength = FALSE;
char buf[256]; /* Static buffer used for headers that are short enough to fit
* in it. A dynamic buffer is used for any longer headers.
*/
while (hdrs < limit) {
/* buf is re-used for each header */
char *bufp = buf;
char *hdrName, *hdrValue;
int sz = sizeof(buf);
/* Skip line *before* doing anything, cos we want to lose the first line which
* contains the request. This code also moves to the next line after each header.
*/
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;
}
hdrName = MagicSubStr(env, s->pool, &bufp, &sz, name, nameEnd);
/* Need to strdup the value because map->put doesn't for some reason */
hdrValue = SubStr(env, s->pool, value, valueEnd);
s->headers_in->put(env, s->headers_in, hdrName, hdrValue, NULL);
gotContentLength |= (NoCaseStrCmp(hdrName, CONTENT_LENGTH) == 0);
hdrCount++;
}
/* Add a zero length content-length header if none was found in the
* request.
*/
if (!gotContentLength) {
s->headers_in->put(env, s->headers_in, CONTENT_LENGTH, "0", NULL);
hdrCount++;
}
return hdrCount;
}
static int JK_METHOD cbInit(struct jk_env *env, jk_ws_service_t *s,
struct jk_worker *w, void *serverObj) {
return JK_TRUE;
}
/* Post request cleanup.
*/
static void JK_METHOD cbAfterRequest( struct jk_env *env, jk_ws_service_t *_this) {
}
/* Set the response head in the server structures. This will be called
* before the first write.
*/
static int JK_METHOD cbHead(struct jk_env *env, jk_ws_service_t *s) {
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "Into jk_ws_service_t::cbHead\n"); */
if (s->status < 100 || s->status > 1000) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::cbHead, invalid status %d\n", s->status);
return JK_ERR;
}
if (s && s->ws_private) {
private_ws_t *p = s->ws_private;
if (!p->responseStarted) {
char *hdrBuf;
FilterResponseHeaders frh;
int rc, errID;
int hdrCount;
const char *reason;
p->responseStarted = JK_TRUE;
if (NULL == s->msg) {
reason = "";
} else {
reason = s->msg;
}
hdrCount = s->headers_out->size(env, s->headers_out);
/* Build a single string containing all the headers
* because that's what Domino needs.
*/
if (hdrCount > 0) {
int i;
int hdrLen;
char *bufp;
for (i = 0, hdrLen = 3; i < hdrCount; i++) {
hdrLen += strlen(s->headers_out->nameAt(env, s->headers_out, i));
hdrLen += strlen(s->headers_out->valueAt(env, s->headers_out, i));
hdrLen += 4;
}
hdrBuf = s->pool->alloc(env, s->pool, hdrLen);
bufp = hdrBuf;
for (i = 0; i < hdrCount; i++) {
Append(&bufp, s->headers_out->nameAt(env, s->headers_out, i));
Append(&bufp, ": ");
Append(&bufp, s->headers_out->valueAt(env, s->headers_out, i));
Append(&bufp, crlf);
}
Append(&bufp, crlf);
} else {
hdrBuf = (char *) crlf;
}
frh.responseCode = s->status;
frh.reasonText = (char *) reason;
frh.headerText = hdrBuf;
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "%d %s\n", s->status, reason); */
/* Send the headers */
rc = p->context->ServerSupport(p->context, kWriteResponseHeaders, &frh, NULL, 0, &errID);
}
return JK_OK;
}
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::cbHead, NULL parameters\n");
return JK_ERR;
}
/*
* Read a chunk of the request body into a buffer. Attempt to read len
* bytes into the buffer. Write the number of bytes actually read into
* actually_read.
*/
static int JK_METHOD cbRead(struct jk_env *env, jk_ws_service_t *s,
void *bytes,
unsigned len,
unsigned *actually_read) {
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "Into jk_ws_service_t::Read\n"); */
if (s && s->ws_private && bytes && actually_read) {
private_ws_t *p = s->ws_private;
/* Copy data from Domino's buffer. Although it seems slightly
* improbably we're believing that Domino always buffers the
* entire request in memory. Not properly tested yet.
*/
if (len > p->reqSize) len = p->reqSize;
memcpy(bytes, p->reqBuffer, len);
p->reqBuffer += len;
p->reqSize -= len;
*actually_read = len;
return JK_OK;
}
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::Read, NULL parameters\n");
return JK_ERR;
}
/*
* Write a chunk of response data back to the browser.
*/
static int JK_METHOD cbWrite(struct jk_env *env, jk_ws_service_t *s,
const void *bytes, unsigned len) {
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "Into jk_ws_service_t::Write\n"); */
if (s && s->ws_private && bytes) {
private_ws_t *p = s->ws_private;
int errID, rc;
/* Send the data */
if (len > 0) {
rc = p->context->WriteClient(p->context, (char *) bytes, len, 0, &errID);
}
return JK_OK;
}
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::Write, NULL parameters\n");
return JK_ERR;
}
/*
* Flush the output buffers.
*/
static int JK_METHOD cbFlush(struct jk_env *env, jk_ws_service_t *s) {
return JK_OK;
}
/* Return TRUE iff the specified filename is absolute. Note that this is only
* called in cases where the definition of 'absolute' is not security sensitive. I'm
* sure there are ways of constructing absolute Win32 paths that it doesn't catch.
*/
static int IsAbsolute(const char *fn) {
#ifdef WIN32
return fn[0] == '\\' || (isalpha(fn[0]) && fn[1] == ':');
#else
return fn[0] == '/';
#endif
}
static const char *AbsPath(jk_env_t *env, const char *base, const char *name) {
if (base == NULL || IsAbsolute(name)) {
return name;
} else {
int bsz = strlen(base);
int nsz = strlen(name);
int ads = (base[bsz-1] != PATHSEP) ? 1 : 0;
char *buf;
if (buf = workerEnv->pool->alloc(env, workerEnv->pool, bsz + ads + nsz + 1), NULL == buf) {
return NULL;
}
memcpy(buf, base, bsz);
if (ads) {
buf[bsz] = PATHSEP;
}
memcpy(buf + bsz + ads, name, nsz);
buf[bsz + ads + nsz] = '\0';
return buf;
}
}
#ifdef WIN32
static const char *ReadRegistry(jk_env_t *env, HKEY hkey, const char *key, const char *base) {
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 = workerEnv->pool->alloc(env, workerEnv->pool, sz), NULL == val) {
return NULL;
}
rc = RegQueryValueEx(hkey, key, (LPDWORD) 0, &type, val, &sz);
if (rc == ERROR_SUCCESS) {
return AbsPath(env, base, val);
}
return NULL;
}
#endif
static int ReadFromRegistry(jk_env_t *env) {
#ifdef WIN32
HKEY hkey;
long rc;
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD) 0, KEY_READ, &hkey);
if (ERROR_SUCCESS != rc) {
return JK_FALSE;
}
serverRoot = ReadRegistry(env, hkey, SERVER_ROOT_TAG, NULL);
workersFile = ReadRegistry(env, hkey, WORKER_FILE_TAG, serverRoot);
tomcatStart = ReadRegistry(env, hkey, TOMCAT_START_TAG, serverRoot);
tomcatStop = ReadRegistry(env, hkey, TOMCAT_STOP_TAG, serverRoot);
RegCloseKey(hkey);
iniFileUsed = JK_FALSE;
return NULL != serverRoot &&
NULL != workersFile;
#else
return JK_FALSE;
#endif
}
/* Read an entry from a map and return a newly allocated copy of it
* on success or NULL on failure.
*/
static const char *ReadMap(jk_env_t *env, jk_map_t *map, const char *name, const char *base)
{
const char *s = map->get(env, map, name);
if (s) {
return AbsPath(env, base, workerEnv->pool->pstrdup(env, workerEnv->pool, s));
}
return NULL;
}
/* Read parameters from an ini file or the registry
*/
static int ReadInitData(jk_env_t *env) {
jk_map_t *map;
/* Attempt to read from an ini file */
if (JK_OK == jk2_map_default_create(env, &map, workerEnv->pool )) {
if (JK_OK == jk2_config_file_read(env, map, iniFileName)) {
serverRoot = ReadMap(env, map, SERVER_ROOT_TAG, NULL);
workersFile = ReadMap(env, map, WORKER_FILE_TAG, serverRoot);
tomcatStart = ReadMap(env, map, TOMCAT_START_TAG, serverRoot);
tomcatStop = ReadMap(env, map, TOMCAT_STOP_TAG, serverRoot);
iniFileUsed = JK_TRUE;
return NULL != serverRoot &&
NULL != workersFile;
}
} else {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"read_registry_init_data, Failed to create map \n");
}
return ReadFromRegistry(env);
}
/* Send a simple response. Used when we don't want to bother Tomcat,
* which in practice means for various error conditions that we can
* detect internally.
*/
static void SimpleResponse(FilterContext *context, int status, char *reason, char *body) {
FilterResponseHeaders frh;
int rc, errID;
char hdrBuf[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);
}
/* Called to reject a URI that contains the string "web-inf". We block
* these because they may indicate an attempt to invoke arbitrary code.
*/
static unsigned int RejectBadURI(FilterContext *context) {
static char *msg = "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>";
SimpleResponse(context, 403, "Forbidden", msg);
return kFilterHandledRequest;
}
/* Called to reject a URI that contains the string "web-inf". We block
* these because they may indicate an attempt to invoke arbitrary code.
*/
static unsigned int RejectWithError(FilterContext *context) {
static char *msg = "<html><body><h1>Error in Filter</h1></body></html>";
SimpleResponse(context, 500, "Error in Filter", msg);
return kFilterHandledRequest;
}
/* Initialize the service structure
*/
static int ProcessRequest(struct jk_env *env, jk_ws_service_t *s,
struct jk_worker *w, void *serverObj) {
/* This is the only fixed size buffer left. It won't be overflowed
* because the Domino 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];
private_ws_t *ws = (private_ws_t *) s->ws_private;
FilterRequest fr;
char *hdrs;
int hdrsz;
int errID = 0;
int hdrCount;
int rc;
static char *methodName[] = { "", "HEAD", "GET", "POST", "PUT", "DELETE" };
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "ProcessRequest(), s = %p, ws = %p\n", s, ws); */
/* Should this rc be checked? */
rc = ws->context->GetRequest(ws->context, &fr, &errID);
s->jvm_route = NULL;
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_ERR;
}
s->method = methodName[ws->reqData->requestMethod];
s->ssl_cert_len = fr.clientCertLen;
s->ssl_cert = fr.clientCert;
s->ssl_cipher = NULL;
s->ssl_session = NULL;
s->ssl_key_size = -1;
if (JK_OK != jk2_map_default_create(env, &s->headers_out, s->pool)) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::init, Failed to create headers_out map\n");
return JK_ERR;
}
if (JK_OK != jk2_map_default_create(env, &s->attributes, s->pool)) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::init, Failed to create attributes map\n");
return JK_ERR;
}
if (JK_OK!=jk2_map_default_create(env, &s->headers_in, s->pool)) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_ws_service_t::init, Failed to create headers_in map\n");
return JK_ERR;
}
if (s->is_ssl) {
int i, dummy;
char *sslNames[] = {
"CERT_ISSUER", "CERT_SUBJECT", "CERT_COOKIE", "CERT_FLAGS", "CERT_SERIALNUMBER",
"HTTPS_SERVER_SUBJECT", "HTTPS_SECRETKEYSIZE", "HTTPS_SERVER_ISSUER", "HTTPS_KEYSIZE"
};
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "Request is SSL\n"); */
/* 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);
}
/* Should also try to make suitable values for s->ssl_cipher and
* s->ssl_session
*/
for (i = 0; i < sizeof(sslNames) / sizeof(sslNames[0]); i++) {
char *value = NULL;
GETVARIABLE(sslNames[i], &value, NULL);
if (value) {
s->attributes->put(env, s->attributes, sslNames[i], value, NULL);
}
}
}
/* Duplicate all the headers now */
hdrsz = ws->reqData->GetAllHeaders(ws->context, &hdrs, &errID);
if (0 == hdrsz) {
return JK_ERR;
}
hdrCount = ParseHeaders(env, s, hdrs, hdrsz);
return JK_OK;
}
/* Handle an HTTP request. Works out whether Tomcat will be interested then either
* despatches it to Tomcat or passes it back to Domino.
*/
static unsigned int ParsedRequest(FilterContext *context, FilterParsedRequest *reqData) {
unsigned int errID;
int rc;
FilterRequest fr;
int result = kFilterNotHandled;
/* TODO: presumably this return code should be checked */
rc = context->GetRequest(context, &fr, &errID);
if (fr.URL && strlen(fr.URL)) {
char *uri = fr.URL;
char *qp, *turi;
jk_uriEnv_t *uriEnv = NULL;
int errID;
char buf[256]; /* enough for the server's name */
char *serverName;
size_t serverNameSz;
int serverPort;
char *uriBuf;
size_t uriSz, uriBufSz;
jk_env_t *env = workerEnv->globalEnv->getEnv(workerEnv->globalEnv);
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "ParsedRequest() - %s\n", uri); */
if (!context->GetServerVariable(context, "SERVER_PORT", buf, sizeof(buf), &errID)) {
return RejectWithError(context);
}
serverPort = atoi(buf);
if (!context->GetServerVariable(context, "SERVER_NAME", buf, sizeof(buf), &errID)) {
return RejectWithError(context);
}
serverName = buf; /* note serverName just aliases buf
* and will be destroyed if buf is reused
*/
serverNameSz = strlen(serverName) + 1;
uriBuf = serverName + serverNameSz;
uriBufSz = sizeof(buf) - serverNameSz;
uriSz = strlen(uri) + 1;
/* Use the stack buffer for sufficiently short URIs */
if (uriSz <= uriBufSz) {
turi = uriBuf;
} else {
turi = context->AllocMem(context, uriSz, 0, &errID);
}
memcpy(turi, uri, uriSz);
rc = jk_requtil_unescapeUrl(turi);
if (rc < 0) {
return RejectWithError(context);
}
jk_requtil_getParents(turi);
if (qp = strchr(turi, '?'), qp != NULL) {
*qp++ = '\0';
}
if (BadURI(turi)) {
return RejectBadURI(context);
}
uriEnv = workerEnv->uriMap->mapUri(env, workerEnv->uriMap, serverName, serverPort, turi);
if (NULL != uriEnv) {
// Here we go
private_ws_t ws;
jk_ws_service_t s;
jk_pool_t *rPool = NULL;
jk_worker_t *worker = uriEnv->worker;
rPool = worker->rPoolCache->get(env, worker->rPoolCache);
if (NULL == rPool) {
rPool = worker->mbean->pool->create(env, worker->mbean->pool, HUGE_POOL_SIZE);
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "HttpExtensionProc: new rpool\n"); */
}
jk2_requtil_initRequest(env, &s);
s.pool = rPool; /* Do we need one? */
s.is_recoverable_error = JK_FALSE;
s.response_started = JK_FALSE;
s.content_read = 0;
s.ws_private = &ws;
s.workerEnv = workerEnv;
s.head = cbHead;
s.read = cbRead;
s.write = cbWrite;
s.init = cbInit;
s.afterRequest = cbAfterRequest;
if (workerEnv->options == JK_OPT_FWDURICOMPATUNPARSED) {
s.req_uri = StrDup(env, rPool, uri);
/* Find the query string again in the original URI */
if (qp = strchr(s.req_uri, '?'), NULL != qp) {
*qp++ = '\0';
}
} else if (workerEnv->options == JK_OPT_FWDURIESCAPED) {
/* Nasty static buffer */
char euri[256];
if (jk_requtil_escapeUrl(turi, euri, sizeof(euri))) {
turi = euri;
}
s.req_uri = turi;
} else {
s.req_uri = turi;
}
s.query_string = qp;
/* Init our private structure
*/
ws.responseStarted = JK_FALSE;
ws.context = context;
ws.reqData = reqData;
/* Fetch info about the request
*/
ws.reqSize = context->GetRequestContents(context, &ws.reqBuffer, &errID);
rc = ProcessRequest(env, &s, worker, context);
if (JK_OK == rc) {
rc = worker->service(env, uriEnv->worker, &s);
}
if (JK_OK == rc) {
result = kFilterHandledRequest;
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "HttpExtensionProc service() returned OK\n"); */
} else {
result = kFilterError;
env->l->jkLog(env, env->l, JK_LOG_ERROR, "HttpExtensionProc error, service() failed\n");
}
s.afterRequest(env, &s);
rPool->reset(env, rPool);
rc = worker->rPoolCache->put(env, worker->rPoolCache, rPool);
}
workerEnv->globalEnv->releaseEnv(workerEnv->globalEnv, env);
}
return result;
}
/* Main entry point for the filter. Called by Domino for every HTTP request.
*/
DLLEXPORT unsigned int HttpFilterProc(FilterContext *context, unsigned int eventType, void *eventData) {
switch (eventType) {
case kFilterParsedRequest:
return ParsedRequest(context, (FilterParsedRequest *) eventData);
default:
break;
}
return kFilterNotHandled;
}
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();
AddInLogMessageText("Command \"%s\" failed (error %u)", NOERROR, cmd, err);
return FALSE;
}
if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, TOMCAT_STARTSTOP_TO)) {
return TRUE;
}
AddInLogMessageText("Command \"%s\" didn't complete in time", NOERROR, cmd);
return FALSE;
#else
int err = system(cmd);
if (0 == err) {
return 1;
}
AddInLogMessageText("Command \"%s\" failed (error %d)", NOERROR, cmd, err);
return 0;
#endif
}
/* Called when the filter is unloaded. Free various resources and
* display a banner.
*/
DLLEXPORT unsigned int TerminateFilter(unsigned int reserved) {
jk_env_t *env = workerEnv->globalEnv->getEnv(workerEnv->globalEnv);
// TODO: Work out if we're doing everything we need to here
if (isInited) {
if (workerEnv) {
jk_env_t *env = workerEnv->globalEnv;
workerEnv->close(env, workerEnv);
}
isInited = JK_FALSE;
}
#ifndef TESTING
if (NULL != tomcatStop && '\0' != *tomcatStop) {
AddInLogMessageText("Attempting to stop Tomcat: %s", NOERROR, tomcatStop);
RunProg(tomcatStop);
}
#endif
AddInLogMessageText(FILTERDESC " unloaded", NOERROR);
apr_pool_destroy(jk_globalPool);
return kFilterHandledEvent;
}
/* Called when Domino loads the filter. Reads a load of config data from
* the registry and elsewhere and displays a banner.
*/
DLLEXPORT unsigned int FilterInit(FilterInitData *filterInitData) {
jk_logger_t *l;
jk_pool_t *globalPool;
jk_bean_t *jkb;
jk_env_t *env;
#ifndef WIN32
Dl_info info;
char *dot, *slash;
memset(&info, 0, sizeof(info));
if (!dladdr(FilterInit, &info) || NULL == info.dli_fname) {
goto initFailed;
}
lstrcpyn(libFileName, info.dli_fname, sizeof(libFileName)-1);
lstrcpyn(iniFileName, info.dli_fname, sizeof(libFileName)-1);
char *slash = strrchr(iniFileName, PATHSEP);
if (NULL == slash) {
slash = iniFileName;
} else {
slash++;
}
char *dot = strrchr(slash, '.');
if (NULL == dot) {
dot = slash + strlen(slash);
}
lstrcpyn(slash, ".properties", (iniFileName + sizeof(iniFileName) - 1) - slash);
#endif
apr_initialize();
apr_pool_create(&jk_globalPool, NULL);
jk2_pool_apr_create(NULL, &globalPool, NULL, jk_globalPool);
/* Create the global environment. This will register the default
* factories
*/
env = jk2_env_getEnv(NULL, globalPool);
#ifdef TESTING
env->registerFactory(env, "logger.printf", jk2_logger_printf_factory);
#endif
jkb = env->createBean2(env, env->globalPool, LOGGER, "");
env->alias(env, LOGGER ":", "logger");
l = jkb->object;
#ifdef _DEBUG
l->level = JK_LOG_DEBUG_LEVEL; /* is that naughty? */
#endif
env->l = l;
env->soName = env->globalPool->pstrdup(env, env->globalPool, libFileName);
if (NULL == env->soName) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "Error creating env->soName\n");
goto initFailed;
}
/* Initialise logger
*/
env->l->init(env, env->l);
/* We should make it relative to JK_HOME or absolute path.
ap_serverRoot_relative(cmd->pool, opt); */
/* Create the workerEnv
*/
jkb = env->createBean2(env, env->globalPool,"workerEnv", "");
workerEnv = jkb->object;
env->alias(env, "workerEnv:", "workerEnv");
if (NULL == workerEnv) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "Error creating workerEnv\n");
goto initFailed;
}
workerEnv->childId = 0;
if (!ReadInitData(env)) {
goto initFailed;
}
workerEnv->initData->add(env, workerEnv->initData, "serverRoot",
workerEnv->pool->pstrdup(env, workerEnv->pool, serverRoot));
env->l->jkLog(env, env->l, JK_LOG_INFO, "Set serverRoot %s\n", serverRoot);
/* Note: we cast away the const qualifier on workersFile here
*/
if (JK_OK != workerEnv->config->setPropertyString(env, workerEnv->config,
"config.file", (char *) workersFile)) {
goto initFailed;
}
workerEnv->init(env, workerEnv);
#ifndef TESTING
/* Attempt to launch Tomcat
*/
if (NULL != tomcatStart && '\0' != *tomcatStart) {
AddInLogMessageText("Attempting to start Tomcat: %s", NOERROR, tomcatStart);
RunProg(tomcatStart);
}
#endif
filterInitData->appFilterVersion = kInterfaceVersion;
filterInitData->eventFlags = kFilterParsedRequest;
strcpy(filterInitData->filterDesc, FILTERDESC);
isInited = JK_TRUE;
/* Display banner
*/
AddInLogMessageText("%s loaded", NOERROR, filterInitData->filterDesc);
return kFilterHandledEvent;
initFailed:
AddInLogMessageText("Error loading %s", NOERROR, FILTERDESC);
return kFilterError;
}
#ifdef WIN32
/* Handle DLL initialisation (on WIN32) by working out what the INI file
* should be called.
*/
BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason, LPVOID lpReserved) {
BOOL fReturn = TRUE;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
switch (ulReason) {
case DLL_PROCESS_ATTACH:
/* TODO: Work out a way to do this on other platforms. */
if (GetModuleFileName(hInst, libFileName, sizeof(libFileName))) {
_splitpath(libFileName, drive, dir, fname, NULL);
_makepath(iniFileName, drive, dir, fname, ".properties");
} else {
fReturn = FALSE;
}
break;
default:
break;
}
return fReturn;
}
#endif
#ifdef TESTING
/* Handle initialisation in the test harness environment.
*/
void TestMain(void) {
strcpy(libFileName, "test.exe");
strcpy(iniFileName, "test.properties");
}
#endif
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/dsapifilter.h
Index: dsapifilter.h
===================================================================
/*--------------------------------------------------------------------
*
* File: dsapifilter.h
*
* Copyright (c)1999 Iris Associates
*
*-------------------------------------------------------------------*/
#if !defined(DSAPIFILTER_H)
#define DSAPIFILTER_H
#ifdef __cplusplus
extern "C"
{
#endif
/*---
* Types and Defines
*/
#define kInterfaceVersion 2
#define kMaxFilterDesc 255
typedef unsigned char LMBCS;
typedef enum
{
kFilterNotHandled = 0,
kFilterHandledRequest = 1,
kFilterHandledEvent = 2,
kFilterError = 3
}
FilterReturnCode;
/*--
* Filter interface
*/
/*---
* events to register for
*/
typedef enum
{
kFilterRawRequest = 0x01,
kFilterParsedRequest = 0x02,
kFilterAuthUser = 0x04,
kFilterUserNameList = 0x08,
kFilterMapURL = 0x10,
kFilterResponse = 0x20,
kFilterRawWrite = 0x40,
kFilterEndRequest = 0x80,
kFilterAny = 0xFF
}
EventFlags;
/*---
* filter initialization data
*/
typedef struct
{
unsigned int serverFilterVersion;
unsigned int appFilterVersion;
unsigned int eventFlags;
unsigned int initFlags;
char filterDesc[kMaxFilterDesc + 1];
}
FilterInitData;
/*---
* request line structure
*/
typedef struct
{
unsigned int method;
char *URL;
char *version;
char *userName;
char *password;
unsigned char *clientCert;
unsigned int clientCertLen;
char *contentRead;
unsigned int contentReadLen;
}
FilterRequest;
/*---
* filter context data included in every call to filter
*/
typedef struct _FilterContext
{
unsigned int contextSize;
unsigned int revision;
void *serverContext;
unsigned int serverReserved;
unsigned int securePort;
void *privateContext;
int (*GetRequest) (struct _FilterContext *context, FilterRequest * request,
unsigned int *errID);
int (*GetRequestContents) (struct _FilterContext *context, char **contents,
unsigned int *errID);
int (*GetServerVariable) (struct _FilterContext * context, char *name, void *buffer,
unsigned int bufferSize, unsigned int *errID);
int (*WriteClient) (struct _FilterContext * context, char *buffer, unsigned int bufferLen,
unsigned int reserved, unsigned int *errID);
void *(*AllocMem) (struct _FilterContext * context, unsigned int size,
unsigned int reserved, unsigned int *errID);
int (*ServerSupport) (struct _FilterContext * context, unsigned int funcType, void *data1,
void *data2, unsigned int other, unsigned int *errID);
}
FilterContext;
typedef unsigned int (*FilterInitFuncType) (FilterInitData * initData);
typedef unsigned int (*FilterEventFuncType) (FilterContext * context, unsigned int eventType,
void *eventData, unsigned int *errID);
typedef unsigned int (*FilterTermFuncType) (unsigned int);
/*---
* request methods
*/
typedef enum
{
kRequestNone = 0,
kRequestHEAD = 1,
kRequestGET = 2,
kRequestPOST = 3,
kRequestPUT = 4,
kRequestDELETE = 5
}
RequestMethod;
/*---
* server support function types
*/
typedef enum
{
kWriteResponseHeaders = 1
}
ServerSupportTypes;
/*---
* 'data1' for server support function 'kWriteResponseHeaders'
*/
typedef struct
{
unsigned int responseCode;
char *reasonText;
char *headerText;
}
FilterResponseHeaders;
/*---
* raw request (headers not processed yet)
*/
typedef struct
{
unsigned int requestMethod;
int (*GetAllHeaders) (FilterContext * context, char **headers, unsigned int *errID);
int (*GetHeader) (FilterContext * context, char *name, char *buffer,
unsigned int bufferSize, unsigned int *errID);
int (*SetHeader) (FilterContext * context, char *name, char *value, unsigned int *errID);
int (*AddHeader) (FilterContext * context, char *header, unsigned int *errID);
unsigned int reserved;
}
FilterRawRequest;
/*---
* parsed request
*/
typedef struct
{
unsigned int requestMethod;
int (*GetAllHeaders) (FilterContext * context, char **headers, unsigned int *errID);
int (*GetHeader) (FilterContext * context, char *name, char *buffer,
unsigned int bufferSize, unsigned int *errID);
unsigned int reserved;
}
FilterParsedRequest;
/*---
* URL map
*/
typedef struct
{
const char *url;
char *pathBuffer;
unsigned int bufferSize;
unsigned int mapType;
}
FilterMapURL;
/*---
* URL map types
*/
typedef enum
{
kURLMapUnknown = 0,
kURLMapPass = 1,
kURLMapExec = 2,
kURLMapRedirect = 3,
kURLMapService = 4,
kURLMapDomino = 5
}
FilterULMapTypes;
/*---
* user authentication
*/
typedef struct
{
LMBCS *userName;
LMBCS *password;
unsigned char *clientCert;
unsigned int clientCertLen;
unsigned int authFlags;
unsigned int preAuthenticated;
unsigned int foundInCache;
unsigned int authNameSize;
LMBCS *authName;
unsigned int authType;
int (*GetUserNameList) (FilterContext * context, LMBCS * buffer, unsigned int bufferSize,
unsigned int *numNames, unsigned int reserved, unsigned int *errID);
int (*GetHeader) (FilterContext * context, char *name, char *buffer,
unsigned int bufferSize, unsigned int *errID);
}
FilterAuthenticate;
/*---
* user authentication types
*/
typedef enum
{
kNotAuthentic = 0,
kAuthenticBasic = 1,
kAuthenticClientCert = 2
}
FilterAuthenticationTypes;
/*---
* authentication configuration flags
*/
typedef enum
{
kAuthAllowBasic = 1,
kAuthAllowAnonymous = 2,
kAuthAllowSSLCert = 4,
kAuthAllowSSLBasic = 8,
kAuthAllowSSLAnonymous = 16,
kAuthRedirectToSSL = 32
}
FilterAuthConfigFlags;
/*---
* user name list
*/
typedef struct
{
const LMBCS *userName;
int (*GetUserNameList) (FilterContext * context, LMBCS * buffer, unsigned int bufferSize,
unsigned int *numNames, unsigned int reserved, unsigned int *errID);
int (*PopulateUserNameList) (FilterContext * context, LMBCS * buffer,
unsigned int bufferSize, unsigned int *numNames,
unsigned int reserved, unsigned int *errID);
int (*AddGroupsToList) (FilterContext * context, LMBCS * groupNames,
unsigned int numGroupNames, unsigned int reserved,
unsigned int *errID);
int (*RemoveGroupsFromList) (FilterContext * context, unsigned int reserved,
unsigned int *errID);
unsigned int reserved;
}
FilterUserNameList;
/*---
* request response
*/
typedef struct
{
unsigned int responseCode;
char *reasonText;
int (*GetAllHeaders) (FilterContext * context, char **headers, unsigned int *errID);
int (*GetHeader) (FilterContext * context, char *name, char *buffer,
unsigned int bufferSize, unsigned int *errID);
int (*SetHeader) (FilterContext * context, char *name, char *value, unsigned int *errID);
int (*AddHeader) (FilterContext * context, char *header, unsigned int *errID);
unsigned int reserved;
}
FilterResponse;
/*---
* write content
*/
typedef struct
{
char *content;
unsigned int contentLen;
unsigned int reserved;
}
FilterRawWrite;
#ifdef __cplusplus
}
#endif
#endif /* DSAPIFILTER_H */
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/dsapi_redirector2.reg
Index: dsapi_redirector2.reg
===================================================================
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Dsapi Redirector\2.0]
"serverRoot"="D:\\Works\\Tomcat\\jakarta-tomcat-4.1.27"
"workersFile"="conf\\workers.properties"
"tomcatStart"="bin\\startup.bat"
"tomcatStop"="bin\\shutdown.bat"
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/dsapi.dsw
Index: dsapi.dsw
===================================================================
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "dsapi"=".\dsapi.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "test"=".\test\test.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/dsapi.dsp
Index: dsapi.dsp
===================================================================
# Microsoft Developer Studio Project File - Name="dsapi" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=dsapi - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "dsapi.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "dsapi.mak" CFG="dsapi - Win32 Debug Static"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "dsapi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "dsapi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "dsapi - Win32 Debug Static" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "dsapi - Win32 Release Static" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "dsapi - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\..\..\..\..\apr\include" /I "..\..\..\..\..\apr-util\include" /I "..\..\..\..\..\pcre\include" /I "$(NOTESAPI)\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HAVE_JNI" /D "HAS_APR" /D "HAS_PCRE" /D "NT" /U "NOUSER" /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 0xc0a /d "NDEBUG"
# ADD RSC /l 0x409 /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 libapr.lib libaprutil.lib ws2_32.lib wsock32.lib advapi32.lib pcre.lib pcreposix.lib notes.lib /nologo /dll /machine:I386 /out:"Release/dsapi_redirector2.dll" /libpath:"..\..\..\..\..\apr\Release" /libpath:"..\..\..\..\..\pcre\lib" /libpath:"..\..\..\..\..\apr-util\Release" /libpath:"$(NOTESAPI)\lib\mswin32"
!ELSEIF "$(CFG)" == "dsapi - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\..\..\..\..\apr\include" /I "..\..\..\..\..\apr-util\include" /I "..\..\..\..\..\pcre\include" /I "$(NOTESAPI)\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HAVE_JNI" /D "HAS_APR" /D "HAS_PCRE" /D "NT" /U "NOUSER" /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 0xc0a /d "_DEBUG"
# ADD RSC /l 0x409 /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 libapr.lib libaprutil.lib ws2_32.lib wsock32.lib advapi32.lib pcre.lib pcreposix.lib notes.lib /nologo /dll /debug /machine:I386 /out:"Debug/dsapi_redirector2.dll" /pdbtype:sept /libpath:"..\..\..\..\..\apr\Release" /libpath:"..\..\..\..\..\pcre\lib" /libpath:"..\..\..\..\..\apr-util\Release" /libpath:"$(NOTESAPI)\lib\mswin32"
# SUBTRACT LINK32 /nodefaultlib
!ELSEIF "$(CFG)" == "dsapi - Win32 Debug Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "DebugS"
# PROP BASE Intermediate_Dir "DebugS"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "DebugS"
# PROP Intermediate_Dir "DebugS"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "$(APACHE2_HOME)\include" /I "$(APACHE2_HOME)\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /D "HAVE_JNI" /D "HAS_APR" /FR /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\..\..\..\..\apr\include" /I "..\..\..\..\..\apr-util\include" /I "..\..\..\..\..\pcre\include" /I "$(NOTESAPI)\include" /D "_DEBUG" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HAVE_JNI" /D "HAS_APR" /D "HAS_PCRE" /D "NT" /U "NOUSER" /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 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libapr.lib libaprutil.lib wsock32.lib advapi32.lib /nologo /dll /debug /machine:I386 /out:"Debug/dsapi_redirector2.dll" /pdbtype:sept /libpath:"$(APACHE2_HOME)\lib"
# SUBTRACT BASE LINK32 /nodefaultlib
# ADD LINK32 libapr.lib libaprutil.lib ws2_32.lib wsock32.lib advapi32.lib pcre.lib pcreposix.lib notes.lib /nologo /dll /debug /machine:I386 /out:"DebugS/dsapi_redirector2.dll" /pdbtype:sept /libpath:"..\..\..\..\..\apr\Release" /libpath:"..\..\..\..\..\pcre\lib" /libpath:"..\..\..\..\..\apr-util\Release" /libpath:"$(NOTESAPI)\lib\mswin32"
# SUBTRACT LINK32 /nodefaultlib
!ELSEIF "$(CFG)" == "dsapi - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "ReleaseS"
# PROP BASE Intermediate_Dir "ReleaseS"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "ReleaseS"
# PROP Intermediate_Dir "ReleaseS"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "$(APACHE2_HOME)\include" /I "$(APACHE2_HOME)\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /D "HAVE_JNI" /D "HAS_APR" /FR /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\..\..\..\..\apr\include" /I "..\..\..\..\..\apr-util\include" /I "..\..\..\..\..\pcre\include" /I "$(NOTESAPI)\include" /D "NDEBUG" /D "_WIN32" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HAVE_JNI" /D "HAS_APR" /D "HAS_PCRE" /D "NT" /U "NOUSER" /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 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libapr.lib libaprutil.lib wsock32.lib advapi32.lib /nologo /dll /machine:I386 /out:"Release/dsapi_redirector2.dll" /libpath:"$(APACHE2_HOME)\lib"
# ADD LINK32 libapr.lib libaprutil.lib ws2_32.lib wsock32.lib advapi32.lib pcre.lib pcreposix.lib notes.lib /nologo /dll /machine:I386 /out:"ReleaseS/dsapi_redirector2.dll" /libpath:"..\..\..\..\..\apr\Release" /libpath:"..\..\..\..\..\pcre\lib" /libpath:"..\..\..\..\..\apr-util\Release" /libpath:"$(NOTESAPI)\lib\mswin32"
!ENDIF
# Begin Target
# Name "dsapi - Win32 Release"
# Name "dsapi - Win32 Debug"
# Name "dsapi - Win32 Debug Static"
# Name "dsapi - Win32 Release Static"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Group "JK2 Common Source"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\common\jk_channel.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_channel_apr_socket.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_channel_jni.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_channel_un.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_config.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_config_file.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_endpoint.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_env.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_handler_logon.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_handler_response.c
# End Source File
# Begin Source File
SOURCE=..\..\jni\jk_jni_aprImpl.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_logger_file.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_logger_win32.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_ajp.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_mutex.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_mutex_proc.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_mutex_thread.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_nwmain.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_objCache.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_pool_apr.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_registry.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_requtil.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_shm.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_signal.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_uriEnv.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_uriMap.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_user.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_vm_default.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_worker_ajp13.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_worker_jni.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_worker_lb.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_worker_run.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_worker_status.c
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_workerEnv.c
# End Source File
# End Group
# Begin Group "DSAPI Source"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\jk_dsapi_plugin.c
# End Source File
# End Group
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Group "JK2 Common Headers"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\include\jk_channel.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_config.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_endpoint.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_env.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_global.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_handler.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_logger.h
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_logger_win32_message.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_map.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_md5.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_msg.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_objCache.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_pool.h
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_registry.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_requtil.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_service.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_shm.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_uriEnv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_uriMap.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_vm.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_worker.h
# End Source File
# Begin Source File
SOURCE=..\..\include\jk_workerEnv.h
# End Source File
# Begin Source File
SOURCE=..\..\jni\org_apache_jk_apr_AprImpl.h
# End Source File
# End Group
# Begin Group "DSAPI Headers"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\config.h
# End Source File
# Begin Source File
SOURCE=.\dsapifilter.h
# End Source File
# End Group
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=..\..\common\jk_logger_win32_message.mc
!IF "$(CFG)" == "dsapi - Win32 Release"
# Begin Custom Build - Creating resources from $(InputPath)
InputDir=\Works\Tomcat\jakarta-tomcat-connectors\jk\native2\common
InputPath=..\..\common\jk_logger_win32_message.mc
"..\..\common\jk_logger_win32_message.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
mc -h $(InputDir) -r $(InputDir) $(InputPath)
# End Custom Build
!ELSEIF "$(CFG)" == "dsapi - Win32 Debug"
# PROP Ignore_Default_Tool 1
# Begin Custom Build - Creating resources from $(InputPath)
InputDir=\Works\Tomcat\jakarta-tomcat-connectors\jk\native2\common
InputPath=..\..\common\jk_logger_win32_message.mc
"..\..\common\jk_logger_win32_message.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
mc -h $(InputDir) -r $(InputDir) $(InputPath)
# End Custom Build
!ELSEIF "$(CFG)" == "dsapi - Win32 Debug Static"
# PROP BASE Ignore_Default_Tool 1
# PROP Ignore_Default_Tool 1
# Begin Custom Build - Creating resources from $(InputPath)
InputDir=\Works\Tomcat\jakarta-tomcat-connectors\jk\native2\common
InputPath=..\..\common\jk_logger_win32_message.mc
"..\..\common\jk_logger_win32_message.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
mc -h $(InputDir) -r $(InputDir) $(InputPath)
# End Custom Build
!ELSEIF "$(CFG)" == "dsapi - Win32 Release Static"
# Begin Custom Build - Creating resources from $(InputPath)
InputDir=\Works\Tomcat\jakarta-tomcat-connectors\jk\native2\common
InputPath=..\..\common\jk_logger_win32_message.mc
"..\..\common\jk_logger_win32_message.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
mc -h $(InputDir) -r $(InputDir) $(InputPath)
# End Custom Build
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\common\jk_logger_win32_message.rc
# End Source File
# End Group
# Begin Group "Other files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\dsapi_redirector2.reg
# End Source File
# Begin Source File
SOURCE=.\todo.txt
# End Source File
# End Group
# End Target
# End Project
1.1 jakarta-tomcat-connectors/jk/native2/server/dsapi/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: DSAPI plugin for Lotus Domino *
* 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
#define PATHSEP '\\'
#elif defined(LINUX)
#undef HAVE_MEMICMP
#define PATHSEP '/'
#elif defined(SOLARIS)
#undef HAVE_MEMICMP
#define PATHSEP '/'
#else
#error Please define one of WIN32, LINUX or SOLARIS
#endif
/* define if you don't have the Notes C API which is available from
*
* http://www.lotus.com/rw/dlcapi.nsf
*/
/* #undef NO_CAPI */
#define DEBUG(args) \
do { _printf args ; } while (0)
#endif /* __config_h */
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org