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