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