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]