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

📄 mod_headers.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 2 页
字号:
                return "header unset takes two arguments";            }            envclause = value;            value = NULL;        }    }    else if (new->action == hdr_echo) {        ap_regex_t *regex;        if (value) {            if (envclause) {                return "Header echo takes two arguments";            }            envclause = value;            value = NULL;        }        if (cmd->info != &hdr_out && cmd->info != &hdr_err)            return "Header echo only valid on Header "                   "directives";        else {            regex = ap_pregcomp(cmd->pool, hdr, AP_REG_EXTENDED | AP_REG_NOSUB);            if (regex == NULL) {                return "Header echo regex could not be compiled";            }        }        new->regex = regex;    }    else if (!value)        return "Header requires three arguments";    /* Handle the envclause on Header */    if (envclause != NULL) {        if (strcasecmp(envclause, "early") == 0) {            condition_var = condition_early;        }        else {            if (strncasecmp(envclause, "env=", 4) != 0) {                return "error: envclause should be in the form env=envar";            }            if ((envclause[4] == '\0')                || ((envclause[4] == '!') && (envclause[5] == '\0'))) {                return "error: missing environment variable name. "                    "envclause should be in the form env=envar ";            }            condition_var = envclause + 4;        }    }    if ((colon = ap_strchr_c(hdr, ':'))) {        hdr = apr_pstrmemdup(cmd->pool, hdr, colon-hdr);    }    new->header = hdr;    new->condition_var = condition_var;    return parse_format_string(cmd->pool, new, value);}/* Handle all (xxx)Header directives */static const char *header_cmd(cmd_parms *cmd, void *indirconf,                              const char *args){    const char *action;    const char *hdr;    const char *val;    const char *envclause;    const char *subs;    action = ap_getword_conf(cmd->pool, &args);    if (cmd->info == &hdr_out) {        if (!strcasecmp(action, "always")) {            cmd->info = &hdr_err;            action = ap_getword_conf(cmd->pool, &args);        }        else if (!strcasecmp(action, "onsuccess")) {            action = ap_getword_conf(cmd->pool, &args);        }    }    hdr = ap_getword_conf(cmd->pool, &args);    val = *args ? ap_getword_conf(cmd->pool, &args) : NULL;    subs = *args ? ap_getword_conf(cmd->pool, &args) : NULL;    envclause = *args ? ap_getword_conf(cmd->pool, &args) : NULL;    if (*args) {        return apr_pstrcat(cmd->pool, cmd->cmd->name,                           " has too many arguments", NULL);    }    return header_inout_cmd(cmd, indirconf, action, hdr, val, subs, envclause);}/* * Process the tags in the format string. Tags may be format specifiers * (%D, %t, etc.), whitespace or text strings. For each tag, run the handler * (formatter) specific to the tag. Handlers return text strings. * Concatenate the return from each handler into one string that is * returned from this call. */static char* process_tags(header_entry *hdr, request_rec *r){    int i;    const char *s;    char *str = NULL;    format_tag *tag = (format_tag*) hdr->ta->elts;    for (i = 0; i < hdr->ta->nelts; i++) {        s = tag[i].func(r, tag[i].arg);        if (str == NULL)            str = apr_pstrdup(r->pool, s);        else            str = apr_pstrcat(r->pool, str, s, NULL);    }    return str ? str : "";}static const char *process_regexp(header_entry *hdr, const char *value,                                  apr_pool_t *pool){    unsigned int nmatch = 10;    ap_regmatch_t pmatch[10];    const char *subs;    char *ret;    int diffsz;    if (ap_regexec(hdr->regex, value, nmatch, pmatch, 0)) {        /* no match, nothing to do */        return value;    }    subs = ap_pregsub(pool, hdr->subs, value, nmatch, pmatch);    diffsz = strlen(subs) - (pmatch[0].rm_eo - pmatch[0].rm_so);    ret = apr_palloc(pool, strlen(value) + 1 + diffsz);    memcpy(ret, value, pmatch[0].rm_so);    strcpy(ret + pmatch[0].rm_so, subs);    strcat(ret, value + pmatch[0].rm_eo);    return ret;}static int echo_header(echo_do *v, const char *key, const char *val){    /* If the input header (key) matches the regex, echo it intact to     * r->headers_out.     */    if (!ap_regexec(v->hdr->regex, key, 0, NULL, 0)) {        apr_table_add(v->r->headers_out, key, val);    }    return 1;}static int edit_header(void *v, const char *key, const char *val){    edit_do *ed = (edit_do *)v;    apr_table_addn(ed->t, key, process_regexp(ed->hdr, val, ed->p));    return 1;}static int add_them_all(void *v, const char *key, const char *val){    apr_table_t *headers = (apr_table_t *)v;    apr_table_addn(headers, key, val);    return 1;}static void do_headers_fixup(request_rec *r, apr_table_t *headers,                             apr_array_header_t *fixup, int early){    echo_do v;    int i;    const char *val;    for (i = 0; i < fixup->nelts; ++i) {        header_entry *hdr = &((header_entry *) (fixup->elts))[i];        const char *envar = hdr->condition_var;        /* ignore early headers in late calls */        if (!early && (envar == condition_early)) {            continue;        }        /* ignore late headers in early calls */        else if (early && (envar != condition_early)) {            continue;        }        /* Have any conditional envar-controlled Header processing to do? */        else if (envar && !early) {            if (*envar != '!') {                if (apr_table_get(r->subprocess_env, envar) == NULL)                    continue;            }            else {                if (apr_table_get(r->subprocess_env, &envar[1]) != NULL)                    continue;            }        }        switch (hdr->action) {        case hdr_add:            apr_table_addn(headers, hdr->header, process_tags(hdr, r));            break;        case hdr_append:            apr_table_mergen(headers, hdr->header, process_tags(hdr, r));            break;        case hdr_merge:            val = apr_table_get(headers, hdr->header);            if (val == NULL) {                apr_table_addn(headers, hdr->header, process_tags(hdr, r));            } else {                char *new_val = process_tags(hdr, r);                apr_size_t new_val_len = strlen(new_val);                int tok_found = 0;                /* modified version of logic in ap_get_token() */                while (*val) {                    const char *tok_start;                    while (*val && apr_isspace(*val))                        ++val;                    tok_start = val;                    while (*val && *val != ',') {                        if (*val++ == '"')                            while (*val)                                if (*val++ == '"')                                    break;                    }                    if (new_val_len == (apr_size_t)(val - tok_start)                        && !strncmp(tok_start, new_val, new_val_len)) {                        tok_found = 1;                        break;                    }                    if (*val)                        ++val;                }                if (!tok_found) {                    apr_table_mergen(headers, hdr->header, new_val);                }            }            break;        case hdr_set:            apr_table_setn(headers, hdr->header, process_tags(hdr, r));            break;        case hdr_unset:            apr_table_unset(headers, hdr->header);            break;        case hdr_echo:            v.r = r;            v.hdr = hdr;            apr_table_do((int (*) (void *, const char *, const char *))                         echo_header, (void *) &v, r->headers_in, NULL);            break;        case hdr_edit:            if (apr_table_get(headers, hdr->header)) {                edit_do ed;                ed.p = r->pool;                ed.hdr = hdr;                ed.t = apr_table_make(r->pool, 5);                apr_table_do(edit_header, (void *) &ed, headers, hdr->header,                             NULL);                apr_table_unset(headers, hdr->header);                apr_table_do(add_them_all, (void *) headers, ed.t, NULL);            }            break;        }    }}static void ap_headers_insert_output_filter(request_rec *r){    headers_conf *dirconf = ap_get_module_config(r->per_dir_config,                                                 &headers_module);    if (dirconf->fixup_out->nelts || dirconf->fixup_err->nelts) {        ap_add_output_filter("FIXUP_HEADERS_OUT", NULL, r, r->connection);    }}/* * Make sure our error-path filter is in place. */static void ap_headers_insert_error_filter(request_rec *r){    headers_conf *dirconf = ap_get_module_config(r->per_dir_config,                                                 &headers_module);    if (dirconf->fixup_err->nelts) {        ap_add_output_filter("FIXUP_HEADERS_ERR", NULL, r, r->connection);    }}static apr_status_t ap_headers_output_filter(ap_filter_t *f,                                             apr_bucket_brigade *in){    headers_conf *dirconf = ap_get_module_config(f->r->per_dir_config,                                                 &headers_module);    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,                 "headers: ap_headers_output_filter()");    /* do the fixup */    do_headers_fixup(f->r, f->r->err_headers_out, dirconf->fixup_err, 0);    do_headers_fixup(f->r, f->r->headers_out, dirconf->fixup_out, 0);    /* remove ourselves from the filter chain */    ap_remove_output_filter(f);    /* send the data up the stack */    return ap_pass_brigade(f->next,in);}/* * Make sure we propagate any "Header always" settings on the error * path through http_protocol.c. */static apr_status_t ap_headers_error_filter(ap_filter_t *f,                                            apr_bucket_brigade *in){    headers_conf *dirconf;    dirconf = ap_get_module_config(f->r->per_dir_config,                                    &headers_module);    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,                 "headers: ap_headers_error_filter()");    /*     * Add any header fields defined by "Header always" to r->err_headers_out.     * Server-wide first, then per-directory to allow overriding.     */    do_headers_fixup(f->r, f->r->err_headers_out, dirconf->fixup_err, 0);    /*     * We've done our bit; remove ourself from the filter chain so there's     * no possibility we'll be called again.     */    ap_remove_output_filter(f);    /*     * Pass the buck.  (euro?)     */    return ap_pass_brigade(f->next, in);}static apr_status_t ap_headers_fixup(request_rec *r){    headers_conf *dirconf = ap_get_module_config(r->per_dir_config,                                                 &headers_module);    /* do the fixup */    if (dirconf->fixup_in->nelts) {        do_headers_fixup(r, r->headers_in, dirconf->fixup_in, 0);    }    return DECLINED;}static apr_status_t ap_headers_early(request_rec *r){    headers_conf *dirconf = ap_get_module_config(r->per_dir_config,                                                 &headers_module);    /* do the fixup */    if (dirconf->fixup_in->nelts) {        do_headers_fixup(r, r->headers_in, dirconf->fixup_in, 1);    }    if (dirconf->fixup_err->nelts) {        do_headers_fixup(r, r->err_headers_out, dirconf->fixup_err, 1);    }    if (dirconf->fixup_out->nelts) {        do_headers_fixup(r, r->headers_out, dirconf->fixup_out, 1);    }    return DECLINED;}static const command_rec headers_cmds[] ={    AP_INIT_RAW_ARGS("Header", header_cmd, &hdr_out, OR_FILEINFO,                     "an optional condition, an action, header and value "                     "followed by optional env clause"),    AP_INIT_RAW_ARGS("RequestHeader", header_cmd, &hdr_in, OR_FILEINFO,                     "an action, header and value followed by optional env "                     "clause"),    {NULL}};static void register_format_tag_handler(const char *tag,                                        const void *tag_handler){    apr_hash_set(format_tag_hash, tag, 1, tag_handler);}static int header_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp){    format_tag_hash = apr_hash_make(p);    register_format_tag_handler("D", (const void *)header_request_duration);    register_format_tag_handler("t", (const void *)header_request_time);    register_format_tag_handler("e", (const void *)header_request_env_var);    register_format_tag_handler("s", (const void *)header_request_ssl_var);    return OK;}static int header_post_config(apr_pool_t *pconf, apr_pool_t *plog,                              apr_pool_t *ptemp, server_rec *s){    header_ssl_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);    return OK;}static void register_hooks(apr_pool_t *p){    ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter,                              NULL, AP_FTYPE_CONTENT_SET);    ap_register_output_filter("FIXUP_HEADERS_ERR", ap_headers_error_filter,                              NULL, AP_FTYPE_CONTENT_SET);    ap_hook_pre_config(header_pre_config,NULL,NULL,APR_HOOK_MIDDLE);    ap_hook_post_config(header_post_config,NULL,NULL,APR_HOOK_MIDDLE);    ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);    ap_hook_insert_error_filter(ap_headers_insert_error_filter,                                NULL, NULL, APR_HOOK_LAST);    ap_hook_fixups(ap_headers_fixup, NULL, NULL, APR_HOOK_LAST);    ap_hook_post_read_request(ap_headers_early, NULL, NULL, APR_HOOK_FIRST);}module AP_MODULE_DECLARE_DATA headers_module ={    STANDARD20_MODULE_STUFF,    create_headers_dir_config,  /* dir config creater */    merge_headers_config,       /* dir merger --- default is to override */    NULL,                       /* server config */    NULL,                       /* merge server configs */    headers_cmds,               /* command apr_table_t */    register_hooks              /* register hooks */};

⌨️ 快捷键说明

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