On Sun, 16 Jul 2000, Gunther Birznieks wrote:
> Is any of this header rewriting already on Ralf's TODO list for mod_rewrite?
>
> Does it make sense to make mod_headers more complex? Or to add these
> features to mod_rewrite already?
>
> Just throwing the idea out there.
>
> This is an interesting module though.
>
I considered adding the ProxyHeaderRewrite and HeaderRewrite commands to
mod_rewrite, but I felt more comfortable mucking around in the much
simpler mod_headers. I'm not happy that I had to duplicate some code from
mod_rewrite, tho.
I did not find any TODO lists for mod_rewrite.
BTW, I have attached a newer patch for mod_headers, which fixes a bug of
mine with ProxyHeaderRewrite unset. (apply to a stock 1.3.12 mod_headers)
I'm glad you find it interesting - this is my first public module
contribution.
-Tim
-------------------------
(from my original post)
The attached patch
(cd apache_1.3.XX; patch -p1 < ProxyHeaderRewrite.p2.patch; make
install)
will add two commands to mod_headers:
HeaderRewrite - dynamically set headers for the client
ProxyHeaderRewrite - dynamically set headers for the upstream proxy
server
While the original mod_headers would allow you so say:
Header append Foo "burfl"
Now you can say
HeaderRewrite append Foo "%{ENV:BURFL}", using the full RewriteCond syntax
My current lightweight apache server config looks something like:
ProxyHeaderRewrite append X-Forwarded-For "%{REMOTE_ADDR}"
ProxyHeaderRewrite append X-Frontend-Host "%{HTTP_HOST}"
<VirtualHost _default_:443>
...
SSLOptions StdEnvVars
ProxyHeaderRewrite append X-SSL-Cipher "%{ENV:SSL_PROTOCOL}
%{ENV:SSL_CIPHER}"
</VirtualHost>
--- apache_1.3.12.dist/src/modules/standard/mod_headers.c Wed Oct 27 02:26:53
1999
+++ apache_1.3.12/src/modules/standard/mod_headers.c Thu Jul 13 16:53:11 2000
@@ -99,9 +99,52 @@
* To remove a header:
* Header unset Author
*
+ *
+ * Non-standard Additions:
+ *
+ * Most code is from mod_rewrite, by
+ * Ralf S. Engelschall
+ * [EMAIL PROTECTED]
+ * Assembled by Tim Bishop <[EMAIL PROTECTED]>
+ *
+ *
+ * HeaderRewrite (set headers to client using RewriteCond syntax)
+ *
+ * Syntax: HeaderRewrite action header rewriteValue
+ *
+ * This works the same as the header directive, except that full
+ * mod_rewrite RewriteCond interpolation is performed on the rewriteValue
+ * string. See http://www.apache.org/docs/mod/mod_rewrite.html#RewriteCond
+ * (Of course, back-references (%N, $N) have no meaning)
+ *
+ *
+ * ProxyHeaderRewrite (set headers sent to upstream servers (if proxying))
+ *
+ * Syntax: ProxyHeaderRewrite action header rewriteValue
+ *
+ * ProxyHeaderRewrite allows you to rewrite headers sent to upstream
+ * servers when your server is functioning as a proxy server.
+ * This is useful when you want to send additional header information
+ * to upstream servers.
+ *
+ * Bugs: Cannot rewrite the Host header with ProxyHeaderRewrite
+ *
+ * Examples:
+ *
+ * # tell upstream server the ip of the request
+ * ProxyHeaderRewrite append X-Forwarded-For "%{REMOTE_ADDR}"
+ * # tell upstream server info on SSL status
+ * <VirtualHost _default_:443>
+ * SSLOptions StdEnvVars
+ * ProxyHeaderRewrite append X-SSL-Cipher "%{ENV:SSL_PROTOCOL}
+%{ENV:SSL_CIPHER}"
+ * </VirtualHost>
+ * # tell upstream server the virtual host used
+ * ProxyHeaderRewrite append X-Frontend-Host "%{HTTP:Host}"
+ *
*/
#include "httpd.h"
+#include "http_log.h"
#include "http_config.h"
typedef enum {
@@ -111,12 +154,50 @@
hdr_unset = 'u' /* unset header */
} hdr_actions;
+typedef enum {
+ hdr_string = 's', /* header is a string */
+ hdr_env_var = 'v', /* set header from env var */
+ hdr_interpolate = 'i' /* header needs to be interpolated (not yet!) */
+} hdr_value_type;
+
+typedef enum {
+ hdr_client = 'c', /* modify headers for client */
+ hdr_upstream = 'u' /* modify headers for upstream server */
+} hdr_header_target;
+
typedef struct {
- hdr_actions action;
- char *header;
- char *value;
+ hdr_actions action;
+ char *header;
+ char *value;
+ hdr_value_type value_type;
+ hdr_header_target header_target; /* one of hdr_client | hdr_upstream */
} header_entry;
+
+/* env variable interpolation support */
+static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len);
+static char *expand_variables(request_rec *r, char *str);
+static char *lookup_variable(request_rec *r, char *var);
+static char *lookup_header(request_rec *r, const char *name);
+
+#ifndef LONG_STRING_LEN
+#define LONG_STRING_LEN 2048
+#endif
+
+/* REMOTE_NAME returns the hostname, or the dotted quad if the
+ * hostname lookup fails. It will force a DNS lookup according
+ * to the HostnameLookups setting.
+ * from httd_core.h
+ */
+#define REMOTE_NAME (1)
+
+ /*
+ * The key in the r->notes table wherein we store our accumulated
+ * Vary values, and the one used for per-condition checks in a chain.
+ */
+#define VARY_KEY "headers-rewrite-Vary"
+#define VARY_KEY_THIS "headers-rewrite-Vary-this"
+
/*
* headers_conf is our per-module configuration. This is used as both
* a per-dir and per-server config
@@ -168,6 +249,103 @@
new = (header_entry *) ap_push_array(serverconf->headers);
}
+ new->value_type = hdr_string;
+ new->header_target = hdr_client; /* modify "outgoing" (to client) headers */
+
+ if (!strcasecmp(action, "set"))
+ new->action = hdr_set;
+ else if (!strcasecmp(action, "add"))
+ new->action = hdr_add;
+ else if (!strcasecmp(action, "append"))
+ new->action = hdr_append;
+ else if (!strcasecmp(action, "unset"))
+ new->action = hdr_unset;
+ else
+ return "first argument must be add, set, append or unset.";
+
+ if (new->action == hdr_unset) {
+ if (value)
+ return "Header unset takes two arguments";
+ }
+ else if (!value)
+ return "Header requires three arguments";
+
+ if ((colon = strchr(hdr, ':')))
+ *colon = '\0';
+
+ new->header = hdr;
+ new->value = value;
+
+ return NULL;
+}
+
+static const char *
+header_rewrite_cmd(cmd_parms *cmd, headers_conf * dirconf,
+ char *action, char *hdr, char *value)
+{
+ header_entry *new;
+ server_rec *s = cmd->server;
+ headers_conf *serverconf =
+ (headers_conf *) ap_get_module_config(s->module_config, &headers_module);
+ char *colon;
+
+ if (cmd->path) {
+ new = (header_entry *) ap_push_array(dirconf->headers);
+ }
+ else {
+ new = (header_entry *) ap_push_array(serverconf->headers);
+ }
+
+ new->value_type = hdr_interpolate;
+ new->header_target = hdr_client;
+
+ if (!strcasecmp(action, "set"))
+ new->action = hdr_set;
+ else if (!strcasecmp(action, "add"))
+ new->action = hdr_add;
+ else if (!strcasecmp(action, "append"))
+ new->action = hdr_append;
+ else if (!strcasecmp(action, "unset"))
+ new->action = hdr_unset;
+ else
+ return "first argument must be add, set, append or unset.";
+
+ if (new->action == hdr_unset) {
+ if (value)
+ return "Header unset takes two arguments";
+ }
+ else if (!value)
+ return "Header requires three arguments";
+
+ if ((colon = strchr(hdr, ':')))
+ *colon = '\0';
+
+ new->header = hdr;
+ new->value = value;
+
+ return NULL;
+}
+
+static const char *
+proxy_header_rewrite_cmd(cmd_parms *cmd, headers_conf * dirconf,
+ char *action, char *hdr, char *value)
+{
+ header_entry *new;
+ server_rec *s = cmd->server;
+ headers_conf *serverconf =
+ (headers_conf *) ap_get_module_config(s->module_config, &headers_module);
+ char *colon;
+
+ if (cmd->path) {
+ new = (header_entry *) ap_push_array(dirconf->headers);
+ }
+ else {
+ new = (header_entry *) ap_push_array(serverconf->headers);
+ }
+
+ new->value_type = hdr_interpolate;
+ new->header_target = hdr_upstream; /* send these headers only to upstream servers
+(that we are proxying for) */
+
if (!strcasecmp(action, "set"))
new->action = hdr_set;
else if (!strcasecmp(action, "add"))
@@ -195,36 +373,453 @@
return NULL;
}
+
static const command_rec headers_cmds[] =
{
{"Header", header_cmd, NULL, OR_FILEINFO, TAKE23,
"an action, header and value"},
+ {"HeaderRewrite", header_rewrite_cmd, NULL, OR_FILEINFO, TAKE23,
+ "an action, header and environment var from which to get header value"},
+ {"ProxyHeaderRewrite", proxy_header_rewrite_cmd, NULL, OR_FILEINFO, TAKE23,
+ "an action, header and environment var from which to get header value"},
{NULL}
};
static void do_headers_fixup(request_rec *r, array_header *headers)
{
int i;
+ table *target_hdrs;
+ const char *value;
for (i = 0; i < headers->nelts; ++i) {
header_entry *hdr = &((header_entry *) (headers->elts))[i];
- switch (hdr->action) {
+
+ /*
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r,
+ "mod_header: processing header: %c %s: %s %c %c",
+ hdr->action, hdr->header, hdr->value,
+ hdr->value_type, hdr->header_target);
+ */
+
+ if ( hdr->header_target == hdr_upstream ) {
+ // skip to next header_entry if not a proxy request
+ if ( r->proxyreq != PROXY_PASS) { continue; }
+ target_hdrs = r->headers_in;
+ } else {
+ target_hdrs = r->headers_out;
+ }
+
+ if (hdr->action != hdr_unset) {
+ if ( hdr->value_type == hdr_string ) {
+ value = hdr->value;
+
+ } else if ( hdr->value_type == hdr_env_var ) {
+ char *varname = hdr->value;
+
+ /* first try the internal Apache notes structure */
+ value = ap_table_get(r->notes, varname);
+ /* if (value) ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_header: found %s in notes table",varname); */
+ /* second try the internal Apache env structure */
+ if (value == NULL) {
+ value = ap_table_get(r->subprocess_env, varname);
+ /* if (value) ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_header: found %s in subprocess env",varname); */
+ }
+ /* third try the external OS env */
+ if (value == NULL) {
+ value = getenv(varname);
+ /* if (value) ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_header: found %s using getenv",varname); */
+ }
+
+ if (value == NULL) {
+ value = "";
+ /* ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_header: %s not found, using ''",varname); */
+ }
+
+ } else if ( hdr->value_type == hdr_interpolate ) {
+ value = expand_variables(r, hdr->value);
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r,
+ "mod_header: interpolated %s -> %s",
+ hdr->value,value);
+ } else {
+ /* not handled */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_header: invalid ProxyHeaderFromEnv coding!");
+ continue;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r,
+ "mod_header: setting %s %s: %s",
+ ( target_hdrs == r->headers_out )
+ ? "client header" : "upstream header",
+ hdr->header, value);
+ } else {
+ /* hdr_unset */
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r,
+ "mod_header: unsetting %s %s:",
+ ( target_hdrs == r->headers_out )
+ ? "client header" : "upstream header",
+ hdr->header);
+ }
+
+ switch (hdr->action) {
case hdr_add:
- ap_table_addn(r->headers_out, hdr->header, hdr->value);
+ ap_table_addn(target_hdrs, hdr->header, value);
break;
case hdr_append:
- ap_table_mergen(r->headers_out, hdr->header, hdr->value);
+ ap_table_mergen(target_hdrs, hdr->header, value);
break;
case hdr_set:
- ap_table_setn(r->headers_out, hdr->header, hdr->value);
+ ap_table_setn(target_hdrs, hdr->header, value);
break;
case hdr_unset:
- ap_table_unset(r->headers_out, hdr->header);
+ ap_table_unset(target_hdrs, hdr->header);
break;
+ }
+
+ }
+
+}
+
+/*
+** This section pilfered from mod_rewrite
+**
+** Ralf S. Engelschall
+** [EMAIL PROTECTED]
+** www.engelschall.com
+*/
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | environment variable support
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+
+
+static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len)
+{
+ char *newbuf;
+ newbuf = expand_variables(r, buf);
+ if (strcmp(newbuf, buf) != 0) {
+ ap_cpystrn(buf, newbuf, buf_len);
+ }
+ return;
+}
+
+static char *expand_variables(request_rec *r, char *str)
+{
+ char output[MAX_STRING_LEN];
+ char input[MAX_STRING_LEN];
+ char *cp;
+ char *cp2;
+ char *cp3;
+ int expanded;
+ char *outp;
+ char *endp;
+
+ ap_cpystrn(input, str, sizeof(input));
+ output[0] = '\0';
+ outp = output;
+ endp = output + sizeof(output);
+ expanded = 0;
+ for (cp = input; cp < input+MAX_STRING_LEN; ) {
+ if ((cp2 = strstr(cp, "%{")) != NULL) {
+ if ((cp3 = strstr(cp2, "}")) != NULL) {
+ *cp2 = '\0';
+ outp = ap_cpystrn(outp, cp, endp - outp);
+
+ cp2 += 2;
+ *cp3 = '\0';
+ outp = ap_cpystrn(outp, lookup_variable(r, cp2), endp - outp);
+
+ cp = cp3+1;
+ expanded = 1;
+ continue;
+ }
+ }
+ outp = ap_cpystrn(outp, cp, endp - outp);
+ break;
+ }
+ return expanded ? ap_pstrdup(r->pool, output) : str;
+}
+
+static char *lookup_variable(request_rec *r, char *var)
+{
+ const char *result;
+ char resultbuf[LONG_STRING_LEN];
+ time_t tc;
+ struct tm *tm;
+ request_rec *rsub;
+#ifndef WIN32
+ struct passwd *pw;
+ struct group *gr;
+ struct stat finfo;
+#endif
+
+ result = NULL;
+
+ /* HTTP headers */
+ if (strcasecmp(var, "HTTP_USER_AGENT") == 0) {
+ result = lookup_header(r, "User-Agent");
+ }
+ else if (strcasecmp(var, "HTTP_REFERER") == 0) {
+ result = lookup_header(r, "Referer");
+ }
+ else if (strcasecmp(var, "HTTP_COOKIE") == 0) {
+ result = lookup_header(r, "Cookie");
+ }
+ else if (strcasecmp(var, "HTTP_FORWARDED") == 0) {
+ result = lookup_header(r, "Forwarded");
+ }
+ else if (strcasecmp(var, "HTTP_HOST") == 0) {
+ result = lookup_header(r, "Host");
+ }
+ else if (strcasecmp(var, "HTTP_PROXY_CONNECTION") == 0) {
+ result = lookup_header(r, "Proxy-Connection");
+ }
+ else if (strcasecmp(var, "HTTP_ACCEPT") == 0) {
+ result = lookup_header(r, "Accept");
+ }
+ /* all other headers from which we are still not know about */
+ else if (strlen(var) > 5 && strncasecmp(var, "HTTP:", 5) == 0) {
+ result = lookup_header(r, var+5);
+ }
+
+ /* connection stuff */
+ else if (strcasecmp(var, "REMOTE_ADDR") == 0) {
+ result = r->connection->remote_ip;
+ }
+ else if (strcasecmp(var, "REMOTE_HOST") == 0) {
+ result = (char *)ap_get_remote_host(r->connection,
+ r->per_dir_config, REMOTE_NAME);
+ }
+ else if (strcasecmp(var, "REMOTE_USER") == 0) {
+ result = r->connection->user;
+ }
+ else if (strcasecmp(var, "REMOTE_IDENT") == 0) {
+ result = (char *)ap_get_remote_logname(r);
+ }
+
+ /* request stuff */
+ else if (strcasecmp(var, "THE_REQUEST") == 0) { /* non-standard */
+ result = r->the_request;
+ }
+ else if (strcasecmp(var, "REQUEST_METHOD") == 0) {
+ result = r->method;
+ }
+ else if (strcasecmp(var, "REQUEST_URI") == 0) { /* non-standard */
+ result = r->uri;
+ }
+ else if (strcasecmp(var, "SCRIPT_FILENAME") == 0 ||
+ strcasecmp(var, "REQUEST_FILENAME") == 0 ) {
+ result = r->filename;
+ }
+ else if (strcasecmp(var, "PATH_INFO") == 0) {
+ result = r->path_info;
+ }
+ else if (strcasecmp(var, "QUERY_STRING") == 0) {
+ result = r->args;
+ }
+ else if (strcasecmp(var, "AUTH_TYPE") == 0) {
+ result = r->connection->ap_auth_type;
+ }
+ else if (strcasecmp(var, "IS_SUBREQ") == 0) { /* non-standard */
+ result = (r->main != NULL ? "true" : "false");
+ }
+
+ /* internal server stuff */
+ else if (strcasecmp(var, "DOCUMENT_ROOT") == 0) {
+ result = (const char *) ap_document_root(r);
+ }
+ else if (strcasecmp(var, "SERVER_ADMIN") == 0) {
+ result = r->server->server_admin;
+ }
+ else if (strcasecmp(var, "SERVER_NAME") == 0) {
+ result = (const char *) ap_get_server_name(r);
+ }
+ else if (strcasecmp(var, "SERVER_ADDR") == 0) { /* non-standard */
+ result = r->connection->local_ip;
+ }
+ else if (strcasecmp(var, "SERVER_PORT") == 0) {
+ ap_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r));
+ result = resultbuf;
+ }
+ else if (strcasecmp(var, "SERVER_PROTOCOL") == 0) {
+ result = r->protocol;
+ }
+ else if (strcasecmp(var, "SERVER_SOFTWARE") == 0) {
+ result = ap_get_server_version();
+ }
+ else if (strcasecmp(var, "API_VERSION") == 0) { /* non-standard */
+ ap_snprintf(resultbuf, sizeof(resultbuf), "%d:%d",
+ MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
+ result = resultbuf;
+ }
+
+ /* underlaying Unix system stuff */
+ else if (strcasecmp(var, "TIME_YEAR") == 0) {
+ tc = time(NULL);
+ tm = localtime(&tc);
+ ap_snprintf(resultbuf, sizeof(resultbuf), "%02d%02d",
+ (tm->tm_year / 100) + 19, tm->tm_year % 100);
+ result = resultbuf;
+ }
+#define MKTIMESTR(format, tmfield) \
+ tc = time(NULL); \
+ tm = localtime(&tc); \
+ ap_snprintf(resultbuf, sizeof(resultbuf), format, tm->tmfield); \
+ result = resultbuf;
+ else if (strcasecmp(var, "TIME_MON") == 0) {
+ MKTIMESTR("%02d", tm_mon+1)
+ }
+ else if (strcasecmp(var, "TIME_DAY") == 0) {
+ MKTIMESTR("%02d", tm_mday)
+ }
+ else if (strcasecmp(var, "TIME_HOUR") == 0) {
+ MKTIMESTR("%02d", tm_hour)
+ }
+ else if (strcasecmp(var, "TIME_MIN") == 0) {
+ MKTIMESTR("%02d", tm_min)
+ }
+ else if (strcasecmp(var, "TIME_SEC") == 0) {
+ MKTIMESTR("%02d", tm_sec)
+ }
+ else if (strcasecmp(var, "TIME_WDAY") == 0) {
+ MKTIMESTR("%d", tm_wday)
+ }
+ else if (strcasecmp(var, "TIME") == 0) {
+ tc = time(NULL);
+ tm = localtime(&tc);
+ ap_snprintf(resultbuf, sizeof(resultbuf),
+ "%02d%02d%02d%02d%02d%02d%02d", (tm->tm_year / 100) + 19,
+ (tm->tm_year % 100), tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ result = resultbuf;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r, "mod_headers: interpolate:
+RESULT='%s'", result);
+ }
+
+ /* all other env-variables from the parent Apache process */
+ else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) {
+ /* first try the internal Apache notes structure */
+ result = ap_table_get(r->notes, var+4);
+ /* second try the internal Apache env structure */
+ if (result == NULL) {
+ result = ap_table_get(r->subprocess_env, var+4);
+ }
+ /* third try the external OS env */
+ if (result == NULL) {
+ result = getenv(var+4);
+ }
+ }
+
+#define LOOKAHEAD(subrecfunc) \
+ if ( \
+ /* filename is safe to use */ \
+ r->filename != NULL \
+ /* - and we're either not in a subrequest */ \
+ && ( r->main == NULL \
+ /* - or in a subrequest where paths are non-NULL... */ \
+ || ( r->main->uri != NULL && r->uri != NULL \
+ /* ...and sub and main paths differ */ \
+ && strcmp(r->main->uri, r->uri) != 0))) { \
+ /* process a file-based subrequest */ \
+ rsub = subrecfunc(r->filename, r); \
+ /* now recursively lookup the variable in the sub_req */ \
+ result = lookup_variable(rsub, var+5); \
+ /* copy it up to our scope before we destroy sub_req's pool */ \
+ result = ap_pstrdup(r->pool, result); \
+ /* cleanup by destroying the subrequest */ \
+ ap_destroy_sub_req(rsub); \
+ /* log it */ \
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r,"mod_headers: interpolate:
+lookahead: path=%s var=%s -> val=%s", \
+ r->filename, var+5, result); \
+ /* return ourself to prevent re-pstrdup */ \
+ return (char *)result; \
+ }
+
+ /* look-ahead for parameter through URI-based sub-request */
+ else if (strlen(var) > 5 && strncasecmp(var, "LA-U:", 5) == 0) {
+ LOOKAHEAD(ap_sub_req_lookup_uri)
+ }
+ /* look-ahead for parameter through file-based sub-request */
+ else if (strlen(var) > 5 && strncasecmp(var, "LA-F:", 5) == 0) {
+ LOOKAHEAD(ap_sub_req_lookup_file)
+ }
+
+#if !defined(WIN32) && !defined(NETWARE)
+ /* Win32 has a rather different view of file ownerships.
+ For now, just forget it */
+
+ /* file stuff */
+ else if (strcasecmp(var, "SCRIPT_USER") == 0) {
+ result = "<unknown>";
+ if (r->finfo.st_mode != 0) {
+ if ((pw = getpwuid(r->finfo.st_uid)) != NULL) {
+ result = pw->pw_name;
+ }
+ }
+ else {
+ if (stat(r->filename, &finfo) == 0) {
+ if ((pw = getpwuid(finfo.st_uid)) != NULL) {
+ result = pw->pw_name;
+ }
+ }
+ }
+ }
+ else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
+ result = "<unknown>";
+ if (r->finfo.st_mode != 0) {
+ if ((gr = getgrgid(r->finfo.st_gid)) != NULL) {
+ result = gr->gr_name;
+ }
+ }
+ else {
+ if (stat(r->filename, &finfo) == 0) {
+ if ((gr = getgrgid(finfo.st_gid)) != NULL) {
+ result = gr->gr_name;
+ }
+ }
}
}
+#endif /* ndef WIN32 && NETWARE*/
+ if (result == NULL) {
+ return ap_pstrdup(r->pool, "");
+ }
+ else {
+ return ap_pstrdup(r->pool, result);
+ }
}
+
+static char *lookup_header(request_rec *r, const char *name)
+{
+ array_header *hdrs_arr;
+ table_entry *hdrs;
+ int i;
+
+ hdrs_arr = ap_table_elts(r->headers_in);
+ hdrs = (table_entry *)hdrs_arr->elts;
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (hdrs[i].key == NULL) {
+ continue;
+ }
+ if (strcasecmp(hdrs[i].key, name) == 0) {
+ ap_table_merge(r->notes, VARY_KEY_THIS, name);
+ return hdrs[i].val;
+ }
+ }
+ return NULL;
+}
+
+
+
+
static int fixup_headers(request_rec *r)
{