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

📄 mod_isapi.c

📁 apache的软件linux版本
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. *//* * mod_isapi.c - Internet Server Application (ISA) module for Apache * by Alexei Kosut <akosut apache.org>, significant overhauls and * redesign by William Rowe <wrowe covalent.net>, and hints from many * other developer/users who have hit on specific flaws. * * This module implements the ISAPI Handler architecture, allowing  * Apache to load Internet Server Applications (ISAPI extensions), * similar to the support in IIS, Zope, O'Reilly's WebSite and others. * * It is a complete implementation of the ISAPI 2.0 specification,  * except for "Microsoft extensions" to the API which provide  * asynchronous I/O.  It is further extended to include additional * "Microsoft extentions" through IIS 5.0, with some deficiencies * where one-to-one mappings don't exist. * * Refer to /manual/mod/mod_isapi.html for additional details on * configuration and use, but check this source for specific support * of the API,  */#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_protocol.h"#include "http_request.h"#include "http_log.h"#include "util_script.h"#include "mod_core.h"#include "apr_lib.h"#include "apr_strings.h"#include "apr_portable.h"#include "apr_buckets.h"#include "apr_thread_mutex.h"#include "apr_thread_rwlock.h"#include "apr_hash.h"#include "mod_isapi.h"/* Retry frequency for a failed-to-load isapi .dll */#define ISAPI_RETRY apr_time_from_sec(30)/********************************************************** * *  ISAPI Module Configuration * **********************************************************/module AP_MODULE_DECLARE_DATA isapi_module;#define ISAPI_UNDEF -1/* Our isapi per-dir config structure */typedef struct isapi_dir_conf {    int read_ahead_buflen;    int log_unsupported;    int log_to_errlog;    int log_to_query;    int fake_async;} isapi_dir_conf;typedef struct isapi_loaded isapi_loaded;apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r,                          const char *fpath, isapi_loaded** isa);static void *create_isapi_dir_config(apr_pool_t *p, char *dummy){    isapi_dir_conf *dir = apr_palloc(p, sizeof(isapi_dir_conf));    dir->read_ahead_buflen = ISAPI_UNDEF;    dir->log_unsupported   = ISAPI_UNDEF;    dir->log_to_errlog     = ISAPI_UNDEF;    dir->log_to_query      = ISAPI_UNDEF;    dir->fake_async        = ISAPI_UNDEF;    return dir;}static void *merge_isapi_dir_configs(apr_pool_t *p, void *base_, void *add_){    isapi_dir_conf *base = (isapi_dir_conf *) base_;    isapi_dir_conf *add = (isapi_dir_conf *) add_;    isapi_dir_conf *dir = apr_palloc(p, sizeof(isapi_dir_conf));    dir->read_ahead_buflen = (add->read_ahead_buflen == ISAPI_UNDEF)                                ? base->read_ahead_buflen                                 : add->read_ahead_buflen;    dir->log_unsupported   = (add->log_unsupported == ISAPI_UNDEF)                                ? base->log_unsupported                                 : add->log_unsupported;    dir->log_to_errlog     = (add->log_to_errlog == ISAPI_UNDEF)                                ? base->log_to_errlog                                 : add->log_to_errlog;    dir->log_to_query      = (add->log_to_query == ISAPI_UNDEF)                                ? base->log_to_query                                 : add->log_to_query;    dir->fake_async        = (add->fake_async == ISAPI_UNDEF)                                ? base->fake_async                                 : add->fake_async;    return dir;}static const char *isapi_cmd_cachefile(cmd_parms *cmd, void *dummy,                                       const char *filename){    isapi_loaded *isa;    apr_finfo_t tmp;    apr_status_t rv;    char *fspec;    /* ### Just an observation ... it would be terribly cool to be     * able to use this per-dir, relative to the directory block being     * defined.  The hash result remains global, but shorthand of     * <Directory "c:/webapps/isapi">     *     ISAPICacheFile myapp.dll anotherapp.dll thirdapp.dll     * </Directory>     * would be very convienent.     */    fspec = ap_server_root_relative(cmd->pool, filename);    if (!fspec) {        ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EBADPATH, cmd->server,                     "ISAPI: invalid module path, skipping %s", filename);        return NULL;    }    if ((rv = apr_stat(&tmp, fspec, APR_FINFO_TYPE,                      cmd->temp_pool)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server,            "ISAPI: unable to stat, skipping %s", fspec);        return NULL;    }    if (tmp.filetype != APR_REG) {        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,            "ISAPI: not a regular file, skipping %s", fspec);        return NULL;    }    /* Load the extention as cached (with null request_rec) */    rv = isapi_lookup(cmd->pool, cmd->server, NULL, fspec, &isa);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server,                     "ISAPI: unable to cache, skipping %s", fspec);        return NULL;    }    return NULL;}static const command_rec isapi_cmds[] = {    AP_INIT_TAKE1("ISAPIReadAheadBuffer", ap_set_int_slot,        (void *)APR_OFFSETOF(isapi_dir_conf, read_ahead_buflen),        OR_FILEINFO, "Maximum client request body to initially pass to the"                     " ISAPI handler (default: 49152)"),    AP_INIT_FLAG("ISAPILogNotSupported", ap_set_flag_slot,        (void *)APR_OFFSETOF(isapi_dir_conf, log_unsupported),        OR_FILEINFO, "Log requests not supported by the ISAPI server"                     " on or off (default: off)"),    AP_INIT_FLAG("ISAPIAppendLogToErrors", ap_set_flag_slot,        (void *)APR_OFFSETOF(isapi_dir_conf, log_to_errlog),        OR_FILEINFO, "Send all Append Log requests to the error log"                     " on or off (default: off)"),    AP_INIT_FLAG("ISAPIAppendLogToQuery", ap_set_flag_slot,        (void *)APR_OFFSETOF(isapi_dir_conf, log_to_query),        OR_FILEINFO, "Append Log requests are concatinated to the query args"                     " on or off (default: on)"),    AP_INIT_FLAG("ISAPIFakeAsync", ap_set_flag_slot,        (void *)APR_OFFSETOF(isapi_dir_conf, fake_async),        OR_FILEINFO, "Fake Asynchronous support for isapi callbacks"                     " on or off [Experimental] (default: off)"),    AP_INIT_ITERATE("ISAPICacheFile", isapi_cmd_cachefile, NULL,        RSRC_CONF, "Cache the specified ISAPI extension in-process"),    {NULL}};/********************************************************** * *  ISAPI Module Cache handling section * **********************************************************//* Our isapi global config values */static struct isapi_global_conf {    apr_pool_t         *pool;    apr_thread_mutex_t *lock;    apr_hash_t         *hash;} loaded;/* Our loaded isapi module description structure */struct isapi_loaded {    const char          *filename;    apr_thread_rwlock_t *in_progress;    apr_status_t         last_load_rv;    apr_time_t           last_load_time;    apr_dso_handle_t    *handle;    HSE_VERSION_INFO    *isapi_version;    apr_uint32_t         report_version;    apr_uint32_t         timeout;    PFN_GETEXTENSIONVERSION GetExtensionVersion;    PFN_HTTPEXTENSIONPROC   HttpExtensionProc;    PFN_TERMINATEEXTENSION  TerminateExtension;};static apr_status_t isapi_unload(isapi_loaded *isa, int force){    /* All done with the DLL... get rid of it...     *     * If optionally cached, and we weren't asked to force the unload,     * pass HSE_TERM_ADVISORY_UNLOAD, and if it returns 1, unload,     * otherwise, leave it alone (it didn't choose to cooperate.)     */    if (!isa->handle) {        return APR_SUCCESS;    }    if (isa->TerminateExtension) {        if (force) {            (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);        }        else if (!(*isa->TerminateExtension)(HSE_TERM_ADVISORY_UNLOAD)) {            return APR_EGENERAL;        }    }    apr_dso_unload(isa->handle);    isa->handle = NULL;    return APR_SUCCESS;}static apr_status_t cleanup_isapi(void *isa_){    isapi_loaded* isa = (isapi_loaded*) isa_;    /* We must force the module to unload, we are about     * to lose the isapi structure's allocation entirely.     */    return isapi_unload(isa, 1);}static apr_status_t isapi_load(apr_pool_t *p, server_rec *s, isapi_loaded *isa){    apr_status_t rv;    isa->isapi_version = apr_pcalloc(p, sizeof(HSE_VERSION_INFO));    /* TODO: These aught to become overrideable, so that we     * assure a given isapi can be fooled into behaving well.     *     * The tricky bit, they aren't really a per-dir sort of     * config, they will always be constant across every     * reference to the .dll no matter what context (vhost,     * location, etc) they apply to.     */    isa->report_version = 0x500; /* Revision 5.0 */    isa->timeout = 300 * 1000000; /* microsecs, not used */    rv = apr_dso_load(&isa->handle, isa->filename, p);    if (rv)    {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                     "ISAPI: failed to load %s", isa->filename);        isa->handle = NULL;        return rv;    }    rv = apr_dso_sym((void**)&isa->GetExtensionVersion, isa->handle,                     "GetExtensionVersion");    if (rv)    {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                     "ISAPI: missing GetExtensionVersion() in %s",                     isa->filename);        apr_dso_unload(isa->handle);        isa->handle = NULL;        return rv;    }    rv = apr_dso_sym((void**)&isa->HttpExtensionProc, isa->handle,                     "HttpExtensionProc");    if (rv)    {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                     "ISAPI: missing HttpExtensionProc() in %s",                     isa->filename);        apr_dso_unload(isa->handle);        isa->handle = NULL;        return rv;    }    /* TerminateExtension() is an optional interface */    rv = apr_dso_sym((void**)&isa->TerminateExtension, isa->handle,                     "TerminateExtension");    apr_set_os_error(0);    /* Run GetExtensionVersion() */    if (!(isa->GetExtensionVersion)(isa->isapi_version)) {        apr_status_t rv = apr_get_os_error();        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                     "ISAPI: failed call to GetExtensionVersion() in %s",                     isa->filename);        apr_dso_unload(isa->handle);        isa->handle = NULL;        return rv;    }    apr_pool_cleanup_register(p, isa, cleanup_isapi,                              apr_pool_cleanup_null);    return APR_SUCCESS;}apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r,                          const char *fpath, isapi_loaded** isa){    apr_status_t rv;    const char *key;    if ((rv = apr_thread_mutex_lock(loaded.lock)) != APR_SUCCESS) {        return rv;    }    *isa = apr_hash_get(loaded.hash, fpath, APR_HASH_KEY_STRING);    if (*isa) {        /* If we find this lock exists, use a set-aside copy of gainlock         * to avoid race conditions on NULLing the in_progress variable         * when the load has completed.  Release the global isapi hash         * lock so other requests can proceed, then rdlock for completion         * of loading our desired dll or wrlock if we would like to retry         * loading the dll (because last_load_rv failed and retry is up.)         */        apr_thread_rwlock_t *gainlock = (*isa)->in_progress;        /* gainlock is NULLed after the module loads successfully.         * This free-threaded module can be used without any locking.         */        if (!gainlock) {            rv = (*isa)->last_load_rv;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -