Coverage Report

Created: 2026-04-09 11:41

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