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

📄 mod_substitute.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 2 页
字号:
        /*         * Everything to be passed to the next filter goes in         * here, our pass brigade.         */        ctx->passbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);        /* Create our temporary pool only once */        apr_pool_create(&(ctx->tpool), f->r->pool);        apr_table_unset(f->r->headers_out, "Content-Length");    }    /*     * Shortcircuit processing     */    if (APR_BRIGADE_EMPTY(bb))        return APR_SUCCESS;    /*     * Here's the concept:     *  Read in the data and look for newlines. Once we     *  find a full "line", add it to our working brigade.     *  If we've finished reading the brigade and we have     *  any left over data (not a "full" line), store that     *  for the next pass.     *     * Note: anything stored in ctx->linebb for sure does not have     * a newline char, so we don't concat that bb with the     * new bb, since we would spending time searching for the newline     * in data we know it doesn't exist. So instead, we simply scan     * our current bb and, if we see a newline, prepend ctx->linebb     * to the front of it. This makes the code much less straight-     * forward (otherwise we could APR_BRIGADE_CONCAT(ctx->linebb, bb)     * and just scan for newlines and not bother with needing to know     * when ctx->linebb needs to be reset) but also faster. We'll take     * the speed.     *     * Note: apr_brigade_split_line would be nice here, but we     * really can't use it since we need more control and we want     * to re-use already read bucket data.     *     * See mod_include if still confused :)     */    while ((b = APR_BRIGADE_FIRST(bb)) && (b != APR_BRIGADE_SENTINEL(bb))) {        if (APR_BUCKET_IS_EOS(b)) {            /*             * if we see the EOS, then we need to pass along everything we             * have. But if the ctx->linebb isn't empty, then we need to add             * that to the end of what we'll be passing.             */            if (!APR_BRIGADE_EMPTY(ctx->linebb)) {                rv = apr_brigade_pflatten(ctx->linebb, &bflat,                                          &fbytes, ctx->tpool);                tmp_b = apr_bucket_transient_create(bflat, fbytes,                                                f->r->connection->bucket_alloc);                do_pattmatch(f, tmp_b, ctx->pattbb, ctx->tpool);                APR_BRIGADE_CONCAT(ctx->passbb, ctx->pattbb);            }            apr_brigade_cleanup(ctx->linebb);            APR_BUCKET_REMOVE(b);            APR_BRIGADE_INSERT_TAIL(ctx->passbb, b);        }        /*         * No need to handle FLUSH buckets separately as we call         * ap_pass_brigade anyway at the end of the loop.         */        else if (APR_BUCKET_IS_METADATA(b)) {            APR_BUCKET_REMOVE(b);            APR_BRIGADE_INSERT_TAIL(ctx->passbb, b);        }        else {            /*             * We have actual "data" so read in as much as we can and start             * scanning and splitting from our read buffer             */            rv = apr_bucket_read(b, &buff, &bytes, APR_BLOCK_READ);            if (rv != APR_SUCCESS || bytes == 0) {                APR_BUCKET_REMOVE(b);            }            else {                int num = 0;                while (bytes > 0) {                    nl = memchr(buff, APR_ASCII_LF, bytes);                    if (nl) {                        len = (apr_size_t) (nl - buff) + 1;                        /* split *after* the newline */                        apr_bucket_split(b, len);                        /*                         * We've likely read more data, so bypass rereading                         * bucket data and continue scanning through this                         * buffer                         */                        bytes -= len;                        buff += len;                        /*                         * we need b to be updated for future potential                         * splitting                         */                        tmp_b = APR_BUCKET_NEXT(b);                        APR_BUCKET_REMOVE(b);                        /*                         * Hey, we found a newline! Don't forget the old                         * stuff that needs to be added to the front. So we                         * add the split bucket to the end, flatten the whole                         * bb, morph the whole shebang into a bucket which is                         * then added to the tail of the newline bb.                         */                        if (!APR_BRIGADE_EMPTY(ctx->linebb)) {                            APR_BRIGADE_INSERT_TAIL(ctx->linebb, b);                            rv = apr_brigade_pflatten(ctx->linebb, &bflat,                                                      &fbytes, ctx->tpool);                            b = apr_bucket_transient_create(bflat, fbytes,                                            f->r->connection->bucket_alloc);                            apr_brigade_cleanup(ctx->linebb);                        }                        do_pattmatch(f, b, ctx->pattbb, ctx->tpool);                        /*                         * Count how many buckets we have in ctx->passbb                         * so far. Yes, this is correct we count ctx->passbb                         * and not ctx->pattbb as we do not reset num on every                         * iteration.                         */                        for (b = APR_BRIGADE_FIRST(ctx->pattbb);                             b != APR_BRIGADE_SENTINEL(ctx->pattbb);                             b = APR_BUCKET_NEXT(b)) {                            num++;                        }                        APR_BRIGADE_CONCAT(ctx->passbb, ctx->pattbb);                        /*                         * If the number of buckets in ctx->passbb reaches an                         * "insane" level, we consume much memory for all the                         * buckets as such. So lets flush them down the chain                         * in this case and thus clear ctx->passbb. This frees                         * the buckets memory for further processing.                         * Usually this condition should not become true, but                         * it is a safety measure for edge cases.                         */                        if (num > AP_MAX_BUCKETS) {                            b = apr_bucket_flush_create(                                                f->r->connection->bucket_alloc);                            APR_BRIGADE_INSERT_TAIL(ctx->passbb, b);                            rv = ap_pass_brigade(f->next, ctx->passbb);                            apr_brigade_cleanup(ctx->passbb);                            num = 0;                            apr_pool_clear(ctx->tpool);                            if (rv != APR_SUCCESS)                                return rv;                        }                        b = tmp_b;                    }                    else {                        /*                         * no newline in whatever is left of this buffer so                         * tuck data away and get next bucket                         */                        APR_BUCKET_REMOVE(b);                        APR_BRIGADE_INSERT_TAIL(ctx->linebb, b);                        bytes = 0;                    }                }            }        }        if (!APR_BRIGADE_EMPTY(ctx->passbb)) {            rv = ap_pass_brigade(f->next, ctx->passbb);            apr_brigade_cleanup(ctx->passbb);            if (rv != APR_SUCCESS) {                apr_pool_clear(ctx->tpool);                return rv;            }        }        apr_pool_clear(ctx->tpool);    }    /* Anything left we want to save/setaside for the next go-around */    if (!APR_BRIGADE_EMPTY(ctx->linebb)) {        /*         * Provide ap_save_brigade with an existing empty brigade         * (ctx->linesbb) to avoid creating a new one.         */        ap_save_brigade(f, &(ctx->linesbb), &(ctx->linebb), f->r->pool);        tmp_bb = ctx->linebb;        ctx->linebb = ctx->linesbb;        ctx->linesbb = tmp_bb;    }    return APR_SUCCESS;}static const char *set_pattern(cmd_parms *cmd, void *cfg, const char *line){    char *from = NULL;    char *to = NULL;    char *flags = NULL;    char *ourline;    char delim;    subst_pattern_t *nscript;    int is_pattern = 0;    int ignore_case = 0;    int flatten = 1;    ap_regex_t *r = NULL;    if (apr_tolower(*line) != 's') {        return "Bad Substitute format, must be an s/// pattern";    }    ourline = apr_pstrdup(cmd->pool, line);    delim = *++ourline;    if (delim)        from = ++ourline;    if (from) {        if (*ourline != delim) {            while (*++ourline && *ourline != delim);        }        if (*ourline) {            *ourline = '\0';            to = ++ourline;        }    }    if (to) {        if (*ourline != delim) {            while (*++ourline && *ourline != delim);        }        if (*ourline) {            *ourline = '\0';            flags = ++ourline;        }    }    if (!delim || !from || !*from || !to) {        return "Bad Substitute format, must be a complete s/// pattern";    }    if (flags) {        while (*flags) {            delim = apr_tolower(*flags);    /* re-use */            if (delim == 'i')                ignore_case = 1;            else if (delim == 'n')                is_pattern = 1;            else if (delim == 'f')                flatten = 1;            else if (delim == 'q')                flatten = 0;            else                return "Bad Substitute flag, only s///[infq] are supported";            flags++;        }    }    /* first see if we can compile the regex */    if (!is_pattern) {        r = ap_pregcomp(cmd->pool, from, AP_REG_EXTENDED |                        (ignore_case ? AP_REG_ICASE : 0));        if (!r)            return "Substitute could not compile regex";    }    nscript = apr_array_push(((subst_dir_conf *) cfg)->patterns);    /* init the new entries */    nscript->pattern = NULL;    nscript->regexp = NULL;    nscript->replacement = NULL;    nscript->patlen = 0;    if (is_pattern) {        nscript->patlen = strlen(from);        nscript->pattern = apr_strmatch_precompile(cmd->pool, from,                                                    !ignore_case);    }    else {        nscript->regexp = r;    }    nscript->replacement = to;    nscript->replen = strlen(to);    nscript->flatten = flatten;    return NULL;}#define PROTO_FLAGS AP_FILTER_PROTO_CHANGE|AP_FILTER_PROTO_CHANGE_LENGTHstatic void register_hooks(apr_pool_t *pool){    ap_register_output_filter(substitute_filter_name, substitute_filter,                              NULL, AP_FTYPE_RESOURCE);}static const command_rec substitute_cmds[] = {    AP_INIT_TAKE1("Substitute", set_pattern, NULL, OR_ALL,                  "Pattern to filter the response content (s/foo/bar/[inf])"),    {NULL}};module AP_MODULE_DECLARE_DATA substitute_module = {    STANDARD20_MODULE_STUFF,    create_substitute_dcfg,     /* dir config creater */    merge_substitute_dcfg,      /* dir merger --- default is to override */    NULL,                       /* server config */    NULL,                       /* merge server config */    substitute_cmds,            /* command table */    register_hooks              /* register hooks */};

⌨️ 快捷键说明

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