Index: third_party/libxml/HTMLtree.c |
diff --git a/third_party/libxml/HTMLtree.c b/third_party/libxml/HTMLtree.c |
index e79d1180f3d4c5936444b0b0119e8d909bf4af81..b5085836b900af69b90eab1d68bd71ed3ba55559 100644 |
--- a/third_party/libxml/HTMLtree.c |
+++ b/third_party/libxml/HTMLtree.c |
@@ -160,14 +160,18 @@ found_content: |
*/ |
int |
htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) { |
- htmlNodePtr cur, meta; |
- const xmlChar *content; |
+ htmlNodePtr cur, meta = NULL, head = NULL; |
+ const xmlChar *content = NULL; |
char newcontent[100]; |
if (doc == NULL) |
return(-1); |
+ /* html isn't a real encoding it's just libxml2 way to get entities */ |
+ if (!xmlStrcasecmp(encoding, BAD_CAST "html")) |
+ return(-1); |
+ |
if (encoding != NULL) { |
snprintf(newcontent, sizeof(newcontent), "text/html; charset=%s", |
(char *)encoding); |
@@ -201,39 +205,24 @@ htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) { |
if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { |
if (xmlStrcasecmp(cur->name, BAD_CAST"head") == 0) |
break; |
- if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) |
+ if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) { |
+ head = cur->parent; |
goto found_meta; |
+ } |
} |
cur = cur->next; |
} |
if (cur == NULL) |
return(-1); |
found_head: |
- if (cur->children == NULL) { |
- if (encoding == NULL) |
- return(0); |
- meta = xmlNewDocNode(doc, NULL, BAD_CAST"meta", NULL); |
- xmlAddChild(cur, meta); |
- xmlNewProp(meta, BAD_CAST"http-equiv", BAD_CAST"Content-Type"); |
- xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent); |
- return(0); |
- } |
+ head = cur; |
+ if (cur->children == NULL) |
+ goto create; |
cur = cur->children; |
found_meta: |
- if (encoding != NULL) { |
- /* |
- * Create a new Meta element with the right attributes |
- */ |
- |
- meta = xmlNewDocNode(doc, NULL, BAD_CAST"meta", NULL); |
- xmlAddPrevSibling(cur, meta); |
- xmlNewProp(meta, BAD_CAST"http-equiv", BAD_CAST"Content-Type"); |
- xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent); |
- } |
- |
/* |
- * Search and destroy all the remaining the meta elements carrying |
+ * Search and update all the remaining the meta elements carrying |
* encoding informations |
*/ |
while (cur != NULL) { |
@@ -253,11 +242,11 @@ found_meta: |
if ((!xmlStrcasecmp(attr->name, BAD_CAST"http-equiv")) |
&& (!xmlStrcasecmp(value, BAD_CAST"Content-Type"))) |
http = 1; |
- else |
+ else |
{ |
if ((value != NULL) && |
- (!xmlStrcasecmp(attr->name, BAD_CAST"content"))) |
- content = value; |
+ (!xmlStrcasecmp(attr->name, BAD_CAST"content"))) |
+ content = value; |
} |
if ((http != 0) && (content != NULL)) |
break; |
@@ -266,16 +255,36 @@ found_meta: |
} |
if ((http != 0) && (content != NULL)) { |
meta = cur; |
- cur = cur->next; |
- xmlUnlinkNode(meta); |
- xmlFreeNode(meta); |
- continue; |
+ break; |
} |
} |
} |
cur = cur->next; |
} |
+create: |
+ if (meta == NULL) { |
+ if ((encoding != NULL) && (head != NULL)) { |
+ /* |
+ * Create a new Meta element with the right attributes |
+ */ |
+ |
+ meta = xmlNewDocNode(doc, NULL, BAD_CAST"meta", NULL); |
+ if (head->children == NULL) |
+ xmlAddChild(head, meta); |
+ else |
+ xmlAddPrevSibling(head->children, meta); |
+ xmlNewProp(meta, BAD_CAST"http-equiv", BAD_CAST"Content-Type"); |
+ xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent); |
+ } |
+ } else { |
+ /* change the document only if there is a real encoding change */ |
+ if (xmlStrcasestr(content, encoding) == NULL) { |
+ xmlSetProp(meta, BAD_CAST"content", BAD_CAST newcontent); |
+ } |
+ } |
+ |
+ |
return(0); |
} |
@@ -316,6 +325,11 @@ htmlIsBooleanAttr(const xmlChar *name) |
} |
#ifdef LIBXML_OUTPUT_ENABLED |
+/* |
+ * private routine exported from xmlIO.c |
+ */ |
+xmlOutputBufferPtr |
+xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder); |
/************************************************************************ |
* * |
* Output error handlers * |
@@ -566,7 +580,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; |
@@ -1150,7 +1164,7 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur, |
if ((cur == NULL) || (filename == NULL)) |
return(-1); |
- |
+ |
xmlInitParser(); |
if (encoding != NULL) { |
@@ -1168,8 +1182,8 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur, |
handler = xmlFindCharEncodingHandler(encoding); |
if (handler == NULL) |
return(-1); |
- htmlSetMetaEncoding(cur, (const xmlChar *) encoding); |
} |
+ htmlSetMetaEncoding(cur, (const xmlChar *) encoding); |
} else { |
htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8"); |
} |