I've patched mod_rivet and some related files
in order to have constructs such as

AddType 'application/x-httpd-rivet; charset=utf-8' rvt

be understood and thus to have the default charset
used within rivet templates and scripts changed 
with a single line.

a developer can override the conf line using 
'headers type ....' commands wherever he/she needs
to do it.

To make the debugging easier I also created the boolean
global configuration option 'HonorHeaderOnlyRequests'
(disabled by default).
 
-- Massimo

Index: src/rivet.h
===================================================================
--- src/rivet.h (revision 669345)
+++ src/rivet.h (working copy)
@@ -5,7 +5,8 @@
 #define TCL_STORAGE_CLASS DLLEXPORT
 #endif /* BUILD_rivet */
 
-#define STREQU(s1, s2) (s1[0] == s2[0] && strcmp(s1, s2) == 0)
+#define STREQU(s1, s2)  (s1[0] == s2[0] && strcmp(s1, s2) == 0)
+#define STRNEQU(s1, s2) (s1[0] == s2[0] && strncmp(s1, s2, strlen(s2)) == 0)
 
 #define TCL_CMD_HEADER(cmd)    \
 static int cmd(\
Index: src/apache-2/mod_rivet.h
===================================================================
--- src/apache-2/mod_rivet.h    (revision 669345)
+++ src/apache-2/mod_rivet.h    (working copy)
@@ -76,6 +76,7 @@
     int upload_max;
     int upload_files_to_var;
     int separate_virtual_interps;
+    int honor_header_only_reqs;                        /* default: 0 */
     char *server_name;
     char *upload_dir;
     apr_table_t *rivet_server_vars;
Index: src/apache-2/mod_rivet.c
===================================================================
--- src/apache-2/mod_rivet.c    (revision 669345)
+++ src/apache-2/mod_rivet.c    (working copy)
@@ -57,8 +57,7 @@
 
 //module AP_MODULE_DECLARE_DATA rivet_module;
 
-/* This is used *only* in the PanicProc.  Otherwise, don't touch
- * it! */
+/* This is used *only* in the PanicProc.  Otherwise, don't touch it! */
 static request_rec *globalrr;
 
 /* Need some arbitrary non-NULL pointer which can't also be a request_rec */
@@ -66,8 +65,9 @@
 #define DEBUG(s) fprintf(stderr, s), fflush(stderr)
 
 /* rivet or tcl file */
-#define RIVET_FILE 1
-#define TCL_FILE 2
+#define CTYPE_NOT_HANDLED   0
+#define RIVET_FILE         1
+#define TCL_FILE           2
 
 /* rivet return codes */
 #define RIVET_OK 0
@@ -77,23 +77,25 @@
 
 /* This snippet of code came from the mod_ruby project, which is under a BSD
license. */
 #ifdef APACHE2 /* Apache 2.x */
-       
 
+#define RIVET_FILE_CTYPE       "application/x-httpd-rivet"
+#define TCL_FILE_CTYPE         "application/x-rivet-tcl"
+
 static void ap_chdir_file(const char *file)
 {
-       const  char *x;
-       char chdir_buf[HUGE_STRING_LEN];
-       x = strrchr(file, '/');
-       if (x == NULL) {
-               chdir(file);
-       }
-       else if (x - file < sizeof(chdir_buf) - 1) {
-               memcpy(chdir_buf, file, x - file);
-               chdir_buf[x - file] = '\0';
-               chdir(chdir_buf);
-       }
+    const  char *x;
+    char chdir_buf[HUGE_STRING_LEN];
+    x = strrchr(file, '/');
+    if (x == NULL) {
+       chdir(file);
+    } else if (x - file < sizeof(chdir_buf) - 1) {
+       memcpy(chdir_buf, file, x - file);
+       chdir_buf[x - file] = '\0';
+       chdir(chdir_buf);
+    }
 }
 #endif
+
 /* Function to be used should we desire to upload files to a variable */
 
 #if 0
@@ -116,16 +118,17 @@
 static int
 Rivet_CheckType (request_rec *req)
 {
-       if ( req->content_type != NULL ) {
-               if( STREQU( req->content_type, "application/x-httpd-rivet")) {
-                       return RIVET_FILE;
-               }
+    int            ctype   = CTYPE_NOT_HANDLED;
 
-                if( STREQU( req->content_type, "application/x-rivet-tcl")) {
-                       return TCL_FILE;
-               }
+    if ( req->content_type != NULL ) {
+       if( STRNEQU( req->content_type, RIVET_FILE_CTYPE) ) {
+           ctype  = RIVET_FILE;
+       } else if( STRNEQU( req->content_type, TCL_FILE_CTYPE) ) {
+           ctype = TCL_FILE;
+       } 
+
     }
-       return 0; 
+    return ctype; 
 }
 /*
  * Rivet_ParseFileArgString (char *szDocRoot, char *szArgs, char **file)
@@ -370,15 +373,16 @@
 
     /* Make sure to flush the output if buffer_add was the only output */
 good:
+
+    if (!globals->req->headers_set && (globals->req->charset != NULL)) {
+       TclWeb_SetHeaderType
(apr_pstrcat(globals->req->req->pool,"text/html;",globals->req->charset),globals->req);
+    }
     TclWeb_PrintHeaders(globals->req);
     Tcl_Flush(*(conf->outchannel));
 
     return TCL_OK;
 }
 
-
-
-
 /* This is a separate function so that it may be called from 'Parse' */
 int
 Rivet_ParseExecFile(TclWebRequest *req, char *filename, int toplevel)
@@ -428,7 +432,6 @@
         *(rsc->cache_free) = *(rsc->cache_size);
     }
 
-
     /* If toplevel is 0, we are being called from Parse, which means
        we need to get the information about the file ourselves. */
     if (toplevel == 0)
@@ -629,6 +632,7 @@
     newrsc->upload_max = oldrsc->upload_max;
     newrsc->upload_files_to_var = oldrsc->upload_files_to_var;
     newrsc->separate_virtual_interps = oldrsc->separate_virtual_interps;
+    newrsc->honor_header_only_reqs = oldrsc->honor_header_only_reqs;
     newrsc->server_name = oldrsc->server_name;
     newrsc->upload_dir = oldrsc->upload_dir;
     newrsc->rivet_server_vars = oldrsc->rivet_server_vars;
@@ -731,6 +735,7 @@
     rsc->upload_max = 0;
     rsc->upload_files_to_var = 0;
     rsc->separate_virtual_interps = 0;
+    rsc->honor_header_only_reqs = 0;
     rsc->server_name = NULL;
     rsc->upload_dir = "/tmp";
     rsc->objCacheList = NULL;
@@ -827,8 +832,7 @@
 
     /* Create TCL commands to deal with Apache's BUFFs. */
     rsc->outchannel = apr_pcalloc(p, sizeof(Tcl_Channel));
-    *(rsc->outchannel) = Tcl_CreateChannel(&RivetChan, "apacheout", rsc,
-            TCL_WRITABLE);
+    *(rsc->outchannel) = Tcl_CreateChannel(&RivetChan, "apacheout", rsc,
TCL_WRITABLE);
 
     Tcl_SetStdChannel(*(rsc->outchannel), TCL_STDOUT);
 
@@ -959,7 +963,8 @@
  *     RivetServerConf UploadMaxSize <integer>
  *     RivetServerConf UploadFilesToVar <yes|no>
  *     RivetServerConf SeparateVirtualInterps <yes|no>
-*/
+ *     RivetServerConf HonorHeaderOnlyRequests <yes|no> (2008-06-20: mm)
+ */
 
 static const char *
 Rivet_ServerConf( cmd_parms *cmd, void *dummy, char *var, char *val )
@@ -984,6 +989,8 @@
         Tcl_GetBoolean (NULL, val, &rsc->upload_files_to_var);
     } else if( STREQU( var, "SeparateVirtualInterps" ) ) {
         Tcl_GetBoolean (NULL, val, &rsc->separate_virtual_interps);
+    } else if( STREQU( var, "HonorHeaderOnlyRequests" ) ) {
+        Tcl_GetBoolean (NULL, val, &rsc->honor_header_only_reqs);
     } else {
         string = Rivet_SetScript( cmd->pool, rsc, var, val);
     }
@@ -1152,6 +1159,7 @@
         overrides->upload_max : base->upload_max;
 
     rsc->separate_virtual_interps = base->separate_virtual_interps;
+    rsc->honor_header_only_reqs = base->honor_header_only_reqs;
 
     /* server_name is set up later. */
 
@@ -1461,21 +1469,24 @@
 static int
 Rivet_SendContent(request_rec *r)
 {
-    char error[MAX_STRING_LEN];
-    char timefmt[MAX_STRING_LEN];
+//    char error[MAX_STRING_LEN];
+//    char timefmt[MAX_STRING_LEN];
     int errstatus;
     int retval;
+    int ctype;
 
-    Tcl_Interp *interp;
-    static Tcl_Obj     *request_init = NULL;
-    static Tcl_Obj     *request_cleanup = NULL;
+    Tcl_Interp         *interp;
+    static Tcl_Obj     *request_init = NULL;
+    static Tcl_Obj     *request_cleanup = NULL;
 
     rivet_interp_globals *globals = NULL;
-    rivet_server_conf *rsc = NULL;
-    rivet_server_conf *rdc;
+    rivet_server_conf  *rsc = NULL;
+    rivet_server_conf  *rdc;
 
-    if (!Rivet_CheckType(r))
+    ctype = Rivet_CheckType(r);  
+    if (ctype == CTYPE_NOT_HANDLED) {
         return DECLINED;
+    }
 
     Tcl_MutexLock(&sendMutex);
 
@@ -1489,6 +1500,10 @@
     globals->r = r;
     globals->req = (TclWebRequest *)apr_pcalloc(r->pool, 
sizeof(TclWebRequest));
 
+/* we will test against NULL to check if a charset was specified in the conf */
+
+    globals->req->charset = NULL;
+
     if (r->per_dir_config != NULL)
         rdc = RIVET_SERVER_CONF( r->per_dir_config );
     else
@@ -1517,8 +1532,8 @@
         goto sendcleanup;
     }
 
-    apr_cpystrn(error, DEFAULT_ERROR_MSG, sizeof(error));
-    apr_cpystrn(timefmt, DEFAULT_TIME_FORMAT, sizeof(timefmt));
+//    apr_cpystrn(error, DEFAULT_ERROR_MSG, sizeof(error));
+//    apr_cpystrn(timefmt, DEFAULT_TIME_FORMAT, sizeof(timefmt));
 
     /* This one is the big catch when it comes to moving towards
        Apache 2.0, or one of them, at least. */
@@ -1581,12 +1596,50 @@
         goto sendcleanup;
     }
 
-    if (r->header_only)
+    if (r->header_only && !rsc->honor_header_only_reqs)
     {
         TclWeb_SetHeaderType(DEFAULT_HEADER_TYPE, globals->req);
         TclWeb_PrintHeaders(globals->req);
         retval = OK;
         goto sendcleanup;
+    } 
+
+/* 
+ * if we are handling the request we also want to check if a charset 
+ * parameter was set with the content type, e.g. rivet's configuration 
+ * or .htaccess had lines like 
+ *
+ * AddType 'application/x-httpd-rivet; charset=utf-8;' rvt 
+ */
+ 
+/*
+ * if strlen(req->content_type) > strlen([RIVET|TCL]_FILE_CTYPE)
+ * a charset parameters might be there 
+ */
+
+    {
+       int content_type_len = strlen(r->content_type);
+
+       if (((ctype==RIVET_FILE) && (content_type_len > 
strlen(RIVET_FILE_CTYPE))) || \
+            ((ctype==TCL_FILE)  && (content_type_len > 
strlen(TCL_FILE_CTYPE)))) {
+           
+           char* charset;
+
+           /* we parse the content type: we are after a 'charset' parameter
definition */
+               
+           charset = strstr(r->content_type,"charset");
+           if (charset != NULL) {
+               charset = apr_pstrdup(r->pool,charset);
+
+           /* ther's some freedom about spaces in the AddType lines: let's 
strip
them off */
+
+               apr_collapse_spaces(charset,charset);
+               globals->req->charset = charset;
+
+               fprintf(stderr,"%s\n",charset);
+               fflush(stderr);
+           }
+       }
     }
 
     if (Rivet_ParseExecFile(globals->req, r->filename, 1) != TCL_OK)
@@ -1600,7 +1653,7 @@
         Tcl_IncrRefCount(request_cleanup);
     }
 
-    if(Tcl_EvalObjEx(interp, request_cleanup, 0) == TCL_ERROR) {
+    if (Tcl_EvalObjEx(interp, request_cleanup, 0) == TCL_ERROR) {
         ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, "%s",
                 Tcl_GetVar(interp, "errorInfo", 0));
     }
@@ -1615,7 +1668,6 @@
     return retval;
 }
 
-
 static void
 rivet_register_hooks (apr_pool_t *p)
 {
Index: src/apache-2/TclWebapache.c
===================================================================
--- src/apache-2/TclWebapache.c (revision 669345)
+++ src/apache-2/TclWebapache.c (working copy)
@@ -87,7 +87,8 @@
     if(req->headers_set)
         return TCL_ERROR;
 
-    req->req->content_type = (char *) apr_pstrdup(req->req->pool, header);
+//    req->req->content_type = (char *) apr_pstrdup(req->req->pool, header);
+    ap_set_content_type(req->req,header);
     req->headers_set = 1;
     return TCL_OK;
 }
Index: src/TclWeb.h
===================================================================
--- src/TclWeb.h        (revision 669345)
+++ src/TclWeb.h        (working copy)
@@ -32,6 +32,7 @@
     int headers_set;           /* has the header been set yet? */
     int content_sent;
     int environment_set;       /* have we setup the environment variables? */
+    char* charset;
 } TclWebRequest;
 
 /*


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to