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