This is an automated email from the ASF dual-hosted git repository.

mxmanghi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tcl-rivet.git


The following commit(s) were added to refs/heads/master by this push:
     new bf0bb2a  environment variables internals revision, add new tests to 
control their resolution and handling
bf0bb2a is described below

commit bf0bb2a066195be28b9ba2eeb02e3d9e9c495c74
Author: Massimo Manghi <massimo.man...@gmail.com>
AuthorDate: Thu Oct 21 12:58:39 2021 +0200

    environment variables internals revision, add new tests to control their 
resolution and handling
---
 ChangeLog                            |  25 ++-
 doc/xml/commands.xml                 |   2 +-
 src/mod_rivet_ng/TclWebapache.c      | 357 ++++++++++++++++++++++++-----------
 src/mod_rivet_ng/rivetCore.c         |   8 +-
 src/mod_rivet_ng/rivet_types.h       |   2 +-
 tests/apachetest/template.conf.1.tcl |   2 +-
 tests/env.rvt                        |  22 ++-
 tests/env.test                       |  45 ++++-
 tests/env_methods.tcl                |  15 ++
 tests/rivet.test                     |  19 +-
 10 files changed, 357 insertions(+), 140 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3934540..bf536f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,19 +1,26 @@
+2021-10-20 Massimo Manghi <mxman...@apache.org>
+       * src/mod_rivet_ng/Tclwebapache.c: new environment variable handling. 
+       Command ::rivet::env doesn't necessarily trigger the whole enviroment 
load
+       into request_rec, it tries to resolve a variable incrementally. Need
+       to recommend the usage of ::rivet::env instead of ::rivet::load_env
+       * tests/env.rvt: adding new tests to environment variable resolution
+
 2021-09-06 Massimo Manghi <mxman...@apache.org>
-    * rivet/packages/session/session-create-*.sql: making cache fields larger
+       * rivet/packages/session/session-create-*.sql: making cache fields 
larger
 
 2021-07-30 Massimo Manghi <mxman...@apache.org>
-    * src/mod_rivet_ng/TclWebapache.c: integrating the current scant Tcl error 
info 
-    returned by the various ::rivet::upload subcommands
-    * rivet/packages/dio/: Removing references to subversion's tags
+       * src/mod_rivet_ng/TclWebapache.c: integrating the current scant Tcl 
error info 
+       returned by the various ::rivet::upload subcommands
+       * rivet/packages/dio/: Removing references to subversion's tags
 
 2021-04-13 Massimo Manghi <mxman...@apache.org>
-    * src/mod_rivet_ng/rivetInspect.c: add server current loglevel. Removed
-    unneeded ref count management in the server array construction
+       * src/mod_rivet_ng/rivetInspect.c: add server current loglevel. Removed
+       unneeded ref count management in the server array construction
 
 2021-03-07 Massimo Manghi <mxman...@apache.org>
-    * VERSION: bumped version as 3.2.1
-    * src/mod_rivet_ng/mod_rivet.c: more linear determination of the bridge 
name
-    * rivet/packages/formbroker.tcl: introduced key maxlength
+       * VERSION: bumped version as 3.2.1
+       * src/mod_rivet_ng/mod_rivet.c: more linear determination of the bridge 
name
+       * rivet/packages/formbroker.tcl: introduced key maxlength
 
 2020-11-19 Massimo Manghi <mxman...@apache.org>
        * rivet/packages/dio/dio.tcl,dio_Mysql.tcl: adding support for
diff --git a/doc/xml/commands.xml b/doc/xml/commands.xml
index 38ee5ab..8e1c3e0 100644
--- a/doc/xml/commands.xml
+++ b/doc/xml/commands.xml
@@ -539,7 +539,7 @@
                            for any special (with respect to SGML, and hence 
HTML) characters
                            from the specified string, and returns the result.  
                            For example, the right angle bracket is escaped to 
the corrected
-                   ampersand gt symbol.
+                 ampersand gt symbol.
                        </para>
           </refsect1>
        </refentry>
diff --git a/src/mod_rivet_ng/TclWebapache.c b/src/mod_rivet_ng/TclWebapache.c
index 3f79c33..d4ae276 100644
--- a/src/mod_rivet_ng/TclWebapache.c
+++ b/src/mod_rivet_ng/TclWebapache.c
@@ -41,15 +41,29 @@
 
 extern module rivet_module;
 extern mod_rivet_globals* module_globals;
-#define TCLWEBPOOL req->req->pool
 
-#define BUFSZ 4096
+/* It's kind of an overkill, but we define macros for handling the
+ * flags that control and reduce the overhead when loading the 
+ * environment variables */
+
+#define ENV_COMMON_VARS_M    1
+#define ENV_CGI_VARS_M       2
+#define ENV_VARS_M           4
+#define ENV_VARS_RESET(env)  env = 0;
+#define ENV_COMMON_VARS(env) env |= ENV_COMMON_VARS_M;
+#define ENV_CGI_VARS(env)    env |= ENV_CGI_VARS_M;
+#define ENV_VARS(env)        env |= ENV_VARS_M;
+
+#define ENV_IS_LOADED(env)          (env == (ENV_COMMON_VARS_M | 
ENV_CGI_VARS_M | ENV_VARS_M))
+#define ENV_COMMON_VARS_LOADED(env) (env & ENV_COMMON_VARS_M) != 0
+#define ENV_CGI_VARS_LOADED(env)    (env & ENV_CGI_VARS_M) != 0
+#define ENV_VARS_LOADED(env)        (env & ENV_VARS_M) != 0
 
 /* This is used below to determine what part of the parmsarray to parse. */
 
-#define PARMSARRAY_COORDINATES i = 0; j = parmsarray->nelts; \
-if (source == VAR_SRC_QUERYSTRING) { j = req->apachereq->nargs; } \
-else if (source == VAR_SRC_POST) { i = req->apachereq->nargs; }
+#define PARMSARRAY_COORDINATES(i,j,parray,nargs) i = 0; j = parray->nelts; \
+if (source == VAR_SRC_QUERYSTRING) { j = nargs; } \
+else if (source == VAR_SRC_POST) { i = nargs; }
 
 /* 
  * -- TclWeb_NewRequestObject
@@ -67,13 +81,12 @@ TclWeb_NewRequestObject (apr_pool_t *p)
     req->apachereq          = ApacheRequest_new(p);
     req->headers_printed    = 0;
     req->headers_set        = 0;
-    req->environment_set    = 0;
+    ENV_VARS_RESET(req->environment_set)
     req->charset            = NULL;  /* we will test against NULL to check if 
a charset *
                                       * was specified in the conf              
         */
     return req;
 }
 
-
 /*
  * -- TclWeb_InitRequest
  *
@@ -101,7 +114,7 @@ TclWeb_InitRequest(rivet_thread_private* private, 
Tcl_Interp *interp)
     req->apachereq          = ApacheRequest_init(req->apachereq,r);
     req->headers_printed    = 0;
     req->headers_set        = 0;
-    req->environment_set    = 0;
+    ENV_VARS_RESET(req->environment_set)
     req->charset            = NULL;
 
     /*
@@ -156,8 +169,6 @@ TclWeb_SetHeaderType(char *header, TclWebRequest *req)
     if (req->headers_set)
         return TCL_ERROR;
 
-//    req->req->content_type = (char *) apr_pstrdup(req->req->pool, header);
-
     ap_set_content_type(req->req,apr_pstrdup(req->req->pool, header));
     req->headers_set = 1;
     return TCL_OK;
@@ -187,7 +198,6 @@ TclWeb_PrintHeaders(TclWebRequest *req)
      */
     
     TclWeb_SendHeaders(req);
-    /* ap_send_http_header(req->req); */
 
     req->headers_printed = 1;
     return TCL_OK;
@@ -207,7 +217,7 @@ TclWeb_PrintError(CONST84 char *errstr, int htmlflag, 
TclWebRequest *req)
     {
         if (htmlflag != 1)
         {
-            ap_rputs(ap_escape_html(TCLWEBPOOL, errstr), req->req);
+            ap_rputs(ap_escape_html(req->req->pool,errstr),req->req);
         } else {
             ap_rputs(errstr, req->req);
         }
@@ -270,65 +280,66 @@ INLINE int
 TclWeb_MakeURL(Tcl_Obj *result, char *filename, TclWebRequest *req)
 {
     Tcl_SetStringObj(result,
-                ap_construct_url(TCLWEBPOOL,filename,req->req),-1);
+                ap_construct_url(req->req->pool,filename,req->req),-1);
     return TCL_OK;
 }
 
 int
 TclWeb_GetVar(Tcl_Obj *result, char *varname, int source, TclWebRequest *req)
 {
-    int i, j;
-    apr_array_header_t *parmsarray = (apr_array_header_t *)
-        apr_table_elts(req->apachereq->parms);
-    apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
+    int i,j;
+    apr_array_header_t *parmsarray = (apr_array_header_t 
*)apr_table_elts(req->apachereq->parms);
+    apr_table_entry_t  *parms = (apr_table_entry_t *)parmsarray->elts;
     int flag = 0;
 
-    PARMSARRAY_COORDINATES;
+    PARMSARRAY_COORDINATES(i,j,parmsarray,req->apachereq->nargs)
 
     /* This isn't real efficient - move to hash table later on... */
     while (i < j)
     {
         char *parmkey = TclWeb_StringToUtf(parms[i].key, req);
-        if (!strncmp(varname, parmkey,
+        if (!strncmp(varname,parmkey,
                     strlen(varname) < strlen(parmkey) ?
                     strlen(parmkey) : strlen(varname)))
         {
+
             /* The following makes sure that we get one string,
                with no sub lists. */
+
             if (flag == 0)
             {
+
                 flag = 1;
-                Tcl_SetStringObj(result,
-                        TclWeb_StringToUtf(parms[i].val, req), -1);
+                Tcl_SetStringObj 
(result,TclWeb_StringToUtf(parms[i].val,req),-1);
+
             } else {
+
                 Tcl_Obj *tmpobj;
                 Tcl_Obj *tmpobjv[2];
                 tmpobjv[0] = result;
-                tmpobjv[1] = TclWeb_StringToUtfToObj(parms[i].val, req);
-                tmpobj = Tcl_ConcatObj(2, tmpobjv);
-                Tcl_SetStringObj(result, Tcl_GetString(tmpobj), -1);
+                tmpobjv[1] = TclWeb_StringToUtfToObj (parms[i].val,req);
+                tmpobj = Tcl_ConcatObj (2,tmpobjv);
+                Tcl_SetStringObj (result,Tcl_GetString(tmpobj),-1);
+
             }
+
         }
         i++;
     }
 
-    if (result->length == 0)
-    {
-           return TCL_ERROR;
-    }
+    if (result->length == 0) { return TCL_ERROR; }
 
     return TCL_OK;
 }
 
 int
-TclWeb_GetVarAsList(Tcl_Obj *result, char *varname, int source, TclWebRequest 
*req)
-{
+TclWeb_GetVarAsList(Tcl_Obj *result, char *varname, int source, TclWebRequest 
*req) {
     int i, j;
     apr_array_header_t *parmsarray = (apr_array_header_t *)
         apr_table_elts(req->apachereq->parms);
     apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
 
-    PARMSARRAY_COORDINATES;
+    PARMSARRAY_COORDINATES(i,j,parmsarray,req->apachereq->nargs)
 
     /* This isn't real efficient - move to hash table later on. */
     while (i < j)
@@ -359,20 +370,20 @@ TclWeb_GetAllVars(Tcl_Obj *result, int source, 
TclWebRequest *req)
         apr_table_elts(req->apachereq->parms);
     apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
 
-    PARMSARRAY_COORDINATES;
+    PARMSARRAY_COORDINATES(i,j,parmsarray,req->apachereq->nargs)
 
     while (i < j)
     {
-       Tcl_ListObjAppendElement(req->interp, result,
-                                TclWeb_StringToUtfToObj(parms[i].key, req));
-       Tcl_ListObjAppendElement(req->interp, result,
-                                TclWeb_StringToUtfToObj(parms[i].val, req));
-       i++;
+        Tcl_ListObjAppendElement(req->interp,result,
+                     TclWeb_StringToUtfToObj(parms[i].key,req));
+        Tcl_ListObjAppendElement(req->interp,result,
+                     TclWeb_StringToUtfToObj(parms[i].val,req));
+        i++;
     }
 
     if (result == NULL)
     {
-       return TCL_ERROR;
+           return TCL_ERROR;
     }
     return TCL_OK;
 }
@@ -385,18 +396,18 @@ TclWeb_GetVarNames(Tcl_Obj *result, int source, 
TclWebRequest *req)
         apr_table_elts(req->apachereq->parms);
     apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
 
-    PARMSARRAY_COORDINATES;
+    PARMSARRAY_COORDINATES(i,j,parmsarray,req->apachereq->nargs)
 
     while (i < j)
     {
-       Tcl_ListObjAppendElement(req->interp, result,
-                                TclWeb_StringToUtfToObj(parms[i].key, req));
-       i++;
+        Tcl_ListObjAppendElement(req->interp, result,
+                     TclWeb_StringToUtfToObj(parms[i].key, req));
+        i++;
     }
 
     if (result == NULL)
     {
-       return TCL_ERROR;
+        return TCL_ERROR;
     }
 
     return TCL_OK;
@@ -410,7 +421,7 @@ TclWeb_VarExists(Tcl_Obj *result, char *varname, int 
source, TclWebRequest *req)
         apr_table_elts(req->apachereq->parms);
     apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
 
-    PARMSARRAY_COORDINATES;
+    PARMSARRAY_COORDINATES(i,j,parmsarray,req->apachereq->nargs)
 
     /* This isn't real efficient - move to hash table later on. */
     while (i < j)
@@ -445,79 +456,181 @@ TclWeb_VarNumber(Tcl_Obj *result, int source, 
TclWebRequest *req)
     return TCL_OK;
 }
 
+/* These 2 array must be aligned and a one-to-one correspondence preserved 
+ * The enum include_vars_idx must be terminated by 'inval_env_var'
+ */
+
+static const char* include_env_vars[] =
+{
+    
"DATE_LOCAL","DATE_GMT","LAST_MODIFIED","DOCUMENT_URI","DOCUMENT_PATH_INFO","DOCUMENT_NAME",
+    "QUERY_STRING_UNESCAPED","USER_NAME","RIVET_CACHE_FREE","RIVET_CACHE_SIZE",
+    NULL
+};
+enum include_vars_idx {
+    
date_local=0,date_gmt,last_modified,document_uri,document_path_info,document_name,
+    query_string_unescaped,user_name,rivet_cache_free,rivet_cache_size,
+    invalid_env_var
+};
+
+static char*
+TclWeb_SelectEnvIncludeVar (rivet_thread_private* private,int idx)
+{
+    switch (idx)
+    {
+        case date_local: 
+        {
+            apr_pool_t* pool = private->req->req->pool;
+            apr_time_t date = private->req->req->request_time;
+
+            return ap_ht_time(pool,date,DEFAULT_TIME_FORMAT,0); 
+        }
+        case date_gmt:
+        {
+            apr_pool_t* pool = private->req->req->pool;
+            apr_time_t date = private->req->req->request_time;
+
+            return ap_ht_time(pool,date,DEFAULT_TIME_FORMAT,1);
+        }
+        case last_modified:
+        {
+            apr_pool_t* pool = private->req->req->pool;
+
+            return 
ap_ht_time(pool,private->req->req->finfo.mtime,DEFAULT_TIME_FORMAT,1);
+        }
+        case document_uri:
+        {
+            return private->req->req->uri;
+        }
+        case document_path_info:
+        {
+            return private->req->req->path_info;
+        }
+        case document_name:
+        {
+            char *t;
+
+            if ((t = strrchr(private->req->req->filename,'/'))) {
+                return ++t;
+            } else {
+                return private->req->req->uri;
+            }
+        }
+        case query_string_unescaped:
+        {
+            if (private->req->req->args) {
+                apr_pool_t* pool = private->req->req->pool;
+                char *arg_copy = (char*) 
apr_pstrdup(pool,private->req->req->args);
+
+                ap_unescape_url(arg_copy);
+                return ap_escape_shell_cmd(pool,arg_copy);
+            } else {
+                return NULL;
+            }
+
+        }
+        case user_name:
+        {
+#ifndef WIN32
+            struct passwd *pw = (struct passwd *) 
getpwuid(private->req->req->finfo.user);
+            if (pw) {
+                //apr_table_set( table, "USER_NAME",
+                //        apr_pstrdup( pool, pw->pw_name ) );
+                return pw->pw_name;
+            } else {
+                apr_pool_t* pool = private->req->req->pool;
+                return (char*) apr_psprintf(pool,"user#%lu",(unsigned 
long)private->req->req->finfo.user);
+            }
+#else
+            return NULL;
+#endif
+        }
+        case rivet_cache_free:
+        {
+            apr_pool_t* pool = private->req->req->pool;
+            return (char*) apr_psprintf (pool, 
"%d",(RIVET_PEEK_INTERP(private,private->running_conf))->cache_free);
+        }
+        case rivet_cache_size:
+        {
+            apr_pool_t* pool = private->req->req->pool;
+            return (char*) apr_psprintf (pool, 
"%d",(RIVET_PEEK_INTERP(private,private->running_conf))->cache_size);
+        }
+    }
+    return NULL;
+}
+
 /*
- * Load the Apache environment and CGI variables into the request.  If we
- * have already done so, we don't need to do it again.
+ * -- TclWeb_InitEnvVars
+ * 
+ * Load the CGI and environment variables into the request_rec environment 
structure
+ * Variables belong to 3 cathegories 
+ *
+ *   + common variables (ap_add_common_vars)
+ *   + CGI variables (ad_cgi_vars)
+ *   + a miscellaneous set of variables 
+ *     listed in the array include_env_vars
+ *
+ * Each cathegory is controlled by flags in order to reduce the overhead of 
getting them
+ * into request_rec in case previous call to ::rivet::env could have already 
forced them
+ * into request_rec
  */
+
 static void
 TclWeb_InitEnvVars (rivet_thread_private* private)
 {
-    //rivet_server_conf *rsc;
-    char *timefmt = DEFAULT_TIME_FORMAT;
-    char *t;
-    apr_time_t date;
-#ifndef WIN32
-    struct passwd *pw;
-#endif /* ndef WIN32 */
-    TclWebRequest *req;
-    apr_table_t *table;  
+    TclWebRequest *req = private->req;
+    apr_table_t   *table;  
+    int            idx;
 
-    req = private->req;
-    table = req->req->subprocess_env;
-    date = req->req->request_time;
-
-    if( req->environment_set ) return;
+    if (ENV_IS_LOADED(req->environment_set)) return;
 
-    //rsc = RIVET_SERVER_CONF( req->req->server->module_config );
+    table = req->req->subprocess_env;
 
     /* Retrieve cgi variables. */
-    ap_add_cgi_vars( req->req );
-    ap_add_common_vars( req->req );
-
-    /* These were the "include vars"  */
-
-    apr_table_set( table, "DATE_LOCAL",
-            ap_ht_time( TCLWEBPOOL, date, timefmt, 0 ) );
-    apr_table_set( table, "DATE_GMT",
-            ap_ht_time( TCLWEBPOOL, date, timefmt, 1 ) );
-    apr_table_set( table, "LAST_MODIFIED",
-            ap_ht_time( TCLWEBPOOL, req->req->finfo.mtime, timefmt, 1 ) );
-    apr_table_set( table, "DOCUMENT_URI", req->req->uri );
-    apr_table_set( table, "DOCUMENT_PATH_INFO", req->req->path_info );
-
-    if ((t = strrchr(req->req->filename, '/'))) {
-        apr_table_set( table, "DOCUMENT_NAME", ++t );
-    } else {
-        apr_table_set( table, "DOCUMENT_NAME", req->req->uri );
+    if (!ENV_CGI_VARS_LOADED(req->environment_set))
+    {
+        ap_add_cgi_vars(req->req);
+        ENV_CGI_VARS(req->environment_set);
     }
-
-    if( req->req->args ) {
-        char *arg_copy = (char*) apr_pstrdup(TCLWEBPOOL, req->req->args);
-        ap_unescape_url(arg_copy);
-        apr_table_set( table, "QUERY_STRING_UNESCAPED",
-                ap_escape_shell_cmd( TCLWEBPOOL, arg_copy ) );
+    if (!ENV_COMMON_VARS_LOADED(req->environment_set))
+    {
+        ap_add_common_vars(req->req);
+        ENV_COMMON_VARS(req->environment_set)
     }
 
-#ifndef WIN32
-    pw = (struct passwd *) getpwuid(req->req->finfo.user);
-    if( pw ) {
-        //apr_table_set( table, "USER_NAME",
-        //        apr_pstrdup( TCLWEBPOOL, pw->pw_name ) );
-    } else {
-        apr_table_set( table, "USER_NAME",
-                (char*) apr_psprintf( TCLWEBPOOL, "user#%lu",
-                    (unsigned long)req->req->finfo.user ) );
+    /* Loading into 'table' the include vars */
+
+    /* actually this is not necessary. ENV_VARS is modified only here therefore
+     * if it's set this function has been called already
+     * and it should have returned at the beginning of the execution. I keep
+     * it for clarity and uniformity with the CGI variables and in case
+     * the incremental environment control is extended
+     */
+
+    if (!ENV_VARS_LOADED(req->environment_set))
+    {
+        for (idx = 0;idx < invalid_env_var;idx++)
+        {
+            
apr_table_set(table,include_env_vars[idx],TclWeb_SelectEnvIncludeVar(private,idx));
+        }
+        ENV_VARS(req->environment_set)
     }
-#endif
 
-    /* Here we create some variables with Rivet internal information. */
+}
 
-    apr_table_set (table, "RIVET_CACHE_FREE",
-            (char*) apr_psprintf (TCLWEBPOOL, 
"%d",(RIVET_PEEK_INTERP(private,private->running_conf))->cache_free));
-    apr_table_set (table, "RIVET_CACHE_SIZE",
-            (char*) apr_psprintf (TCLWEBPOOL, 
"%d",(RIVET_PEEK_INTERP(private,private->running_conf))->cache_size));
+static char*
+TclWeb_GetEnvIncludeVar (rivet_thread_private* private,char* key)
+{
+    int    idx;
 
-    req->environment_set = 1;
+    for (idx = 0;idx < invalid_env_var; idx++)
+    {
+        const char* include_var_p = include_env_vars[idx];
+        if (strncmp(key,include_var_p,strlen(key) < strlen(include_var_p) ? 
strlen(key) : strlen(include_var_p)) == 0)
+        {
+            return TclWeb_SelectEnvIncludeVar(private,idx);
+        }
+    }
+    return NULL;
 }
 
 int
@@ -610,21 +723,21 @@ TclWeb_GetHeaderVars(Tcl_Obj 
*headersvar,rivet_thread_private* private)
 INLINE int
 TclWeb_Base64Encode(char *out, char *in, TclWebRequest *req)
 {
-    out = ap_pbase64encode(TCLWEBPOOL, in);
+    out = ap_pbase64encode(req->req->pool, in);
     return TCL_OK;
 }
 
 INLINE int
 TclWeb_Base64Decode(char *out, char *in, TclWebRequest *req)
 {
-    out = ap_pbase64decode(TCLWEBPOOL, in);
+    out = ap_pbase64decode(req->req->pool, in);
     return TCL_OK;
 }
 
 INLINE int
 TclWeb_EscapeShellCommand(char *out, char *in, TclWebRequest *req)
 {
-    out = ap_escape_shell_cmd(TCLWEBPOOL, in);
+    out = ap_escape_shell_cmd(req->req->pool, in);
     return TCL_OK;
 }
 
@@ -639,7 +752,7 @@ char *TclWeb_StringToUtf(char *in, TclWebRequest *req)
     Tcl_DString dstr;
     Tcl_DStringInit(&dstr);
     Tcl_ExternalToUtfDString(NULL, in, (signed)strlen(in), &dstr);
-    tmp = (char*) apr_pstrdup(TCLWEBPOOL, Tcl_DStringValue(&dstr));
+    tmp = (char*) apr_pstrdup(req->req->pool, Tcl_DStringValue(&dstr));
     Tcl_DStringFree(&dstr);
     return tmp;
 }
@@ -678,7 +791,7 @@ int TclWeb_UploadChannel(char *varname, TclWebRequest *req)
         }
         Tcl_RegisterChannel(req->interp,chan);
 
-        result = Tcl_NewObj();        
+        result = Tcl_NewObj();
         Tcl_SetStringObj(result, Tcl_GetChannelName(chan), -1);
         Tcl_SetObjResult(req->interp, result);
         
@@ -829,23 +942,37 @@ char *
 TclWeb_GetEnvVar(rivet_thread_private* private,char *key)
 {
     char *val;
-    TclWebRequest *req;
-
-    req = private->req;
-    TclWeb_InitEnvVars(private);
+    TclWebRequest *req = private->req;
 
     /* Check to see if it's a header variable first. */
-    val = (char *)apr_table_get( req->req->headers_in, key );
+    val = (char *)apr_table_get (req->req->headers_in,key);
+    if (val) { return val; }
+
+    /* We incrementally prepare subprocess_env */
+    /* CGI common vars first */
 
-    if( !val ) {
-        val = (char *)apr_table_get( req->req->subprocess_env, key );
+    if (!ENV_COMMON_VARS_LOADED(req->environment_set))
+    {
+        ap_add_common_vars(req->req);
+        ENV_COMMON_VARS(req->environment_set)
     }
+    val = (char *)apr_table_get(req->req->subprocess_env,key);
+    if (val) { return val; }
 
-    return val;
+    /* CGI HTTP 1.1 vars */
+
+    if (!ENV_CGI_VARS_LOADED(req->environment_set))
+    {
+        ap_add_cgi_vars(req->req);
+        ENV_CGI_VARS(req->environment_set)
+    }
+    val = (char *)apr_table_get(req->req->subprocess_env,key);
+    if (val) { return val; }
+    return TclWeb_GetEnvIncludeVar(private,key);
 }
 
 char *
-TclWeb_GetVirtualFile( TclWebRequest *req, char *virtualname )
+TclWeb_GetVirtualFile(TclWebRequest *req, char *virtualname)
 {
     request_rec *apreq;
     char *filename = NULL;
diff --git a/src/mod_rivet_ng/rivetCore.c b/src/mod_rivet_ng/rivetCore.c
index c7d4e21..1554bb2 100644
--- a/src/mod_rivet_ng/rivetCore.c
+++ b/src/mod_rivet_ng/rivetCore.c
@@ -669,9 +669,9 @@ TCL_CMD_HEADER ( Rivet_Var )
                          "|number|all)");
         return TCL_ERROR;
     }
-    cmd = Tcl_GetString(objv[0]);
+    cmd     = Tcl_GetString(objv[0]);
     command = Tcl_GetString(objv[1]);
-    result = Tcl_NewObj();
+    result  = Tcl_NewObj();
 
     /* determine if var_qs, var_post or var was called */
 
@@ -1414,9 +1414,9 @@ TCL_CMD_HEADER( Rivet_EnvCmd )
         return TCL_ERROR;
     }
 
-    key = Tcl_GetStringFromObj( objv[1], NULL );
+    key = Tcl_GetStringFromObj (objv[1],NULL);
 
-    val = TclWeb_GetEnvVar( private, key );
+    val = TclWeb_GetEnvVar (private,key);
 
     Tcl_SetObjResult(interp, Tcl_NewStringObj( val, -1 ) );
     return TCL_OK;
diff --git a/src/mod_rivet_ng/rivet_types.h b/src/mod_rivet_ng/rivet_types.h
index 6d24ff4..d3f30ca 100644
--- a/src/mod_rivet_ng/rivet_types.h
+++ b/src/mod_rivet_ng/rivet_types.h
@@ -87,7 +87,7 @@ typedef struct TclWebRequest {
     int             headers_printed;   /* has the header been printed yet? */
     int             headers_set;               /* has the header been set yet? 
    */
     int             content_sent;
-    int             environment_set;   /* have we setup the environment 
variables? */
+    unsigned int    environment_set;   /* have we setup the environment 
variables? */
     char*           charset;
 } TclWebRequest;
 
diff --git a/tests/apachetest/template.conf.1.tcl 
b/tests/apachetest/template.conf.1.tcl
index 5b96c92..b63cacc 100644
--- a/tests/apachetest/template.conf.1.tcl
+++ b/tests/apachetest/template.conf.1.tcl
@@ -1,4 +1,4 @@
-# \$Id\$
+
 # Minimal config file for testing
 
 # Parsed by makeconf.tcl
diff --git a/tests/env.rvt b/tests/env.rvt
index d039ce0..fe45389 100644
--- a/tests/env.rvt
+++ b/tests/env.rvt
@@ -1,7 +1,25 @@
 <?
 
-::rivet::load_env
+if {[::rivet::var_qs exists protocol]} {
 
-puts "env(DOCUMENT_NAME) = $env(DOCUMENT_NAME)\n"
+    puts [::rivet::env SERVER_PROTOCOL]
 
+} else {
+
+    set load_env_f [::rivet::var get load_env 0]
+
+    if {[string is true $load_env_f]} {
+
+        # test env-1.1
+
+        ::rivet::load_env
+        puts "env(DOCUMENT_NAME) = $env(DOCUMENT_NAME)\n"
+    } else {
+
+        # test env-1.2
+
+        set doc_name [::rivet::env DOCUMENT_NAME]
+        puts "env(DOCUMENT_NAME) = $doc_name\n"
+    }
+} 
 ?>
diff --git a/tests/env.test b/tests/env.test
index 05de770..155836c 100644
--- a/tests/env.test
+++ b/tests/env.test
@@ -1,9 +1,44 @@
-# $Id$
+#
+# testing how the environment variables resolution 
+# is handled by mod_rivet
+#
 
-set testfilename1 env.rvt
+set rvttestfilename env.rvt
 
 ::tcltest::test env-1.1 {Environment variable} {
-    set page [ ::http::geturl "${urlbase}$testfilename1" ]
-    regexp -line "^env\\(DOCUMENT_NAME\\) = $testfilename1\$" [ ::http::data 
$page ] match
+    set page [ ::http::geturl "${urlbase}$rvttestfilename?load_env=true" ]
+    regexp -line "^env\\(DOCUMENT_NAME\\) = $rvttestfilename\$" [::http::data 
$page] match
     set match
-} "env(DOCUMENT_NAME) = $testfilename1"
+} "env(DOCUMENT_NAME) = $rvttestfilename"
+
+::tcltest::test env-1.2 {Environment variable} {
+    set page [ ::http::geturl "${urlbase}$rvttestfilename?load_env=false" ]
+    regexp -line "^env\\(DOCUMENT_NAME\\) = $rvttestfilename\$" [::http::data 
$page] match
+    set match
+} "env(DOCUMENT_NAME) = $rvttestfilename"
+
+::tcltest::test env-1.2.1 {CGI Environment variable double translation} {
+    set page1 [ ::http::geturl "${urlbase}$rvttestfilename?protocol=1"]
+    set match1 [string trim [::http::data $page1]]
+    set page2 [ ::http::geturl "${urlbase}$rvttestfilename?protocol=1"]
+    set match2 [string trim [::http::data $page2]]
+    #puts "proto: $match1 $match2"
+    expr [string match $match1 $match2]
+} "1"
+
+set envmethod env_methods.tcl
+set env_vars [list "DATE_LOCAL" "DATE_GMT" "LAST_MODIFIED" "DOCUMENT_URI" 
"DOCUMENT_PATH_INFO" "DOCUMENT_NAME"  \
+                   "QUERY_STRING_UNESCAPED" "RIVET_CACHE_FREE" 
"RIVET_CACHE_SIZE" "HTTP_ACCEPT" "HTTP_HOST" \
+                   "QUERY_STRING" "SCRIPT_FILENAME" "SERVER_NAME" 
"SERVER_PORT" "SERVER_PROTOCOL"]
+
+puts "comparing ::rivet::env and ::rivet::load_env for variable resolution"
+foreach v $env_vars {
+    puts -nonewline "$v "
+    ::tcltest::test env-1.3 {Environment variable methods} {
+        set page [::http::geturl "${urlbase}$envmethod?envvar=$v"]
+        ::http::data $page
+    } "$v: OK"
+}
+puts ""
+
+
diff --git a/tests/env_methods.tcl b/tests/env_methods.tcl
new file mode 100644
index 0000000..e52b003
--- /dev/null
+++ b/tests/env_methods.tcl
@@ -0,0 +1,15 @@
+
+    set envvar [::rivet::var_qs get envvar]
+    set v1 [::rivet::env $envvar]
+    
+    ::rivet::load_env loadenv
+    set v2 $loadenv($envvar)
+    set comp [string match $v1 $v2]
+    if {$comp} {
+        set msg OK
+    } else {
+        set msg "env: $v1, load_env: $v2"
+    }
+
+    puts -nonewline "$envvar: $msg"
+
diff --git a/tests/rivet.test b/tests/rivet.test
index fade49a..6ed3950 100755
--- a/tests/rivet.test
+++ b/tests/rivet.test
@@ -2,6 +2,23 @@
 # the next line restarts using tclsh \
     exec tclsh "$0" "$@"
 
+#   Licensed to the Apache Software Foundation (ASF) under one
+#   or more contributor license agreements.  See the NOTICE file
+#   distributed with this work for additional information
+#   regarding copyright ownership.  The ASF licenses this file
+#   to you under the Apache License, Version 2.0 (the
+#   "License"); you may not use this file except in compliance
+#   with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+#   Unless required by applicable law or agreed to in writing,
+#   software distributed under the License is distributed on an
+#   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#   KIND, either express or implied.  See the License for the
+#   specific language governing permissions and limitations
+#   under the License.
+
 # Rivet test suite, by David N. Welton <dav...@apache.org>
 
 # See README file for more information.
@@ -27,8 +44,6 @@ set testgroup1 1
 set testgroup2 1
 set testgroup3 1
 
-#lappend TestList failtest.test
-
 # Run all tests against one server process.
 
 if { $testgroup1 } {

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@tcl.apache.org
For additional commands, e-mail: commits-h...@tcl.apache.org

Reply via email to