--- mod_czs.c 2000/08/09 07:13:10 1.2 +++ mod_czs.c 2000/08/13 20:11:51 1.13 @@ -1,6 +1,10 @@ /* * mod_czs -- nuke iso8859-2 characters + * sets `Contnet-type: text/html; charset=foobar' based on user agent string + * from client browser + * * Dobrica Pavlinusic + * Robert Avilov (some fixes of ua_charset part) * * based on mod_format by Stephen F. Booth and * mod_mocrify by Peter Triller, Ernst Bachmann @@ -32,67 +36,111 @@ module MODULE_VAR_EXPORT mod_czs; FILE *in; -int do_czs; static int czs_handler(request_rec *r) { char buffer[MAX_STRING_LEN] = "undefined buffer content"; - int i; + char *b,*do_czs,*do_mac; + char *rexp = "< *META *HTTP-EQUIV=\"(Content-Type)\" *CONTENT=\"(text/html[^\"]+)\" *>"; + regex_t *regexp; + int nsub = 10; + regmatch_t regm[10]; + int i,f_ch=MAX_STRING_LEN,l_ch=0; if(r->method_number != M_GET) return DECLINED; if(r->finfo.st_mode == 0) return NOT_FOUND; + do_czs = (char *)ap_table_get(r->notes,"do_czs"); + do_mac = (char *)ap_table_get(r->notes,"do_mac"); + in = ap_pfopen(r->pool, r->filename, "r"); if(in == NULL) { ap_log_reason("file permissions deny server access", r->filename, r); return FORBIDDEN; } - if(r->args != 0 || do_czs) { - ap_table_setn(r->headers_out, "X-czs_filename", r->filename); - if (r->args != 0) { - ap_table_setn(r->headers_out, "X-czs_args", r->args); - } +#ifdef DEBUG + ap_table_setn(r->headers_out, "X-czs_filename", r->filename); + if (r->args != 0) { + ap_table_setn(r->headers_out, "X-czs_args", r->args); } + ap_table_setn(r->headers_out, "X-do_czs", do_czs); + ap_table_setn(r->headers_out, "X-do_mac", do_mac); + ap_table_setn(r->headers_out, "X-content-type", r->content_type); +#endif - r->content_type = "text/html"; /* hm? */ +#ifdef TEST_QUERYSTRINGV + if (r->args == 0 && do_czs == NULL && do_mac == NULL || ap_strcasestr(r->content_type,"cgi") != NULL) { +#else + if (do_czs == NULL && do_mac == NULL || ap_strcasestr(r->content_type,"cgi") != NULL) { +#endif + return DECLINED; +/* ap_send_fd(in, r); */ + } else { - ap_soft_timeout("send", r); - ap_send_http_header(r); + regexp = ap_pregcomp(r->pool, rexp, REG_EXTENDED | REG_ICASE ); + + if (regexp == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, + "unable to compile pattern \"%s\"", rexp); + return DECLINED; + } + + ap_soft_timeout("send", r); + ap_send_http_header(r); - if(r->header_only) { - ap_kill_timeout(r); - ap_pfclose(r->pool, in); - return OK; - } + if(r->header_only) { + ap_kill_timeout(r); + ap_pfclose(r->pool, in); + return OK; + } -#ifdef TEST_QUERYSTRING - if(r->args == 0 && !do_czs) { - ap_send_fd(in, r); - } else { + + while(fgets(buffer,MAX_STRING_LEN,in)) { + if (do_czs != NULL) { + for(i=0; i\n",i,regm[i].rm_so,regm[i].rm_eo); #endif - while(fgets(buffer,MAX_STRING_LEN,in)) { - for(i=0; i l_ch) + l_ch = regm[i].rm_eo; + } +#if 0 + ap_rprintf(r,"\n",i,regm[i].rm_so,regm[i].rm_eo); +#endif + } + buffer[f_ch]=0; + ap_rprintf(r,"%s", ap_pstrcat(r->pool, buffer,"", buffer+l_ch, NULL)); + } else { + ap_rprintf(r,"%s",buffer); } } - ap_rprintf(r,"%s",buffer); - } -#ifdef TEST_QUERYSTRING +/* ap_pregfree(r->pool, regexp); */ } -#endif ap_kill_timeout(r); ap_pfclose(r->pool, in); @@ -102,22 +150,92 @@ int translate_path(request_rec *r) { char *uri = r->uri; request_rec *subr; + char *ct; + char *ua; - if (uri[0]=='/' && uri[1]=='_' && uri[2]=='/') { -#if 0 - ap_table_setn(r->headers_out, "Location", ap_pstrcat(r->pool, uri+2, "?czs", NULL)); - return REDIRECT; +#ifdef DEBUG + ap_table_setn(r->headers_out, "X-translate-uri", r->uri); #endif - subr = (request_rec *) ap_sub_req_lookup_uri(r->uri+2, r); + + if (uri[0]=='/' && (uri[1] | 0x20) =='c' && (uri[2] | 0x20)=='z' && (uri[3] | 0x20) =='s' && uri[4]=='/') { + subr = (request_rec *) ap_sub_req_lookup_uri(r->uri+4, r); r->filename=ap_pstrdup(r->pool, subr->filename); + ct = (char *)subr->content_type; + if (ct == NULL) return DECLINED; /* hm? */ +#ifdef DEBUG + ap_table_setn(r->headers_out, "X-translate-sub-ct", ct); +#endif + ap_table_setn(r->notes,"do_czs",ap_pstrdup(r->pool,"1")); ap_destroy_sub_req(subr); - do_czs=1; return OK; } + ua = (char *)ap_table_get(r->headers_in, "User-Agent"); + if (ua == NULL) ua = "unknown"; + +#ifdef DEBUG + ap_table_setn(r->headers_out, "X-translate-UA", ua); +#endif + + if (uri[0]=='/' && (uri[1] | 0x20) =='m' && (uri[2] | 0x20)=='a' && (uri[3] | 0x20) =='c' && uri[4]=='/') { + subr = (request_rec *) ap_sub_req_lookup_uri(r->uri+4, r); + r->filename=ap_pstrdup(r->pool, subr->filename); + ct = (char *)subr->content_type; + if (ct == NULL) return DECLINED; /* hm? */ +#ifdef DEBUG + ap_table_setn(r->headers_out, "X-translate-sub-ct", ct); +#endif + /* will store User-Agent in do_mac as true value */ + if (ap_strcasestr(ua, "Mac")) + ap_table_setn(r->notes,"do_mac",ua); + else { + ap_table_setn(r->headers_out, "Location", r->uri+4); + return REDIRECT; + } + ap_destroy_sub_req(subr); + return OK; + } + +#if 0 + if (ap_strcasestr(ua, "Mac")) { + ap_table_setn(r->headers_out, "Location", ap_pstrcat(r->pool, "/mac/", r->uri, NULL)); + return REDIRECT; + } +#endif + + return DECLINED; +} + +static int add_charset_header(request_rec * r) +{ + char *ua, *ct; + + ua = (char *)ap_table_get(r->notes, "do_mac"); + ct = (char *)r->content_type; + + if (ct != NULL && !ap_table_get(r->notes,"do_czs")) { + + if (ap_strcasestr(ct, "text") == NULL) + return DECLINED; /* Don't mess with other types */ + + if (ua) { /* do_mac */ + if (ap_strcasestr(ua, "MSIE") != NULL) + r->content_type = ap_pstrcat(r->pool, ct,"; charset=x-mac-roman", NULL); + else + r->content_type = ap_pstrcat(r->pool, ct,"; charset=MacCE", NULL); + } else + r->content_type = ap_pstrcat(r->pool, ct,"; charset=iso-8859-2", NULL); + } + +#ifdef DEBUG + ap_table_setn(r->headers_out, "X-Content-Type", ct); + ap_table_setn(r->headers_out, "X-new-Content-Type", r->content_type); + ap_table_setn(r->headers_out, "X-User-Agent", ua); +#endif return DECLINED; } - + + /* Dispatch list of content handlers */ static const handler_rec czs_handlers[] = { { "czs", czs_handler }, @@ -139,11 +257,17 @@ NULL, /* [#5] check if the user is ok _here_ */ NULL, /* [#2] check access by host address */ NULL, /* [#6] determine MIME type */ - NULL, /* [#7] pre-run fixups */ + add_charset_header, /* [#7] pre-run fixups */ NULL, /* [#9] log a transaction */ NULL, /* [#3] header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* [#0] post read-request */ +#ifdef EAPI + ,NULL, /* EAPI: add_module */ + NULL, /* EAPI: remove_module */ + NULL, /* EAPI: rewrite_command */ + NULL /* EAPI: new_connection */ +#endif };