xref: /aosp_15_r20/external/cronet/third_party/libxml/src/xmlwriter.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 
2 /*
3  * xmlwriter.c: XML text writer implementation
4  *
5  * For license and disclaimer see the license and disclaimer of
6  * libxml2.
7  *
8  * [email protected]
9  */
10 
11 #define IN_LIBXML
12 #include "libxml.h"
13 #include <string.h>
14 #include <stdarg.h>
15 
16 #include <libxml/xmlmemory.h>
17 #include <libxml/parser.h>
18 #include <libxml/parserInternals.h>
19 #include <libxml/uri.h>
20 #include <libxml/HTMLtree.h>
21 #include <libxml/SAX2.h>
22 
23 #ifdef LIBXML_WRITER_ENABLED
24 
25 #include <libxml/xmlwriter.h>
26 
27 #include "private/buf.h"
28 #include "private/enc.h"
29 #include "private/error.h"
30 #include "private/save.h"
31 
32 #define B64LINELEN 72
33 #define B64CRLF "\r\n"
34 
35 #ifndef va_copy
36   #ifdef __va_copy
37     #define va_copy(dest, src) __va_copy(dest, src)
38   #else
39     #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
40   #endif
41 #endif
42 
43 /*
44  * Types are kept private
45  */
46 typedef enum {
47     XML_TEXTWRITER_NONE = 0,
48     XML_TEXTWRITER_NAME,
49     XML_TEXTWRITER_ATTRIBUTE,
50     XML_TEXTWRITER_TEXT,
51     XML_TEXTWRITER_PI,
52     XML_TEXTWRITER_PI_TEXT,
53     XML_TEXTWRITER_CDATA,
54     XML_TEXTWRITER_DTD,
55     XML_TEXTWRITER_DTD_TEXT,
56     XML_TEXTWRITER_DTD_ELEM,
57     XML_TEXTWRITER_DTD_ELEM_TEXT,
58     XML_TEXTWRITER_DTD_ATTL,
59     XML_TEXTWRITER_DTD_ATTL_TEXT,
60     XML_TEXTWRITER_DTD_ENTY,    /* entity */
61     XML_TEXTWRITER_DTD_ENTY_TEXT,
62     XML_TEXTWRITER_DTD_PENT,    /* parameter entity */
63     XML_TEXTWRITER_COMMENT
64 } xmlTextWriterState;
65 
66 typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
67 
68 struct _xmlTextWriterStackEntry {
69     xmlChar *name;
70     xmlTextWriterState state;
71 };
72 
73 typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
74 struct _xmlTextWriterNsStackEntry {
75     xmlChar *prefix;
76     xmlChar *uri;
77     xmlLinkPtr elem;
78 };
79 
80 struct _xmlTextWriter {
81     xmlOutputBufferPtr out;     /* output buffer */
82     xmlListPtr nodes;           /* element name stack */
83     xmlListPtr nsstack;         /* name spaces stack */
84     int level;
85     int indent;                 /* enable indent */
86     int doindent;               /* internal indent flag */
87     xmlChar *ichar;             /* indent character */
88     char qchar;                 /* character used for quoting attribute values */
89     xmlParserCtxtPtr ctxt;
90     int no_doc_free;
91     xmlDocPtr doc;
92 };
93 
94 static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
95 static int xmlCmpTextWriterStackEntry(const void *data0,
96                                       const void *data1);
97 static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
98 static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
99 static int xmlCmpTextWriterNsStackEntry(const void *data0,
100                                         const void *data1);
101 static int xmlTextWriterWriteDocCallback(void *context,
102                                          const char *str, int len);
103 static int xmlTextWriterCloseDocCallback(void *context);
104 
105 static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr) LIBXML_ATTR_FORMAT(1,0);
106 static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
107                                       const unsigned char *data);
108 static void xmlTextWriterStartDocumentCallback(void *ctx);
109 static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
110 static int
111   xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
112                                        xmlTextWriterStackEntry * p);
113 
114 /**
115  * xmlWriterErrMsg:
116  * @ctxt:  a writer context
117  * @error:  the error number
118  * @msg:  the error message
119  *
120  * Handle a writer error
121  */
122 static void
xmlWriterErrMsg(xmlTextWriterPtr ctxt,xmlParserErrors error,const char * msg)123 xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
124                const char *msg)
125 {
126     if (ctxt != NULL) {
127 	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
128 	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
129 		    NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
130     } else {
131 	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
132                     XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
133     }
134 }
135 
136 /**
137  * xmlWriterErrMsgInt:
138  * @ctxt:  a writer context
139  * @error:  the error number
140  * @msg:  the error message
141  * @val:  an int
142  *
143  * Handle a writer error
144  */
145 static void LIBXML_ATTR_FORMAT(3,0)
xmlWriterErrMsgInt(xmlTextWriterPtr ctxt,xmlParserErrors error,const char * msg,int val)146 xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
147                const char *msg, int val)
148 {
149     if (ctxt != NULL) {
150 	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
151 	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
152 		    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
153     } else {
154 	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
155                     XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
156     }
157 }
158 
159 /**
160  * xmlNewTextWriter:
161  * @out:  an xmlOutputBufferPtr
162  *
163  * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
164  * NOTE: the @out parameter will be deallocated when the writer is closed
165  *       (if the call succeed.)
166  *
167  * Returns the new xmlTextWriterPtr or NULL in case of error
168  */
169 xmlTextWriterPtr
xmlNewTextWriter(xmlOutputBufferPtr out)170 xmlNewTextWriter(xmlOutputBufferPtr out)
171 {
172     xmlTextWriterPtr ret;
173 
174     ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
175     if (ret == NULL) {
176         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
177                         "xmlNewTextWriter : out of memory!\n");
178         return NULL;
179     }
180     memset(ret, 0, sizeof(xmlTextWriter));
181 
182     ret->nodes = xmlListCreate(xmlFreeTextWriterStackEntry,
183                                xmlCmpTextWriterStackEntry);
184     if (ret->nodes == NULL) {
185         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
186                         "xmlNewTextWriter : out of memory!\n");
187         xmlFree(ret);
188         return NULL;
189     }
190 
191     ret->nsstack = xmlListCreate(xmlFreeTextWriterNsStackEntry,
192                                  xmlCmpTextWriterNsStackEntry);
193     if (ret->nsstack == NULL) {
194         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
195                         "xmlNewTextWriter : out of memory!\n");
196         xmlListDelete(ret->nodes);
197         xmlFree(ret);
198         return NULL;
199     }
200 
201     ret->out = out;
202     ret->ichar = xmlStrdup(BAD_CAST " ");
203     ret->qchar = '"';
204 
205     if (!ret->ichar) {
206         xmlListDelete(ret->nodes);
207         xmlListDelete(ret->nsstack);
208         xmlFree(ret);
209         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
210                         "xmlNewTextWriter : out of memory!\n");
211         return NULL;
212     }
213 
214     ret->doc = xmlNewDoc(NULL);
215 
216     ret->no_doc_free = 0;
217 
218     return ret;
219 }
220 
221 /**
222  * xmlNewTextWriterFilename:
223  * @uri:  the URI of the resource for the output
224  * @compression:  compress the output?
225  *
226  * Create a new xmlNewTextWriter structure with @uri as output
227  *
228  * Returns the new xmlTextWriterPtr or NULL in case of error
229  */
230 xmlTextWriterPtr
xmlNewTextWriterFilename(const char * uri,int compression)231 xmlNewTextWriterFilename(const char *uri, int compression)
232 {
233     xmlTextWriterPtr ret;
234     xmlOutputBufferPtr out;
235 
236     out = xmlOutputBufferCreateFilename(uri, NULL, compression);
237     if (out == NULL) {
238         xmlWriterErrMsg(NULL, XML_IO_EIO,
239                         "xmlNewTextWriterFilename : cannot open uri\n");
240         return NULL;
241     }
242 
243     ret = xmlNewTextWriter(out);
244     if (ret == NULL) {
245         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
246                         "xmlNewTextWriterFilename : out of memory!\n");
247         xmlOutputBufferClose(out);
248         return NULL;
249     }
250 
251     ret->indent = 0;
252     ret->doindent = 0;
253     return ret;
254 }
255 
256 /**
257  * xmlNewTextWriterMemory:
258  * @buf:  xmlBufferPtr
259  * @compression:  compress the output?
260  *
261  * Create a new xmlNewTextWriter structure with @buf as output
262  * TODO: handle compression
263  *
264  * Returns the new xmlTextWriterPtr or NULL in case of error
265  */
266 xmlTextWriterPtr
xmlNewTextWriterMemory(xmlBufferPtr buf,int compression ATTRIBUTE_UNUSED)267 xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
268 {
269     xmlTextWriterPtr ret;
270     xmlOutputBufferPtr out;
271 
272 /*::todo handle compression */
273     out = xmlOutputBufferCreateBuffer(buf, NULL);
274 
275     if (out == NULL) {
276         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
277                         "xmlNewTextWriterMemory : out of memory!\n");
278         return NULL;
279     }
280 
281     ret = xmlNewTextWriter(out);
282     if (ret == NULL) {
283         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
284                         "xmlNewTextWriterMemory : out of memory!\n");
285         xmlOutputBufferClose(out);
286         return NULL;
287     }
288 
289     return ret;
290 }
291 
292 /**
293  * xmlNewTextWriterPushParser:
294  * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
295  * @compression:  compress the output?
296  *
297  * Create a new xmlNewTextWriter structure with @ctxt as output
298  * NOTE: the @ctxt context will be freed with the resulting writer
299  *       (if the call succeeds).
300  * TODO: handle compression
301  *
302  * Returns the new xmlTextWriterPtr or NULL in case of error
303  */
304 xmlTextWriterPtr
xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,int compression ATTRIBUTE_UNUSED)305 xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
306                            int compression ATTRIBUTE_UNUSED)
307 {
308     xmlTextWriterPtr ret;
309     xmlOutputBufferPtr out;
310 
311     if (ctxt == NULL) {
312         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
313                         "xmlNewTextWriterPushParser : invalid context!\n");
314         return NULL;
315     }
316 
317     out = xmlOutputBufferCreateIO(xmlTextWriterWriteDocCallback,
318                                   xmlTextWriterCloseDocCallback,
319                                   (void *) ctxt, NULL);
320     if (out == NULL) {
321         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
322                         "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
323         return NULL;
324     }
325 
326     ret = xmlNewTextWriter(out);
327     if (ret == NULL) {
328         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
329                         "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
330         xmlOutputBufferClose(out);
331         return NULL;
332     }
333 
334     ret->ctxt = ctxt;
335 
336     return ret;
337 }
338 
339 /**
340  * xmlNewTextWriterDoc:
341  * @doc: address of a xmlDocPtr to hold the new XML document tree
342  * @compression:  compress the output?
343  *
344  * Create a new xmlNewTextWriter structure with @*doc as output
345  *
346  * Returns the new xmlTextWriterPtr or NULL in case of error
347  */
348 xmlTextWriterPtr
xmlNewTextWriterDoc(xmlDocPtr * doc,int compression)349 xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
350 {
351     xmlTextWriterPtr ret;
352     xmlSAXHandler saxHandler;
353     xmlParserCtxtPtr ctxt;
354 
355     memset(&saxHandler, '\0', sizeof(saxHandler));
356     xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
357     saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
358     saxHandler.startElement = xmlSAX2StartElement;
359     saxHandler.endElement = xmlSAX2EndElement;
360 
361     ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
362     if (ctxt == NULL) {
363         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
364                 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
365         return NULL;
366     }
367     /*
368      * For some reason this seems to completely break if node names
369      * are interned.
370      */
371     ctxt->dictNames = 0;
372 
373     ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
374     if (ctxt->myDoc == NULL) {
375         xmlFreeParserCtxt(ctxt);
376         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
377                         "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
378         return NULL;
379     }
380 
381     ret = xmlNewTextWriterPushParser(ctxt, compression);
382     if (ret == NULL) {
383         xmlFreeDoc(ctxt->myDoc);
384         xmlFreeParserCtxt(ctxt);
385         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
386                 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
387         return NULL;
388     }
389 
390     xmlSetDocCompressMode(ctxt->myDoc, compression);
391 
392     if (doc != NULL) {
393         *doc = ctxt->myDoc;
394 	ret->no_doc_free = 1;
395     }
396 
397     return ret;
398 }
399 
400 /**
401  * xmlNewTextWriterTree:
402  * @doc: xmlDocPtr
403  * @node: xmlNodePtr or NULL for doc->children
404  * @compression:  compress the output?
405  *
406  * Create a new xmlNewTextWriter structure with @doc as output
407  * starting at @node
408  *
409  * Returns the new xmlTextWriterPtr or NULL in case of error
410  */
411 xmlTextWriterPtr
xmlNewTextWriterTree(xmlDocPtr doc,xmlNodePtr node,int compression)412 xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
413 {
414     xmlTextWriterPtr ret;
415     xmlSAXHandler saxHandler;
416     xmlParserCtxtPtr ctxt;
417 
418     if (doc == NULL) {
419         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
420                         "xmlNewTextWriterTree : invalid document tree!\n");
421         return NULL;
422     }
423 
424     memset(&saxHandler, '\0', sizeof(saxHandler));
425     xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
426     saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
427     saxHandler.startElement = xmlSAX2StartElement;
428     saxHandler.endElement = xmlSAX2EndElement;
429 
430     ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
431     if (ctxt == NULL) {
432         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
433                         "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
434         return NULL;
435     }
436     /*
437      * For some reason this seems to completely break if node names
438      * are interned.
439      */
440     ctxt->dictNames = 0;
441 
442     ret = xmlNewTextWriterPushParser(ctxt, compression);
443     if (ret == NULL) {
444         xmlFreeParserCtxt(ctxt);
445         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
446                         "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
447         return NULL;
448     }
449 
450     ctxt->myDoc = doc;
451     ctxt->node = node;
452     ret->no_doc_free = 1;
453 
454     xmlSetDocCompressMode(doc, compression);
455 
456     return ret;
457 }
458 
459 /**
460  * xmlFreeTextWriter:
461  * @writer:  the xmlTextWriterPtr
462  *
463  * Deallocate all the resources associated to the writer
464  */
465 void
xmlFreeTextWriter(xmlTextWriterPtr writer)466 xmlFreeTextWriter(xmlTextWriterPtr writer)
467 {
468     if (writer == NULL)
469         return;
470 
471     if (writer->out != NULL)
472         xmlOutputBufferClose(writer->out);
473 
474     if (writer->nodes != NULL)
475         xmlListDelete(writer->nodes);
476 
477     if (writer->nsstack != NULL)
478         xmlListDelete(writer->nsstack);
479 
480     if (writer->ctxt != NULL) {
481         if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
482 	    xmlFreeDoc(writer->ctxt->myDoc);
483 	    writer->ctxt->myDoc = NULL;
484 	}
485         xmlFreeParserCtxt(writer->ctxt);
486     }
487 
488     if (writer->doc != NULL)
489         xmlFreeDoc(writer->doc);
490 
491     if (writer->ichar != NULL)
492         xmlFree(writer->ichar);
493     xmlFree(writer);
494 }
495 
496 /**
497  * xmlTextWriterStartDocument:
498  * @writer:  the xmlTextWriterPtr
499  * @version:  the xml version ("1.0") or NULL for default ("1.0")
500  * @encoding:  the encoding or NULL for default
501  * @standalone: "yes" or "no" or NULL for default
502  *
503  * Start a new xml document
504  *
505  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
506  */
507 int
xmlTextWriterStartDocument(xmlTextWriterPtr writer,const char * version,const char * encoding,const char * standalone)508 xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
509                            const char *encoding, const char *standalone)
510 {
511     int count;
512     int sum;
513     xmlLinkPtr lk;
514     xmlCharEncodingHandlerPtr encoder;
515 
516     if ((writer == NULL) || (writer->out == NULL)) {
517         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
518                         "xmlTextWriterStartDocument : invalid writer!\n");
519         return -1;
520     }
521 
522     lk = xmlListFront(writer->nodes);
523     if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
524         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
525                         "xmlTextWriterStartDocument : not allowed in this context!\n");
526         return -1;
527     }
528 
529     encoder = NULL;
530     if (encoding != NULL) {
531         encoder = xmlFindCharEncodingHandler(encoding);
532         if (encoder == NULL) {
533             xmlWriterErrMsg(writer, XML_ERR_UNSUPPORTED_ENCODING,
534                             "xmlTextWriterStartDocument : unsupported encoding\n");
535             return -1;
536         }
537     }
538 
539     writer->out->encoder = encoder;
540     if (encoder != NULL) {
541 	if (writer->out->conv == NULL) {
542 	    writer->out->conv = xmlBufCreateSize(4000);
543 	}
544         xmlCharEncOutput(writer->out, 1);
545         if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
546             writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
547     } else
548         writer->out->conv = NULL;
549 
550     sum = 0;
551     count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
552     if (count < 0)
553         return -1;
554     sum += count;
555     count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
556     if (count < 0)
557         return -1;
558     sum += count;
559     if (version != 0)
560         count = xmlOutputBufferWriteString(writer->out, version);
561     else
562         count = xmlOutputBufferWriteString(writer->out, "1.0");
563     if (count < 0)
564         return -1;
565     sum += count;
566     count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
567     if (count < 0)
568         return -1;
569     sum += count;
570     if (writer->out->encoder != 0) {
571         count = xmlOutputBufferWriteString(writer->out, " encoding=");
572         if (count < 0)
573             return -1;
574         sum += count;
575         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
576         if (count < 0)
577             return -1;
578         sum += count;
579         count =
580             xmlOutputBufferWriteString(writer->out,
581                                        writer->out->encoder->name);
582         if (count < 0)
583             return -1;
584         sum += count;
585         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
586         if (count < 0)
587             return -1;
588         sum += count;
589     }
590 
591     if (standalone != 0) {
592         count = xmlOutputBufferWriteString(writer->out, " standalone=");
593         if (count < 0)
594             return -1;
595         sum += count;
596         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
597         if (count < 0)
598             return -1;
599         sum += count;
600         count = xmlOutputBufferWriteString(writer->out, standalone);
601         if (count < 0)
602             return -1;
603         sum += count;
604         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
605         if (count < 0)
606             return -1;
607         sum += count;
608     }
609 
610     count = xmlOutputBufferWriteString(writer->out, "?>\n");
611     if (count < 0)
612         return -1;
613     sum += count;
614 
615     return sum;
616 }
617 
618 /**
619  * xmlTextWriterEndDocument:
620  * @writer:  the xmlTextWriterPtr
621  *
622  * End an xml document. All open elements are closed, and
623  * the content is flushed to the output.
624  *
625  * Returns the bytes written or -1 in case of error
626  */
627 int
xmlTextWriterEndDocument(xmlTextWriterPtr writer)628 xmlTextWriterEndDocument(xmlTextWriterPtr writer)
629 {
630     int count;
631     int sum;
632     xmlLinkPtr lk;
633     xmlTextWriterStackEntry *p;
634 
635     if (writer == NULL) {
636         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
637                         "xmlTextWriterEndDocument : invalid writer!\n");
638         return -1;
639     }
640 
641     sum = 0;
642     while ((lk = xmlListFront(writer->nodes)) != NULL) {
643         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
644         if (p == 0)
645             break;
646         switch (p->state) {
647             case XML_TEXTWRITER_NAME:
648             case XML_TEXTWRITER_ATTRIBUTE:
649             case XML_TEXTWRITER_TEXT:
650                 count = xmlTextWriterEndElement(writer);
651                 if (count < 0)
652                     return -1;
653                 sum += count;
654                 break;
655             case XML_TEXTWRITER_PI:
656             case XML_TEXTWRITER_PI_TEXT:
657                 count = xmlTextWriterEndPI(writer);
658                 if (count < 0)
659                     return -1;
660                 sum += count;
661                 break;
662             case XML_TEXTWRITER_CDATA:
663                 count = xmlTextWriterEndCDATA(writer);
664                 if (count < 0)
665                     return -1;
666                 sum += count;
667                 break;
668             case XML_TEXTWRITER_DTD:
669             case XML_TEXTWRITER_DTD_TEXT:
670             case XML_TEXTWRITER_DTD_ELEM:
671             case XML_TEXTWRITER_DTD_ELEM_TEXT:
672             case XML_TEXTWRITER_DTD_ATTL:
673             case XML_TEXTWRITER_DTD_ATTL_TEXT:
674             case XML_TEXTWRITER_DTD_ENTY:
675             case XML_TEXTWRITER_DTD_ENTY_TEXT:
676             case XML_TEXTWRITER_DTD_PENT:
677                 count = xmlTextWriterEndDTD(writer);
678                 if (count < 0)
679                     return -1;
680                 sum += count;
681                 break;
682             case XML_TEXTWRITER_COMMENT:
683                 count = xmlTextWriterEndComment(writer);
684                 if (count < 0)
685                     return -1;
686                 sum += count;
687                 break;
688             default:
689                 break;
690         }
691     }
692 
693     if (!writer->indent) {
694         count = xmlOutputBufferWriteString(writer->out, "\n");
695         if (count < 0)
696             return -1;
697         sum += count;
698     }
699 
700     count = xmlTextWriterFlush(writer);
701     if (count < 0)
702         return -1;
703     sum += count;
704 
705 
706     return sum;
707 }
708 
709 /**
710  * xmlTextWriterStartComment:
711  * @writer:  the xmlTextWriterPtr
712  *
713  * Start an xml comment.
714  *
715  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
716  */
717 int
xmlTextWriterStartComment(xmlTextWriterPtr writer)718 xmlTextWriterStartComment(xmlTextWriterPtr writer)
719 {
720     int count;
721     int sum;
722     xmlLinkPtr lk;
723     xmlTextWriterStackEntry *p;
724 
725     if (writer == NULL) {
726         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
727                         "xmlTextWriterStartComment : invalid writer!\n");
728         return -1;
729     }
730 
731     sum = 0;
732     lk = xmlListFront(writer->nodes);
733     if (lk != 0) {
734         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
735         if (p != 0) {
736             switch (p->state) {
737                 case XML_TEXTWRITER_TEXT:
738                 case XML_TEXTWRITER_NONE:
739                     break;
740                 case XML_TEXTWRITER_NAME:
741                     /* Output namespace declarations */
742                     count = xmlTextWriterOutputNSDecl(writer);
743                     if (count < 0)
744                         return -1;
745                     sum += count;
746                     count = xmlOutputBufferWriteString(writer->out, ">");
747                     if (count < 0)
748                         return -1;
749                     sum += count;
750                     if (writer->indent) {
751                         count =
752                             xmlOutputBufferWriteString(writer->out, "\n");
753                         if (count < 0)
754                             return -1;
755                         sum += count;
756                     }
757                     p->state = XML_TEXTWRITER_TEXT;
758                     break;
759                 default:
760                     return -1;
761             }
762         }
763     }
764 
765     p = (xmlTextWriterStackEntry *)
766         xmlMalloc(sizeof(xmlTextWriterStackEntry));
767     if (p == 0) {
768         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
769                         "xmlTextWriterStartElement : out of memory!\n");
770         return -1;
771     }
772 
773     p->name = NULL;
774     p->state = XML_TEXTWRITER_COMMENT;
775 
776     xmlListPushFront(writer->nodes, p);
777 
778     if (writer->indent) {
779         count = xmlTextWriterWriteIndent(writer);
780         if (count < 0)
781             return -1;
782         sum += count;
783     }
784 
785     count = xmlOutputBufferWriteString(writer->out, "<!--");
786     if (count < 0)
787         return -1;
788     sum += count;
789 
790     return sum;
791 }
792 
793 /**
794  * xmlTextWriterEndComment:
795  * @writer:  the xmlTextWriterPtr
796  *
797  * End the current xml comment.
798  *
799  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
800  */
801 int
xmlTextWriterEndComment(xmlTextWriterPtr writer)802 xmlTextWriterEndComment(xmlTextWriterPtr writer)
803 {
804     int count;
805     int sum;
806     xmlLinkPtr lk;
807     xmlTextWriterStackEntry *p;
808 
809     if (writer == NULL) {
810         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
811                         "xmlTextWriterEndComment : invalid writer!\n");
812         return -1;
813     }
814 
815     lk = xmlListFront(writer->nodes);
816     if (lk == 0) {
817         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
818                         "xmlTextWriterEndComment : not allowed in this context!\n");
819         return -1;
820     }
821 
822     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
823     if (p == 0)
824         return -1;
825 
826     sum = 0;
827     switch (p->state) {
828         case XML_TEXTWRITER_COMMENT:
829             count = xmlOutputBufferWriteString(writer->out, "-->");
830             if (count < 0)
831                 return -1;
832             sum += count;
833             break;
834         default:
835             return -1;
836     }
837 
838     if (writer->indent) {
839         count = xmlOutputBufferWriteString(writer->out, "\n");
840         if (count < 0)
841             return -1;
842         sum += count;
843     }
844 
845     xmlListPopFront(writer->nodes);
846     return sum;
847 }
848 
849 /**
850  * xmlTextWriterWriteFormatComment:
851  * @writer:  the xmlTextWriterPtr
852  * @format:  format string (see printf)
853  * @...:  extra parameters for the format
854  *
855  * Write an xml comment.
856  *
857  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
858  */
859 int
xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,const char * format,...)860 xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
861                                 const char *format, ...)
862 {
863     int rc;
864     va_list ap;
865 
866     va_start(ap, format);
867 
868     rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
869 
870     va_end(ap);
871     return rc;
872 }
873 
874 /**
875  * xmlTextWriterWriteVFormatComment:
876  * @writer:  the xmlTextWriterPtr
877  * @format:  format string (see printf)
878  * @argptr:  pointer to the first member of the variable argument list.
879  *
880  * Write an xml comment.
881  *
882  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
883  */
884 int
xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,const char * format,va_list argptr)885 xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
886                                  const char *format, va_list argptr)
887 {
888     int rc;
889     xmlChar *buf;
890 
891     if (writer == NULL) {
892         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
893                         "xmlTextWriterWriteVFormatComment : invalid writer!\n");
894         return -1;
895     }
896 
897     buf = xmlTextWriterVSprintf(format, argptr);
898     if (buf == NULL)
899         return -1;
900 
901     rc = xmlTextWriterWriteComment(writer, buf);
902 
903     xmlFree(buf);
904     return rc;
905 }
906 
907 /**
908  * xmlTextWriterWriteComment:
909  * @writer:  the xmlTextWriterPtr
910  * @content:  comment string
911  *
912  * Write an xml comment.
913  *
914  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
915  */
916 int
xmlTextWriterWriteComment(xmlTextWriterPtr writer,const xmlChar * content)917 xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
918 {
919     int count;
920     int sum;
921 
922     sum = 0;
923     count = xmlTextWriterStartComment(writer);
924     if (count < 0)
925         return -1;
926     sum += count;
927     count = xmlTextWriterWriteString(writer, content);
928     if (count < 0)
929         return -1;
930     sum += count;
931     count = xmlTextWriterEndComment(writer);
932     if (count < 0)
933         return -1;
934     sum += count;
935 
936     return sum;
937 }
938 
939 /**
940  * xmlTextWriterStartElement:
941  * @writer:  the xmlTextWriterPtr
942  * @name:  element name
943  *
944  * Start an xml element.
945  *
946  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
947  */
948 int
xmlTextWriterStartElement(xmlTextWriterPtr writer,const xmlChar * name)949 xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
950 {
951     int count;
952     int sum;
953     xmlLinkPtr lk;
954     xmlTextWriterStackEntry *p;
955 
956     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
957         return -1;
958 
959     sum = 0;
960     lk = xmlListFront(writer->nodes);
961     if (lk != 0) {
962         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
963         if (p != 0) {
964             switch (p->state) {
965                 case XML_TEXTWRITER_PI:
966                 case XML_TEXTWRITER_PI_TEXT:
967                     return -1;
968                 case XML_TEXTWRITER_NONE:
969                     break;
970 				case XML_TEXTWRITER_ATTRIBUTE:
971 					count = xmlTextWriterEndAttribute(writer);
972 					if (count < 0)
973 						return -1;
974 					sum += count;
975 					/* fallthrough */
976                 case XML_TEXTWRITER_NAME:
977                     /* Output namespace declarations */
978                     count = xmlTextWriterOutputNSDecl(writer);
979                     if (count < 0)
980                         return -1;
981                     sum += count;
982                     count = xmlOutputBufferWriteString(writer->out, ">");
983                     if (count < 0)
984                         return -1;
985                     sum += count;
986                     if (writer->indent)
987                         count =
988                             xmlOutputBufferWriteString(writer->out, "\n");
989                     p->state = XML_TEXTWRITER_TEXT;
990                     break;
991                 default:
992                     break;
993             }
994         }
995     }
996 
997     p = (xmlTextWriterStackEntry *)
998         xmlMalloc(sizeof(xmlTextWriterStackEntry));
999     if (p == 0) {
1000         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1001                         "xmlTextWriterStartElement : out of memory!\n");
1002         return -1;
1003     }
1004 
1005     p->name = xmlStrdup(name);
1006     if (p->name == 0) {
1007         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1008                         "xmlTextWriterStartElement : out of memory!\n");
1009         xmlFree(p);
1010         return -1;
1011     }
1012     p->state = XML_TEXTWRITER_NAME;
1013 
1014     xmlListPushFront(writer->nodes, p);
1015 
1016     if (writer->indent) {
1017         count = xmlTextWriterWriteIndent(writer);
1018         sum += count;
1019     }
1020 
1021     count = xmlOutputBufferWriteString(writer->out, "<");
1022     if (count < 0)
1023         return -1;
1024     sum += count;
1025     count =
1026         xmlOutputBufferWriteString(writer->out, (const char *) p->name);
1027     if (count < 0)
1028         return -1;
1029     sum += count;
1030 
1031     return sum;
1032 }
1033 
1034 /**
1035  * xmlTextWriterStartElementNS:
1036  * @writer:  the xmlTextWriterPtr
1037  * @prefix:  namespace prefix or NULL
1038  * @name:  element local name
1039  * @namespaceURI:  namespace URI or NULL
1040  *
1041  * Start an xml element with namespace support.
1042  *
1043  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1044  */
1045 int
xmlTextWriterStartElementNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI)1046 xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1047                             const xmlChar * prefix, const xmlChar * name,
1048                             const xmlChar * namespaceURI)
1049 {
1050     int count;
1051     int sum;
1052     xmlChar *buf;
1053 
1054     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1055         return -1;
1056 
1057     buf = NULL;
1058     if (prefix != 0) {
1059         buf = xmlStrdup(prefix);
1060         buf = xmlStrcat(buf, BAD_CAST ":");
1061     }
1062     buf = xmlStrcat(buf, name);
1063 
1064     sum = 0;
1065     count = xmlTextWriterStartElement(writer, buf);
1066     xmlFree(buf);
1067     if (count < 0)
1068         return -1;
1069     sum += count;
1070 
1071     if (namespaceURI != 0) {
1072         xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1073         xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1074         if (p == 0) {
1075             xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1076                             "xmlTextWriterStartElementNS : out of memory!\n");
1077             return -1;
1078         }
1079 
1080         buf = xmlStrdup(BAD_CAST "xmlns");
1081         if (prefix != 0) {
1082             buf = xmlStrcat(buf, BAD_CAST ":");
1083             buf = xmlStrcat(buf, prefix);
1084         }
1085 
1086         p->prefix = buf;
1087         p->uri = xmlStrdup(namespaceURI);
1088         if (p->uri == 0) {
1089             xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1090                             "xmlTextWriterStartElementNS : out of memory!\n");
1091             xmlFree(p);
1092             return -1;
1093         }
1094         p->elem = xmlListFront(writer->nodes);
1095 
1096         xmlListPushFront(writer->nsstack, p);
1097     }
1098 
1099     return sum;
1100 }
1101 
1102 /**
1103  * xmlTextWriterEndElement:
1104  * @writer:  the xmlTextWriterPtr
1105  *
1106  * End the current xml element.
1107  *
1108  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1109  */
1110 int
xmlTextWriterEndElement(xmlTextWriterPtr writer)1111 xmlTextWriterEndElement(xmlTextWriterPtr writer)
1112 {
1113     int count;
1114     int sum;
1115     xmlLinkPtr lk;
1116     xmlTextWriterStackEntry *p;
1117 
1118     if (writer == NULL)
1119         return -1;
1120 
1121     lk = xmlListFront(writer->nodes);
1122     if (lk == 0) {
1123         xmlListDelete(writer->nsstack);
1124         writer->nsstack = NULL;
1125         return -1;
1126     }
1127 
1128     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1129     if (p == 0) {
1130         xmlListDelete(writer->nsstack);
1131         writer->nsstack = NULL;
1132         return -1;
1133     }
1134 
1135     sum = 0;
1136     switch (p->state) {
1137         case XML_TEXTWRITER_ATTRIBUTE:
1138             count = xmlTextWriterEndAttribute(writer);
1139             if (count < 0) {
1140                 xmlListDelete(writer->nsstack);
1141                 writer->nsstack = NULL;
1142                 return -1;
1143             }
1144             sum += count;
1145             /* fallthrough */
1146         case XML_TEXTWRITER_NAME:
1147             /* Output namespace declarations */
1148             count = xmlTextWriterOutputNSDecl(writer);
1149             if (count < 0)
1150                 return -1;
1151             sum += count;
1152 
1153             if (writer->indent) /* next element needs indent */
1154                 writer->doindent = 1;
1155             count = xmlOutputBufferWriteString(writer->out, "/>");
1156             if (count < 0)
1157                 return -1;
1158             sum += count;
1159             break;
1160         case XML_TEXTWRITER_TEXT:
1161             if ((writer->indent) && (writer->doindent)) {
1162                 count = xmlTextWriterWriteIndent(writer);
1163                 sum += count;
1164                 writer->doindent = 1;
1165             } else
1166                 writer->doindent = 1;
1167             count = xmlOutputBufferWriteString(writer->out, "</");
1168             if (count < 0)
1169                 return -1;
1170             sum += count;
1171             count = xmlOutputBufferWriteString(writer->out,
1172                                                (const char *) p->name);
1173             if (count < 0)
1174                 return -1;
1175             sum += count;
1176             count = xmlOutputBufferWriteString(writer->out, ">");
1177             if (count < 0)
1178                 return -1;
1179             sum += count;
1180             break;
1181         default:
1182             return -1;
1183     }
1184 
1185     if (writer->indent) {
1186         count = xmlOutputBufferWriteString(writer->out, "\n");
1187         sum += count;
1188     }
1189 
1190     xmlListPopFront(writer->nodes);
1191     return sum;
1192 }
1193 
1194 /**
1195  * xmlTextWriterFullEndElement:
1196  * @writer:  the xmlTextWriterPtr
1197  *
1198  * End the current xml element. Writes an end tag even if the element is empty
1199  *
1200  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1201  */
1202 int
xmlTextWriterFullEndElement(xmlTextWriterPtr writer)1203 xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1204 {
1205     int count;
1206     int sum;
1207     xmlLinkPtr lk;
1208     xmlTextWriterStackEntry *p;
1209 
1210     if (writer == NULL)
1211         return -1;
1212 
1213     lk = xmlListFront(writer->nodes);
1214     if (lk == 0)
1215         return -1;
1216 
1217     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1218     if (p == 0)
1219         return -1;
1220 
1221     sum = 0;
1222     switch (p->state) {
1223         case XML_TEXTWRITER_ATTRIBUTE:
1224             count = xmlTextWriterEndAttribute(writer);
1225             if (count < 0)
1226                 return -1;
1227             sum += count;
1228             /* fallthrough */
1229         case XML_TEXTWRITER_NAME:
1230             /* Output namespace declarations */
1231             count = xmlTextWriterOutputNSDecl(writer);
1232             if (count < 0)
1233                 return -1;
1234             sum += count;
1235 
1236             count = xmlOutputBufferWriteString(writer->out, ">");
1237             if (count < 0)
1238                 return -1;
1239             sum += count;
1240             if (writer->indent)
1241                 writer->doindent = 0;
1242             /* fallthrough */
1243         case XML_TEXTWRITER_TEXT:
1244             if ((writer->indent) && (writer->doindent)) {
1245                 count = xmlTextWriterWriteIndent(writer);
1246                 sum += count;
1247                 writer->doindent = 1;
1248             } else
1249                 writer->doindent = 1;
1250             count = xmlOutputBufferWriteString(writer->out, "</");
1251             if (count < 0)
1252                 return -1;
1253             sum += count;
1254             count = xmlOutputBufferWriteString(writer->out,
1255                                                (const char *) p->name);
1256             if (count < 0)
1257                 return -1;
1258             sum += count;
1259             count = xmlOutputBufferWriteString(writer->out, ">");
1260             if (count < 0)
1261                 return -1;
1262             sum += count;
1263             break;
1264         default:
1265             return -1;
1266     }
1267 
1268     if (writer->indent) {
1269         count = xmlOutputBufferWriteString(writer->out, "\n");
1270         sum += count;
1271     }
1272 
1273     xmlListPopFront(writer->nodes);
1274     return sum;
1275 }
1276 
1277 /**
1278  * xmlTextWriterWriteFormatRaw:
1279  * @writer:  the xmlTextWriterPtr
1280  * @format:  format string (see printf)
1281  * @...:  extra parameters for the format
1282  *
1283  * Write a formatted raw xml text.
1284  *
1285  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1286  */
1287 int
xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer,const char * format,...)1288 xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1289                             ...)
1290 {
1291     int rc;
1292     va_list ap;
1293 
1294     va_start(ap, format);
1295 
1296     rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1297 
1298     va_end(ap);
1299     return rc;
1300 }
1301 
1302 /**
1303  * xmlTextWriterWriteVFormatRaw:
1304  * @writer:  the xmlTextWriterPtr
1305  * @format:  format string (see printf)
1306  * @argptr:  pointer to the first member of the variable argument list.
1307  *
1308  * Write a formatted raw xml text.
1309  *
1310  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1311  */
1312 int
xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer,const char * format,va_list argptr)1313 xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1314                              va_list argptr)
1315 {
1316     int rc;
1317     xmlChar *buf;
1318 
1319     if (writer == NULL)
1320         return -1;
1321 
1322     buf = xmlTextWriterVSprintf(format, argptr);
1323     if (buf == NULL)
1324         return -1;
1325 
1326     rc = xmlTextWriterWriteRaw(writer, buf);
1327 
1328     xmlFree(buf);
1329     return rc;
1330 }
1331 
1332 /**
1333  * xmlTextWriterWriteRawLen:
1334  * @writer:  the xmlTextWriterPtr
1335  * @content:  text string
1336  * @len:  length of the text string
1337  *
1338  * Write an xml text.
1339  * TODO: what about entities and special chars??
1340  *
1341  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1342  */
1343 int
xmlTextWriterWriteRawLen(xmlTextWriterPtr writer,const xmlChar * content,int len)1344 xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1345                          int len)
1346 {
1347     int count;
1348     int sum;
1349     xmlLinkPtr lk;
1350     xmlTextWriterStackEntry *p;
1351 
1352     if (writer == NULL) {
1353         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
1354                         "xmlTextWriterWriteRawLen : invalid writer!\n");
1355         return -1;
1356     }
1357 
1358     if ((content == NULL) || (len < 0)) {
1359         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
1360                         "xmlTextWriterWriteRawLen : invalid content!\n");
1361         return -1;
1362     }
1363 
1364     sum = 0;
1365     lk = xmlListFront(writer->nodes);
1366     if (lk != 0) {
1367         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1368         count = xmlTextWriterHandleStateDependencies(writer, p);
1369         if (count < 0)
1370             return -1;
1371         sum += count;
1372     }
1373 
1374     if (writer->indent)
1375         writer->doindent = 0;
1376 
1377     if (content != NULL) {
1378         count =
1379             xmlOutputBufferWrite(writer->out, len, (const char *) content);
1380         if (count < 0)
1381             return -1;
1382         sum += count;
1383     }
1384 
1385     return sum;
1386 }
1387 
1388 /**
1389  * xmlTextWriterWriteRaw:
1390  * @writer:  the xmlTextWriterPtr
1391  * @content:  text string
1392  *
1393  * Write a raw xml text.
1394  *
1395  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1396  */
1397 int
xmlTextWriterWriteRaw(xmlTextWriterPtr writer,const xmlChar * content)1398 xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1399 {
1400     return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1401 }
1402 
1403 /**
1404  * xmlTextWriterWriteFormatString:
1405  * @writer:  the xmlTextWriterPtr
1406  * @format:  format string (see printf)
1407  * @...:  extra parameters for the format
1408  *
1409  * Write a formatted xml text.
1410  *
1411  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1412  */
1413 int
xmlTextWriterWriteFormatString(xmlTextWriterPtr writer,const char * format,...)1414 xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1415                                ...)
1416 {
1417     int rc;
1418     va_list ap;
1419 
1420     if ((writer == NULL) || (format == NULL))
1421         return -1;
1422 
1423     va_start(ap, format);
1424 
1425     rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1426 
1427     va_end(ap);
1428     return rc;
1429 }
1430 
1431 /**
1432  * xmlTextWriterWriteVFormatString:
1433  * @writer:  the xmlTextWriterPtr
1434  * @format:  format string (see printf)
1435  * @argptr:  pointer to the first member of the variable argument list.
1436  *
1437  * Write a formatted xml text.
1438  *
1439  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1440  */
1441 int
xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,const char * format,va_list argptr)1442 xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1443                                 const char *format, va_list argptr)
1444 {
1445     int rc;
1446     xmlChar *buf;
1447 
1448     if ((writer == NULL) || (format == NULL))
1449         return -1;
1450 
1451     buf = xmlTextWriterVSprintf(format, argptr);
1452     if (buf == NULL)
1453         return -1;
1454 
1455     rc = xmlTextWriterWriteString(writer, buf);
1456 
1457     xmlFree(buf);
1458     return rc;
1459 }
1460 
1461 /**
1462  * xmlTextWriterWriteString:
1463  * @writer:  the xmlTextWriterPtr
1464  * @content:  text string
1465  *
1466  * Write an xml text.
1467  *
1468  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1469  */
1470 int
xmlTextWriterWriteString(xmlTextWriterPtr writer,const xmlChar * content)1471 xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1472 {
1473     int count;
1474     int sum;
1475     xmlLinkPtr lk;
1476     xmlTextWriterStackEntry *p;
1477     xmlChar *buf;
1478 
1479     if ((writer == NULL) || (content == NULL))
1480         return -1;
1481 
1482     sum = 0;
1483     buf = (xmlChar *) content;
1484     lk = xmlListFront(writer->nodes);
1485     if (lk != 0) {
1486         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1487         if (p != 0) {
1488             switch (p->state) {
1489                 case XML_TEXTWRITER_NAME:
1490                 case XML_TEXTWRITER_TEXT:
1491 #if 0
1492                     buf = NULL;
1493 		    xmlOutputBufferWriteEscape(writer->out, content, NULL);
1494 #endif
1495                     buf = xmlEncodeSpecialChars(NULL, content);
1496                     break;
1497                 case XML_TEXTWRITER_ATTRIBUTE:
1498                     buf = NULL;
1499                     xmlBufAttrSerializeTxtContent(writer->out->buffer,
1500                                                   writer->doc, NULL, content);
1501                     break;
1502 		default:
1503 		    break;
1504             }
1505         }
1506     }
1507 
1508     if (buf != NULL) {
1509         count = xmlTextWriterWriteRaw(writer, buf);
1510 
1511         if (buf != content)     /* buf was allocated by us, so free it */
1512             xmlFree(buf);
1513 
1514         if (count < 0)
1515             return -1;
1516         sum += count;
1517     }
1518 
1519     return sum;
1520 }
1521 
1522 /**
1523  * xmlOutputBufferWriteBase64:
1524  * @out: the xmlOutputBufferPtr
1525  * @data:   binary data
1526  * @len:  the number of bytes to encode
1527  *
1528  * Write base64 encoded data to an xmlOutputBuffer.
1529  * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1530  *
1531  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1532  */
1533 static int
xmlOutputBufferWriteBase64(xmlOutputBufferPtr out,int len,const unsigned char * data)1534 xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1535                            const unsigned char *data)
1536 {
1537     static const unsigned char dtable[64] =
1538             {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1539 	     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1540 	     'a','b','c','d','e','f','g','h','i','j','k','l','m',
1541 	     'n','o','p','q','r','s','t','u','v','w','x','y','z',
1542 	     '0','1','2','3','4','5','6','7','8','9','+','/'};
1543 
1544     int i;
1545     int linelen;
1546     int count;
1547     int sum;
1548 
1549     if ((out == NULL) || (len < 0) || (data == NULL))
1550         return(-1);
1551 
1552     linelen = 0;
1553     sum = 0;
1554 
1555     i = 0;
1556     while (1) {
1557         unsigned char igroup[3];
1558         unsigned char ogroup[4];
1559         int c;
1560         int n;
1561 
1562         igroup[0] = igroup[1] = igroup[2] = 0;
1563         for (n = 0; n < 3 && i < len; n++, i++) {
1564             c = data[i];
1565             igroup[n] = (unsigned char) c;
1566         }
1567 
1568         if (n > 0) {
1569             ogroup[0] = dtable[igroup[0] >> 2];
1570             ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1571             ogroup[2] =
1572                 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1573             ogroup[3] = dtable[igroup[2] & 0x3F];
1574 
1575             if (n < 3) {
1576                 ogroup[3] = '=';
1577                 if (n < 2) {
1578                     ogroup[2] = '=';
1579                 }
1580             }
1581 
1582             if (linelen >= B64LINELEN) {
1583                 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1584                 if (count == -1)
1585                     return -1;
1586                 sum += count;
1587                 linelen = 0;
1588             }
1589             count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1590             if (count == -1)
1591                 return -1;
1592             sum += count;
1593 
1594             linelen += 4;
1595         }
1596 
1597         if (i >= len)
1598             break;
1599     }
1600 
1601     return sum;
1602 }
1603 
1604 /**
1605  * xmlTextWriterWriteBase64:
1606  * @writer: the xmlTextWriterPtr
1607  * @data:   binary data
1608  * @start:  the position within the data of the first byte to encode
1609  * @len:  the number of bytes to encode
1610  *
1611  * Write an base64 encoded xml text.
1612  *
1613  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1614  */
1615 int
xmlTextWriterWriteBase64(xmlTextWriterPtr writer,const char * data,int start,int len)1616 xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
1617                          int start, int len)
1618 {
1619     int count;
1620     int sum;
1621     xmlLinkPtr lk;
1622     xmlTextWriterStackEntry *p;
1623 
1624     if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
1625         return -1;
1626 
1627     sum = 0;
1628     lk = xmlListFront(writer->nodes);
1629     if (lk != 0) {
1630         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1631         if (p != 0) {
1632             count = xmlTextWriterHandleStateDependencies(writer, p);
1633             if (count < 0)
1634                 return -1;
1635             sum += count;
1636         }
1637     }
1638 
1639     if (writer->indent)
1640         writer->doindent = 0;
1641 
1642     count =
1643         xmlOutputBufferWriteBase64(writer->out, len,
1644                                    (unsigned char *) data + start);
1645     if (count < 0)
1646         return -1;
1647     sum += count;
1648 
1649     return sum;
1650 }
1651 
1652 /**
1653  * xmlOutputBufferWriteBinHex:
1654  * @out: the xmlOutputBufferPtr
1655  * @data:   binary data
1656  * @len:  the number of bytes to encode
1657  *
1658  * Write hqx encoded data to an xmlOutputBuffer.
1659  * ::todo
1660  *
1661  * Returns the bytes written (may be 0 because of buffering)
1662  * or -1 in case of error
1663  */
1664 static int
xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,int len,const unsigned char * data)1665 xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1666                            int len, const unsigned char *data)
1667 {
1668     int count;
1669     int sum;
1670     static const char hex[16] =
1671 	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1672     int i;
1673 
1674     if ((out == NULL) || (data == NULL) || (len < 0)) {
1675         return -1;
1676     }
1677 
1678     sum = 0;
1679     for (i = 0; i < len; i++) {
1680         count =
1681             xmlOutputBufferWrite(out, 1,
1682                                  (const char *) &hex[data[i] >> 4]);
1683         if (count == -1)
1684             return -1;
1685         sum += count;
1686         count =
1687             xmlOutputBufferWrite(out, 1,
1688                                  (const char *) &hex[data[i] & 0xF]);
1689         if (count == -1)
1690             return -1;
1691         sum += count;
1692     }
1693 
1694     return sum;
1695 }
1696 
1697 /**
1698  * xmlTextWriterWriteBinHex:
1699  * @writer: the xmlTextWriterPtr
1700  * @data:   binary data
1701  * @start:  the position within the data of the first byte to encode
1702  * @len:  the number of bytes to encode
1703  *
1704  * Write a BinHex encoded xml text.
1705  *
1706  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1707  */
1708 int
xmlTextWriterWriteBinHex(xmlTextWriterPtr writer,const char * data,int start,int len)1709 xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
1710                          int start, int len)
1711 {
1712     int count;
1713     int sum;
1714     xmlLinkPtr lk;
1715     xmlTextWriterStackEntry *p;
1716 
1717     if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
1718         return -1;
1719 
1720     sum = 0;
1721     lk = xmlListFront(writer->nodes);
1722     if (lk != 0) {
1723         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1724         if (p != 0) {
1725             count = xmlTextWriterHandleStateDependencies(writer, p);
1726             if (count < 0)
1727                 return -1;
1728             sum += count;
1729         }
1730     }
1731 
1732     if (writer->indent)
1733         writer->doindent = 0;
1734 
1735     count =
1736         xmlOutputBufferWriteBinHex(writer->out, len,
1737                                    (unsigned char *) data + start);
1738     if (count < 0)
1739         return -1;
1740     sum += count;
1741 
1742     return sum;
1743 }
1744 
1745 /**
1746  * xmlTextWriterStartAttribute:
1747  * @writer:  the xmlTextWriterPtr
1748  * @name:  element name
1749  *
1750  * Start an xml attribute.
1751  *
1752  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1753  */
1754 int
xmlTextWriterStartAttribute(xmlTextWriterPtr writer,const xmlChar * name)1755 xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1756 {
1757     int count;
1758     int sum;
1759     xmlLinkPtr lk;
1760     xmlTextWriterStackEntry *p;
1761 
1762     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1763         return -1;
1764 
1765     sum = 0;
1766     lk = xmlListFront(writer->nodes);
1767     if (lk == 0)
1768         return -1;
1769 
1770     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1771     if (p == 0)
1772         return -1;
1773 
1774     switch (p->state) {
1775         case XML_TEXTWRITER_ATTRIBUTE:
1776             count = xmlTextWriterEndAttribute(writer);
1777             if (count < 0)
1778                 return -1;
1779             sum += count;
1780             /* fallthrough */
1781         case XML_TEXTWRITER_NAME:
1782             count = xmlOutputBufferWriteString(writer->out, " ");
1783             if (count < 0)
1784                 return -1;
1785             sum += count;
1786             count =
1787                 xmlOutputBufferWriteString(writer->out,
1788                                            (const char *) name);
1789             if (count < 0)
1790                 return -1;
1791             sum += count;
1792             count = xmlOutputBufferWriteString(writer->out, "=");
1793             if (count < 0)
1794                 return -1;
1795             sum += count;
1796             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1797             if (count < 0)
1798                 return -1;
1799             sum += count;
1800             p->state = XML_TEXTWRITER_ATTRIBUTE;
1801             break;
1802         default:
1803             return -1;
1804     }
1805 
1806     return sum;
1807 }
1808 
1809 /**
1810  * xmlTextWriterStartAttributeNS:
1811  * @writer:  the xmlTextWriterPtr
1812  * @prefix:  namespace prefix or NULL
1813  * @name:  element local name
1814  * @namespaceURI:  namespace URI or NULL
1815  *
1816  * Start an xml attribute with namespace support.
1817  *
1818  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1819  */
1820 int
xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI)1821 xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1822                               const xmlChar * prefix, const xmlChar * name,
1823                               const xmlChar * namespaceURI)
1824 {
1825     int count;
1826     int sum;
1827     xmlChar *buf;
1828     xmlTextWriterNsStackEntry *p;
1829 
1830     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1831         return -1;
1832 
1833     /* Handle namespace first in case of error */
1834     if (namespaceURI != 0) {
1835         xmlTextWriterNsStackEntry nsentry, *curns;
1836 
1837         buf = xmlStrdup(BAD_CAST "xmlns");
1838         if (prefix != 0) {
1839             buf = xmlStrcat(buf, BAD_CAST ":");
1840             buf = xmlStrcat(buf, prefix);
1841         }
1842 
1843         nsentry.prefix = buf;
1844         nsentry.uri = (xmlChar *)namespaceURI;
1845         nsentry.elem = xmlListFront(writer->nodes);
1846 
1847         curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1848                                                            (void *)&nsentry);
1849         if ((curns != NULL)) {
1850             xmlFree(buf);
1851             if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1852                 /* Namespace already defined on element skip */
1853                 buf = NULL;
1854             } else {
1855                 /* Prefix mismatch so error out */
1856                 return -1;
1857             }
1858         }
1859 
1860         /* Do not add namespace decl to list - it is already there */
1861         if (buf != NULL) {
1862             p = (xmlTextWriterNsStackEntry *)
1863                 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1864             if (p == 0) {
1865                 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1866 								        "xmlTextWriterStartAttributeNS : out of memory!\n");
1867                 return -1;
1868             }
1869 
1870             p->prefix = buf;
1871             p->uri = xmlStrdup(namespaceURI);
1872             if (p->uri == 0) {
1873                 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1874                         "xmlTextWriterStartAttributeNS : out of memory!\n");
1875                 xmlFree(p);
1876                 return -1;
1877             }
1878             p->elem = xmlListFront(writer->nodes);
1879 
1880             xmlListPushFront(writer->nsstack, p);
1881         }
1882     }
1883 
1884     buf = NULL;
1885     if (prefix != 0) {
1886         buf = xmlStrdup(prefix);
1887         buf = xmlStrcat(buf, BAD_CAST ":");
1888     }
1889     buf = xmlStrcat(buf, name);
1890 
1891     sum = 0;
1892     count = xmlTextWriterStartAttribute(writer, buf);
1893     xmlFree(buf);
1894     if (count < 0)
1895         return -1;
1896     sum += count;
1897 
1898     return sum;
1899 }
1900 
1901 /**
1902  * xmlTextWriterEndAttribute:
1903  * @writer:  the xmlTextWriterPtr
1904  *
1905  * End the current xml element.
1906  *
1907  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1908  */
1909 int
xmlTextWriterEndAttribute(xmlTextWriterPtr writer)1910 xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1911 {
1912     int count;
1913     int sum;
1914     xmlLinkPtr lk;
1915     xmlTextWriterStackEntry *p;
1916 
1917     if (writer == NULL)
1918         return -1;
1919 
1920     lk = xmlListFront(writer->nodes);
1921     if (lk == 0) {
1922         return -1;
1923     }
1924 
1925     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1926     if (p == 0) {
1927         return -1;
1928     }
1929 
1930     sum = 0;
1931     switch (p->state) {
1932         case XML_TEXTWRITER_ATTRIBUTE:
1933             p->state = XML_TEXTWRITER_NAME;
1934 
1935             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1936             if (count < 0) {
1937                 return -1;
1938             }
1939             sum += count;
1940             break;
1941         default:
1942             return -1;
1943     }
1944 
1945     return sum;
1946 }
1947 
1948 /**
1949  * xmlTextWriterWriteFormatAttribute:
1950  * @writer:  the xmlTextWriterPtr
1951  * @name:  attribute name
1952  * @format:  format string (see printf)
1953  * @...:  extra parameters for the format
1954  *
1955  * Write a formatted xml attribute.
1956  *
1957  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1958  */
1959 int
xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,const xmlChar * name,const char * format,...)1960 xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1961                                   const xmlChar * name, const char *format,
1962                                   ...)
1963 {
1964     int rc;
1965     va_list ap;
1966 
1967     va_start(ap, format);
1968 
1969     rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1970 
1971     va_end(ap);
1972     return rc;
1973 }
1974 
1975 /**
1976  * xmlTextWriterWriteVFormatAttribute:
1977  * @writer:  the xmlTextWriterPtr
1978  * @name:  attribute name
1979  * @format:  format string (see printf)
1980  * @argptr:  pointer to the first member of the variable argument list.
1981  *
1982  * Write a formatted xml attribute.
1983  *
1984  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1985  */
1986 int
xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,const xmlChar * name,const char * format,va_list argptr)1987 xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1988                                    const xmlChar * name,
1989                                    const char *format, va_list argptr)
1990 {
1991     int rc;
1992     xmlChar *buf;
1993 
1994     if (writer == NULL)
1995         return -1;
1996 
1997     buf = xmlTextWriterVSprintf(format, argptr);
1998     if (buf == NULL)
1999         return -1;
2000 
2001     rc = xmlTextWriterWriteAttribute(writer, name, buf);
2002 
2003     xmlFree(buf);
2004     return rc;
2005 }
2006 
2007 /**
2008  * xmlTextWriterWriteAttribute:
2009  * @writer:  the xmlTextWriterPtr
2010  * @name:  attribute name
2011  * @content:  attribute content
2012  *
2013  * Write an xml attribute.
2014  *
2015  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2016  */
2017 int
xmlTextWriterWriteAttribute(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * content)2018 xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2019                             const xmlChar * content)
2020 {
2021     int count;
2022     int sum;
2023 
2024     sum = 0;
2025     count = xmlTextWriterStartAttribute(writer, name);
2026     if (count < 0)
2027         return -1;
2028     sum += count;
2029     count = xmlTextWriterWriteString(writer, content);
2030     if (count < 0)
2031         return -1;
2032     sum += count;
2033     count = xmlTextWriterEndAttribute(writer);
2034     if (count < 0)
2035         return -1;
2036     sum += count;
2037 
2038     return sum;
2039 }
2040 
2041 /**
2042  * xmlTextWriterWriteFormatAttributeNS:
2043  * @writer:  the xmlTextWriterPtr
2044  * @prefix:  namespace prefix
2045  * @name:  attribute local name
2046  * @namespaceURI:  namespace URI
2047  * @format:  format string (see printf)
2048  * @...:  extra parameters for the format
2049  *
2050  * Write a formatted xml attribute.with namespace support
2051  *
2052  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2053  */
2054 int
xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI,const char * format,...)2055 xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2056                                     const xmlChar * prefix,
2057                                     const xmlChar * name,
2058                                     const xmlChar * namespaceURI,
2059                                     const char *format, ...)
2060 {
2061     int rc;
2062     va_list ap;
2063 
2064     va_start(ap, format);
2065 
2066     rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2067                                               namespaceURI, format, ap);
2068 
2069     va_end(ap);
2070     return rc;
2071 }
2072 
2073 /**
2074  * xmlTextWriterWriteVFormatAttributeNS:
2075  * @writer:  the xmlTextWriterPtr
2076  * @prefix:  namespace prefix
2077  * @name:  attribute local name
2078  * @namespaceURI:  namespace URI
2079  * @format:  format string (see printf)
2080  * @argptr:  pointer to the first member of the variable argument list.
2081  *
2082  * Write a formatted xml attribute.with namespace support
2083  *
2084  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2085  */
2086 int
xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI,const char * format,va_list argptr)2087 xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2088                                      const xmlChar * prefix,
2089                                      const xmlChar * name,
2090                                      const xmlChar * namespaceURI,
2091                                      const char *format, va_list argptr)
2092 {
2093     int rc;
2094     xmlChar *buf;
2095 
2096     if (writer == NULL)
2097         return -1;
2098 
2099     buf = xmlTextWriterVSprintf(format, argptr);
2100     if (buf == NULL)
2101         return -1;
2102 
2103     rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2104                                        buf);
2105 
2106     xmlFree(buf);
2107     return rc;
2108 }
2109 
2110 /**
2111  * xmlTextWriterWriteAttributeNS:
2112  * @writer:  the xmlTextWriterPtr
2113  * @prefix:  namespace prefix
2114  * @name:  attribute local name
2115  * @namespaceURI:  namespace URI
2116  * @content:  attribute content
2117  *
2118  * Write an xml attribute.
2119  *
2120  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2121  */
2122 int
xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI,const xmlChar * content)2123 xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2124                               const xmlChar * prefix, const xmlChar * name,
2125                               const xmlChar * namespaceURI,
2126                               const xmlChar * content)
2127 {
2128     int count;
2129     int sum;
2130 
2131     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2132         return -1;
2133 
2134     sum = 0;
2135     count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2136     if (count < 0)
2137         return -1;
2138     sum += count;
2139     count = xmlTextWriterWriteString(writer, content);
2140     if (count < 0)
2141         return -1;
2142     sum += count;
2143     count = xmlTextWriterEndAttribute(writer);
2144     if (count < 0)
2145         return -1;
2146     sum += count;
2147 
2148     return sum;
2149 }
2150 
2151 /**
2152  * xmlTextWriterWriteFormatElement:
2153  * @writer:  the xmlTextWriterPtr
2154  * @name:  element name
2155  * @format:  format string (see printf)
2156  * @...:  extra parameters for the format
2157  *
2158  * Write a formatted xml element.
2159  *
2160  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2161  */
2162 int
xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,const xmlChar * name,const char * format,...)2163 xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2164                                 const xmlChar * name, const char *format,
2165                                 ...)
2166 {
2167     int rc;
2168     va_list ap;
2169 
2170     va_start(ap, format);
2171 
2172     rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2173 
2174     va_end(ap);
2175     return rc;
2176 }
2177 
2178 /**
2179  * xmlTextWriterWriteVFormatElement:
2180  * @writer:  the xmlTextWriterPtr
2181  * @name:  element name
2182  * @format:  format string (see printf)
2183  * @argptr:  pointer to the first member of the variable argument list.
2184  *
2185  * Write a formatted xml element.
2186  *
2187  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2188  */
2189 int
xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,const xmlChar * name,const char * format,va_list argptr)2190 xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2191                                  const xmlChar * name, const char *format,
2192                                  va_list argptr)
2193 {
2194     int rc;
2195     xmlChar *buf;
2196 
2197     if (writer == NULL)
2198         return -1;
2199 
2200     buf = xmlTextWriterVSprintf(format, argptr);
2201     if (buf == NULL)
2202         return -1;
2203 
2204     rc = xmlTextWriterWriteElement(writer, name, buf);
2205 
2206     xmlFree(buf);
2207     return rc;
2208 }
2209 
2210 /**
2211  * xmlTextWriterWriteElement:
2212  * @writer:  the xmlTextWriterPtr
2213  * @name:  element name
2214  * @content:  element content
2215  *
2216  * Write an xml element.
2217  *
2218  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2219  */
2220 int
xmlTextWriterWriteElement(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * content)2221 xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2222                           const xmlChar * content)
2223 {
2224     int count;
2225     int sum;
2226 
2227     sum = 0;
2228     count = xmlTextWriterStartElement(writer, name);
2229     if (count == -1)
2230         return -1;
2231     sum += count;
2232     if (content != NULL) {
2233 	count = xmlTextWriterWriteString(writer, content);
2234 	if (count == -1)
2235 	    return -1;
2236 	sum += count;
2237     }
2238     count = xmlTextWriterEndElement(writer);
2239     if (count == -1)
2240         return -1;
2241     sum += count;
2242 
2243     return sum;
2244 }
2245 
2246 /**
2247  * xmlTextWriterWriteFormatElementNS:
2248  * @writer:  the xmlTextWriterPtr
2249  * @prefix:  namespace prefix
2250  * @name:  element local name
2251  * @namespaceURI:  namespace URI
2252  * @format:  format string (see printf)
2253  * @...:  extra parameters for the format
2254  *
2255  * Write a formatted xml element with namespace support.
2256  *
2257  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2258  */
2259 int
xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI,const char * format,...)2260 xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2261                                   const xmlChar * prefix,
2262                                   const xmlChar * name,
2263                                   const xmlChar * namespaceURI,
2264                                   const char *format, ...)
2265 {
2266     int rc;
2267     va_list ap;
2268 
2269     va_start(ap, format);
2270 
2271     rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2272                                             namespaceURI, format, ap);
2273 
2274     va_end(ap);
2275     return rc;
2276 }
2277 
2278 /**
2279  * xmlTextWriterWriteVFormatElementNS:
2280  * @writer:  the xmlTextWriterPtr
2281  * @prefix:  namespace prefix
2282  * @name:  element local name
2283  * @namespaceURI:  namespace URI
2284  * @format:  format string (see printf)
2285  * @argptr:  pointer to the first member of the variable argument list.
2286  *
2287  * Write a formatted xml element with namespace support.
2288  *
2289  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2290  */
2291 int
xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI,const char * format,va_list argptr)2292 xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2293                                    const xmlChar * prefix,
2294                                    const xmlChar * name,
2295                                    const xmlChar * namespaceURI,
2296                                    const char *format, va_list argptr)
2297 {
2298     int rc;
2299     xmlChar *buf;
2300 
2301     if (writer == NULL)
2302         return -1;
2303 
2304     buf = xmlTextWriterVSprintf(format, argptr);
2305     if (buf == NULL)
2306         return -1;
2307 
2308     rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2309                                      buf);
2310 
2311     xmlFree(buf);
2312     return rc;
2313 }
2314 
2315 /**
2316  * xmlTextWriterWriteElementNS:
2317  * @writer:  the xmlTextWriterPtr
2318  * @prefix:  namespace prefix
2319  * @name:  element local name
2320  * @namespaceURI:  namespace URI
2321  * @content:  element content
2322  *
2323  * Write an xml element with namespace support.
2324  *
2325  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2326  */
2327 int
xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,const xmlChar * prefix,const xmlChar * name,const xmlChar * namespaceURI,const xmlChar * content)2328 xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2329                             const xmlChar * prefix, const xmlChar * name,
2330                             const xmlChar * namespaceURI,
2331                             const xmlChar * content)
2332 {
2333     int count;
2334     int sum;
2335 
2336     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2337         return -1;
2338 
2339     sum = 0;
2340     count =
2341         xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2342     if (count < 0)
2343         return -1;
2344     sum += count;
2345     count = xmlTextWriterWriteString(writer, content);
2346     if (count == -1)
2347         return -1;
2348     sum += count;
2349     count = xmlTextWriterEndElement(writer);
2350     if (count == -1)
2351         return -1;
2352     sum += count;
2353 
2354     return sum;
2355 }
2356 
2357 /**
2358  * xmlTextWriterStartPI:
2359  * @writer:  the xmlTextWriterPtr
2360  * @target:  PI target
2361  *
2362  * Start an xml PI.
2363  *
2364  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2365  */
2366 int
xmlTextWriterStartPI(xmlTextWriterPtr writer,const xmlChar * target)2367 xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2368 {
2369     int count;
2370     int sum;
2371     xmlLinkPtr lk;
2372     xmlTextWriterStackEntry *p;
2373 
2374     if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2375         return -1;
2376 
2377     if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
2378         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2379                         "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2380         return -1;
2381     }
2382 
2383     sum = 0;
2384     lk = xmlListFront(writer->nodes);
2385     if (lk != 0) {
2386         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2387         if (p != 0) {
2388             switch (p->state) {
2389                 case XML_TEXTWRITER_ATTRIBUTE:
2390                     count = xmlTextWriterEndAttribute(writer);
2391                     if (count < 0)
2392                         return -1;
2393                     sum += count;
2394                     /* fallthrough */
2395                 case XML_TEXTWRITER_NAME:
2396                     /* Output namespace declarations */
2397                     count = xmlTextWriterOutputNSDecl(writer);
2398                     if (count < 0)
2399                         return -1;
2400                     sum += count;
2401                     count = xmlOutputBufferWriteString(writer->out, ">");
2402                     if (count < 0)
2403                         return -1;
2404                     sum += count;
2405                     p->state = XML_TEXTWRITER_TEXT;
2406                     break;
2407                 case XML_TEXTWRITER_NONE:
2408                 case XML_TEXTWRITER_TEXT:
2409                 case XML_TEXTWRITER_DTD:
2410                     break;
2411                 case XML_TEXTWRITER_PI:
2412                 case XML_TEXTWRITER_PI_TEXT:
2413                     xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2414                                     "xmlTextWriterStartPI : nested PI!\n");
2415                     return -1;
2416                 default:
2417                     return -1;
2418             }
2419         }
2420     }
2421 
2422     p = (xmlTextWriterStackEntry *)
2423         xmlMalloc(sizeof(xmlTextWriterStackEntry));
2424     if (p == 0) {
2425         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2426                         "xmlTextWriterStartPI : out of memory!\n");
2427         return -1;
2428     }
2429 
2430     p->name = xmlStrdup(target);
2431     if (p->name == 0) {
2432         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2433                         "xmlTextWriterStartPI : out of memory!\n");
2434         xmlFree(p);
2435         return -1;
2436     }
2437     p->state = XML_TEXTWRITER_PI;
2438 
2439     xmlListPushFront(writer->nodes, p);
2440 
2441     count = xmlOutputBufferWriteString(writer->out, "<?");
2442     if (count < 0)
2443         return -1;
2444     sum += count;
2445     count =
2446         xmlOutputBufferWriteString(writer->out, (const char *) p->name);
2447     if (count < 0)
2448         return -1;
2449     sum += count;
2450 
2451     return sum;
2452 }
2453 
2454 /**
2455  * xmlTextWriterEndPI:
2456  * @writer:  the xmlTextWriterPtr
2457  *
2458  * End the current xml PI.
2459  *
2460  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2461  */
2462 int
xmlTextWriterEndPI(xmlTextWriterPtr writer)2463 xmlTextWriterEndPI(xmlTextWriterPtr writer)
2464 {
2465     int count;
2466     int sum;
2467     xmlLinkPtr lk;
2468     xmlTextWriterStackEntry *p;
2469 
2470     if (writer == NULL)
2471         return -1;
2472 
2473     lk = xmlListFront(writer->nodes);
2474     if (lk == 0)
2475         return 0;
2476 
2477     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2478     if (p == 0)
2479         return 0;
2480 
2481     sum = 0;
2482     switch (p->state) {
2483         case XML_TEXTWRITER_PI:
2484         case XML_TEXTWRITER_PI_TEXT:
2485             count = xmlOutputBufferWriteString(writer->out, "?>");
2486             if (count < 0)
2487                 return -1;
2488             sum += count;
2489             break;
2490         default:
2491             return -1;
2492     }
2493 
2494     if (writer->indent) {
2495         count = xmlOutputBufferWriteString(writer->out, "\n");
2496 	if (count < 0)
2497 	return -1;
2498         sum += count;
2499     }
2500 
2501     xmlListPopFront(writer->nodes);
2502     return sum;
2503 }
2504 
2505 /**
2506  * xmlTextWriterWriteFormatPI:
2507  * @writer:  the xmlTextWriterPtr
2508  * @target:  PI target
2509  * @format:  format string (see printf)
2510  * @...:  extra parameters for the format
2511  *
2512  * Write a formatted PI.
2513  *
2514  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2515  */
2516 int
xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer,const xmlChar * target,const char * format,...)2517 xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2518                            const char *format, ...)
2519 {
2520     int rc;
2521     va_list ap;
2522 
2523     va_start(ap, format);
2524 
2525     rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2526 
2527     va_end(ap);
2528     return rc;
2529 }
2530 
2531 /**
2532  * xmlTextWriterWriteVFormatPI:
2533  * @writer:  the xmlTextWriterPtr
2534  * @target:  PI target
2535  * @format:  format string (see printf)
2536  * @argptr:  pointer to the first member of the variable argument list.
2537  *
2538  * Write a formatted xml PI.
2539  *
2540  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2541  */
2542 int
xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,const xmlChar * target,const char * format,va_list argptr)2543 xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2544                             const xmlChar * target, const char *format,
2545                             va_list argptr)
2546 {
2547     int rc;
2548     xmlChar *buf;
2549 
2550     if (writer == NULL)
2551         return -1;
2552 
2553     buf = xmlTextWriterVSprintf(format, argptr);
2554     if (buf == NULL)
2555         return -1;
2556 
2557     rc = xmlTextWriterWritePI(writer, target, buf);
2558 
2559     xmlFree(buf);
2560     return rc;
2561 }
2562 
2563 /**
2564  * xmlTextWriterWritePI:
2565  * @writer:  the xmlTextWriterPtr
2566  * @target:  PI target
2567  * @content:  PI content
2568  *
2569  * Write an xml PI.
2570  *
2571  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2572  */
2573 int
xmlTextWriterWritePI(xmlTextWriterPtr writer,const xmlChar * target,const xmlChar * content)2574 xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2575                      const xmlChar * content)
2576 {
2577     int count;
2578     int sum;
2579 
2580     sum = 0;
2581     count = xmlTextWriterStartPI(writer, target);
2582     if (count == -1)
2583         return -1;
2584     sum += count;
2585     if (content != 0) {
2586         count = xmlTextWriterWriteString(writer, content);
2587         if (count == -1)
2588             return -1;
2589         sum += count;
2590     }
2591     count = xmlTextWriterEndPI(writer);
2592     if (count == -1)
2593         return -1;
2594     sum += count;
2595 
2596     return sum;
2597 }
2598 
2599 /**
2600  * xmlTextWriterStartCDATA:
2601  * @writer:  the xmlTextWriterPtr
2602  *
2603  * Start an xml CDATA section.
2604  *
2605  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2606  */
2607 int
xmlTextWriterStartCDATA(xmlTextWriterPtr writer)2608 xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2609 {
2610     int count;
2611     int sum;
2612     xmlLinkPtr lk;
2613     xmlTextWriterStackEntry *p;
2614 
2615     if (writer == NULL)
2616         return -1;
2617 
2618     sum = 0;
2619     lk = xmlListFront(writer->nodes);
2620     if (lk != 0) {
2621         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2622         if (p != 0) {
2623             switch (p->state) {
2624                 case XML_TEXTWRITER_NONE:
2625 		case XML_TEXTWRITER_TEXT:
2626                 case XML_TEXTWRITER_PI:
2627                 case XML_TEXTWRITER_PI_TEXT:
2628                     break;
2629                 case XML_TEXTWRITER_ATTRIBUTE:
2630                     count = xmlTextWriterEndAttribute(writer);
2631                     if (count < 0)
2632                         return -1;
2633                     sum += count;
2634                     /* fallthrough */
2635                 case XML_TEXTWRITER_NAME:
2636                     /* Output namespace declarations */
2637                     count = xmlTextWriterOutputNSDecl(writer);
2638                     if (count < 0)
2639                         return -1;
2640                     sum += count;
2641                     count = xmlOutputBufferWriteString(writer->out, ">");
2642                     if (count < 0)
2643                         return -1;
2644                     sum += count;
2645                     p->state = XML_TEXTWRITER_TEXT;
2646                     break;
2647                 case XML_TEXTWRITER_CDATA:
2648                     xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2649                                     "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2650                     return -1;
2651                 default:
2652                     return -1;
2653             }
2654         }
2655     }
2656 
2657     p = (xmlTextWriterStackEntry *)
2658         xmlMalloc(sizeof(xmlTextWriterStackEntry));
2659     if (p == 0) {
2660         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2661                         "xmlTextWriterStartCDATA : out of memory!\n");
2662         return -1;
2663     }
2664 
2665     p->name = NULL;
2666     p->state = XML_TEXTWRITER_CDATA;
2667 
2668     xmlListPushFront(writer->nodes, p);
2669 
2670     count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2671     if (count < 0)
2672         return -1;
2673     sum += count;
2674 
2675     return sum;
2676 }
2677 
2678 /**
2679  * xmlTextWriterEndCDATA:
2680  * @writer:  the xmlTextWriterPtr
2681  *
2682  * End an xml CDATA section.
2683  *
2684  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2685  */
2686 int
xmlTextWriterEndCDATA(xmlTextWriterPtr writer)2687 xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2688 {
2689     int count;
2690     int sum;
2691     xmlLinkPtr lk;
2692     xmlTextWriterStackEntry *p;
2693 
2694     if (writer == NULL)
2695         return -1;
2696 
2697     lk = xmlListFront(writer->nodes);
2698     if (lk == 0)
2699         return -1;
2700 
2701     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2702     if (p == 0)
2703         return -1;
2704 
2705     sum = 0;
2706     switch (p->state) {
2707         case XML_TEXTWRITER_CDATA:
2708             count = xmlOutputBufferWriteString(writer->out, "]]>");
2709             if (count < 0)
2710                 return -1;
2711             sum += count;
2712             break;
2713         default:
2714             return -1;
2715     }
2716 
2717     xmlListPopFront(writer->nodes);
2718     return sum;
2719 }
2720 
2721 /**
2722  * xmlTextWriterWriteFormatCDATA:
2723  * @writer:  the xmlTextWriterPtr
2724  * @format:  format string (see printf)
2725  * @...:  extra parameters for the format
2726  *
2727  * Write a formatted xml CDATA.
2728  *
2729  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2730  */
2731 int
xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer,const char * format,...)2732 xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2733                               ...)
2734 {
2735     int rc;
2736     va_list ap;
2737 
2738     va_start(ap, format);
2739 
2740     rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2741 
2742     va_end(ap);
2743     return rc;
2744 }
2745 
2746 /**
2747  * xmlTextWriterWriteVFormatCDATA:
2748  * @writer:  the xmlTextWriterPtr
2749  * @format:  format string (see printf)
2750  * @argptr:  pointer to the first member of the variable argument list.
2751  *
2752  * Write a formatted xml CDATA.
2753  *
2754  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2755  */
2756 int
xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer,const char * format,va_list argptr)2757 xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2758                                va_list argptr)
2759 {
2760     int rc;
2761     xmlChar *buf;
2762 
2763     if (writer == NULL)
2764         return -1;
2765 
2766     buf = xmlTextWriterVSprintf(format, argptr);
2767     if (buf == NULL)
2768         return -1;
2769 
2770     rc = xmlTextWriterWriteCDATA(writer, buf);
2771 
2772     xmlFree(buf);
2773     return rc;
2774 }
2775 
2776 /**
2777  * xmlTextWriterWriteCDATA:
2778  * @writer:  the xmlTextWriterPtr
2779  * @content:  CDATA content
2780  *
2781  * Write an xml CDATA.
2782  *
2783  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2784  */
2785 int
xmlTextWriterWriteCDATA(xmlTextWriterPtr writer,const xmlChar * content)2786 xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2787 {
2788     int count;
2789     int sum;
2790 
2791     sum = 0;
2792     count = xmlTextWriterStartCDATA(writer);
2793     if (count == -1)
2794         return -1;
2795     sum += count;
2796     if (content != 0) {
2797         count = xmlTextWriterWriteString(writer, content);
2798         if (count == -1)
2799             return -1;
2800         sum += count;
2801     }
2802     count = xmlTextWriterEndCDATA(writer);
2803     if (count == -1)
2804         return -1;
2805     sum += count;
2806 
2807     return sum;
2808 }
2809 
2810 /**
2811  * xmlTextWriterStartDTD:
2812  * @writer:  the xmlTextWriterPtr
2813  * @name:  the name of the DTD
2814  * @pubid:  the public identifier, which is an alternative to the system identifier
2815  * @sysid:  the system identifier, which is the URI of the DTD
2816  *
2817  * Start an xml DTD.
2818  *
2819  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2820  */
2821 int
xmlTextWriterStartDTD(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid)2822 xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2823                       const xmlChar * name,
2824                       const xmlChar * pubid, const xmlChar * sysid)
2825 {
2826     int count;
2827     int sum;
2828     xmlLinkPtr lk;
2829     xmlTextWriterStackEntry *p;
2830 
2831     if (writer == NULL || name == NULL || *name == '\0')
2832         return -1;
2833 
2834     sum = 0;
2835     lk = xmlListFront(writer->nodes);
2836     if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
2837         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2838                         "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2839         return -1;
2840     }
2841 
2842     p = (xmlTextWriterStackEntry *)
2843         xmlMalloc(sizeof(xmlTextWriterStackEntry));
2844     if (p == 0) {
2845         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2846                         "xmlTextWriterStartDTD : out of memory!\n");
2847         return -1;
2848     }
2849 
2850     p->name = xmlStrdup(name);
2851     if (p->name == 0) {
2852         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2853                         "xmlTextWriterStartDTD : out of memory!\n");
2854         xmlFree(p);
2855         return -1;
2856     }
2857     p->state = XML_TEXTWRITER_DTD;
2858 
2859     xmlListPushFront(writer->nodes, p);
2860 
2861     count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2862     if (count < 0)
2863         return -1;
2864     sum += count;
2865     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2866     if (count < 0)
2867         return -1;
2868     sum += count;
2869 
2870     if (pubid != 0) {
2871         if (sysid == 0) {
2872             xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2873                             "xmlTextWriterStartDTD : system identifier needed!\n");
2874             return -1;
2875         }
2876 
2877         if (writer->indent)
2878             count = xmlOutputBufferWrite(writer->out, 1, "\n");
2879         else
2880             count = xmlOutputBufferWrite(writer->out, 1, " ");
2881         if (count < 0)
2882             return -1;
2883         sum += count;
2884 
2885         count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2886         if (count < 0)
2887             return -1;
2888         sum += count;
2889 
2890         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2891         if (count < 0)
2892             return -1;
2893         sum += count;
2894 
2895         count =
2896             xmlOutputBufferWriteString(writer->out, (const char *) pubid);
2897         if (count < 0)
2898             return -1;
2899         sum += count;
2900 
2901         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2902         if (count < 0)
2903             return -1;
2904         sum += count;
2905     }
2906 
2907     if (sysid != 0) {
2908         if (pubid == 0) {
2909             if (writer->indent)
2910                 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2911             else
2912                 count = xmlOutputBufferWrite(writer->out, 1, " ");
2913             if (count < 0)
2914                 return -1;
2915             sum += count;
2916             count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2917             if (count < 0)
2918                 return -1;
2919             sum += count;
2920         } else {
2921 			if (writer->indent)
2922             count = xmlOutputBufferWriteString(writer->out, "\n       ");
2923             else
2924                 count = xmlOutputBufferWrite(writer->out, 1, " ");
2925             if (count < 0)
2926                 return -1;
2927             sum += count;
2928         }
2929 
2930         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2931         if (count < 0)
2932             return -1;
2933         sum += count;
2934 
2935         count =
2936             xmlOutputBufferWriteString(writer->out, (const char *) sysid);
2937         if (count < 0)
2938             return -1;
2939         sum += count;
2940 
2941         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2942         if (count < 0)
2943             return -1;
2944         sum += count;
2945     }
2946 
2947     return sum;
2948 }
2949 
2950 /**
2951  * xmlTextWriterEndDTD:
2952  * @writer:  the xmlTextWriterPtr
2953  *
2954  * End an xml DTD.
2955  *
2956  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2957  */
2958 int
xmlTextWriterEndDTD(xmlTextWriterPtr writer)2959 xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2960 {
2961     int loop;
2962     int count;
2963     int sum;
2964     xmlLinkPtr lk;
2965     xmlTextWriterStackEntry *p;
2966 
2967     if (writer == NULL)
2968         return -1;
2969 
2970     sum = 0;
2971     loop = 1;
2972     while (loop) {
2973         lk = xmlListFront(writer->nodes);
2974         if (lk == NULL)
2975             break;
2976         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2977         if (p == 0)
2978             break;
2979         switch (p->state) {
2980             case XML_TEXTWRITER_DTD_TEXT:
2981                 count = xmlOutputBufferWriteString(writer->out, "]");
2982                 if (count < 0)
2983                     return -1;
2984                 sum += count;
2985                 /* fallthrough */
2986             case XML_TEXTWRITER_DTD:
2987                 count = xmlOutputBufferWriteString(writer->out, ">");
2988 
2989                 if (writer->indent) {
2990                     if (count < 0)
2991                         return -1;
2992                     sum += count;
2993                     count = xmlOutputBufferWriteString(writer->out, "\n");
2994                 }
2995 
2996                 xmlListPopFront(writer->nodes);
2997                 break;
2998             case XML_TEXTWRITER_DTD_ELEM:
2999             case XML_TEXTWRITER_DTD_ELEM_TEXT:
3000                 count = xmlTextWriterEndDTDElement(writer);
3001                 break;
3002             case XML_TEXTWRITER_DTD_ATTL:
3003             case XML_TEXTWRITER_DTD_ATTL_TEXT:
3004                 count = xmlTextWriterEndDTDAttlist(writer);
3005                 break;
3006             case XML_TEXTWRITER_DTD_ENTY:
3007             case XML_TEXTWRITER_DTD_PENT:
3008             case XML_TEXTWRITER_DTD_ENTY_TEXT:
3009                 count = xmlTextWriterEndDTDEntity(writer);
3010                 break;
3011             case XML_TEXTWRITER_COMMENT:
3012                 count = xmlTextWriterEndComment(writer);
3013                 break;
3014             default:
3015                 loop = 0;
3016                 continue;
3017         }
3018 
3019         if (count < 0)
3020             return -1;
3021         sum += count;
3022     }
3023 
3024     return sum;
3025 }
3026 
3027 /**
3028  * xmlTextWriterWriteFormatDTD:
3029  * @writer:  the xmlTextWriterPtr
3030  * @name:  the name of the DTD
3031  * @pubid:  the public identifier, which is an alternative to the system identifier
3032  * @sysid:  the system identifier, which is the URI of the DTD
3033  * @format:  format string (see printf)
3034  * @...:  extra parameters for the format
3035  *
3036  * Write a DTD with a formatted markup declarations part.
3037  *
3038  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3039  */
3040 int
xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid,const char * format,...)3041 xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3042                             const xmlChar * name,
3043                             const xmlChar * pubid,
3044                             const xmlChar * sysid, const char *format, ...)
3045 {
3046     int rc;
3047     va_list ap;
3048 
3049     va_start(ap, format);
3050 
3051     rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3052                                       ap);
3053 
3054     va_end(ap);
3055     return rc;
3056 }
3057 
3058 /**
3059  * xmlTextWriterWriteVFormatDTD:
3060  * @writer:  the xmlTextWriterPtr
3061  * @name:  the name of the DTD
3062  * @pubid:  the public identifier, which is an alternative to the system identifier
3063  * @sysid:  the system identifier, which is the URI of the DTD
3064  * @format:  format string (see printf)
3065  * @argptr:  pointer to the first member of the variable argument list.
3066  *
3067  * Write a DTD with a formatted markup declarations part.
3068  *
3069  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3070  */
3071 int
xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid,const char * format,va_list argptr)3072 xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3073                              const xmlChar * name,
3074                              const xmlChar * pubid,
3075                              const xmlChar * sysid,
3076                              const char *format, va_list argptr)
3077 {
3078     int rc;
3079     xmlChar *buf;
3080 
3081     if (writer == NULL)
3082         return -1;
3083 
3084     buf = xmlTextWriterVSprintf(format, argptr);
3085     if (buf == NULL)
3086         return -1;
3087 
3088     rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3089 
3090     xmlFree(buf);
3091     return rc;
3092 }
3093 
3094 /**
3095  * xmlTextWriterWriteDTD:
3096  * @writer:  the xmlTextWriterPtr
3097  * @name:  the name of the DTD
3098  * @pubid:  the public identifier, which is an alternative to the system identifier
3099  * @sysid:  the system identifier, which is the URI of the DTD
3100  * @subset:  string content of the DTD
3101  *
3102  * Write a DTD.
3103  *
3104  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3105  */
3106 int
xmlTextWriterWriteDTD(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid,const xmlChar * subset)3107 xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3108                       const xmlChar * name,
3109                       const xmlChar * pubid,
3110                       const xmlChar * sysid, const xmlChar * subset)
3111 {
3112     int count;
3113     int sum;
3114 
3115     sum = 0;
3116     count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3117     if (count == -1)
3118         return -1;
3119     sum += count;
3120     if (subset != 0) {
3121         count = xmlTextWriterWriteString(writer, subset);
3122         if (count == -1)
3123             return -1;
3124         sum += count;
3125     }
3126     count = xmlTextWriterEndDTD(writer);
3127     if (count == -1)
3128         return -1;
3129     sum += count;
3130 
3131     return sum;
3132 }
3133 
3134 /**
3135  * xmlTextWriterStartDTDElement:
3136  * @writer:  the xmlTextWriterPtr
3137  * @name:  the name of the DTD element
3138  *
3139  * Start an xml DTD element.
3140  *
3141  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3142  */
3143 int
xmlTextWriterStartDTDElement(xmlTextWriterPtr writer,const xmlChar * name)3144 xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3145 {
3146     int count;
3147     int sum;
3148     xmlLinkPtr lk;
3149     xmlTextWriterStackEntry *p;
3150 
3151     if (writer == NULL || name == NULL || *name == '\0')
3152         return -1;
3153 
3154     sum = 0;
3155     lk = xmlListFront(writer->nodes);
3156     if (lk == 0) {
3157         return -1;
3158     }
3159 
3160     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3161     if (p != 0) {
3162         switch (p->state) {
3163             case XML_TEXTWRITER_DTD:
3164                 count = xmlOutputBufferWriteString(writer->out, " [");
3165                 if (count < 0)
3166                     return -1;
3167                 sum += count;
3168                 if (writer->indent) {
3169                     count = xmlOutputBufferWriteString(writer->out, "\n");
3170                     if (count < 0)
3171                         return -1;
3172                     sum += count;
3173                 }
3174                 p->state = XML_TEXTWRITER_DTD_TEXT;
3175                 /* fallthrough */
3176             case XML_TEXTWRITER_DTD_TEXT:
3177             case XML_TEXTWRITER_NONE:
3178                 break;
3179             default:
3180                 return -1;
3181         }
3182     }
3183 
3184     p = (xmlTextWriterStackEntry *)
3185         xmlMalloc(sizeof(xmlTextWriterStackEntry));
3186     if (p == 0) {
3187         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3188                         "xmlTextWriterStartDTDElement : out of memory!\n");
3189         return -1;
3190     }
3191 
3192     p->name = xmlStrdup(name);
3193     if (p->name == 0) {
3194         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3195                         "xmlTextWriterStartDTDElement : out of memory!\n");
3196         xmlFree(p);
3197         return -1;
3198     }
3199     p->state = XML_TEXTWRITER_DTD_ELEM;
3200 
3201     xmlListPushFront(writer->nodes, p);
3202 
3203     if (writer->indent) {
3204         count = xmlTextWriterWriteIndent(writer);
3205         if (count < 0)
3206             return -1;
3207         sum += count;
3208     }
3209 
3210     count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3211     if (count < 0)
3212         return -1;
3213     sum += count;
3214     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3215     if (count < 0)
3216         return -1;
3217     sum += count;
3218 
3219     return sum;
3220 }
3221 
3222 /**
3223  * xmlTextWriterEndDTDElement:
3224  * @writer:  the xmlTextWriterPtr
3225  *
3226  * End an xml DTD element.
3227  *
3228  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3229  */
3230 int
xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)3231 xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3232 {
3233     int count;
3234     int sum;
3235     xmlLinkPtr lk;
3236     xmlTextWriterStackEntry *p;
3237 
3238     if (writer == NULL)
3239         return -1;
3240 
3241     sum = 0;
3242     lk = xmlListFront(writer->nodes);
3243     if (lk == 0)
3244         return -1;
3245 
3246     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3247     if (p == 0)
3248         return -1;
3249 
3250     switch (p->state) {
3251         case XML_TEXTWRITER_DTD_ELEM:
3252         case XML_TEXTWRITER_DTD_ELEM_TEXT:
3253             count = xmlOutputBufferWriteString(writer->out, ">");
3254             if (count < 0)
3255                 return -1;
3256             sum += count;
3257             break;
3258         default:
3259             return -1;
3260     }
3261 
3262     if (writer->indent) {
3263         count = xmlOutputBufferWriteString(writer->out, "\n");
3264         if (count < 0)
3265             return -1;
3266         sum += count;
3267     }
3268 
3269     xmlListPopFront(writer->nodes);
3270     return sum;
3271 }
3272 
3273 /**
3274  * xmlTextWriterWriteFormatDTDElement:
3275  * @writer:  the xmlTextWriterPtr
3276  * @name:  the name of the DTD element
3277  * @format:  format string (see printf)
3278  * @...:  extra parameters for the format
3279  *
3280  * Write a formatted DTD element.
3281  *
3282  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3283  */
3284 int
xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,const xmlChar * name,const char * format,...)3285 xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3286                                    const xmlChar * name,
3287                                    const char *format, ...)
3288 {
3289     int rc;
3290     va_list ap;
3291 
3292     va_start(ap, format);
3293 
3294     rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3295 
3296     va_end(ap);
3297     return rc;
3298 }
3299 
3300 /**
3301  * xmlTextWriterWriteVFormatDTDElement:
3302  * @writer:  the xmlTextWriterPtr
3303  * @name:  the name of the DTD element
3304  * @format:  format string (see printf)
3305  * @argptr:  pointer to the first member of the variable argument list.
3306  *
3307  * Write a formatted DTD element.
3308  *
3309  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3310  */
3311 int
xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,const xmlChar * name,const char * format,va_list argptr)3312 xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3313                                     const xmlChar * name,
3314                                     const char *format, va_list argptr)
3315 {
3316     int rc;
3317     xmlChar *buf;
3318 
3319     if (writer == NULL)
3320         return -1;
3321 
3322     buf = xmlTextWriterVSprintf(format, argptr);
3323     if (buf == NULL)
3324         return -1;
3325 
3326     rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3327 
3328     xmlFree(buf);
3329     return rc;
3330 }
3331 
3332 /**
3333  * xmlTextWriterWriteDTDElement:
3334  * @writer:  the xmlTextWriterPtr
3335  * @name:  the name of the DTD element
3336  * @content:  content of the element
3337  *
3338  * Write a DTD element.
3339  *
3340  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3341  */
3342 int
xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * content)3343 xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3344                              const xmlChar * name, const xmlChar * content)
3345 {
3346     int count;
3347     int sum;
3348 
3349     if (content == NULL)
3350         return -1;
3351 
3352     sum = 0;
3353     count = xmlTextWriterStartDTDElement(writer, name);
3354     if (count == -1)
3355         return -1;
3356     sum += count;
3357 
3358     count = xmlTextWriterWriteString(writer, content);
3359     if (count == -1)
3360         return -1;
3361     sum += count;
3362 
3363     count = xmlTextWriterEndDTDElement(writer);
3364     if (count == -1)
3365         return -1;
3366     sum += count;
3367 
3368     return sum;
3369 }
3370 
3371 /**
3372  * xmlTextWriterStartDTDAttlist:
3373  * @writer:  the xmlTextWriterPtr
3374  * @name:  the name of the DTD ATTLIST
3375  *
3376  * Start an xml DTD ATTLIST.
3377  *
3378  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3379  */
3380 int
xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer,const xmlChar * name)3381 xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3382 {
3383     int count;
3384     int sum;
3385     xmlLinkPtr lk;
3386     xmlTextWriterStackEntry *p;
3387 
3388     if (writer == NULL || name == NULL || *name == '\0')
3389         return -1;
3390 
3391     sum = 0;
3392     lk = xmlListFront(writer->nodes);
3393     if (lk == 0) {
3394         return -1;
3395     }
3396 
3397     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3398     if (p != 0) {
3399         switch (p->state) {
3400             case XML_TEXTWRITER_DTD:
3401                 count = xmlOutputBufferWriteString(writer->out, " [");
3402                 if (count < 0)
3403                     return -1;
3404                 sum += count;
3405                 if (writer->indent) {
3406                     count = xmlOutputBufferWriteString(writer->out, "\n");
3407                     if (count < 0)
3408                         return -1;
3409                     sum += count;
3410                 }
3411                 p->state = XML_TEXTWRITER_DTD_TEXT;
3412                 /* fallthrough */
3413             case XML_TEXTWRITER_DTD_TEXT:
3414             case XML_TEXTWRITER_NONE:
3415                 break;
3416             default:
3417                 return -1;
3418         }
3419     }
3420 
3421     p = (xmlTextWriterStackEntry *)
3422         xmlMalloc(sizeof(xmlTextWriterStackEntry));
3423     if (p == 0) {
3424         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3425                         "xmlTextWriterStartDTDAttlist : out of memory!\n");
3426         return -1;
3427     }
3428 
3429     p->name = xmlStrdup(name);
3430     if (p->name == 0) {
3431         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3432                         "xmlTextWriterStartDTDAttlist : out of memory!\n");
3433         xmlFree(p);
3434         return -1;
3435     }
3436     p->state = XML_TEXTWRITER_DTD_ATTL;
3437 
3438     xmlListPushFront(writer->nodes, p);
3439 
3440     if (writer->indent) {
3441         count = xmlTextWriterWriteIndent(writer);
3442         if (count < 0)
3443             return -1;
3444         sum += count;
3445     }
3446 
3447     count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3448     if (count < 0)
3449         return -1;
3450     sum += count;
3451     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3452     if (count < 0)
3453         return -1;
3454     sum += count;
3455 
3456     return sum;
3457 }
3458 
3459 /**
3460  * xmlTextWriterEndDTDAttlist:
3461  * @writer:  the xmlTextWriterPtr
3462  *
3463  * End an xml DTD attribute list.
3464  *
3465  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3466  */
3467 int
xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)3468 xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3469 {
3470     int count;
3471     int sum;
3472     xmlLinkPtr lk;
3473     xmlTextWriterStackEntry *p;
3474 
3475     if (writer == NULL)
3476         return -1;
3477 
3478     sum = 0;
3479     lk = xmlListFront(writer->nodes);
3480     if (lk == 0)
3481         return -1;
3482 
3483     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3484     if (p == 0)
3485         return -1;
3486 
3487     switch (p->state) {
3488         case XML_TEXTWRITER_DTD_ATTL:
3489         case XML_TEXTWRITER_DTD_ATTL_TEXT:
3490             count = xmlOutputBufferWriteString(writer->out, ">");
3491             if (count < 0)
3492                 return -1;
3493             sum += count;
3494             break;
3495         default:
3496             return -1;
3497     }
3498 
3499     if (writer->indent) {
3500         count = xmlOutputBufferWriteString(writer->out, "\n");
3501         if (count < 0)
3502             return -1;
3503         sum += count;
3504     }
3505 
3506     xmlListPopFront(writer->nodes);
3507     return sum;
3508 }
3509 
3510 /**
3511  * xmlTextWriterWriteFormatDTDAttlist:
3512  * @writer:  the xmlTextWriterPtr
3513  * @name:  the name of the DTD ATTLIST
3514  * @format:  format string (see printf)
3515  * @...:  extra parameters for the format
3516  *
3517  * Write a formatted DTD ATTLIST.
3518  *
3519  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3520  */
3521 int
xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,const xmlChar * name,const char * format,...)3522 xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3523                                    const xmlChar * name,
3524                                    const char *format, ...)
3525 {
3526     int rc;
3527     va_list ap;
3528 
3529     va_start(ap, format);
3530 
3531     rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3532 
3533     va_end(ap);
3534     return rc;
3535 }
3536 
3537 /**
3538  * xmlTextWriterWriteVFormatDTDAttlist:
3539  * @writer:  the xmlTextWriterPtr
3540  * @name:  the name of the DTD ATTLIST
3541  * @format:  format string (see printf)
3542  * @argptr:  pointer to the first member of the variable argument list.
3543  *
3544  * Write a formatted DTD ATTLIST.
3545  *
3546  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3547  */
3548 int
xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,const xmlChar * name,const char * format,va_list argptr)3549 xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3550                                     const xmlChar * name,
3551                                     const char *format, va_list argptr)
3552 {
3553     int rc;
3554     xmlChar *buf;
3555 
3556     if (writer == NULL)
3557         return -1;
3558 
3559     buf = xmlTextWriterVSprintf(format, argptr);
3560     if (buf == NULL)
3561         return -1;
3562 
3563     rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3564 
3565     xmlFree(buf);
3566     return rc;
3567 }
3568 
3569 /**
3570  * xmlTextWriterWriteDTDAttlist:
3571  * @writer:  the xmlTextWriterPtr
3572  * @name:  the name of the DTD ATTLIST
3573  * @content:  content of the ATTLIST
3574  *
3575  * Write a DTD ATTLIST.
3576  *
3577  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3578  */
3579 int
xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * content)3580 xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3581                              const xmlChar * name, const xmlChar * content)
3582 {
3583     int count;
3584     int sum;
3585 
3586     if (content == NULL)
3587         return -1;
3588 
3589     sum = 0;
3590     count = xmlTextWriterStartDTDAttlist(writer, name);
3591     if (count == -1)
3592         return -1;
3593     sum += count;
3594 
3595     count = xmlTextWriterWriteString(writer, content);
3596     if (count == -1)
3597         return -1;
3598     sum += count;
3599 
3600     count = xmlTextWriterEndDTDAttlist(writer);
3601     if (count == -1)
3602         return -1;
3603     sum += count;
3604 
3605     return sum;
3606 }
3607 
3608 /**
3609  * xmlTextWriterStartDTDEntity:
3610  * @writer:  the xmlTextWriterPtr
3611  * @pe:  TRUE if this is a parameter entity, FALSE if not
3612  * @name:  the name of the DTD ATTLIST
3613  *
3614  * Start an xml DTD ATTLIST.
3615  *
3616  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3617  */
3618 int
xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,int pe,const xmlChar * name)3619 xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3620                             int pe, const xmlChar * name)
3621 {
3622     int count;
3623     int sum;
3624     xmlLinkPtr lk;
3625     xmlTextWriterStackEntry *p;
3626 
3627     if (writer == NULL || name == NULL || *name == '\0')
3628         return -1;
3629 
3630     sum = 0;
3631     lk = xmlListFront(writer->nodes);
3632     if (lk != 0) {
3633 
3634         p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3635         if (p != 0) {
3636             switch (p->state) {
3637                 case XML_TEXTWRITER_DTD:
3638                     count = xmlOutputBufferWriteString(writer->out, " [");
3639                     if (count < 0)
3640                         return -1;
3641                     sum += count;
3642                     if (writer->indent) {
3643                         count =
3644                             xmlOutputBufferWriteString(writer->out, "\n");
3645                         if (count < 0)
3646                             return -1;
3647                         sum += count;
3648                     }
3649                     p->state = XML_TEXTWRITER_DTD_TEXT;
3650                     /* fallthrough */
3651                 case XML_TEXTWRITER_DTD_TEXT:
3652                 case XML_TEXTWRITER_NONE:
3653                     break;
3654                 default:
3655                     return -1;
3656             }
3657         }
3658     }
3659 
3660     p = (xmlTextWriterStackEntry *)
3661         xmlMalloc(sizeof(xmlTextWriterStackEntry));
3662     if (p == 0) {
3663         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3664                         "xmlTextWriterStartDTDElement : out of memory!\n");
3665         return -1;
3666     }
3667 
3668     p->name = xmlStrdup(name);
3669     if (p->name == 0) {
3670         xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3671                         "xmlTextWriterStartDTDElement : out of memory!\n");
3672         xmlFree(p);
3673         return -1;
3674     }
3675 
3676     if (pe != 0)
3677         p->state = XML_TEXTWRITER_DTD_PENT;
3678     else
3679         p->state = XML_TEXTWRITER_DTD_ENTY;
3680 
3681     xmlListPushFront(writer->nodes, p);
3682 
3683     if (writer->indent) {
3684         count = xmlTextWriterWriteIndent(writer);
3685         if (count < 0)
3686             return -1;
3687         sum += count;
3688     }
3689 
3690     count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3691     if (count < 0)
3692         return -1;
3693     sum += count;
3694 
3695     if (pe != 0) {
3696         count = xmlOutputBufferWriteString(writer->out, "% ");
3697         if (count < 0)
3698             return -1;
3699         sum += count;
3700     }
3701 
3702     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3703     if (count < 0)
3704         return -1;
3705     sum += count;
3706 
3707     return sum;
3708 }
3709 
3710 /**
3711  * xmlTextWriterEndDTDEntity:
3712  * @writer:  the xmlTextWriterPtr
3713  *
3714  * End an xml DTD entity.
3715  *
3716  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3717  */
3718 int
xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)3719 xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3720 {
3721     int count;
3722     int sum;
3723     xmlLinkPtr lk;
3724     xmlTextWriterStackEntry *p;
3725 
3726     if (writer == NULL)
3727         return -1;
3728 
3729     sum = 0;
3730     lk = xmlListFront(writer->nodes);
3731     if (lk == 0)
3732         return -1;
3733 
3734     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3735     if (p == 0)
3736         return -1;
3737 
3738     switch (p->state) {
3739         case XML_TEXTWRITER_DTD_ENTY_TEXT:
3740             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3741             if (count < 0)
3742                 return -1;
3743             sum += count;
3744             /* Falls through. */
3745         case XML_TEXTWRITER_DTD_ENTY:
3746         case XML_TEXTWRITER_DTD_PENT:
3747             count = xmlOutputBufferWriteString(writer->out, ">");
3748             if (count < 0)
3749                 return -1;
3750             sum += count;
3751             break;
3752         default:
3753             return -1;
3754     }
3755 
3756     if (writer->indent) {
3757         count = xmlOutputBufferWriteString(writer->out, "\n");
3758         if (count < 0)
3759             return -1;
3760         sum += count;
3761     }
3762 
3763     xmlListPopFront(writer->nodes);
3764     return sum;
3765 }
3766 
3767 /**
3768  * xmlTextWriterWriteFormatDTDInternalEntity:
3769  * @writer:  the xmlTextWriterPtr
3770  * @pe:  TRUE if this is a parameter entity, FALSE if not
3771  * @name:  the name of the DTD entity
3772  * @format:  format string (see printf)
3773  * @...:  extra parameters for the format
3774  *
3775  * Write a formatted DTD internal entity.
3776  *
3777  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3778  */
3779 int
xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,int pe,const xmlChar * name,const char * format,...)3780 xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3781                                           int pe,
3782                                           const xmlChar * name,
3783                                           const char *format, ...)
3784 {
3785     int rc;
3786     va_list ap;
3787 
3788     va_start(ap, format);
3789 
3790     rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3791                                                     format, ap);
3792 
3793     va_end(ap);
3794     return rc;
3795 }
3796 
3797 /**
3798  * xmlTextWriterWriteVFormatDTDInternalEntity:
3799  * @writer:  the xmlTextWriterPtr
3800  * @pe:  TRUE if this is a parameter entity, FALSE if not
3801  * @name:  the name of the DTD entity
3802  * @format:  format string (see printf)
3803  * @argptr:  pointer to the first member of the variable argument list.
3804  *
3805  * Write a formatted DTD internal entity.
3806  *
3807  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3808  */
3809 int
xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,int pe,const xmlChar * name,const char * format,va_list argptr)3810 xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3811                                            int pe,
3812                                            const xmlChar * name,
3813                                            const char *format,
3814                                            va_list argptr)
3815 {
3816     int rc;
3817     xmlChar *buf;
3818 
3819     if (writer == NULL)
3820         return -1;
3821 
3822     buf = xmlTextWriterVSprintf(format, argptr);
3823     if (buf == NULL)
3824         return -1;
3825 
3826     rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3827 
3828     xmlFree(buf);
3829     return rc;
3830 }
3831 
3832 /**
3833  * xmlTextWriterWriteDTDEntity:
3834  * @writer:  the xmlTextWriterPtr
3835  * @pe:  TRUE if this is a parameter entity, FALSE if not
3836  * @name:  the name of the DTD entity
3837  * @pubid:  the public identifier, which is an alternative to the system identifier
3838  * @sysid:  the system identifier, which is the URI of the DTD
3839  * @ndataid:  the xml notation name.
3840  * @content:  content of the entity
3841  *
3842  * Write a DTD entity.
3843  *
3844  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3845  */
3846 int
xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,int pe,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid,const xmlChar * ndataid,const xmlChar * content)3847 xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3848                             int pe,
3849                             const xmlChar * name,
3850                             const xmlChar * pubid,
3851                             const xmlChar * sysid,
3852                             const xmlChar * ndataid,
3853                             const xmlChar * content)
3854 {
3855     if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
3856         return -1;
3857     if ((pe != 0) && (ndataid != NULL))
3858         return -1;
3859 
3860     if ((pubid == NULL) && (sysid == NULL))
3861         return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3862                                                    content);
3863 
3864     return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3865                                                sysid, ndataid);
3866 }
3867 
3868 /**
3869  * xmlTextWriterWriteDTDInternalEntity:
3870  * @writer:  the xmlTextWriterPtr
3871  * @pe:  TRUE if this is a parameter entity, FALSE if not
3872  * @name:  the name of the DTD entity
3873  * @content:  content of the entity
3874  *
3875  * Write a DTD internal entity.
3876  *
3877  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3878  */
3879 int
xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,int pe,const xmlChar * name,const xmlChar * content)3880 xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3881                                     int pe,
3882                                     const xmlChar * name,
3883                                     const xmlChar * content)
3884 {
3885     int count;
3886     int sum;
3887 
3888     if ((name == NULL) || (*name == '\0') || (content == NULL))
3889         return -1;
3890 
3891     sum = 0;
3892     count = xmlTextWriterStartDTDEntity(writer, pe, name);
3893     if (count == -1)
3894         return -1;
3895     sum += count;
3896 
3897     count = xmlTextWriterWriteString(writer, content);
3898     if (count == -1)
3899         return -1;
3900     sum += count;
3901 
3902     count = xmlTextWriterEndDTDEntity(writer);
3903     if (count == -1)
3904         return -1;
3905     sum += count;
3906 
3907     return sum;
3908 }
3909 
3910 /**
3911  * xmlTextWriterWriteDTDExternalEntity:
3912  * @writer:  the xmlTextWriterPtr
3913  * @pe:  TRUE if this is a parameter entity, FALSE if not
3914  * @name:  the name of the DTD entity
3915  * @pubid:  the public identifier, which is an alternative to the system identifier
3916  * @sysid:  the system identifier, which is the URI of the DTD
3917  * @ndataid:  the xml notation name.
3918  *
3919  * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
3920  *
3921  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3922  */
3923 int
xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,int pe,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid,const xmlChar * ndataid)3924 xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3925                                     int pe,
3926                                     const xmlChar * name,
3927                                     const xmlChar * pubid,
3928                                     const xmlChar * sysid,
3929                                     const xmlChar * ndataid)
3930 {
3931     int count;
3932     int sum;
3933 
3934     if (((pubid == NULL) && (sysid == NULL)))
3935         return -1;
3936     if ((pe != 0) && (ndataid != NULL))
3937         return -1;
3938 
3939     sum = 0;
3940     count = xmlTextWriterStartDTDEntity(writer, pe, name);
3941     if (count == -1)
3942         return -1;
3943     sum += count;
3944 
3945     count =
3946         xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3947                                                     ndataid);
3948     if (count < 0)
3949         return -1;
3950     sum += count;
3951 
3952     count = xmlTextWriterEndDTDEntity(writer);
3953     if (count == -1)
3954         return -1;
3955     sum += count;
3956 
3957     return sum;
3958 }
3959 
3960 /**
3961  * xmlTextWriterWriteDTDExternalEntityContents:
3962  * @writer:  the xmlTextWriterPtr
3963  * @pubid:  the public identifier, which is an alternative to the system identifier
3964  * @sysid:  the system identifier, which is the URI of the DTD
3965  * @ndataid:  the xml notation name.
3966  *
3967  * Write the contents of a DTD external entity.
3968  *
3969  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3970  */
3971 int
xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,const xmlChar * pubid,const xmlChar * sysid,const xmlChar * ndataid)3972 xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3973                                             const xmlChar * pubid,
3974                                             const xmlChar * sysid,
3975                                             const xmlChar * ndataid)
3976 {
3977     int count;
3978     int sum;
3979     xmlLinkPtr lk;
3980     xmlTextWriterStackEntry *p;
3981 
3982     if (writer == NULL) {
3983         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
3984                         "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3985         return -1;
3986     }
3987 
3988     sum = 0;
3989     lk = xmlListFront(writer->nodes);
3990     if (lk == 0) {
3991         xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
3992                         "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3993         return -1;
3994     }
3995 
3996     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3997     if (p == 0)
3998         return -1;
3999 
4000     switch (p->state) {
4001         case XML_TEXTWRITER_DTD_ENTY:
4002             break;
4003         case XML_TEXTWRITER_DTD_PENT:
4004             if (ndataid != NULL) {
4005                 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4006                                 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4007                 return -1;
4008             }
4009             break;
4010         default:
4011             xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4012                             "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4013             return -1;
4014     }
4015 
4016     if (pubid != 0) {
4017         if (sysid == 0) {
4018             xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4019                             "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
4020             return -1;
4021         }
4022 
4023         count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4024         if (count < 0)
4025             return -1;
4026         sum += count;
4027 
4028         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4029         if (count < 0)
4030             return -1;
4031         sum += count;
4032 
4033         count =
4034             xmlOutputBufferWriteString(writer->out, (const char *) pubid);
4035         if (count < 0)
4036             return -1;
4037         sum += count;
4038 
4039         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4040         if (count < 0)
4041             return -1;
4042         sum += count;
4043     }
4044 
4045     if (sysid != 0) {
4046         if (pubid == 0) {
4047             count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4048             if (count < 0)
4049                 return -1;
4050             sum += count;
4051         }
4052 
4053         count = xmlOutputBufferWriteString(writer->out, " ");
4054         if (count < 0)
4055             return -1;
4056         sum += count;
4057 
4058         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4059         if (count < 0)
4060             return -1;
4061         sum += count;
4062 
4063         count =
4064             xmlOutputBufferWriteString(writer->out, (const char *) sysid);
4065         if (count < 0)
4066             return -1;
4067         sum += count;
4068 
4069         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4070         if (count < 0)
4071             return -1;
4072         sum += count;
4073     }
4074 
4075     if (ndataid != NULL) {
4076         count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4077         if (count < 0)
4078             return -1;
4079         sum += count;
4080 
4081         count =
4082             xmlOutputBufferWriteString(writer->out,
4083                                        (const char *) ndataid);
4084         if (count < 0)
4085             return -1;
4086         sum += count;
4087     }
4088 
4089     return sum;
4090 }
4091 
4092 /**
4093  * xmlTextWriterWriteDTDNotation:
4094  * @writer:  the xmlTextWriterPtr
4095  * @name:  the name of the xml notation
4096  * @pubid:  the public identifier, which is an alternative to the system identifier
4097  * @sysid:  the system identifier, which is the URI of the DTD
4098  *
4099  * Write a DTD entity.
4100  *
4101  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4102  */
4103 int
xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,const xmlChar * name,const xmlChar * pubid,const xmlChar * sysid)4104 xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4105                               const xmlChar * name,
4106                               const xmlChar * pubid, const xmlChar * sysid)
4107 {
4108     int count;
4109     int sum;
4110     xmlLinkPtr lk;
4111     xmlTextWriterStackEntry *p;
4112 
4113     if (writer == NULL || name == NULL || *name == '\0')
4114         return -1;
4115 
4116     sum = 0;
4117     lk = xmlListFront(writer->nodes);
4118     if (lk == 0) {
4119         return -1;
4120     }
4121 
4122     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4123     if (p != 0) {
4124         switch (p->state) {
4125             case XML_TEXTWRITER_DTD:
4126                 count = xmlOutputBufferWriteString(writer->out, " [");
4127                 if (count < 0)
4128                     return -1;
4129                 sum += count;
4130                 if (writer->indent) {
4131                     count = xmlOutputBufferWriteString(writer->out, "\n");
4132                     if (count < 0)
4133                         return -1;
4134                     sum += count;
4135                 }
4136                 p->state = XML_TEXTWRITER_DTD_TEXT;
4137                 /* fallthrough */
4138             case XML_TEXTWRITER_DTD_TEXT:
4139                 break;
4140             default:
4141                 return -1;
4142         }
4143     }
4144 
4145     if (writer->indent) {
4146         count = xmlTextWriterWriteIndent(writer);
4147         if (count < 0)
4148             return -1;
4149         sum += count;
4150     }
4151 
4152     count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4153     if (count < 0)
4154         return -1;
4155     sum += count;
4156     count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4157     if (count < 0)
4158         return -1;
4159     sum += count;
4160 
4161     if (pubid != 0) {
4162         count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4163         if (count < 0)
4164             return -1;
4165         sum += count;
4166         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4167         if (count < 0)
4168             return -1;
4169         sum += count;
4170         count =
4171             xmlOutputBufferWriteString(writer->out, (const char *) pubid);
4172         if (count < 0)
4173             return -1;
4174         sum += count;
4175         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4176         if (count < 0)
4177             return -1;
4178         sum += count;
4179     }
4180 
4181     if (sysid != 0) {
4182         if (pubid == 0) {
4183             count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4184             if (count < 0)
4185                 return -1;
4186             sum += count;
4187         }
4188         count = xmlOutputBufferWriteString(writer->out, " ");
4189         if (count < 0)
4190             return -1;
4191         sum += count;
4192         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4193         if (count < 0)
4194             return -1;
4195         sum += count;
4196         count =
4197             xmlOutputBufferWriteString(writer->out, (const char *) sysid);
4198         if (count < 0)
4199             return -1;
4200         sum += count;
4201         count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4202         if (count < 0)
4203             return -1;
4204         sum += count;
4205     }
4206 
4207     count = xmlOutputBufferWriteString(writer->out, ">");
4208     if (count < 0)
4209         return -1;
4210     sum += count;
4211 
4212     return sum;
4213 }
4214 
4215 /**
4216  * xmlTextWriterFlush:
4217  * @writer:  the xmlTextWriterPtr
4218  *
4219  * Flush the output buffer.
4220  *
4221  * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4222  */
4223 int
xmlTextWriterFlush(xmlTextWriterPtr writer)4224 xmlTextWriterFlush(xmlTextWriterPtr writer)
4225 {
4226     int count;
4227 
4228     if (writer == NULL)
4229         return -1;
4230 
4231     if (writer->out == NULL)
4232         count = 0;
4233     else
4234         count = xmlOutputBufferFlush(writer->out);
4235 
4236     return count;
4237 }
4238 
4239 /**
4240  * xmlTextWriterClose:
4241  * @writer:  the xmlTextWriterPtr
4242  *
4243  * Flushes and closes the output buffer.
4244  *
4245  * Available since 2.13.0.
4246  *
4247  * Returns an xmlParserErrors code.
4248  */
4249 int
xmlTextWriterClose(xmlTextWriterPtr writer)4250 xmlTextWriterClose(xmlTextWriterPtr writer)
4251 {
4252     int result;
4253 
4254     if ((writer == NULL) || (writer->out == NULL))
4255         return XML_ERR_ARGUMENT;
4256 
4257     result = xmlOutputBufferClose(writer->out);
4258     writer->out = NULL;
4259 
4260     if (result >= 0)
4261         result = XML_ERR_OK;
4262     else
4263         result = -result;
4264 
4265     return result;
4266 }
4267 
4268 /**
4269  * misc
4270  */
4271 
4272 /**
4273  * xmlFreeTextWriterStackEntry:
4274  * @lk:  the xmlLinkPtr
4275  *
4276  * Free callback for the xmlList.
4277  */
4278 static void
xmlFreeTextWriterStackEntry(xmlLinkPtr lk)4279 xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4280 {
4281     xmlTextWriterStackEntry *p;
4282 
4283     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4284     if (p == 0)
4285         return;
4286 
4287     if (p->name != 0)
4288         xmlFree(p->name);
4289     xmlFree(p);
4290 }
4291 
4292 /**
4293  * xmlCmpTextWriterStackEntry:
4294  * @data0:  the first data
4295  * @data1:  the second data
4296  *
4297  * Compare callback for the xmlList.
4298  *
4299  * Returns -1, 0, 1
4300  */
4301 static int
xmlCmpTextWriterStackEntry(const void * data0,const void * data1)4302 xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4303 {
4304     xmlTextWriterStackEntry *p0;
4305     xmlTextWriterStackEntry *p1;
4306 
4307     if (data0 == data1)
4308         return 0;
4309 
4310     if (data0 == 0)
4311         return -1;
4312 
4313     if (data1 == 0)
4314         return 1;
4315 
4316     p0 = (xmlTextWriterStackEntry *) data0;
4317     p1 = (xmlTextWriterStackEntry *) data1;
4318 
4319     return xmlStrcmp(p0->name, p1->name);
4320 }
4321 
4322 /**
4323  * misc
4324  */
4325 
4326 /**
4327  * xmlTextWriterOutputNSDecl:
4328  * @writer:  the xmlTextWriterPtr
4329  *
4330  * Output the current namespace declarations.
4331  */
4332 static int
xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)4333 xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4334 {
4335     xmlLinkPtr lk;
4336     xmlTextWriterNsStackEntry *np;
4337     int count;
4338     int sum;
4339 
4340     sum = 0;
4341     while (!xmlListEmpty(writer->nsstack)) {
4342         xmlChar *namespaceURI = NULL;
4343         xmlChar *prefix = NULL;
4344 
4345         lk = xmlListFront(writer->nsstack);
4346         np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4347 
4348         if (np != 0) {
4349             namespaceURI = xmlStrdup(np->uri);
4350             prefix = xmlStrdup(np->prefix);
4351         }
4352 
4353         xmlListPopFront(writer->nsstack);
4354 
4355         if (np != 0) {
4356             count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4357             xmlFree(namespaceURI);
4358             xmlFree(prefix);
4359 
4360             if (count < 0) {
4361                 xmlListDelete(writer->nsstack);
4362                 writer->nsstack = NULL;
4363                 return -1;
4364             }
4365             sum += count;
4366         }
4367     }
4368     return sum;
4369 }
4370 
4371 /**
4372  * xmlFreeTextWriterNsStackEntry:
4373  * @lk:  the xmlLinkPtr
4374  *
4375  * Free callback for the xmlList.
4376  */
4377 static void
xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)4378 xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4379 {
4380     xmlTextWriterNsStackEntry *p;
4381 
4382     p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4383     if (p == 0)
4384         return;
4385 
4386     if (p->prefix != 0)
4387         xmlFree(p->prefix);
4388     if (p->uri != 0)
4389         xmlFree(p->uri);
4390 
4391     xmlFree(p);
4392 }
4393 
4394 /**
4395  * xmlCmpTextWriterNsStackEntry:
4396  * @data0:  the first data
4397  * @data1:  the second data
4398  *
4399  * Compare callback for the xmlList.
4400  *
4401  * Returns -1, 0, 1
4402  */
4403 static int
xmlCmpTextWriterNsStackEntry(const void * data0,const void * data1)4404 xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4405 {
4406     xmlTextWriterNsStackEntry *p0;
4407     xmlTextWriterNsStackEntry *p1;
4408     int rc;
4409 
4410     if (data0 == data1)
4411         return 0;
4412 
4413     if (data0 == 0)
4414         return -1;
4415 
4416     if (data1 == 0)
4417         return 1;
4418 
4419     p0 = (xmlTextWriterNsStackEntry *) data0;
4420     p1 = (xmlTextWriterNsStackEntry *) data1;
4421 
4422     rc = xmlStrcmp(p0->prefix, p1->prefix);
4423 
4424     if ((rc != 0) || (p0->elem != p1->elem))
4425         rc = -1;
4426 
4427     return rc;
4428 }
4429 
4430 /**
4431  * xmlTextWriterWriteDocCallback:
4432  * @context:  the xmlBufferPtr
4433  * @str:  the data to write
4434  * @len:  the length of the data
4435  *
4436  * Write callback for the xmlOutputBuffer with target xmlBuffer
4437  *
4438  * Returns -1, 0, 1
4439  */
4440 static int
xmlTextWriterWriteDocCallback(void * context,const char * str,int len)4441 xmlTextWriterWriteDocCallback(void *context, const char *str, int len)
4442 {
4443     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4444     int rc;
4445 
4446     if ((rc = xmlParseChunk(ctxt, str, len, 0)) != 0) {
4447         xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
4448                         "xmlTextWriterWriteDocCallback : XML error %d !\n",
4449                         rc);
4450         return -1;
4451     }
4452 
4453     return len;
4454 }
4455 
4456 /**
4457  * xmlTextWriterCloseDocCallback:
4458  * @context:  the xmlBufferPtr
4459  *
4460  * Close callback for the xmlOutputBuffer with target xmlBuffer
4461  *
4462  * Returns -1, 0, 1
4463  */
4464 static int
xmlTextWriterCloseDocCallback(void * context)4465 xmlTextWriterCloseDocCallback(void *context)
4466 {
4467     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4468     int rc;
4469 
4470     if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
4471         xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
4472                         "xmlTextWriterCloseDocCallback : XML error %d !\n",
4473                         rc);
4474         return -1;
4475     }
4476 
4477     return 0;
4478 }
4479 
4480 /**
4481  * xmlTextWriterVSprintf:
4482  * @format:  see printf
4483  * @argptr:  pointer to the first member of the variable argument list.
4484  *
4485  * Utility function for formatted output
4486  *
4487  * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4488  */
4489 static xmlChar *
xmlTextWriterVSprintf(const char * format,va_list argptr)4490 xmlTextWriterVSprintf(const char *format, va_list argptr)
4491 {
4492     int size;
4493     int count;
4494     xmlChar *buf;
4495     va_list locarg;
4496 
4497     size = BUFSIZ;
4498     buf = (xmlChar *) xmlMalloc(size);
4499     if (buf == NULL) {
4500         xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
4501                         "xmlTextWriterVSprintf : out of memory!\n");
4502         return NULL;
4503     }
4504 
4505     va_copy(locarg, argptr);
4506     while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
4507            || (count == size - 1) || (count == size) || (count > size)) {
4508 	va_end(locarg);
4509         xmlFree(buf);
4510         size += BUFSIZ;
4511         buf = (xmlChar *) xmlMalloc(size);
4512         if (buf == NULL) {
4513             xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
4514                             "xmlTextWriterVSprintf : out of memory!\n");
4515             return NULL;
4516         }
4517 	va_copy(locarg, argptr);
4518     }
4519     va_end(locarg);
4520 
4521     return buf;
4522 }
4523 
4524 /**
4525  * xmlTextWriterStartDocumentCallback:
4526  * @ctx: the user data (XML parser context)
4527  *
4528  * called at the start of document processing.
4529  */
4530 static void
xmlTextWriterStartDocumentCallback(void * ctx)4531 xmlTextWriterStartDocumentCallback(void *ctx)
4532 {
4533     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4534     xmlDocPtr doc;
4535 
4536 #ifdef LIBXML_HTML_ENABLED
4537     if (ctxt->html) {
4538         if (ctxt->myDoc == NULL)
4539             ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4540         if (ctxt->myDoc == NULL) {
4541             xmlCtxtErrMemory(ctxt);
4542             return;
4543         }
4544     } else
4545 #endif
4546     {
4547         doc = ctxt->myDoc;
4548         if (doc == NULL)
4549             doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4550         if (doc != NULL) {
4551             if (doc->children == NULL) {
4552                 if (ctxt->encoding != NULL)
4553                     doc->encoding = xmlStrdup(ctxt->encoding);
4554                 else
4555                     doc->encoding = NULL;
4556                 doc->standalone = ctxt->standalone;
4557             }
4558         } else {
4559             xmlCtxtErrMemory(ctxt);
4560             return;
4561         }
4562     }
4563     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4564         (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4565         ctxt->myDoc->URL =
4566             xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4567         if (ctxt->myDoc->URL == NULL)
4568             ctxt->myDoc->URL =
4569                 xmlStrdup((const xmlChar *) ctxt->input->filename);
4570     }
4571 }
4572 
4573 /**
4574  * xmlTextWriterSetIndent:
4575  * @writer:  the xmlTextWriterPtr
4576  * @indent:  do indentation?
4577  *
4578  * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4579  *
4580  * Returns -1 on error or 0 otherwise.
4581  */
4582 int
xmlTextWriterSetIndent(xmlTextWriterPtr writer,int indent)4583 xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
4584 {
4585     if ((writer == NULL) || (indent < 0))
4586         return -1;
4587 
4588     writer->indent = indent;
4589     writer->doindent = 1;
4590 
4591     return 0;
4592 }
4593 
4594 /**
4595  * xmlTextWriterSetIndentString:
4596  * @writer:  the xmlTextWriterPtr
4597  * @str:  the xmlChar string
4598  *
4599  * Set string indentation.
4600  *
4601  * Returns -1 on error or 0 otherwise.
4602  */
4603 int
xmlTextWriterSetIndentString(xmlTextWriterPtr writer,const xmlChar * str)4604 xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
4605 {
4606     if ((writer == NULL) || (!str))
4607         return -1;
4608 
4609     if (writer->ichar != NULL)
4610         xmlFree(writer->ichar);
4611     writer->ichar = xmlStrdup(str);
4612 
4613     if (!writer->ichar)
4614         return -1;
4615     else
4616         return 0;
4617 }
4618 
4619 /**
4620  * xmlTextWriterSetQuoteChar:
4621  * @writer:  the xmlTextWriterPtr
4622  * @quotechar:  the quote character
4623  *
4624  * Set the character used for quoting attributes.
4625  *
4626  * Returns -1 on error or 0 otherwise.
4627  */
4628 int
xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer,xmlChar quotechar)4629 xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
4630 {
4631     if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
4632         return -1;
4633 
4634     writer->qchar = quotechar;
4635 
4636     return 0;
4637 }
4638 
4639 /**
4640  * xmlTextWriterWriteIndent:
4641  * @writer:  the xmlTextWriterPtr
4642  *
4643  * Write indent string.
4644  *
4645  * Returns -1 on error or the number of strings written.
4646  */
4647 static int
xmlTextWriterWriteIndent(xmlTextWriterPtr writer)4648 xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
4649 {
4650     int lksize;
4651     int i;
4652     int ret;
4653 
4654     lksize = xmlListSize(writer->nodes);
4655     if (lksize < 1)
4656         return (-1);            /* list is empty */
4657     for (i = 0; i < (lksize - 1); i++) {
4658         ret = xmlOutputBufferWriteString(writer->out,
4659                                          (const char *) writer->ichar);
4660         if (ret == -1)
4661             return (-1);
4662     }
4663 
4664     return (lksize - 1);
4665 }
4666 
4667 /**
4668  * xmlTextWriterHandleStateDependencies:
4669  * @writer:  the xmlTextWriterPtr
4670  * @p:  the xmlTextWriterStackEntry
4671  *
4672  * Write state dependent strings.
4673  *
4674  * Returns -1 on error or the number of characters written.
4675  */
4676 static int
xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,xmlTextWriterStackEntry * p)4677 xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4678                                      xmlTextWriterStackEntry * p)
4679 {
4680     int count;
4681     int sum;
4682     char extra[3];
4683 
4684     if (writer == NULL)
4685         return -1;
4686 
4687     if (p == NULL)
4688         return 0;
4689 
4690     sum = 0;
4691     extra[0] = extra[1] = extra[2] = '\0';
4692     if (p != 0) {
4693         sum = 0;
4694         switch (p->state) {
4695             case XML_TEXTWRITER_NAME:
4696                 /* Output namespace declarations */
4697                 count = xmlTextWriterOutputNSDecl(writer);
4698                 if (count < 0)
4699                     return -1;
4700                 sum += count;
4701                 extra[0] = '>';
4702                 p->state = XML_TEXTWRITER_TEXT;
4703                 break;
4704             case XML_TEXTWRITER_PI:
4705                 extra[0] = ' ';
4706                 p->state = XML_TEXTWRITER_PI_TEXT;
4707                 break;
4708             case XML_TEXTWRITER_DTD:
4709                 extra[0] = ' ';
4710                 extra[1] = '[';
4711                 p->state = XML_TEXTWRITER_DTD_TEXT;
4712                 break;
4713             case XML_TEXTWRITER_DTD_ELEM:
4714                 extra[0] = ' ';
4715                 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4716                 break;
4717             case XML_TEXTWRITER_DTD_ATTL:
4718                 extra[0] = ' ';
4719                 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4720                 break;
4721             case XML_TEXTWRITER_DTD_ENTY:
4722             case XML_TEXTWRITER_DTD_PENT:
4723                 extra[0] = ' ';
4724                 extra[1] = writer->qchar;
4725                 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4726                 break;
4727             default:
4728                 break;
4729         }
4730     }
4731 
4732     if (*extra != '\0') {
4733         count = xmlOutputBufferWriteString(writer->out, extra);
4734         if (count < 0)
4735             return -1;
4736         sum += count;
4737     }
4738 
4739     return sum;
4740 }
4741 
4742 #endif
4743