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

📄 mod_ext_filter.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as * applicable. * * 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. *//* * mod_ext_filter allows Unix-style filters to filter http content. */#include "httpd.h"#include "http_config.h"#include "http_log.h"#include "http_protocol.h"#define CORE_PRIVATE#include "http_core.h"#include "apr_buckets.h"#include "util_filter.h"#include "util_script.h"#include "util_time.h"#include "apr_strings.h"#include "apr_hash.h"#include "apr_lib.h"#include "apr_poll.h"#define APR_WANT_STRFUNC#include "apr_want.h"typedef struct ef_server_t {    apr_pool_t *p;    apr_hash_t *h;} ef_server_t;typedef struct ef_filter_t {    const char *name;    enum {INPUT_FILTER=1, OUTPUT_FILTER} mode;    ap_filter_type ftype;    const char *command;    const char *enable_env;    const char *disable_env;    char **args;    const char *intype;             /* list of IMTs we process (well, just one for now) */#define INTYPE_ALL (char *)1    const char *outtype;            /* IMT of filtered output */#define OUTTYPE_UNCHANGED (char *)1    int preserves_content_length;} ef_filter_t;typedef struct ef_dir_t {    int debug;    int log_stderr;} ef_dir_t;typedef struct ef_ctx_t {    apr_pool_t *p;    apr_proc_t *proc;    apr_procattr_t *procattr;    ef_dir_t *dc;    ef_filter_t *filter;    int noop;#if APR_FILES_AS_SOCKETS    apr_pollfd_t *pollset;#endif} ef_ctx_t;module AP_MODULE_DECLARE_DATA ext_filter_module;static const server_rec *main_server;static apr_status_t ef_output_filter(ap_filter_t *, apr_bucket_brigade *);#define DBGLVL_SHOWOPTIONS         1#define DBGLVL_ERRORCHECK          2#define DBGLVL_GORY                9#define ERRFN_USERDATA_KEY         "EXTFILTCHILDERRFN"static void *create_ef_dir_conf(apr_pool_t *p, char *dummy){    ef_dir_t *dc = (ef_dir_t *)apr_pcalloc(p, sizeof(ef_dir_t));    dc->debug = -1;    dc->log_stderr = -1;    return dc;}static void *create_ef_server_conf(apr_pool_t *p, server_rec *s){    ef_server_t *conf;    conf = (ef_server_t *)apr_pcalloc(p, sizeof(ef_server_t));    conf->p = p;    conf->h = apr_hash_make(conf->p);    return conf;}static void *merge_ef_dir_conf(apr_pool_t *p, void *basev, void *overridesv){    ef_dir_t *a = (ef_dir_t *)apr_pcalloc (p, sizeof(ef_dir_t));    ef_dir_t *base = (ef_dir_t *)basev, *over = (ef_dir_t *)overridesv;    if (over->debug != -1) {        /* if admin coded something... */        a->debug = over->debug;    }    else {        a->debug = base->debug;    }    if (over->log_stderr != -1) {   /* if admin coded something... */        a->log_stderr = over->log_stderr;    }    else {        a->log_stderr = base->log_stderr;    }    return a;}static const char *add_options(cmd_parms *cmd, void *in_dc,                               const char *arg){    ef_dir_t *dc = in_dc;    if (!strncasecmp(arg, "DebugLevel=", 11)) {        dc->debug = atoi(arg + 11);    }    else if (!strcasecmp(arg, "LogStderr")) {        dc->log_stderr = 1;    }    else if (!strcasecmp(arg, "NoLogStderr")) {        dc->log_stderr = 0;    }    else {        return apr_pstrcat(cmd->temp_pool,                            "Invalid ExtFilterOptions option: ",                           arg,                           NULL);    }    return NULL;}static const char *parse_cmd(apr_pool_t *p, const char **args, ef_filter_t *filter){    if (**args == '"') {        const char *start = *args + 1;        char *parms;        int escaping = 0;        apr_status_t rv;        ++*args; /* move past leading " */        /* find true end of args string (accounting for escaped quotes) */        while (**args && (**args != '"' || (**args == '"' && escaping))) {            if (escaping) {                escaping = 0;            }            else if (**args == '\\') {                escaping = 1;            }            ++*args;        }        if (**args != '"') {            return "Expected cmd= delimiter";        }        /* copy *just* the arg string for parsing, */        parms = apr_pstrndup(p, start, *args - start);        ++*args; /* move past trailing " */        /* parse and tokenize the args. */        rv = apr_tokenize_to_argv(parms, &(filter->args), p);        if (rv != APR_SUCCESS) {            return "cmd= parse error";        }    }    else    {        /* simple path */        /* Allocate space for two argv pointers and parse the args. */        filter->args = (char **)apr_palloc(p, 2 * sizeof(char *));        filter->args[0] = ap_getword_white(p, args);        filter->args[1] = NULL; /* end of args */    }    if (!filter->args[0]) {        return "Invalid cmd= parameter";    }    filter->command = filter->args[0];        return NULL;}static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args){    ef_server_t *conf = ap_get_module_config(cmd->server->module_config,                                             &ext_filter_module);    const char *token;    const char *name;    ef_filter_t *filter;    name = ap_getword_white(cmd->pool, &args);    if (!name) {        return "Filter name not found";    }    if (apr_hash_get(conf->h, name, APR_HASH_KEY_STRING)) {        return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",                            name);    }    filter = (ef_filter_t *)apr_pcalloc(conf->p, sizeof(ef_filter_t));    filter->name = name;    filter->mode = OUTPUT_FILTER;    filter->ftype = AP_FTYPE_RESOURCE;    apr_hash_set(conf->h, name, APR_HASH_KEY_STRING, filter);    while (*args) {        while (apr_isspace(*args)) {            ++args;        }        /* Nasty parsing...  I wish I could simply use ap_getword_white()         * here and then look at the token, but ap_getword_white() doesn't         * do the right thing when we have cmd="word word word"         */        if (!strncasecmp(args, "preservescontentlength", 22)) {            token = ap_getword_white(cmd->pool, &args);            if (!strcasecmp(token, "preservescontentlength")) {                filter->preserves_content_length = 1;            }            else {                return apr_psprintf(cmd->pool,                                     "mangled argument `%s'",                                    token);            }            continue;        }        if (!strncasecmp(args, "mode=", 5)) {            args += 5;            token = ap_getword_white(cmd->pool, &args);            if (!strcasecmp(token, "output")) {                filter->mode = OUTPUT_FILTER;            }            else if (!strcasecmp(token, "input")) {                filter->mode = INPUT_FILTER;            }            else {                return apr_psprintf(cmd->pool, "Invalid mode: `%s'",                                    token);            }            continue;        }        if (!strncasecmp(args, "ftype=", 6)) {            args += 6;            token = ap_getword_white(cmd->pool, &args);            filter->ftype = atoi(token);            continue;        }        if (!strncasecmp(args, "enableenv=", 10)) {            args += 10;            token = ap_getword_white(cmd->pool, &args);            filter->enable_env = token;            continue;        }                if (!strncasecmp(args, "disableenv=", 11)) {            args += 11;            token = ap_getword_white(cmd->pool, &args);            filter->disable_env = token;            continue;        }                if (!strncasecmp(args, "intype=", 7)) {            args += 7;            filter->intype = ap_getword_white(cmd->pool, &args);            continue;        }        if (!strncasecmp(args, "outtype=", 8)) {            args += 8;            filter->outtype = ap_getword_white(cmd->pool, &args);            continue;        }        if (!strncasecmp(args, "cmd=", 4)) {            args += 4;            if ((token = parse_cmd(cmd->pool, &args, filter))) {                return token;            }            continue;        }        return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'",                            args);    }    /* parsing is done...  register the filter      */    if (filter->mode == OUTPUT_FILTER) {        /* XXX need a way to ensure uniqueness among all filters */        ap_register_output_filter(filter->name, ef_output_filter, NULL, filter->ftype);    }#if 0              /* no input filters yet */    else if (filter->mode == INPUT_FILTER) {        /* XXX need a way to ensure uniqueness among all filters */        ap_register_input_filter(filter->name, ef_input_filter, NULL, AP_FTYPE_RESOURCE);    }#endif    else {        ap_assert(1 != 1); /* we set the field wrong somehow */    }    return NULL;}static const command_rec cmds[] ={    AP_INIT_ITERATE("ExtFilterOptions",                    add_options,                    NULL,                    ACCESS_CONF, /* same as SetInputFilter/SetOutputFilter */                    "valid options: DebugLevel=n, LogStderr, NoLogStderr"),    AP_INIT_RAW_ARGS("ExtFilterDefine",                     define_filter,                     NULL,                     RSRC_CONF,                     "Define an external filter"),    {NULL}};static int ef_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_s){    main_server = main_s;    return OK;}static void register_hooks(apr_pool_t *p){    ap_hook_post_config(ef_init, NULL, NULL, APR_HOOK_MIDDLE);}static apr_status_t set_resource_limits(request_rec *r,                                         apr_procattr_t *procattr){#if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \    defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)    core_dir_config *conf =         (core_dir_config *)ap_get_module_config(r->per_dir_config,                                                &core_module);    apr_status_t rv;#ifdef RLIMIT_CPU    rv = apr_procattr_limit_set(procattr, APR_LIMIT_CPU, conf->limit_cpu);    ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */#endif#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)    rv = apr_procattr_limit_set(procattr, APR_LIMIT_MEM, conf->limit_mem);    ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */#endif#ifdef RLIMIT_NPROC    rv = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, conf->limit_nproc);    ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */#endif#endif /* if at least one limit defined */    return APR_SUCCESS;}static apr_status_t ef_close_file(void *vfile){    return apr_file_close(vfile);}static void child_errfn(apr_pool_t *pool, apr_status_t err, const char *description){    request_rec *r;    void *vr;    apr_file_t *stderr_log;    char errbuf[200];    char time_str[APR_CTIME_LEN];    apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);    r = vr;    apr_file_open_stderr(&stderr_log, pool);    ap_recent_ctime(time_str, apr_time_now());    apr_file_printf(stderr_log,                    "[%s] [client %s] mod_ext_filter (%d)%s: %s\n",                    time_str,                    r->connection->remote_ip,                    err,                    apr_strerror(err, errbuf, sizeof(errbuf)),                    description);}/* init_ext_filter_process: get the external filter process going * This is per-filter-instance (i.e., per-request) initialization. */static apr_status_t init_ext_filter_process(ap_filter_t *f){    ef_ctx_t *ctx = f->ctx;    apr_status_t rc;    ef_dir_t *dc = ctx->dc;    const char * const *env;    ctx->proc = apr_pcalloc(ctx->p, sizeof(*ctx->proc));    rc = apr_procattr_create(&ctx->procattr, ctx->p);    ap_assert(rc == APR_SUCCESS);    rc = apr_procattr_io_set(ctx->procattr,                            APR_CHILD_BLOCK,                            APR_CHILD_BLOCK,                            APR_CHILD_BLOCK);    ap_assert(rc == APR_SUCCESS);    rc = set_resource_limits(f->r, ctx->procattr);    ap_assert(rc == APR_SUCCESS);    if (dc->log_stderr > 0) {        rc = apr_procattr_child_err_set(ctx->procattr,                                      f->r->server->error_log, /* stderr in child */                                      NULL);        ap_assert(rc == APR_SUCCESS);    }    rc = apr_procattr_child_errfn_set(ctx->procattr, child_errfn);    ap_assert(rc == APR_SUCCESS);    apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p);        if (dc->debug >= DBGLVL_ERRORCHECK) {        rc = apr_procattr_error_check_set(ctx->procattr, 1);        ap_assert(rc == APR_SUCCESS);    }        /* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO,

⌨️ 快捷键说明

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