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

📄 mod_charset_lite.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 3 页
字号:
    apr_brigade_cleanup(ctx->tmpbb);    return rv;}/* send_downstream() is passed the translated data; it puts it in a single- * bucket brigade and passes the brigade to the next filter */static apr_status_t send_downstream(ap_filter_t *f, const char *tmp, apr_size_t len){    request_rec *r = f->r;    conn_rec *c = r->connection;    apr_bucket *b;    b = apr_bucket_transient_create(tmp, len, c->bucket_alloc);    return send_bucket_downstream(f, b);}static apr_status_t send_eos(ap_filter_t *f){    request_rec *r = f->r;    conn_rec *c = r->connection;    apr_bucket_brigade *bb;    apr_bucket *b;    charset_filter_ctx_t *ctx = f->ctx;    apr_status_t rv;    bb = apr_brigade_create(r->pool, c->bucket_alloc);    b = apr_bucket_eos_create(c->bucket_alloc);    APR_BRIGADE_INSERT_TAIL(bb, b);    rv = ap_pass_brigade(f->next, bb);    if (rv != APR_SUCCESS) {        ctx->ees = EES_DOWNSTREAM;    }    return rv;}static apr_status_t set_aside_partial_char(charset_filter_ctx_t *ctx,                                           const char *partial,                                           apr_size_t partial_len){    apr_status_t rv;    if (sizeof(ctx->buf) > partial_len) {        ctx->saved = partial_len;        memcpy(ctx->buf, partial, partial_len);        rv = APR_SUCCESS;    }    else {        rv = APR_INCOMPLETE;        ctx->ees = EES_LIMIT; /* we don't handle chars this wide which straddle                               * buckets                               */    }    return rv;}static apr_status_t finish_partial_char(charset_filter_ctx_t *ctx,                                        /* input buffer: */                                        const char **cur_str,                                        apr_size_t *cur_len,                                        /* output buffer: */                                        char **out_str,                                        apr_size_t *out_len){    apr_status_t rv;    apr_size_t tmp_input_len;    /* Keep adding bytes from the input string to the saved string until we     *    1) finish the input char     *    2) get an error     * or 3) run out of bytes to add     */    do {        ctx->buf[ctx->saved] = **cur_str;        ++ctx->saved;        ++*cur_str;        --*cur_len;        tmp_input_len = ctx->saved;        rv = apr_xlate_conv_buffer(ctx->xlate,                                   ctx->buf,                                   &tmp_input_len,                                   *out_str,                                   out_len);    } while (rv == APR_INCOMPLETE && *cur_len);    if (rv == APR_SUCCESS) {        ctx->saved = 0;    }    else {        ctx->ees = EES_LIMIT; /* code isn't smart enough to handle chars                               * straddling more than two buckets                               */    }    return rv;}static void log_xlate_error(ap_filter_t *f, apr_status_t rv){    charset_filter_ctx_t *ctx = f->ctx;    const char *msg;    char msgbuf[100];    int cur;    switch(ctx->ees) {    case EES_LIMIT:        rv = 0;        msg = "xlate filter - a built-in restriction was encountered";        break;    case EES_BAD_INPUT:        rv = 0;        msg = "xlate filter - an input character was invalid";        break;    case EES_BUCKET_READ:        rv = 0;        msg = "xlate filter - bucket read routine failed";        break;    case EES_INCOMPLETE_CHAR:        rv = 0;        strcpy(msgbuf, "xlate filter - incomplete char at end of input - ");        cur = 0;        while ((apr_size_t)cur < ctx->saved) {            apr_snprintf(msgbuf + strlen(msgbuf), sizeof(msgbuf) - strlen(msgbuf),                         "%02X", (unsigned)ctx->buf[cur]);            ++cur;        }        msg = msgbuf;        break;    case EES_DOWNSTREAM:        msg = "xlate filter - an error occurred in a lower filter";        break;    default:        msg = "xlate filter - returning error";    }    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,                  "%s", msg);}/* chk_filter_chain() is called once per filter instance; it tries to * determine if the current filter instance should be disabled because * its translation is incompatible with the translation of an existing * instance of the translate filter * * Example bad scenario: * *   configured filter chain for the request: *     INCLUDES XLATEOUT(8859-1->UTS-16) *   configured filter chain for the subrequest: *     XLATEOUT(8859-1->UTS-16) * *   When the subrequest is processed, the filter chain will be *     XLATEOUT(8859-1->UTS-16) XLATEOUT(8859-1->UTS-16) *   This makes no sense, so the instance of XLATEOUT added for the *   subrequest will be noop-ed. * * Example good scenario: * *   configured filter chain for the request: *     INCLUDES XLATEOUT(8859-1->UTS-16) *   configured filter chain for the subrequest: *     XLATEOUT(IBM-1047->8859-1) * *   When the subrequest is processed, the filter chain will be *     XLATEOUT(IBM-1047->8859-1) XLATEOUT(8859-1->UTS-16) *   This makes sense, so the instance of XLATEOUT added for the *   subrequest will be left alone and it will translate from *   IBM-1047->8859-1. */static void chk_filter_chain(ap_filter_t *f){    ap_filter_t *curf;    charset_filter_ctx_t *curctx, *last_xlate_ctx = NULL,        *ctx = f->ctx;    int debug = ctx->dc->debug;    int output = !strcasecmp(f->frec->name, XLATEOUT_FILTER_NAME);    if (ctx->noop) {        return;    }    /* walk the filter chain; see if it makes sense for our filter to     * do any translation     */    curf = output ? f->r->output_filters : f->r->input_filters;    while (curf) {        if (!strcasecmp(curf->frec->name, f->frec->name) &&            curf->ctx) {            curctx = (charset_filter_ctx_t *)curf->ctx;            if (!last_xlate_ctx) {                last_xlate_ctx = curctx;            }            else {                if (strcmp(last_xlate_ctx->dc->charset_default,                           curctx->dc->charset_source)) {                    /* incompatible translation                     * if our filter instance is incompatible with an instance                     * already in place, noop our instance                     * Notes:                     * . We are only willing to noop our own instance.                     * . It is possible to noop another instance which has not                     *   yet run, but this is not currently implemented.                     *   Hopefully it will not be needed.                     * . It is not possible to noop an instance which has                     *   already run.                     */                    if (last_xlate_ctx == f->ctx) {                        last_xlate_ctx->noop = 1;                        if (debug >= DBGLVL_PMC) {                            const char *symbol = output ? "->" : "<-";                            ap_log_rerror(APLOG_MARK, APLOG_DEBUG,                                          0, f->r,                                          "%s %s - disabling "                                          "translation %s%s%s; existing "                                          "translation %s%s%s",                                          f->r->uri ? "uri" : "file",                                          f->r->uri ? f->r->uri : f->r->filename,                                          last_xlate_ctx->dc->charset_source,                                          symbol,                                          last_xlate_ctx->dc->charset_default,                                          curctx->dc->charset_source,                                          symbol,                                          curctx->dc->charset_default);                        }                    }                    else {                        const char *symbol = output ? "->" : "<-";                        ap_log_rerror(APLOG_MARK, APLOG_ERR,                                      0, f->r,                                      "chk_filter_chain() - can't disable "                                      "translation %s%s%s; existing "                                      "translation %s%s%s",                                      last_xlate_ctx->dc->charset_source,                                      symbol,                                      last_xlate_ctx->dc->charset_default,                                      curctx->dc->charset_source,                                      symbol,                                      curctx->dc->charset_default);                    }                    break;                }            }        }        curf = curf->next;    }}/* xlate_brigade() is used to filter request and response bodies * * we'll stop when one of the following occurs: * . we run out of buckets * . we run out of space in the output buffer * . we hit an error or metadata * * inputs: *   bb:               brigade to process *   buffer:           storage to hold the translated characters *   buffer_avail:     size of buffer *   (and a few more uninteresting parms) * * outputs: *   return value:     APR_SUCCESS or some error code *   bb:               we've removed any buckets representing the *                     translated characters; the eos bucket, if *                     present, will be left in the brigade *   buffer:           filled in with translated characters *   buffer_avail:     updated with the bytes remaining *   hit_eos:          did we hit an EOS bucket? */static apr_status_t xlate_brigade(charset_filter_ctx_t *ctx,                                  apr_bucket_brigade *bb,                                  char *buffer,                                  apr_size_t *buffer_avail,                                  int *hit_eos){    apr_bucket *b = NULL; /* set to NULL only to quiet some gcc */    apr_bucket *consumed_bucket;    const char *bucket;    apr_size_t bytes_in_bucket; /* total bytes read from current bucket */    apr_size_t bucket_avail;    /* bytes left in current bucket */    apr_status_t rv = APR_SUCCESS;    *hit_eos = 0;    bucket_avail = 0;    consumed_bucket = NULL;    while (1) {        if (!bucket_avail) { /* no bytes left to process in the current bucket... */            if (consumed_bucket) {                apr_bucket_delete(consumed_bucket);                consumed_bucket = NULL;            }            b = APR_BRIGADE_FIRST(bb);            if (b == APR_BRIGADE_SENTINEL(bb) ||                APR_BUCKET_IS_METADATA(b)) {                break;            }            rv = apr_bucket_read(b, &bucket, &bytes_in_bucket, APR_BLOCK_READ);            if (rv != APR_SUCCESS) {                ctx->ees = EES_BUCKET_READ;                break;            }            bucket_avail = bytes_in_bucket;            consumed_bucket = b;   /* for axing when we're done reading it */        }        if (bucket_avail) {            /* We've got data, so translate it. */            if (ctx->saved) {                /* Rats... we need to finish a partial character from the previous                 * bucket.                 *                 * Strangely, finish_partial_char() increments the input buffer                 * pointer but does not increment the output buffer pointer.                 */                apr_size_t old_buffer_avail = *buffer_avail;                rv = finish_partial_char(ctx,                                         &bucket, &bucket_avail,                                         &buffer, buffer_avail);                buffer += old_buffer_avail - *buffer_avail;            }            else {                apr_size_t old_buffer_avail = *buffer_avail;                apr_size_t old_bucket_avail = bucket_avail;                rv = apr_xlate_conv_buffer(ctx->xlate,                                           bucket, &bucket_avail,                                           buffer,                                           buffer_avail);                buffer  += old_buffer_avail - *buffer_avail;                bucket  += old_bucket_avail - bucket_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, bucket, bucket_avail);                    bucket_avail = 0;                }            }            if (rv != APR_SUCCESS) {                /* bad input byte or partial char too big to store */                break;            }            if (*buffer_avail < XLATE_MIN_BUFF_LEFT) {                /* if any data remains in the current bucket, split there */                if (bucket_avail) {                    apr_bucket_split(b, bytes_in_bucket - bucket_avail);                }                apr_bucket_delete(b);                break;            }        }    }    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;

⌨️ 快捷键说明

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