Borland C fix from Moritz Both regenerate, workaround a problem for buffer
* 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
svn path=/trunk/; revision=3790
diff --git a/ChangeLog b/ChangeLog
index dd3590a..d6f3a73 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Mon Sep 1 15:02:05 CEST 2008 Daniel Veillard <daniel@veillard.com>
+
+ * 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
+
Sat Aug 30 16:58:40 CEST 2008 Daniel Veillard <daniel@veillard.com>
* configure.in, doc/*: preparing 2.7.0 release
diff --git a/HTMLtree.c b/HTMLtree.c
index e79d118..37999f7 100644
--- a/HTMLtree.c
+++ b/HTMLtree.c
@@ -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;
diff --git a/Makefile.am b/Makefile.am
index de57c46..800a766 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
diff --git a/NEWS b/NEWS
index 2d6a794..6f0ece4 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/gentest.py b/gentest.py
index 17c9f59..f178620 100755
--- a/gentest.py
+++ b/gentest.py
@@ -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 = []
diff --git a/parser.c b/parser.c
index 42b2852..9876a46 100644
--- a/parser.c
+++ b/parser.c
@@ -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);
diff --git a/python/libxml.c b/python/libxml.c
index 95b3cb9..3f2ede7 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -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);
}
diff --git a/runxmlconf.c b/runxmlconf.c
index 0529058..8ef7f74 100644
--- a/runxmlconf.c
+++ b/runxmlconf.c
@@ -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();
diff --git a/testapi.c b/testapi.c
index 037f7e4..6f85910 100644
--- a/testapi.c
+++ b/testapi.c
@@ -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);
diff --git a/tree.c b/tree.c
index f26748e..76926fd 100644
--- a/tree.c
+++ b/tree.c
@@ -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;
}
/**
diff --git a/trionan.c b/trionan.c
index 6eb616a..95baae1 100644
--- a/trionan.c
+++ b/trionan.c
@@ -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[] = {
diff --git a/xmlIO.c b/xmlIO.c
index aa97c44..d4dc364 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -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;
diff --git a/xmlsave.c b/xmlsave.c
index 2a61577..a650722 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -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);
- }
- /*
- * initialize the state, e.g. if outputting a BOM
- */
- xmlCharEncOutFunc(buf->encoder, buf->conv, NULL);
+ switched_encoding = 1;
}
- 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);
+ if (ctxt->options & XML_SAVE_FORMAT)
+ htmlDocContentDumpFormatOutput(buf, cur,
+ (const char *)encoding, 1);
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");
- }
-
-#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;
- }
- }
+ htmlDocContentDumpFormatOutput(buf, cur,
+ (const char *)encoding, 0);
+ if (ctxt->encoding != NULL)
+ cur->encoding = oldenc;
+ return(0);
+#else
+ return(-1);
#endif
- if (cur->children != NULL) {
- xmlNodePtr child = cur->children;
+ } 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;
+ }
+ if (ctxt->escape == xmlEscapeEntities)
+ ctxt->escape = NULL;
+ if (ctxt->escapeAttr == xmlEscapeEntities)
+ ctxt->escapeAttr = NULL;
+ }
- while (child != NULL) {
- ctxt->level = 0;
-#ifdef LIBXML_HTML_ENABLED
- if (is_xhtml)
- xhtmlNodeDumpOutput(ctxt, child);
+
+ /*
+ * 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");
+ }
+
+#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;
+ }
+ }
#endif
- xmlNodeDumpOutputInternal(ctxt, child);
- xmlOutputBufferWrite(buf, 1, "\n");
- child = child->next;
+ if (cur->children != NULL) {
+ xmlNodePtr child = cur->children;
+
+ while (child != NULL) {
+ ctxt->level = 0;
+#ifdef LIBXML_HTML_ENABLED
+ if (is_xhtml)
+ xhtmlNodeDumpOutput(ctxt, child);
+ else
+#endif
+ 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);
}