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

📄 mod_charset_lite.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 3 页
字号:
        }    }    if (!APR_BRIGADE_EMPTY(bb)) {        b = APR_BRIGADE_FIRST(bb);        if (APR_BUCKET_IS_EOS(b)) {            /* Leave the eos bucket in the brigade for reporting to             * subsequent filters.             */            *hit_eos = 1;            if (ctx->saved) {                /* Oops... we have a partial char from the previous bucket                 * that won't be completed because there's no more data.                 */                rv = APR_INCOMPLETE;                ctx->ees = EES_INCOMPLETE_CHAR;            }        }    }    return rv;}/* xlate_out_filter() handles (almost) arbitrary conversions from one charset * to another... * translation is determined in the fixup hook (find_code_page), which is * where the filter's context data is set up... the context data gives us * the translation handle */static apr_status_t xlate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb){    charset_req_t *reqinfo = ap_get_module_config(f->r->request_config,                                                  &charset_lite_module);    charset_dir_t *dc = ap_get_module_config(f->r->per_dir_config,                                             &charset_lite_module);    charset_filter_ctx_t *ctx = f->ctx;    apr_bucket *dptr, *consumed_bucket;    const char *cur_str;    apr_size_t cur_len, cur_avail;    char tmp[OUTPUT_XLATE_BUF_SIZE];    apr_size_t space_avail;    int done;    apr_status_t rv = APR_SUCCESS;    if (!ctx) {        /* this is SetOutputFilter path; grab the preallocated context,         * if any; note that if we decided not to do anything in an earlier         * handler, we won't even have a reqinfo         */        if (reqinfo) {            ctx = f->ctx = reqinfo->output_ctx;            reqinfo->output_ctx = NULL; /* prevent SNAFU if user coded us twice                                         * in the filter chain; we can't have two                                         * instances using the same context                                         */        }        if (!ctx) {                   /* no idea how to translate; don't do anything */            ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(charset_filter_ctx_t));            ctx->dc = dc;            ctx->noop = 1;        }    }    /* catch proxy requests */    if (f->r->proxyreq) return DECLINED;    /* Opening the output translation (this used to be done in the fixup hook,     * but that was too early: a subsequent type modification, e.g., by a     * CGI script, would go unnoticed. Now we do it in the filter itself.)     */    if (!ctx->noop && ctx->xlate == NULL)    {        const char *mime_type = f->r->content_type ? f->r->content_type : ap_default_type(f->r);        /* 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) == 0 ||#if APR_CHARSET_EBCDIC        /* 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) == 0 ||#endif        strncasecmp(mime_type, "message/", 8) == 0) {            rv = apr_xlate_open(&ctx->xlate,                        dc->charset_default, dc->charset_source, f->r->pool);            if (rv != APR_SUCCESS) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,                              "can't open translation %s->%s",                              dc->charset_source, dc->charset_default);                ctx->noop = 1;            }        }        else {                ctx->noop = 1;                if (dc->debug >= DBGLVL_GORY)                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,                                  "mime type is %s; no translation selected",                                  mime_type);            }    }    if (dc->debug >= DBGLVL_GORY) {        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,                     "xlate_out_filter() - "                     "charset_source: %s charset_default: %s",                     dc && dc->charset_source ? dc->charset_source : "(none)",                     dc && dc->charset_default ? dc->charset_default : "(none)");    }    if (!ctx->ran) {  /* filter never ran before */        chk_filter_chain(f);        ctx->ran = 1;    }    if (ctx->noop) {        return ap_pass_brigade(f->next, bb);    }    dptr = APR_BRIGADE_FIRST(bb);    done = 0;    cur_len = 0;    space_avail = sizeof(tmp);    consumed_bucket = NULL;    while (!done) {        if (!cur_len) { /* no bytes left to process in the current bucket... */            if (consumed_bucket) {                apr_bucket_delete(consumed_bucket);                consumed_bucket = NULL;            }            if (dptr == APR_BRIGADE_SENTINEL(bb)) {                done = 1;                break;            }            if (APR_BUCKET_IS_EOS(dptr)) {                done = 1;                cur_len = -1; /* XXX yuck, but that tells us to send                                 * eos down; when we minimize our bb construction                                 * we'll fix this crap */                if (ctx->saved) {                    /* Oops... we have a partial char from the previous bucket                     * that won't be completed because there's no more data.                     */                    rv = APR_INCOMPLETE;                    ctx->ees = EES_INCOMPLETE_CHAR;                }                break;            }            rv = apr_bucket_read(dptr, &cur_str, &cur_len, APR_BLOCK_READ);            if (rv != APR_SUCCESS) {                done = 1;                ctx->ees = EES_BUCKET_READ;                break;            }            consumed_bucket = dptr; /* for axing when we're done reading it */            dptr = APR_BUCKET_NEXT(dptr); /* get ready for when we access the                                          * next bucket */        }        /* Try to fill up our tmp buffer with translated data. */        cur_avail = cur_len;        if (cur_len) { /* maybe we just hit the end of a pipe (len = 0) ? */            if (ctx->saved) {                /* Rats... we need to finish a partial character from the previous                 * bucket.                 */                char *tmp_tmp;                tmp_tmp = tmp + sizeof(tmp) - space_avail;                rv = finish_partial_char(ctx,                                         &cur_str, &cur_len,                                         &tmp_tmp, &space_avail);            }            else {                rv = apr_xlate_conv_buffer(ctx->xlate,                                           cur_str, &cur_avail,                                           tmp + sizeof(tmp) - space_avail, &space_avail);                /* Update input ptr and len after consuming some bytes */                cur_str += cur_len - cur_avail;                cur_len = cur_avail;                if (rv == APR_INCOMPLETE) { /* partial character at end of input */                    /* We need to save the final byte(s) for next time; we can't                     * convert it until we look at the next bucket.                     */                    rv = set_aside_partial_char(ctx, cur_str, cur_len);                    cur_len = 0;                }            }        }        if (rv != APR_SUCCESS) {            /* bad input byte or partial char too big to store */            done = 1;        }        if (space_avail < XLATE_MIN_BUFF_LEFT) {            /* It is time to flush, as there is not enough space left in the             * current output buffer to bother with converting more data.             */            rv = send_downstream(f, tmp, sizeof(tmp) - space_avail);            if (rv != APR_SUCCESS) {                done = 1;            }            /* tmp is now empty */            space_avail = sizeof(tmp);        }    }    if (rv == APR_SUCCESS) {        if (space_avail < sizeof(tmp)) { /* gotta write out what we converted */            rv = send_downstream(f, tmp, sizeof(tmp) - space_avail);        }    }    if (rv == APR_SUCCESS) {        if (cur_len == -1) {            rv = send_eos(f);        }    }    else {        log_xlate_error(f, rv);    }    return rv;}static int xlate_in_filter(ap_filter_t *f, apr_bucket_brigade *bb,                           ap_input_mode_t mode, apr_read_type_e block,                           apr_off_t readbytes){    apr_status_t rv;    charset_req_t *reqinfo = ap_get_module_config(f->r->request_config,                                                  &charset_lite_module);    charset_dir_t *dc = ap_get_module_config(f->r->per_dir_config,                                             &charset_lite_module);    charset_filter_ctx_t *ctx = f->ctx;    apr_size_t buffer_size;    int hit_eos;    if (!ctx) {        /* this is SetInputFilter path; grab the preallocated context,         * if any; note that if we decided not to do anything in an earlier         * handler, we won't even have a reqinfo         */        if (reqinfo) {            ctx = f->ctx = reqinfo->input_ctx;            reqinfo->input_ctx = NULL; /* prevent SNAFU if user coded us twice                                        * in the filter chain; we can't have two                                        * instances using the same context                                        */        }        if (!ctx) {                   /* no idea how to translate; don't do anything */            ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(charset_filter_ctx_t));            ctx->dc = dc;            ctx->noop = 1;        }    }    if (dc->debug >= DBGLVL_GORY) {        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,                     "xlate_in_filter() - "                     "charset_source: %s charset_default: %s",                     dc && dc->charset_source ? dc->charset_source : "(none)",                     dc && dc->charset_default ? dc->charset_default : "(none)");    }    if (!ctx->ran) {  /* filter never ran before */        chk_filter_chain(f);        ctx->ran = 1;    }    if (ctx->noop) {        return ap_get_brigade(f->next, bb, mode, block, readbytes);    }    if (APR_BRIGADE_EMPTY(ctx->bb)) {        if ((rv = ap_get_brigade(f->next, bb, mode, block,                                 readbytes)) != APR_SUCCESS) {            return rv;        }    }    else {        APR_BRIGADE_PREPEND(bb, ctx->bb); /* first use the leftovers */    }    buffer_size = INPUT_XLATE_BUF_SIZE;    rv = xlate_brigade(ctx, bb, ctx->tmp, &buffer_size, &hit_eos);    if (rv == APR_SUCCESS) {        if (!hit_eos) {            /* move anything leftover into our context for next time;             * we don't currently "set aside" since the data came from             * down below, but I suspect that for long-term we need to             * do that             */            APR_BRIGADE_CONCAT(ctx->bb, bb);        }        if (buffer_size < INPUT_XLATE_BUF_SIZE) { /* do we have output? */            apr_bucket *e;            e = apr_bucket_heap_create(ctx->tmp,                                       INPUT_XLATE_BUF_SIZE - buffer_size,                                       NULL, f->r->connection->bucket_alloc);            /* make sure we insert at the head, because there may be             * an eos bucket already there, and the eos bucket should             * come after the data             */            APR_BRIGADE_INSERT_HEAD(bb, e);        }        else {            /* XXX need to get some more data... what if the last brigade             * we got had only the first byte of a multibyte char?  we need             * to grab more data from the network instead of returning an             * empty brigade             */        }    }    else {        log_xlate_error(f, rv);    }    return rv;}static const command_rec cmds[] ={    AP_INIT_TAKE1("CharsetSourceEnc",                  add_charset_source,                  NULL,                  OR_FILEINFO,                  "source (html,cgi,ssi) file charset"),    AP_INIT_TAKE1("CharsetDefault",                  add_charset_default,                  NULL,                  OR_FILEINFO,                  "name of default charset"),    AP_INIT_ITERATE("CharsetOptions",                    add_charset_options,                    NULL,                    OR_FILEINFO,                    "valid options: ImplicitAdd, NoImplicitAdd, DebugLevel=n"),    {NULL}};static void charset_register_hooks(apr_pool_t *p){    ap_hook_fixups(find_code_page, NULL, NULL, APR_HOOK_MIDDLE);    ap_hook_insert_filter(xlate_insert_filter, NULL, NULL, APR_HOOK_REALLY_LAST);    ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, NULL,                              AP_FTYPE_RESOURCE);    ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, NULL,                             AP_FTYPE_RESOURCE);}module AP_MODULE_DECLARE_DATA charset_lite_module ={    STANDARD20_MODULE_STUFF,    create_charset_dir_conf,    merge_charset_dir_conf,    NULL,    NULL,    cmds,    charset_register_hooks};

⌨️ 快捷键说明

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