| 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);
|
|
|
|
|