/* Copyright (c) 2003, WebThing Ltd Author: Nick Kew This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Namespace Handler for XHTML (http://www.w3.org/1999/xhtml) This will process XHTML markup to Appendix-C compatible XHTML that can be sent to current and older web browsers as text/html * All HTML is written in the default namespace * Empty elements end with " />" * Substitutes any META element that sets content-type PURPOSE: * Distributed with mod_xmlns as a sample namespace processor * May be useful operationally to post-process XHTML that is not Appendix-C compliant. BUGS: * If there is a default namespace defined for something other than XHTML, it'll get confused. * Doesn't reliably support charset declaration in a META element COMPILING: minimal example with GCC, in the same directory as mod_xmlns.h $ gcc -Wall -O2 -fPIC -shared -I/usr/local/apache/include -o /usr/local/apache/modules/xhtml10.so xhtml10.c BASIC USAGE with mod_xmlns (or mod_publisher_xml): # Load the module LoadModule xmlns_module /usr/local/apache/modules/mod_xmlns.so # Activate it on selected MIME types AddOutputFilterByType xmlns text/xml application/xml [...] # Load support for the XHTML namespace LoadNamespace xmlns_xhtml10 /usr/local/apache/modules/xhtml10.so See the website for details: http://apache.webthing.com/mod_xmlns/ */ #include "mod_xmlns.h" #include #include static int is_empty(const parsedname* name) { const char** p ; static const char* empty_elts[] = { "br" , "link" , "img" , "hr" , "input" , "meta" , "base" , "area" , "param" , "col" , "frame" , "isindex" , "basefont" , NULL } ; for ( p = empty_elts ; *p ; ++p ) if ( ( name->eltlen == strlen(*p) ) && !strncmp( *p, name->elt, name->eltlen) ) return 1 ; return 0 ; } static int hstart(saxctxt* ctx, const parsedname* name3, const XML_Char** atts) { int have_default_ns = 0 ; apr_hash_index_t* index ; if ( ! strncmp(name3->elt, "meta", 4) ) { const XML_Char** a ; for ( a = atts ; *a ; a += 2 ) if ( !strcasecmp(a[0], "http-equiv") && a[1] && !strcasecmp(a[1], "content-type") ) { ap_fputs(F, BB, "") ; return 1 ; } } ap_fputc(F, BB, '<') ; ap_fwrite(F, BB, name3->elt, name3->eltlen) ; if ( atts ) { const XML_Char** a ; for ( a = atts ; *a ; a += 2 ) { ap_fputstrs(F, BB, " ", a[0], "=\"", a[1], "\"", NULL) ; } } for ( index = apr_hash_first(CTX->f->r->pool, CTX->activens) ; index ; index = apr_hash_next(index) ) { const void* prefix ; void* rec ; apr_ssize_t len ; apr_hash_this(index, &prefix, &len, &rec) ; if ( ! ((xmlns_active*)rec)->printed ) { if ( prefix && strlen((const char*)prefix) ) if ( ((xmlns_active*)rec)->ns ) ap_fputstrs(F, BB, " xmlns:", (const char*)prefix , "=\"", ((xmlns_active*)rec)->ns->xmlns, "\"", NULL) ; else { ap_fputstrs(F, BB, " xmlns:", (const char*)prefix , "=\"", NULL) ; ap_fwrite(F, BB, name3->ns, name3->nslen) ; ap_fputc(F, BB, '"') ; } else { if ( ((xmlns_active*)rec)->ns ) ap_fputstrs(F, BB, " xmlns=\"", ((xmlns_active*)rec)->ns->xmlns, "\"", NULL) ; else { ap_fputs(F, BB, " xmlns=\"") ; ap_fwrite(F, BB, name3->ns, name3->nslen) ; ap_fputc(F, BB, '"') ; } have_default_ns = 1 ; } ((xmlns_active*)rec)->printed = 1 ; } } if ( ! have_default_ns && !strncmp( "html", name3->elt, 4) ) ap_fputs(F, BB, " xmlns=\"http://www.w3.org/1999/xhtml\">") ; else if ( is_empty(name3) ) ap_fputs(F, BB, " />") ; else ap_fputc(F, BB, '>') ; return 1 ; /* nonzero return to suppress default */ } static int hend(saxctxt* ctx, const parsedname* name) { if ( ! is_empty(name) ) { ap_fputs(F, BB, "elt, name->eltlen) ; ap_fputc(F, BB, '>') ; } return 1 ; /* nonzero return to suppress default */ } xmlns xmlns_xhtml10 = { "http://www.w3.org/1999/xhtml" , /* URI */ hstart , /* StartElement */ hend , /* EndElement */ NULL , /* StartNSDecl */ NULL , /* EndNSDecl */ NULL /* private */ } ;