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