diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | HTMLtree.c | 7 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | NEWS | 27 | ||||
-rwxr-xr-x | gentest.py | 1 | ||||
-rw-r--r-- | parser.c | 2 | ||||
-rw-r--r-- | python/libxml.c | 147 | ||||
-rw-r--r-- | runxmlconf.c | 8 | ||||
-rw-r--r-- | testapi.c | 4 | ||||
-rw-r--r-- | tree.c | 13 | ||||
-rw-r--r-- | trionan.c | 4 | ||||
-rw-r--r-- | xmlIO.c | 69 | ||||
-rw-r--r-- | xmlsave.c | 279 |
13 files changed, 367 insertions, 214 deletions
@@ -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 @@ -316,6 +316,11 @@ htmlIsBooleanAttr(const xmlChar *name) } #ifdef LIBXML_OUTPUT_ENABLED +/* + * private routine exported from xmlIO.c + */ +xmlOutputBufferPtr +xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder); /************************************************************************ * * * Output error handlers * @@ -566,7 +571,7 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) { 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 de57c465..800a7662 100644 --- a/Makefile.am +++ b/Makefile.am @@ -157,7 +157,7 @@ rebuild_testapi: # 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 @@ runxmlconf_LDADD= $(LDADDS) 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 @@ -15,6 +15,33 @@ ChangeLog.html 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 @@ -260,6 +260,7 @@ extra_post_call = { "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 = [] @@ -8694,7 +8694,7 @@ reparse: "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 95b3cb92..3f2ede7b 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 @@ libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args) 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 @@ libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args) } 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 0529058e..8ef7f747 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 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 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(); @@ -599,9 +599,10 @@ static void des_xmlTextReaderPtr(int no ATTRIBUTE_UNUSED, xmlTextReaderPtr val, #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 @@ test_xmlBufferSetAllocationScheme(void) { 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); @@ -680,7 +680,9 @@ try_complex: */ void xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) { - xmlBufferAllocScheme = scheme; + if ((scheme == XML_BUFFER_ALLOC_EXACT) || + (scheme == XML_BUFFER_ALLOC_DOUBLEIT)) + xmlBufferAllocScheme = scheme; } /** @@ -6736,9 +6738,12 @@ xmlBufferSetAllocationScheme(xmlBufferPtr buf, #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; } /** @@ -129,7 +129,11 @@ static TRIO_CONST char rcsid[] = "@(#)$Id$"; */ #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[] = { @@ -135,6 +135,9 @@ typedef struct _xmlOutputCallback { 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 @@ xmlIOHTTPOpenW(const char *post_uri, int compression) { /* 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 @@ xmlIOHTTPOpenW(const char *post_uri, int compression) return (ctxt); } #endif /* LIBXML_OUTPUT_ENABLED */ - + #ifdef LIBXML_OUTPUT_ENABLED /** * xmlIOHTTPDfltOpenW @@ -2275,8 +2278,57 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) { 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 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) { return(ret); } + #endif /* LIBXML_OUTPUT_ENABLED */ /** @@ -2502,7 +2555,7 @@ __xmlOutputBufferCreateFilename(const char *URI, 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 @@ __xmlOutputBufferCreateFilename(const char *URI, 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 @@ __xmlOutputBufferCreateFilename(const char *URI, /* * 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 @@ xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) { if (file == NULL) return(NULL); - ret = xmlAllocOutputBuffer(encoder); + ret = xmlAllocOutputBufferInternal(encoder); if (ret != NULL) { ret->context = file; ret->writecallback = xmlFileWrite; @@ -2814,7 +2867,7 @@ xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) { 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 @@ xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite, if (iowrite == NULL) return(NULL); - ret = xmlAllocOutputBuffer(encoder); + ret = xmlAllocOutputBufferInternal(encoder); if (ret != NULL) { ret->context = (void *) ioctx; ret->writecallback = iowrite; @@ -457,6 +457,40 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr) * * ************************************************************************/ +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 @@ xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { } } +#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 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { 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 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { 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 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { 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); } |