libxml2 r3790 - in trunk: . python



Author: veillard
Date: Mon Sep  1 13:08:57 2008
New Revision: 3790
URL: http://svn.gnome.org/viewvc/libxml2?rev=3790&view=rev

Log:
* trionan.c: Borland C fix from Moritz Both
* testapi.c: regenerate, workaround a problem for buffer testing
* xmlIO.c HTMLtree.c: new internal entry point to hide even better
  xmlAllocOutputBufferInternal
* tree.c: harden the code around buffer allocation schemes
* parser.c: restore the warning when namespace names are not absolute
  URIs
* runxmlconf.c: continue regression tests if we get the expected
  number of errors
* Makefile.am: run the python tests on make check
* xmlsave.c: handle the HTML documents and trees
* python/libxml.c: convert python serialization to the xmlSave APIs
  and avoid some horrible hacks
Daniel


Modified:
   trunk/ChangeLog
   trunk/HTMLtree.c
   trunk/Makefile.am
   trunk/NEWS
   trunk/gentest.py
   trunk/parser.c
   trunk/python/libxml.c
   trunk/runxmlconf.c
   trunk/testapi.c
   trunk/tree.c
   trunk/trionan.c
   trunk/xmlIO.c
   trunk/xmlsave.c

Modified: trunk/HTMLtree.c
==============================================================================
--- trunk/HTMLtree.c	(original)
+++ trunk/HTMLtree.c	Mon Sep  1 13:08:57 2008
@@ -316,6 +316,11 @@
 }
 
 #ifdef LIBXML_OUTPUT_ENABLED
+/*
+ * private routine exported from xmlIO.c
+ */
+xmlOutputBufferPtr
+xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
 /************************************************************************
  *									*
  * 			Output error handlers				*
@@ -566,7 +571,7 @@
     if (handler == NULL)
 	handler = xmlFindCharEncodingHandler("ascii");
 
-    buf = xmlAllocOutputBuffer(handler);
+    buf = xmlAllocOutputBufferInternal(handler);
     if (buf == NULL) {
 	*mem = NULL;
 	*size = 0;

Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am	(original)
+++ trunk/Makefile.am	Mon Sep  1 13:08:57 2008
@@ -157,7 +157,7 @@
 
 # that one is just to make sure it is rebuilt if missing
 # but adding the dependances generate mess
-testapi.c:
+testapi.c: $(srcdir)/gentest.py
 	-@(if [ "$(PYTHON)" != "" ] ; then \
 	    $(PYTHON) $(srcdir)/gentest.py $(srcdir) ; fi )
 
@@ -178,6 +178,8 @@
 
 runtests:
 	$(CHECKER) ./runtest$(EXEEXT) && $(CHECKER) ./testrecurse$(EXEEXT) &&$(CHECKER) ./testapi$(EXEEXT) && $(CHECKER) ./testchar$(EXEEXT)&& $(CHECKER) ./testdict$(EXEEXT) && $(CHECKER) ./runxmlconf$(EXEEXT)
+	@(if [ "@PYTHON_SUBDIR@" != "" ] ; then cd python ; \
+	    $(MAKE) MAKEFLAGS+=--silent tests ; fi)
 
 check: all runtests
 

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Mon Sep  1 13:08:57 2008
@@ -15,6 +15,33 @@
 to the SVN at 
 http://svn.gnome.org/viewcvs/libxml2/trunk/
  code base.Here is the list of public releases:
+2.7.0: Aug 30 2008:
+   - Documentation: switch ChangeLog to UTF-8, improve mutithreads and
+      xmlParserCleanup docs
+   - Portability fixes: Older Win32 platforms (Rob Richards), MSVC
+      porting fix (Rob Richards), Mac OS X regression tests (Sven Herzberg),
+      non GNUCC builds (Rob Richards), compilation on Haiku (Andreas FÃrber)
+      
+   - Bug fixes: various realloc problems (Ashwin), potential double-free
+      (Ashwin), regexp crash, icrash with invalid whitespace facets (Rob
+      Richards), pattern fix when streaming (William Brack), various XML
+      parsing and validation fixes based on the W3C regression tests, reader
+      tree skipping function fix (Ashwin), Schemas regexps escaping fix
+      (Volker Grabsch), handling of entity push errors (Ashwin), fix a slowdown
+      when encoder cant serialize characters on output
+   - Code cleanup: compilation fix without the reader, without the output
+      (Robert Schwebel), python whitespace (Martin), many space/tabs cleanups,
+      serious cleanup of the entity handling code
+   - Improvement: switch parser to XML-1.0 5th edition, add parsing flags
+      for old versions, switch URI parsing to RFC 3986,
+      add xmlSchemaValidCtxtGetParserCtxt (Holger Kaelberer),
+      new hashing functions for dictionnaries (based on Stefan Behnel work),
+      improve handling of misplaced html/head/body in HTML parser, better
+      regression test tools and code coverage display, better algorithms
+      to detect various versions of the billion laughts attacks, make
+      arbitrary parser limits avoidable as a parser option
+
+
 2.6.32: Apr 8 2008:
    - Documentation: returning heap memory to kernel (Wolfram Sang),
       trying to clarify xmlCleanupParser() use, xmlXPathContext improvement

Modified: trunk/gentest.py
==============================================================================
--- trunk/gentest.py	(original)
+++ trunk/gentest.py	Mon Sep  1 13:08:57 2008
@@ -260,6 +260,7 @@
    "xmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
    "xmlParseExtParsedEnt": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
    "xmlDOMWrapAdoptNode": "if ((node != NULL) && (node->parent == NULL)) {xmlUnlinkNode(node);xmlFreeNode(node);node = NULL;}",
+   "xmlBufferSetAllocationScheme": "if ((buf != NULL) && (scheme == XML_BUFFER_ALLOC_IMMUTABLE) && (buf->content != NULL) && (buf->content != static_buf_content)) { xmlFree(buf->content); buf->content = NULL;}"
 }
 
 modules = []

Modified: trunk/parser.c
==============================================================================
--- trunk/parser.c	(original)
+++ trunk/parser.c	Mon Sep  1 13:08:57 2008
@@ -8694,7 +8694,7 @@
 			         "xmlns: '%s' is not a valid URI\n",
 					   URL, NULL, NULL);
 		    } else {
-			if ((ctxt->pedantic) && (uri->scheme == NULL)) {
+			if (uri->scheme == NULL) {
 			    xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
 				      "xmlns: URI %s is not absolute\n",
 				      URL, NULL, NULL);

Modified: trunk/python/libxml.c
==============================================================================
--- trunk/python/libxml.c	(original)
+++ trunk/python/libxml.c	Mon Sep  1 13:08:57 2008
@@ -24,6 +24,7 @@
 #include <libxml/xmlIO.h>
 #include <libxml/c14n.h>
 #include <libxml/xmlreader.h>
+#include <libxml/xmlsave.h>
 #include "libxml_wrap.h"
 #include "libxml2-py.h"
 
@@ -2761,6 +2762,9 @@
     const char *encoding;
     int format;
     int len;
+    xmlSaveCtxtPtr ctxt;
+    xmlBufferPtr buf;
+    int options = 0;
 
     if (!PyArg_ParseTuple(args, (char *) "Ozi:serializeNode", &pyobj_node,
                           &encoding, &format))
@@ -2773,137 +2777,52 @@
     }
     if (node->type == XML_DOCUMENT_NODE) {
         doc = (xmlDocPtr) node;
-        xmlDocDumpFormatMemoryEnc(doc, &c_retval, &len,
-                                  (const char *) encoding, format);
-        py_retval = libxml_charPtrWrap((char *) c_retval);
+	node = NULL;
 #ifdef LIBXML_HTML_ENABLED
     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
-        xmlOutputBufferPtr buf;
-        xmlCharEncodingHandlerPtr handler = NULL;
-
         doc = (xmlDocPtr) node;
-        if (encoding != NULL)
-            htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
-        encoding = (const char *) htmlGetMetaEncoding(doc);
-
-        if (encoding != NULL) {
-            handler = xmlFindCharEncodingHandler(encoding);
-            if (handler == NULL) {
-                Py_INCREF(Py_None);
-                return (Py_None);
-            }
-        }
-
-        /*
-         * Fallback to HTML or ASCII when the encoding is unspecified
-         */
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("HTML");
-        if (handler == NULL)
-            handler = xmlFindCharEncodingHandler("ascii");
-
-        buf = xmlAllocOutputBuffer(handler);
-        if (buf == NULL) {
-            Py_INCREF(Py_None);
-            return (Py_None);
-        }
-        htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
-        xmlOutputBufferFlush(buf);
-        if (buf->conv != NULL) {
-            len = buf->conv->use;
-            c_retval = buf->conv->content;
-            buf->conv->content = NULL;
-        } else {
-            len = buf->buffer->use;
-            c_retval = buf->buffer->content;
-            buf->buffer->content = NULL;
-        }
-        (void) xmlOutputBufferClose(buf);
-        py_retval = libxml_charPtrWrap((char *) c_retval);
-#endif /* LIBXML_HTML_ENABLED */
+	node = NULL;
+#endif
     } else {
         if (node->type == XML_NAMESPACE_DECL)
 	    doc = NULL;
 	else
             doc = node->doc;
         if ((doc == NULL) || (doc->type == XML_DOCUMENT_NODE)) {
-            xmlOutputBufferPtr buf;
-            xmlCharEncodingHandlerPtr handler = NULL;
-
-            if (encoding != NULL) {
-                handler = xmlFindCharEncodingHandler(encoding);
-                if (handler == NULL) {
-                    Py_INCREF(Py_None);
-                    return (Py_None);
-                }
-            }
-
-            buf = xmlAllocOutputBuffer(handler);
-            if (buf == NULL) {
-                Py_INCREF(Py_None);
-                return (Py_None);
-            }
-            xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
-            xmlOutputBufferFlush(buf);
-            if (buf->conv != NULL) {
-                len = buf->conv->use;
-                c_retval = buf->conv->content;
-                buf->conv->content = NULL;
-            } else {
-                len = buf->buffer->use;
-                c_retval = buf->buffer->content;
-                buf->buffer->content = NULL;
-            }
-            (void) xmlOutputBufferClose(buf);
-            py_retval = libxml_charPtrWrap((char *) c_retval);
 #ifdef LIBXML_HTML_ENABLED
         } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
-            xmlOutputBufferPtr buf;
-            xmlCharEncodingHandlerPtr handler = NULL;
-
-            if (encoding != NULL)
-                htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
-            encoding = (const char *) htmlGetMetaEncoding(doc);
-            if (encoding != NULL) {
-                handler = xmlFindCharEncodingHandler(encoding);
-                if (handler == NULL) {
-                    Py_INCREF(Py_None);
-                    return (Py_None);
-                }
-            }
-
-            /*
-             * Fallback to HTML or ASCII when the encoding is unspecified
-             */
-            if (handler == NULL)
-                handler = xmlFindCharEncodingHandler("HTML");
-            if (handler == NULL)
-                handler = xmlFindCharEncodingHandler("ascii");
-
-            buf = xmlAllocOutputBuffer(handler);
-            if (buf == NULL) {
-                Py_INCREF(Py_None);
-                return (Py_None);
-            }
-            htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
-            xmlOutputBufferFlush(buf);
-            if (buf->conv != NULL) {
-                len = buf->conv->use;
-                c_retval = buf->conv->content;
-                buf->conv->content = NULL;
-            } else {
-                len = buf->buffer->use;
-                c_retval = buf->buffer->content;
-                buf->buffer->content = NULL;
-            }
-            (void) xmlOutputBufferClose(buf);
-            py_retval = libxml_charPtrWrap((char *) c_retval);
 #endif /* LIBXML_HTML_ENABLED */
         } else {
             Py_INCREF(Py_None);
             return (Py_None);
         }
     }
+
+
+    buf = xmlBufferCreate();
+    if (buf == NULL) {
+	Py_INCREF(Py_None);
+	return (Py_None);
+    }
+    if (format) options |= XML_SAVE_FORMAT;
+    ctxt = xmlSaveToBuffer(buf, encoding, options);
+    if (ctxt == NULL) {
+	xmlBufferFree(buf);
+	Py_INCREF(Py_None);
+	return (Py_None);
+    }
+    if (node == NULL)
+	xmlSaveDoc(ctxt, doc);
+    else
+	xmlSaveTree(ctxt, node);
+    xmlSaveClose(ctxt);
+
+    c_retval = buf->content;
+    buf->content = NULL;
+
+    xmlBufferFree(buf);
+    py_retval = libxml_charPtrWrap((char *) c_retval);
+
     return (py_retval);
 }
 

Modified: trunk/runxmlconf.c
==============================================================================
--- trunk/runxmlconf.c	(original)
+++ trunk/runxmlconf.c	Mon Sep  1 13:08:57 2008
@@ -33,7 +33,7 @@
 static FILE *logfile = NULL;
 static int verbose = 0;
 
-
+#define NB_EXPECTED_ERRORS 15
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 
@@ -588,10 +588,14 @@
 	printf("Total %d tests, no errors\n",
 	       nb_tests);
     } else {
-        ret = 1;
+	ret = 1;
 	printf("Total %d tests, %d errors, %d leaks\n",
 	       nb_tests, nb_errors, nb_leaks);
 	printf("See %s for detailed output\n", LOGFILE);
+	if ((nb_leaks == 0) && (nb_errors == NB_EXPECTED_ERRORS)) {
+	    printf("%d errors were expected\n", nb_errors);
+	    ret = 0;
+	}
     }
     xmlXPathFreeContext(ctxtXPath);
     xmlCleanupParser();

Modified: trunk/testapi.c
==============================================================================
--- trunk/testapi.c	(original)
+++ trunk/testapi.c	Mon Sep  1 13:08:57 2008
@@ -599,9 +599,10 @@
 #endif
 
 #define gen_nb_xmlBufferPtr 3
+static const char *static_buf_content = "a static buffer";
 static xmlBufferPtr gen_xmlBufferPtr(int no, int nr ATTRIBUTE_UNUSED) {
     if (no == 0) return(xmlBufferCreate());
-    if (no == 1) return(xmlBufferCreateStatic((void *)"a static buffer", 13));
+    if (no == 1) return(xmlBufferCreateStatic((void *)static_buf_content, 13));
     return(NULL);
 }
 static void des_xmlBufferPtr(int no ATTRIBUTE_UNUSED, xmlBufferPtr val, int nr ATTRIBUTE_UNUSED) {
@@ -18827,6 +18828,7 @@
         scheme = gen_xmlBufferAllocationScheme(n_scheme, 1);
 
         xmlBufferSetAllocationScheme(buf, scheme);
+        if ((buf != NULL) && (scheme == XML_BUFFER_ALLOC_IMMUTABLE) && (buf->content != NULL) && (buf->content != static_buf_content)) { xmlFree(buf->content); buf->content = NULL;}
         call_tests++;
         des_xmlBufferPtr(n_buf, buf, 0);
         des_xmlBufferAllocationScheme(n_scheme, scheme, 1);

Modified: trunk/tree.c
==============================================================================
--- trunk/tree.c	(original)
+++ trunk/tree.c	Mon Sep  1 13:08:57 2008
@@ -680,7 +680,9 @@
  */
 void
 xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
-    xmlBufferAllocScheme = scheme;
+    if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
+        (scheme == XML_BUFFER_ALLOC_DOUBLEIT))
+	xmlBufferAllocScheme = scheme;
 }
 
 /**
@@ -6736,9 +6738,12 @@
 #endif
         return;
     }
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
-
-    buf->alloc = scheme;
+    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
+        (buf->alloc == XML_BUFFER_ALLOC_IO)) return;
+    if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
+        (scheme == XML_BUFFER_ALLOC_EXACT) ||
+        (scheme == XML_BUFFER_ALLOC_IMMUTABLE))
+	buf->alloc = scheme;
 }
 
 /**

Modified: trunk/trionan.c
==============================================================================
--- trunk/trionan.c	(original)
+++ trunk/trionan.c	Mon Sep  1 13:08:57 2008
@@ -129,7 +129,11 @@
  */
 #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
 
+#if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590)
+static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275;
+#else
 static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
+#endif
 
 /* Mask for the exponent */
 static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {

Modified: trunk/xmlIO.c
==============================================================================
--- trunk/xmlIO.c	(original)
+++ trunk/xmlIO.c	Mon Sep  1 13:08:57 2008
@@ -135,6 +135,9 @@
 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
 static int xmlOutputCallbackNr = 0;
 static int xmlOutputCallbackInitialized = 0;
+
+xmlOutputBufferPtr
+xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /************************************************************************
@@ -1720,7 +1723,7 @@
     {
         /*  Any character conversions should have been done before this  */
 
-        ctxt->doc_buff = xmlAllocOutputBuffer(NULL);
+        ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
     }
 
     if (ctxt->doc_buff == NULL) {
@@ -1731,7 +1734,7 @@
     return (ctxt);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
-				
+
 #ifdef LIBXML_OUTPUT_ENABLED
 /**
  * xmlIOHTTPDfltOpenW
@@ -2275,8 +2278,57 @@
 	return(NULL);
     }
 
+    ret->encoder = encoder;
+    if (encoder != NULL) {
+        ret->conv = xmlBufferCreateSize(4000);
+	if (ret->conv == NULL) {
+	    xmlFree(ret);
+	    return(NULL);
+	}
+
+	/*
+	 * This call is designed to initiate the encoder state
+	 */
+	xmlCharEncOutFunc(encoder, ret->conv, NULL); 
+    } else
+        ret->conv = NULL;
+    ret->writecallback = NULL;
+    ret->closecallback = NULL;
+    ret->context = NULL;
+    ret->written = 0;
+
+    return(ret);
+}
+
+/**
+ * xmlAllocOutputBufferInternal:
+ * @encoder:  the encoding converter or NULL
+ *
+ * Create a buffered parser output
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
+    xmlOutputBufferPtr ret;
+
+    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
+    if (ret == NULL) {
+	xmlIOErrMemory("creating output buffer");
+	return(NULL);
+    }
+    memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
+    ret->buffer = xmlBufferCreate();
+    if (ret->buffer == NULL) {
+        xmlFree(ret);
+	return(NULL);
+    }
+
+
     /*
      * For conversion buffers we use the special IO handling
+     * We don't do that from the exported API to avoid confusing
+     * user's code.
      */
     ret->buffer->alloc = XML_BUFFER_ALLOC_IO;
     ret->buffer->contentIO = ret->buffer->content;
@@ -2302,6 +2354,7 @@
 
     return(ret);
 }
+
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /**
@@ -2502,7 +2555,7 @@
 	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
 	    context = xmlGzfileOpenW(unescaped, compression);
 	    if (context != NULL) {
-		ret = xmlAllocOutputBuffer(encoder);
+		ret = xmlAllocOutputBufferInternal(encoder);
 		if (ret != NULL) {
 		    ret->context = context;
 		    ret->writecallback = xmlGzfileWrite;
@@ -2539,7 +2592,7 @@
 	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
 	    context = xmlGzfileOpenW(URI, compression);
 	    if (context != NULL) {
-		ret = xmlAllocOutputBuffer(encoder);
+		ret = xmlAllocOutputBufferInternal(encoder);
 		if (ret != NULL) {
 		    ret->context = context;
 		    ret->writecallback = xmlGzfileWrite;
@@ -2572,7 +2625,7 @@
     /*
      * Allocate the Output buffer front-end.
      */
-    ret = xmlAllocOutputBuffer(encoder);
+    ret = xmlAllocOutputBufferInternal(encoder);
     if (ret != NULL) {
 	ret->context = context;
 	ret->writecallback = xmlOutputCallbackTable[i].writecallback;
@@ -2656,7 +2709,7 @@
 
     if (file == NULL) return(NULL);
 
-    ret = xmlAllocOutputBuffer(encoder);
+    ret = xmlAllocOutputBufferInternal(encoder);
     if (ret != NULL) {
         ret->context = file;
 	ret->writecallback = xmlFileWrite;
@@ -2814,7 +2867,7 @@
 
     if (fd < 0) return(NULL);
 
-    ret = xmlAllocOutputBuffer(encoder);
+    ret = xmlAllocOutputBufferInternal(encoder);
     if (ret != NULL) {
         ret->context = (void *) (long) fd;
 	ret->writecallback = xmlFdWrite;
@@ -2875,7 +2928,7 @@
 
     if (iowrite == NULL) return(NULL);
 
-    ret = xmlAllocOutputBuffer(encoder);
+    ret = xmlAllocOutputBufferInternal(encoder);
     if (ret != NULL) {
         ret->context = (void *) ioctx;
 	ret->writecallback = iowrite;

Modified: trunk/xmlsave.c
==============================================================================
--- trunk/xmlsave.c	(original)
+++ trunk/xmlsave.c	Mon Sep  1 13:08:57 2008
@@ -457,6 +457,40 @@
  *									*
  ************************************************************************/
 
+static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
+    xmlOutputBufferPtr buf = ctxt->buf;
+
+    if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
+	buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
+	if (buf->encoder == NULL) {
+	    xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
+		       (const char *)encoding);
+	    return(-1);
+	}
+	buf->conv = xmlBufferCreate();
+	if (buf->conv == NULL) {
+	    xmlCharEncCloseFunc(buf->encoder);
+	    xmlSaveErrMemory("creating encoding buffer");
+	    return(-1);
+	}
+	/*
+	 * initialize the state, e.g. if outputting a BOM
+	 */
+	xmlCharEncOutFunc(buf->encoder, buf->conv, NULL);
+    }
+    return(0);
+}
+
+static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
+    xmlOutputBufferPtr buf = ctxt->buf;
+    xmlOutputBufferFlush(buf);
+    xmlCharEncCloseFunc(buf->encoder);
+    xmlBufferFree(buf->conv);
+    buf->encoder = NULL;
+    buf->conv = NULL;
+    return(0);
+}
+
 #ifdef LIBXML_HTML_ENABLED
 static void
 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
@@ -638,6 +672,66 @@
     }
 }
 
+#ifdef LIBXML_HTML_ENABLED
+/**
+ * xmlNodeDumpOutputInternal:
+ * @cur:  the current node
+ *
+ * Dump an HTML node, recursive behaviour, children are printed too.
+ */
+static int
+htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
+    const xmlChar *oldenc = NULL;
+    const xmlChar *oldctxtenc = ctxt->encoding;
+    const xmlChar *encoding = ctxt->encoding;
+    xmlOutputBufferPtr buf = ctxt->buf;
+    int switched_encoding = 0;
+    xmlDocPtr doc;
+
+    xmlInitParser();
+
+    doc = cur->doc; {
+    if (doc != NULL)
+        oldenc = doc->encoding;
+	if (ctxt->encoding != NULL) {
+	    doc->encoding = BAD_CAST ctxt->encoding;
+	} else if (doc->encoding != NULL) {
+	    encoding = doc->encoding;
+	}
+    }
+
+    if ((encoding != NULL) && (doc != NULL))
+	htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
+    if ((encoding == NULL) && (doc != NULL))
+	encoding = htmlGetMetaEncoding(doc);
+    if (encoding == NULL)
+	encoding = BAD_CAST "HTML";
+    if ((encoding != NULL) && (oldctxtenc == NULL) &&
+	(buf->encoder == NULL) && (buf->conv == NULL)) {
+	if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
+	    doc->encoding = oldenc;
+	    return(-1);
+	}
+	switched_encoding = 1;
+    }
+    if (ctxt->options & XML_SAVE_FORMAT)
+	htmlNodeDumpFormatOutput(buf, doc, cur,
+				       (const char *)encoding, 1);
+    else
+	htmlNodeDumpFormatOutput(buf, doc, cur,
+				       (const char *)encoding, 0);
+    /*
+     * Restore the state of the saving context at the end of the document
+     */
+    if ((switched_encoding) && (oldctxtenc == NULL)) {
+	xmlSaveClearEncoding(ctxt);
+    }
+    if (doc != NULL)
+	doc->encoding = oldenc;
+    return(0);
+}
+#endif
+
 /**
  * xmlNodeDumpOutputInternal:
  * @cur:  the current node
@@ -662,6 +756,13 @@
 	xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
 	return;
     }
+#ifdef LIBXML_HTML_ENABLED
+    if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
+        (cur->doc->type == XML_HTML_DOCUMENT_NODE)) {
+	htmlNodeDumpOutputInternal(ctxt, cur);
+	return;
+    }
+#endif
     if (cur->type == XML_DTD_NODE) {
         xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
 	return;
@@ -835,9 +936,14 @@
     xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
     xmlOutputBufferPtr buf = ctxt->buf;
     xmlCharEncoding enc;
+    int switched_encoding = 0;
 
     xmlInitParser();
 
+    if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
+        (cur->type != XML_DOCUMENT_NODE))
+	 return(-1);
+
     if (ctxt->encoding != NULL) {
         cur->encoding = BAD_CAST ctxt->encoding;
     } else if (cur->encoding != NULL) {
@@ -847,110 +953,119 @@
 		     xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
     }
 
-    enc = xmlParseCharEncoding((const char*) encoding);
-    if ((encoding != NULL) && (oldctxtenc == NULL) &&
-        (buf->encoder == NULL) && (buf->conv == NULL) &&
-	((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
-	if ((enc != XML_CHAR_ENCODING_UTF8) &&
-	    (enc != XML_CHAR_ENCODING_NONE) &&
-	    (enc != XML_CHAR_ENCODING_ASCII)) {
-	    /*
-	     * we need to switch to this encoding but just for this document
-	     * since we output the XMLDecl the conversion must be done to not
-	     * generate not well formed documents.
-	     */
-	    buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
-	    if (buf->encoder == NULL) {
-		xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
-		           (const char *)encoding);
+    if (cur->type == XML_HTML_DOCUMENT_NODE) {
+#ifdef LIBXML_HTML_ENABLED
+        if (encoding != NULL)
+	    htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
+        if (encoding == NULL)
+	    encoding = htmlGetMetaEncoding(cur);
+        if (encoding == NULL)
+	    encoding = BAD_CAST "HTML";
+	if ((encoding != NULL) && (oldctxtenc == NULL) &&
+	    (buf->encoder == NULL) && (buf->conv == NULL)) {
+	    if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
+		cur->encoding = oldenc;
 		return(-1);
 	    }
-	    buf->conv = xmlBufferCreate();
-	    if (buf->conv == NULL) {
-		xmlCharEncCloseFunc(buf->encoder);
-		xmlSaveErrMemory("creating encoding buffer");
-		return(-1);
+	    switched_encoding = 1;
+	}
+        if (ctxt->options & XML_SAVE_FORMAT)
+	    htmlDocContentDumpFormatOutput(buf, cur,
+	                                   (const char *)encoding, 1);
+	else
+	    htmlDocContentDumpFormatOutput(buf, cur,
+	                                   (const char *)encoding, 0);
+	if (ctxt->encoding != NULL)
+	    cur->encoding = oldenc;
+	return(0);
+#else
+        return(-1);
+#endif
+    } else if (cur->type == XML_DOCUMENT_NODE) {
+	enc = xmlParseCharEncoding((const char*) encoding);
+	if ((encoding != NULL) && (oldctxtenc == NULL) &&
+	    (buf->encoder == NULL) && (buf->conv == NULL) &&
+	    ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
+	    if ((enc != XML_CHAR_ENCODING_UTF8) &&
+		(enc != XML_CHAR_ENCODING_NONE) &&
+		(enc != XML_CHAR_ENCODING_ASCII)) {
+		/*
+		 * we need to switch to this encoding but just for this
+		 * document since we output the XMLDecl the conversion
+		 * must be done to not generate not well formed documents.
+		 */
+		if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
+		    cur->encoding = oldenc;
+		    return(-1);
+		}
+		switched_encoding = 1;
 	    }
-	    /*
-	     * initialize the state, e.g. if outputting a BOM
-	     */
-	    xmlCharEncOutFunc(buf->encoder, buf->conv, NULL);
+	    if (ctxt->escape == xmlEscapeEntities)
+		ctxt->escape = NULL;
+	    if (ctxt->escapeAttr == xmlEscapeEntities)
+		ctxt->escapeAttr = NULL;
 	}
-	if (ctxt->escape == xmlEscapeEntities)
-	    ctxt->escape = NULL;
-	if (ctxt->escapeAttr == xmlEscapeEntities)
-	    ctxt->escapeAttr = NULL;
-    }
 
 
-    /*
-     * Save the XML declaration
-     */
-    if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
-	xmlOutputBufferWrite(buf, 14, "<?xml version=");
-	if (cur->version != NULL) 
-	    xmlBufferWriteQuotedString(buf->buffer, cur->version);
-	else
-	    xmlOutputBufferWrite(buf, 5, "\"1.0\"");
-	if (encoding != NULL) {
-	    xmlOutputBufferWrite(buf, 10, " encoding=");
-	    xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
-	}
-	switch (cur->standalone) {
-	    case 0:
-		xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
-		break;
-	    case 1:
-		xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
-		break;
+	/*
+	 * Save the XML declaration
+	 */
+	if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
+	    xmlOutputBufferWrite(buf, 14, "<?xml version=");
+	    if (cur->version != NULL) 
+		xmlBufferWriteQuotedString(buf->buffer, cur->version);
+	    else
+		xmlOutputBufferWrite(buf, 5, "\"1.0\"");
+	    if (encoding != NULL) {
+		xmlOutputBufferWrite(buf, 10, " encoding=");
+		xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
+	    }
+	    switch (cur->standalone) {
+		case 0:
+		    xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
+		    break;
+		case 1:
+		    xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
+		    break;
+	    }
+	    xmlOutputBufferWrite(buf, 3, "?>\n");
 	}
-	xmlOutputBufferWrite(buf, 3, "?>\n");
-    }
 
 #ifdef LIBXML_HTML_ENABLED
-    if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
-	dtd = xmlGetIntSubset(cur);
-	if (dtd != NULL) {
-	    is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
-	    if (is_xhtml < 0) is_xhtml = 0;
+	if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
+	    dtd = xmlGetIntSubset(cur);
+	    if (dtd != NULL) {
+		is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
+		if (is_xhtml < 0) is_xhtml = 0;
+	    }
 	}
-    }
 #endif
-    if (cur->children != NULL) {
-        xmlNodePtr child = cur->children;
+	if (cur->children != NULL) {
+	    xmlNodePtr child = cur->children;
 
-	while (child != NULL) {
-	    ctxt->level = 0;
+	    while (child != NULL) {
+		ctxt->level = 0;
 #ifdef LIBXML_HTML_ENABLED
-	    if (is_xhtml)
-		xhtmlNodeDumpOutput(ctxt, child);
-	    else
+		if (is_xhtml)
+		    xhtmlNodeDumpOutput(ctxt, child);
+		else
 #endif
-		xmlNodeDumpOutputInternal(ctxt, child);
-	    xmlOutputBufferWrite(buf, 1, "\n");
-	    child = child->next;
+		    xmlNodeDumpOutputInternal(ctxt, child);
+		xmlOutputBufferWrite(buf, 1, "\n");
+		child = child->next;
+	    }
 	}
     }
-    if (ctxt->encoding != NULL)
-        cur->encoding = oldenc;
-    
+
     /*
      * Restore the state of the saving context at the end of the document
      */
-    if ((encoding != NULL) && (oldctxtenc == NULL) &&
-	((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
-	if ((enc != XML_CHAR_ENCODING_UTF8) &&
-	    (enc != XML_CHAR_ENCODING_NONE) &&
-	    (enc != XML_CHAR_ENCODING_ASCII)) {
-	    xmlOutputBufferFlush(buf);
-	    xmlCharEncCloseFunc(buf->encoder);
-	    xmlBufferFree(buf->conv);
-	    buf->encoder = NULL;
-	    buf->conv = NULL;
-	}
+    if ((switched_encoding) && (oldctxtenc == NULL)) {
+	xmlSaveClearEncoding(ctxt);
 	ctxt->escape = oldescape;
 	ctxt->escapeAttr = oldescapeAttr;
     }
+    cur->encoding = oldenc;
     return(0);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]