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
 }
 
 

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature



Reply via email to