Hi,
I've come up with the included patch to add a RequestHeader directive to mod_headers in the 1.3 tree.
My patch adds a callback in the 'header parser' phase which takes care of the request headers.
My patch also modifies mod_rewrite.c so in case we have EAPI installed lookup_variable is registered as a hook (ap::mod_headers::lookup_variable) so its variable expansion function can be called from mod_headers.
In case EAPI is present, occurences of %{....} in the header text (for both request and response headers) will be replaced with the content of the named variable.
As I do not have much experience of the Apache source tree I might have written code that is incompatible or not conforming to the general Apache guidelines. Please feel free to send me any feedback.
Regards,
Mathias.
--- apache_1.3.31/src/modules/standard/mod_headers.c.orig 2004-10-14
15:44:37.000000000 +0200
+++ apache_1.3.31/src/modules/standard/mod_headers.c 2004-10-15 09:59:57.000000000
+0200
@@ -60,8 +60,12 @@
*/
#include "httpd.h"
+#include "http_core.h"
#include "http_config.h"
+#define HDR_IN 0
+#define HDR_OUT 1
+
typedef enum {
hdr_add = 'a', /* add header (could mean multiple hdrs) */
hdr_set = 's', /* set (replace old value) */
@@ -74,6 +78,7 @@
char *header;
char *value;
int do_err;
+ int do_req;
} header_entry;
/*
@@ -126,10 +131,15 @@
new = (header_entry *) ap_push_array(serverconf->headers);
}
- if (cmd->info) {
- new->do_err = 1;
- } else {
- new->do_err = 0;
+ if (cmd->info == (void *) 0) {
+ new->do_err = 0;
+ new->do_req = 0;
+ } else if (cmd->info == (void *) 1) {
+ new->do_err = 1;
+ new->do_req = 0;
+ } else if (cmd->info == (void *) 2) {
+ new->do_err = 0;
+ new->do_req = 1;
}
if (!strcasecmp(action, "set"))
@@ -165,25 +175,146 @@
"an action, header and value"},
{"ErrorHeader", header_cmd, (void *)1, OR_FILEINFO, TAKE23,
"an action, header and value"},
+ {"RequestHeader", header_cmd, (void *)2, OR_FILEINFO, TAKE23,
+ "an action, header and value"},
{NULL}
};
-static void do_headers_fixup(request_rec *r, array_header *headers)
+/*
+ * Expand environment variables (widely inspired by mod_rewrite).
+ */
+
+static void do_expand (request_rec *r, char *input, char *buffer, int nbuf)
{
- int i;
+ char *inp, *outp;
+ size_t span, space;
+
+ inp = input;
+ outp = buffer;
+ space = nbuf - 1; /* room for '\0' */
+
+ for(;;) {
+ span = strcspn(inp, "%");
+ if (span > space) {
+ span = space;
+ }
+ memcpy(outp, inp, span);
+ inp += span;
+ outp += span;
+ space -= span;
+ if (space == 0 || *inp == '\0') {
+ break;
+ }
+
+ /* now we have a % */
+ if (inp[1] == '{') {
+ /* %{...} variable lookup expansion */
+ char *endp;
+ char *var;
+
+ endp = find_closing_bracket(inp+2, '{', '}');
+ if (endp == NULL) {
+ goto skip;
+ }
+
+ var = ap_pstrndup(r->pool, inp+2, endp-inp-2);
+ span = ap_cpystrn(outp, lookup_variable(r, var), space) - outp;
+
+ inp = endp+1;
+ outp += span;
+ space -= span;
+ continue;
+ }
+ skip:
+ *outp++ = *inp++;
+ space--;
+ }
+
+ *outp++ = '\0';
+}
+
+/*
+**
+** Bracketed expression handling
+** s points after the opening bracket
+**
+*/
+
+static char *find_closing_bracket(char *s, int left, int right)
+{
+ int depth;
+
+ for (depth = 1; *s; ++s) {
+ if (*s == right && --depth == 0) {
+ return s;
+ }
+ else if (*s == left) {
+ ++depth;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Lookup variables %{...}
+ *
+ * We use EAPI and call a hook registered by mod_rewrite for its
+ * lookup_variable function.
+ *
+ * If EAPI is not defined, simply return what we were provided
+ * with.
+ */
+static char * lookup_variable(request_rec * r, char * var) {
+ const char *result;
+#ifdef EAPI
+ ap_hook_use("ap::mod_headers::lookup_variable",
+ AP_HOOK_SIG3(ptr,ptr,ptr),
+ AP_HOOK_DECLINE(NULL),
+ &result, r, var);
+#else
+ result = var;
+#endif
+
+ if (result == NULL) {
+ return var;
+ } else {
+ return result;
+ }
+}
+
+static void do_headers_fixup(request_rec *r, int inout, array_header *headers)
+{
+ int i;
+ char buffer[MAX_STRING_LEN];
+
for (i = 0; i < headers->nelts; ++i) {
header_entry *hdr = &((header_entry *) (headers->elts))[i];
- table *tbl = (hdr->do_err ? r->err_headers_out : r->headers_out);
+ table *tbl;
+
+ memset (buffer, 0, sizeof(buffer));
+
+ if (inout == HDR_OUT && !hdr->do_req) {
+ tbl = (hdr->do_err ? r->err_headers_out : r->headers_out);
+ } else if (hdr->do_req) {
+ tbl = r->headers_in;
+ }
+
+ /*
+ * Expand occurrences of %{...}
+ */
+
+ do_expand (r, hdr->value, buffer, sizeof(buffer));
+
switch (hdr->action) {
case hdr_add:
- ap_table_addn(tbl, hdr->header, hdr->value);
+ ap_table_addn(tbl, hdr->header, ap_pstrdup(r->pool,buffer));
break;
case hdr_append:
- ap_table_mergen(tbl, hdr->header, hdr->value);
+ ap_table_mergen(tbl, hdr->header, ap_pstrdup(r->pool,buffer));
break;
case hdr_set:
- ap_table_setn(tbl, hdr->header, hdr->value);
+ ap_table_setn(tbl, hdr->header, ap_pstrdup(r->pool,buffer));
break;
case hdr_unset:
ap_table_unset(tbl, hdr->header);
@@ -202,8 +333,23 @@
headers_conf *dirconf =
(headers_conf *) ap_get_module_config(dconf, &headers_module);
- do_headers_fixup(r, serverconf->headers);
- do_headers_fixup(r, dirconf->headers);
+ do_headers_fixup(r, HDR_OUT, serverconf->headers);
+ do_headers_fixup(r, HDR_OUT, dirconf->headers);
+
+ return DECLINED;
+}
+
+static int fix_request_headers(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ headers_conf *serverconf =
+ (headers_conf *) ap_get_module_config(sconf, &headers_module);
+ void *dconf = r->per_dir_config;
+ headers_conf *dirconf =
+ (headers_conf *) ap_get_module_config(dconf, &headers_module);
+
+ do_headers_fixup(r, HDR_IN, serverconf->headers);
+ do_headers_fixup(r, HDR_IN, dirconf->headers);
return DECLINED;
}
@@ -225,10 +371,10 @@
NULL, /* type_checker */
fixup_headers, /* fixups */
NULL, /* logger */
- NULL, /* header parser */
+ fix_request_headers, /* header parser */
NULL, /* child_init */
NULL, /* child_exit */
- NULL /* post read-request */
+ NULL /* post read-request */
};
--- apache_1.3.31/src/modules/standard/mod_rewrite.c.orig 2004-10-15
09:38:16.000000000 +0200
+++ apache_1.3.31/src/modules/standard/mod_rewrite.c 2004-10-15 09:40:05.000000000
+0200
@@ -946,7 +946,15 @@
for (; s; s = s->next) {
open_rewritelog(s, p);
run_rewritemap_programs(s, p);
- }
+ }
+
+#ifdef EAPI
+ /*
+ * Allow mod_headers to use our lookup_variable
+ */
+ ap_hook_register("ap::mod_headers::lookup_variable",
+ lookup_variable, AP_HOOK_NOCTX);
+#endif
}
smime.p7s
Description: S/MIME Cryptographic Signature
