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