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