On Thu, 3 Aug 2000, Stas Bekman wrote:

> On Thu, 3 Aug 2000, ___cliff rayman___ wrote:
> 
> > use Apache::URI ();
> > $r->parsed_uri->scheme;
> > 
> > returns http or https
> 
> Not really, you can spoof both:
> http://thingy.kcilink.com/modperlguide/config/Knowing_the_proxy_pass_ed_Connec.html
>  
> > [EMAIL PROTECTED] wrote:
> > 
> > > I've got a section of our site where I want to force the user to
> > > connect via ssl.
> > > Inside of mod_perl, is there a parameter I can grab to see whether
> > > the connection is ssl or not?  Or a way to get the port number?
> > >
> > > Scott

I had the same problem recently, where the mod_perl backend server did not
know what was happening on the front end with respect to SSL.  I solved it
in a way that is flexible, but perhaps overkill:

I patched mod_headers.c on the frontend server to allow one to attach
extra headers to requests when they are proxied to the backend.  This
allows you to stuff info in headers about SSL, or the remote-ip, etc.  
You can specify headers to set with the same substitution syntax as
RewriteRule

(The patch is attached)

example:

On the front-end server:
( cd apache_1.3.12 ; patch -p1 <ProxyHeaderRewrite.p2.patch ;make install)

in httpd.conf;
# tell upstream server the ip of the request, and pass along the Host
ProxyHeaderRewrite append X-Forwarded-For      "%{REMOTE_ADDR}" 
ProxyHeaderRewrite append X-Frontend-Host      "%{HTTP_HOST}"
# 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}"



Now, for a typical SSL request that is proxied to the back end (as
plaintext), these headers are added: 
X-Forwarded-For: 1.2.3.4
X-Frontend-Host: my.frontend.site.com
X-SSL-Cipher: SSLv3 IDEA



On the backend server, parse the headers with some little perl handler in
startup.pl, and stuff the info where most other modules expect it (in $r,
or in environment vars):

sub My::ProxyHeaderParse ($) {
   my $r = shift;

      # we'll only look at the X-Forwarded-For header if the requests
      # comes from our local network
      return OK unless ($r->connection->remote_ip =~ /^192\.168/ );

      if (my ($ip) = $r->header_in('X-Forwarded-For') =~ /([^,\s]+)$/) {
          $r->connection->remote_ip($ip);
      }

      # mv X-Frontend-Host: into Host: header
      my $host_header = $r->header_in('X-Frontend-Host');
      if ( defined($host_header) ) {
          $r->header_in('Host', $host_header)
      }

      # set up ssl env vars, if present in a X-SSL-Cipher header
      my $ssl_header = $r->header_in('X-SSL-Cipher');
      if ( defined($ssl_header) ) {
          ($ENV{SSL_PROTOCOL}, $ENV{SSL_CIPHER}) = split(/ /,$ssl_header);
          $ENV{HTTPS} = 'ON';  # CGI.pm:protocol() require 'ON'  (not 1 !)
      } 
        
   return OK;
  }

# called in httpd.conf
#  PerlPostReadRequestHandler My::ProxyHeaderParse

--- 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)
 {

Reply via email to