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

📄 mod_charset_lite.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 2000-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. *//* * simple hokey charset recoding configuration module * * See mod_ebcdic and mod_charset for more thought-out examples.  This * one is just so Jeff can learn how a module works and experiment with * basic character set recoding configuration. * * !!!This is an extremely cheap ripoff of mod_charset.c from Russian Apache!!! */#include "httpd.h"#include "http_config.h"#define CORE_PRIVATE#include "http_core.h"#include "http_log.h"#include "http_main.h"#include "http_protocol.h"#include "http_request.h"#include "util_charset.h"#include "apr_buckets.h"#include "util_filter.h"#include "apr_strings.h"#include "apr_lib.h"#include "apr_xlate.h"#define APR_WANT_STRFUNC#include "apr_want.h"#define OUTPUT_XLATE_BUF_SIZE (16*1024) /* size of translation buffer used on output */#define INPUT_XLATE_BUF_SIZE  (8*1024)  /* size of translation buffer used on input */#define XLATE_MIN_BUFF_LEFT 128  /* flush once there is no more than this much                                  * space left in the translation buffer                                   */#define FATTEST_CHAR  8          /* we don't handle chars wider than this that straddle                                   * two buckets                                  *//* extended error status codes; this is used in addition to an apr_status_t to * track errors in the translation filter */typedef enum {    EES_INIT = 0,   /* no error info yet; value must be 0 for easy init */    EES_LIMIT,      /* built-in restriction encountered */    EES_INCOMPLETE_CHAR, /* incomplete multi-byte char at end of content */    EES_BUCKET_READ,    EES_DOWNSTREAM, /* something bad happened in a filter below xlate */    EES_BAD_INPUT   /* input data invalid */} ees_t;/* registered name of the output translation filter */#define XLATEOUT_FILTER_NAME "XLATEOUT"/* registered name of input translation filter */#define XLATEIN_FILTER_NAME  "XLATEIN" typedef struct charset_dir_t {    /** debug level; -1 means uninitialized, 0 means no debug */    int debug;    const char *charset_source; /* source encoding */    const char *charset_default; /* how to ship on wire */    /** module does ap_add_*_filter()? */        enum {IA_INIT, IA_IMPADD, IA_NOIMPADD} implicit_add; } charset_dir_t;/* charset_filter_ctx_t is created for each filter instance; because the same * filter code is used for translating in both directions, we need this context * data to tell the filter which translation handle to use; it also can hold a * character which was split between buckets */typedef struct charset_filter_ctx_t {    apr_xlate_t *xlate;    charset_dir_t *dc;    ees_t ees;              /* extended error status */    apr_size_t saved;    char buf[FATTEST_CHAR]; /* we want to be able to build a complete char here */    int ran;                /* has filter instance run before? */    int noop;               /* should we pass brigades through unchanged? */    char *tmp;              /* buffer for input filtering */    apr_bucket_brigade *bb; /* input buckets we couldn't finish translating */} charset_filter_ctx_t;/* charset_req_t is available via r->request_config if any translation is * being performed */typedef struct charset_req_t {    charset_dir_t *dc;    charset_filter_ctx_t *output_ctx, *input_ctx;} charset_req_t;/* debug level definitions */#define DBGLVL_GORY           9 /* gory details */#define DBGLVL_FLOW           4 /* enough messages to see what happens on                                 * each request */#define DBGLVL_PMC            2 /* messages about possible misconfiguration */module AP_MODULE_DECLARE_DATA charset_lite_module;static void *create_charset_dir_conf(apr_pool_t *p,char *dummy){    charset_dir_t *dc = (charset_dir_t *)apr_pcalloc(p,sizeof(charset_dir_t));    dc->debug = -1;    return dc;}static void *merge_charset_dir_conf(apr_pool_t *p, void *basev, void *overridesv){    charset_dir_t *a = (charset_dir_t *)apr_pcalloc (p, sizeof(charset_dir_t));    charset_dir_t *base = (charset_dir_t *)basev,        *over = (charset_dir_t *)overridesv;    /* If it is defined in the current container, use it.  Otherwise, use the one     * from the enclosing container.      */    a->debug =         over->debug != -1 ? over->debug : base->debug;    a->charset_default =         over->charset_default ? over->charset_default : base->charset_default;    a->charset_source =         over->charset_source ? over->charset_source : base->charset_source;    a->implicit_add =        over->implicit_add != IA_INIT ? over->implicit_add : base->implicit_add;    return a;}/* CharsetSourceEnc charset */static const char *add_charset_source(cmd_parms *cmd, void *in_dc,                                      const char *name){    charset_dir_t *dc = in_dc;    dc->charset_source = name;    return NULL;}/* CharsetDefault charset */static const char *add_charset_default(cmd_parms *cmd, void *in_dc,                                        const char *name){    charset_dir_t *dc = in_dc;    dc->charset_default = name;    return NULL;}/* CharsetOptions optionflag... */static const char *add_charset_options(cmd_parms *cmd, void *in_dc,                                        const char *flag){    charset_dir_t *dc = in_dc;    if (!strcasecmp(flag, "ImplicitAdd")) {        dc->implicit_add = IA_IMPADD;    }    else if (!strcasecmp(flag, "NoImplicitAdd")) {        dc->implicit_add = IA_NOIMPADD;    }    else if (!strncasecmp(flag, "DebugLevel=", 11)) {        dc->debug = atoi(flag + 11);    }    else {        return apr_pstrcat(cmd->temp_pool,                            "Invalid CharsetOptions option: ",                           flag,                           NULL);    }    return NULL;}/* find_code_page() is a fixup hook that decides if translation should be * enabled; if so, it sets up request data for use by the filter registration * hook so that it knows what to do */static int find_code_page(request_rec *r){    charset_dir_t *dc = ap_get_module_config(r->per_dir_config,                                              &charset_lite_module);    charset_req_t *reqinfo;    charset_filter_ctx_t *input_ctx, *output_ctx;    apr_status_t rv;    const char *mime_type;    if (dc->debug >= DBGLVL_FLOW) {        ap_log_rerror(APLOG_MARK,APLOG_DEBUG, 0, r,                      "uri: %s file: %s method: %d "                      "imt: %s flags: %s%s%s %s->%s",                      r->uri, r->filename, r->method_number,                      r->content_type ? r->content_type : "(unknown)",                      r->main     ? "S" : "",    /* S if subrequest */                      r->prev     ? "R" : "",    /* R if redirect */                      r->proxyreq ? "P" : "",    /* P if proxy */                      dc->charset_source, dc->charset_default);    }    /* If we don't have a full directory configuration, bail out.     */    if (!dc->charset_source || !dc->charset_default) {        if (dc->debug >= DBGLVL_PMC) {            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                          "incomplete configuration: src %s, dst %s",                          dc->charset_source ? dc->charset_source : "unspecified",                          dc->charset_default ? dc->charset_default : "unspecified");        }        return DECLINED;    }    /* catch proxy requests */    if (r->proxyreq) return DECLINED;    /* mod_rewrite indicators */    if (!strncmp(r->filename, "redirect:", 9)) return DECLINED;     if (!strncmp(r->filename, "gone:", 5)) return DECLINED;     if (!strncmp(r->filename, "passthrough:", 12)) return DECLINED;     if (!strncmp(r->filename, "forbidden:", 10)) return DECLINED;         mime_type = r->content_type ? r->content_type : ap_default_type(r);    /* If mime type isn't text or message, bail out.     *//* XXX When we handle translation of the request body, watch out here as *     1.3 allowed additional mime types: multipart and  *     application/x-www-form-urlencoded */                 if (strncasecmp(mime_type, "text/", 5) &&#if APR_CHARSET_EBCDIC || AP_WANT_DIR_TRANSLATION        /* On an EBCDIC machine, be willing to translate mod_autoindex-         * generated output.  Otherwise, it doesn't look too cool.         *         * XXX This isn't a perfect fix because this doesn't trigger us         * to convert from the charset of the source code to ASCII.  The         * general solution seems to be to allow a generator to set an         * indicator in the r specifying that the body is coded in the         * implementation character set (i.e., the charset of the source         * code).  This would get several different types of documents         * translated properly: mod_autoindex output, mod_status output,         * mod_info output, hard-coded error documents, etc.         */        strcmp(mime_type, DIR_MAGIC_TYPE) &&#endif        strncasecmp(mime_type, "message/", 8)) {        if (dc->debug >= DBGLVL_GORY) {            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                          "mime type is %s; no translation selected",                          mime_type);        }        return DECLINED;    }    if (dc->debug >= DBGLVL_GORY) {        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                      "charset_source: %s charset_default: %s",                      dc && dc->charset_source ? dc->charset_source : "(none)",                      dc && dc->charset_default ? dc->charset_default : "(none)");    }    /* Get storage for the request data and the output filter context.     * We rarely need the input filter context, so allocate that separately.     */    reqinfo = (charset_req_t *)apr_pcalloc(r->pool,                                            sizeof(charset_req_t) +                                            sizeof(charset_filter_ctx_t));    output_ctx = (charset_filter_ctx_t *)(reqinfo + 1);    reqinfo->dc = dc;    output_ctx->dc = dc;    ap_set_module_config(r->request_config, &charset_lite_module, reqinfo);    reqinfo->output_ctx = output_ctx;    rv = apr_xlate_open(&output_ctx->xlate,                         dc->charset_default, dc->charset_source, r->pool);    if (rv != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                      "can't open translation %s->%s",                      dc->charset_source, dc->charset_default);        return HTTP_INTERNAL_SERVER_ERROR;    }    switch (r->method_number) {    case M_PUT:    case M_POST:        /* Set up input translation.  Note: A request body can be included          * with the OPTIONS method, but for now we don't set up translation          * of it.         */        input_ctx = apr_pcalloc(r->pool, sizeof(charset_filter_ctx_t));        input_ctx->bb = apr_brigade_create(r->pool,                                           r->connection->bucket_alloc);        input_ctx->tmp = apr_palloc(r->pool, INPUT_XLATE_BUF_SIZE);        input_ctx->dc = dc;        reqinfo->input_ctx = input_ctx;        rv = apr_xlate_open(&input_ctx->xlate, dc->charset_source,                             dc->charset_default, r->pool);        if (rv != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "can't open translation %s->%s",                          dc->charset_default, dc->charset_source);            return HTTP_INTERNAL_SERVER_ERROR;        }    }    return DECLINED;}static int configured_in_list(request_rec *r, const char *filter_name,                              struct ap_filter_t *filter_list){    struct ap_filter_t *filter = filter_list;    while (filter) {        if (!strcasecmp(filter_name, filter->frec->name)) {            return 1;        }        filter = filter->next;    }    return 0;}static int configured_on_input(request_rec *r, const char *filter_name){    return configured_in_list(r, filter_name, r->input_filters);}static int configured_on_output(request_rec *r, const char *filter_name){    return configured_in_list(r, filter_name, r->output_filters);}/* xlate_insert_filter() is a filter hook which decides whether or not * to insert a translation filter for the current request. */static void xlate_insert_filter(request_rec *r){    /* Hey... don't be so quick to use reqinfo->dc here; reqinfo may be NULL */    charset_req_t *reqinfo = ap_get_module_config(r->request_config,                                                   &charset_lite_module);    charset_dir_t *dc = ap_get_module_config(r->per_dir_config,                                              &charset_lite_module);    if (reqinfo) {

⌨️ 快捷键说明

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