From: Martin Kraemer Date: Mon, 15 Dec 2003 14:24:31 +0000 (+0000) Subject: Flame bait: mod_charset_lite would decide in the mime checker phase X-Git-Tag: pre_ajp_proxy~920 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e4a2a262326c10ee8a51fe0b818f705d96b12a0b;p=apache Flame bait: mod_charset_lite would decide in the mime checker phase whether a conversion was required, and would stick with that decision, even if a later handler (like CGI script) would modify the actual MIME type returned in the response. That was fatal when an EBCDIC machine was going to return, say, an image/gif (because the initial MIME type would be text/plain, and only later on be set to image/gif). But even for "ordinary" ASCII-based machines the conversion fails if a CGI script decides to return UTF-16 data. At the moment the following change is #if #system(bs2000), but IMHO it should be enabled globally: I moved the conversion decision into the filter itself (because it is the handler which does the final decision which MIME time is tagged on the response, and we can only evaluate its decision after it started the output generation). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102066 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/experimental/mod_charset_lite.c b/modules/experimental/mod_charset_lite.c index 08f16ff11e..ed8bebf46a 100644 --- a/modules/experimental/mod_charset_lite.c +++ b/modules/experimental/mod_charset_lite.c @@ -307,7 +307,16 @@ static int find_code_page(request_rec *r) "mime type is %s; no translation selected", mime_type); } +#if #system(bs2000) +/* We must not bail out here (i.e., the MIME test must be in the filter + * itself, not in the fixup, because only then is the final MIME type known. + * Examples for late changes to the MIME type include CGI handling (MIME + * type is set in the Content-Type header produced by the CGI script), or + * PHP (until PHP runs, the MIME type is set to application/x-httpd-php) + */ +#else return DECLINED; +#endif } if (dc->debug >= DBGLVL_GORY) { @@ -330,6 +339,16 @@ static int find_code_page(request_rec *r) ap_set_module_config(r->request_config, &charset_lite_module, reqinfo); reqinfo->output_ctx = output_ctx; + +#if #system(bs2000) +/* We must not open the xlation table here yet, because the final MIME + * type is not known until we are actually called in the output filter. + * With POST or PUT request, the case is different, because their MIME + * type is set in the request headers, and their data are prerequisites + * for actually calling, e.g., the CGI handler later on. + */ + output_ctx->xlate = NULL; +#else rv = apr_xlate_open(&output_ctx->xlate, dc->charset_default, dc->charset_source, r->pool); if (rv != APR_SUCCESS) { @@ -338,6 +357,7 @@ static int find_code_page(request_rec *r) dc->charset_source, dc->charset_default); return HTTP_INTERNAL_SERVER_ERROR; } +#endif switch (r->method_number) { case M_PUT: @@ -858,6 +878,56 @@ static apr_status_t xlate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) } } +#if #system(bs2000) + /* Opening the output translation (this used to be done in the fixup hook, + * but that was too early: a subsequent type modification, e.g., by a + * CGI script, would go unnoticed. Now we do it in the filter itself.) + */ + if (!ctx->noop && ctx->xlate == NULL) + { + const char *mime_type = f->r->content_type ? f->r->content_type : ap_default_type(f->r); + + /* XXX When we handle translation of the request body, watch out here as + * 1.3 allowed additional mime types: multipart and + * application/x-www-form-urlencoded + */ + if (strncasecmp(mime_type, "text/", 5) == 0 || +#if APR_CHARSET_EBCDIC + /* On an EBCDIC machine, be willing to translate mod_autoindex- + * generated output. Otherwise, it doesn't look too cool. + * + * XXX This isn't a perfect fix because this doesn't trigger us + * to convert from the charset of the source code to ASCII. The + * general solution seems to be to allow a generator to set an + * indicator in the r specifying that the body is coded in the + * implementation character set (i.e., the charset of the source + * code). This would get several different types of documents + * translated properly: mod_autoindex output, mod_status output, + * mod_info output, hard-coded error documents, etc. + */ + strcmp(mime_type, DIR_MAGIC_TYPE) == 0 || +#endif + strncasecmp(mime_type, "message/", 8) == 0) { + + rv = apr_xlate_open(&ctx->xlate, + dc->charset_default, dc->charset_source, f->r->pool); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, + "can't open translation %s->%s", + dc->charset_source, dc->charset_default); + ctx->noop = 1; + } + } + else { + ctx->noop = 1; + if (dc->debug >= DBGLVL_GORY) + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, + "mime type is %s; no translation selected", + mime_type); + } + } +#endif + if (dc->debug >= DBGLVL_GORY) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "xlate_out_filter() - "