⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jk_dsapi_plugin.c

📁 精通tomcat书籍原代码,希望大家共同学习
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  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 + -