/* 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 See the website for details: http://apache.webthing.com/mod_xmlns/ */ #include "mod_xmlns.h" #include #include #define F ctx->f #define BB ctx->bb #define XHTML10 "http://www.w3.org/1999/xhtml" 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 apr_status_t hstart(xmlns_public* ctx, const parsedname* name3, const xml_char_t** atts) { if ( ! strncmp(name3->elt, "meta", 4) ) { const xml_char_t** 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 APR_SUCCESS ; } } ap_fputc(F, BB, '<') ; ap_fwrite(F, BB, name3->elt, name3->eltlen) ; if ( atts ) { const xml_char_t** a ; for ( a = atts ; *a ; a += 2 ) { /* Parse the attributes to deal correctly with attributes from other namespaces. */ parsedname a3 ; xmlns_parsename(*a, &a3) ; ap_fputc(F, BB, ' ') ; switch ( a3.nparts ) { case 2: ap_fwrite(F, BB, a3.ns, a3.nslen) ; ap_fputc(F, BB, ':') ; break ; case 3: ap_fwrite(F, BB, a3.prefix, a3.prefixlen) ; ap_fputc(F, BB, ':') ; break ; } ap_fwrite(F, BB, a3.elt, a3.eltlen) ; ap_fputstrs(F, BB, "=\"", a[1], "\"", NULL) ; } } if ( !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 APR_SUCCESS ; } static apr_status_t hend(xmlns_public* ctx, const parsedname* name) { if ( ! is_empty(name) ) { ap_fputs(F, BB, "elt, name->eltlen) ; ap_fputc(F, BB, '>') ; } return APR_SUCCESS ; } /* we don't yet implement SSI */ #define CommentStr NULL #define hcomment NULL static xmlns xmlns_xhtml10 = { hstart , /* StartElement */ hend , /* EndElement */ NULL , /* StartNSDecl */ NULL , /* EndNSDecl */ CommentStr , /* Comment Identifier (should be "#") */ hcomment /* Comment Handler */ } ; static void xhtml_hooks(apr_pool_t* pool) { ap_register_provider(pool, "xmlns", XHTML10 , "1.0", &xmlns_xhtml10) ; } module AP_MODULE_DECLARE_DATA xhtml_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, NULL, xhtml_hooks } ;