📄 jk_dsapi_plugin.c
字号:
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/***************************************************************************
* Description: DSAPI plugin for Lotus Domino *
* Author: Andy Armstrong <andy@tagish.com> *
* Version: $Revision: 299862 $ *
***************************************************************************/
/* Based on the IIS redirector by Gal Shachor <shachor@il.ibm.com> */
#include "config.h"
#include "inifile.h"
/* JK stuff */
#include "jk_global.h"
#include "jk_util.h"
#include "jk_map.h"
#include "jk_pool.h"
#include "jk_service.h"
#include "jk_worker.h"
#include "jk_ajp12_worker.h"
#include "jk_uri_worker_map.h"
#ifndef NO_CAPI
/* Domino stuff */
#include <global.h>
#include <addin.h>
#else
#include <stdarg.h>
#define NOERROR 0
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dsapifilter.h"
#if !defined(DLLEXPORT)
#ifdef WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
#endif
#define VERSION "1.0.3"
#define VERSION_STRING "Jakarta/DSAPI/" VERSION
/* What we call ourselves */
#define FILTERDESC "Apache Tomcat Interceptor (" VERSION_STRING ")"
#define SERVERDFLT "Lotus Domino"
/* Registry location of configuration data */
#define REGISTRY_LOCATION "Software\\Apache Software Foundation\\Jakarta Dsapi Redirector\\1.0"
/* Name of INI file relative to whatever the 'current' directory is when the filter is
* loaded. Certainly on Linux this is the Domino 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 struct private_ws
{
jk_pool_t p;
/* These get passed in by Domino and are used to access various
* Domino methods and data.
*/
FilterContext *context;
FilterParsedRequest *reqData;
/* True iff the response headers have been sent
*/
int responseStarted;
/* Current pointer into and remaining size
* of request body data
*/
char *reqBuffer;
unsigned int reqSize;
} private_ws_t;
/* These three functions are called back (indirectly) by
* Tomcat during request processing. StartResponse() sends
* the headers associated with the response.
*/
static int JK_METHOD StartResponse(jk_ws_service_t *s, int status,
const char *reason,
const char *const *hdrNames,
const char *const *hdrValues,
unsigned hdrCount);
/* Read() is called by Tomcat to read from the request body (if any).
*/
static int JK_METHOD Read(jk_ws_service_t *s, void *b, unsigned l,
unsigned *a);
/* Write() is called by Tomcat to send data back to the client.
*/
static int JK_METHOD Write(jk_ws_service_t *s, const void *b, unsigned l);
static int ReadInitData(void);
#ifndef USE_INIFILE
static const char *GetRegString(HKEY hkey, const char *key);
#endif
static unsigned int ParsedRequest(FilterContext * 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;
}
#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
/* Get the value of a server (CGI) variable as a string
*/
static int GetVariable(private_ws_t * ws, char *hdrName,
char *buf, DWORD bufsz, char **dest, const char *dflt)
{
int errID;
if (ws->context->
GetServerVariable(ws->context, hdrName, buf, bufsz, &errID))
*dest = jk_pool_strdup(&ws->p, buf);
else
*dest = jk_pool_strdup(&ws->p, dflt);
DEBUG(("%s = %s\n", hdrName, *dest));
return JK_TRUE;
}
/* Get the value of a server (CGI) variable as an integer
*/
static int GetVariableInt(private_ws_t * ws, char *hdrName,
char *buf, DWORD bufsz, int *dest, int dflt)
{
int errID;
if (ws->context->
GetServerVariable(ws->context, hdrName, buf, bufsz, &errID))
*dest = atoi(buf);
else
*dest = dflt;
DEBUG(("%s = %d\n", hdrName, *dest));
return JK_TRUE;
}
/* Get the value of a server (CGI) variable as an integer
*/
static int GetVariableBool(private_ws_t * ws, char *hdrName,
char *buf, DWORD bufsz, int *dest, int dflt)
{
int errID;
if (ws->context->
GetServerVariable(ws->context, hdrName, buf, bufsz, &errID)) {
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;
}
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(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 *hdrBuf;
FilterResponseHeaders frh;
int rc, errID;
p->responseStarted = JK_TRUE;
if (NULL == reason)
reason = "";
/* Build a single string containing all the headers
* because that's what Domino needs.
*/
if (hdrCount > 0) {
unsigned i;
unsigned hdrLen;
char *bufp;
for (i = 0, hdrLen = 3; i < hdrCount; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -