Index: third_party/libxml/xmlsave.c |
diff --git a/third_party/libxml/xmlsave.c b/third_party/libxml/xmlsave.c |
index 2a61577f697c8e0abd15d5fe2a2de5ab12049e74..aaa5da8af6daa6e045ac83014ec9dc314358a959 100644 |
--- a/third_party/libxml/xmlsave.c |
+++ b/third_party/libxml/xmlsave.c |
@@ -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,19 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { |
xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); |
return; |
} |
+#ifdef LIBXML_HTML_ENABLED |
+ if (ctxt->options & XML_SAVE_XHTML) { |
+ xhtmlNodeDumpOutput(ctxt, cur); |
+ return; |
+ } |
+ if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) && |
+ (cur->doc->type == XML_HTML_DOCUMENT_NODE) && |
+ ((ctxt->options & XML_SAVE_AS_XML) == 0)) || |
+ (ctxt->options & XML_SAVE_AS_HTML)) { |
+ htmlNodeDumpOutputInternal(ctxt, cur); |
+ return; |
+ } |
+#endif |
if (cur->type == XML_DTD_NODE) { |
xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); |
return; |
@@ -835,9 +942,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 +959,125 @@ 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) && |
+ ((ctxt->options & XML_SAVE_AS_XML) == 0) && |
+ ((ctxt->options & XML_SAVE_XHTML) == 0)) || |
+ (ctxt->options & XML_SAVE_AS_HTML)) { |
+#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); |
+ } |
+ 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) || |
+ (ctxt->options & XML_SAVE_AS_XML) || |
+ (ctxt->options & XML_SAVE_XHTML)) { |
+ 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_XHTML) |
+ is_xhtml = 1; |
+ 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); |
} |
@@ -2008,6 +2135,7 @@ xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, |
ctxt.format = format; |
ctxt.encoding = (const xmlChar *) encoding; |
xmlSaveCtxtInit(&ctxt); |
+ ctxt.options |= XML_SAVE_AS_XML; |
#ifdef LIBXML_HTML_ENABLED |
dtd = xmlGetIntSubset(doc); |
@@ -2093,6 +2221,7 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, |
ctxt.format = format; |
ctxt.encoding = (const xmlChar *) txt_encoding; |
xmlSaveCtxtInit(&ctxt); |
+ ctxt.options |= XML_SAVE_AS_XML; |
xmlDocContentDumpOutput(&ctxt, out_doc); |
xmlOutputBufferFlush(out_buff); |
if (out_buff->conv != NULL) { |
@@ -2211,6 +2340,7 @@ xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) { |
ctxt.format = format; |
ctxt.encoding = (const xmlChar *) encoding; |
xmlSaveCtxtInit(&ctxt); |
+ ctxt.options |= XML_SAVE_AS_XML; |
xmlDocContentDumpOutput(&ctxt, cur); |
ret = xmlOutputBufferClose(buf); |
@@ -2260,6 +2390,7 @@ xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) { |
ctxt.format = 0; |
ctxt.encoding = (const xmlChar *) encoding; |
xmlSaveCtxtInit(&ctxt); |
+ ctxt.options |= XML_SAVE_AS_XML; |
xmlDocContentDumpOutput(&ctxt, cur); |
ret = xmlOutputBufferClose(buf); |
return(ret); |
@@ -2299,6 +2430,7 @@ xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, |
ctxt.format = format; |
ctxt.encoding = (const xmlChar *) encoding; |
xmlSaveCtxtInit(&ctxt); |
+ ctxt.options |= XML_SAVE_AS_XML; |
xmlDocContentDumpOutput(&ctxt, cur); |
ret = xmlOutputBufferClose(buf); |
return (ret); |
@@ -2353,6 +2485,7 @@ xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur, |
ctxt.format = format; |
ctxt.encoding = (const xmlChar *) encoding; |
xmlSaveCtxtInit(&ctxt); |
+ ctxt.options |= XML_SAVE_AS_XML; |
xmlDocContentDumpOutput(&ctxt, cur); |