1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * HTMLtree.c : implementation of access function for an HTML tree.
3*7c568831SAndroid Build Coastguard Worker *
4*7c568831SAndroid Build Coastguard Worker * See Copyright for the status of this software.
5*7c568831SAndroid Build Coastguard Worker *
6*7c568831SAndroid Build Coastguard Worker * [email protected]
7*7c568831SAndroid Build Coastguard Worker */
8*7c568831SAndroid Build Coastguard Worker
9*7c568831SAndroid Build Coastguard Worker
10*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
11*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
12*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_HTML_ENABLED
13*7c568831SAndroid Build Coastguard Worker
14*7c568831SAndroid Build Coastguard Worker #include <string.h> /* for memset() only ! */
15*7c568831SAndroid Build Coastguard Worker #include <ctype.h>
16*7c568831SAndroid Build Coastguard Worker #include <stdlib.h>
17*7c568831SAndroid Build Coastguard Worker
18*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
19*7c568831SAndroid Build Coastguard Worker #include <libxml/HTMLparser.h>
20*7c568831SAndroid Build Coastguard Worker #include <libxml/HTMLtree.h>
21*7c568831SAndroid Build Coastguard Worker #include <libxml/entities.h>
22*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
23*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
24*7c568831SAndroid Build Coastguard Worker #include <libxml/uri.h>
25*7c568831SAndroid Build Coastguard Worker
26*7c568831SAndroid Build Coastguard Worker #include "private/buf.h"
27*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
28*7c568831SAndroid Build Coastguard Worker #include "private/io.h"
29*7c568831SAndroid Build Coastguard Worker #include "private/save.h"
30*7c568831SAndroid Build Coastguard Worker
31*7c568831SAndroid Build Coastguard Worker /************************************************************************
32*7c568831SAndroid Build Coastguard Worker * *
33*7c568831SAndroid Build Coastguard Worker * Getting/Setting encoding meta tags *
34*7c568831SAndroid Build Coastguard Worker * *
35*7c568831SAndroid Build Coastguard Worker ************************************************************************/
36*7c568831SAndroid Build Coastguard Worker
37*7c568831SAndroid Build Coastguard Worker /**
38*7c568831SAndroid Build Coastguard Worker * htmlGetMetaEncoding:
39*7c568831SAndroid Build Coastguard Worker * @doc: the document
40*7c568831SAndroid Build Coastguard Worker *
41*7c568831SAndroid Build Coastguard Worker * Encoding definition lookup in the Meta tags
42*7c568831SAndroid Build Coastguard Worker *
43*7c568831SAndroid Build Coastguard Worker * Returns the current encoding as flagged in the HTML source
44*7c568831SAndroid Build Coastguard Worker */
45*7c568831SAndroid Build Coastguard Worker const xmlChar *
htmlGetMetaEncoding(htmlDocPtr doc)46*7c568831SAndroid Build Coastguard Worker htmlGetMetaEncoding(htmlDocPtr doc) {
47*7c568831SAndroid Build Coastguard Worker htmlNodePtr cur;
48*7c568831SAndroid Build Coastguard Worker const xmlChar *content;
49*7c568831SAndroid Build Coastguard Worker const xmlChar *encoding;
50*7c568831SAndroid Build Coastguard Worker
51*7c568831SAndroid Build Coastguard Worker if (doc == NULL)
52*7c568831SAndroid Build Coastguard Worker return(NULL);
53*7c568831SAndroid Build Coastguard Worker cur = doc->children;
54*7c568831SAndroid Build Coastguard Worker
55*7c568831SAndroid Build Coastguard Worker /*
56*7c568831SAndroid Build Coastguard Worker * Search the html
57*7c568831SAndroid Build Coastguard Worker */
58*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
59*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
60*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cur->name, BAD_CAST"html"))
61*7c568831SAndroid Build Coastguard Worker break;
62*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cur->name, BAD_CAST"head"))
63*7c568831SAndroid Build Coastguard Worker goto found_head;
64*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cur->name, BAD_CAST"meta"))
65*7c568831SAndroid Build Coastguard Worker goto found_meta;
66*7c568831SAndroid Build Coastguard Worker }
67*7c568831SAndroid Build Coastguard Worker cur = cur->next;
68*7c568831SAndroid Build Coastguard Worker }
69*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
70*7c568831SAndroid Build Coastguard Worker return(NULL);
71*7c568831SAndroid Build Coastguard Worker cur = cur->children;
72*7c568831SAndroid Build Coastguard Worker
73*7c568831SAndroid Build Coastguard Worker /*
74*7c568831SAndroid Build Coastguard Worker * Search the head
75*7c568831SAndroid Build Coastguard Worker */
76*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
77*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
78*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cur->name, BAD_CAST"head"))
79*7c568831SAndroid Build Coastguard Worker break;
80*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cur->name, BAD_CAST"meta"))
81*7c568831SAndroid Build Coastguard Worker goto found_meta;
82*7c568831SAndroid Build Coastguard Worker }
83*7c568831SAndroid Build Coastguard Worker cur = cur->next;
84*7c568831SAndroid Build Coastguard Worker }
85*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
86*7c568831SAndroid Build Coastguard Worker return(NULL);
87*7c568831SAndroid Build Coastguard Worker found_head:
88*7c568831SAndroid Build Coastguard Worker cur = cur->children;
89*7c568831SAndroid Build Coastguard Worker
90*7c568831SAndroid Build Coastguard Worker /*
91*7c568831SAndroid Build Coastguard Worker * Search the meta elements
92*7c568831SAndroid Build Coastguard Worker */
93*7c568831SAndroid Build Coastguard Worker found_meta:
94*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
95*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
96*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(cur->name, BAD_CAST"meta")) {
97*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr = cur->properties;
98*7c568831SAndroid Build Coastguard Worker int http;
99*7c568831SAndroid Build Coastguard Worker const xmlChar *value;
100*7c568831SAndroid Build Coastguard Worker
101*7c568831SAndroid Build Coastguard Worker content = NULL;
102*7c568831SAndroid Build Coastguard Worker http = 0;
103*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
104*7c568831SAndroid Build Coastguard Worker if ((attr->children != NULL) &&
105*7c568831SAndroid Build Coastguard Worker (attr->children->type == XML_TEXT_NODE) &&
106*7c568831SAndroid Build Coastguard Worker (attr->children->next == NULL)) {
107*7c568831SAndroid Build Coastguard Worker value = attr->children->content;
108*7c568831SAndroid Build Coastguard Worker if ((!xmlStrcasecmp(attr->name, BAD_CAST"http-equiv"))
109*7c568831SAndroid Build Coastguard Worker && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
110*7c568831SAndroid Build Coastguard Worker http = 1;
111*7c568831SAndroid Build Coastguard Worker else if ((value != NULL)
112*7c568831SAndroid Build Coastguard Worker && (!xmlStrcasecmp(attr->name, BAD_CAST"content")))
113*7c568831SAndroid Build Coastguard Worker content = value;
114*7c568831SAndroid Build Coastguard Worker if ((http != 0) && (content != NULL))
115*7c568831SAndroid Build Coastguard Worker goto found_content;
116*7c568831SAndroid Build Coastguard Worker }
117*7c568831SAndroid Build Coastguard Worker attr = attr->next;
118*7c568831SAndroid Build Coastguard Worker }
119*7c568831SAndroid Build Coastguard Worker }
120*7c568831SAndroid Build Coastguard Worker }
121*7c568831SAndroid Build Coastguard Worker cur = cur->next;
122*7c568831SAndroid Build Coastguard Worker }
123*7c568831SAndroid Build Coastguard Worker return(NULL);
124*7c568831SAndroid Build Coastguard Worker
125*7c568831SAndroid Build Coastguard Worker found_content:
126*7c568831SAndroid Build Coastguard Worker encoding = xmlStrstr(content, BAD_CAST"charset=");
127*7c568831SAndroid Build Coastguard Worker if (encoding == NULL)
128*7c568831SAndroid Build Coastguard Worker encoding = xmlStrstr(content, BAD_CAST"Charset=");
129*7c568831SAndroid Build Coastguard Worker if (encoding == NULL)
130*7c568831SAndroid Build Coastguard Worker encoding = xmlStrstr(content, BAD_CAST"CHARSET=");
131*7c568831SAndroid Build Coastguard Worker if (encoding != NULL) {
132*7c568831SAndroid Build Coastguard Worker encoding += 8;
133*7c568831SAndroid Build Coastguard Worker } else {
134*7c568831SAndroid Build Coastguard Worker encoding = xmlStrstr(content, BAD_CAST"charset =");
135*7c568831SAndroid Build Coastguard Worker if (encoding == NULL)
136*7c568831SAndroid Build Coastguard Worker encoding = xmlStrstr(content, BAD_CAST"Charset =");
137*7c568831SAndroid Build Coastguard Worker if (encoding == NULL)
138*7c568831SAndroid Build Coastguard Worker encoding = xmlStrstr(content, BAD_CAST"CHARSET =");
139*7c568831SAndroid Build Coastguard Worker if (encoding != NULL)
140*7c568831SAndroid Build Coastguard Worker encoding += 9;
141*7c568831SAndroid Build Coastguard Worker }
142*7c568831SAndroid Build Coastguard Worker if (encoding != NULL) {
143*7c568831SAndroid Build Coastguard Worker while ((*encoding == ' ') || (*encoding == '\t')) encoding++;
144*7c568831SAndroid Build Coastguard Worker }
145*7c568831SAndroid Build Coastguard Worker return(encoding);
146*7c568831SAndroid Build Coastguard Worker }
147*7c568831SAndroid Build Coastguard Worker
148*7c568831SAndroid Build Coastguard Worker /**
149*7c568831SAndroid Build Coastguard Worker * htmlSetMetaEncoding:
150*7c568831SAndroid Build Coastguard Worker * @doc: the document
151*7c568831SAndroid Build Coastguard Worker * @encoding: the encoding string
152*7c568831SAndroid Build Coastguard Worker *
153*7c568831SAndroid Build Coastguard Worker * Sets the current encoding in the Meta tags
154*7c568831SAndroid Build Coastguard Worker * NOTE: this will not change the document content encoding, just
155*7c568831SAndroid Build Coastguard Worker * the META flag associated.
156*7c568831SAndroid Build Coastguard Worker *
157*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success and -1 in case of error
158*7c568831SAndroid Build Coastguard Worker */
159*7c568831SAndroid Build Coastguard Worker int
htmlSetMetaEncoding(htmlDocPtr doc,const xmlChar * encoding)160*7c568831SAndroid Build Coastguard Worker htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) {
161*7c568831SAndroid Build Coastguard Worker htmlNodePtr cur, meta = NULL, head = NULL;
162*7c568831SAndroid Build Coastguard Worker const xmlChar *content = NULL;
163*7c568831SAndroid Build Coastguard Worker char newcontent[100];
164*7c568831SAndroid Build Coastguard Worker
165*7c568831SAndroid Build Coastguard Worker newcontent[0] = 0;
166*7c568831SAndroid Build Coastguard Worker
167*7c568831SAndroid Build Coastguard Worker if (doc == NULL)
168*7c568831SAndroid Build Coastguard Worker return(-1);
169*7c568831SAndroid Build Coastguard Worker
170*7c568831SAndroid Build Coastguard Worker /* html isn't a real encoding it's just libxml2 way to get entities */
171*7c568831SAndroid Build Coastguard Worker if (!xmlStrcasecmp(encoding, BAD_CAST "html"))
172*7c568831SAndroid Build Coastguard Worker return(-1);
173*7c568831SAndroid Build Coastguard Worker
174*7c568831SAndroid Build Coastguard Worker if (encoding != NULL) {
175*7c568831SAndroid Build Coastguard Worker snprintf(newcontent, sizeof(newcontent), "text/html; charset=%s",
176*7c568831SAndroid Build Coastguard Worker (char *)encoding);
177*7c568831SAndroid Build Coastguard Worker newcontent[sizeof(newcontent) - 1] = 0;
178*7c568831SAndroid Build Coastguard Worker }
179*7c568831SAndroid Build Coastguard Worker
180*7c568831SAndroid Build Coastguard Worker cur = doc->children;
181*7c568831SAndroid Build Coastguard Worker
182*7c568831SAndroid Build Coastguard Worker /*
183*7c568831SAndroid Build Coastguard Worker * Search the html
184*7c568831SAndroid Build Coastguard Worker */
185*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
186*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
187*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp(cur->name, BAD_CAST"html") == 0)
188*7c568831SAndroid Build Coastguard Worker break;
189*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp(cur->name, BAD_CAST"head") == 0)
190*7c568831SAndroid Build Coastguard Worker goto found_head;
191*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0)
192*7c568831SAndroid Build Coastguard Worker goto found_meta;
193*7c568831SAndroid Build Coastguard Worker }
194*7c568831SAndroid Build Coastguard Worker cur = cur->next;
195*7c568831SAndroid Build Coastguard Worker }
196*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
197*7c568831SAndroid Build Coastguard Worker return(-1);
198*7c568831SAndroid Build Coastguard Worker cur = cur->children;
199*7c568831SAndroid Build Coastguard Worker
200*7c568831SAndroid Build Coastguard Worker /*
201*7c568831SAndroid Build Coastguard Worker * Search the head
202*7c568831SAndroid Build Coastguard Worker */
203*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
204*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
205*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp(cur->name, BAD_CAST"head") == 0)
206*7c568831SAndroid Build Coastguard Worker break;
207*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) {
208*7c568831SAndroid Build Coastguard Worker head = cur->parent;
209*7c568831SAndroid Build Coastguard Worker goto found_meta;
210*7c568831SAndroid Build Coastguard Worker }
211*7c568831SAndroid Build Coastguard Worker }
212*7c568831SAndroid Build Coastguard Worker cur = cur->next;
213*7c568831SAndroid Build Coastguard Worker }
214*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
215*7c568831SAndroid Build Coastguard Worker return(-1);
216*7c568831SAndroid Build Coastguard Worker found_head:
217*7c568831SAndroid Build Coastguard Worker head = cur;
218*7c568831SAndroid Build Coastguard Worker if (cur->children == NULL)
219*7c568831SAndroid Build Coastguard Worker goto create;
220*7c568831SAndroid Build Coastguard Worker cur = cur->children;
221*7c568831SAndroid Build Coastguard Worker
222*7c568831SAndroid Build Coastguard Worker found_meta:
223*7c568831SAndroid Build Coastguard Worker /*
224*7c568831SAndroid Build Coastguard Worker * Search and update all the remaining the meta elements carrying
225*7c568831SAndroid Build Coastguard Worker * encoding information
226*7c568831SAndroid Build Coastguard Worker */
227*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
228*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
229*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) {
230*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr = cur->properties;
231*7c568831SAndroid Build Coastguard Worker int http;
232*7c568831SAndroid Build Coastguard Worker const xmlChar *value;
233*7c568831SAndroid Build Coastguard Worker
234*7c568831SAndroid Build Coastguard Worker content = NULL;
235*7c568831SAndroid Build Coastguard Worker http = 0;
236*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
237*7c568831SAndroid Build Coastguard Worker if ((attr->children != NULL) &&
238*7c568831SAndroid Build Coastguard Worker (attr->children->type == XML_TEXT_NODE) &&
239*7c568831SAndroid Build Coastguard Worker (attr->children->next == NULL)) {
240*7c568831SAndroid Build Coastguard Worker value = attr->children->content;
241*7c568831SAndroid Build Coastguard Worker if ((!xmlStrcasecmp(attr->name, BAD_CAST"http-equiv"))
242*7c568831SAndroid Build Coastguard Worker && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
243*7c568831SAndroid Build Coastguard Worker http = 1;
244*7c568831SAndroid Build Coastguard Worker else
245*7c568831SAndroid Build Coastguard Worker {
246*7c568831SAndroid Build Coastguard Worker if ((value != NULL) &&
247*7c568831SAndroid Build Coastguard Worker (!xmlStrcasecmp(attr->name, BAD_CAST"content")))
248*7c568831SAndroid Build Coastguard Worker content = value;
249*7c568831SAndroid Build Coastguard Worker }
250*7c568831SAndroid Build Coastguard Worker if ((http != 0) && (content != NULL))
251*7c568831SAndroid Build Coastguard Worker break;
252*7c568831SAndroid Build Coastguard Worker }
253*7c568831SAndroid Build Coastguard Worker attr = attr->next;
254*7c568831SAndroid Build Coastguard Worker }
255*7c568831SAndroid Build Coastguard Worker if ((http != 0) && (content != NULL)) {
256*7c568831SAndroid Build Coastguard Worker meta = cur;
257*7c568831SAndroid Build Coastguard Worker break;
258*7c568831SAndroid Build Coastguard Worker }
259*7c568831SAndroid Build Coastguard Worker
260*7c568831SAndroid Build Coastguard Worker }
261*7c568831SAndroid Build Coastguard Worker }
262*7c568831SAndroid Build Coastguard Worker cur = cur->next;
263*7c568831SAndroid Build Coastguard Worker }
264*7c568831SAndroid Build Coastguard Worker create:
265*7c568831SAndroid Build Coastguard Worker if (meta == NULL) {
266*7c568831SAndroid Build Coastguard Worker if ((encoding != NULL) && (head != NULL)) {
267*7c568831SAndroid Build Coastguard Worker /*
268*7c568831SAndroid Build Coastguard Worker * Create a new Meta element with the right attributes
269*7c568831SAndroid Build Coastguard Worker */
270*7c568831SAndroid Build Coastguard Worker
271*7c568831SAndroid Build Coastguard Worker meta = xmlNewDocNode(doc, NULL, BAD_CAST"meta", NULL);
272*7c568831SAndroid Build Coastguard Worker if (head->children == NULL)
273*7c568831SAndroid Build Coastguard Worker xmlAddChild(head, meta);
274*7c568831SAndroid Build Coastguard Worker else
275*7c568831SAndroid Build Coastguard Worker xmlAddPrevSibling(head->children, meta);
276*7c568831SAndroid Build Coastguard Worker xmlNewProp(meta, BAD_CAST"http-equiv", BAD_CAST"Content-Type");
277*7c568831SAndroid Build Coastguard Worker xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent);
278*7c568831SAndroid Build Coastguard Worker }
279*7c568831SAndroid Build Coastguard Worker } else {
280*7c568831SAndroid Build Coastguard Worker /* remove the meta tag if NULL is passed */
281*7c568831SAndroid Build Coastguard Worker if (encoding == NULL) {
282*7c568831SAndroid Build Coastguard Worker xmlUnlinkNode(meta);
283*7c568831SAndroid Build Coastguard Worker xmlFreeNode(meta);
284*7c568831SAndroid Build Coastguard Worker }
285*7c568831SAndroid Build Coastguard Worker /* change the document only if there is a real encoding change */
286*7c568831SAndroid Build Coastguard Worker else if (xmlStrcasestr(content, encoding) == NULL) {
287*7c568831SAndroid Build Coastguard Worker xmlSetProp(meta, BAD_CAST"content", BAD_CAST newcontent);
288*7c568831SAndroid Build Coastguard Worker }
289*7c568831SAndroid Build Coastguard Worker }
290*7c568831SAndroid Build Coastguard Worker
291*7c568831SAndroid Build Coastguard Worker
292*7c568831SAndroid Build Coastguard Worker return(0);
293*7c568831SAndroid Build Coastguard Worker }
294*7c568831SAndroid Build Coastguard Worker
295*7c568831SAndroid Build Coastguard Worker /**
296*7c568831SAndroid Build Coastguard Worker * booleanHTMLAttrs:
297*7c568831SAndroid Build Coastguard Worker *
298*7c568831SAndroid Build Coastguard Worker * These are the HTML attributes which will be output
299*7c568831SAndroid Build Coastguard Worker * in minimized form, i.e. <option selected="selected"> will be
300*7c568831SAndroid Build Coastguard Worker * output as <option selected>, as per XSLT 1.0 16.2 "HTML Output Method"
301*7c568831SAndroid Build Coastguard Worker *
302*7c568831SAndroid Build Coastguard Worker */
303*7c568831SAndroid Build Coastguard Worker static const char* const htmlBooleanAttrs[] = {
304*7c568831SAndroid Build Coastguard Worker "checked", "compact", "declare", "defer", "disabled", "ismap",
305*7c568831SAndroid Build Coastguard Worker "multiple", "nohref", "noresize", "noshade", "nowrap", "readonly",
306*7c568831SAndroid Build Coastguard Worker "selected", NULL
307*7c568831SAndroid Build Coastguard Worker };
308*7c568831SAndroid Build Coastguard Worker
309*7c568831SAndroid Build Coastguard Worker
310*7c568831SAndroid Build Coastguard Worker /**
311*7c568831SAndroid Build Coastguard Worker * htmlIsBooleanAttr:
312*7c568831SAndroid Build Coastguard Worker * @name: the name of the attribute to check
313*7c568831SAndroid Build Coastguard Worker *
314*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
315*7c568831SAndroid Build Coastguard Worker *
316*7c568831SAndroid Build Coastguard Worker * Determine if a given attribute is a boolean attribute.
317*7c568831SAndroid Build Coastguard Worker *
318*7c568831SAndroid Build Coastguard Worker * returns: false if the attribute is not boolean, true otherwise.
319*7c568831SAndroid Build Coastguard Worker */
320*7c568831SAndroid Build Coastguard Worker int
htmlIsBooleanAttr(const xmlChar * name)321*7c568831SAndroid Build Coastguard Worker htmlIsBooleanAttr(const xmlChar *name)
322*7c568831SAndroid Build Coastguard Worker {
323*7c568831SAndroid Build Coastguard Worker int i = 0;
324*7c568831SAndroid Build Coastguard Worker
325*7c568831SAndroid Build Coastguard Worker while (htmlBooleanAttrs[i] != NULL) {
326*7c568831SAndroid Build Coastguard Worker if (xmlStrcasecmp((const xmlChar *)htmlBooleanAttrs[i], name) == 0)
327*7c568831SAndroid Build Coastguard Worker return 1;
328*7c568831SAndroid Build Coastguard Worker i++;
329*7c568831SAndroid Build Coastguard Worker }
330*7c568831SAndroid Build Coastguard Worker return 0;
331*7c568831SAndroid Build Coastguard Worker }
332*7c568831SAndroid Build Coastguard Worker
333*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
334*7c568831SAndroid Build Coastguard Worker /************************************************************************
335*7c568831SAndroid Build Coastguard Worker * *
336*7c568831SAndroid Build Coastguard Worker * Output error handlers *
337*7c568831SAndroid Build Coastguard Worker * *
338*7c568831SAndroid Build Coastguard Worker ************************************************************************/
339*7c568831SAndroid Build Coastguard Worker
340*7c568831SAndroid Build Coastguard Worker /**
341*7c568831SAndroid Build Coastguard Worker * htmlSaveErr:
342*7c568831SAndroid Build Coastguard Worker * @code: the error number
343*7c568831SAndroid Build Coastguard Worker * @node: the location of the error.
344*7c568831SAndroid Build Coastguard Worker * @extra: extra information
345*7c568831SAndroid Build Coastguard Worker *
346*7c568831SAndroid Build Coastguard Worker * Handle an out of memory condition
347*7c568831SAndroid Build Coastguard Worker */
348*7c568831SAndroid Build Coastguard Worker static void
htmlSaveErr(int code,xmlNodePtr node,const char * extra)349*7c568831SAndroid Build Coastguard Worker htmlSaveErr(int code, xmlNodePtr node, const char *extra)
350*7c568831SAndroid Build Coastguard Worker {
351*7c568831SAndroid Build Coastguard Worker const char *msg = NULL;
352*7c568831SAndroid Build Coastguard Worker int res;
353*7c568831SAndroid Build Coastguard Worker
354*7c568831SAndroid Build Coastguard Worker switch(code) {
355*7c568831SAndroid Build Coastguard Worker case XML_SAVE_NOT_UTF8:
356*7c568831SAndroid Build Coastguard Worker msg = "string is not in UTF-8\n";
357*7c568831SAndroid Build Coastguard Worker break;
358*7c568831SAndroid Build Coastguard Worker case XML_SAVE_CHAR_INVALID:
359*7c568831SAndroid Build Coastguard Worker msg = "invalid character value\n";
360*7c568831SAndroid Build Coastguard Worker break;
361*7c568831SAndroid Build Coastguard Worker case XML_SAVE_UNKNOWN_ENCODING:
362*7c568831SAndroid Build Coastguard Worker msg = "unknown encoding %s\n";
363*7c568831SAndroid Build Coastguard Worker break;
364*7c568831SAndroid Build Coastguard Worker case XML_SAVE_NO_DOCTYPE:
365*7c568831SAndroid Build Coastguard Worker msg = "HTML has no DOCTYPE\n";
366*7c568831SAndroid Build Coastguard Worker break;
367*7c568831SAndroid Build Coastguard Worker default:
368*7c568831SAndroid Build Coastguard Worker msg = "unexpected error number\n";
369*7c568831SAndroid Build Coastguard Worker }
370*7c568831SAndroid Build Coastguard Worker
371*7c568831SAndroid Build Coastguard Worker res = xmlRaiseError(NULL, NULL, NULL, NULL, node,
372*7c568831SAndroid Build Coastguard Worker XML_FROM_OUTPUT, code, XML_ERR_ERROR, NULL, 0,
373*7c568831SAndroid Build Coastguard Worker extra, NULL, NULL, 0, 0,
374*7c568831SAndroid Build Coastguard Worker msg, extra);
375*7c568831SAndroid Build Coastguard Worker if (res < 0)
376*7c568831SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_OUTPUT, NULL);
377*7c568831SAndroid Build Coastguard Worker }
378*7c568831SAndroid Build Coastguard Worker
379*7c568831SAndroid Build Coastguard Worker /************************************************************************
380*7c568831SAndroid Build Coastguard Worker * *
381*7c568831SAndroid Build Coastguard Worker * Dumping HTML tree content to a simple buffer *
382*7c568831SAndroid Build Coastguard Worker * *
383*7c568831SAndroid Build Coastguard Worker ************************************************************************/
384*7c568831SAndroid Build Coastguard Worker
385*7c568831SAndroid Build Coastguard Worker static xmlCharEncodingHandler *
htmlFindOutputEncoder(const char * encoding)386*7c568831SAndroid Build Coastguard Worker htmlFindOutputEncoder(const char *encoding) {
387*7c568831SAndroid Build Coastguard Worker xmlCharEncodingHandler *handler = NULL;
388*7c568831SAndroid Build Coastguard Worker
389*7c568831SAndroid Build Coastguard Worker if (encoding != NULL) {
390*7c568831SAndroid Build Coastguard Worker int res;
391*7c568831SAndroid Build Coastguard Worker
392*7c568831SAndroid Build Coastguard Worker res = xmlOpenCharEncodingHandler(encoding, /* output */ 1,
393*7c568831SAndroid Build Coastguard Worker &handler);
394*7c568831SAndroid Build Coastguard Worker if (res != XML_ERR_OK)
395*7c568831SAndroid Build Coastguard Worker htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
396*7c568831SAndroid Build Coastguard Worker } else {
397*7c568831SAndroid Build Coastguard Worker /*
398*7c568831SAndroid Build Coastguard Worker * Fallback to HTML when the encoding is unspecified
399*7c568831SAndroid Build Coastguard Worker */
400*7c568831SAndroid Build Coastguard Worker xmlOpenCharEncodingHandler("HTML", /* output */ 1, &handler);
401*7c568831SAndroid Build Coastguard Worker }
402*7c568831SAndroid Build Coastguard Worker
403*7c568831SAndroid Build Coastguard Worker return(handler);
404*7c568831SAndroid Build Coastguard Worker }
405*7c568831SAndroid Build Coastguard Worker
406*7c568831SAndroid Build Coastguard Worker /**
407*7c568831SAndroid Build Coastguard Worker * htmlBufNodeDumpFormat:
408*7c568831SAndroid Build Coastguard Worker * @buf: the xmlBufPtr output
409*7c568831SAndroid Build Coastguard Worker * @doc: the document
410*7c568831SAndroid Build Coastguard Worker * @cur: the current node
411*7c568831SAndroid Build Coastguard Worker * @format: should formatting spaces been added
412*7c568831SAndroid Build Coastguard Worker *
413*7c568831SAndroid Build Coastguard Worker * Dump an HTML node, recursive behaviour,children are printed too.
414*7c568831SAndroid Build Coastguard Worker *
415*7c568831SAndroid Build Coastguard Worker * Returns the number of byte written or -1 in case of error
416*7c568831SAndroid Build Coastguard Worker */
417*7c568831SAndroid Build Coastguard Worker static size_t
htmlBufNodeDumpFormat(xmlBufPtr buf,xmlDocPtr doc,xmlNodePtr cur,int format)418*7c568831SAndroid Build Coastguard Worker htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur,
419*7c568831SAndroid Build Coastguard Worker int format) {
420*7c568831SAndroid Build Coastguard Worker size_t use;
421*7c568831SAndroid Build Coastguard Worker size_t ret;
422*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr outbuf;
423*7c568831SAndroid Build Coastguard Worker
424*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
425*7c568831SAndroid Build Coastguard Worker return ((size_t) -1);
426*7c568831SAndroid Build Coastguard Worker }
427*7c568831SAndroid Build Coastguard Worker if (buf == NULL) {
428*7c568831SAndroid Build Coastguard Worker return ((size_t) -1);
429*7c568831SAndroid Build Coastguard Worker }
430*7c568831SAndroid Build Coastguard Worker outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
431*7c568831SAndroid Build Coastguard Worker if (outbuf == NULL)
432*7c568831SAndroid Build Coastguard Worker return ((size_t) -1);
433*7c568831SAndroid Build Coastguard Worker memset(outbuf, 0, sizeof(xmlOutputBuffer));
434*7c568831SAndroid Build Coastguard Worker outbuf->buffer = buf;
435*7c568831SAndroid Build Coastguard Worker outbuf->encoder = NULL;
436*7c568831SAndroid Build Coastguard Worker outbuf->writecallback = NULL;
437*7c568831SAndroid Build Coastguard Worker outbuf->closecallback = NULL;
438*7c568831SAndroid Build Coastguard Worker outbuf->context = NULL;
439*7c568831SAndroid Build Coastguard Worker outbuf->written = 0;
440*7c568831SAndroid Build Coastguard Worker
441*7c568831SAndroid Build Coastguard Worker use = xmlBufUse(buf);
442*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(outbuf, doc, cur, NULL, format);
443*7c568831SAndroid Build Coastguard Worker if (outbuf->error)
444*7c568831SAndroid Build Coastguard Worker ret = (size_t) -1;
445*7c568831SAndroid Build Coastguard Worker else
446*7c568831SAndroid Build Coastguard Worker ret = xmlBufUse(buf) - use;
447*7c568831SAndroid Build Coastguard Worker xmlFree(outbuf);
448*7c568831SAndroid Build Coastguard Worker return (ret);
449*7c568831SAndroid Build Coastguard Worker }
450*7c568831SAndroid Build Coastguard Worker
451*7c568831SAndroid Build Coastguard Worker /**
452*7c568831SAndroid Build Coastguard Worker * htmlNodeDump:
453*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
454*7c568831SAndroid Build Coastguard Worker * @doc: the document
455*7c568831SAndroid Build Coastguard Worker * @cur: the current node
456*7c568831SAndroid Build Coastguard Worker *
457*7c568831SAndroid Build Coastguard Worker * Dump an HTML node, recursive behaviour,children are printed too,
458*7c568831SAndroid Build Coastguard Worker * and formatting returns are added.
459*7c568831SAndroid Build Coastguard Worker *
460*7c568831SAndroid Build Coastguard Worker * Returns the number of byte written or -1 in case of error
461*7c568831SAndroid Build Coastguard Worker */
462*7c568831SAndroid Build Coastguard Worker int
htmlNodeDump(xmlBufferPtr buf,xmlDocPtr doc,xmlNodePtr cur)463*7c568831SAndroid Build Coastguard Worker htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) {
464*7c568831SAndroid Build Coastguard Worker xmlBufPtr buffer;
465*7c568831SAndroid Build Coastguard Worker size_t ret1;
466*7c568831SAndroid Build Coastguard Worker int ret2;
467*7c568831SAndroid Build Coastguard Worker
468*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (cur == NULL))
469*7c568831SAndroid Build Coastguard Worker return(-1);
470*7c568831SAndroid Build Coastguard Worker
471*7c568831SAndroid Build Coastguard Worker xmlInitParser();
472*7c568831SAndroid Build Coastguard Worker buffer = xmlBufFromBuffer(buf);
473*7c568831SAndroid Build Coastguard Worker if (buffer == NULL)
474*7c568831SAndroid Build Coastguard Worker return(-1);
475*7c568831SAndroid Build Coastguard Worker
476*7c568831SAndroid Build Coastguard Worker ret1 = htmlBufNodeDumpFormat(buffer, doc, cur, 1);
477*7c568831SAndroid Build Coastguard Worker
478*7c568831SAndroid Build Coastguard Worker ret2 = xmlBufBackToBuffer(buffer, buf);
479*7c568831SAndroid Build Coastguard Worker
480*7c568831SAndroid Build Coastguard Worker if ((ret1 == (size_t) -1) || (ret2 < 0))
481*7c568831SAndroid Build Coastguard Worker return(-1);
482*7c568831SAndroid Build Coastguard Worker return(ret1 > INT_MAX ? INT_MAX : ret1);
483*7c568831SAndroid Build Coastguard Worker }
484*7c568831SAndroid Build Coastguard Worker
485*7c568831SAndroid Build Coastguard Worker /**
486*7c568831SAndroid Build Coastguard Worker * htmlNodeDumpFileFormat:
487*7c568831SAndroid Build Coastguard Worker * @out: the FILE pointer
488*7c568831SAndroid Build Coastguard Worker * @doc: the document
489*7c568831SAndroid Build Coastguard Worker * @cur: the current node
490*7c568831SAndroid Build Coastguard Worker * @encoding: the document encoding
491*7c568831SAndroid Build Coastguard Worker * @format: should formatting spaces been added
492*7c568831SAndroid Build Coastguard Worker *
493*7c568831SAndroid Build Coastguard Worker * Dump an HTML node, recursive behaviour,children are printed too.
494*7c568831SAndroid Build Coastguard Worker *
495*7c568831SAndroid Build Coastguard Worker * TODO: if encoding == NULL try to save in the doc encoding
496*7c568831SAndroid Build Coastguard Worker *
497*7c568831SAndroid Build Coastguard Worker * returns: the number of byte written or -1 in case of failure.
498*7c568831SAndroid Build Coastguard Worker */
499*7c568831SAndroid Build Coastguard Worker int
htmlNodeDumpFileFormat(FILE * out,xmlDocPtr doc,xmlNodePtr cur,const char * encoding,int format)500*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
501*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur, const char *encoding, int format) {
502*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
503*7c568831SAndroid Build Coastguard Worker xmlCharEncodingHandlerPtr handler;
504*7c568831SAndroid Build Coastguard Worker int ret;
505*7c568831SAndroid Build Coastguard Worker
506*7c568831SAndroid Build Coastguard Worker xmlInitParser();
507*7c568831SAndroid Build Coastguard Worker
508*7c568831SAndroid Build Coastguard Worker /*
509*7c568831SAndroid Build Coastguard Worker * save the content to a temp buffer.
510*7c568831SAndroid Build Coastguard Worker */
511*7c568831SAndroid Build Coastguard Worker handler = htmlFindOutputEncoder(encoding);
512*7c568831SAndroid Build Coastguard Worker buf = xmlOutputBufferCreateFile(out, handler);
513*7c568831SAndroid Build Coastguard Worker if (buf == NULL)
514*7c568831SAndroid Build Coastguard Worker return(0);
515*7c568831SAndroid Build Coastguard Worker
516*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(buf, doc, cur, NULL, format);
517*7c568831SAndroid Build Coastguard Worker
518*7c568831SAndroid Build Coastguard Worker ret = xmlOutputBufferClose(buf);
519*7c568831SAndroid Build Coastguard Worker return(ret);
520*7c568831SAndroid Build Coastguard Worker }
521*7c568831SAndroid Build Coastguard Worker
522*7c568831SAndroid Build Coastguard Worker /**
523*7c568831SAndroid Build Coastguard Worker * htmlNodeDumpFile:
524*7c568831SAndroid Build Coastguard Worker * @out: the FILE pointer
525*7c568831SAndroid Build Coastguard Worker * @doc: the document
526*7c568831SAndroid Build Coastguard Worker * @cur: the current node
527*7c568831SAndroid Build Coastguard Worker *
528*7c568831SAndroid Build Coastguard Worker * Dump an HTML node, recursive behaviour,children are printed too,
529*7c568831SAndroid Build Coastguard Worker * and formatting returns are added.
530*7c568831SAndroid Build Coastguard Worker */
531*7c568831SAndroid Build Coastguard Worker void
htmlNodeDumpFile(FILE * out,xmlDocPtr doc,xmlNodePtr cur)532*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFile(FILE *out, xmlDocPtr doc, xmlNodePtr cur) {
533*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFileFormat(out, doc, cur, NULL, 1);
534*7c568831SAndroid Build Coastguard Worker }
535*7c568831SAndroid Build Coastguard Worker
536*7c568831SAndroid Build Coastguard Worker /**
537*7c568831SAndroid Build Coastguard Worker * htmlDocDumpMemoryFormat:
538*7c568831SAndroid Build Coastguard Worker * @cur: the document
539*7c568831SAndroid Build Coastguard Worker * @mem: OUT: the memory pointer
540*7c568831SAndroid Build Coastguard Worker * @size: OUT: the memory length
541*7c568831SAndroid Build Coastguard Worker * @format: should formatting spaces been added
542*7c568831SAndroid Build Coastguard Worker *
543*7c568831SAndroid Build Coastguard Worker * Dump an HTML document in memory and return the xmlChar * and it's size.
544*7c568831SAndroid Build Coastguard Worker * It's up to the caller to free the memory.
545*7c568831SAndroid Build Coastguard Worker */
546*7c568831SAndroid Build Coastguard Worker void
htmlDocDumpMemoryFormat(xmlDocPtr cur,xmlChar ** mem,int * size,int format)547*7c568831SAndroid Build Coastguard Worker htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
548*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
549*7c568831SAndroid Build Coastguard Worker xmlCharEncodingHandlerPtr handler = NULL;
550*7c568831SAndroid Build Coastguard Worker const char *encoding;
551*7c568831SAndroid Build Coastguard Worker
552*7c568831SAndroid Build Coastguard Worker xmlInitParser();
553*7c568831SAndroid Build Coastguard Worker
554*7c568831SAndroid Build Coastguard Worker if ((mem == NULL) || (size == NULL))
555*7c568831SAndroid Build Coastguard Worker return;
556*7c568831SAndroid Build Coastguard Worker *mem = NULL;
557*7c568831SAndroid Build Coastguard Worker *size = 0;
558*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
559*7c568831SAndroid Build Coastguard Worker return;
560*7c568831SAndroid Build Coastguard Worker
561*7c568831SAndroid Build Coastguard Worker encoding = (const char *) htmlGetMetaEncoding(cur);
562*7c568831SAndroid Build Coastguard Worker handler = htmlFindOutputEncoder(encoding);
563*7c568831SAndroid Build Coastguard Worker buf = xmlAllocOutputBuffer(handler);
564*7c568831SAndroid Build Coastguard Worker if (buf == NULL)
565*7c568831SAndroid Build Coastguard Worker return;
566*7c568831SAndroid Build Coastguard Worker
567*7c568831SAndroid Build Coastguard Worker htmlDocContentDumpFormatOutput(buf, cur, NULL, format);
568*7c568831SAndroid Build Coastguard Worker
569*7c568831SAndroid Build Coastguard Worker xmlOutputBufferFlush(buf);
570*7c568831SAndroid Build Coastguard Worker
571*7c568831SAndroid Build Coastguard Worker if (!buf->error) {
572*7c568831SAndroid Build Coastguard Worker if (buf->conv != NULL) {
573*7c568831SAndroid Build Coastguard Worker *size = xmlBufUse(buf->conv);
574*7c568831SAndroid Build Coastguard Worker *mem = xmlStrndup(xmlBufContent(buf->conv), *size);
575*7c568831SAndroid Build Coastguard Worker } else {
576*7c568831SAndroid Build Coastguard Worker *size = xmlBufUse(buf->buffer);
577*7c568831SAndroid Build Coastguard Worker *mem = xmlStrndup(xmlBufContent(buf->buffer), *size);
578*7c568831SAndroid Build Coastguard Worker }
579*7c568831SAndroid Build Coastguard Worker }
580*7c568831SAndroid Build Coastguard Worker
581*7c568831SAndroid Build Coastguard Worker xmlOutputBufferClose(buf);
582*7c568831SAndroid Build Coastguard Worker }
583*7c568831SAndroid Build Coastguard Worker
584*7c568831SAndroid Build Coastguard Worker /**
585*7c568831SAndroid Build Coastguard Worker * htmlDocDumpMemory:
586*7c568831SAndroid Build Coastguard Worker * @cur: the document
587*7c568831SAndroid Build Coastguard Worker * @mem: OUT: the memory pointer
588*7c568831SAndroid Build Coastguard Worker * @size: OUT: the memory length
589*7c568831SAndroid Build Coastguard Worker *
590*7c568831SAndroid Build Coastguard Worker * Dump an HTML document in memory and return the xmlChar * and it's size.
591*7c568831SAndroid Build Coastguard Worker * It's up to the caller to free the memory.
592*7c568831SAndroid Build Coastguard Worker */
593*7c568831SAndroid Build Coastguard Worker void
htmlDocDumpMemory(xmlDocPtr cur,xmlChar ** mem,int * size)594*7c568831SAndroid Build Coastguard Worker htmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
595*7c568831SAndroid Build Coastguard Worker htmlDocDumpMemoryFormat(cur, mem, size, 1);
596*7c568831SAndroid Build Coastguard Worker }
597*7c568831SAndroid Build Coastguard Worker
598*7c568831SAndroid Build Coastguard Worker
599*7c568831SAndroid Build Coastguard Worker /************************************************************************
600*7c568831SAndroid Build Coastguard Worker * *
601*7c568831SAndroid Build Coastguard Worker * Dumping HTML tree content to an I/O output buffer *
602*7c568831SAndroid Build Coastguard Worker * *
603*7c568831SAndroid Build Coastguard Worker ************************************************************************/
604*7c568831SAndroid Build Coastguard Worker
605*7c568831SAndroid Build Coastguard Worker /**
606*7c568831SAndroid Build Coastguard Worker * htmlDtdDumpOutput:
607*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
608*7c568831SAndroid Build Coastguard Worker * @doc: the document
609*7c568831SAndroid Build Coastguard Worker * @encoding: the encoding string
610*7c568831SAndroid Build Coastguard Worker *
611*7c568831SAndroid Build Coastguard Worker * TODO: check whether encoding is needed
612*7c568831SAndroid Build Coastguard Worker *
613*7c568831SAndroid Build Coastguard Worker * Dump the HTML document DTD, if any.
614*7c568831SAndroid Build Coastguard Worker */
615*7c568831SAndroid Build Coastguard Worker static void
htmlDtdDumpOutput(xmlOutputBufferPtr buf,xmlDocPtr doc,const char * encoding ATTRIBUTE_UNUSED)616*7c568831SAndroid Build Coastguard Worker htmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
617*7c568831SAndroid Build Coastguard Worker const char *encoding ATTRIBUTE_UNUSED) {
618*7c568831SAndroid Build Coastguard Worker xmlDtdPtr cur = doc->intSubset;
619*7c568831SAndroid Build Coastguard Worker
620*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
621*7c568831SAndroid Build Coastguard Worker htmlSaveErr(XML_SAVE_NO_DOCTYPE, (xmlNodePtr) doc, NULL);
622*7c568831SAndroid Build Coastguard Worker return;
623*7c568831SAndroid Build Coastguard Worker }
624*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
625*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
626*7c568831SAndroid Build Coastguard Worker if (cur->ExternalID != NULL) {
627*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, " PUBLIC ");
628*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteQuotedString(buf, cur->ExternalID);
629*7c568831SAndroid Build Coastguard Worker if (cur->SystemID != NULL) {
630*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, " ");
631*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteQuotedString(buf, cur->SystemID);
632*7c568831SAndroid Build Coastguard Worker }
633*7c568831SAndroid Build Coastguard Worker } else if (cur->SystemID != NULL &&
634*7c568831SAndroid Build Coastguard Worker xmlStrcmp(cur->SystemID, BAD_CAST "about:legacy-compat")) {
635*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, " SYSTEM ");
636*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteQuotedString(buf, cur->SystemID);
637*7c568831SAndroid Build Coastguard Worker }
638*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">\n");
639*7c568831SAndroid Build Coastguard Worker }
640*7c568831SAndroid Build Coastguard Worker
641*7c568831SAndroid Build Coastguard Worker /**
642*7c568831SAndroid Build Coastguard Worker * htmlAttrDumpOutput:
643*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
644*7c568831SAndroid Build Coastguard Worker * @doc: the document
645*7c568831SAndroid Build Coastguard Worker * @cur: the attribute pointer
646*7c568831SAndroid Build Coastguard Worker *
647*7c568831SAndroid Build Coastguard Worker * Dump an HTML attribute
648*7c568831SAndroid Build Coastguard Worker */
649*7c568831SAndroid Build Coastguard Worker static void
htmlAttrDumpOutput(xmlOutputBufferPtr buf,xmlDocPtr doc,xmlAttrPtr cur)650*7c568831SAndroid Build Coastguard Worker htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
651*7c568831SAndroid Build Coastguard Worker xmlChar *value;
652*7c568831SAndroid Build Coastguard Worker
653*7c568831SAndroid Build Coastguard Worker /*
654*7c568831SAndroid Build Coastguard Worker * The html output method should not escape a & character
655*7c568831SAndroid Build Coastguard Worker * occurring in an attribute value immediately followed by
656*7c568831SAndroid Build Coastguard Worker * a { character (see Section B.7.1 of the HTML 4.0 Recommendation).
657*7c568831SAndroid Build Coastguard Worker * This is implemented in xmlEncodeEntitiesReentrant
658*7c568831SAndroid Build Coastguard Worker */
659*7c568831SAndroid Build Coastguard Worker
660*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
661*7c568831SAndroid Build Coastguard Worker return;
662*7c568831SAndroid Build Coastguard Worker }
663*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, " ");
664*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
665*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
666*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ":");
667*7c568831SAndroid Build Coastguard Worker }
668*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
669*7c568831SAndroid Build Coastguard Worker if ((cur->children != NULL) && (!htmlIsBooleanAttr(cur->name))) {
670*7c568831SAndroid Build Coastguard Worker value = xmlNodeListGetString(doc, cur->children, 0);
671*7c568831SAndroid Build Coastguard Worker if (value) {
672*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "=");
673*7c568831SAndroid Build Coastguard Worker if ((cur->ns == NULL) && (cur->parent != NULL) &&
674*7c568831SAndroid Build Coastguard Worker (cur->parent->ns == NULL) &&
675*7c568831SAndroid Build Coastguard Worker ((!xmlStrcasecmp(cur->name, BAD_CAST "href")) ||
676*7c568831SAndroid Build Coastguard Worker (!xmlStrcasecmp(cur->name, BAD_CAST "action")) ||
677*7c568831SAndroid Build Coastguard Worker (!xmlStrcasecmp(cur->name, BAD_CAST "src")) ||
678*7c568831SAndroid Build Coastguard Worker ((!xmlStrcasecmp(cur->name, BAD_CAST "name")) &&
679*7c568831SAndroid Build Coastguard Worker (!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) {
680*7c568831SAndroid Build Coastguard Worker xmlChar *escaped;
681*7c568831SAndroid Build Coastguard Worker xmlChar *tmp = value;
682*7c568831SAndroid Build Coastguard Worker
683*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*tmp)) tmp++;
684*7c568831SAndroid Build Coastguard Worker
685*7c568831SAndroid Build Coastguard Worker /*
686*7c568831SAndroid Build Coastguard Worker * Angle brackets are technically illegal in URIs, but they're
687*7c568831SAndroid Build Coastguard Worker * used in server side includes, for example. Curly brackets
688*7c568831SAndroid Build Coastguard Worker * are illegal as well and often used in templates.
689*7c568831SAndroid Build Coastguard Worker * Don't escape non-whitespace, printable ASCII chars for
690*7c568831SAndroid Build Coastguard Worker * improved interoperability. Only escape space, control
691*7c568831SAndroid Build Coastguard Worker * and non-ASCII chars.
692*7c568831SAndroid Build Coastguard Worker */
693*7c568831SAndroid Build Coastguard Worker escaped = xmlURIEscapeStr(tmp,
694*7c568831SAndroid Build Coastguard Worker BAD_CAST "\"#$%&+,/:;<=>?@[\\]^`{|}");
695*7c568831SAndroid Build Coastguard Worker if (escaped != NULL) {
696*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteQuotedString(buf, escaped);
697*7c568831SAndroid Build Coastguard Worker xmlFree(escaped);
698*7c568831SAndroid Build Coastguard Worker } else {
699*7c568831SAndroid Build Coastguard Worker buf->error = XML_ERR_NO_MEMORY;
700*7c568831SAndroid Build Coastguard Worker }
701*7c568831SAndroid Build Coastguard Worker } else {
702*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteQuotedString(buf, value);
703*7c568831SAndroid Build Coastguard Worker }
704*7c568831SAndroid Build Coastguard Worker xmlFree(value);
705*7c568831SAndroid Build Coastguard Worker } else {
706*7c568831SAndroid Build Coastguard Worker buf->error = XML_ERR_NO_MEMORY;
707*7c568831SAndroid Build Coastguard Worker }
708*7c568831SAndroid Build Coastguard Worker }
709*7c568831SAndroid Build Coastguard Worker }
710*7c568831SAndroid Build Coastguard Worker
711*7c568831SAndroid Build Coastguard Worker /**
712*7c568831SAndroid Build Coastguard Worker * htmlNodeDumpFormatOutput:
713*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
714*7c568831SAndroid Build Coastguard Worker * @doc: the document
715*7c568831SAndroid Build Coastguard Worker * @cur: the current node
716*7c568831SAndroid Build Coastguard Worker * @encoding: the encoding string (unused)
717*7c568831SAndroid Build Coastguard Worker * @format: should formatting spaces been added
718*7c568831SAndroid Build Coastguard Worker *
719*7c568831SAndroid Build Coastguard Worker * Dump an HTML node, recursive behaviour,children are printed too.
720*7c568831SAndroid Build Coastguard Worker */
721*7c568831SAndroid Build Coastguard Worker void
htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf,xmlDocPtr doc,xmlNodePtr cur,const char * encoding ATTRIBUTE_UNUSED,int format)722*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
723*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur, const char *encoding ATTRIBUTE_UNUSED,
724*7c568831SAndroid Build Coastguard Worker int format) {
725*7c568831SAndroid Build Coastguard Worker xmlNodePtr root, parent;
726*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
727*7c568831SAndroid Build Coastguard Worker const htmlElemDesc * info;
728*7c568831SAndroid Build Coastguard Worker
729*7c568831SAndroid Build Coastguard Worker xmlInitParser();
730*7c568831SAndroid Build Coastguard Worker
731*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (buf == NULL)) {
732*7c568831SAndroid Build Coastguard Worker return;
733*7c568831SAndroid Build Coastguard Worker }
734*7c568831SAndroid Build Coastguard Worker
735*7c568831SAndroid Build Coastguard Worker root = cur;
736*7c568831SAndroid Build Coastguard Worker parent = cur->parent;
737*7c568831SAndroid Build Coastguard Worker while (1) {
738*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
739*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
740*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
741*7c568831SAndroid Build Coastguard Worker if (((xmlDocPtr) cur)->intSubset != NULL) {
742*7c568831SAndroid Build Coastguard Worker htmlDtdDumpOutput(buf, (xmlDocPtr) cur, NULL);
743*7c568831SAndroid Build Coastguard Worker }
744*7c568831SAndroid Build Coastguard Worker if (cur->children != NULL) {
745*7c568831SAndroid Build Coastguard Worker /* Always validate cur->parent when descending. */
746*7c568831SAndroid Build Coastguard Worker if (cur->parent == parent) {
747*7c568831SAndroid Build Coastguard Worker parent = cur;
748*7c568831SAndroid Build Coastguard Worker cur = cur->children;
749*7c568831SAndroid Build Coastguard Worker continue;
750*7c568831SAndroid Build Coastguard Worker }
751*7c568831SAndroid Build Coastguard Worker } else {
752*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "\n");
753*7c568831SAndroid Build Coastguard Worker }
754*7c568831SAndroid Build Coastguard Worker break;
755*7c568831SAndroid Build Coastguard Worker
756*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
757*7c568831SAndroid Build Coastguard Worker /*
758*7c568831SAndroid Build Coastguard Worker * Some users like lxml are known to pass nodes with a corrupted
759*7c568831SAndroid Build Coastguard Worker * tree structure. Fall back to a recursive call to handle this
760*7c568831SAndroid Build Coastguard Worker * case.
761*7c568831SAndroid Build Coastguard Worker */
762*7c568831SAndroid Build Coastguard Worker if ((cur->parent != parent) && (cur->children != NULL)) {
763*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
764*7c568831SAndroid Build Coastguard Worker break;
765*7c568831SAndroid Build Coastguard Worker }
766*7c568831SAndroid Build Coastguard Worker
767*7c568831SAndroid Build Coastguard Worker /*
768*7c568831SAndroid Build Coastguard Worker * Get specific HTML info for that node.
769*7c568831SAndroid Build Coastguard Worker */
770*7c568831SAndroid Build Coastguard Worker if (cur->ns == NULL)
771*7c568831SAndroid Build Coastguard Worker info = htmlTagLookup(cur->name);
772*7c568831SAndroid Build Coastguard Worker else
773*7c568831SAndroid Build Coastguard Worker info = NULL;
774*7c568831SAndroid Build Coastguard Worker
775*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "<");
776*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
777*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
778*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ":");
779*7c568831SAndroid Build Coastguard Worker }
780*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
781*7c568831SAndroid Build Coastguard Worker if (cur->nsDef)
782*7c568831SAndroid Build Coastguard Worker xmlNsListDumpOutput(buf, cur->nsDef);
783*7c568831SAndroid Build Coastguard Worker attr = cur->properties;
784*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
785*7c568831SAndroid Build Coastguard Worker htmlAttrDumpOutput(buf, doc, attr);
786*7c568831SAndroid Build Coastguard Worker attr = attr->next;
787*7c568831SAndroid Build Coastguard Worker }
788*7c568831SAndroid Build Coastguard Worker
789*7c568831SAndroid Build Coastguard Worker if ((info != NULL) && (info->empty)) {
790*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">");
791*7c568831SAndroid Build Coastguard Worker } else if (cur->children == NULL) {
792*7c568831SAndroid Build Coastguard Worker if ((info != NULL) && (info->saveEndTag != 0) &&
793*7c568831SAndroid Build Coastguard Worker (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
794*7c568831SAndroid Build Coastguard Worker (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
795*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">");
796*7c568831SAndroid Build Coastguard Worker } else {
797*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "></");
798*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
799*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf,
800*7c568831SAndroid Build Coastguard Worker (const char *)cur->ns->prefix);
801*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ":");
802*7c568831SAndroid Build Coastguard Worker }
803*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
804*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">");
805*7c568831SAndroid Build Coastguard Worker }
806*7c568831SAndroid Build Coastguard Worker } else {
807*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">");
808*7c568831SAndroid Build Coastguard Worker if ((format) && (info != NULL) && (!info->isinline) &&
809*7c568831SAndroid Build Coastguard Worker (cur->children->type != HTML_TEXT_NODE) &&
810*7c568831SAndroid Build Coastguard Worker (cur->children->type != HTML_ENTITY_REF_NODE) &&
811*7c568831SAndroid Build Coastguard Worker (cur->children != cur->last) &&
812*7c568831SAndroid Build Coastguard Worker (cur->name != NULL) &&
813*7c568831SAndroid Build Coastguard Worker (cur->name[0] != 'p')) /* p, pre, param */
814*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "\n");
815*7c568831SAndroid Build Coastguard Worker parent = cur;
816*7c568831SAndroid Build Coastguard Worker cur = cur->children;
817*7c568831SAndroid Build Coastguard Worker continue;
818*7c568831SAndroid Build Coastguard Worker }
819*7c568831SAndroid Build Coastguard Worker
820*7c568831SAndroid Build Coastguard Worker if ((format) && (cur->next != NULL) &&
821*7c568831SAndroid Build Coastguard Worker (info != NULL) && (!info->isinline)) {
822*7c568831SAndroid Build Coastguard Worker if ((cur->next->type != HTML_TEXT_NODE) &&
823*7c568831SAndroid Build Coastguard Worker (cur->next->type != HTML_ENTITY_REF_NODE) &&
824*7c568831SAndroid Build Coastguard Worker (parent != NULL) &&
825*7c568831SAndroid Build Coastguard Worker (parent->name != NULL) &&
826*7c568831SAndroid Build Coastguard Worker (parent->name[0] != 'p')) /* p, pre, param */
827*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "\n");
828*7c568831SAndroid Build Coastguard Worker }
829*7c568831SAndroid Build Coastguard Worker
830*7c568831SAndroid Build Coastguard Worker break;
831*7c568831SAndroid Build Coastguard Worker
832*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
833*7c568831SAndroid Build Coastguard Worker htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur);
834*7c568831SAndroid Build Coastguard Worker break;
835*7c568831SAndroid Build Coastguard Worker
836*7c568831SAndroid Build Coastguard Worker case HTML_TEXT_NODE:
837*7c568831SAndroid Build Coastguard Worker if (cur->content == NULL)
838*7c568831SAndroid Build Coastguard Worker break;
839*7c568831SAndroid Build Coastguard Worker if (((cur->name == (const xmlChar *)xmlStringText) ||
840*7c568831SAndroid Build Coastguard Worker (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
841*7c568831SAndroid Build Coastguard Worker ((parent == NULL) ||
842*7c568831SAndroid Build Coastguard Worker ((xmlStrcasecmp(parent->name, BAD_CAST "script")) &&
843*7c568831SAndroid Build Coastguard Worker (xmlStrcasecmp(parent->name, BAD_CAST "style"))))) {
844*7c568831SAndroid Build Coastguard Worker xmlChar *buffer;
845*7c568831SAndroid Build Coastguard Worker
846*7c568831SAndroid Build Coastguard Worker buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
847*7c568831SAndroid Build Coastguard Worker if (buffer == NULL) {
848*7c568831SAndroid Build Coastguard Worker buf->error = XML_ERR_NO_MEMORY;
849*7c568831SAndroid Build Coastguard Worker return;
850*7c568831SAndroid Build Coastguard Worker }
851*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)buffer);
852*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
853*7c568831SAndroid Build Coastguard Worker } else {
854*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->content);
855*7c568831SAndroid Build Coastguard Worker }
856*7c568831SAndroid Build Coastguard Worker break;
857*7c568831SAndroid Build Coastguard Worker
858*7c568831SAndroid Build Coastguard Worker case HTML_COMMENT_NODE:
859*7c568831SAndroid Build Coastguard Worker if (cur->content != NULL) {
860*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "<!--");
861*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->content);
862*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "-->");
863*7c568831SAndroid Build Coastguard Worker }
864*7c568831SAndroid Build Coastguard Worker break;
865*7c568831SAndroid Build Coastguard Worker
866*7c568831SAndroid Build Coastguard Worker case HTML_PI_NODE:
867*7c568831SAndroid Build Coastguard Worker if (cur->name != NULL) {
868*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "<?");
869*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
870*7c568831SAndroid Build Coastguard Worker if (cur->content != NULL) {
871*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, " ");
872*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf,
873*7c568831SAndroid Build Coastguard Worker (const char *)cur->content);
874*7c568831SAndroid Build Coastguard Worker }
875*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">");
876*7c568831SAndroid Build Coastguard Worker }
877*7c568831SAndroid Build Coastguard Worker break;
878*7c568831SAndroid Build Coastguard Worker
879*7c568831SAndroid Build Coastguard Worker case HTML_ENTITY_REF_NODE:
880*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "&");
881*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
882*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ";");
883*7c568831SAndroid Build Coastguard Worker break;
884*7c568831SAndroid Build Coastguard Worker
885*7c568831SAndroid Build Coastguard Worker case HTML_PRESERVE_NODE:
886*7c568831SAndroid Build Coastguard Worker if (cur->content != NULL) {
887*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->content);
888*7c568831SAndroid Build Coastguard Worker }
889*7c568831SAndroid Build Coastguard Worker break;
890*7c568831SAndroid Build Coastguard Worker
891*7c568831SAndroid Build Coastguard Worker default:
892*7c568831SAndroid Build Coastguard Worker break;
893*7c568831SAndroid Build Coastguard Worker }
894*7c568831SAndroid Build Coastguard Worker
895*7c568831SAndroid Build Coastguard Worker while (1) {
896*7c568831SAndroid Build Coastguard Worker if (cur == root)
897*7c568831SAndroid Build Coastguard Worker return;
898*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) {
899*7c568831SAndroid Build Coastguard Worker cur = cur->next;
900*7c568831SAndroid Build Coastguard Worker break;
901*7c568831SAndroid Build Coastguard Worker }
902*7c568831SAndroid Build Coastguard Worker
903*7c568831SAndroid Build Coastguard Worker cur = parent;
904*7c568831SAndroid Build Coastguard Worker /* cur->parent was validated when descending. */
905*7c568831SAndroid Build Coastguard Worker parent = cur->parent;
906*7c568831SAndroid Build Coastguard Worker
907*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
908*7c568831SAndroid Build Coastguard Worker (cur->type == XML_DOCUMENT_NODE)) {
909*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "\n");
910*7c568831SAndroid Build Coastguard Worker } else {
911*7c568831SAndroid Build Coastguard Worker if ((format) && (cur->ns == NULL))
912*7c568831SAndroid Build Coastguard Worker info = htmlTagLookup(cur->name);
913*7c568831SAndroid Build Coastguard Worker else
914*7c568831SAndroid Build Coastguard Worker info = NULL;
915*7c568831SAndroid Build Coastguard Worker
916*7c568831SAndroid Build Coastguard Worker if ((format) && (info != NULL) && (!info->isinline) &&
917*7c568831SAndroid Build Coastguard Worker (cur->last->type != HTML_TEXT_NODE) &&
918*7c568831SAndroid Build Coastguard Worker (cur->last->type != HTML_ENTITY_REF_NODE) &&
919*7c568831SAndroid Build Coastguard Worker (cur->children != cur->last) &&
920*7c568831SAndroid Build Coastguard Worker (cur->name != NULL) &&
921*7c568831SAndroid Build Coastguard Worker (cur->name[0] != 'p')) /* p, pre, param */
922*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "\n");
923*7c568831SAndroid Build Coastguard Worker
924*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "</");
925*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
926*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
927*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ":");
928*7c568831SAndroid Build Coastguard Worker }
929*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, (const char *)cur->name);
930*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, ">");
931*7c568831SAndroid Build Coastguard Worker
932*7c568831SAndroid Build Coastguard Worker if ((format) && (info != NULL) && (!info->isinline) &&
933*7c568831SAndroid Build Coastguard Worker (cur->next != NULL)) {
934*7c568831SAndroid Build Coastguard Worker if ((cur->next->type != HTML_TEXT_NODE) &&
935*7c568831SAndroid Build Coastguard Worker (cur->next->type != HTML_ENTITY_REF_NODE) &&
936*7c568831SAndroid Build Coastguard Worker (parent != NULL) &&
937*7c568831SAndroid Build Coastguard Worker (parent->name != NULL) &&
938*7c568831SAndroid Build Coastguard Worker (parent->name[0] != 'p')) /* p, pre, param */
939*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(buf, "\n");
940*7c568831SAndroid Build Coastguard Worker }
941*7c568831SAndroid Build Coastguard Worker }
942*7c568831SAndroid Build Coastguard Worker }
943*7c568831SAndroid Build Coastguard Worker }
944*7c568831SAndroid Build Coastguard Worker }
945*7c568831SAndroid Build Coastguard Worker
946*7c568831SAndroid Build Coastguard Worker /**
947*7c568831SAndroid Build Coastguard Worker * htmlNodeDumpOutput:
948*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
949*7c568831SAndroid Build Coastguard Worker * @doc: the document
950*7c568831SAndroid Build Coastguard Worker * @cur: the current node
951*7c568831SAndroid Build Coastguard Worker * @encoding: the encoding string (unused)
952*7c568831SAndroid Build Coastguard Worker *
953*7c568831SAndroid Build Coastguard Worker * Dump an HTML node, recursive behaviour,children are printed too,
954*7c568831SAndroid Build Coastguard Worker * and formatting returns/spaces are added.
955*7c568831SAndroid Build Coastguard Worker */
956*7c568831SAndroid Build Coastguard Worker void
htmlNodeDumpOutput(xmlOutputBufferPtr buf,xmlDocPtr doc,xmlNodePtr cur,const char * encoding ATTRIBUTE_UNUSED)957*7c568831SAndroid Build Coastguard Worker htmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
958*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur, const char *encoding ATTRIBUTE_UNUSED) {
959*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(buf, doc, cur, NULL, 1);
960*7c568831SAndroid Build Coastguard Worker }
961*7c568831SAndroid Build Coastguard Worker
962*7c568831SAndroid Build Coastguard Worker /**
963*7c568831SAndroid Build Coastguard Worker * htmlDocContentDumpFormatOutput:
964*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
965*7c568831SAndroid Build Coastguard Worker * @cur: the document
966*7c568831SAndroid Build Coastguard Worker * @encoding: the encoding string (unused)
967*7c568831SAndroid Build Coastguard Worker * @format: should formatting spaces been added
968*7c568831SAndroid Build Coastguard Worker *
969*7c568831SAndroid Build Coastguard Worker * Dump an HTML document.
970*7c568831SAndroid Build Coastguard Worker */
971*7c568831SAndroid Build Coastguard Worker void
htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf,xmlDocPtr cur,const char * encoding ATTRIBUTE_UNUSED,int format)972*7c568831SAndroid Build Coastguard Worker htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
973*7c568831SAndroid Build Coastguard Worker const char *encoding ATTRIBUTE_UNUSED,
974*7c568831SAndroid Build Coastguard Worker int format) {
975*7c568831SAndroid Build Coastguard Worker int type = 0;
976*7c568831SAndroid Build Coastguard Worker if (cur) {
977*7c568831SAndroid Build Coastguard Worker type = cur->type;
978*7c568831SAndroid Build Coastguard Worker cur->type = XML_HTML_DOCUMENT_NODE;
979*7c568831SAndroid Build Coastguard Worker }
980*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, NULL, format);
981*7c568831SAndroid Build Coastguard Worker if (cur)
982*7c568831SAndroid Build Coastguard Worker cur->type = (xmlElementType) type;
983*7c568831SAndroid Build Coastguard Worker }
984*7c568831SAndroid Build Coastguard Worker
985*7c568831SAndroid Build Coastguard Worker /**
986*7c568831SAndroid Build Coastguard Worker * htmlDocContentDumpOutput:
987*7c568831SAndroid Build Coastguard Worker * @buf: the HTML buffer output
988*7c568831SAndroid Build Coastguard Worker * @cur: the document
989*7c568831SAndroid Build Coastguard Worker * @encoding: the encoding string (unused)
990*7c568831SAndroid Build Coastguard Worker *
991*7c568831SAndroid Build Coastguard Worker * Dump an HTML document. Formatting return/spaces are added.
992*7c568831SAndroid Build Coastguard Worker */
993*7c568831SAndroid Build Coastguard Worker void
htmlDocContentDumpOutput(xmlOutputBufferPtr buf,xmlDocPtr cur,const char * encoding ATTRIBUTE_UNUSED)994*7c568831SAndroid Build Coastguard Worker htmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
995*7c568831SAndroid Build Coastguard Worker const char *encoding ATTRIBUTE_UNUSED) {
996*7c568831SAndroid Build Coastguard Worker htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, NULL, 1);
997*7c568831SAndroid Build Coastguard Worker }
998*7c568831SAndroid Build Coastguard Worker
999*7c568831SAndroid Build Coastguard Worker /************************************************************************
1000*7c568831SAndroid Build Coastguard Worker * *
1001*7c568831SAndroid Build Coastguard Worker * Saving functions front-ends *
1002*7c568831SAndroid Build Coastguard Worker * *
1003*7c568831SAndroid Build Coastguard Worker ************************************************************************/
1004*7c568831SAndroid Build Coastguard Worker
1005*7c568831SAndroid Build Coastguard Worker /**
1006*7c568831SAndroid Build Coastguard Worker * htmlDocDump:
1007*7c568831SAndroid Build Coastguard Worker * @f: the FILE*
1008*7c568831SAndroid Build Coastguard Worker * @cur: the document
1009*7c568831SAndroid Build Coastguard Worker *
1010*7c568831SAndroid Build Coastguard Worker * Dump an HTML document to an open FILE.
1011*7c568831SAndroid Build Coastguard Worker *
1012*7c568831SAndroid Build Coastguard Worker * returns: the number of byte written or -1 in case of failure.
1013*7c568831SAndroid Build Coastguard Worker */
1014*7c568831SAndroid Build Coastguard Worker int
htmlDocDump(FILE * f,xmlDocPtr cur)1015*7c568831SAndroid Build Coastguard Worker htmlDocDump(FILE *f, xmlDocPtr cur) {
1016*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
1017*7c568831SAndroid Build Coastguard Worker xmlCharEncodingHandlerPtr handler = NULL;
1018*7c568831SAndroid Build Coastguard Worker const char *encoding;
1019*7c568831SAndroid Build Coastguard Worker int ret;
1020*7c568831SAndroid Build Coastguard Worker
1021*7c568831SAndroid Build Coastguard Worker xmlInitParser();
1022*7c568831SAndroid Build Coastguard Worker
1023*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (f == NULL)) {
1024*7c568831SAndroid Build Coastguard Worker return(-1);
1025*7c568831SAndroid Build Coastguard Worker }
1026*7c568831SAndroid Build Coastguard Worker
1027*7c568831SAndroid Build Coastguard Worker encoding = (const char *) htmlGetMetaEncoding(cur);
1028*7c568831SAndroid Build Coastguard Worker handler = htmlFindOutputEncoder(encoding);
1029*7c568831SAndroid Build Coastguard Worker buf = xmlOutputBufferCreateFile(f, handler);
1030*7c568831SAndroid Build Coastguard Worker if (buf == NULL)
1031*7c568831SAndroid Build Coastguard Worker return(-1);
1032*7c568831SAndroid Build Coastguard Worker htmlDocContentDumpOutput(buf, cur, NULL);
1033*7c568831SAndroid Build Coastguard Worker
1034*7c568831SAndroid Build Coastguard Worker ret = xmlOutputBufferClose(buf);
1035*7c568831SAndroid Build Coastguard Worker return(ret);
1036*7c568831SAndroid Build Coastguard Worker }
1037*7c568831SAndroid Build Coastguard Worker
1038*7c568831SAndroid Build Coastguard Worker /**
1039*7c568831SAndroid Build Coastguard Worker * htmlSaveFile:
1040*7c568831SAndroid Build Coastguard Worker * @filename: the filename (or URL)
1041*7c568831SAndroid Build Coastguard Worker * @cur: the document
1042*7c568831SAndroid Build Coastguard Worker *
1043*7c568831SAndroid Build Coastguard Worker * Dump an HTML document to a file. If @filename is "-" the stdout file is
1044*7c568831SAndroid Build Coastguard Worker * used.
1045*7c568831SAndroid Build Coastguard Worker * returns: the number of byte written or -1 in case of failure.
1046*7c568831SAndroid Build Coastguard Worker */
1047*7c568831SAndroid Build Coastguard Worker int
htmlSaveFile(const char * filename,xmlDocPtr cur)1048*7c568831SAndroid Build Coastguard Worker htmlSaveFile(const char *filename, xmlDocPtr cur) {
1049*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
1050*7c568831SAndroid Build Coastguard Worker xmlCharEncodingHandlerPtr handler = NULL;
1051*7c568831SAndroid Build Coastguard Worker const char *encoding;
1052*7c568831SAndroid Build Coastguard Worker int ret;
1053*7c568831SAndroid Build Coastguard Worker
1054*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (filename == NULL))
1055*7c568831SAndroid Build Coastguard Worker return(-1);
1056*7c568831SAndroid Build Coastguard Worker
1057*7c568831SAndroid Build Coastguard Worker xmlInitParser();
1058*7c568831SAndroid Build Coastguard Worker
1059*7c568831SAndroid Build Coastguard Worker encoding = (const char *) htmlGetMetaEncoding(cur);
1060*7c568831SAndroid Build Coastguard Worker handler = htmlFindOutputEncoder(encoding);
1061*7c568831SAndroid Build Coastguard Worker buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
1062*7c568831SAndroid Build Coastguard Worker if (buf == NULL)
1063*7c568831SAndroid Build Coastguard Worker return(0);
1064*7c568831SAndroid Build Coastguard Worker
1065*7c568831SAndroid Build Coastguard Worker htmlDocContentDumpOutput(buf, cur, NULL);
1066*7c568831SAndroid Build Coastguard Worker
1067*7c568831SAndroid Build Coastguard Worker ret = xmlOutputBufferClose(buf);
1068*7c568831SAndroid Build Coastguard Worker return(ret);
1069*7c568831SAndroid Build Coastguard Worker }
1070*7c568831SAndroid Build Coastguard Worker
1071*7c568831SAndroid Build Coastguard Worker /**
1072*7c568831SAndroid Build Coastguard Worker * htmlSaveFileFormat:
1073*7c568831SAndroid Build Coastguard Worker * @filename: the filename
1074*7c568831SAndroid Build Coastguard Worker * @cur: the document
1075*7c568831SAndroid Build Coastguard Worker * @format: should formatting spaces been added
1076*7c568831SAndroid Build Coastguard Worker * @encoding: the document encoding
1077*7c568831SAndroid Build Coastguard Worker *
1078*7c568831SAndroid Build Coastguard Worker * Dump an HTML document to a file using a given encoding.
1079*7c568831SAndroid Build Coastguard Worker *
1080*7c568831SAndroid Build Coastguard Worker * returns: the number of byte written or -1 in case of failure.
1081*7c568831SAndroid Build Coastguard Worker */
1082*7c568831SAndroid Build Coastguard Worker int
htmlSaveFileFormat(const char * filename,xmlDocPtr cur,const char * encoding,int format)1083*7c568831SAndroid Build Coastguard Worker htmlSaveFileFormat(const char *filename, xmlDocPtr cur,
1084*7c568831SAndroid Build Coastguard Worker const char *encoding, int format) {
1085*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
1086*7c568831SAndroid Build Coastguard Worker xmlCharEncodingHandlerPtr handler = NULL;
1087*7c568831SAndroid Build Coastguard Worker int ret;
1088*7c568831SAndroid Build Coastguard Worker
1089*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (filename == NULL))
1090*7c568831SAndroid Build Coastguard Worker return(-1);
1091*7c568831SAndroid Build Coastguard Worker
1092*7c568831SAndroid Build Coastguard Worker xmlInitParser();
1093*7c568831SAndroid Build Coastguard Worker
1094*7c568831SAndroid Build Coastguard Worker handler = htmlFindOutputEncoder(encoding);
1095*7c568831SAndroid Build Coastguard Worker if (handler != NULL)
1096*7c568831SAndroid Build Coastguard Worker htmlSetMetaEncoding(cur, (const xmlChar *) handler->name);
1097*7c568831SAndroid Build Coastguard Worker else
1098*7c568831SAndroid Build Coastguard Worker htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
1099*7c568831SAndroid Build Coastguard Worker
1100*7c568831SAndroid Build Coastguard Worker /*
1101*7c568831SAndroid Build Coastguard Worker * save the content to a temp buffer.
1102*7c568831SAndroid Build Coastguard Worker */
1103*7c568831SAndroid Build Coastguard Worker buf = xmlOutputBufferCreateFilename(filename, handler, 0);
1104*7c568831SAndroid Build Coastguard Worker if (buf == NULL)
1105*7c568831SAndroid Build Coastguard Worker return(0);
1106*7c568831SAndroid Build Coastguard Worker
1107*7c568831SAndroid Build Coastguard Worker htmlDocContentDumpFormatOutput(buf, cur, encoding, format);
1108*7c568831SAndroid Build Coastguard Worker
1109*7c568831SAndroid Build Coastguard Worker ret = xmlOutputBufferClose(buf);
1110*7c568831SAndroid Build Coastguard Worker return(ret);
1111*7c568831SAndroid Build Coastguard Worker }
1112*7c568831SAndroid Build Coastguard Worker
1113*7c568831SAndroid Build Coastguard Worker /**
1114*7c568831SAndroid Build Coastguard Worker * htmlSaveFileEnc:
1115*7c568831SAndroid Build Coastguard Worker * @filename: the filename
1116*7c568831SAndroid Build Coastguard Worker * @cur: the document
1117*7c568831SAndroid Build Coastguard Worker * @encoding: the document encoding
1118*7c568831SAndroid Build Coastguard Worker *
1119*7c568831SAndroid Build Coastguard Worker * Dump an HTML document to a file using a given encoding
1120*7c568831SAndroid Build Coastguard Worker * and formatting returns/spaces are added.
1121*7c568831SAndroid Build Coastguard Worker *
1122*7c568831SAndroid Build Coastguard Worker * returns: the number of byte written or -1 in case of failure.
1123*7c568831SAndroid Build Coastguard Worker */
1124*7c568831SAndroid Build Coastguard Worker int
htmlSaveFileEnc(const char * filename,xmlDocPtr cur,const char * encoding)1125*7c568831SAndroid Build Coastguard Worker htmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
1126*7c568831SAndroid Build Coastguard Worker return(htmlSaveFileFormat(filename, cur, encoding, 1));
1127*7c568831SAndroid Build Coastguard Worker }
1128*7c568831SAndroid Build Coastguard Worker
1129*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
1130*7c568831SAndroid Build Coastguard Worker
1131*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_HTML_ENABLED */
1132