in modules/metadata/mod_headers.c [779:926]
static int 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;
}
/* Do we have an expression to evaluate? */
else if (hdr->expr != NULL) {
const char *err = NULL;
int eval = ap_expr_exec(r, hdr->expr, &err);
if (err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01501)
"Failed to evaluate expression (%s) - ignoring",
err);
}
else if (!eval) {
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 (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:
if (r->headers_in != headers &&
!ap_cstr_casecmp(hdr->header, "Content-Type")) {
ap_set_content_type_ex(r, process_tags(hdr, r), 1);
}
apr_table_setn(headers, hdr->header, process_tags(hdr, r));
break;
case hdr_setifempty:
if (NULL == apr_table_get(headers, hdr->header)) {
if (r->headers_in != headers &&
!ap_cstr_casecmp(hdr->header, "Content-Type")) {
ap_set_content_type_ex(r, process_tags(hdr, r), 1);
}
apr_table_setn(headers, hdr->header, process_tags(hdr, r));
}
break;
case hdr_unset:
apr_table_unset(headers, hdr->header);
if (r->headers_in != headers &&
!ap_cstr_casecmp(hdr->header, "Content-Type")) {
ap_set_content_type_ex(r, NULL, 1);
}
break;
case hdr_echo:
v.r = r;
v.hdr = hdr;
apr_table_do(echo_header, &v, r->headers_in, NULL);
break;
case hdr_edit:
case hdr_edit_all:
if (!ap_cstr_casecmp(hdr->header, "Content-Type") && r->content_type) {
const char *repl = process_regexp(hdr, r->content_type, r);
if (repl == NULL)
return 0;
if (r->headers_in != headers) ap_set_content_type_ex(r, repl, 1);
}
if (apr_table_get(headers, hdr->header)) {
edit_do ed;
ed.r = r;
ed.hdr = hdr;
ed.t = apr_table_make(r->pool, 5);
if (!apr_table_do(edit_header, (void *) &ed, headers,
hdr->header, NULL))
return 0;
apr_table_unset(headers, hdr->header);
apr_table_do(add_them_all, (void *) headers, ed.t, NULL);
}
break;
case hdr_note:
apr_table_setn(r->notes, process_tags(hdr, r), apr_table_get(headers, hdr->header));
break;
}
}
return 1;
}